Files
palemoon27/gfx/layers/IMFYCbCrImage.cpp
T
roytam1 ed0b673484 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1149343 - Part2: Add HW decode blacklisting support on mac. r=mattwoodrow (bd3d67e2e)
- missing bit of  Bug 1149343 - Part 1: Unify prefs/blacklist for hardware acceleration (551804df4)
- Bug 1174055 - Load WMF DLLs in MFStartup(), never unload them. r=jya (f2eb84146)
- Bug 1153123 - Don't upload in the ImageBridge thread if A8 texture sharing is broken. r=Bas (40d4a057f)
- logical extension of ug 1149343 - Part 1: Unify prefs/blacklist for hardware acceleration (57adc4003)
- Fix a startup crash when attempting to test D3D11 texture sharing. (bug 1170211, r=jmuizelaar, a=KWierso) (0a8fdc55f)
- Bug 1175366 - Don't use DXVA if D3D11 texture sharing is broken. r=jrmuizel (968b04384)
- Bug 1156135 - Add live pref for disabling DXVA when it fails to render correctly. r=ajones (1aed3e54d)
- Bug 1171094. Disallow D3D11 ANGLE with old DisplayLink drivers. r=Bas (c7e91c2bd)
- Bug 1173972. Improve logging in gfxWindowPlatform. r=milan (870aefb7b)
- Bug 1176506 - Don't test texture sharing on WARP devices since it never works and can be detected as a driver reset. r=Bas (5d8baec76)
- Bug 1180246 - Part 1 - remove dependencies on gfxD2DSurface. r=bas (6d20a0c23)
- Bug 1180246 - Part 2 - kill gfxD2DSurface with fire. r=bas (107da3dd1)
- Bug 1159751 - Use a more explicit order of destruction in gfxWindowsPlatform. r=bas (903a29b36)
- Bug 1180246 - Part 3 - remove usage of cairo_d2d_device. r=bas (b9c66f7d4)
- Bug 1180246 - Part 4 - reduce Cairo dependencies where safe in TextureClientD3D9. r=bas (07a18c32b)
- Bug 1170390 - Make gfxPlatform::CreateOffscreenSurface use explicit format rather than guess. r=jrmuizel (491a790ed)
- Bug 1109718. Log when RenderTargetView's need to be recreated. r=mwoodrow (fdaa1199d)
- Bug 1184130. Report mismatches of adapter description and vendor id that we get from the registry. r=bas (ffee48afb)
- Split gfxWindowsPlatform::UpdateRenderMode() into multiple functions. (bug 1179051 part 1, r=bas) (270caa1e5)
- Bug 1170143 - Disable texture sharing if we've blacklisted direct2d. r=Bas (bfb85c2b3)
- Bug 1170143 - Disable alpha texture sharing for intel driver version 8.15.10.2086 since it crashes. r=jrmuizel (cffedeb74)
- Bug 1173719 - Prevent crashes when passing touch events across the PBrowser interface with APZ disabled. r=botond (6585f60bf)
- Bug 1173983 - Use R8 textures for d3d11 alpha textures since it appears to be better supported. r=Bas (946c1e36c)
- missing bit of Bug 1150124. Move WARP reporter closer to actually testing WARP. (7ebc11c2f)
- Bug 1175104 - Enable multithread support on our d3d11 content device. r=Bas (32844aba1)
- Fix regression where WARP could be used as a fallback on Windows 7. (bug 1179051 part 2.1, r=jrmuizel) (89e1f5c3d)
- bug 1171113 - Add widget/uikit. r=roc (NPOTB) (dc79563ae)
- Move compositor backend decisions into gfxPlatform. (bug 1179051 part 3, r=mattwoodrow) (b1b8e10c6)
- Move more compositor backend checks into gfxPlatform. (bug 1179051 part 4, r=mattwoodrow) (6c9d820a0)
- Bug 1176052 - Introduce gfxCriticalNote. r=jmuizelaar (1cc2a0c90)
2021-06-16 15:49:44 +08:00

293 lines
8.8 KiB
C++

