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 #include "TextureD3D11.h"
9 #include "CompositorD3D11.h"
10 #include "DXVA2Manager.h"
12 #include "MainThreadUtils.h"
13 #include "gfx2DGlue.h"
14 #include "gfxContext.h"
15 #include "gfxWindowsPlatform.h"
16 #include "mozilla/DataMutex.h"
17 #include "mozilla/StaticPrefs_gfx.h"
18 #include "mozilla/gfx/DataSurfaceHelpers.h"
19 #include "mozilla/gfx/DeviceManagerDx.h"
20 #include "mozilla/gfx/FileHandleWrapper.h"
21 #include "mozilla/gfx/Logging.h"
22 #include "mozilla/gfx/gfxVars.h"
23 #include "mozilla/ipc/FileDescriptor.h"
24 #include "mozilla/layers/CompositorBridgeChild.h"
25 #include "mozilla/layers/D3D11TextureIMFSampleImage.h"
26 #include "mozilla/layers/GpuProcessD3D11QueryMap.h"
27 #include "mozilla/layers/GpuProcessD3D11TextureMap.h"
28 #include "mozilla/layers/HelpersD3D11.h"
29 #include "mozilla/layers/VideoProcessorD3D11.h"
30 #include "mozilla/webrender/RenderD3D11TextureHost.h"
31 #include "mozilla/webrender/RenderThread.h"
32 #include "mozilla/webrender/WebRenderAPI.h"
40 gfx::DeviceResetReason
DXGIErrorToDeviceResetReason(HRESULT aError
) {
43 return gfx::DeviceResetReason::OK
;
44 case DXGI_ERROR_DEVICE_REMOVED
:
45 return gfx::DeviceResetReason::REMOVED
;
46 case DXGI_ERROR_DRIVER_INTERNAL_ERROR
:
47 return gfx::DeviceResetReason::DRIVER_ERROR
;
48 case DXGI_ERROR_DEVICE_HUNG
:
49 return gfx::DeviceResetReason::HUNG
;
50 case DXGI_ERROR_DEVICE_RESET
:
51 return gfx::DeviceResetReason::RESET
;
52 case DXGI_ERROR_INVALID_CALL
:
53 return gfx::DeviceResetReason::INVALID_CALL
;
55 gfxCriticalNote
<< "Device reset with D3D11Device unexpected reason: "
59 return gfx::DeviceResetReason::UNKNOWN
;
62 static const GUID sD3D11TextureUsage
= {
66 {0xb5, 0xfa, 0x4d, 0x87, 0x16, 0xd5, 0xcc, 0x4e}};
68 /* This class gets its lifetime tied to a D3D texture
69 * and increments memory usage on construction and decrements
71 class TextureMemoryMeasurer final
: public IUnknown
{
73 explicit TextureMemoryMeasurer(size_t aMemoryUsed
) {
74 mMemoryUsed
= aMemoryUsed
;
75 gfxWindowsPlatform::sD3D11SharedTextures
+= mMemoryUsed
;
78 STDMETHODIMP_(ULONG
) AddRef() {
82 STDMETHODIMP
QueryInterface(REFIID riid
, void** ppvObject
) {
83 IUnknown
* punk
= nullptr;
84 if (riid
== IID_IUnknown
) {
96 STDMETHODIMP_(ULONG
) Release() {
97 int refCnt
= --mRefCnt
;
99 gfxWindowsPlatform::sD3D11SharedTextures
-= mMemoryUsed
;
109 ~TextureMemoryMeasurer() = default;
112 static DXGI_FORMAT
SurfaceFormatToDXGIFormat(gfx::SurfaceFormat aFormat
) {
114 case SurfaceFormat::B8G8R8A8
:
115 return DXGI_FORMAT_B8G8R8A8_UNORM
;
116 case SurfaceFormat::B8G8R8X8
:
117 return DXGI_FORMAT_B8G8R8A8_UNORM
;
118 case SurfaceFormat::R8G8B8A8
:
119 return DXGI_FORMAT_R8G8B8A8_UNORM
;
120 case SurfaceFormat::R8G8B8X8
:
121 return DXGI_FORMAT_R8G8B8A8_UNORM
;
122 case SurfaceFormat::A8
:
123 return DXGI_FORMAT_R8_UNORM
;
124 case SurfaceFormat::A16
:
125 return DXGI_FORMAT_R16_UNORM
;
127 MOZ_ASSERT(false, "unsupported format");
128 return DXGI_FORMAT_UNKNOWN
;
132 void ReportTextureMemoryUsage(ID3D11Texture2D
* aTexture
, size_t aBytes
) {
133 aTexture
->SetPrivateDataInterface(sD3D11TextureUsage
,
134 new TextureMemoryMeasurer(aBytes
));
137 static uint32_t GetRequiredTilesD3D11(uint32_t aSize
, uint32_t aMaxSize
) {
138 uint32_t requiredTiles
= aSize
/ aMaxSize
;
139 if (aSize
% aMaxSize
) {
142 return requiredTiles
;
145 static IntRect
GetTileRectD3D11(uint32_t aID
, IntSize aSize
,
147 uint32_t horizontalTiles
= GetRequiredTilesD3D11(aSize
.width
, aMaxSize
);
148 uint32_t verticalTiles
= GetRequiredTilesD3D11(aSize
.height
, aMaxSize
);
150 uint32_t verticalTile
= aID
/ horizontalTiles
;
151 uint32_t horizontalTile
= aID
% horizontalTiles
;
154 horizontalTile
* aMaxSize
, verticalTile
* aMaxSize
,
155 horizontalTile
< (horizontalTiles
- 1) ? aMaxSize
156 : aSize
.width
% aMaxSize
,
157 verticalTile
< (verticalTiles
- 1) ? aMaxSize
: aSize
.height
% aMaxSize
);
160 AutoTextureLock::AutoTextureLock(IDXGIKeyedMutex
* aMutex
, HRESULT
& aResult
,
164 mResult
= mMutex
->AcquireSync(0, aTimeout
);
167 aResult
= E_INVALIDARG
;
171 AutoTextureLock::~AutoTextureLock() {
172 if (mMutex
&& !FAILED(mResult
) && mResult
!= WAIT_TIMEOUT
&&
173 mResult
!= WAIT_ABANDONED
) {
174 mMutex
->ReleaseSync(0);
178 ID3D11ShaderResourceView
* TextureSourceD3D11::GetShaderResourceView() {
179 MOZ_ASSERT(mTexture
== GetD3D11Texture(),
180 "You need to override GetShaderResourceView if you're overriding "
183 if (!mSRV
&& mTexture
) {
184 RefPtr
<ID3D11Device
> device
;
185 mTexture
->GetDevice(getter_AddRefs(device
));
187 // see comment in CompositingRenderTargetD3D11 constructor
188 CD3D11_SHADER_RESOURCE_VIEW_DESC
srvDesc(D3D11_SRV_DIMENSION_TEXTURE2D
,
190 D3D11_SHADER_RESOURCE_VIEW_DESC
* desc
=
191 mFormatOverride
== DXGI_FORMAT_UNKNOWN
? nullptr : &srvDesc
;
194 device
->CreateShaderResourceView(mTexture
, desc
, getter_AddRefs(mSRV
));
196 gfxCriticalNote
<< "[D3D11] TextureSourceD3D11:GetShaderResourceView "
205 DataTextureSourceD3D11::DataTextureSourceD3D11(ID3D11Device
* aDevice
,
206 SurfaceFormat aFormat
,
214 mAllowTextureUploads(true) {}
216 DataTextureSourceD3D11::DataTextureSourceD3D11(ID3D11Device
* aDevice
,
217 SurfaceFormat aFormat
,
218 ID3D11Texture2D
* aTexture
)
221 mFlags(TextureFlags::NO_FLAGS
),
225 mAllowTextureUploads(false) {
227 D3D11_TEXTURE2D_DESC desc
;
228 aTexture
->GetDesc(&desc
);
230 mSize
= IntSize(desc
.Width
, desc
.Height
);
233 DataTextureSourceD3D11::DataTextureSourceD3D11(gfx::SurfaceFormat aFormat
,
234 TextureSourceProvider
* aProvider
,
235 ID3D11Texture2D
* aTexture
)
236 : DataTextureSourceD3D11(aProvider
->GetD3D11Device(), aFormat
, aTexture
) {}
238 DataTextureSourceD3D11::DataTextureSourceD3D11(gfx::SurfaceFormat aFormat
,
239 TextureSourceProvider
* aProvider
,
241 : DataTextureSourceD3D11(aProvider
->GetD3D11Device(), aFormat
, aFlags
) {}
243 DataTextureSourceD3D11::~DataTextureSourceD3D11() {}
245 enum class SerializeWithMoz2D
: bool { No
, Yes
};
247 template <typename T
> // ID3D10Texture2D or ID3D11Texture2D
248 static bool LockD3DTexture(
249 T
* aTexture
, SerializeWithMoz2D aSerialize
= SerializeWithMoz2D::No
) {
250 MOZ_ASSERT(aTexture
);
251 RefPtr
<IDXGIKeyedMutex
> mutex
;
252 aTexture
->QueryInterface((IDXGIKeyedMutex
**)getter_AddRefs(mutex
));
253 // Textures created by the DXVA decoders don't have a mutex for
257 if (aSerialize
== SerializeWithMoz2D::Yes
) {
258 AutoSerializeWithMoz2D
serializeWithMoz2D(BackendType::DIRECT2D1_1
);
259 hr
= mutex
->AcquireSync(0, 10000);
261 hr
= mutex
->AcquireSync(0, 10000);
263 if (hr
== WAIT_TIMEOUT
) {
264 RefPtr
<ID3D11Device
> device
;
265 aTexture
->GetDevice(getter_AddRefs(device
));
267 gfxCriticalNote
<< "GFX: D3D11 lock mutex timeout - no device returned";
268 } else if (device
->GetDeviceRemovedReason() != S_OK
) {
269 gfxCriticalNote
<< "GFX: D3D11 lock mutex timeout - device removed";
271 gfxDevCrash(LogReason::D3DLockTimeout
)
272 << "D3D lock mutex timeout - device not removed";
274 } else if (hr
== WAIT_ABANDONED
) {
275 gfxCriticalNote
<< "GFX: D3D11 lock mutex abandoned";
279 NS_WARNING("Failed to lock the texture");
286 template <typename T
>
287 static bool HasKeyedMutex(T
* aTexture
) {
288 MOZ_ASSERT(aTexture
);
289 RefPtr
<IDXGIKeyedMutex
> mutex
;
290 aTexture
->QueryInterface((IDXGIKeyedMutex
**)getter_AddRefs(mutex
));
294 template <typename T
> // ID3D10Texture2D or ID3D11Texture2D
295 static void UnlockD3DTexture(
296 T
* aTexture
, SerializeWithMoz2D aSerialize
= SerializeWithMoz2D::No
) {
297 MOZ_ASSERT(aTexture
);
298 RefPtr
<IDXGIKeyedMutex
> mutex
;
299 aTexture
->QueryInterface((IDXGIKeyedMutex
**)getter_AddRefs(mutex
));
302 if (aSerialize
== SerializeWithMoz2D::Yes
) {
303 AutoSerializeWithMoz2D
serializeWithMoz2D(BackendType::DIRECT2D1_1
);
304 hr
= mutex
->ReleaseSync(0);
306 hr
= mutex
->ReleaseSync(0);
309 NS_WARNING("Failed to unlock the texture");
314 D3D11TextureData::D3D11TextureData(ID3D11Texture2D
* aTexture
,
315 uint32_t aArrayIndex
,
316 RefPtr
<gfx::FileHandleWrapper
> aSharedHandle
,
318 gfx::SurfaceFormat aFormat
,
319 TextureAllocationFlags aFlags
)
322 mNeedsClear(aFlags
& ALLOC_CLEAR_BUFFER
),
323 mHasKeyedMutex(HasKeyedMutex(aTexture
)),
325 mSharedHandle(std::move(aSharedHandle
)),
326 mArrayIndex(aArrayIndex
),
327 mAllocationFlags(aFlags
) {
328 MOZ_ASSERT(aTexture
);
331 static void DestroyDrawTarget(RefPtr
<DrawTarget
>& aDT
,
332 RefPtr
<ID3D11Texture2D
>& aTexture
) {
333 // An Azure DrawTarget needs to be locked when it gets nullptr'ed as this is
334 // when it calls EndDraw. This EndDraw should not execute anything so it
335 // shouldn't -really- need the lock but the debug layer chokes on this.
336 LockD3DTexture(aTexture
.get(), SerializeWithMoz2D::Yes
);
339 // Do the serialization here, so we can hold it while destroying the texture.
340 AutoSerializeWithMoz2D
serializeWithMoz2D(BackendType::DIRECT2D1_1
);
341 UnlockD3DTexture(aTexture
.get(), SerializeWithMoz2D::No
);
345 D3D11TextureData::~D3D11TextureData() {
347 DestroyDrawTarget(mDrawTarget
, mTexture
);
350 if (mGpuProcessTextureId
.isSome()) {
351 auto* textureMap
= GpuProcessD3D11TextureMap::Get();
353 textureMap
->Unregister(mGpuProcessTextureId
.ref());
355 gfxCriticalNoteOnce
<< "GpuProcessD3D11TextureMap does not exist";
359 if (mGpuProcessQueryId
.isSome()) {
360 auto* queryMap
= GpuProcessD3D11QueryMap::Get();
362 queryMap
->Unregister(mGpuProcessQueryId
.ref());
364 gfxCriticalNoteOnce
<< "GpuProcessD3D11QueryMap does not exist";
369 bool D3D11TextureData::Lock(OpenMode aMode
) {
370 if (mHasKeyedMutex
&&
371 !LockD3DTexture(mTexture
.get(), SerializeWithMoz2D::Yes
)) {
375 if (NS_IsMainThread()) {
376 if (!PrepareDrawTargetInLock(aMode
)) {
385 bool D3D11TextureData::PrepareDrawTargetInLock(OpenMode aMode
) {
386 // Make sure that successful write-lock means we will have a DrawTarget to
388 if (!mDrawTarget
&& (aMode
& OpenMode::OPEN_WRITE
|| mNeedsClear
)) {
389 mDrawTarget
= BorrowDrawTarget();
396 mDrawTarget
->SetTransform(Matrix());
399 mDrawTarget
->ClearRect(Rect(0, 0, mSize
.width
, mSize
.height
));
406 void D3D11TextureData::Unlock() {
407 if (mHasKeyedMutex
) {
408 UnlockD3DTexture(mTexture
.get(), SerializeWithMoz2D::Yes
);
412 void D3D11TextureData::FillInfo(TextureData::Info
& aInfo
) const {
414 aInfo
.format
= mFormat
;
415 aInfo
.supportsMoz2D
= true;
416 aInfo
.hasSynchronization
= mHasKeyedMutex
;
419 void D3D11TextureData::SyncWithObject(RefPtr
<SyncObjectClient
> aSyncObject
) {
420 if (!aSyncObject
|| mHasKeyedMutex
) {
421 // When we have per texture synchronization we sync using the keyed mutex.
425 MOZ_ASSERT(aSyncObject
->GetSyncType() == SyncObjectClient::SyncType::D3D11
);
426 SyncObjectD3D11Client
* sync
=
427 static_cast<SyncObjectD3D11Client
*>(aSyncObject
.get());
428 sync
->RegisterTexture(mTexture
);
431 bool D3D11TextureData::SerializeSpecific(
432 SurfaceDescriptorD3D10
* const aOutDesc
) {
433 if (mGpuProcessTextureId
.isNothing()) {
435 *aOutDesc
= SurfaceDescriptorD3D10(
436 mSharedHandle
, mGpuProcessTextureId
, mArrayIndex
, mFormat
, mSize
,
437 mColorSpace
, mColorRange
, /* hasKeyedMutex */ mHasKeyedMutex
,
438 /* fenceInfo */ Nothing(), mGpuProcessQueryId
);
442 bool D3D11TextureData::Serialize(SurfaceDescriptor
& aOutDescriptor
) {
443 SurfaceDescriptorD3D10 desc
;
444 if (!SerializeSpecific(&desc
)) return false;
446 aOutDescriptor
= std::move(desc
);
450 void D3D11TextureData::GetSubDescriptor(
451 RemoteDecoderVideoSubDescriptor
* const aOutDesc
) {
452 SurfaceDescriptorD3D10 ret
;
453 if (!SerializeSpecific(&ret
)) return;
455 *aOutDesc
= std::move(ret
);
459 already_AddRefed
<TextureClient
> D3D11TextureData::CreateTextureClient(
460 ID3D11Texture2D
* aTexture
, uint32_t aIndex
, gfx::IntSize aSize
,
461 gfx::SurfaceFormat aFormat
, gfx::ColorSpace2 aColorSpace
,
462 gfx::ColorRange aColorRange
, KnowsCompositor
* aKnowsCompositor
,
463 RefPtr
<IMFSampleUsageInfo
> aUsageInfo
) {
464 D3D11TextureData
* data
= new D3D11TextureData(
465 aTexture
, aIndex
, nullptr, aSize
, aFormat
,
466 TextureAllocationFlags::ALLOC_MANUAL_SYNCHRONIZATION
);
467 data
->mColorSpace
= aColorSpace
;
468 data
->SetColorRange(aColorRange
);
470 RefPtr
<TextureClient
> textureClient
= MakeAndAddRef
<TextureClient
>(
471 data
, TextureFlags::NO_FLAGS
, aKnowsCompositor
->GetTextureForwarder());
472 const auto textureId
= GpuProcessD3D11TextureMap::GetNextTextureId();
473 data
->SetGpuProcessTextureId(textureId
);
475 // Register ID3D11Texture2D to GpuProcessD3D11TextureMap
476 auto* textureMap
= GpuProcessD3D11TextureMap::Get();
478 textureMap
->Register(textureId
, aTexture
, aIndex
, aSize
, aUsageInfo
);
480 gfxCriticalNoteOnce
<< "GpuProcessD3D11TextureMap does not exist";
483 return textureClient
.forget();
486 D3D11TextureData
* D3D11TextureData::Create(IntSize aSize
, SurfaceFormat aFormat
,
487 TextureAllocationFlags aFlags
,
488 ID3D11Device
* aDevice
) {
489 return Create(aSize
, aFormat
, nullptr, aFlags
, aDevice
);
492 D3D11TextureData
* D3D11TextureData::Create(SourceSurface
* aSurface
,
493 TextureAllocationFlags aFlags
,
494 ID3D11Device
* aDevice
) {
495 return Create(aSurface
->GetSize(), aSurface
->GetFormat(), aSurface
, aFlags
,
499 D3D11TextureData
* D3D11TextureData::Create(IntSize aSize
, SurfaceFormat aFormat
,
500 SourceSurface
* aSurface
,
501 TextureAllocationFlags aFlags
,
502 ID3D11Device
* aDevice
) {
503 if (aFormat
== SurfaceFormat::A8
) {
504 // Currently we don't support A8 surfaces. Fallback.
508 // Just grab any device. We never use the immediate context, so the devices
509 // are fine to use from any thread.
510 RefPtr
<ID3D11Device
> device
= aDevice
;
512 device
= DeviceManagerDx::Get()->GetContentDevice();
518 CD3D11_TEXTURE2D_DESC
newDesc(
519 DXGI_FORMAT_B8G8R8A8_UNORM
, aSize
.width
, aSize
.height
, 1, 1,
520 D3D11_BIND_RENDER_TARGET
| D3D11_BIND_SHADER_RESOURCE
);
522 if (aFormat
== SurfaceFormat::NV12
) {
523 newDesc
.Format
= DXGI_FORMAT_NV12
;
524 } else if (aFormat
== SurfaceFormat::P010
) {
525 newDesc
.Format
= DXGI_FORMAT_P010
;
526 } else if (aFormat
== SurfaceFormat::P016
) {
527 newDesc
.Format
= DXGI_FORMAT_P016
;
531 D3D11_RESOURCE_MISC_SHARED_NTHANDLE
| D3D11_RESOURCE_MISC_SHARED
;
532 bool useKeyedMutex
= false;
533 if (!NS_IsMainThread()) {
534 // On the main thread we use the syncobject to handle synchronization.
535 if (!(aFlags
& ALLOC_MANUAL_SYNCHRONIZATION
)) {
536 newDesc
.MiscFlags
= D3D11_RESOURCE_MISC_SHARED_NTHANDLE
|
537 D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX
;
538 useKeyedMutex
= true;
542 if (aSurface
&& useKeyedMutex
&&
543 !DeviceManagerDx::Get()->CanInitializeKeyedMutexTextures()) {
547 D3D11_SUBRESOURCE_DATA uploadData
;
548 D3D11_SUBRESOURCE_DATA
* uploadDataPtr
= nullptr;
549 RefPtr
<DataSourceSurface
> srcSurf
;
552 srcSurf
= aSurface
->GetDataSurface();
556 << "Failed to GetDataSurface in D3D11TextureData::Create";
560 DataSourceSurface::MappedSurface sourceMap
;
561 if (!srcSurf
->Map(DataSourceSurface::READ
, &sourceMap
)) {
563 << "Failed to map source surface for D3D11TextureData::Create";
567 uploadData
.pSysMem
= sourceMap
.mData
;
568 uploadData
.SysMemPitch
= sourceMap
.mStride
;
569 uploadData
.SysMemSlicePitch
= 0; // unused
571 uploadDataPtr
= &uploadData
;
575 RefPtr
<ID3D10Multithread
> mt
;
576 device
->QueryInterface((ID3D10Multithread
**)getter_AddRefs(mt
));
578 RefPtr
<ID3D11Texture2D
> texture11
;
581 AutoSerializeWithMoz2D
serializeWithMoz2D(BackendType::DIRECT2D1_1
);
582 D3D11MTAutoEnter
lock(mt
.forget());
584 HRESULT hr
= device
->CreateTexture2D(&newDesc
, uploadDataPtr
,
585 getter_AddRefs(texture11
));
587 if (FAILED(hr
) || !texture11
) {
588 gfxCriticalNote
<< "[D3D11] 2 CreateTexture2D failure Size: " << aSize
589 << "texture11: " << texture11
590 << " Code: " << gfx::hexa(hr
);
599 // If we created the texture with a keyed mutex, then we expect all operations
600 // on it to be synchronized using it. If we did an initial upload using
601 // aSurface then bizarely this isn't covered, so we insert a manual
602 // lock/unlock pair to force this.
603 if (aSurface
&& useKeyedMutex
) {
604 if (!LockD3DTexture(texture11
.get(), SerializeWithMoz2D::Yes
)) {
607 UnlockD3DTexture(texture11
.get(), SerializeWithMoz2D::Yes
);
610 RefPtr
<IDXGIResource1
> resource
;
611 texture11
->QueryInterface((IDXGIResource1
**)getter_AddRefs(resource
));
613 gfxCriticalNoteOnce
<< "Failed to get IDXGIResource";
618 HRESULT hr
= resource
->GetSharedHandle(&sharedHandle
);
619 hr
= resource
->CreateSharedHandle(
620 nullptr, DXGI_SHARED_RESOURCE_READ
| DXGI_SHARED_RESOURCE_WRITE
, nullptr,
623 gfxCriticalNoteOnce
<< "GetSharedHandle failed: " << gfx::hexa(hr
);
627 texture11
->SetPrivateDataInterface(
629 new TextureMemoryMeasurer(newDesc
.Width
* newDesc
.Height
* 4));
631 RefPtr
<gfx::FileHandleWrapper
> handle
=
632 new gfx::FileHandleWrapper(UniqueFileHandle(sharedHandle
));
634 D3D11TextureData
* data
=
635 new D3D11TextureData(texture11
, 0, handle
, aSize
, aFormat
, aFlags
);
637 texture11
->GetDevice(getter_AddRefs(device
));
638 if (XRE_IsGPUProcess() &&
639 device
== gfx::DeviceManagerDx::Get()->GetCompositorDevice()) {
640 const auto textureId
= GpuProcessD3D11TextureMap::GetNextTextureId();
641 data
->SetGpuProcessTextureId(textureId
);
642 // Register ID3D11Texture2D to GpuProcessD3D11TextureMap
643 auto* textureMap
= GpuProcessD3D11TextureMap::Get();
645 textureMap
->Register(textureId
, texture11
, 0, aSize
, nullptr, handle
);
647 gfxCriticalNoteOnce
<< "GpuProcessD3D11TextureMap does not exist";
654 void D3D11TextureData::Deallocate(LayersIPCChannel
* aAllocator
) {
655 mDrawTarget
= nullptr;
659 TextureData
* D3D11TextureData::CreateSimilar(
660 LayersIPCChannel
* aAllocator
, LayersBackend aLayersBackend
,
661 TextureFlags aFlags
, TextureAllocationFlags aAllocFlags
) const {
662 return D3D11TextureData::Create(mSize
, mFormat
, aAllocFlags
);
665 TextureFlags
D3D11TextureData::GetTextureFlags() const {
666 // With WebRender, resource open happens asynchronously on RenderThread.
667 // During opening the resource on host side, TextureClient needs to be alive.
668 // With WAIT_HOST_USAGE_END, keep TextureClient alive during host side usage.
669 return TextureFlags::WAIT_HOST_USAGE_END
;
672 void D3D11TextureData::RegisterQuery(RefPtr
<ID3D11Query
> aQuery
,
673 bool aOnlyForOverlay
) {
674 MOZ_ASSERT(XRE_IsGPUProcess());
675 MOZ_ASSERT(GpuProcessD3D11QueryMap::Get());
677 if (!GpuProcessD3D11QueryMap::Get()) {
681 if (mGpuProcessQueryId
.isNothing()) {
682 mGpuProcessQueryId
= Some(GpuProcessQueryId::GetNext());
684 mGpuProcessQueryId
.ref().mOnlyForOverlay
= aOnlyForOverlay
;
685 GpuProcessD3D11QueryMap::Get()->Register(mGpuProcessQueryId
.ref(), aQuery
);
688 DXGIYCbCrTextureData
* DXGIYCbCrTextureData::Create(
689 ID3D11Texture2D
* aTextureY
, ID3D11Texture2D
* aTextureCb
,
690 ID3D11Texture2D
* aTextureCr
, const gfx::IntSize
& aSize
,
691 const gfx::IntSize
& aSizeY
, const gfx::IntSize
& aSizeCbCr
,
692 gfx::ColorDepth aColorDepth
, YUVColorSpace aYUVColorSpace
,
693 gfx::ColorRange aColorRange
) {
694 if (!aTextureY
|| !aTextureCb
|| !aTextureCr
) {
698 aTextureY
->SetPrivateDataInterface(
700 new TextureMemoryMeasurer(aSizeY
.width
* aSizeY
.height
));
701 aTextureCb
->SetPrivateDataInterface(
703 new TextureMemoryMeasurer(aSizeCbCr
.width
* aSizeCbCr
.height
));
704 aTextureCr
->SetPrivateDataInterface(
706 new TextureMemoryMeasurer(aSizeCbCr
.width
* aSizeCbCr
.height
));
708 RefPtr
<IDXGIResource1
> resource
;
710 aTextureY
->QueryInterface((IDXGIResource1
**)getter_AddRefs(resource
));
713 HRESULT hr
= resource
->CreateSharedHandle(
714 nullptr, DXGI_SHARED_RESOURCE_READ
| DXGI_SHARED_RESOURCE_WRITE
, nullptr,
719 const RefPtr
<gfx::FileHandleWrapper
> sharedHandleY
=
720 new gfx::FileHandleWrapper(UniqueFileHandle(handleY
));
722 aTextureCb
->QueryInterface((IDXGIResource1
**)getter_AddRefs(resource
));
725 hr
= resource
->CreateSharedHandle(
726 nullptr, DXGI_SHARED_RESOURCE_READ
| DXGI_SHARED_RESOURCE_WRITE
, nullptr,
731 const RefPtr
<gfx::FileHandleWrapper
> sharedHandleCb
=
732 new gfx::FileHandleWrapper(UniqueFileHandle(handleCb
));
734 aTextureCr
->QueryInterface((IDXGIResource1
**)getter_AddRefs(resource
));
736 hr
= resource
->CreateSharedHandle(
737 nullptr, DXGI_SHARED_RESOURCE_READ
| DXGI_SHARED_RESOURCE_WRITE
, nullptr,
742 const RefPtr
<gfx::FileHandleWrapper
> sharedHandleCr
=
743 new gfx::FileHandleWrapper(UniqueFileHandle(handleCr
));
745 DXGIYCbCrTextureData
* texture
= new DXGIYCbCrTextureData();
746 texture
->mHandles
[0] = sharedHandleY
;
747 texture
->mHandles
[1] = sharedHandleCb
;
748 texture
->mHandles
[2] = sharedHandleCr
;
749 texture
->mD3D11Textures
[0] = aTextureY
;
750 texture
->mD3D11Textures
[1] = aTextureCb
;
751 texture
->mD3D11Textures
[2] = aTextureCr
;
752 texture
->mSize
= aSize
;
753 texture
->mSizeY
= aSizeY
;
754 texture
->mSizeCbCr
= aSizeCbCr
;
755 texture
->mColorDepth
= aColorDepth
;
756 texture
->mYUVColorSpace
= aYUVColorSpace
;
757 texture
->mColorRange
= aColorRange
;
762 void DXGIYCbCrTextureData::FillInfo(TextureData::Info
& aInfo
) const {
764 aInfo
.format
= gfx::SurfaceFormat::YUV420
;
765 aInfo
.supportsMoz2D
= false;
766 aInfo
.hasSynchronization
= false;
769 void DXGIYCbCrTextureData::SerializeSpecific(
770 SurfaceDescriptorDXGIYCbCr
* const aOutDesc
) {
771 *aOutDesc
= SurfaceDescriptorDXGIYCbCr(mHandles
[0], mHandles
[1], mHandles
[2],
772 mSize
, mSizeY
, mSizeCbCr
, mColorDepth
,
773 mYUVColorSpace
, mColorRange
);
776 bool DXGIYCbCrTextureData::Serialize(SurfaceDescriptor
& aOutDescriptor
) {
777 SurfaceDescriptorDXGIYCbCr desc
;
778 SerializeSpecific(&desc
);
780 aOutDescriptor
= std::move(desc
);
784 void DXGIYCbCrTextureData::GetSubDescriptor(
785 RemoteDecoderVideoSubDescriptor
* const aOutDesc
) {
786 SurfaceDescriptorDXGIYCbCr desc
;
787 SerializeSpecific(&desc
);
789 *aOutDesc
= std::move(desc
);
792 void DXGIYCbCrTextureData::Deallocate(LayersIPCChannel
*) {
793 mD3D11Textures
[0] = nullptr;
794 mD3D11Textures
[1] = nullptr;
795 mD3D11Textures
[2] = nullptr;
798 TextureFlags
DXGIYCbCrTextureData::GetTextureFlags() const {
799 // With WebRender, resource open happens asynchronously on RenderThread.
800 // During opening the resource on host side, TextureClient needs to be alive.
801 // With WAIT_HOST_USAGE_END, keep TextureClient alive during host side usage.
802 return TextureFlags::WAIT_HOST_USAGE_END
;
805 already_AddRefed
<TextureHost
> CreateTextureHostD3D11(
806 const SurfaceDescriptor
& aDesc
, ISurfaceAllocator
* aDeallocator
,
807 LayersBackend aBackend
, TextureFlags aFlags
) {
808 RefPtr
<TextureHost
> result
;
809 switch (aDesc
.type()) {
810 case SurfaceDescriptor::TSurfaceDescriptorD3D10
: {
812 new DXGITextureHostD3D11(aFlags
, aDesc
.get_SurfaceDescriptorD3D10());
815 case SurfaceDescriptor::TSurfaceDescriptorDXGIYCbCr
: {
816 result
= new DXGIYCbCrTextureHostD3D11(
817 aFlags
, aDesc
.get_SurfaceDescriptorDXGIYCbCr());
821 MOZ_ASSERT_UNREACHABLE("Unsupported SurfaceDescriptor type");
824 return result
.forget();
827 already_AddRefed
<DrawTarget
> D3D11TextureData::BorrowDrawTarget() {
828 MOZ_ASSERT(NS_IsMainThread() || NS_IsInCanvasThreadOrWorker());
830 if (!mDrawTarget
&& mTexture
) {
831 // This may return a null DrawTarget
832 mDrawTarget
= Factory::CreateDrawTargetForD3D11Texture(mTexture
, mFormat
);
834 gfxCriticalNote
<< "Could not borrow DrawTarget (D3D11) " << (int)mFormat
;
838 RefPtr
<DrawTarget
> result
= mDrawTarget
;
839 return result
.forget();
842 bool D3D11TextureData::UpdateFromSurface(gfx::SourceSurface
* aSurface
) {
843 // Supporting texture updates after creation requires an ID3D11DeviceContext
844 // and those aren't threadsafe. We'd need to either lock, or have a device for
845 // whatever thread this runs on and we're trying to avoid extra devices (bug
848 "UpdateFromSurface not supported for D3D11! Use CreateFromSurface "
853 static RefPtr
<ID3D11Texture2D
> OpenSharedD3D11Texture(
854 ID3D11Device
* const aDevice
, const HANDLE handle
) {
857 RefPtr
<ID3D11Device1
> device1
;
858 aDevice
->QueryInterface((ID3D11Device1
**)getter_AddRefs(device1
));
860 gfxCriticalNoteOnce
<< "Failed to get ID3D11Device1";
864 RefPtr
<ID3D11Texture2D
> tex
;
865 auto hr
= device1
->OpenSharedResource1(
866 (HANDLE
)handle
, __uuidof(ID3D11Texture2D
),
867 (void**)(ID3D11Texture2D
**)getter_AddRefs(tex
));
869 gfxCriticalNote
<< "Error code from OpenSharedResource1: " << gfx::hexa(hr
);
876 static RefPtr
<ID3D11Texture2D
> OpenSharedD3D11Texture(
877 DXGITextureHostD3D11
* aTextureHost
, ID3D11Device
* const aDevice
) {
879 MOZ_ASSERT(aTextureHost
);
881 const auto& handle
= aTextureHost
->mHandle
;
882 const auto& gpuProcessTextureId
= aTextureHost
->mGpuProcessTextureId
;
884 RefPtr
<ID3D11Texture2D
> texture
;
885 if (gpuProcessTextureId
.isSome()) {
886 auto* textureMap
= layers::GpuProcessD3D11TextureMap::Get();
888 texture
= textureMap
->GetTexture(gpuProcessTextureId
.ref());
891 texture
= OpenSharedD3D11Texture(aDevice
, handle
->GetHandle());
900 DXGITextureHostD3D11::DXGITextureHostD3D11(
901 TextureFlags aFlags
, const SurfaceDescriptorD3D10
& aDescriptor
)
902 : TextureHost(TextureHostType::DXGI
, aFlags
),
903 mHandle(aDescriptor
.handle()),
904 mGpuProcessTextureId(aDescriptor
.gpuProcessTextureId()),
905 mArrayIndex(aDescriptor
.arrayIndex()),
906 mGpuProcessQueryId(aDescriptor
.gpuProcessQueryId()),
907 mSize(aDescriptor
.size()),
908 mFormat(aDescriptor
.format()),
909 mHasKeyedMutex(aDescriptor
.hasKeyedMutex()),
910 mAcquireFenceInfo(aDescriptor
.fenceInfo().isSome()
911 ? aDescriptor
.fenceInfo().ref()
913 mColorSpace(aDescriptor
.colorSpace()),
914 mColorRange(aDescriptor
.colorRange()) {}
916 already_AddRefed
<gfx::DataSourceSurface
> DXGITextureHostD3D11::GetAsSurface(
917 gfx::DataSourceSurface
* aSurface
) {
918 RefPtr
<ID3D11Device
> d3d11Device
=
919 DeviceManagerDx::Get()->GetCompositorDevice();
924 RefPtr
<ID3D11Texture2D
> d3dTexture
=
925 OpenSharedD3D11Texture(this, d3d11Device
);
930 bool isLocked
= LockD3DTexture(d3dTexture
.get());
936 mozilla::MakeScopeExit([&]() { UnlockD3DTexture(d3dTexture
.get()); });
940 case gfx::SurfaceFormat::R8G8B8X8
:
941 case gfx::SurfaceFormat::R8G8B8A8
:
942 case gfx::SurfaceFormat::B8G8R8A8
:
943 case gfx::SurfaceFormat::B8G8R8X8
:
955 D3D11_TEXTURE2D_DESC textureDesc
= {0};
956 d3dTexture
->GetDesc(&textureDesc
);
958 RefPtr
<ID3D11DeviceContext
> context
;
959 d3d11Device
->GetImmediateContext(getter_AddRefs(context
));
961 textureDesc
.CPUAccessFlags
= D3D11_CPU_ACCESS_READ
;
962 textureDesc
.Usage
= D3D11_USAGE_STAGING
;
963 textureDesc
.BindFlags
= 0;
964 textureDesc
.MiscFlags
= 0;
965 textureDesc
.MipLevels
= 1;
966 RefPtr
<ID3D11Texture2D
> cpuTexture
;
967 HRESULT hr
= d3d11Device
->CreateTexture2D(&textureDesc
, nullptr,
968 getter_AddRefs(cpuTexture
));
973 context
->CopyResource(cpuTexture
, d3dTexture
);
975 D3D11_MAPPED_SUBRESOURCE mappedSubresource
;
976 hr
= context
->Map(cpuTexture
, 0, D3D11_MAP_READ
, 0, &mappedSubresource
);
981 RefPtr
<DataSourceSurface
> surf
= gfx::CreateDataSourceSurfaceFromData(
982 IntSize(textureDesc
.Width
, textureDesc
.Height
), GetFormat(),
983 (uint8_t*)mappedSubresource
.pData
, mappedSubresource
.RowPitch
);
984 context
->Unmap(cpuTexture
, 0);
985 return surf
.forget();
988 already_AddRefed
<gfx::DataSourceSurface
>
989 DXGITextureHostD3D11::GetAsSurfaceWithDevice(
990 ID3D11Device
* const aDevice
,
991 DataMutex
<RefPtr
<VideoProcessorD3D11
>>& aVideoProcessorD3D11
) {
996 RefPtr
<ID3D11Texture2D
> d3dTexture
= OpenSharedD3D11Texture(this, aDevice
);
1001 bool isLocked
= LockD3DTexture(d3dTexture
.get());
1007 mozilla::MakeScopeExit([&]() { UnlockD3DTexture(d3dTexture
.get()); });
1009 bool isRGB
= [&]() {
1011 case gfx::SurfaceFormat::R8G8B8X8
:
1012 case gfx::SurfaceFormat::R8G8B8A8
:
1013 case gfx::SurfaceFormat::B8G8R8A8
:
1014 case gfx::SurfaceFormat::B8G8R8X8
:
1023 RefPtr
<gfx::DrawTarget
> dt
=
1024 gfx::Factory::CreateDrawTargetForD3D11Texture(d3dTexture
, mFormat
);
1028 RefPtr
<gfx::SourceSurface
> surface
= dt
->Snapshot();
1032 RefPtr
<DataSourceSurface
> dataSurface
= surface
->GetDataSurface();
1036 return dataSurface
.forget();
1039 if (mFormat
!= gfx::SurfaceFormat::NV12
&&
1040 mFormat
!= gfx::SurfaceFormat::P010
&&
1041 mFormat
!= gfx::SurfaceFormat::P016
) {
1042 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
1046 RefPtr
<ID3D11Device
> device
;
1047 d3dTexture
->GetDevice(getter_AddRefs(device
));
1049 gfxCriticalNoteOnce
<< "Failed to get D3D11 device from source texture";
1053 RefPtr
<ID3D11DeviceContext
> context
;
1054 device
->GetImmediateContext(getter_AddRefs(context
));
1056 auto* queryMap
= GpuProcessD3D11QueryMap::Get();
1057 if (queryMap
&& mGpuProcessQueryId
.isSome()) {
1058 auto query
= queryMap
->GetQuery(mGpuProcessQueryId
.ref());
1060 // Wait ID3D11Query of D3D11Texture2D copy complete just before blitting
1061 // for video overlay with non Intel GPUs. See Bug 1817617.
1063 bool ret
= layers::WaitForFrameGPUQuery(device
, context
, query
, &result
);
1065 gfxCriticalNoteOnce
<< "WaitForFrameGPUQuery() failed";
1068 gfxCriticalNoteOnce
<< "Failed to get ID3D11Query";
1072 CD3D11_TEXTURE2D_DESC desc
;
1073 d3dTexture
->GetDesc(&desc
);
1075 desc
= CD3D11_TEXTURE2D_DESC(
1076 DXGI_FORMAT_B8G8R8A8_UNORM
, desc
.Width
, desc
.Height
, 1, 1,
1077 D3D11_BIND_RENDER_TARGET
| D3D11_BIND_SHADER_RESOURCE
);
1079 D3D11_RESOURCE_MISC_SHARED_NTHANDLE
| D3D11_RESOURCE_MISC_SHARED
;
1081 RefPtr
<ID3D11Texture2D
> copiedTexture
;
1083 device
->CreateTexture2D(&desc
, nullptr, getter_AddRefs(copiedTexture
));
1085 gfxCriticalNoteOnce
<< "Failed to create copiedTexture: " << gfx::hexa(hr
);
1090 auto lock
= aVideoProcessorD3D11
.Lock();
1091 auto& videoProcessor
= lock
.ref();
1092 if (videoProcessor
&& (videoProcessor
->mDevice
!= device
)) {
1093 videoProcessor
= nullptr;
1096 if (!videoProcessor
) {
1097 videoProcessor
= VideoProcessorD3D11::Create(device
);
1098 if (!videoProcessor
) {
1099 gfxCriticalNoteOnce
<< "Failed to create VideoProcessorD3D11";
1104 if (!videoProcessor
->Init(mSize
)) {
1105 gfxCriticalNoteOnce
<< "Failed to init VideoProcessorD3D11";
1109 if (!videoProcessor
->CallVideoProcessorBlt(this, d3dTexture
,
1111 gfxCriticalNoteOnce
<< "CallVideoProcessorBlt failed";
1117 // Wait VideoProcessorBlt gpu task complete.
1118 RefPtr
<ID3D11Query
> query
;
1119 CD3D11_QUERY_DESC
desc(D3D11_QUERY_EVENT
);
1120 hr
= device
->CreateQuery(&desc
, getter_AddRefs(query
));
1121 if (FAILED(hr
) || !query
) {
1122 gfxWarning() << "Could not create D3D11_QUERY_EVENT: " << gfx::hexa(hr
);
1126 context
->End(query
);
1129 bool ret
= WaitForFrameGPUQuery(device
, context
, query
, &result
);
1131 gfxCriticalNoteOnce
<< "WaitForFrameGPUQuery() failed";
1135 RefPtr
<IDXGIResource1
> resource
;
1136 copiedTexture
->QueryInterface((IDXGIResource1
**)getter_AddRefs(resource
));
1138 gfxCriticalNoteOnce
<< "Failed to get IDXGIResource";
1142 HANDLE sharedHandle
;
1143 hr
= resource
->CreateSharedHandle(
1144 nullptr, DXGI_SHARED_RESOURCE_READ
| DXGI_SHARED_RESOURCE_WRITE
, nullptr,
1147 gfxCriticalNoteOnce
<< "GetSharedHandle failed: " << gfx::hexa(hr
);
1151 RefPtr
<gfx::FileHandleWrapper
> handle
=
1152 new gfx::FileHandleWrapper(UniqueFileHandle(sharedHandle
));
1154 d3dTexture
= OpenSharedD3D11Texture(aDevice
, handle
->GetHandle());
1156 gfxCriticalNoteOnce
<< "Failed to open copied texture handle";
1160 RefPtr
<gfx::DrawTarget
> dt
= gfx::Factory::CreateDrawTargetForD3D11Texture(
1161 d3dTexture
, gfx::SurfaceFormat::B8G8R8A8
);
1163 gfxCriticalNote
<< "Failed to create DrawTarget (D3D11)";
1166 RefPtr
<gfx::SourceSurface
> surface
= dt
->Snapshot();
1170 RefPtr
<DataSourceSurface
> dataSurface
= surface
->GetDataSurface();
1175 return dataSurface
.forget();
1178 void DXGITextureHostD3D11::CreateRenderTexture(
1179 const wr::ExternalImageId
& aExternalImageId
) {
1180 MOZ_ASSERT(mExternalImageId
.isSome());
1182 RefPtr
<wr::RenderDXGITextureHost
> texture
= new wr::RenderDXGITextureHost(
1183 mHandle
, mGpuProcessTextureId
, mArrayIndex
, mFormat
, mColorSpace
,
1184 mColorRange
, mSize
, mHasKeyedMutex
, mAcquireFenceInfo
,
1185 mGpuProcessQueryId
);
1186 if (mFlags
& TextureFlags::SOFTWARE_DECODED_VIDEO
) {
1187 texture
->SetIsSoftwareDecodedVideo();
1189 if (mFlags
& TextureFlags::DRM_SOURCE
) {
1190 texture
->SetIsFromDRMSource(/* aIsFromDRMSource */ true);
1192 wr::RenderThread::Get()->RegisterExternalImage(aExternalImageId
,
1196 uint32_t DXGITextureHostD3D11::NumSubTextures() {
1197 switch (GetFormat()) {
1198 case gfx::SurfaceFormat::R8G8B8X8
:
1199 case gfx::SurfaceFormat::R8G8B8A8
:
1200 case gfx::SurfaceFormat::B8G8R8A8
:
1201 case gfx::SurfaceFormat::B8G8R8X8
: {
1204 case gfx::SurfaceFormat::NV12
:
1205 case gfx::SurfaceFormat::P010
:
1206 case gfx::SurfaceFormat::P016
: {
1210 MOZ_ASSERT_UNREACHABLE("unexpected format");
1216 void DXGITextureHostD3D11::PushResourceUpdates(
1217 wr::TransactionBuilder
& aResources
, ResourceUpdateOp aOp
,
1218 const Range
<wr::ImageKey
>& aImageKeys
, const wr::ExternalImageId
& aExtID
) {
1219 if (!gfx::gfxVars::UseWebRenderANGLE()) {
1220 MOZ_ASSERT_UNREACHABLE("unexpected to be called without ANGLE");
1224 MOZ_ASSERT(mHandle
|| mGpuProcessTextureId
.isSome());
1225 auto method
= aOp
== TextureHost::ADD_IMAGE
1226 ? &wr::TransactionBuilder::AddExternalImage
1227 : &wr::TransactionBuilder::UpdateExternalImage
;
1229 case gfx::SurfaceFormat::R8G8B8X8
:
1230 case gfx::SurfaceFormat::R8G8B8A8
:
1231 case gfx::SurfaceFormat::B8G8R8A8
:
1232 case gfx::SurfaceFormat::B8G8R8X8
: {
1233 MOZ_ASSERT(aImageKeys
.length() == 1);
1235 wr::ImageDescriptor
descriptor(mSize
, GetFormat());
1236 // Prefer TextureExternal unless the backend requires TextureRect.
1237 TextureHost::NativeTexturePolicy policy
=
1238 TextureHost::BackendNativeTexturePolicy(aResources
.GetBackendType(),
1240 auto imageType
= policy
== TextureHost::NativeTexturePolicy::REQUIRE
1241 ? wr::ExternalImageType::TextureHandle(
1242 wr::ImageBufferKind::TextureRect
)
1243 : wr::ExternalImageType::TextureHandle(
1244 wr::ImageBufferKind::TextureExternal
);
1245 (aResources
.*method
)(aImageKeys
[0], descriptor
, aExtID
, imageType
, 0,
1246 /* aNormalizedUvs */ false);
1249 case gfx::SurfaceFormat::P010
:
1250 case gfx::SurfaceFormat::P016
:
1251 case gfx::SurfaceFormat::NV12
: {
1252 MOZ_ASSERT(aImageKeys
.length() == 2);
1253 MOZ_ASSERT(mSize
.width
% 2 == 0);
1254 MOZ_ASSERT(mSize
.height
% 2 == 0);
1256 wr::ImageDescriptor
descriptor0(mSize
, mFormat
== gfx::SurfaceFormat::NV12
1257 ? gfx::SurfaceFormat::A8
1258 : gfx::SurfaceFormat::A16
);
1259 wr::ImageDescriptor
descriptor1(mSize
/ 2,
1260 mFormat
== gfx::SurfaceFormat::NV12
1261 ? gfx::SurfaceFormat::R8G8
1262 : gfx::SurfaceFormat::R16G16
);
1263 // Prefer TextureExternal unless the backend requires TextureRect.
1264 TextureHost::NativeTexturePolicy policy
=
1265 TextureHost::BackendNativeTexturePolicy(aResources
.GetBackendType(),
1267 auto imageType
= policy
== TextureHost::NativeTexturePolicy::REQUIRE
1268 ? wr::ExternalImageType::TextureHandle(
1269 wr::ImageBufferKind::TextureRect
)
1270 : wr::ExternalImageType::TextureHandle(
1271 wr::ImageBufferKind::TextureExternal
);
1272 (aResources
.*method
)(aImageKeys
[0], descriptor0
, aExtID
, imageType
, 0,
1273 /* aNormalizedUvs */ false);
1274 (aResources
.*method
)(aImageKeys
[1], descriptor1
, aExtID
, imageType
, 1,
1275 /* aNormalizedUvs */ false);
1279 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
1284 void DXGITextureHostD3D11::PushDisplayItems(
1285 wr::DisplayListBuilder
& aBuilder
, const wr::LayoutRect
& aBounds
,
1286 const wr::LayoutRect
& aClip
, wr::ImageRendering aFilter
,
1287 const Range
<wr::ImageKey
>& aImageKeys
, PushDisplayItemFlagSet aFlags
) {
1288 bool preferCompositorSurface
=
1289 aFlags
.contains(PushDisplayItemFlag::PREFER_COMPOSITOR_SURFACE
);
1290 if (!gfx::gfxVars::UseWebRenderANGLE()) {
1291 MOZ_ASSERT_UNREACHABLE("unexpected to be called without ANGLE");
1295 bool preferExternalCompositing
=
1296 SupportsExternalCompositing(aBuilder
.GetBackendType());
1297 if (aFlags
.contains(PushDisplayItemFlag::EXTERNAL_COMPOSITING_DISABLED
)) {
1298 MOZ_ASSERT(aBuilder
.GetBackendType() != WebRenderBackend::SOFTWARE
);
1299 preferExternalCompositing
= false;
1302 switch (GetFormat()) {
1303 case gfx::SurfaceFormat::R8G8B8X8
:
1304 case gfx::SurfaceFormat::R8G8B8A8
:
1305 case gfx::SurfaceFormat::B8G8R8A8
:
1306 case gfx::SurfaceFormat::B8G8R8X8
: {
1307 MOZ_ASSERT(aImageKeys
.length() == 1);
1308 aBuilder
.PushImage(aBounds
, aClip
, true, false, aFilter
, aImageKeys
[0],
1309 !(mFlags
& TextureFlags::NON_PREMULTIPLIED
),
1310 wr::ColorF
{1.0f
, 1.0f
, 1.0f
, 1.0f
},
1311 preferCompositorSurface
, preferExternalCompositing
);
1314 case gfx::SurfaceFormat::P010
:
1315 case gfx::SurfaceFormat::P016
:
1316 case gfx::SurfaceFormat::NV12
: {
1317 // DXGI_FORMAT_P010 stores its 10 bit value in the most significant bits
1318 // of each 16 bit word with the unused lower bits cleared to zero so that
1319 // it may be handled as if it was DXGI_FORMAT_P016. This is approximately
1320 // perceptually correct. However, due to rounding error, the precise
1321 // quantized value after sampling may be off by 1.
1322 MOZ_ASSERT(aImageKeys
.length() == 2);
1323 aBuilder
.PushNV12Image(
1324 aBounds
, aClip
, true, aImageKeys
[0], aImageKeys
[1],
1325 GetFormat() == gfx::SurfaceFormat::NV12
? wr::ColorDepth::Color8
1326 : wr::ColorDepth::Color16
,
1327 wr::ToWrYuvColorSpace(ToYUVColorSpace(mColorSpace
)),
1328 wr::ToWrColorRange(mColorRange
), aFilter
, preferCompositorSurface
,
1329 preferExternalCompositing
);
1333 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
1338 bool DXGITextureHostD3D11::SupportsExternalCompositing(
1339 WebRenderBackend aBackend
) {
1340 if (aBackend
== WebRenderBackend::SOFTWARE
) {
1343 // XXX Add P010 and P016 support.
1344 if (GetFormat() == gfx::SurfaceFormat::NV12
) {
1345 if ((mFlags
& TextureFlags::SOFTWARE_DECODED_VIDEO
) &&
1346 (gfx::gfxVars::UseWebRenderDCompVideoSwOverlayWin())) {
1349 if (!(mFlags
& TextureFlags::SOFTWARE_DECODED_VIDEO
) &&
1350 (gfx::gfxVars::UseWebRenderDCompVideoHwOverlayWin())) {
1357 DXGIYCbCrTextureHostD3D11::DXGIYCbCrTextureHostD3D11(
1358 TextureFlags aFlags
, const SurfaceDescriptorDXGIYCbCr
& aDescriptor
)
1359 : TextureHost(TextureHostType::DXGIYCbCr
, aFlags
),
1360 mSize(aDescriptor
.size()),
1361 mSizeY(aDescriptor
.sizeY()),
1362 mSizeCbCr(aDescriptor
.sizeCbCr()),
1364 mColorDepth(aDescriptor
.colorDepth()),
1365 mYUVColorSpace(aDescriptor
.yUVColorSpace()),
1366 mColorRange(aDescriptor
.colorRange()) {
1367 mHandles
[0] = aDescriptor
.handleY();
1368 mHandles
[1] = aDescriptor
.handleCb();
1369 mHandles
[2] = aDescriptor
.handleCr();
1372 void DXGIYCbCrTextureHostD3D11::CreateRenderTexture(
1373 const wr::ExternalImageId
& aExternalImageId
) {
1374 MOZ_ASSERT(mExternalImageId
.isSome());
1376 RefPtr
<wr::RenderTextureHost
> texture
= new wr::RenderDXGIYCbCrTextureHost(
1377 mHandles
, mYUVColorSpace
, mColorDepth
, mColorRange
, mSizeY
, mSizeCbCr
);
1379 wr::RenderThread::Get()->RegisterExternalImage(aExternalImageId
,
1383 uint32_t DXGIYCbCrTextureHostD3D11::NumSubTextures() {
1384 // ycbcr use 3 sub textures.
1388 void DXGIYCbCrTextureHostD3D11::PushResourceUpdates(
1389 wr::TransactionBuilder
& aResources
, ResourceUpdateOp aOp
,
1390 const Range
<wr::ImageKey
>& aImageKeys
, const wr::ExternalImageId
& aExtID
) {
1391 if (!gfx::gfxVars::UseWebRenderANGLE()) {
1392 MOZ_ASSERT_UNREACHABLE("unexpected to be called without ANGLE");
1396 MOZ_ASSERT(mHandles
[0] && mHandles
[1] && mHandles
[2]);
1397 MOZ_ASSERT(aImageKeys
.length() == 3);
1398 // Assume the chroma planes are rounded up if the luma plane is odd sized.
1399 MOZ_ASSERT((mSizeCbCr
.width
== mSizeY
.width
||
1400 mSizeCbCr
.width
== (mSizeY
.width
+ 1) >> 1) &&
1401 (mSizeCbCr
.height
== mSizeY
.height
||
1402 mSizeCbCr
.height
== (mSizeY
.height
+ 1) >> 1));
1404 auto method
= aOp
== TextureHost::ADD_IMAGE
1405 ? &wr::TransactionBuilder::AddExternalImage
1406 : &wr::TransactionBuilder::UpdateExternalImage
;
1408 // Prefer TextureExternal unless the backend requires TextureRect.
1409 // Use a size that is the maximum of the Y and CbCr sizes.
1410 IntSize textureSize
= std::max(mSizeY
, mSizeCbCr
);
1411 TextureHost::NativeTexturePolicy policy
=
1412 TextureHost::BackendNativeTexturePolicy(aResources
.GetBackendType(),
1414 auto imageType
= policy
== TextureHost::NativeTexturePolicy::REQUIRE
1415 ? wr::ExternalImageType::TextureHandle(
1416 wr::ImageBufferKind::TextureRect
)
1417 : wr::ExternalImageType::TextureHandle(
1418 wr::ImageBufferKind::TextureExternal
);
1421 wr::ImageDescriptor
descriptor0(mSizeY
, gfx::SurfaceFormat::A8
);
1423 wr::ImageDescriptor
descriptor1(mSizeCbCr
, gfx::SurfaceFormat::A8
);
1424 (aResources
.*method
)(aImageKeys
[0], descriptor0
, aExtID
, imageType
, 0,
1425 /* aNormalizedUvs */ false);
1426 (aResources
.*method
)(aImageKeys
[1], descriptor1
, aExtID
, imageType
, 1,
1427 /* aNormalizedUvs */ false);
1428 (aResources
.*method
)(aImageKeys
[2], descriptor1
, aExtID
, imageType
, 2,
1429 /* aNormalizedUvs */ false);
1432 void DXGIYCbCrTextureHostD3D11::PushDisplayItems(
1433 wr::DisplayListBuilder
& aBuilder
, const wr::LayoutRect
& aBounds
,
1434 const wr::LayoutRect
& aClip
, wr::ImageRendering aFilter
,
1435 const Range
<wr::ImageKey
>& aImageKeys
, PushDisplayItemFlagSet aFlags
) {
1436 if (!gfx::gfxVars::UseWebRenderANGLE()) {
1437 MOZ_ASSERT_UNREACHABLE("unexpected to be called without ANGLE");
1441 MOZ_ASSERT(aImageKeys
.length() == 3);
1443 aBuilder
.PushYCbCrPlanarImage(
1444 aBounds
, aClip
, true, aImageKeys
[0], aImageKeys
[1], aImageKeys
[2],
1445 wr::ToWrColorDepth(mColorDepth
), wr::ToWrYuvColorSpace(mYUVColorSpace
),
1446 wr::ToWrColorRange(mColorRange
), aFilter
,
1447 aFlags
.contains(PushDisplayItemFlag::PREFER_COMPOSITOR_SURFACE
),
1448 SupportsExternalCompositing(aBuilder
.GetBackendType()));
1451 bool DXGIYCbCrTextureHostD3D11::SupportsExternalCompositing(
1452 WebRenderBackend aBackend
) {
1453 return aBackend
== WebRenderBackend::SOFTWARE
;
1456 bool DataTextureSourceD3D11::Update(DataSourceSurface
* aSurface
,
1457 nsIntRegion
* aDestRegion
,
1458 IntPoint
* aSrcOffset
,
1459 IntPoint
* aDstOffset
) {
1460 // Incremental update with a source offset is only used on Mac so it is not
1461 // clear that we ever will need to support it for D3D.
1462 MOZ_ASSERT(!aSrcOffset
);
1463 MOZ_RELEASE_ASSERT(!aDstOffset
);
1464 MOZ_ASSERT(aSurface
);
1466 MOZ_ASSERT(mAllowTextureUploads
);
1467 if (!mAllowTextureUploads
) {
1477 uint32_t bpp
= BytesPerPixel(aSurface
->GetFormat());
1478 DXGI_FORMAT dxgiFormat
= SurfaceFormatToDXGIFormat(aSurface
->GetFormat());
1480 mSize
= aSurface
->GetSize();
1481 mFormat
= aSurface
->GetFormat();
1483 CD3D11_TEXTURE2D_DESC
desc(dxgiFormat
, mSize
.width
, mSize
.height
, 1, 1);
1485 int32_t maxSize
= GetMaxTextureSizeFromDevice(mDevice
);
1486 if ((mSize
.width
<= maxSize
&& mSize
.height
<= maxSize
) ||
1487 (mFlags
& TextureFlags::DISALLOW_BIGIMAGE
)) {
1489 D3D11_TEXTURE2D_DESC currentDesc
;
1490 mTexture
->GetDesc(¤tDesc
);
1492 // Make sure there's no size mismatch, if there is, recreate.
1493 if (static_cast<int32_t>(currentDesc
.Width
) != mSize
.width
||
1494 static_cast<int32_t>(currentDesc
.Height
) != mSize
.height
||
1495 currentDesc
.Format
!= dxgiFormat
) {
1497 // Make sure we upload the whole surface.
1498 aDestRegion
= nullptr;
1502 nsIntRegion
* regionToUpdate
= aDestRegion
;
1504 hr
= mDevice
->CreateTexture2D(&desc
, nullptr, getter_AddRefs(mTexture
));
1506 if (FAILED(hr
) || !mTexture
) {
1511 if (mFlags
& TextureFlags::COMPONENT_ALPHA
) {
1512 regionToUpdate
= nullptr;
1516 DataSourceSurface::MappedSurface map
;
1517 if (!aSurface
->Map(DataSourceSurface::MapType::READ
, &map
)) {
1518 gfxCriticalError() << "Failed to map surface.";
1523 RefPtr
<ID3D11DeviceContext
> context
;
1524 mDevice
->GetImmediateContext(getter_AddRefs(context
));
1526 if (regionToUpdate
) {
1527 for (auto iter
= regionToUpdate
->RectIter(); !iter
.Done(); iter
.Next()) {
1528 const IntRect
& rect
= iter
.Get();
1532 box
.left
= rect
.X();
1534 box
.right
= rect
.XMost();
1535 box
.bottom
= rect
.YMost();
1537 void* data
= map
.mData
+ map
.mStride
* rect
.Y() +
1538 BytesPerPixel(aSurface
->GetFormat()) * rect
.X();
1540 context
->UpdateSubresource(mTexture
, 0, &box
, data
, map
.mStride
,
1541 map
.mStride
* rect
.Height());
1544 context
->UpdateSubresource(mTexture
, 0, nullptr, map
.mData
, map
.mStride
,
1545 map
.mStride
* mSize
.height
);
1551 uint32_t tileCount
= GetRequiredTilesD3D11(mSize
.width
, maxSize
) *
1552 GetRequiredTilesD3D11(mSize
.height
, maxSize
);
1554 mTileTextures
.resize(tileCount
);
1555 mTileSRVs
.resize(tileCount
);
1558 DataSourceSurface::ScopedMap
map(aSurface
, DataSourceSurface::READ
);
1559 if (!map
.IsMapped()) {
1560 gfxCriticalError() << "Failed to map surface.";
1565 for (uint32_t i
= 0; i
< tileCount
; i
++) {
1566 IntRect tileRect
= GetTileRect(i
);
1568 desc
.Width
= tileRect
.Width();
1569 desc
.Height
= tileRect
.Height();
1570 desc
.Usage
= D3D11_USAGE_IMMUTABLE
;
1572 D3D11_SUBRESOURCE_DATA initData
;
1574 map
.GetData() + tileRect
.Y() * map
.GetStride() + tileRect
.X() * bpp
;
1575 initData
.SysMemPitch
= map
.GetStride();
1577 hr
= mDevice
->CreateTexture2D(&desc
, &initData
,
1578 getter_AddRefs(mTileTextures
[i
]));
1579 if (FAILED(hr
) || !mTileTextures
[i
]) {
1588 ID3D11Texture2D
* DataTextureSourceD3D11::GetD3D11Texture() const {
1589 return mIterating
? mTileTextures
[mCurrentTile
] : mTexture
;
1592 RefPtr
<TextureSource
> DataTextureSourceD3D11::ExtractCurrentTile() {
1593 MOZ_ASSERT(mIterating
);
1594 return new DataTextureSourceD3D11(mDevice
, mFormat
,
1595 mTileTextures
[mCurrentTile
]);
1598 ID3D11ShaderResourceView
* DataTextureSourceD3D11::GetShaderResourceView() {
1600 if (!mTileSRVs
[mCurrentTile
]) {
1601 if (!mTileTextures
[mCurrentTile
]) {
1605 RefPtr
<ID3D11Device
> device
;
1606 mTileTextures
[mCurrentTile
]->GetDevice(getter_AddRefs(device
));
1607 HRESULT hr
= device
->CreateShaderResourceView(
1608 mTileTextures
[mCurrentTile
], nullptr,
1609 getter_AddRefs(mTileSRVs
[mCurrentTile
]));
1612 << "[D3D11] DataTextureSourceD3D11:GetShaderResourceView CreateSRV "
1618 return mTileSRVs
[mCurrentTile
];
1621 return TextureSourceD3D11::GetShaderResourceView();
1624 void DataTextureSourceD3D11::Reset() {
1626 mTileSRVs
.resize(0);
1627 mTileTextures
.resize(0);
1633 IntRect
DataTextureSourceD3D11::GetTileRect(uint32_t aIndex
) const {
1634 return GetTileRectD3D11(aIndex
, mSize
, GetMaxTextureSizeFromDevice(mDevice
));
1637 IntRect
DataTextureSourceD3D11::GetTileRect() {
1638 IntRect rect
= GetTileRect(mCurrentTile
);
1639 return IntRect(rect
.X(), rect
.Y(), rect
.Width(), rect
.Height());
1642 CompositingRenderTargetD3D11::CompositingRenderTargetD3D11(
1643 ID3D11Texture2D
* aTexture
, const gfx::IntPoint
& aOrigin
,
1644 DXGI_FORMAT aFormatOverride
)
1645 : CompositingRenderTarget(aOrigin
) {
1646 MOZ_ASSERT(aTexture
);
1648 mTexture
= aTexture
;
1650 RefPtr
<ID3D11Device
> device
;
1651 mTexture
->GetDevice(getter_AddRefs(device
));
1653 mFormatOverride
= aFormatOverride
;
1655 // If we happen to have a typeless underlying DXGI surface, we need to be
1656 // explicit about the format here. (Such a surface could come from an external
1657 // source, such as the Oculus compositor)
1658 CD3D11_RENDER_TARGET_VIEW_DESC
rtvDesc(D3D11_RTV_DIMENSION_TEXTURE2D
,
1660 D3D11_RENDER_TARGET_VIEW_DESC
* desc
=
1661 aFormatOverride
== DXGI_FORMAT_UNKNOWN
? nullptr : &rtvDesc
;
1664 device
->CreateRenderTargetView(mTexture
, desc
, getter_AddRefs(mRTView
));
1667 LOGD3D11("Failed to create RenderTargetView.");
1671 void CompositingRenderTargetD3D11::BindRenderTarget(
1672 ID3D11DeviceContext
* aContext
) {
1674 FLOAT clear
[] = {0, 0, 0, 0};
1675 aContext
->ClearRenderTargetView(mRTView
, clear
);
1676 mClearOnBind
= false;
1678 ID3D11RenderTargetView
* view
= mRTView
;
1679 aContext
->OMSetRenderTargets(1, &view
, nullptr);
1682 IntSize
CompositingRenderTargetD3D11::GetSize() const {
1683 return TextureSourceD3D11::GetSize();
1686 static inline bool ShouldDevCrashOnSyncInitFailure() {
1687 // Compositor shutdown does not wait for video decoding to finish, so it is
1688 // possible for the compositor to destroy the SyncObject before video has a
1689 // chance to initialize it.
1690 if (!NS_IsMainThread()) {
1694 // Note: CompositorIsInGPUProcess is a main-thread-only function.
1695 return !CompositorBridgeChild::CompositorIsInGPUProcess() &&
1696 !DeviceManagerDx::Get()->HasDeviceReset();
1699 SyncObjectD3D11Host::SyncObjectD3D11Host(ID3D11Device
* aDevice
)
1700 : mSyncHandle(nullptr), mDevice(aDevice
) {
1701 MOZ_ASSERT(aDevice
);
1704 bool SyncObjectD3D11Host::Init() {
1705 CD3D11_TEXTURE2D_DESC
desc(
1706 DXGI_FORMAT_B8G8R8A8_UNORM
, 1, 1, 1, 1,
1707 D3D11_BIND_SHADER_RESOURCE
| D3D11_BIND_RENDER_TARGET
);
1708 desc
.MiscFlags
= D3D11_RESOURCE_MISC_SHARED_NTHANDLE
|
1709 D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX
;
1711 RefPtr
<ID3D11Texture2D
> texture
;
1713 mDevice
->CreateTexture2D(&desc
, nullptr, getter_AddRefs(texture
));
1714 if (FAILED(hr
) || !texture
) {
1715 gfxWarning() << "Could not create a sync texture: " << gfx::hexa(hr
);
1719 hr
= texture
->QueryInterface((IDXGIResource1
**)getter_AddRefs(mSyncTexture
));
1720 if (FAILED(hr
) || !mSyncTexture
) {
1721 gfxWarning() << "Could not QI sync texture: " << gfx::hexa(hr
);
1725 hr
= mSyncTexture
->QueryInterface(
1726 (IDXGIKeyedMutex
**)getter_AddRefs(mKeyedMutex
));
1727 if (FAILED(hr
) || !mKeyedMutex
) {
1728 gfxWarning() << "Could not QI keyed-mutex: " << gfx::hexa(hr
);
1732 HANDLE sharedHandle
;
1733 hr
= mSyncTexture
->CreateSharedHandle(
1734 nullptr, DXGI_SHARED_RESOURCE_READ
| DXGI_SHARED_RESOURCE_WRITE
, nullptr,
1737 gfxWarning() << "Could not get sync texture shared handle: "
1741 mSyncHandle
= new gfx::FileHandleWrapper(UniqueFileHandle(sharedHandle
));
1746 SyncHandle
SyncObjectD3D11Host::GetSyncHandle() { return mSyncHandle
; }
1748 bool SyncObjectD3D11Host::Synchronize(bool aFallible
) {
1750 AutoTextureLock
lock(mKeyedMutex
, hr
, 10000);
1752 if (hr
== WAIT_TIMEOUT
) {
1753 hr
= mDevice
->GetDeviceRemovedReason();
1755 // Since the timeout is related to the driver-removed. Return false for
1757 gfxCriticalNote
<< "GFX: D3D11 timeout with device-removed:"
1759 } else if (aFallible
) {
1760 gfxCriticalNote
<< "GFX: D3D11 timeout on the D3D11 sync lock.";
1762 // There is no driver-removed event. Crash with this timeout.
1763 MOZ_CRASH("GFX: D3D11 normal status timeout");
1768 if (hr
== WAIT_ABANDONED
) {
1769 gfxCriticalNote
<< "GFX: AL_D3D11 abandoned sync";
1775 SyncObjectD3D11Client::SyncObjectD3D11Client(SyncHandle aSyncHandle
,
1776 ID3D11Device
* aDevice
)
1777 : mSyncLock("SyncObjectD3D11"), mSyncHandle(aSyncHandle
), mDevice(aDevice
) {
1778 MOZ_ASSERT(aDevice
);
1781 SyncObjectD3D11Client::SyncObjectD3D11Client(SyncHandle aSyncHandle
)
1782 : mSyncLock("SyncObjectD3D11"), mSyncHandle(aSyncHandle
) {}
1784 bool SyncObjectD3D11Client::Init(ID3D11Device
* aDevice
, bool aFallible
) {
1793 RefPtr
<ID3D11Device1
> device1
;
1794 aDevice
->QueryInterface((ID3D11Device1
**)getter_AddRefs(device1
));
1796 gfxCriticalNoteOnce
<< "Failed to get ID3D11Device1";
1800 HRESULT hr
= device1
->OpenSharedResource1(
1801 mSyncHandle
->GetHandle(), __uuidof(ID3D11Texture2D
),
1802 (void**)(ID3D11Texture2D
**)getter_AddRefs(mSyncTexture
));
1803 if (FAILED(hr
) || !mSyncTexture
) {
1804 gfxCriticalNote
<< "Failed to OpenSharedResource1 for SyncObjectD3D11: "
1806 if (!aFallible
&& ShouldDevCrashOnSyncInitFailure()) {
1807 gfxDevCrash(LogReason::D3D11FinalizeFrame
)
1808 << "Without device reset: " << hexa(hr
);
1813 hr
= mSyncTexture
->QueryInterface(__uuidof(IDXGIKeyedMutex
),
1814 getter_AddRefs(mKeyedMutex
));
1815 if (FAILED(hr
) || !mKeyedMutex
) {
1816 // Leave both the critical error and MOZ_CRASH for now; the critical error
1817 // lets us "save" the hr value. We will probably eventually replace this
1818 // with gfxDevCrash.
1820 gfxCriticalError() << "Failed to get KeyedMutex (2): " << hexa(hr
);
1821 MOZ_CRASH("GFX: Cannot get D3D11 KeyedMutex");
1823 gfxCriticalNote
<< "Failed to get KeyedMutex (3): " << hexa(hr
);
1831 void SyncObjectD3D11Client::RegisterTexture(ID3D11Texture2D
* aTexture
) {
1832 mSyncedTextures
.push_back(aTexture
);
1835 bool SyncObjectD3D11Client::IsSyncObjectValid() {
1836 MOZ_ASSERT(mDevice
);
1840 // We have only 1 sync object. As a thing that somehow works,
1841 // we copy each of the textures that need to be synced with the compositor
1842 // into our sync object and only use a lock for this sync object.
1843 // This way, we don't have to sync every texture we send to the compositor.
1844 // We only have to do this once per transaction.
1845 bool SyncObjectD3D11Client::Synchronize(bool aFallible
) {
1846 MOZ_ASSERT(mDevice
);
1847 // Since this can be called from either the Paint or Main thread.
1848 // We don't want this to race since we initialize the sync texture here
1850 MutexAutoLock
syncLock(mSyncLock
);
1852 if (!mSyncedTextures
.size()) {
1855 if (!Init(mDevice
, aFallible
)) {
1859 return SynchronizeInternal(mDevice
, aFallible
);
1862 bool SyncObjectD3D11Client::SynchronizeInternal(ID3D11Device
* aDevice
,
1864 mSyncLock
.AssertCurrentThreadOwns();
1867 AutoTextureLock
lock(mKeyedMutex
, hr
, 20000);
1869 if (hr
== WAIT_TIMEOUT
) {
1870 if (DeviceManagerDx::Get()->HasDeviceReset()) {
1871 gfxWarning() << "AcquireSync timed out because of device reset.";
1875 gfxWarning() << "Timeout on the D3D11 sync lock.";
1877 gfxDevCrash(LogReason::D3D11SyncLock
)
1878 << "Timeout on the D3D11 sync lock.";
1884 box
.front
= box
.top
= box
.left
= 0;
1885 box
.back
= box
.bottom
= box
.right
= 1;
1887 RefPtr
<ID3D11DeviceContext
> ctx
;
1888 aDevice
->GetImmediateContext(getter_AddRefs(ctx
));
1890 for (auto iter
= mSyncedTextures
.begin(); iter
!= mSyncedTextures
.end();
1892 ctx
->CopySubresourceRegion(mSyncTexture
, 0, 0, 0, 0, *iter
, 0, &box
);
1895 mSyncedTextures
.clear();
1900 uint32_t GetMaxTextureSizeFromDevice(ID3D11Device
* aDevice
) {
1901 return GetMaxTextureSizeForFeatureLevel(aDevice
->GetFeatureLevel());
1904 AutoLockD3D11Texture::AutoLockD3D11Texture(ID3D11Texture2D
* aTexture
) {
1905 aTexture
->QueryInterface((IDXGIKeyedMutex
**)getter_AddRefs(mMutex
));
1909 HRESULT hr
= mMutex
->AcquireSync(0, 10000);
1910 if (hr
== WAIT_TIMEOUT
) {
1911 MOZ_CRASH("GFX: IMFYCbCrImage timeout");
1915 NS_WARNING("Failed to lock the texture");
1919 AutoLockD3D11Texture::~AutoLockD3D11Texture() {
1923 HRESULT hr
= mMutex
->ReleaseSync(0);
1925 NS_WARNING("Failed to unlock the texture");
1929 SyncObjectD3D11ClientContentDevice::SyncObjectD3D11ClientContentDevice(
1930 SyncHandle aSyncHandle
)
1931 : SyncObjectD3D11Client(aSyncHandle
) {}
1933 bool SyncObjectD3D11ClientContentDevice::Synchronize(bool aFallible
) {
1934 // Since this can be called from either the Paint or Main thread.
1935 // We don't want this to race since we initialize the sync texture here
1937 MutexAutoLock
syncLock(mSyncLock
);
1939 MOZ_ASSERT(mContentDevice
);
1941 if (!mSyncedTextures
.size()) {
1945 if (!Init(mContentDevice
, aFallible
)) {
1949 RefPtr
<ID3D11Device
> dev
;
1950 mSyncTexture
->GetDevice(getter_AddRefs(dev
));
1952 if (dev
== DeviceManagerDx::Get()->GetContentDevice()) {
1953 if (DeviceManagerDx::Get()->HasDeviceReset()) {
1958 if (dev
!= mContentDevice
) {
1959 gfxWarning() << "Attempt to sync texture from invalid device.";
1963 return SyncObjectD3D11Client::SynchronizeInternal(dev
, aFallible
);
1966 bool SyncObjectD3D11ClientContentDevice::IsSyncObjectValid() {
1967 RefPtr
<ID3D11Device
> dev
;
1968 // There is a case that devices are not initialized yet with WebRender.
1969 if (gfxPlatform::GetPlatform()->DevicesInitialized()) {
1970 dev
= DeviceManagerDx::Get()->GetContentDevice();
1973 // Update mDevice if the ContentDevice initialization is detected.
1974 if (!mContentDevice
&& dev
&& NS_IsMainThread()) {
1975 mContentDevice
= dev
;
1978 if (!dev
|| (NS_IsMainThread() && dev
!= mContentDevice
)) {
1984 void SyncObjectD3D11ClientContentDevice::EnsureInitialized() {
1985 if (mContentDevice
) {
1989 if (XRE_IsGPUProcess() || !gfxPlatform::GetPlatform()->DevicesInitialized()) {
1993 mContentDevice
= DeviceManagerDx::Get()->GetContentDevice();
1996 } // namespace layers
1997 } // namespace mozilla