TextureClient* IMFYCbCrImage::GetTextureClient(CompositableClient* aClient) { if (mTextureClient) { return mTextureClient; } RefPtr<ID3D11Device> device; gfxWindowsPlatform::GetPlatform()->GetD3D11ImageBridgeDevice(&device); LayersBackend backend = aClient->GetForwarder()->GetCompositorBackendType(); if (!device || backend != LayersBackend::LAYERS_D3D11) { if (backend == LayersBackend::LAYERS_D3D9 || backend == LayersBackend::LAYERS_D3D11) { return GetD3D9TextureClient(aClient); } return nullptr; } RefPtr<ID3D11DeviceContext> ctx; device->GetImmediateContext(getter_AddRefs(ctx)); CD3D11_TEXTURE2D_DESC newDesc(DXGI_FORMAT_R8_UNORM, mData.mYSize.width, mData.mYSize.height, 1, 1); newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; RefPtr<ID3D11Texture2D> textureY; HRESULT hr = device->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(textureY)); NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr); newDesc.Width = mData.mCbCrSize.width; newDesc.Height = mData.mCbCrSize.height; RefPtr<ID3D11Texture2D> textureCb; hr = device->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(textureCb)); NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr); RefPtr<ID3D11Texture2D> textureCr; hr = device->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(textureCr)); NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr); { AutoLockTexture lockY(textureY); AutoLockTexture lockCb(textureCb); AutoLockTexture lockCr(textureCr); ctx->UpdateSubresource(textureY, 0, nullptr, mData.mYChannel, mData.mYStride, mData.mYStride * mData.mYSize.height); ctx->UpdateSubresource(textureCb, 0, nullptr, mData.mCbChannel, mData.mCbCrStride, mData.mCbCrStride * mData.mCbCrSize.height); ctx->UpdateSubresource(textureCr, 0, nullptr, mData.mCrChannel, mData.mCbCrStride, mData.mCbCrStride * mData.mCbCrSize.height); } mTextureClient = TextureClient::CreateWithData( DXGIYCbCrTextureData::Create(aClient->GetForwarder(), TextureFlags::DEFAULT, textureY, textureCb, textureCr, GetSize(), mData.mYSize, mData.mCbCrSize), TextureFlags::DEFAULT, aClient->GetForwarder() ); return mTextureClient; }
TextureClient* IMFYCbCrImage::GetTextureClient(CompositableClient* aClient) { ID3D11Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D11ImageBridgeDevice(); if (!device || aClient->GetForwarder()->GetCompositorBackendType() != LayersBackend::LAYERS_D3D11) { IDirect3DDevice9* d3d9device = gfxWindowsPlatform::GetPlatform()->GetD3D9Device(); if (d3d9device && aClient->GetForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_D3D9) { return GetD3D9TextureClient(aClient); } return nullptr; } if (mTextureClient) { return mTextureClient; } RefPtr<ID3D11DeviceContext> ctx; device->GetImmediateContext(byRef(ctx)); CD3D11_TEXTURE2D_DESC newDesc(DXGI_FORMAT_A8_UNORM, mData.mYSize.width, mData.mYSize.height, 1, 1); newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; RefPtr<ID3D11Texture2D> textureY; HRESULT hr = device->CreateTexture2D(&newDesc, nullptr, byRef(textureY)); NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr); newDesc.Width = mData.mCbCrSize.width; newDesc.Height = mData.mCbCrSize.height; RefPtr<ID3D11Texture2D> textureCb; hr = device->CreateTexture2D(&newDesc, nullptr, byRef(textureCb)); NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr); RefPtr<ID3D11Texture2D> textureCr; hr = device->CreateTexture2D(&newDesc, nullptr, byRef(textureCr)); NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr); { AutoLockTexture lockY(textureY); AutoLockTexture lockCb(textureCb); AutoLockTexture lockCr(textureCr); ctx->UpdateSubresource(textureY, 0, nullptr, mData.mYChannel, mData.mYStride, mData.mYStride * mData.mYSize.height); ctx->UpdateSubresource(textureCb, 0, nullptr, mData.mCbChannel, mData.mCbCrStride, mData.mCbCrStride * mData.mCbCrSize.height); ctx->UpdateSubresource(textureCr, 0, nullptr, mData.mCrChannel, mData.mCbCrStride, mData.mCbCrStride * mData.mCbCrSize.height); } RefPtr<IDXGIResource> resource; HANDLE shareHandleY; textureY->QueryInterface((IDXGIResource**)byRef(resource)); hr = resource->GetSharedHandle(&shareHandleY); HANDLE shareHandleCb; textureCb->QueryInterface((IDXGIResource**)byRef(resource)); hr = resource->GetSharedHandle(&shareHandleCb); HANDLE shareHandleCr; textureCr->QueryInterface((IDXGIResource**)byRef(resource)); hr = resource->GetSharedHandle(&shareHandleCr); mTextureClient = DXGIYCbCrTextureClient::Create(aClient->GetForwarder(), TextureFlags::DEFAULT, textureY, textureCb, textureCr, shareHandleY, shareHandleCb, shareHandleCr, GetSize(), mData.mYSize, mData.mCbCrSize); return mTextureClient; }
TextureClient* IMFYCbCrImage::GetTextureClient(KnowsCompositor* aForwarder) { if (mTextureClient) { return mTextureClient; } RefPtr<ID3D11Device> device = gfx::DeviceManagerDx::Get()->GetContentDevice(); if (!device) { device = gfx::DeviceManagerDx::Get()->GetCompositorDevice(); } LayersBackend backend = aForwarder->GetCompositorBackendType(); if (!device || backend != LayersBackend::LAYERS_D3D11) { if (backend == LayersBackend::LAYERS_D3D9 || backend == LayersBackend::LAYERS_D3D11) { return GetD3D9TextureClient(aForwarder); } return nullptr; } if (!gfx::DeviceManagerDx::Get()->CanInitializeKeyedMutexTextures()) { return nullptr; } if (mData.mYStride < 0 || mData.mCbCrStride < 0) { // D3D11 only supports unsigned stride values. return nullptr; } CD3D11_TEXTURE2D_DESC newDesc(DXGI_FORMAT_R8_UNORM, mData.mYSize.width, mData.mYSize.height, 1, 1); if (device == gfx::DeviceManagerDx::Get()->GetCompositorDevice()) { newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; } else { newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; } RefPtr<ID3D11Texture2D> textureY; D3D11_SUBRESOURCE_DATA yData = { mData.mYChannel, (UINT)mData.mYStride, 0 }; HRESULT hr = device->CreateTexture2D(&newDesc, &yData, getter_AddRefs(textureY)); NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr); newDesc.Width = mData.mCbCrSize.width; newDesc.Height = mData.mCbCrSize.height; RefPtr<ID3D11Texture2D> textureCb; D3D11_SUBRESOURCE_DATA cbData = { mData.mCbChannel, (UINT)mData.mCbCrStride, 0 }; hr = device->CreateTexture2D(&newDesc, &cbData, getter_AddRefs(textureCb)); NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr); RefPtr<ID3D11Texture2D> textureCr; D3D11_SUBRESOURCE_DATA crData = { mData.mCrChannel, (UINT)mData.mCbCrStride, 0 }; hr = device->CreateTexture2D(&newDesc, &crData, getter_AddRefs(textureCr)); NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr); // Even though the textures we created are meant to be protected by a keyed mutex, // it appears that D3D doesn't include the initial memory upload within this // synchronization. Add an empty lock/unlock pair since that appears to // be sufficient to make sure we synchronize. { AutoLockTexture lockCr(textureCr); } mTextureClient = TextureClient::CreateWithData( DXGIYCbCrTextureData::Create(TextureFlags::DEFAULT, textureY, textureCb, textureCr, GetSize(), mData.mYSize, mData.mCbCrSize), TextureFlags::DEFAULT, aForwarder->GetTextureForwarder() ); return mTextureClient; }