Bug 1497294 - P4. Use EnumSet with D3D11DeviceStatus and checks for P010 and P016 support. r=mattwoodrow
authorJean-Yves Avenard <jyavenard@mozilla.com>
Wed, 10 Oct 2018 22:14:51 +0000
changeset 496485 7a75881a86843c15f7f8977fa7b21388593a4628
parent 496484 45cbc8ce2df1db1311fa5b6e9e505d103ebed1cf
child 496486 e62671b3410d0a27ab55852aff7aaca9c7deca5d
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1497294
milestone64.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 1497294 - P4. Use EnumSet with D3D11DeviceStatus and checks for P010 and P016 support. r=mattwoodrow This allows to more easily construct it and add new values as needed. The other bool members could be made to be part of the set, but this would require more significant code change. Depends on D8082 Differential Revision: https://phabricator.services.mozilla.com/D8129
gfx/ipc/GraphicsMessages.ipdlh
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
@@ -6,16 +6,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 using struct DxgiAdapterDesc from "mozilla/D3DMessageUtils.h";
 using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
 using mozilla::gfx::FeatureStatus from "gfxTelemetry.h";
 using mozilla::gfx::BackendType from "mozilla/gfx/Types.h";
 using mozilla::gfx::IntSize from "mozilla/gfx/Point.h";
 using gfxImageFormat from "mozilla/gfx/Types.h";
+using mozilla::gfx::D3D11Checks::VideoFormatOption from "mozilla/gfx/D3D11Checks.h";
+using mozilla::gfx::D3D11Checks::VideoFormatOptionSet from "mozilla/gfx/D3D11Checks.h";
 
 namespace mozilla {
 namespace gfx {
 
 union GfxPrefValue {
   bool;
   int32_t;
   uint32_t;
@@ -30,17 +32,17 @@ struct GfxPrefSetting {
 
 struct D3D11DeviceStatus
 {
   bool isWARP;
   bool textureSharingWorks;
   uint32_t featureLevel;
   DxgiAdapterDesc adapter;
   int32_t sequenceNumber;
-  bool useNV12;
+  VideoFormatOptionSet formatOptions;
 };
 
 struct DevicePrefs
 {
   FeatureStatus hwCompositing;
   FeatureStatus d3d11Compositing;
   FeatureStatus oglCompositing;
   FeatureStatus advancedLayers;
--- a/gfx/thebes/D3D11Checks.cpp
+++ b/gfx/thebes/D3D11Checks.cpp
@@ -406,39 +406,67 @@ 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)
+/* static */ D3D11Checks::VideoFormatOptionSet
+D3D11Checks::FormatOptions(ID3D11Device* device)
 {
-  if(gfxVars::DXNV12Blocked()) {
-    return false;
-  }
+  auto doesNV12Work = [&]() {
+    if (gfxVars::DXNV12Blocked()) {
+      return false;
+    }
 
-  DXGI_ADAPTER_DESC desc;
-  PodZero(&desc);
-  if (!GetDxgiDesc(device, &desc)) {
-    // Failed to retrieve device information, assume it doesn't work
-    return false;
-  }
+    DXGI_ADAPTER_DESC desc;
+    PodZero(&desc);
+    if (!GetDxgiDesc(device, &desc)) {
+      // Failed to retrieve device information, assume it doesn't work
+      return false;
+    }
+
+    UINT formatSupport;
+    HRESULT hr = device->CheckFormatSupport(DXGI_FORMAT_NV12, &formatSupport);
+    if (FAILED(hr) || !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D)) {
+      return false;
+    }
 
-  HRESULT hr;
-  UINT formatSupport;
-  hr = device->CheckFormatSupport(DXGI_FORMAT_NV12, &formatSupport);
-  if (FAILED(hr) || !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D)) {
-    return false;
-  }
+    nsString version;
+    nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
+    if (gfxInfo) {
+      gfxInfo->GetAdapterDriverVersion(version);
+    }
+    return DXVA2Manager::IsNV12Supported(desc.VendorId, desc.DeviceId, version);
+  };
+
+  auto doesP010Work = [&]() {
+    UINT formatSupport;
+    HRESULT hr = device->CheckFormatSupport(DXGI_FORMAT_P010, &formatSupport);
+    return (SUCCEEDED(hr) && (formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D));
+  };
 
-  nsString version;
-  nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
-  if (gfxInfo) {
-    gfxInfo->GetAdapterDriverVersion(version);
+  auto doesP016Work = [&]() {
+    UINT formatSupport;
+    HRESULT hr = device->CheckFormatSupport(DXGI_FORMAT_P016, &formatSupport);
+    return (SUCCEEDED(hr) && (formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D));
+  };
+
+  VideoFormatOptionSet options;
+  if (!doesNV12Work()) {
+    // If the device doesn't support NV12, there's really no point testing for
+    // P010 and P016.
+    return options;
   }
-  return DXVA2Manager::IsNV12Supported(desc.VendorId, desc.DeviceId, version);
+  options += VideoFormatOption::NV12;
+  if (doesP010Work()) {
+    options += VideoFormatOption::P010;
+  }
+  if (doesP016Work()) {
+    options += VideoFormatOption::P016;
+  }
+  return options;
 }
 
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/thebes/D3D11Checks.h
+++ b/gfx/thebes/D3D11Checks.h
@@ -1,31 +1,52 @@
 /* -*- 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/. */
 
 #ifndef mozilla_gfx_thebes_D3D11Checks_h
 #define mozilla_gfx_thebes_D3D11Checks_h
 
+#include "mozilla/EnumSet.h"
+#include "mozilla/EnumTypeTraits.h"
+
 struct ID3D11Device;
 struct IDXGIAdapter;
 struct DXGI_ADAPTER_DESC;
 
 namespace mozilla {
 namespace gfx {
 
 struct D3D11Checks
 {
+  enum class VideoFormatOption
+  {
+    NV12,
+    P010,
+    P016,
+  };
+  using VideoFormatOptionSet = EnumSet<VideoFormatOption>;
+
   static bool DoesRenderTargetViewNeedRecreating(ID3D11Device* aDevice);
   static bool DoesDeviceWork();
   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);
+  static VideoFormatOptionSet FormatOptions(ID3D11Device* device);
 };
 
 } // namespace gfx
+
+// Used for IPDL serialization.
+// The 'value' have to be the biggest enum from D3D11Checks::Option.
+template <>
+struct MaxEnumValue<::mozilla::gfx::D3D11Checks::VideoFormatOption>
+{
+  static constexpr unsigned int value =
+    static_cast<unsigned int>(gfx::D3D11Checks::VideoFormatOption::P016);
+};
+
 } // namespace mozilla
 
 #endif // mozilla_gfx_thebes_D3D11Checks_h
--- a/gfx/thebes/DeviceManagerDx.cpp
+++ b/gfx/thebes/DeviceManagerDx.cpp
@@ -509,29 +509,28 @@ 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);
+  auto formatOptions = D3D11Checks::FormatOptions(device);
   {
     MutexAutoLock lock(mDeviceLock);
     mCompositorDevice = device;
 
     int32_t sequenceNumber = GetNextDeviceCounter();
-    mDeviceStatus = Some(D3D11DeviceStatus(
-      false,
-      textureSharingWorks,
-      featureLevel,
-      DxgiAdapterDesc::From(desc),
-      sequenceNumber,
-      useNV12));
+    mDeviceStatus = Some(D3D11DeviceStatus(false,
+                                           textureSharingWorks,
+                                           featureLevel,
+                                           DxgiAdapterDesc::From(desc),
+                                           sequenceNumber,
+                                           formatOptions));
   }
   mCompositorDevice->SetExceptionMode(0);
 }
 
 bool
 DeviceManagerDx::CreateDevice(IDXGIAdapter* aAdapter,
                                  D3D_DRIVER_TYPE aDriverType,
                                  UINT aFlags,
@@ -618,29 +617,28 @@ DeviceManagerDx::CreateWARPCompositorDev
     textureSharingWorks = D3D11Checks::DoesTextureSharingWork(device);
   }
 
   DxgiAdapterDesc nullAdapter;
   PodZero(&nullAdapter);
 
   int featureLevel = device->GetFeatureLevel();
 
