1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "TextureD3D11.h"
7 #include "CompositorD3D11.h"
8 #include "gfxContext.h"
9 #include "Effects.h"
10 #include "gfxWindowsPlatform.h"
11 #include "gfx2DGlue.h"
12 #include "gfxPrefs.h"
13 #include "ReadbackManagerD3D11.h"
14 #include "mozilla/gfx/DeviceManagerDx.h"
15 #include "mozilla/gfx/Logging.h"
16
17 namespace mozilla {
18
19 using namespace gfx;
20
21 namespace layers {
22
23 static const GUID sD3D11TextureUsage =
24 { 0xd89275b0, 0x6c7d, 0x4038, { 0xb5, 0xfa, 0x4d, 0x87, 0x16, 0xd5, 0xcc, 0x4e } };
25
26 /* This class gets its lifetime tied to a D3D texture
27 * and increments memory usage on construction and decrements
28 * on destruction */
29 class TextureMemoryMeasurer : public IUnknown
30 {
31 public:
TextureMemoryMeasurer(size_t aMemoryUsed)32 TextureMemoryMeasurer(size_t aMemoryUsed)
33 {
34 mMemoryUsed = aMemoryUsed;
35 gfxWindowsPlatform::sD3D11SharedTextures += mMemoryUsed;
36 mRefCnt = 0;
37 }
AddRef()38 STDMETHODIMP_(ULONG) AddRef() {
39 mRefCnt++;
40 return mRefCnt;
41 }
QueryInterface(REFIID riid,void ** ppvObject)42 STDMETHODIMP QueryInterface(REFIID riid,
43 void **ppvObject)
44 {
45 IUnknown *punk = nullptr;
46 if (riid == IID_IUnknown) {
47 punk = this;
48 }
49 *ppvObject = punk;
50 if (punk) {
51 punk->AddRef();
52 return S_OK;
53 } else {
54 return E_NOINTERFACE;
55 }
56 }
57
Release()58 STDMETHODIMP_(ULONG) Release() {
59 int refCnt = --mRefCnt;
60 if (refCnt == 0) {
61 gfxWindowsPlatform::sD3D11SharedTextures -= mMemoryUsed;
62 delete this;
63 }
64 return refCnt;
65 }
66 private:
67 int mRefCnt;
68 int mMemoryUsed;
69 };
70
71 static DXGI_FORMAT
SurfaceFormatToDXGIFormat(gfx::SurfaceFormat aFormat)72 SurfaceFormatToDXGIFormat(gfx::SurfaceFormat aFormat)
73 {
74 switch (aFormat) {
75 case SurfaceFormat::B8G8R8A8:
76 return DXGI_FORMAT_B8G8R8A8_UNORM;
77 case SurfaceFormat::B8G8R8X8:
78 return DXGI_FORMAT_B8G8R8A8_UNORM;
79 case SurfaceFormat::R8G8B8A8:
80 return DXGI_FORMAT_R8G8B8A8_UNORM;
81 case SurfaceFormat::R8G8B8X8:
82 return DXGI_FORMAT_R8G8B8A8_UNORM;
83 case SurfaceFormat::A8:
84 return DXGI_FORMAT_R8_UNORM;
85 default:
86 MOZ_ASSERT(false, "unsupported format");
87 return DXGI_FORMAT_UNKNOWN;
88 }
89 }
90
91 static uint32_t
GetRequiredTilesD3D11(uint32_t aSize,uint32_t aMaxSize)92 GetRequiredTilesD3D11(uint32_t aSize, uint32_t aMaxSize)
93 {
94 uint32_t requiredTiles = aSize / aMaxSize;
95 if (aSize % aMaxSize) {
96 requiredTiles++;
97 }
98 return requiredTiles;
99 }
100
101 static IntRect
GetTileRectD3D11(uint32_t aID,IntSize aSize,uint32_t aMaxSize)102 GetTileRectD3D11(uint32_t aID, IntSize aSize, uint32_t aMaxSize)
103 {
104 uint32_t horizontalTiles = GetRequiredTilesD3D11(aSize.width, aMaxSize);
105 uint32_t verticalTiles = GetRequiredTilesD3D11(aSize.height, aMaxSize);
106
107 uint32_t verticalTile = aID / horizontalTiles;
108 uint32_t horizontalTile = aID % horizontalTiles;
109
110 return IntRect(horizontalTile * aMaxSize,
111 verticalTile * aMaxSize,
112 horizontalTile < (horizontalTiles - 1) ? aMaxSize : aSize.width % aMaxSize,
113 verticalTile < (verticalTiles - 1) ? aMaxSize : aSize.height % aMaxSize);
114 }
115
AutoTextureLock(IDXGIKeyedMutex * aMutex,HRESULT & aResult,uint32_t aTimeout)116 AutoTextureLock::AutoTextureLock(IDXGIKeyedMutex* aMutex,
117 HRESULT& aResult,
118 uint32_t aTimeout)
119 {
120 mMutex = aMutex;
121 mResult = mMutex->AcquireSync(0, aTimeout);
122 aResult = mResult;
123 }
124
~AutoTextureLock()125 AutoTextureLock::~AutoTextureLock()
126 {
127 if (!FAILED(mResult) && mResult != WAIT_TIMEOUT &&
128 mResult != WAIT_ABANDONED) {
129 mMutex->ReleaseSync(0);
130 }
131 }
132
133 ID3D11ShaderResourceView*
GetShaderResourceView()134 TextureSourceD3D11::GetShaderResourceView()
135 {
136 MOZ_ASSERT(mTexture == GetD3D11Texture(), "You need to override GetShaderResourceView if you're overriding GetD3D11Texture!");
137
138 if (!mSRV && mTexture) {
139 RefPtr<ID3D11Device> device;
140 mTexture->GetDevice(getter_AddRefs(device));
141
142 // see comment in CompositingRenderTargetD3D11 constructor
143 CD3D11_SHADER_RESOURCE_VIEW_DESC srvDesc(D3D11_SRV_DIMENSION_TEXTURE2D, mFormatOverride);
144 D3D11_SHADER_RESOURCE_VIEW_DESC *desc = mFormatOverride == DXGI_FORMAT_UNKNOWN ? nullptr : &srvDesc;
145
146 HRESULT hr = device->CreateShaderResourceView(mTexture, desc, getter_AddRefs(mSRV));
147 if (FAILED(hr)) {
148 gfxCriticalNote << "[D3D11] TextureSourceD3D11:GetShaderResourceView CreateSRV failure " << gfx::hexa(hr);
149 return nullptr;
150 }
151 }
152 return mSRV;
153 }
154
DataTextureSourceD3D11(SurfaceFormat aFormat,CompositorD3D11 * aCompositor,TextureFlags aFlags)155 DataTextureSourceD3D11::DataTextureSourceD3D11(SurfaceFormat aFormat,
156 CompositorD3D11* aCompositor,
157 TextureFlags aFlags)
158 : mCompositor(aCompositor)
159 , mFormat(aFormat)
160 , mFlags(aFlags)
161 , mCurrentTile(0)
162 , mIsTiled(false)
163 , mIterating(false)
164 , mAllowTextureUploads(true)
165 {
166 MOZ_COUNT_CTOR(DataTextureSourceD3D11);
167 }
168
DataTextureSourceD3D11(SurfaceFormat aFormat,CompositorD3D11 * aCompositor,ID3D11Texture2D * aTexture)169 DataTextureSourceD3D11::DataTextureSourceD3D11(SurfaceFormat aFormat,
170 CompositorD3D11* aCompositor,
171 ID3D11Texture2D* aTexture)
172 : mCompositor(aCompositor)
173 , mFormat(aFormat)
174 , mFlags(TextureFlags::NO_FLAGS)
175 , mCurrentTile(0)
176 , mIsTiled(false)
177 , mIterating(false)
178 , mAllowTextureUploads(false)
179 {
180 MOZ_COUNT_CTOR(DataTextureSourceD3D11);
181
182 mTexture = aTexture;
183 D3D11_TEXTURE2D_DESC desc;
184 aTexture->GetDesc(&desc);
185
186 mSize = IntSize(desc.Width, desc.Height);
187 }
188
189
190
~DataTextureSourceD3D11()191 DataTextureSourceD3D11::~DataTextureSourceD3D11()
192 {
193 MOZ_COUNT_DTOR(DataTextureSourceD3D11);
194 }
195
196
197 template<typename T> // ID3D10Texture2D or ID3D11Texture2D
LockD3DTexture(T * aTexture)198 static bool LockD3DTexture(T* aTexture)
199 {
200 MOZ_ASSERT(aTexture);
201 RefPtr<IDXGIKeyedMutex> mutex;
202 aTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
203 // Textures created by the DXVA decoders don't have a mutex for synchronization
204 if (mutex) {
205 HRESULT hr = mutex->AcquireSync(0, 10000);
206 if (hr == WAIT_TIMEOUT) {
207 gfxDevCrash(LogReason::D3DLockTimeout) << "D3D lock mutex timeout";
208 } else if (hr == WAIT_ABANDONED) {
209 gfxCriticalNote << "GFX: D3D11 lock mutex abandoned";
210 }
211
212 if (FAILED(hr)) {
213 NS_WARNING("Failed to lock the texture");
214 return false;
215 }
216 }
217 return true;
218 }
219
220 template<typename T>
HasKeyedMutex(T * aTexture)221 static bool HasKeyedMutex(T* aTexture)
222 {
223 RefPtr<IDXGIKeyedMutex> mutex;
224 aTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
225 return !!mutex;
226 }
227
228 template<typename T> // ID3D10Texture2D or ID3D11Texture2D
UnlockD3DTexture(T * aTexture)229 static void UnlockD3DTexture(T* aTexture)
230 {
231 MOZ_ASSERT(aTexture);
232 RefPtr<IDXGIKeyedMutex> mutex;
233 aTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
234 if (mutex) {
235 HRESULT hr = mutex->ReleaseSync(0);
236 if (FAILED(hr)) {
237 NS_WARNING("Failed to unlock the texture");
238 }
239 }
240 }
241
DXGITextureData(gfx::IntSize aSize,gfx::SurfaceFormat aFormat,bool aNeedsClear,bool aNeedsClearWhite,bool aIsForOutOfBandContent)242 DXGITextureData::DXGITextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
243 bool aNeedsClear, bool aNeedsClearWhite,
244 bool aIsForOutOfBandContent)
245 : mSize(aSize)
246 , mFormat(aFormat)
247 , mNeedsClear(aNeedsClear)
248 , mNeedsClearWhite(aNeedsClearWhite)
249 , mHasSynchronization(false)
250 , mIsForOutOfBandContent(aIsForOutOfBandContent)
251 {}
252
D3D11TextureData(ID3D11Texture2D * aTexture,gfx::IntSize aSize,gfx::SurfaceFormat aFormat,bool aNeedsClear,bool aNeedsClearWhite,bool aIsForOutOfBandContent)253 D3D11TextureData::D3D11TextureData(ID3D11Texture2D* aTexture,
254 gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
255 bool aNeedsClear, bool aNeedsClearWhite,
256 bool aIsForOutOfBandContent)
257 : DXGITextureData(aSize, aFormat, aNeedsClear, aNeedsClearWhite, aIsForOutOfBandContent)
258 , mTexture(aTexture)
259 {
260 MOZ_ASSERT(aTexture);
261 mHasSynchronization = HasKeyedMutex(aTexture);
262 }
263
~D3D11TextureData()264 D3D11TextureData::~D3D11TextureData()
265 {
266 #ifdef DEBUG
267 // An Azure DrawTarget needs to be locked when it gets nullptr'ed as this is
268 // when it calls EndDraw. This EndDraw should not execute anything so it
269 // shouldn't -really- need the lock but the debug layer chokes on this.
270 if (mDrawTarget) {
271 Lock(OpenMode::OPEN_NONE);
272 mDrawTarget = nullptr;
273 Unlock();
274 }
275 #endif
276 }
277
278 bool
Lock(OpenMode aMode)279 D3D11TextureData::Lock(OpenMode aMode)
280 {
281 if (!LockD3DTexture(mTexture.get())) {
282 return false;
283 }
284
285 if (NS_IsMainThread() && !mIsForOutOfBandContent) {
286 if (!PrepareDrawTargetInLock(aMode)) {
287 Unlock();
288 return false;
289 }
290 }
291
292 return true;
293 }
294
295 bool
PrepareDrawTargetInLock(OpenMode aMode)296 DXGITextureData::PrepareDrawTargetInLock(OpenMode aMode)
297 {
298 // Make sure that successful write-lock means we will have a DrawTarget to
299 // write into.
300 if (!mDrawTarget && (aMode & OpenMode::OPEN_WRITE || mNeedsClear || mNeedsClearWhite)) {
301 mDrawTarget = BorrowDrawTarget();
302 if (!mDrawTarget) {
303 return false;
304 }
305 }
306
307 if (mNeedsClear) {
308 mDrawTarget->ClearRect(Rect(0, 0, mSize.width, mSize.height));
309 mNeedsClear = false;
310 }
311 if (mNeedsClearWhite) {
312 mDrawTarget->FillRect(Rect(0, 0, mSize.width, mSize.height), ColorPattern(Color(1.0, 1.0, 1.0, 1.0)));
313 mNeedsClearWhite = false;
314 }
315
316 return true;
317 }
318
319 void
Unlock()320 D3D11TextureData::Unlock()
321 {
322 UnlockD3DTexture(mTexture.get());
323 }
324
325
326 void
FillInfo(TextureData::Info & aInfo) const327 DXGITextureData::FillInfo(TextureData::Info& aInfo) const
328 {
329 aInfo.size = mSize;
330 aInfo.format = mFormat;
331 aInfo.supportsMoz2D = true;
332 aInfo.hasIntermediateBuffer = false;
333 aInfo.hasSynchronization = mHasSynchronization;
334 }
335
336 void
SyncWithObject(SyncObject * aSyncObject)337 D3D11TextureData::SyncWithObject(SyncObject* aSyncObject)
338 {
339 if (!aSyncObject || !NS_IsMainThread() || mIsForOutOfBandContent) {
340 // When off the main thread we sync using a keyed mutex per texture.
341 return;
342 }
343
344 MOZ_ASSERT(aSyncObject->GetSyncType() == SyncObject::SyncType::D3D11);
345 SyncObjectD3D11* sync = static_cast<SyncObjectD3D11*>(aSyncObject);
346 sync->RegisterTexture(mTexture);
347 }
348
349 bool
Serialize(SurfaceDescriptor & aOutDescriptor)350 DXGITextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
351 {
352 RefPtr<IDXGIResource> resource;
353 GetDXGIResource((IDXGIResource**)getter_AddRefs(resource));
354 if (!resource) {
355 return false;
356 }
357 HANDLE sharedHandle;
358 HRESULT hr = resource->GetSharedHandle(&sharedHandle);
359 if (FAILED(hr)) {
360 LOGD3D11("Error getting shared handle for texture.");
361 return false;
362 }
363
364 aOutDescriptor = SurfaceDescriptorD3D10((WindowsHandle)sharedHandle, mFormat, mSize);
365 return true;
366 }
367
368 DXGITextureData*
Create(IntSize aSize,SurfaceFormat aFormat,TextureAllocationFlags aFlags)369 DXGITextureData::Create(IntSize aSize, SurfaceFormat aFormat, TextureAllocationFlags aFlags)
370 {
371 if (aFormat == SurfaceFormat::A8) {
372 // Currently we don't support A8 surfaces. Fallback.
373 return nullptr;
374 }
375
376 return D3D11TextureData::Create(aSize, aFormat, aFlags);
377 }
378
379 DXGITextureData*
Create(IntSize aSize,SurfaceFormat aFormat,SourceSurface * aSurface,TextureAllocationFlags aFlags,ID3D11Device * aDevice)380 D3D11TextureData::Create(IntSize aSize, SurfaceFormat aFormat, SourceSurface* aSurface,
381 TextureAllocationFlags aFlags, ID3D11Device* aDevice)
382 {
383 // Just grab any device. We never use the immediate context, so the devices are fine
384 // to use from any thread.
385 RefPtr<ID3D11Device> device = aDevice;
386 if (!device) {
387 device = DeviceManagerDx::Get()->GetContentDevice();
388 if (!device) {
389 return nullptr;
390 }
391 }
392
393 CD3D11_TEXTURE2D_DESC newDesc(DXGI_FORMAT_B8G8R8A8_UNORM,
394 aSize.width, aSize.height, 1, 1,
395 D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE);
396
397 newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
398 if (!NS_IsMainThread() || !!(aFlags & ALLOC_FOR_OUT_OF_BAND_CONTENT)) {
399 // On the main thread we use the syncobject to handle synchronization.
400 if (!(aFlags & ALLOC_MANUAL_SYNCHRONIZATION)) {
401 newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
402 }
403 }
404
405 if (aSurface && newDesc.MiscFlags == D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX &&
406 !DeviceManagerDx::Get()->CanInitializeKeyedMutexTextures()) {
407 return nullptr;
408 }
409
410 D3D11_SUBRESOURCE_DATA uploadData;
411 D3D11_SUBRESOURCE_DATA* uploadDataPtr = nullptr;
412 RefPtr<DataSourceSurface> srcSurf;
413 if (aSurface) {
414 srcSurf = aSurface->GetDataSurface();
415
416 if (!srcSurf) {
417 gfxCriticalError() << "Failed to GetDataSurface in D3D11TextureData::Create";
418 return nullptr;
419 }
420
421 DataSourceSurface::MappedSurface sourceMap;
422 if (!srcSurf->Map(DataSourceSurface::READ, &sourceMap)) {
423 gfxCriticalError() << "Failed to map source surface for D3D11TextureData::Create";
424 return nullptr;
425 }
426
427 uploadData.pSysMem = sourceMap.mData;
428 uploadData.SysMemPitch = sourceMap.mStride;
429 uploadData.SysMemSlicePitch = 0; // unused
430
431 uploadDataPtr = &uploadData;
432 }
433
434 RefPtr<ID3D11Texture2D> texture11;
435 HRESULT hr = device->CreateTexture2D(&newDesc, uploadDataPtr, getter_AddRefs(texture11));
436 if (srcSurf) {
437 srcSurf->Unmap();
438 }
439 if (FAILED(hr)) {
440 gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(aSize)))
441 << "[D3D11] 2 CreateTexture2D failure " << aSize << " Code: " << gfx::hexa(hr);
442 return nullptr;
443 }
444
445 // If we created the texture with a keyed mutex, then we expect all operations
446 // on it to be synchronized using it. If we did an initial upload using aSurface
447 // then bizarely this isn't covered, so we insert a manual lock/unlock pair
448 // to force this.
449 if (aSurface && newDesc.MiscFlags == D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) {
450 if (!LockD3DTexture(texture11.get())) {
451 return nullptr;
452 }
453 UnlockD3DTexture(texture11.get());
454 }
455 texture11->SetPrivateDataInterface(sD3D11TextureUsage,
456 new TextureMemoryMeasurer(newDesc.Width * newDesc.Height * 4));
457 return new D3D11TextureData(texture11, aSize, aFormat,
458 aFlags & ALLOC_CLEAR_BUFFER,
459 aFlags & ALLOC_CLEAR_BUFFER_WHITE,
460 aFlags & ALLOC_FOR_OUT_OF_BAND_CONTENT);
461 }
462
463 DXGITextureData*
Create(IntSize aSize,SurfaceFormat aFormat,TextureAllocationFlags aFlags,ID3D11Device * aDevice)464 D3D11TextureData::Create(IntSize aSize, SurfaceFormat aFormat,
465 TextureAllocationFlags aFlags, ID3D11Device* aDevice)
466 {
467 return D3D11TextureData::Create(aSize, aFormat, nullptr, aFlags, aDevice);
468 }
469
470 DXGITextureData*
Create(SourceSurface * aSurface,TextureAllocationFlags aFlags,ID3D11Device * aDevice)471 D3D11TextureData::Create(SourceSurface* aSurface,
472 TextureAllocationFlags aFlags, ID3D11Device* aDevice)
473 {
474 if (aSurface->GetFormat() == SurfaceFormat::A8) {
475 // Currently we don't support A8 surfaces. Fallback.
476 return nullptr;
477 }
478
479 return D3D11TextureData::Create(aSurface->GetSize(), aSurface->GetFormat(),
480 aSurface, aFlags, aDevice);
481 }
482
483 void
Deallocate(LayersIPCChannel * aAllocator)484 D3D11TextureData::Deallocate(LayersIPCChannel* aAllocator)
485 {
486 mDrawTarget = nullptr;
487 mTexture = nullptr;
488 }
489
490 already_AddRefed<TextureClient>
CreateD3D11TextureClientWithDevice(IntSize aSize,SurfaceFormat aFormat,TextureFlags aTextureFlags,TextureAllocationFlags aAllocFlags,ID3D11Device * aDevice,LayersIPCChannel * aAllocator)491 CreateD3D11TextureClientWithDevice(IntSize aSize, SurfaceFormat aFormat,
492 TextureFlags aTextureFlags, TextureAllocationFlags aAllocFlags,
493 ID3D11Device* aDevice,
494 LayersIPCChannel* aAllocator)
495 {
496 TextureData* data = D3D11TextureData::Create(aSize, aFormat, aAllocFlags, aDevice);
497 if (!data) {
498 return nullptr;
499 }
500 return MakeAndAddRef<TextureClient>(data, aTextureFlags, aAllocator);
501 }
502
503 TextureData*
CreateSimilar(LayersIPCChannel * aAllocator,LayersBackend aLayersBackend,TextureFlags aFlags,TextureAllocationFlags aAllocFlags) const504 D3D11TextureData::CreateSimilar(LayersIPCChannel* aAllocator,
505 LayersBackend aLayersBackend,
506 TextureFlags aFlags,
507 TextureAllocationFlags aAllocFlags) const
508 {
509 return D3D11TextureData::Create(mSize, mFormat, aAllocFlags);
510 }
511
512 void
GetDXGIResource(IDXGIResource ** aOutResource)513 D3D11TextureData::GetDXGIResource(IDXGIResource** aOutResource)
514 {
515 mTexture->QueryInterface(aOutResource);
516 }
517
518 DXGIYCbCrTextureData*
Create(TextureFlags aFlags,IUnknown * aTextureY,IUnknown * aTextureCb,IUnknown * aTextureCr,HANDLE aHandleY,HANDLE aHandleCb,HANDLE aHandleCr,const gfx::IntSize & aSize,const gfx::IntSize & aSizeY,const gfx::IntSize & aSizeCbCr)519 DXGIYCbCrTextureData::Create(TextureFlags aFlags,
520 IUnknown* aTextureY,
521 IUnknown* aTextureCb,
522 IUnknown* aTextureCr,
523 HANDLE aHandleY,
524 HANDLE aHandleCb,
525 HANDLE aHandleCr,
526 const gfx::IntSize& aSize,
527 const gfx::IntSize& aSizeY,
528 const gfx::IntSize& aSizeCbCr)
529 {
530 if (!aHandleY || !aHandleCb || !aHandleCr ||
531 !aTextureY || !aTextureCb || !aTextureCr) {
532 return nullptr;
533 }
534
535 DXGIYCbCrTextureData* texture = new DXGIYCbCrTextureData();
536 texture->mHandles[0] = aHandleY;
537 texture->mHandles[1] = aHandleCb;
538 texture->mHandles[2] = aHandleCr;
539 texture->mHoldRefs[0] = aTextureY;
540 texture->mHoldRefs[1] = aTextureCb;
541 texture->mHoldRefs[2] = aTextureCr;
542 texture->mSize = aSize;
543 texture->mSizeY = aSizeY;
544 texture->mSizeCbCr = aSizeCbCr;
545
546 return texture;
547 }
548
549 DXGIYCbCrTextureData*
Create(TextureFlags aFlags,ID3D11Texture2D * aTextureY,ID3D11Texture2D * aTextureCb,ID3D11Texture2D * aTextureCr,const gfx::IntSize & aSize,const gfx::IntSize & aSizeY,const gfx::IntSize & aSizeCbCr)550 DXGIYCbCrTextureData::Create(TextureFlags aFlags,
551 ID3D11Texture2D* aTextureY,
552 ID3D11Texture2D* aTextureCb,
553 ID3D11Texture2D* aTextureCr,
554 const gfx::IntSize& aSize,
555 const gfx::IntSize& aSizeY,
556 const gfx::IntSize& aSizeCbCr)
557 {
558 if (!aTextureY || !aTextureCb || !aTextureCr) {
559 return nullptr;
560 }
561
562 aTextureY->SetPrivateDataInterface(sD3D11TextureUsage,
563 new TextureMemoryMeasurer(aSize.width * aSize.height));
564 aTextureCb->SetPrivateDataInterface(sD3D11TextureUsage,
565 new TextureMemoryMeasurer(aSizeCbCr.width * aSizeCbCr.height));
566 aTextureCr->SetPrivateDataInterface(sD3D11TextureUsage,
567 new TextureMemoryMeasurer(aSizeCbCr.width * aSizeCbCr.height));
568
569 RefPtr<IDXGIResource> resource;
570
571 aTextureY->QueryInterface((IDXGIResource**)getter_AddRefs(resource));
572
573 HANDLE handleY;
574 HRESULT hr = resource->GetSharedHandle(&handleY);
575 if (FAILED(hr)) {
576 return nullptr;
577 }
578
579 aTextureCb->QueryInterface((IDXGIResource**)getter_AddRefs(resource));
580
581 HANDLE handleCb;
582 hr = resource->GetSharedHandle(&handleCb);
583 if (FAILED(hr)) {
584 return nullptr;
585 }
586
587 aTextureCr->QueryInterface((IDXGIResource**)getter_AddRefs(resource));
588 HANDLE handleCr;
589 hr = resource->GetSharedHandle(&handleCr);
590 if (FAILED(hr)) {
591 return nullptr;
592 }
593
594 return DXGIYCbCrTextureData::Create(aFlags,
595 aTextureY, aTextureCb, aTextureCr,
596 handleY, handleCb, handleCr,
597 aSize, aSizeY, aSizeCbCr);
598 }
599
600 void
FillInfo(TextureData::Info & aInfo) const601 DXGIYCbCrTextureData::FillInfo(TextureData::Info& aInfo) const
602 {
603 aInfo.size = mSize;
604 aInfo.format = gfx::SurfaceFormat::YUV;
605 aInfo.supportsMoz2D = false;
606 aInfo.hasIntermediateBuffer = false;
607 aInfo.hasSynchronization = false;
608 }
609
610 bool
Serialize(SurfaceDescriptor & aOutDescriptor)611 DXGIYCbCrTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
612 {
613 aOutDescriptor = SurfaceDescriptorDXGIYCbCr(
614 (WindowsHandle)mHandles[0], (WindowsHandle)mHandles[1], (WindowsHandle)mHandles[2],
615 mSize, mSizeY, mSizeCbCr
616 );
617 return true;
618 }
619
620 void
Deallocate(LayersIPCChannel *)621 DXGIYCbCrTextureData::Deallocate(LayersIPCChannel*)
622 {
623 mHoldRefs[0] = nullptr;
624 mHoldRefs[1] = nullptr;
625 mHoldRefs[2] = nullptr;
626 }
627
628 already_AddRefed<TextureHost>
CreateTextureHostD3D11(const SurfaceDescriptor & aDesc,ISurfaceAllocator * aDeallocator,TextureFlags aFlags)629 CreateTextureHostD3D11(const SurfaceDescriptor& aDesc,
630 ISurfaceAllocator* aDeallocator,
631 TextureFlags aFlags)
632 {
633 RefPtr<TextureHost> result;
634 switch (aDesc.type()) {
635 case SurfaceDescriptor::TSurfaceDescriptorD3D10: {
636 result = new DXGITextureHostD3D11(aFlags,
637 aDesc.get_SurfaceDescriptorD3D10());
638 break;
639 }
640 case SurfaceDescriptor::TSurfaceDescriptorDXGIYCbCr: {
641 result = new DXGIYCbCrTextureHostD3D11(aFlags,
642 aDesc.get_SurfaceDescriptorDXGIYCbCr());
643 break;
644 }
645 default: {
646 MOZ_ASSERT_UNREACHABLE("Unsupported SurfaceDescriptor type");
647 }
648 }
649 return result.forget();
650 }
651
652
653 already_AddRefed<DrawTarget>
BorrowDrawTarget()654 D3D11TextureData::BorrowDrawTarget()
655 {
656 MOZ_ASSERT(NS_IsMainThread());
657
658 if (!mDrawTarget && mTexture) {
659 // This may return a null DrawTarget
660 mDrawTarget = Factory::CreateDrawTargetForD3D11Texture(mTexture, mFormat);
661 if (!mDrawTarget) {
662 gfxCriticalNote << "Could not borrow DrawTarget (D3D11) " << (int)mFormat;
663 }
664 }
665
666 RefPtr<DrawTarget> result = mDrawTarget;
667 return result.forget();
668 }
669
670 bool
UpdateFromSurface(gfx::SourceSurface * aSurface)671 D3D11TextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
672 {
673 // Supporting texture updates after creation requires an ID3D11DeviceContext and those
674 // aren't threadsafe. We'd need to either lock, or have a device for whatever thread
675 // this runs on and we're trying to avoid extra devices (bug 1284672).
676 MOZ_ASSERT(false, "UpdateFromSurface not supported for D3D11! Use CreateFromSurface instead");
677 return false;
678 }
679
DXGITextureHostD3D11(TextureFlags aFlags,const SurfaceDescriptorD3D10 & aDescriptor)680 DXGITextureHostD3D11::DXGITextureHostD3D11(TextureFlags aFlags,
681 const SurfaceDescriptorD3D10& aDescriptor)
682 : TextureHost(aFlags)
683 , mSize(aDescriptor.size())
684 , mHandle(aDescriptor.handle())
685 , mFormat(aDescriptor.format())
686 , mIsLocked(false)
687 {
688 }
689
690 bool
OpenSharedHandle()691 DXGITextureHostD3D11::OpenSharedHandle()
692 {
693 if (!GetDevice()) {
694 return false;
695 }
696
697 HRESULT hr = GetDevice()->OpenSharedResource((HANDLE)mHandle,
698 __uuidof(ID3D11Texture2D),
699 (void**)(ID3D11Texture2D**)getter_AddRefs(mTexture));
700 if (FAILED(hr)) {
701 NS_WARNING("Failed to open shared texture");
702 return false;
703 }
704
705 D3D11_TEXTURE2D_DESC desc;
706 mTexture->GetDesc(&desc);
707 mSize = IntSize(desc.Width, desc.Height);
708 return true;
709 }
710
711 RefPtr<ID3D11Device>
GetDevice()712 DXGITextureHostD3D11::GetDevice()
713 {
714 if (mFlags & TextureFlags::INVALID_COMPOSITOR) {
715 return nullptr;
716 }
717
718 return DeviceManagerDx::Get()->GetCompositorDevice();
719 }
720
AssertD3D11Compositor(Compositor * aCompositor)721 static CompositorD3D11* AssertD3D11Compositor(Compositor* aCompositor)
722 {
723 CompositorD3D11* compositor = aCompositor ? aCompositor->AsCompositorD3D11()
724 : nullptr;
725 if (!compositor) {
726 gfxCriticalNote << "[D3D11] Attempt to set an incompatible compositor";
727 }
728 return compositor;
729 }
730
731 void
SetCompositor(Compositor * aCompositor)732 DXGITextureHostD3D11::SetCompositor(Compositor* aCompositor)
733 {
734 CompositorD3D11* d3dCompositor = AssertD3D11Compositor(aCompositor);
735 if (!d3dCompositor) {
736 mCompositor = nullptr;
737 mTextureSource = nullptr;
738 return;
739 }
740 mCompositor = d3dCompositor;
741 if (mTextureSource) {
742 mTextureSource->SetCompositor(aCompositor);
743 }
744 }
745
746 Compositor*
GetCompositor()747 DXGITextureHostD3D11::GetCompositor()
748 {
749 return mCompositor;
750 }
751
752 bool
Lock()753 DXGITextureHostD3D11::Lock()
754 {
755 if (!mCompositor) {
756 // Make an early return here if we call SetCompositor() with an incompatible
757 // compositor. This check tries to prevent the problem where we use that
758 // incompatible compositor to compose this texture.
759 return false;
760 }
761
762 return LockInternal();
763 }
764
765 bool
LockWithoutCompositor()766 DXGITextureHostD3D11::LockWithoutCompositor()
767 {
768 // Unlike the normal Lock() function, this function may be called when
769 // mCompositor is nullptr such as during WebVR frame submission. So, there is
770 // no 'mCompositor' checking here.
771 return LockInternal();
772 }
773
774 void
Unlock()775 DXGITextureHostD3D11::Unlock()
776 {
777 UnlockInternal();
778 }
779
780 void
UnlockWithoutCompositor()781 DXGITextureHostD3D11::UnlockWithoutCompositor()
782 {
783 UnlockInternal();
784 }
785
786 bool
LockInternal()787 DXGITextureHostD3D11::LockInternal()
788 {
789 if (!GetDevice()) {
790 NS_WARNING("trying to lock a TextureHost without a D3D device");
791 return false;
792 }
793
794 if (!mTextureSource) {
795 if (!mTexture && !OpenSharedHandle()) {
796 DeviceManagerDx::Get()->ForceDeviceReset(ForcedDeviceResetReason::OPENSHAREDHANDLE);
797 return false;
798 }
799
800 mTextureSource = new DataTextureSourceD3D11(mFormat, mCompositor, mTexture);
801 }
802
803 mIsLocked = LockD3DTexture(mTextureSource->GetD3D11Texture());
804
805 return mIsLocked;
806 }
807
808 void
UnlockInternal()809 DXGITextureHostD3D11::UnlockInternal()
810 {
811 UnlockD3DTexture(mTextureSource->GetD3D11Texture());
812 }
813
814 bool
BindTextureSource(CompositableTextureSourceRef & aTexture)815 DXGITextureHostD3D11::BindTextureSource(CompositableTextureSourceRef& aTexture)
816 {
817 MOZ_ASSERT(mIsLocked);
818 // If Lock was successful we must have a valid TextureSource.
819 MOZ_ASSERT(mTextureSource);
820 aTexture = mTextureSource;
821 return !!aTexture;
822 }
823
DXGIYCbCrTextureHostD3D11(TextureFlags aFlags,const SurfaceDescriptorDXGIYCbCr & aDescriptor)824 DXGIYCbCrTextureHostD3D11::DXGIYCbCrTextureHostD3D11(TextureFlags aFlags,
825 const SurfaceDescriptorDXGIYCbCr& aDescriptor)
826 : TextureHost(aFlags)
827 , mSize(aDescriptor.size())
828 , mIsLocked(false)
829 {
830 mHandles[0] = aDescriptor.handleY();
831 mHandles[1] = aDescriptor.handleCb();
832 mHandles[2] = aDescriptor.handleCr();
833 }
834
835 bool
OpenSharedHandle()836 DXGIYCbCrTextureHostD3D11::OpenSharedHandle()
837 {
838 RefPtr<ID3D11Device> device = GetDevice();
839 if (!device) {
840 return false;
841 }
842
843 RefPtr<ID3D11Texture2D> textures[3];
844
845 HRESULT hr = device->OpenSharedResource((HANDLE)mHandles[0],
846 __uuidof(ID3D11Texture2D),
847 (void**)(ID3D11Texture2D**)getter_AddRefs(textures[0]));
848 if (FAILED(hr)) {
849 NS_WARNING("Failed to open shared texture for Y Plane");
850 return false;
851 }
852
853 hr = device->OpenSharedResource((HANDLE)mHandles[1],
854 __uuidof(ID3D11Texture2D),
855 (void**)(ID3D11Texture2D**)getter_AddRefs(textures[1]));
856 if (FAILED(hr)) {
857 NS_WARNING("Failed to open shared texture for Cb Plane");
858 return false;
859 }
860
861 hr = device->OpenSharedResource((HANDLE)mHandles[2],
862 __uuidof(ID3D11Texture2D),
863 (void**)(ID3D11Texture2D**)getter_AddRefs(textures[2]));
864 if (FAILED(hr)) {
865 NS_WARNING("Failed to open shared texture for Cr Plane");
866 return false;
867 }
868
869 mTextures[0] = textures[0].forget();
870 mTextures[1] = textures[1].forget();
871 mTextures[2] = textures[2].forget();
872
873 return true;
874 }
875
876 RefPtr<ID3D11Device>
GetDevice()877 DXGIYCbCrTextureHostD3D11::GetDevice()
878 {
879 if (mFlags & TextureFlags::INVALID_COMPOSITOR) {
880 return nullptr;
881 }
882
883 return DeviceManagerDx::Get()->GetCompositorDevice();
884 }
885
886 void
SetCompositor(Compositor * aCompositor)887 DXGIYCbCrTextureHostD3D11::SetCompositor(Compositor* aCompositor)
888 {
889 mCompositor = AssertD3D11Compositor(aCompositor);
890 if (!mCompositor) {
891 mTextureSources[0] = nullptr;
892 mTextureSources[1] = nullptr;
893 mTextureSources[2] = nullptr;
894 return;
895 }
896
897 if (mTextureSources[0]) {
898 mTextureSources[0]->SetCompositor(aCompositor);
899 }
900 }
901
902 Compositor*
GetCompositor()903 DXGIYCbCrTextureHostD3D11::GetCompositor()
904 {
905 return mCompositor;
906 }
907
908 bool
Lock()909 DXGIYCbCrTextureHostD3D11::Lock()
910 {
911 if (!mCompositor) {
912 NS_WARNING("no suitable compositor");
913 return false;
914 }
915
916 if (!GetDevice()) {
917 NS_WARNING("trying to lock a TextureHost without a D3D device");
918 return false;
919 }
920 if (!mTextureSources[0]) {
921 if (!mTextures[0] && !OpenSharedHandle()) {
922 return false;
923 }
924
925 MOZ_ASSERT(mTextures[1] && mTextures[2]);
926
927 mTextureSources[0] = new DataTextureSourceD3D11(SurfaceFormat::A8, mCompositor, mTextures[0]);
928 mTextureSources[1] = new DataTextureSourceD3D11(SurfaceFormat::A8, mCompositor, mTextures[1]);
929 mTextureSources[2] = new DataTextureSourceD3D11(SurfaceFormat::A8, mCompositor, mTextures[2]);
930 mTextureSources[0]->SetNextSibling(mTextureSources[1]);
931 mTextureSources[1]->SetNextSibling(mTextureSources[2]);
932 }
933
934 mIsLocked = LockD3DTexture(mTextureSources[0]->GetD3D11Texture()) &&
935 LockD3DTexture(mTextureSources[1]->GetD3D11Texture()) &&
936 LockD3DTexture(mTextureSources[2]->GetD3D11Texture());
937
938 return mIsLocked;
939 }
940
941 void
Unlock()942 DXGIYCbCrTextureHostD3D11::Unlock()
943 {
944 MOZ_ASSERT(mIsLocked);
945 UnlockD3DTexture(mTextureSources[0]->GetD3D11Texture());
946 UnlockD3DTexture(mTextureSources[1]->GetD3D11Texture());
947 UnlockD3DTexture(mTextureSources[2]->GetD3D11Texture());
948 mIsLocked = false;
949 }
950
951 bool
BindTextureSource(CompositableTextureSourceRef & aTexture)952 DXGIYCbCrTextureHostD3D11::BindTextureSource(CompositableTextureSourceRef& aTexture)
953 {
954 MOZ_ASSERT(mIsLocked);
955 // If Lock was successful we must have a valid TextureSource.
956 MOZ_ASSERT(mTextureSources[0] && mTextureSources[1] && mTextureSources[2]);
957 aTexture = mTextureSources[0].get();
958 return !!aTexture;
959 }
960
961 bool
Update(DataSourceSurface * aSurface,nsIntRegion * aDestRegion,IntPoint * aSrcOffset)962 DataTextureSourceD3D11::Update(DataSourceSurface* aSurface,
963 nsIntRegion* aDestRegion,
964 IntPoint* aSrcOffset)
965 {
966 // Incremental update with a source offset is only used on Mac so it is not
967 // clear that we ever will need to support it for D3D.
968 MOZ_ASSERT(!aSrcOffset);
969 MOZ_ASSERT(aSurface);
970
971 MOZ_ASSERT(mAllowTextureUploads);
972 if (!mAllowTextureUploads) {
973 return false;
974 }
975
976 HRESULT hr;
977
978 if (!mCompositor || !mCompositor->GetDevice()) {
979 return false;
980 }
981
982 uint32_t bpp = BytesPerPixel(aSurface->GetFormat());
983 DXGI_FORMAT dxgiFormat = SurfaceFormatToDXGIFormat(aSurface->GetFormat());
984
985 mSize = aSurface->GetSize();
986 mFormat = aSurface->GetFormat();
987
988 CD3D11_TEXTURE2D_DESC desc(dxgiFormat, mSize.width, mSize.height, 1, 1);
989
990 int32_t maxSize = mCompositor->GetMaxTextureSize();
991 if ((mSize.width <= maxSize && mSize.height <= maxSize) ||
992 (mFlags & TextureFlags::DISALLOW_BIGIMAGE)) {
993
994 if (mTexture) {
995 D3D11_TEXTURE2D_DESC currentDesc;
996 mTexture->GetDesc(¤tDesc);
997
998 // Make sure there's no size mismatch, if there is, recreate.
999 if (currentDesc.Width != mSize.width || currentDesc.Height != mSize.height ||
1000 currentDesc.Format != dxgiFormat) {
1001 mTexture = nullptr;
1002 // Make sure we upload the whole surface.
1003 aDestRegion = nullptr;
1004 }
1005 }
1006
1007 nsIntRegion *regionToUpdate = aDestRegion;
1008 if (!mTexture) {
1009 hr = mCompositor->GetDevice()->CreateTexture2D(&desc, nullptr, getter_AddRefs(mTexture));
1010 mIsTiled = false;
1011 if (FAILED(hr) || !mTexture) {
1012 Reset();
1013 return false;
1014 }
1015
1016 if (mFlags & TextureFlags::COMPONENT_ALPHA) {
1017 regionToUpdate = nullptr;
1018 }
1019 }
1020
1021 DataSourceSurface::MappedSurface map;
1022 if (!aSurface->Map(DataSourceSurface::MapType::READ, &map)) {
1023 gfxCriticalError() << "Failed to map surface.";
1024 Reset();
1025 return false;
1026 }
1027
1028 if (regionToUpdate) {
1029 for (auto iter = regionToUpdate->RectIter(); !iter.Done(); iter.Next()) {
1030 const IntRect& rect = iter.Get();
1031 D3D11_BOX box;
1032 box.front = 0;
1033 box.back = 1;
1034 box.left = rect.x;
1035 box.top = rect.y;
1036 box.right = rect.XMost();
1037 box.bottom = rect.YMost();
1038
1039 void* data = map.mData + map.mStride * rect.y + BytesPerPixel(aSurface->GetFormat()) * rect.x;
1040
1041 mCompositor->GetDC()->UpdateSubresource(mTexture, 0, &box, data, map.mStride, map.mStride * rect.height);
1042 }
1043 } else {
1044 mCompositor->GetDC()->UpdateSubresource(mTexture, 0, nullptr, aSurface->GetData(),
1045 aSurface->Stride(), aSurface->Stride() * mSize.height);
1046 }
1047
1048 aSurface->Unmap();
1049 } else {
1050 mIsTiled = true;
1051 uint32_t tileCount = GetRequiredTilesD3D11(mSize.width, maxSize) *
1052 GetRequiredTilesD3D11(mSize.height, maxSize);
1053
1054 mTileTextures.resize(tileCount);
1055 mTileSRVs.resize(tileCount);
1056 mTexture = nullptr;
1057
1058 for (uint32_t i = 0; i < tileCount; i++) {
1059 IntRect tileRect = GetTileRect(i);
1060
1061 desc.Width = tileRect.width;
1062 desc.Height = tileRect.height;
1063 desc.Usage = D3D11_USAGE_IMMUTABLE;
1064
1065 D3D11_SUBRESOURCE_DATA initData;
1066 initData.pSysMem = aSurface->GetData() +
1067 tileRect.y * aSurface->Stride() +
1068 tileRect.x * bpp;
1069 initData.SysMemPitch = aSurface->Stride();
1070
1071 hr = mCompositor->GetDevice()->CreateTexture2D(&desc, &initData, getter_AddRefs(mTileTextures[i]));
1072 if (FAILED(hr) || !mTileTextures[i]) {
1073 Reset();
1074 return false;
1075 }
1076 }
1077 }
1078 return true;
1079 }
1080
1081 ID3D11Texture2D*
GetD3D11Texture() const1082 DataTextureSourceD3D11::GetD3D11Texture() const
1083 {
1084 return mIterating ? mTileTextures[mCurrentTile]
1085 : mTexture;
1086 }
1087
1088 ID3D11ShaderResourceView*
GetShaderResourceView()1089 DataTextureSourceD3D11::GetShaderResourceView()
1090 {
1091 if (mIterating) {
1092 if (!mTileSRVs[mCurrentTile]) {
1093 if (!mTileTextures[mCurrentTile]) {
1094 return nullptr;
1095 }
1096
1097 RefPtr<ID3D11Device> device;
1098 mTileTextures[mCurrentTile]->GetDevice(getter_AddRefs(device));
1099 HRESULT hr = device->CreateShaderResourceView(mTileTextures[mCurrentTile], nullptr, getter_AddRefs(mTileSRVs[mCurrentTile]));
1100 if (FAILED(hr)) {
1101 gfxCriticalNote << "[D3D11] DataTextureSourceD3D11:GetShaderResourceView CreateSRV failure " << gfx::hexa(hr);
1102 return nullptr;
1103 }
1104 }
1105 return mTileSRVs[mCurrentTile];
1106 }
1107
1108 return TextureSourceD3D11::GetShaderResourceView();
1109 }
1110
1111 void
Reset()1112 DataTextureSourceD3D11::Reset()
1113 {
1114 mTexture = nullptr;
1115 mTileSRVs.resize(0);
1116 mTileTextures.resize(0);
1117 mIsTiled = false;
1118 mSize.width = 0;
1119 mSize.height = 0;
1120 }
1121
1122 IntRect
GetTileRect(uint32_t aIndex) const1123 DataTextureSourceD3D11::GetTileRect(uint32_t aIndex) const
1124 {
1125 return GetTileRectD3D11(aIndex, mSize, mCompositor->GetMaxTextureSize());
1126 }
1127
1128 IntRect
GetTileRect()1129 DataTextureSourceD3D11::GetTileRect()
1130 {
1131 IntRect rect = GetTileRect(mCurrentTile);
1132 return IntRect(rect.x, rect.y, rect.width, rect.height);
1133 }
1134
1135 void
SetCompositor(Compositor * aCompositor)1136 DataTextureSourceD3D11::SetCompositor(Compositor* aCompositor)
1137 {
1138 CompositorD3D11* d3dCompositor = AssertD3D11Compositor(aCompositor);
1139 if (!d3dCompositor) {
1140 return;
1141 }
1142 mCompositor = d3dCompositor;
1143 if (mNextSibling) {
1144 mNextSibling->SetCompositor(aCompositor);
1145 }
1146 }
1147
CompositingRenderTargetD3D11(ID3D11Texture2D * aTexture,const gfx::IntPoint & aOrigin,DXGI_FORMAT aFormatOverride)1148 CompositingRenderTargetD3D11::CompositingRenderTargetD3D11(ID3D11Texture2D* aTexture,
1149 const gfx::IntPoint& aOrigin,
1150 DXGI_FORMAT aFormatOverride)
1151 : CompositingRenderTarget(aOrigin)
1152 {
1153 MOZ_ASSERT(aTexture);
1154
1155 mTexture = aTexture;
1156
1157 RefPtr<ID3D11Device> device;
1158 mTexture->GetDevice(getter_AddRefs(device));
1159
1160 mFormatOverride = aFormatOverride;
1161
1162 // If we happen to have a typeless underlying DXGI surface, we need to be explicit
1163 // about the format here. (Such a surface could come from an external source, such
1164 // as the Oculus compositor)
1165 CD3D11_RENDER_TARGET_VIEW_DESC rtvDesc(D3D11_RTV_DIMENSION_TEXTURE2D, mFormatOverride);
1166 D3D11_RENDER_TARGET_VIEW_DESC *desc = aFormatOverride == DXGI_FORMAT_UNKNOWN ? nullptr : &rtvDesc;
1167
1168 HRESULT hr = device->CreateRenderTargetView(mTexture, desc, getter_AddRefs(mRTView));
1169
1170 if (FAILED(hr)) {
1171 LOGD3D11("Failed to create RenderTargetView.");
1172 }
1173 }
1174
1175 void
BindRenderTarget(ID3D11DeviceContext * aContext)1176 CompositingRenderTargetD3D11::BindRenderTarget(ID3D11DeviceContext* aContext)
1177 {
1178 if (mClearOnBind) {
1179 FLOAT clear[] = { 0, 0, 0, 0 };
1180 aContext->ClearRenderTargetView(mRTView, clear);
1181 mClearOnBind = false;
1182 }
1183 ID3D11RenderTargetView* view = mRTView;
1184 aContext->OMSetRenderTargets(1, &view, nullptr);
1185 }
1186
1187 IntSize
GetSize() const1188 CompositingRenderTargetD3D11::GetSize() const
1189 {
1190 return TextureSourceD3D11::GetSize();
1191 }
1192
SyncObjectD3D11(SyncHandle aHandle)1193 SyncObjectD3D11::SyncObjectD3D11(SyncHandle aHandle)
1194 {
1195 MOZ_ASSERT(aHandle);
1196 mD3D11Device = DeviceManagerDx::Get()->GetContentDevice();
1197 mHandle = aHandle;
1198 }
1199
1200 void
RegisterTexture(ID3D11Texture2D * aTexture)1201 SyncObjectD3D11::RegisterTexture(ID3D11Texture2D* aTexture)
1202 {
1203 mD3D11SyncedTextures.push_back(aTexture);
1204 }
1205
1206 bool
IsSyncObjectValid()1207 SyncObjectD3D11::IsSyncObjectValid()
1208 {
1209 RefPtr<ID3D11Device> dev = DeviceManagerDx::Get()->GetContentDevice();
1210 if (!dev || (dev != mD3D11Device)) {
1211 return false;
1212 }
1213 return true;
1214 }
1215
1216 void
FinalizeFrame()1217 SyncObjectD3D11::FinalizeFrame()
1218 {
1219 HRESULT hr;
1220
1221 if (!mD3D11Texture && mD3D11SyncedTextures.size()) {
1222 RefPtr<ID3D11Device> device = DeviceManagerDx::Get()->GetContentDevice();
1223
1224 hr = device->OpenSharedResource(mHandle, __uuidof(ID3D11Texture2D), (void**)(ID3D11Texture2D**)getter_AddRefs(mD3D11Texture));
1225
1226 if (FAILED(hr) || !mD3D11Texture) {
1227 gfxCriticalError() << "Failed to D3D11 OpenSharedResource for frame finalization: " << hexa(hr);
1228
1229 if (DeviceManagerDx::Get()->HasDeviceReset()) {
1230 return;
1231 }
1232
1233 gfxDevCrash(LogReason::D3D11FinalizeFrame) << "Without device reset: " << hexa(hr);
1234 }
1235
1236 // test QI
1237 RefPtr<IDXGIKeyedMutex> mutex;
1238 hr = mD3D11Texture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
1239
1240 if (FAILED(hr) || !mutex) {
1241 // Leave both the critical error and MOZ_CRASH for now; the critical error lets
1242 // us "save" the hr value. We will probably eventuall replace this with gfxDevCrash.
1243 gfxCriticalError() << "Failed to get KeyedMutex (2): " << hexa(hr);
1244 MOZ_CRASH("GFX: Cannot get D3D11 KeyedMutex");
1245 }
1246 }
1247
1248 if (mD3D11SyncedTextures.size()) {
1249 RefPtr<IDXGIKeyedMutex> mutex;
1250 hr = mD3D11Texture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
1251 {
1252 AutoTextureLock lock(mutex, hr, 20000);
1253
1254 if (hr == WAIT_TIMEOUT) {
1255 if (DeviceManagerDx::Get()->HasDeviceReset()) {
1256 gfxWarning() << "AcquireSync timed out because of device reset.";
1257 return;
1258 }
1259 gfxDevCrash(LogReason::D3D11SyncLock) << "Timeout on the D3D11 sync lock";
1260 }
1261
1262 D3D11_BOX box;
1263 box.front = box.top = box.left = 0;
1264 box.back = box.bottom = box.right = 1;
1265
1266 RefPtr<ID3D11Device> dev = DeviceManagerDx::Get()->GetContentDevice();
1267 if (!dev) {
1268 if (DeviceManagerDx::Get()->HasDeviceReset()) {
1269 return;
1270 }
1271 MOZ_CRASH("GFX: Invalid D3D11 content device");
1272 }
1273
1274 RefPtr<ID3D11DeviceContext> ctx;
1275 dev->GetImmediateContext(getter_AddRefs(ctx));
1276
1277 for (auto iter = mD3D11SyncedTextures.begin(); iter != mD3D11SyncedTextures.end(); iter++) {
1278 ctx->CopySubresourceRegion(mD3D11Texture, 0, 0, 0, 0, *iter, 0, &box);
1279 }
1280 }
1281
1282 mD3D11SyncedTextures.clear();
1283 }
1284 }
1285
1286 }
1287 }
1288