Backed out 3 changesets (bug 1889130) for causing xpcshell failures in test_dooh...
[gecko.git] / gfx / layers / D3D11YCbCrImage.cpp
blob09549d251edf6889ba6ff374af4ba1d201ca9395
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 "D3D11YCbCrImage.h"
9 #include "YCbCrUtils.h"
10 #include "gfx2DGlue.h"
11 #include "mozilla/gfx/DeviceManagerDx.h"
12 #include "mozilla/gfx/gfxVars.h"
13 #include "mozilla/layers/CompositableClient.h"
14 #include "mozilla/layers/CompositableForwarder.h"
15 #include "mozilla/layers/TextureD3D11.h"
17 using namespace mozilla::gfx;
19 namespace mozilla {
20 namespace layers {
22 class AutoCheckLockD3D11Texture final {
23 public:
24 explicit AutoCheckLockD3D11Texture(ID3D11Texture2D* aTexture)
25 : mIsLocked(false) {
26 aTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mMutex));
27 if (!mMutex) {
28 // If D3D11Texture does not have keyed mutex, we think that the
29 // D3D11Texture could be locked.
30 mIsLocked = true;
31 return;
34 // Test to see if the keyed mutex has been released
35 HRESULT hr = mMutex->AcquireSync(0, 0);
36 if (hr == S_OK || hr == WAIT_ABANDONED) {
37 mIsLocked = true;
38 // According to Microsoft documentation:
39 // WAIT_ABANDONED - The shared surface and keyed mutex are no longer in a
40 // consistent state. If AcquireSync returns this value, you should release
41 // and recreate both the keyed mutex and the shared surface
42 // So even if we do get WAIT_ABANDONED, the keyed mutex will have to be
43 // released.
44 mSyncAcquired = true;
48 ~AutoCheckLockD3D11Texture() {
49 if (!mSyncAcquired) {
50 return;
52 HRESULT hr = mMutex->ReleaseSync(0);
53 if (FAILED(hr)) {
54 NS_WARNING("Failed to unlock the texture");
58 bool IsLocked() const { return mIsLocked; }
60 private:
61 bool mIsLocked;
62 bool mSyncAcquired = false;
63 RefPtr<IDXGIKeyedMutex> mMutex;
66 DXGIYCbCrTextureAllocationHelper::DXGIYCbCrTextureAllocationHelper(
67 const PlanarYCbCrData& aData, TextureFlags aTextureFlags,
68 ID3D11Device* aDevice)
69 : ITextureClientAllocationHelper(
70 gfx::SurfaceFormat::YUV420, aData.mPictureRect.Size(),
71 BackendSelector::Content, aTextureFlags, ALLOC_DEFAULT),
72 mData(aData),
73 mDevice(aDevice) {}
75 bool DXGIYCbCrTextureAllocationHelper::IsCompatible(
76 TextureClient* aTextureClient) {
77 MOZ_ASSERT(aTextureClient->GetFormat() == gfx::SurfaceFormat::YUV420);
79 DXGIYCbCrTextureData* dxgiData =
80 aTextureClient->GetInternalData()->AsDXGIYCbCrTextureData();
81 if (!dxgiData || aTextureClient->GetSize() != mData.mPictureRect.Size() ||
82 dxgiData->GetYSize() != mData.YDataSize() ||
83 dxgiData->GetCbCrSize() != mData.CbCrDataSize() ||
84 dxgiData->GetColorDepth() != mData.mColorDepth ||
85 dxgiData->GetYUVColorSpace() != mData.mYUVColorSpace) {
86 return false;
89 ID3D11Texture2D* textureY = dxgiData->GetD3D11Texture(0);
90 ID3D11Texture2D* textureCb = dxgiData->GetD3D11Texture(1);
91 ID3D11Texture2D* textureCr = dxgiData->GetD3D11Texture(2);
93 RefPtr<ID3D11Device> device;
94 textureY->GetDevice(getter_AddRefs(device));
95 if (!device || device != gfx::DeviceManagerDx::Get()->GetImageDevice()) {
96 return false;
99 // Test to see if the keyed mutex has been released.
100 // If D3D11Texture failed to lock, do not recycle the DXGIYCbCrTextureData.
102 AutoCheckLockD3D11Texture lockY(textureY);
103 AutoCheckLockD3D11Texture lockCr(textureCr);
104 AutoCheckLockD3D11Texture lockCb(textureCb);
106 if (!lockY.IsLocked() || !lockCr.IsLocked() || !lockCb.IsLocked()) {
107 return false;
110 return true;
113 already_AddRefed<TextureClient> DXGIYCbCrTextureAllocationHelper::Allocate(
114 KnowsCompositor* aAllocator) {
115 auto ySize = mData.YDataSize();
116 auto cbcrSize = mData.CbCrDataSize();
117 CD3D11_TEXTURE2D_DESC newDesc(mData.mColorDepth == gfx::ColorDepth::COLOR_8
118 ? DXGI_FORMAT_R8_UNORM
119 : DXGI_FORMAT_R16_UNORM,
120 ySize.width, ySize.height, 1, 1);
121 newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_NTHANDLE |
122 D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
124 RefPtr<ID3D10Multithread> mt;
125 HRESULT hr = mDevice->QueryInterface((ID3D10Multithread**)getter_AddRefs(mt));
127 if (FAILED(hr) || !mt) {
128 gfxCriticalError() << "Multithread safety interface not supported. " << hr;
129 return nullptr;
132 if (!mt->GetMultithreadProtected()) {
133 gfxCriticalError() << "Device used not marked as multithread-safe.";
134 return nullptr;
137 D3D11MTAutoEnter mtAutoEnter(mt.forget());
139 RefPtr<ID3D11Texture2D> textureY;
140 hr = mDevice->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(textureY));
141 NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
143 newDesc.Width = cbcrSize.width;
144 newDesc.Height = cbcrSize.height;
146 RefPtr<ID3D11Texture2D> textureCb;
147 hr = mDevice->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(textureCb));
148 NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
150 RefPtr<ID3D11Texture2D> textureCr;
151 hr = mDevice->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(textureCr));
152 NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
154 TextureForwarder* forwarder =
155 aAllocator ? aAllocator->GetTextureForwarder() : nullptr;
157 return TextureClient::CreateWithData(
158 DXGIYCbCrTextureData::Create(
159 textureY, textureCb, textureCr, mData.mPictureRect.Size(), ySize,
160 cbcrSize, mData.mColorDepth, mData.mYUVColorSpace, mData.mColorRange),
161 mTextureFlags, forwarder);
164 already_AddRefed<TextureClient> D3D11YCbCrRecycleAllocator::Allocate(
165 SurfaceFormat aFormat, IntSize aSize, BackendSelector aSelector,
166 TextureFlags aTextureFlags, TextureAllocationFlags aAllocFlags) {
167 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
168 return nullptr;
171 } // namespace layers
172 } // namespace mozilla