Bug 1284672 - Try use an exsiting D3D11 device for video rather than creating new ones. r=dvander
authorMatt Woodrow <mwoodrow@mozilla.com>
Tue, 02 Aug 2016 18:46:27 +1200
changeset 307916 b407b980351600f6708db179c9bdb3338bf24796
parent 307915 02bab8358e59db5ca28e3fbbfd46907c4e5ba238
child 307917 35ba6de9c442bb9bdbb80677dfef18b05ece7b1e
push id31034
push usercbook@mozilla.com
push dateWed, 03 Aug 2016 15:09:36 +0000
treeherderautoland@8ceb6981305f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander
bugs1284672
milestone51.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 1284672 - Try use an exsiting D3D11 device for video rather than creating new ones. r=dvander
gfx/thebes/DeviceManagerD3D11.cpp
gfx/thebes/DeviceManagerD3D11.h
--- a/gfx/thebes/DeviceManagerD3D11.cpp
+++ b/gfx/thebes/DeviceManagerD3D11.cpp
@@ -40,17 +40,18 @@ DeviceManagerD3D11::Init()
 DeviceManagerD3D11::Shutdown()
 {
   sInstance = nullptr;
 }
 
 DeviceManagerD3D11::DeviceManagerD3D11()
  : mDeviceLock("gfxWindowsPlatform.mDeviceLock"),
    mIsWARP(false),
-   mTextureSharingWorks(false)
+   mTextureSharingWorks(false),
+   mCompositorDeviceSupportsVideo(false)
 {
   // Set up the D3D11 feature levels we can ask for.
   if (IsWin8OrLater()) {
     mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_11_1);
   }
   mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_11_0);
   mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_10_1);
   mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_10_0);
@@ -206,63 +207,92 @@ DeviceManagerD3D11::GetDXGIAdapter()
   }
 
   // We leak this module everywhere, we might as well do so here as well.
   dxgiModule.disown();
   return mAdapter;
 }
 
 bool
-DeviceManagerD3D11::AttemptD3D11DeviceCreationHelper(
-  IDXGIAdapter1* aAdapter, RefPtr<ID3D11Device>& aOutDevice, HRESULT& aResOut)
+DeviceManagerD3D11::AttemptD3D11DeviceCreationHelperInner(
+  IDXGIAdapter1* aAdapter, bool aAttemptVideoSupport, RefPtr<ID3D11Device>& aOutDevice, HRESULT& aResOut)
 {
+  // Use D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
+  // to prevent bug 1092260. IE 11 also uses this flag.
+  UINT flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS;
+  if (aAttemptVideoSupport) {
+    flags |= D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
+  }
+
   MOZ_SEH_TRY {
     aResOut =
       sD3D11CreateDeviceFn(
-        aAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
-        // Use D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
-        // to prevent bug 1092260. IE 11 also uses this flag.
-        D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
+        aAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, flags,
         mFeatureLevels.Elements(), mFeatureLevels.Length(),
         D3D11_SDK_VERSION, getter_AddRefs(aOutDevice), nullptr, nullptr);
   } MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
     return false;
   }
   return true;
 }
 
