Files
tubestation/gfx/layers/D3D11YCbCrImage.cpp
Brad Werth c15ff565da Bug 1906527 Part 1: Rename SurfaceFormat::YUV422 to YUY2, and rename YUV to YUV420. r=jgilbert
This is just a renaming patch, motivated by a need for clarity before
addding more YUV formats. Comments and log messages are updated as well,
and one function in MacIOSurface is renamed.

There is one small change in TextureHost.cpp  to satisfy clang-tidy.

Differential Revision: https://phabricator.services.mozilla.com/D217883
2024-08-05 17:59:15 +00:00

173 lines
5.8 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 "D3D11YCbCrImage.h"
#include "YCbCrUtils.h"
#include "gfx2DGlue.h"
#include "mozilla/gfx/DeviceManagerDx.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/layers/CompositableClient.h"
#include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/layers/TextureD3D11.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
class AutoCheckLockD3D11Texture final {
public:
explicit AutoCheckLockD3D11Texture(ID3D11Texture2D* aTexture)
: mIsLocked(false) {
aTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mMutex));
if (!mMutex) {
// If D3D11Texture does not have keyed mutex, we think that the
// D3D11Texture could be locked.
mIsLocked = true;
return;
}
// Test to see if the keyed mutex has been released
HRESULT hr = mMutex->AcquireSync(0, 0);
if (hr == S_OK || hr == WAIT_ABANDONED) {
mIsLocked = true;
// According to Microsoft documentation:
// WAIT_ABANDONED - The shared surface and keyed mutex are no longer in a
// consistent state. If AcquireSync returns this value, you should release
// and recreate both the keyed mutex and the shared surface
// So even if we do get WAIT_ABANDONED, the keyed mutex will have to be
// released.
mSyncAcquired = true;
}
}
~AutoCheckLockD3D11Texture() {
if (!mSyncAcquired) {
return;
}
HRESULT hr = mMutex->ReleaseSync(0);
if (FAILED(hr)) {
NS_WARNING("Failed to unlock the texture");
}
}
bool IsLocked() const { return mIsLocked; }
private:
bool mIsLocked;
bool mSyncAcquired = false;
RefPtr<IDXGIKeyedMutex> mMutex;
};
DXGIYCbCrTextureAllocationHelper::DXGIYCbCrTextureAllocationHelper(
const PlanarYCbCrData& aData, TextureFlags aTextureFlags,
ID3D11Device* aDevice)
: ITextureClientAllocationHelper(
gfx::SurfaceFormat::YUV420, aData.mPictureRect.Size(),
BackendSelector::Content, aTextureFlags, ALLOC_DEFAULT),
mData(aData),
mDevice(aDevice) {}
bool DXGIYCbCrTextureAllocationHelper::IsCompatible(
TextureClient* aTextureClient) {
MOZ_ASSERT(aTextureClient->GetFormat() == gfx::SurfaceFormat::YUV420);
DXGIYCbCrTextureData* dxgiData =
aTextureClient->GetInternalData()->AsDXGIYCbCrTextureData();
if (!dxgiData || aTextureClient->GetSize() != mData.mPictureRect.Size() ||
dxgiData->GetYSize() != mData.YDataSize() ||
dxgiData->GetCbCrSize() != mData.CbCrDataSize() ||
dxgiData->GetColorDepth() != mData.mColorDepth ||
dxgiData->GetYUVColorSpace() != mData.mYUVColorSpace) {
return false;
}
ID3D11Texture2D* textureY = dxgiData->GetD3D11Texture(0);
ID3D11Texture2D* textureCb = dxgiData->GetD3D11Texture(1);
ID3D11Texture2D* textureCr = dxgiData->GetD3D11Texture(2);
RefPtr<ID3D11Device> device;
textureY->GetDevice(getter_AddRefs(device));
if (!device || device != gfx::DeviceManagerDx::Get()->GetImageDevice()) {
return false;
}
// Test to see if the keyed mutex has been released.
// If D3D11Texture failed to lock, do not recycle the DXGIYCbCrTextureData.
AutoCheckLockD3D11Texture lockY(textureY);
AutoCheckLockD3D11Texture lockCr(textureCr);
AutoCheckLockD3D11Texture lockCb(textureCb);
if (!lockY.IsLocked() || !lockCr.IsLocked() || !lockCb.IsLocked()) {
return false;
}
return true;
}
already_AddRefed<TextureClient> DXGIYCbCrTextureAllocationHelper::Allocate(
KnowsCompositor* aAllocator) {
auto ySize = mData.YDataSize();
auto cbcrSize = mData.CbCrDataSize();
CD3D11_TEXTURE2D_DESC newDesc(mData.mColorDepth == gfx::ColorDepth::COLOR_8
? DXGI_FORMAT_R8_UNORM
: DXGI_FORMAT_R16_UNORM,
ySize.width, ySize.height, 1, 1);
newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_NTHANDLE |
D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
RefPtr<ID3D10Multithread> mt;
HRESULT hr = mDevice->QueryInterface((ID3D10Multithread**)getter_AddRefs(mt));
if (FAILED(hr) || !mt) {
gfxCriticalError() << "Multithread safety interface not supported. " << hr;
return nullptr;
}
if (!mt->GetMultithreadProtected()) {
gfxCriticalError() << "Device used not marked as multithread-safe.";
return nullptr;
}
D3D11MTAutoEnter mtAutoEnter(mt.forget());
RefPtr<ID3D11Texture2D> textureY;
hr = mDevice->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(textureY));
NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
newDesc.Width = cbcrSize.width;
newDesc.Height = cbcrSize.height;
RefPtr<ID3D11Texture2D> textureCb;
hr = mDevice->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(textureCb));
NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
RefPtr<ID3D11Texture2D> textureCr;
hr = mDevice->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(textureCr));
NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
TextureForwarder* forwarder =
aAllocator ? aAllocator->GetTextureForwarder() : nullptr;
return TextureClient::CreateWithData(
DXGIYCbCrTextureData::Create(
textureY, textureCb, textureCr, mData.mPictureRect.Size(), ySize,
cbcrSize, mData.mColorDepth, mData.mYUVColorSpace, mData.mColorRange),
mTextureFlags, forwarder);
}
already_AddRefed<TextureClient> D3D11YCbCrRecycleAllocator::Allocate(
SurfaceFormat aFormat, IntSize aSize, BackendSelector aSelector,
TextureFlags aTextureFlags, TextureAllocationFlags aAllocFlags) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return nullptr;
}
} // namespace layers
} // namespace mozilla