1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef MOZILLA_GFX_TEXTURED3D11_H
8 #define MOZILLA_GFX_TEXTURED3D11_H
15 #include "gfxWindowsPlatform.h"
16 #include "mozilla/DataMutex.h"
17 #include "mozilla/GfxMessageUtils.h"
18 #include "mozilla/Maybe.h"
19 #include "mozilla/gfx/2D.h"
20 #include "mozilla/layers/Compositor.h"
21 #include "mozilla/layers/SyncObject.h"
22 #include "mozilla/layers/TextureClient.h"
23 #include "mozilla/layers/TextureHost.h"
28 class FileHandleWrapper
;
38 gfx::DeviceResetReason
DXGIErrorToDeviceResetReason(HRESULT aError
);
40 already_AddRefed
<TextureHost
> CreateTextureHostD3D11(
41 const SurfaceDescriptor
& aDesc
, ISurfaceAllocator
* aDeallocator
,
42 LayersBackend aBackend
, TextureFlags aFlags
);
44 class MOZ_RAII AutoTextureLock final
{
46 AutoTextureLock(IDXGIKeyedMutex
* aMutex
, HRESULT
& aResult
,
47 uint32_t aTimeout
= 0);
51 RefPtr
<IDXGIKeyedMutex
> mMutex
;
55 class CompositorD3D11
;
56 class IMFSampleUsageInfo
;
57 class VideoProcessorD3D11
;
59 class D3D11TextureData final
: public TextureData
{
61 // If aDevice is null, use one provided by gfxWindowsPlatform.
62 static D3D11TextureData
* Create(gfx::IntSize aSize
,
63 gfx::SurfaceFormat aFormat
,
64 TextureAllocationFlags aAllocFlags
,
65 ID3D11Device
* aDevice
= nullptr);
66 static D3D11TextureData
* Create(gfx::SourceSurface
* aSurface
,
67 TextureAllocationFlags aAllocFlags
,
68 ID3D11Device
* aDevice
= nullptr);
70 static already_AddRefed
<TextureClient
> CreateTextureClient(
71 ID3D11Texture2D
* aTexture
, uint32_t aIndex
, gfx::IntSize aSize
,
72 gfx::SurfaceFormat aFormat
, gfx::ColorSpace2 aColorSpace
,
73 gfx::ColorRange aColorRange
, KnowsCompositor
* aKnowsCompositor
,
74 RefPtr
<IMFSampleUsageInfo
> aUsageInfo
);
76 virtual ~D3D11TextureData();
78 bool UpdateFromSurface(gfx::SourceSurface
* aSurface
) override
;
80 bool Lock(OpenMode aMode
) override
;
82 void Unlock() override
;
84 already_AddRefed
<gfx::DrawTarget
> BorrowDrawTarget() override
;
86 TextureData
* CreateSimilar(LayersIPCChannel
* aAllocator
,
87 LayersBackend aLayersBackend
, TextureFlags aFlags
,
88 TextureAllocationFlags aAllocFlags
) const override
;
90 void SyncWithObject(RefPtr
<SyncObjectClient
> aSyncObject
) override
;
92 ID3D11Texture2D
* GetD3D11Texture() const { return mTexture
; }
94 void Deallocate(LayersIPCChannel
* aAllocator
) override
;
96 D3D11TextureData
* AsD3D11TextureData() override
{ return this; }
98 TextureAllocationFlags
GetTextureAllocationFlags() const {
99 return mAllocationFlags
;
102 TextureType
GetTextureType() const override
{ return TextureType::D3D11
; }
104 void FillInfo(TextureData::Info
& aInfo
) const override
;
106 bool Serialize(SurfaceDescriptor
& aOutDescrptor
) override
;
107 void GetSubDescriptor(RemoteDecoderVideoSubDescriptor
* aOutDesc
) override
;
109 gfx::ColorRange
GetColorRange() const { return mColorRange
; }
110 void SetColorRange(gfx::ColorRange aColorRange
) { mColorRange
= aColorRange
; }
112 gfx::IntSize
GetSize() const { return mSize
; }
113 gfx::SurfaceFormat
GetSurfaceFormat() const { return mFormat
; }
115 TextureFlags
GetTextureFlags() const override
;
117 void SetGpuProcessTextureId(GpuProcessTextureId aTextureId
) {
118 mGpuProcessTextureId
= Some(aTextureId
);
121 Maybe
<GpuProcessTextureId
> GetGpuProcessTextureId() {
122 return mGpuProcessTextureId
;
125 void RegisterQuery(RefPtr
<ID3D11Query
> aQuery
, bool aOnlyForOverlay
= false);
128 D3D11TextureData(ID3D11Texture2D
* aTexture
, uint32_t aArrayIndex
,
129 RefPtr
<gfx::FileHandleWrapper
> aSharedHandle
,
130 gfx::IntSize aSize
, gfx::SurfaceFormat aFormat
,
131 TextureAllocationFlags aFlags
);
133 bool PrepareDrawTargetInLock(OpenMode aMode
);
135 friend class gl::GLBlitHelper
;
136 bool SerializeSpecific(SurfaceDescriptorD3D10
* aOutDesc
);
138 static D3D11TextureData
* Create(gfx::IntSize aSize
,
139 gfx::SurfaceFormat aFormat
,
140 gfx::SourceSurface
* aSurface
,
141 TextureAllocationFlags aAllocFlags
,
142 ID3D11Device
* aDevice
= nullptr);
144 // Hold on to the DrawTarget because it is expensive to create one each
146 RefPtr
<gfx::DrawTarget
> mDrawTarget
;
147 const gfx::IntSize mSize
;
148 const gfx::SurfaceFormat mFormat
;
151 gfx::ColorSpace2 mColorSpace
= gfx::ColorSpace2::SRGB
;
154 gfx::ColorRange mColorRange
= gfx::ColorRange::LIMITED
;
155 bool mNeedsClear
= false;
156 const bool mHasKeyedMutex
;
158 RefPtr
<ID3D11Texture2D
> mTexture
;
159 const RefPtr
<gfx::FileHandleWrapper
> mSharedHandle
;
160 Maybe
<GpuProcessTextureId
> mGpuProcessTextureId
;
161 uint32_t mArrayIndex
= 0;
162 const TextureAllocationFlags mAllocationFlags
;
163 Maybe
<GpuProcessQueryId
> mGpuProcessQueryId
;
166 class DXGIYCbCrTextureData
: public TextureData
{
167 friend class gl::GLBlitHelper
;
170 static DXGIYCbCrTextureData
* Create(
171 ID3D11Texture2D
* aTextureCb
, ID3D11Texture2D
* aTextureY
,
172 ID3D11Texture2D
* aTextureCr
, const gfx::IntSize
& aSize
,
173 const gfx::IntSize
& aSizeY
, const gfx::IntSize
& aSizeCbCr
,
174 gfx::ColorDepth aColorDepth
, gfx::YUVColorSpace aYUVColorSpace
,
175 gfx::ColorRange aColorRange
);
177 bool Lock(OpenMode
) override
{ return true; }
179 void Unlock() override
{}
181 void FillInfo(TextureData::Info
& aInfo
) const override
;
183 void SerializeSpecific(SurfaceDescriptorDXGIYCbCr
* aOutDesc
);
184 bool Serialize(SurfaceDescriptor
& aOutDescriptor
) override
;
185 void GetSubDescriptor(RemoteDecoderVideoSubDescriptor
* aOutDesc
) override
;
187 already_AddRefed
<gfx::DrawTarget
> BorrowDrawTarget() override
{
191 void Deallocate(LayersIPCChannel
* aAllocator
) override
;
193 bool UpdateFromSurface(gfx::SourceSurface
*) override
{ return false; }
195 TextureFlags
GetTextureFlags() const override
;
197 DXGIYCbCrTextureData
* AsDXGIYCbCrTextureData() override
{ return this; }
199 gfx::IntSize
GetYSize() const { return mSizeY
; }
201 gfx::IntSize
GetCbCrSize() const { return mSizeCbCr
; }
203 gfx::ColorDepth
GetColorDepth() const { return mColorDepth
; }
204 gfx::YUVColorSpace
GetYUVColorSpace() const { return mYUVColorSpace
; }
205 gfx::ColorRange
GetColorRange() const { return mColorRange
; }
207 ID3D11Texture2D
* GetD3D11Texture(size_t index
) {
208 return mD3D11Textures
[index
];
212 RefPtr
<ID3D11Texture2D
> mD3D11Textures
[3];
213 RefPtr
<gfx::FileHandleWrapper
> mHandles
[3];
216 gfx::IntSize mSizeCbCr
;
217 gfx::ColorDepth mColorDepth
;
218 gfx::YUVColorSpace mYUVColorSpace
;
219 gfx::ColorRange mColorRange
;
223 * TextureSource that provides with the necessary APIs to be composited by a
226 class TextureSourceD3D11
{
228 TextureSourceD3D11() : mFormatOverride(DXGI_FORMAT_UNKNOWN
) {}
229 virtual ~TextureSourceD3D11() = default;
231 virtual ID3D11Texture2D
* GetD3D11Texture() const { return mTexture
; }
232 virtual ID3D11ShaderResourceView
* GetShaderResourceView();
235 virtual gfx::IntSize
GetSize() const { return mSize
; }
238 RefPtr
<ID3D11Texture2D
> mTexture
;
239 RefPtr
<ID3D11ShaderResourceView
> mSRV
;
240 DXGI_FORMAT mFormatOverride
;
244 * A TextureSource that implements the DataTextureSource interface.
245 * it can be used without a TextureHost and is able to upload texture data
246 * from a gfx::DataSourceSurface.
248 class DataTextureSourceD3D11
: public DataTextureSource
,
249 public TextureSourceD3D11
,
250 public BigImageIterator
{
252 /// Constructor allowing the texture to perform texture uploads.
254 /// The texture can be used as an actual DataTextureSource.
255 DataTextureSourceD3D11(ID3D11Device
* aDevice
, gfx::SurfaceFormat aFormat
,
256 TextureFlags aFlags
);
258 /// Constructor for textures created around DXGI shared handles, disallowing
261 /// The texture CANNOT be used as a DataTextureSource.
262 DataTextureSourceD3D11(ID3D11Device
* aDevice
, gfx::SurfaceFormat aFormat
,
263 ID3D11Texture2D
* aTexture
);
265 DataTextureSourceD3D11(gfx::SurfaceFormat aFormat
,
266 TextureSourceProvider
* aProvider
,
267 ID3D11Texture2D
* aTexture
);
268 DataTextureSourceD3D11(gfx::SurfaceFormat aFormat
,
269 TextureSourceProvider
* aProvider
, TextureFlags aFlags
);
271 virtual ~DataTextureSourceD3D11();
273 const char* Name() const override
{ return "DataTextureSourceD3D11"; }
277 bool Update(gfx::DataSourceSurface
* aSurface
,
278 nsIntRegion
* aDestRegion
= nullptr,
279 gfx::IntPoint
* aSrcOffset
= nullptr,
280 gfx::IntPoint
* aDstOffset
= nullptr) override
;
284 TextureSourceD3D11
* AsSourceD3D11() override
{ return this; }
286 ID3D11Texture2D
* GetD3D11Texture() const override
;
288 ID3D11ShaderResourceView
* GetShaderResourceView() override
;
290 // Returns nullptr if this texture was created by a DXGI TextureHost.
291 DataTextureSource
* AsDataTextureSource() override
{
292 return mAllowTextureUploads
? this : nullptr;
295 void DeallocateDeviceData() override
{ mTexture
= nullptr; }
297 gfx::IntSize
GetSize() const override
{ return mSize
; }
299 gfx::SurfaceFormat
GetFormat() const override
{ return mFormat
; }
303 BigImageIterator
* AsBigImageIterator() override
{
304 return mIsTiled
? this : nullptr;
307 size_t GetTileCount() override
{ return mTileTextures
.size(); }
309 bool NextTile() override
{ return (++mCurrentTile
< mTileTextures
.size()); }
311 gfx::IntRect
GetTileRect() override
;
313 void EndBigImageIteration() override
{ mIterating
= false; }
315 void BeginBigImageIteration() override
{
320 RefPtr
<TextureSource
> ExtractCurrentTile() override
;
325 gfx::IntRect
GetTileRect(uint32_t aIndex
) const;
327 std::vector
<RefPtr
<ID3D11Texture2D
>> mTileTextures
;
328 std::vector
<RefPtr
<ID3D11ShaderResourceView
>> mTileSRVs
;
329 RefPtr
<ID3D11Device
> mDevice
;
330 gfx::SurfaceFormat mFormat
;
332 uint32_t mCurrentTile
;
335 // Sadly, the code was originally organized so that this class is used both in
336 // the cases where we want to perform texture uploads through the
337 // DataTextureSource interface, and the cases where we wrap the texture around
338 // an existing DXGI handle in which case we should not use it as a
339 // DataTextureSource. This member differentiates the two scenarios. When it is
340 // false the texture "pretends" to not be a DataTextureSource.
341 bool mAllowTextureUploads
;
345 * A TextureHost for shared D3D11 textures.
347 class DXGITextureHostD3D11
: public TextureHost
{
349 DXGITextureHostD3D11(TextureFlags aFlags
,
350 const SurfaceDescriptorD3D10
& aDescriptor
);
352 void DeallocateDeviceData() override
{}
354 gfx::SurfaceFormat
GetFormat() const override
{ return mFormat
; }
356 gfx::IntSize
GetSize() const override
{ return mSize
; }
357 gfx::ColorRange
GetColorRange() const override
{ return mColorRange
; }
359 already_AddRefed
<gfx::DataSourceSurface
> GetAsSurface(
360 gfx::DataSourceSurface
* aSurface
) override
;
362 // Return DataSourceSurface using aDevice withou readback to CPU.
363 already_AddRefed
<gfx::DataSourceSurface
> GetAsSurfaceWithDevice(
364 ID3D11Device
* const aDevice
,
365 DataMutex
<RefPtr
<VideoProcessorD3D11
>>& aVideoProcessorD3D11
);
367 void CreateRenderTexture(
368 const wr::ExternalImageId
& aExternalImageId
) override
;
370 uint32_t NumSubTextures() override
;
372 void PushResourceUpdates(wr::TransactionBuilder
& aResources
,
373 ResourceUpdateOp aOp
,
374 const Range
<wr::ImageKey
>& aImageKeys
,
375 const wr::ExternalImageId
& aExtID
) override
;
377 void PushDisplayItems(wr::DisplayListBuilder
& aBuilder
,
378 const wr::LayoutRect
& aBounds
,
379 const wr::LayoutRect
& aClip
, wr::ImageRendering aFilter
,
380 const Range
<wr::ImageKey
>& aImageKeys
,
381 PushDisplayItemFlagSet aFlags
) override
;
383 bool SupportsExternalCompositing(WebRenderBackend aBackend
) override
;
385 DXGITextureHostD3D11
* AsDXGITextureHostD3D11() override
{ return this; }
387 const RefPtr
<gfx::FileHandleWrapper
> mHandle
;
388 const Maybe
<GpuProcessTextureId
> mGpuProcessTextureId
;
389 const uint32_t mArrayIndex
;
390 const Maybe
<GpuProcessQueryId
> mGpuProcessQueryId
;
391 const gfx::IntSize mSize
;
392 const gfx::SurfaceFormat mFormat
;
393 const bool mHasKeyedMutex
;
394 const gfx::FenceInfo mAcquireFenceInfo
;
395 const gfx::ColorSpace2 mColorSpace
;
396 const gfx::ColorRange mColorRange
;
399 class DXGIYCbCrTextureHostD3D11
: public TextureHost
{
401 DXGIYCbCrTextureHostD3D11(TextureFlags aFlags
,
402 const SurfaceDescriptorDXGIYCbCr
& aDescriptor
);
404 void DeallocateDeviceData() override
{}
406 gfx::SurfaceFormat
GetFormat() const override
{
407 return gfx::SurfaceFormat::YUV420
;
410 gfx::ColorDepth
GetColorDepth() const override
{ return mColorDepth
; }
411 gfx::YUVColorSpace
GetYUVColorSpace() const override
{
412 return mYUVColorSpace
;
414 gfx::ColorRange
GetColorRange() const override
{ return mColorRange
; }
416 gfx::IntSize
GetSize() const override
{ return mSize
; }
418 already_AddRefed
<gfx::DataSourceSurface
> GetAsSurface(
419 gfx::DataSourceSurface
* aSurface
) override
{
423 void CreateRenderTexture(
424 const wr::ExternalImageId
& aExternalImageId
) override
;
426 uint32_t NumSubTextures() override
;
428 void PushResourceUpdates(wr::TransactionBuilder
& aResources
,
429 ResourceUpdateOp aOp
,
430 const Range
<wr::ImageKey
>& aImageKeys
,
431 const wr::ExternalImageId
& aExtID
) override
;
433 void PushDisplayItems(wr::DisplayListBuilder
& aBuilder
,
434 const wr::LayoutRect
& aBounds
,
435 const wr::LayoutRect
& aClip
, wr::ImageRendering aFilter
,
436 const Range
<wr::ImageKey
>& aImageKeys
,
437 PushDisplayItemFlagSet aFlags
) override
;
439 bool SupportsExternalCompositing(WebRenderBackend aBackend
) override
;
442 RefPtr
<ID3D11Texture2D
> mTextures
[3];
446 gfx::IntSize mSizeCbCr
;
447 // Handles will be closed automatically when `UniqueFileHandle` gets
449 RefPtr
<gfx::FileHandleWrapper
> mHandles
[3];
451 gfx::ColorDepth mColorDepth
;
452 gfx::YUVColorSpace mYUVColorSpace
;
453 gfx::ColorRange mColorRange
;
456 class CompositingRenderTargetD3D11
: public CompositingRenderTarget
,
457 public TextureSourceD3D11
{
459 CompositingRenderTargetD3D11(
460 ID3D11Texture2D
* aTexture
, const gfx::IntPoint
& aOrigin
,
461 DXGI_FORMAT aFormatOverride
= DXGI_FORMAT_UNKNOWN
);
463 const char* Name() const override
{ return "CompositingRenderTargetD3D11"; }
465 TextureSourceD3D11
* AsSourceD3D11() override
{ return this; }
467 void BindRenderTarget(ID3D11DeviceContext
* aContext
);
469 gfx::IntSize
GetSize() const override
;
471 void SetSize(const gfx::IntSize
& aSize
) { mSize
= aSize
; }
474 friend class CompositorD3D11
;
475 RefPtr
<ID3D11RenderTargetView
> mRTView
;
478 class SyncObjectD3D11Host
: public SyncObjectHost
{
480 explicit SyncObjectD3D11Host(ID3D11Device
* aDevice
);
482 bool Init() override
;
484 SyncHandle
GetSyncHandle() override
;
486 bool Synchronize(bool aFallible
) override
;
488 IDXGIKeyedMutex
* GetKeyedMutex() { return mKeyedMutex
.get(); };
491 virtual ~SyncObjectD3D11Host() = default;
493 SyncHandle mSyncHandle
;
494 RefPtr
<ID3D11Device
> mDevice
;
495 RefPtr
<IDXGIResource1
> mSyncTexture
;
496 RefPtr
<IDXGIKeyedMutex
> mKeyedMutex
;
499 class SyncObjectD3D11Client
: public SyncObjectClient
{
501 SyncObjectD3D11Client(SyncHandle aSyncHandle
, ID3D11Device
* aDevice
);
503 bool Synchronize(bool aFallible
) override
;
505 bool IsSyncObjectValid() override
;
507 void EnsureInitialized() override
{}
509 SyncType
GetSyncType() override
{ return SyncType::D3D11
; }
511 void RegisterTexture(ID3D11Texture2D
* aTexture
);
514 explicit SyncObjectD3D11Client(SyncHandle aSyncHandle
);
515 bool Init(ID3D11Device
* aDevice
, bool aFallible
);
516 bool SynchronizeInternal(ID3D11Device
* aDevice
, bool aFallible
);
517 Mutex mSyncLock MOZ_UNANNOTATED
;
518 RefPtr
<ID3D11Texture2D
> mSyncTexture
;
519 std::vector
<ID3D11Texture2D
*> mSyncedTextures
;
522 SyncHandle mSyncHandle
;
523 RefPtr
<IDXGIKeyedMutex
> mKeyedMutex
;
524 const RefPtr
<ID3D11Device
> mDevice
;
527 class SyncObjectD3D11ClientContentDevice
: public SyncObjectD3D11Client
{
529 explicit SyncObjectD3D11ClientContentDevice(SyncHandle aSyncHandle
);
531 bool Synchronize(bool aFallible
) override
;
533 bool IsSyncObjectValid() override
;
535 void EnsureInitialized() override
;
538 RefPtr
<ID3D11Device
> mContentDevice
;
541 inline uint32_t GetMaxTextureSizeForFeatureLevel(
542 D3D_FEATURE_LEVEL aFeatureLevel
) {
543 int32_t maxTextureSize
;
544 switch (aFeatureLevel
) {
545 case D3D_FEATURE_LEVEL_11_1
:
546 case D3D_FEATURE_LEVEL_11_0
:
547 maxTextureSize
= D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION
;
549 case D3D_FEATURE_LEVEL_10_1
:
550 case D3D_FEATURE_LEVEL_10_0
:
551 maxTextureSize
= D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION
;
553 case D3D_FEATURE_LEVEL_9_3
:
554 maxTextureSize
= D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION
;
557 maxTextureSize
= D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION
;
559 return maxTextureSize
;
562 uint32_t GetMaxTextureSizeFromDevice(ID3D11Device
* aDevice
);
563 void ReportTextureMemoryUsage(ID3D11Texture2D
* aTexture
, size_t aBytes
);
565 class AutoLockD3D11Texture
{
567 explicit AutoLockD3D11Texture(ID3D11Texture2D
* aTexture
);
568 ~AutoLockD3D11Texture();
571 RefPtr
<IDXGIKeyedMutex
> mMutex
;
574 class D3D11MTAutoEnter
{
576 explicit D3D11MTAutoEnter(already_AddRefed
<ID3D10Multithread
> aMT
)
582 ~D3D11MTAutoEnter() {
589 RefPtr
<ID3D10Multithread
> mMT
;
592 } // namespace layers
593 } // namespace mozilla
595 #endif /* MOZILLA_GFX_TEXTURED3D11_H */