Bug 1352016 - P3. Check if NV12 rendering is usable when allocating D3D11 surface. r?mattwoodrow
MozReview-Commit-ID: EgA6lEeIyBj
--- a/gfx/ipc/GraphicsMessages.ipdlh
+++ b/gfx/ipc/GraphicsMessages.ipdlh
@@ -17,16 +17,17 @@ namespace gfx {
struct D3D11DeviceStatus
{
bool isWARP;
bool textureSharingWorks;
uint32_t featureLevel;
DxgiAdapterDesc adapter;
int32_t sequenceNumber;
+ bool useNV12;
};
struct DevicePrefs
{
FeatureStatus hwCompositing;
FeatureStatus d3d11Compositing;
FeatureStatus oglCompositing;
FeatureStatus advancedLayers;
--- a/gfx/layers/D3D11ShareHandleImage.cpp
+++ b/gfx/layers/D3D11ShareHandleImage.cpp
@@ -29,17 +29,18 @@ D3D11ShareHandleImage::D3D11ShareHandleI
mPictureRect(aRect)
{
}
bool
D3D11ShareHandleImage::AllocateTexture(D3D11RecycleAllocator* aAllocator, ID3D11Device* aDevice)
{
if (aAllocator) {
- if (gfxPrefs::PDMWMFUseNV12Format()) {
+ if (gfxPrefs::PDMWMFUseNV12Format() &&
+ gfx::DeviceManagerDx::Get()->CanUseNV12()) {
mTextureClient = aAllocator->CreateOrRecycleClient(gfx::SurfaceFormat::NV12, mSize);
} else {
mTextureClient = aAllocator->CreateOrRecycleClient(gfx::SurfaceFormat::B8G8R8A8, mSize);
}
if (mTextureClient) {
mTexture = static_cast<D3D11TextureData*>(mTextureClient->GetInternalData())->GetD3D11Texture();
return true;
}
--- a/gfx/thebes/D3D11Checks.cpp
+++ b/gfx/thebes/D3D11Checks.cpp
@@ -1,14 +1,15 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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 "D3D11Checks.h"
+#include "DXVA2Manager.h"
#include "gfxConfig.h"
#include "GfxDriverInfo.h"
#include "gfxPrefs.h"
#include "gfxWindowsPlatform.h"
#include "mozilla/RefPtr.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/layers/TextureD3D11.h"
#include "nsIGfxInfo.h"
@@ -404,10 +405,28 @@ D3D11Checks::WarnOnAdapterMismatch(ID3D1
D3D11Checks::DoesRemotePresentWork(IDXGIAdapter* adapter)
{
// Remote presentation was added in DXGI 1.2, for Windows 8 and the Platform Update to Windows 7.
RefPtr<IDXGIAdapter2> check;
HRESULT hr = adapter->QueryInterface(__uuidof(IDXGIAdapter2), getter_AddRefs(check));
return SUCCEEDED(hr) && check;
}
+/* static */ bool
+D3D11Checks::DoesNV12Work(ID3D11Device* device)
+{
+ DXGI_ADAPTER_DESC desc;
+ PodZero(&desc);
+ if (!GetDxgiDesc(device, &desc)) {
+ // Failed to retrieve device information, assume it doesn't work
+ return false;
+ }
+
+ nsString version;
+ nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
+ if (gfxInfo) {
+ gfxInfo->GetAdapterDriverVersion(version);
+ }
+ return DXVA2Manager::IsNV12Supported(desc.VendorId, desc.DeviceId, version);
+}
+
} // namespace gfx
} // namespace mozilla
--- a/gfx/thebes/D3D11Checks.h
+++ b/gfx/thebes/D3D11Checks.h
@@ -12,19 +12,20 @@ struct DXGI_ADAPTER_DESC;
namespace mozilla {
namespace gfx {
struct D3D11Checks
{
static bool DoesRenderTargetViewNeedRecreating(ID3D11Device* aDevice);
static bool DoesDeviceWork();
- static bool DoesTextureSharingWork(ID3D11Device *device);
- static bool DoesAlphaTextureSharingWork(ID3D11Device *device);
+ static bool DoesTextureSharingWork(ID3D11Device* device);
+ static bool DoesAlphaTextureSharingWork(ID3D11Device* device);
static void WarnOnAdapterMismatch(ID3D11Device* device);
static bool GetDxgiDesc(ID3D11Device* device, DXGI_ADAPTER_DESC* out);
static bool DoesRemotePresentWork(IDXGIAdapter* adapter);
+ static bool DoesNV12Work(ID3D11Device* device);
};
} // namespace gfx
} // namespace mozilla
#endif // mozilla_gfx_thebes_D3D11Checks_h
--- a/gfx/thebes/DeviceManagerDx.cpp
+++ b/gfx/thebes/DeviceManagerDx.cpp
@@ -390,27 +390,29 @@ DeviceManagerDx::CreateCompositorDevice(
"RenderTargetViews need recreating");
}
if (XRE_IsParentProcess()) {
// It seems like this may only happen when we're using the NVIDIA gpu
D3D11Checks::WarnOnAdapterMismatch(device);
}
uint32_t featureLevel = device->GetFeatureLevel();
+ bool useNV12 = D3D11Checks::DoesNV12Work(device);
{
MutexAutoLock lock(mDeviceLock);
mCompositorDevice = device;
int32_t sequenceNumber = GetNextDeviceCounter();
mDeviceStatus = Some(D3D11DeviceStatus(
false,
textureSharingWorks,
featureLevel,
DxgiAdapterDesc::From(desc),
- sequenceNumber));
+ sequenceNumber,
+ useNV12));
}
mCompositorDevice->SetExceptionMode(0);
}
bool
DeviceManagerDx::CreateDevice(IDXGIAdapter* aAdapter,
D3D_DRIVER_TYPE aDriverType,
UINT aFlags,
@@ -496,27 +498,30 @@ DeviceManagerDx::CreateWARPCompositorDev
if (IsWin8OrLater()) {
textureSharingWorks = D3D11Checks::DoesTextureSharingWork(device);
}
DxgiAdapterDesc nullAdapter;
PodZero(&nullAdapter);
int featureLevel = device->GetFeatureLevel();
+
+ bool useNV12 = D3D11Checks::DoesNV12Work(device);
{
MutexAutoLock lock(mDeviceLock);
mCompositorDevice = device;
int32_t sequenceNumber = GetNextDeviceCounter();
mDeviceStatus = Some(D3D11DeviceStatus(
true,
textureSharingWorks,
featureLevel,
nullAdapter,
- sequenceNumber));
+ sequenceNumber,
+ useNV12));
}
mCompositorDevice->SetExceptionMode(0);
reporterWARP.SetSuccessful();
}
FeatureStatus
DeviceManagerDx::CreateContentDevice()
@@ -996,16 +1001,26 @@ DeviceManagerDx::IsWARP()
{
MutexAutoLock lock(mDeviceLock);
if (!mDeviceStatus) {
return false;
}
return mDeviceStatus->isWARP();
}
+bool
+DeviceManagerDx::CanUseNV12()
+{
+ MutexAutoLock lock(mDeviceLock);
+ if (!mDeviceStatus) {
+ return false;
+ }
+ return mDeviceStatus->useNV12();
+}
+
void
DeviceManagerDx::InitializeDirectDraw()
{
MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread());
if (mDirectDraw) {
// Already initialized.
return;
--- a/gfx/thebes/DeviceManagerDx.h
+++ b/gfx/thebes/DeviceManagerDx.h
@@ -59,16 +59,17 @@ public:
RefPtr<ID3D11Device> GetContentDevice();
RefPtr<ID3D11Device> CreateDecoderDevice();
RefPtr<layers::MLGDevice> GetMLGDevice();
IDirectDraw7* GetDirectDraw();
unsigned GetCompositorFeatureLevel() const;
bool TextureSharingWorks();
bool IsWARP();
+ bool CanUseNV12();
// Returns true if we can create a texture with
// D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX and also
// upload texture data during the CreateTexture2D
// call. This crashes on some devices, so we might
// need to avoid it.
bool CanInitializeKeyedMutexTextures();