+bool
+DeviceManagerD3D11::AttemptD3D11DeviceCreationHelper(
+  FeatureState& aD3d11, IDXGIAdapter1* aAdapter, bool aAttemptVideoSupport, RefPtr<ID3D11Device>& aOutDevice)
+{
+  HRESULT hr;
+  RefPtr<ID3D11Device> device;
+  if (!AttemptD3D11DeviceCreationHelperInner(aAdapter, aAttemptVideoSupport, device, hr)) {
+    if (!aAttemptVideoSupport) {
+      gfxCriticalError() << "Crash during D3D11 device creation";
+      aD3d11.SetFailed(FeatureStatus::CrashedInHandler, "Crashed trying to acquire a D3D11 device",
+                       NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_DEVICE1"));
+    }
+    return false;
+  }
+
+  if (FAILED(hr) || !device) {
+    if (!aAttemptVideoSupport) {
+      gfxCriticalError() << "D3D11 device creation failed: " << hexa(hr);
+      aD3d11.SetFailed(FeatureStatus::Failed, "Failed to acquire a D3D11 device",
+                       NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_DEVICE2"));
+    }
+    return false;
+  }
+  if (!D3D11Checks::DoesDeviceWork()) {
+    if (!aAttemptVideoSupport) {
+      aD3d11.SetFailed(FeatureStatus::Broken, "Direct3D11 device was determined to be broken",
+                       NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_BROKEN"));
+    }
+    return false;
+  }
+
+  aOutDevice = device;
+  return true;
+}
+
 void
 DeviceManagerD3D11::AttemptD3D11DeviceCreation(FeatureState& d3d11)
 {
   RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter();
   if (!adapter) {
     d3d11.SetFailed(FeatureStatus::Unavailable, "Failed to acquire a DXGI adapter",
                     NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_DXGI"));
     return;
   }
 
-  HRESULT hr;
   RefPtr<ID3D11Device> device;
-  if (!AttemptD3D11DeviceCreationHelper(adapter, device, hr)) {
-    gfxCriticalError() << "Crash during D3D11 device creation";
-    d3d11.SetFailed(FeatureStatus::CrashedInHandler, "Crashed trying to acquire a D3D11 device",
-                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_DEVICE1"));
-    return;
-  }
-
-  if (FAILED(hr) || !device) {
-    gfxCriticalError() << "D3D11 device creation failed: " << hexa(hr);
-    d3d11.SetFailed(FeatureStatus::Failed, "Failed to acquire a D3D11 device",
-                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_DEVICE2"));
-    return;
-  }
-  if (!D3D11Checks::DoesDeviceWork()) {
-    d3d11.SetFailed(FeatureStatus::Broken, "Direct3D11 device was determined to be broken",
-                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_BROKEN"));
-    return;
+  if (!AttemptD3D11DeviceCreationHelper(d3d11, adapter, true, device)) {
+    // Try again without video support and record that it failed.
+    mCompositorDeviceSupportsVideo = false;
+    if (!AttemptD3D11DeviceCreationHelper(d3d11, adapter, false, device)) {
+      return;
+    }
+  } else {
+    mCompositorDeviceSupportsVideo = true;
   }
 
   {
     MutexAutoLock lock(mDeviceLock);
     mCompositorDevice = device;
   }
 
   // Only test this when not using WARP since it can fail and cause
@@ -428,29 +458,44 @@ DeviceManagerD3D11::AttemptD3D11ContentD
 bool
 DeviceManagerD3D11::CreateD3D11DecoderDeviceHelper(
   IDXGIAdapter1* aAdapter, RefPtr<ID3D11Device>& aDevice, HRESULT& aResOut)
 {
   MOZ_SEH_TRY{
     aResOut =
       sD3D11CreateDeviceFn(
         aAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
-        D3D11_CREATE_DEVICE_VIDEO_SUPPORT,
+        D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS | D3D11_CREATE_DEVICE_VIDEO_SUPPORT,
         mFeatureLevels.Elements(), mFeatureLevels.Length(),
         D3D11_SDK_VERSION, getter_AddRefs(aDevice), nullptr, nullptr);
 
   } MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
     return false;
   }
   return true;
 }
 
 RefPtr<ID3D11Device>
 DeviceManagerD3D11::CreateDecoderDevice()
 {
+  if (mCompositorDevice && mCompositorDeviceSupportsVideo && !mDecoderDevice) {
+    mDecoderDevice = mCompositorDevice;
+
+    RefPtr<ID3D10Multithread> multi;
+    mDecoderDevice->QueryInterface(__uuidof(ID3D10Multithread), getter_AddRefs(multi));
+    if (multi) {
+      multi->SetMultithreadProtected(TRUE);
+    }
+  }
+
+  if (mDecoderDevice) {
+    RefPtr<ID3D11Device> dev = mDecoderDevice;
+    return dev.forget();
+  }
+
    if (!sD3D11CreateDeviceFn) {
     // We should just be on Windows Vista or XP in this case.
     return nullptr;
   }
 
   RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter();
   if (!adapter) {
     return nullptr;
@@ -465,16 +510,18 @@ DeviceManagerD3D11::CreateDecoderDevice(
   if (FAILED(hr) || !device || !D3D11Checks::DoesDeviceWork()) {
     return nullptr;
   }
 
   RefPtr<ID3D10Multithread> multi;
   device->QueryInterface(__uuidof(ID3D10Multithread), getter_AddRefs(multi));
 
   multi->SetMultithreadProtected(TRUE);
+
+  mDecoderDevice = device;
   return device;
 }
 
 void
 DeviceManagerD3D11::ResetDevices()
 {
   MutexAutoLock lock(mDeviceLock);
 
--- a/gfx/thebes/DeviceManagerD3D11.h
+++ b/gfx/thebes/DeviceManagerD3D11.h
@@ -63,20 +63,26 @@ public:
   bool GetAnyDeviceRemovedReason(DeviceResetReason* aOutReason);
 
 private:
   IDXGIAdapter1 *GetDXGIAdapter();
 
   void DisableD3D11AfterCrash();
 
   void AttemptD3D11DeviceCreation(mozilla::gfx::FeatureState& d3d11);
-  bool AttemptD3D11DeviceCreationHelper(
+  bool AttemptD3D11DeviceCreationHelperInner(
       IDXGIAdapter1* aAdapter,
+      bool aAttemptVideoSupport,
       RefPtr<ID3D11Device>& aOutDevice,
       HRESULT& aResOut);
+  bool AttemptD3D11DeviceCreationHelper(
+      mozilla::gfx::FeatureState& aD3d11,
+      IDXGIAdapter1* aAdapter,
+      bool aAttemptVideoSupport,
+      RefPtr<ID3D11Device>& aOutDevice);
 
   void AttemptWARPDeviceCreation();
   bool AttemptWARPDeviceCreationHelper(
       mozilla::ScopedGfxFeatureReporter& aReporterWARP,
       RefPtr<ID3D11Device>& aOutDevice,
       HRESULT& aResOut);
 
   mozilla::gfx::FeatureStatus AttemptD3D11ContentDeviceCreation();
@@ -95,16 +101,18 @@ private:
 private:
   static StaticAutoPtr<DeviceManagerD3D11> sInstance;
 
   mozilla::Mutex mDeviceLock;
   nsTArray<D3D_FEATURE_LEVEL> mFeatureLevels;
   RefPtr<IDXGIAdapter1> mAdapter;
   RefPtr<ID3D11Device> mCompositorDevice;
   RefPtr<ID3D11Device> mContentDevice;
+  RefPtr<ID3D11Device> mDecoderDevice;
   mozilla::Atomic<bool> mIsWARP;
   mozilla::Atomic<bool> mTextureSharingWorks;
+  bool mCompositorDeviceSupportsVideo;
 };
 
 } // namespace gfx
 } // namespace mozilla
 
 #endif // mozilla_gfx_thebes_DeviceManagerD3D11_h