зеркало из https://github.com/mozilla/gecko-dev.git
152 строки
4.4 KiB
C++
152 строки
4.4 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "IMFYCbCrImage.h"
|
|
#include "mozilla/gfx/DeviceManagerDx.h"
|
|
#include "mozilla/gfx/gfxVars.h"
|
|
#include "mozilla/gfx/Types.h"
|
|
#include "mozilla/layers/TextureD3D11.h"
|
|
#include "mozilla/layers/CompositableClient.h"
|
|
#include "mozilla/layers/CompositableForwarder.h"
|
|
#include "mozilla/layers/D3D11YCbCrImage.h"
|
|
#include "mozilla/layers/TextureClient.h"
|
|
#include "d3d9.h"
|
|
|
|
namespace mozilla {
|
|
namespace layers {
|
|
|
|
IMFYCbCrImage::IMFYCbCrImage(IMFMediaBuffer* aBuffer, IMF2DBuffer* a2DBuffer,
|
|
KnowsCompositor* aKnowsCompositor,
|
|
ImageContainer* aContainer)
|
|
: RecyclingPlanarYCbCrImage(nullptr),
|
|
mBuffer(aBuffer),
|
|
m2DBuffer(a2DBuffer) {
|
|
mAllocator = aContainer->GetD3D11YCbCrRecycleAllocator(aKnowsCompositor);
|
|
}
|
|
|
|
IMFYCbCrImage::~IMFYCbCrImage() {
|
|
if (m2DBuffer) {
|
|
m2DBuffer->Unlock2D();
|
|
} else {
|
|
mBuffer->Unlock();
|
|
}
|
|
}
|
|
|
|
/* static */
|
|
bool IMFYCbCrImage::CopyDataToTexture(const Data& aData, ID3D11Device* aDevice,
|
|
DXGIYCbCrTextureData* aTextureData) {
|
|
MOZ_ASSERT(aTextureData);
|
|
|
|
HRESULT hr;
|
|
RefPtr<ID3D10Multithread> mt;
|
|
|
|
hr = aDevice->QueryInterface((ID3D10Multithread**)getter_AddRefs(mt));
|
|
if (FAILED(hr)) {
|
|
return false;
|
|
}
|
|
|
|
if (!mt->GetMultithreadProtected()) {
|
|
return false;
|
|
}
|
|
|
|
if (!gfx::DeviceManagerDx::Get()->CanInitializeKeyedMutexTextures()) {
|
|
return false;
|
|
}
|
|
|
|
ID3D11Texture2D* textureY = aTextureData->GetD3D11Texture(0);
|
|
ID3D11Texture2D* textureCb = aTextureData->GetD3D11Texture(1);
|
|
ID3D11Texture2D* textureCr = aTextureData->GetD3D11Texture(2);
|
|
|
|
D3D11MTAutoEnter mtAutoEnter(mt.forget());
|
|
|
|
RefPtr<ID3D11DeviceContext> ctx;
|
|
aDevice->GetImmediateContext(getter_AddRefs(ctx));
|
|
if (!ctx) {
|
|
gfxCriticalError() << "Failed to get immediate context.";
|
|
return false;
|
|
}
|
|
|
|
// The documentation here seems to suggest using the immediate mode context
|
|
// on more than one thread is not allowed:
|
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/ff476891(v=vs.85).aspx
|
|
// The Debug Layer seems to imply it is though. When the ID3D10Multithread
|
|
// layer is on. The Enter/Leave of the critical section shouldn't even be
|
|
// required but were added for extra security.
|
|
|
|
{
|
|
AutoLockD3D11Texture lockY(textureY);
|
|
AutoLockD3D11Texture lockCr(textureCr);
|
|
AutoLockD3D11Texture lockCb(textureCb);
|
|
D3D11MTAutoEnter mtAutoEnter(mt.forget());
|
|
|
|
D3D11_BOX box;
|
|
box.front = box.top = box.left = 0;
|
|
box.back = 1;
|
|
box.right = aData.mYSize.width;
|
|
box.bottom = aData.mYSize.height;
|
|
ctx->UpdateSubresource(textureY, 0, &box, aData.mYChannel, aData.mYStride,
|
|
0);
|
|
|
|
box.right = aData.mCbCrSize.width;
|
|
box.bottom = aData.mCbCrSize.height;
|
|
ctx->UpdateSubresource(textureCb, 0, &box, aData.mCbChannel,
|
|
aData.mCbCrStride, 0);
|
|
ctx->UpdateSubresource(textureCr, 0, &box, aData.mCrChannel,
|
|
aData.mCbCrStride, 0);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
TextureClient* IMFYCbCrImage::GetD3D11TextureClient(
|
|
KnowsCompositor* aKnowsCompositor) {
|
|
if (!mAllocator) {
|
|
return nullptr;
|
|
}
|
|
|
|
RefPtr<ID3D11Device> device = gfx::DeviceManagerDx::Get()->GetImageDevice();
|
|
if (!device) {
|
|
return nullptr;
|
|
}
|
|
|
|
{
|
|
DXGIYCbCrTextureAllocationHelper helper(mData, TextureFlags::DEFAULT,
|
|
device);
|
|
mTextureClient = mAllocator->CreateOrRecycle(helper);
|
|
}
|
|
|
|
if (!mTextureClient) {
|
|
return nullptr;
|
|
}
|
|
|
|
DXGIYCbCrTextureData* data =
|
|
mTextureClient->GetInternalData()->AsDXGIYCbCrTextureData();
|
|
|
|
if (!CopyDataToTexture(mData, device, data)) {
|
|
// Failed to copy data
|
|
mTextureClient = nullptr;
|
|
return nullptr;
|
|
}
|
|
|
|
return mTextureClient;
|
|
}
|
|
|
|
TextureClient* IMFYCbCrImage::GetTextureClient(
|
|
KnowsCompositor* aKnowsCompositor) {
|
|
if (mTextureClient) {
|
|
return mTextureClient;
|
|
}
|
|
|
|
RefPtr<ID3D11Device> device = gfx::DeviceManagerDx::Get()->GetImageDevice();
|
|
if (!device || !aKnowsCompositor->SupportsD3D11()) {
|
|
return nullptr;
|
|
}
|
|
return GetD3D11TextureClient(aKnowsCompositor);
|
|
}
|
|
|
|
} // namespace layers
|
|
} // namespace mozilla
|