Source code

Revision control

Other Tools

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/. */
6
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"
16
#include "d3d9.h"
17
18
namespace mozilla {
19
namespace layers {
20
21
IMFYCbCrImage::IMFYCbCrImage(IMFMediaBuffer* aBuffer, IMF2DBuffer* a2DBuffer,
22
KnowsCompositor* aKnowsCompositor,
23
ImageContainer* aContainer)
24
: RecyclingPlanarYCbCrImage(nullptr),
25
mBuffer(aBuffer),
26
m2DBuffer(a2DBuffer) {
27
mAllocator = aContainer->GetD3D11YCbCrRecycleAllocator(aKnowsCompositor);
28
}
29
30
IMFYCbCrImage::~IMFYCbCrImage() {
31
if (m2DBuffer) {
32
m2DBuffer->Unlock2D();
33
} else {
34
mBuffer->Unlock();
35
}
36
}
37
38
/* static */
39
bool IMFYCbCrImage::CopyDataToTexture(const Data& aData, ID3D11Device* aDevice,
40
DXGIYCbCrTextureData* aTextureData) {
41
MOZ_ASSERT(aTextureData);
42
43
HRESULT hr;
44
RefPtr<ID3D10Multithread> mt;
45
46
hr = aDevice->QueryInterface((ID3D10Multithread**)getter_AddRefs(mt));
47
if (FAILED(hr)) {
48
return false;
49
}
50
51
if (!mt->GetMultithreadProtected()) {
52
return false;
53
}
54
55
if (!gfx::DeviceManagerDx::Get()->CanInitializeKeyedMutexTextures()) {
56
return false;
57
}
58
59
ID3D11Texture2D* textureY = aTextureData->GetD3D11Texture(0);
60
ID3D11Texture2D* textureCb = aTextureData->GetD3D11Texture(1);
61
ID3D11Texture2D* textureCr = aTextureData->GetD3D11Texture(2);
62
63
D3D11MTAutoEnter mtAutoEnter(mt.forget());
64
65
RefPtr<ID3D11DeviceContext> ctx;
66
aDevice->GetImmediateContext(getter_AddRefs(ctx));
67
if (!ctx) {
68
gfxCriticalError() << "Failed to get immediate context.";
69
return false;
70
}
71
72
// The documentation here seems to suggest using the immediate mode context
73
// on more than one thread is not allowed:
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.
78
79
{
80
AutoLockD3D11Texture lockY(textureY);
81
AutoLockD3D11Texture lockCr(textureCr);
82
AutoLockD3D11Texture lockCb(textureCb);
83
D3D11MTAutoEnter mtAutoEnter(mt.forget());
84
85
D3D11_BOX box;
86
box.front = box.top = box.left = 0;
87
box.back = 1;
88
box.right = aData.mYSize.width;
89
box.bottom = aData.mYSize.height;
90
ctx->UpdateSubresource(textureY, 0, &box, aData.mYChannel, aData.mYStride,
91
0);
92
93
box.right = aData.mCbCrSize.width;
94
box.bottom = aData.mCbCrSize.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);
99
}
100
101
return true;
102
}
103
104
TextureClient* IMFYCbCrImage::GetD3D11TextureClient(
105
KnowsCompositor* aKnowsCompositor) {
106
if (!mAllocator) {
107
return nullptr;
108
}
109
110
RefPtr<ID3D11Device> device = gfx::DeviceManagerDx::Get()->GetImageDevice();
111
if (!device) {
112
return nullptr;
113
}
114
115
{
116
DXGIYCbCrTextureAllocationHelper helper(mData, TextureFlags::DEFAULT,
117
device);
118
mTextureClient = mAllocator->CreateOrRecycle(helper);
119
}
120
121
if (!mTextureClient) {
122
return nullptr;
123
}
124
125
DXGIYCbCrTextureData* data =
126
mTextureClient->GetInternalData()->AsDXGIYCbCrTextureData();
127
128
if (!CopyDataToTexture(mData, device, data)) {
129
// Failed to copy data
130
mTextureClient = nullptr;
131
return nullptr;
132
}
133
134
return mTextureClient;
135
}
136
137
TextureClient* IMFYCbCrImage::GetTextureClient(
138
KnowsCompositor* aKnowsCompositor) {
139
if (mTextureClient) {
140
return mTextureClient;
141
}
142
143
RefPtr<ID3D11Device> device = gfx::DeviceManagerDx::Get()->GetImageDevice();
144
if (!device || !aKnowsCompositor->SupportsD3D11()) {
145
return nullptr;
146
}
147
return GetD3D11TextureClient(aKnowsCompositor);
148
}
149
150
} // namespace layers
151
} // namespace mozilla