/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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/layers/TextureD3D11.h"
#include "mozilla/layers/CompositableClient.h"
#include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/gfx/Types.h"
#include "mozilla/layers/TextureClient.h"
#include "d3d9.h"
namespace mozilla {
namespace layers {
IMFYCbCrImage::IMFYCbCrImage(IMFMediaBuffer* aBuffer, IMF2DBuffer* a2DBuffer)
: PlanarYCbCrImage(nullptr)
, mBuffer(aBuffer)
, m2DBuffer(a2DBuffer)
{}
IMFYCbCrImage::~IMFYCbCrImage()
{
if (m2DBuffer) {
m2DBuffer->Unlock2D();
}
else {
mBuffer->Unlock();
}
}
struct AutoLockTexture
{
AutoLockTexture(ID3D11Texture2D* aTexture)
{
aTexture->QueryInterface((IDXGIKeyedMutex**)byRef(mMutex));
HRESULT hr = mMutex->AcquireSync(0, 10000);
if (hr == WAIT_TIMEOUT) {
MOZ_CRASH();
}
if (FAILED(hr)) {
NS_WARNING("Failed to lock the texture");
}
}
~AutoLockTexture()
{
HRESULT hr = mMutex->ReleaseSync(0);
if (FAILED(hr)) {
NS_WARNING("Failed to unlock the texture");
}
}
RefPtr<IDXGIKeyedMutex> mMutex;
};
static already_AddRefed<IDirect3DTexture9>
InitTextures(IDirect3DDevice9* aDevice,
const IntSize &aSize,
_D3DFORMAT aFormat,
RefPtr<IDirect3DSurface9>& aSurface,
HANDLE& aHandle,
D3DLOCKED_RECT& aLockedRect)
{
if (!aDevice) {
return nullptr;
}
RefPtr<IDirect3DTexture9> result;
if (FAILED(aDevice->CreateTexture(aSize.width, aSize.height,
1, 0, aFormat, D3DPOOL_DEFAULT,
byRef(result), &aHandle))) {
return nullptr;
}
if (!result) {
return nullptr;
}
RefPtr<IDirect3DTexture9> tmpTexture;
if (FAILED(aDevice->CreateTexture(aSize.width, aSize.height,
1, 0, aFormat, D3DPOOL_SYSTEMMEM,
byRef(tmpTexture), nullptr))) {
return nullptr;
}
if (!tmpTexture) {
return nullptr;
}
tmpTexture->GetSurfaceLevel(0, byRef(aSurface));
aSurface->LockRect(&aLockedRect, nullptr, 0);
if (!aLockedRect.pBits) {
NS_WARNING("Could not lock surface");
return nullptr;
}
return result.forget();
}
static void
FinishTextures(IDirect3DDevice9* aDevice,
IDirect3DTexture9* aTexture,
IDirect3DSurface9* aSurface)
{
if (!aDevice) {
return;
}
aSurface->UnlockRect();
nsRefPtr<IDirect3DSurface9> dstSurface;
aTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
aDevice->UpdateSurface(aSurface, nullptr, dstSurface, nullptr);
}
static bool UploadData(IDirect3DDevice9* aDevice,
RefPtr<IDirect3DTexture9>& aTexture,
HANDLE& aHandle,
uint8_t* aSrc,
const gfx::IntSize& aSrcSize,
int32_t aSrcStride)
{
RefPtr<IDirect3DSurface9> surf;
D3DLOCKED_RECT rect;
aTexture = InitTextures(aDevice, aSrcSize, D3DFMT_A8, surf, aHandle, rect);
if (!aTexture) {
return false;
}
if (aSrcStride == rect.Pitch) {
memcpy(rect.pBits, aSrc, rect.Pitch * aSrcSize.height);
} else {
for (int i = 0; i < aSrcSize.height; i++) {
memcpy((uint8_t*)rect.pBits + i * rect.Pitch,
aSrc + i * aSrcStride,
aSrcSize.width);
}
}
FinishTextures(aDevice, aTexture, surf);
return true;
}
TextureClient*
IMFYCbCrImage::GetD3D9TextureClient(CompositableClient* aClient)
{
IDirect3DDevice9* device = gfxWindowsPlatform::GetPlatform()->GetD3D9Device();
RefPtr<IDirect3DTexture9> textureY;
HANDLE shareHandleY = 0;
if (!UploadData(device, textureY, shareHandleY,
mData.mYChannel, mData.mYSize, mData.mYStride)) {
return nullptr;
}
RefPtr<IDirect3DTexture9> textureCb;
HANDLE shareHandleCb = 0;
if (!UploadData(device, textureCb, shareHandleCb,
mData.mCbChannel, mData.mCbCrSize, mData.mCbCrStride)) {
return nullptr;
}
RefPtr<IDirect3DTexture9> textureCr;
HANDLE shareHandleCr = 0;
if (!UploadData(device, textureCr, shareHandleCr,
mData.mCrChannel, mData.mCbCrSize, mData.mCbCrStride)) {
return nullptr;
}
RefPtr<IDirect3DQuery9> query;
HRESULT hr = device->CreateQuery(D3DQUERYTYPE_EVENT, byRef(query));
hr = query->Issue(D3DISSUE_END);
int iterations = 0;
bool valid = false;
while (iterations < 10) {
HRESULT hr = query->GetData(nullptr, 0, D3DGETDATA_FLUSH);
if (hr == S_FALSE) {
Sleep(1);
iterations++;
continue;
}
if (hr == S_OK) {
valid = true;
}
break;
}
if (!valid) {
return nullptr;
}
mTextureClient = DXGIYCbCrTextureClient::Create(aClient->GetForwarder(),
TextureFlags::DEFAULT,
textureY,
textureCb,
textureCr,
shareHandleY,
shareHandleCb,
shareHandleCr,
GetSize(),
mData.mYSize,
mData.mCbCrSize);
return mTextureClient;
}
TextureClient*
IMFYCbCrImage::GetTextureClient(CompositableClient* aClient)
{
ID3D11Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D11ImageBridgeDevice();
if (!device ||
aClient->GetForwarder()->GetCompositorBackendType() != LayersBackend::LAYERS_D3D11) {
IDirect3DDevice9* d3d9device = gfxWindowsPlatform::GetPlatform()->GetD3D9Device();
if (d3d9device && aClient->GetForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_D3D9) {
return GetD3D9TextureClient(aClient);
}
return nullptr;
}
if (mTextureClient) {
return mTextureClient;
}
RefPtr<ID3D11DeviceContext> ctx;
device->GetImmediateContext(byRef(ctx));
CD3D11_TEXTURE2D_DESC newDesc(DXGI_FORMAT_R8_UNORM,
mData.mYSize.width, mData.mYSize.height, 1, 1);
newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
RefPtr<ID3D11Texture2D> textureY;
HRESULT hr = device->CreateTexture2D(&newDesc, nullptr, byRef(textureY));
NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
newDesc.Width = mData.mCbCrSize.width;
newDesc.Height = mData.mCbCrSize.height;
RefPtr<ID3D11Texture2D> textureCb;
hr = device->CreateTexture2D(&newDesc, nullptr, byRef(textureCb));
NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
RefPtr<ID3D11Texture2D> textureCr;
hr = device->CreateTexture2D(&newDesc, nullptr, byRef(textureCr));
NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
{
AutoLockTexture lockY(textureY);
AutoLockTexture lockCb(textureCb);
AutoLockTexture lockCr(textureCr);
ctx->UpdateSubresource(textureY, 0, nullptr, mData.mYChannel,
mData.mYStride, mData.mYStride * mData.mYSize.height);
ctx->UpdateSubresource(textureCb, 0, nullptr, mData.mCbChannel,
mData.mCbCrStride, mData.mCbCrStride * mData.mCbCrSize.height);
ctx->UpdateSubresource(textureCr, 0, nullptr, mData.mCrChannel,
mData.mCbCrStride, mData.mCbCrStride * mData.mCbCrSize.height);
}
RefPtr<IDXGIResource> resource;
HANDLE shareHandleY;
textureY->QueryInterface((IDXGIResource**)byRef(resource));
hr = resource->GetSharedHandle(&shareHandleY);
HANDLE shareHandleCb;
textureCb->QueryInterface((IDXGIResource**)byRef(resource));
hr = resource->GetSharedHandle(&shareHandleCb);
HANDLE shareHandleCr;
textureCr->QueryInterface((IDXGIResource**)byRef(resource));
hr = resource->GetSharedHandle(&shareHandleCr);
mTextureClient = DXGIYCbCrTextureClient::Create(aClient->GetForwarder(),
TextureFlags::DEFAULT,
textureY,
textureCb,
textureCr,
shareHandleY,
shareHandleCb,
shareHandleCr,
GetSize(),
mData.mYSize,
mData.mCbCrSize);
return mTextureClient;
}
} // namespace layers
} // namespace mozilla