-  bool useNV12 = D3D11Checks::DoesNV12Work(device);
+  auto formatOptions = D3D11Checks::FormatOptions(device);
   {
     MutexAutoLock lock(mDeviceLock);
     mCompositorDevice = device;
 
     int32_t sequenceNumber = GetNextDeviceCounter();
-    mDeviceStatus = Some(D3D11DeviceStatus(
-      true,
-      textureSharingWorks,
-      featureLevel,
-      nullAdapter,
-      sequenceNumber,
-      useNV12));
+    mDeviceStatus = Some(D3D11DeviceStatus(true,
+                                           textureSharingWorks,
+                                           featureLevel,
+                                           nullAdapter,
+                                           sequenceNumber,
+                                           formatOptions));
   }
   mCompositorDevice->SetExceptionMode(0);
 
   reporterWARP.SetSuccessful();
 }
 
 FeatureStatus
 DeviceManagerDx::CreateContentDevice()
@@ -1174,17 +1172,40 @@ DeviceManagerDx::IsWARP()
 
 bool
 DeviceManagerDx::CanUseNV12()
 {
   MutexAutoLock lock(mDeviceLock);
   if (!mDeviceStatus) {
     return false;
   }
-  return mDeviceStatus->useNV12();
+  return mDeviceStatus->formatOptions().contains(
+    D3D11Checks::VideoFormatOption::NV12);
+}
+
+bool
+DeviceManagerDx::CanUseP010()
+{
+  MutexAutoLock lock(mDeviceLock);
+  if (!mDeviceStatus) {
+    return false;
+  }
+  return mDeviceStatus->formatOptions().contains(
+    D3D11Checks::VideoFormatOption::P010);
+}
+
+bool
+DeviceManagerDx::CanUseP016()
+{
+  MutexAutoLock lock(mDeviceLock);
+  if (!mDeviceStatus) {
+    return false;
+  }
+  return mDeviceStatus->formatOptions().contains(
+    D3D11Checks::VideoFormatOption::P016);
 }
 
 bool
 DeviceManagerDx::CanUseDComp()
 {
   MutexAutoLock lock(mDeviceLock);
   return !!mDirectCompositionDevice;
 }
--- a/gfx/thebes/DeviceManagerDx.h
+++ b/gfx/thebes/DeviceManagerDx.h
@@ -64,16 +64,18 @@ public:
   RefPtr<ID3D11Device> CreateDecoderDevice();
   RefPtr<layers::MLGDevice> GetMLGDevice();
   IDirectDraw7* GetDirectDraw();
 
   unsigned GetCompositorFeatureLevel() const;
   bool TextureSharingWorks();
   bool IsWARP();
   bool CanUseNV12();
+  bool CanUseP010();
+  bool CanUseP016();
   bool CanUseDComp();
 
   // 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();