Bug 1352016 - P2. Check if NV12 rendering is usable when allocating D3D11 surface. r=mattwoodrow
☠☠ backed out by 08a75460a0d8 ☠ ☠
authorJean-Yves Avenard <jyavenard@mozilla.com>
Sun, 10 Sep 2017 17:54:31 +0200
changeset 429890 e79e512f803f56f3af3110a8e67722c6d6ae9fb8
parent 429889 9eed6a69298c723817a6e6abc7537fd5fffae098
child 429891 ebc7c92e8dc0a5575d51a3b21b7cf426b1516f74
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1352016
milestone57.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1352016 - P2. Check if NV12 rendering is usable when allocating D3D11 surface. r=mattwoodrow MozReview-Commit-ID: EgA6lEeIyBj
gfx/ipc/GraphicsMessages.ipdlh
gfx/layers/D3D11ShareHandleImage.cpp
gfx/thebes/D3D11Checks.cpp
gfx/thebes/D3D11Checks.h
gfx/thebes/DeviceManagerDx.cpp
gfx/thebes/DeviceManagerDx.h
--- 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,26 @@ 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 works
+    return true;
+  }
+
+  nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
+  nsString version;
+  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 true;
+  }
+  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();