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 "IMFYCbCrImage.h"
8 #include "mozilla/gfx/DeviceManagerDx.h"
9 #include "mozilla/gfx/gfxVars.h"
10 #include "mozilla/gfx/Types.h"
11 #include "mozilla/layers/TextureD3D11.h"
12 #include "mozilla/layers/CompositableClient.h"
13 #include "mozilla/layers/CompositableForwarder.h"
14 #include "mozilla/layers/D3D11YCbCrImage.h"
15 #include "mozilla/layers/TextureClient.h"
21 IMFYCbCrImage::IMFYCbCrImage(IMFMediaBuffer
* aBuffer
, IMF2DBuffer
* a2DBuffer
,
22 KnowsCompositor
* aKnowsCompositor
,
23 ImageContainer
* aContainer
)
24 : RecyclingPlanarYCbCrImage(nullptr),
26 m2DBuffer(a2DBuffer
) {
27 mAllocator
= aContainer
->GetD3D11YCbCrRecycleAllocator(aKnowsCompositor
);
30 IMFYCbCrImage::~IMFYCbCrImage() {
32 m2DBuffer
->Unlock2D();
39 bool IMFYCbCrImage::CopyDataToTexture(const Data
& aData
, ID3D11Device
* aDevice
,
40 DXGIYCbCrTextureData
* aTextureData
) {
41 MOZ_ASSERT(aTextureData
);
44 RefPtr
<ID3D10Multithread
> mt
;
46 hr
= aDevice
->QueryInterface((ID3D10Multithread
**)getter_AddRefs(mt
));
51 if (!mt
->GetMultithreadProtected()) {
55 if (!gfx::DeviceManagerDx::Get()->CanInitializeKeyedMutexTextures()) {
59 ID3D11Texture2D
* textureY
= aTextureData
->GetD3D11Texture(0);
60 ID3D11Texture2D
* textureCb
= aTextureData
->GetD3D11Texture(1);
61 ID3D11Texture2D
* textureCr
= aTextureData
->GetD3D11Texture(2);
63 D3D11MTAutoEnter
mtAutoEnter(mt
.forget());
65 RefPtr
<ID3D11DeviceContext
> ctx
;
66 aDevice
->GetImmediateContext(getter_AddRefs(ctx
));
68 gfxCriticalError() << "Failed to get immediate context.";
72 // The documentation here seems to suggest using the immediate mode context
73 // on more than one thread is not allowed:
74 // https://msdn.microsoft.com/en-us/library/windows/desktop/ff476891(v=vs.85).aspx
75 // The Debug Layer seems to imply it is though. When the ID3D10Multithread
76 // layer is on. The Enter/Leave of the critical section shouldn't even be
77 // required but were added for extra security.
80 AutoLockD3D11Texture
lockY(textureY
);
81 AutoLockD3D11Texture
lockCr(textureCr
);
82 AutoLockD3D11Texture
lockCb(textureCb
);
83 D3D11MTAutoEnter
mtAutoEnter(mt
.forget());
86 box
.front
= box
.top
= box
.left
= 0;
88 box
.right
= aData
.YDataSize().width
;
89 box
.bottom
= aData
.YDataSize().height
;
90 ctx
->UpdateSubresource(textureY
, 0, &box
, aData
.mYChannel
, aData
.mYStride
,
93 box
.right
= aData
.CbCrDataSize().width
;
94 box
.bottom
= aData
.CbCrDataSize().height
;
95 ctx
->UpdateSubresource(textureCb
, 0, &box
, aData
.mCbChannel
,
96 aData
.mCbCrStride
, 0);
97 ctx
->UpdateSubresource(textureCr
, 0, &box
, aData
.mCrChannel
,
98 aData
.mCbCrStride
, 0);
104 TextureClient
* IMFYCbCrImage::GetD3D11TextureClient(
105 KnowsCompositor
* aKnowsCompositor
) {
110 RefPtr
<ID3D11Device
> device
= gfx::DeviceManagerDx::Get()->GetImageDevice();
116 DXGIYCbCrTextureAllocationHelper
helper(mData
, TextureFlags::DEFAULT
,
118 mTextureClient
= mAllocator
->CreateOrRecycle(helper
);
121 if (!mTextureClient
) {
125 DXGIYCbCrTextureData
* data
=
126 mTextureClient
->GetInternalData()->AsDXGIYCbCrTextureData();
128 if (!CopyDataToTexture(mData
, device
, data
)) {
129 // Failed to copy data
130 mTextureClient
= nullptr;
134 return mTextureClient
;
137 TextureClient
* IMFYCbCrImage::GetTextureClient(
138 KnowsCompositor
* aKnowsCompositor
) {
139 if (mTextureClient
) {
140 return mTextureClient
;
143 RefPtr
<ID3D11Device
> device
= gfx::DeviceManagerDx::Get()->GetImageDevice();
144 if (!device
|| !aKnowsCompositor
->SupportsD3D11()) {
147 return GetD3D11TextureClient(aKnowsCompositor
);
150 } // namespace layers
151 } // namespace mozilla