Remove D3D11Status flag in favor of FeatureStatus. (bug 1183910 part 3, r=mattwoodrow)
authorDavid Anderson <danderson@mozilla.com>
Thu, 30 Jul 2015 00:24:56 -0700
changeset 287089 e590bfd26a09ef153d681eaafcfb285006b4305e
parent 287088 1199933ae78ca2294d7e19015d566b23bc8e52b2
child 287090 925d26f0ad697bd0b08909b0b207e85f574b65e9
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1183910
milestone42.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
Remove D3D11Status flag in favor of FeatureStatus. (bug 1183910 part 3, r=mattwoodrow)
gfx/src/gfxTelemetry.cpp
gfx/src/gfxTelemetry.h
gfx/thebes/gfxWindowsPlatform.cpp
gfx/thebes/gfxWindowsPlatform.h
--- a/gfx/src/gfxTelemetry.cpp
+++ b/gfx/src/gfxTelemetry.cpp
@@ -27,10 +27,17 @@ FeatureStatusToString(FeatureStatus aSta
     case FeatureStatus::Available:
       return "available";
     default:
       MOZ_ASSERT_UNREACHABLE("missing status case");
       return "unknown";
   }
 }
 
+bool
+IsFeatureStatusFailure(FeatureStatus aStatus)
+{
+  return aStatus != FeatureStatus::Unused &&
+         aStatus != FeatureStatus::Available;
+}
+
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/src/gfxTelemetry.h
+++ b/gfx/src/gfxTelemetry.h
@@ -34,13 +34,14 @@ enum class FeatureStatus
   // This feature was explicitly disabled by the user.
   Disabled,
 
   // This feature is available for use.
   Available
 };
 
 const char* FeatureStatusToString(FeatureStatus aStatus);
+bool IsFeatureStatusFailure(FeatureStatus aStatus);
 
 } // namespace gfx
 } // namespace mozilla
 
 #endif // gfx_src_gfxTelemetry_h__
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -1906,45 +1906,50 @@ CanUseWARP()
       gfxPrefs::LayersD3D11DisableWARP() ||
       GetModuleHandleA("nvdxgiwrap.dll"))
   {
     return false;
   }
   return true;
 }
 
-auto
-gfxWindowsPlatform::CheckD3D11Support() -> D3D11Status
+FeatureStatus
+gfxWindowsPlatform::CheckD3D11Support(bool* aCanUseHardware)
 {
   if (gfxPrefs::LayersD3D11ForceWARP()) {
-    return D3D11Status::OnlyWARP;
+    *aCanUseHardware = false;
+    return FeatureStatus::Available;
   }
+
   if (nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo()) {
     int32_t status;
     if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS, &status))) {
       if (status != nsIGfxInfo::FEATURE_STATUS_OK) {
-        if (!CanUseWARP()) {
-          return D3D11Status::Blocked;
+        if (CanUseWARP()) {
+          *aCanUseHardware = false;
+          return FeatureStatus::Available;
         }
-        return D3D11Status::OnlyWARP;
+        return FeatureStatus::Blacklisted;
       }
     }
   }
-  if (!GetDXGIAdapter()) {
-    return D3D11Status::OnlyWARP;
+
+  // If we've used WARP once, we continue to use it after device resets.
+  if (!GetDXGIAdapter() || mIsWARP) {
+    *aCanUseHardware = false;
   }
-  return D3D11Status::Ok;
+  return FeatureStatus::Available;
 }
 
 // We don't have access to the D3D11CreateDevice type in gfxWindowsPlatform.h,
 // since it doesn't include d3d11.h, so we use a static here. It should only
-// be used within InitD3D11Devices.
+// be used within InitializeD3D11.
 decltype(D3D11CreateDevice)* sD3D11CreateDeviceFn = nullptr;
 
-bool
+void
 gfxWindowsPlatform::AttemptD3D11DeviceCreation()
 {
   RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter();
   MOZ_ASSERT(adapter);
 
   HRESULT hr = E_INVALIDARG;
   MOZ_SEH_TRY {
     hr =
@@ -1952,38 +1957,37 @@ gfxWindowsPlatform::AttemptD3D11DeviceCr
                            // 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,
                            mFeatureLevels.Elements(), mFeatureLevels.Length(),
                            D3D11_SDK_VERSION, byRef(mD3D11Device), nullptr, nullptr);
   } MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
     gfxCriticalError() << "Crash during D3D11 device creation";
-    return false;
+    return;
   }
 
   if (FAILED(hr) || !DoesD3D11DeviceWork(mD3D11Device)) {
     gfxCriticalError() << "D3D11 device creation failed" << hexa(hr);
-    return false;
+    return;
   }
   if (!mD3D11Device) {
-    return false;
+    return;
   }
 
   CheckIfRenderTargetViewNeedsRecreating(mD3D11Device);
 
   // Only test this when not using WARP since it can fail and cause
   // GetDeviceRemovedReason to return weird values.
   mDoesD3D11TextureSharingWork = ::DoesD3D11TextureSharingWork(mD3D11Device);
   mD3D11Device->SetExceptionMode(0);
   mIsWARP = false;
-  return true;
 }
 
-bool
+void
 gfxWindowsPlatform::AttemptWARPDeviceCreation()
 {
   ScopedGfxFeatureReporter reporterWARP("D3D11-WARP", gfxPrefs::LayersD3D11ForceWARP());
 
   MOZ_SEH_TRY {
     HRESULT hr =
       sD3D11CreateDeviceFn(nullptr, D3D_DRIVER_TYPE_WARP, nullptr,
                            // Use
@@ -1991,34 +1995,33 @@ gfxWindowsPlatform::AttemptWARPDeviceCre
                            // to prevent bug 1092260. IE 11 also uses this flag.
                            D3D11_CREATE_DEVICE_BGRA_SUPPORT,
                            mFeatureLevels.Elements(), mFeatureLevels.Length(),
                            D3D11_SDK_VERSION, byRef(mD3D11Device), nullptr, nullptr);
 
     if (FAILED(hr)) {
       // This should always succeed... in theory.
       gfxCriticalError() << "Failed to initialize WARP D3D11 device! " << hexa(hr);
-      return false;
+      return;
     }
 
     reporterWARP.SetSuccessful();
   } MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
     gfxCriticalError() << "Exception occurred initializing WARP D3D11 device!";
-    return false;
+    return;
 
   }
 
   // Only test for texture sharing on Windows 8 since it puts the device into
   // an unusable state if used on Windows 7
   if (IsWin8OrLater()) {
     mDoesD3D11TextureSharingWork = ::DoesD3D11TextureSharingWork(mD3D11Device);
   }
   mD3D11Device->SetExceptionMode(0);
   mIsWARP = true;
-  return true;
 }
 
 bool
 gfxWindowsPlatform::AttemptD3D11ContentDeviceCreation()
 {
   HRESULT hr = E_INVALIDARG;
   MOZ_SEH_TRY {
     hr =
@@ -2041,40 +2044,39 @@ gfxWindowsPlatform::AttemptD3D11ContentD
   nsRefPtr<ID3D10Multithread> multi;
   mD3D11ContentDevice->QueryInterface(__uuidof(ID3D10Multithread), getter_AddRefs(multi));
   multi->SetMultithreadProtected(TRUE);
 
   Factory::SetDirect3D11Device(mD3D11ContentDevice);
   return true;
 }
 
-bool
+void
 gfxWindowsPlatform::AttemptD3D11ImageBridgeDeviceCreation()
 {
   HRESULT hr = E_INVALIDARG;
   MOZ_SEH_TRY{
     hr =
       sD3D11CreateDeviceFn(GetDXGIAdapter(), D3D_DRIVER_TYPE_UNKNOWN, nullptr,
                            D3D11_CREATE_DEVICE_BGRA_SUPPORT,
                            mFeatureLevels.Elements(), mFeatureLevels.Length(),
                            D3D11_SDK_VERSION, byRef(mD3D11ImageBridgeDevice), nullptr, nullptr);
   } MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
-    return false;
+    return;
   }
 
   if (FAILED(hr)) {
-    return false;
+    return;
   }
 
   mD3D11ImageBridgeDevice->SetExceptionMode(0);
   if (!DoesD3D11AlphaTextureSharingWork(mD3D11ImageBridgeDevice)) {
     mD3D11ImageBridgeDevice = nullptr;
-    return false;
+    return;
   }
-  return true;
 }
 
 void
 gfxWindowsPlatform::InitializeDevices()
 {
   // If we previously crashed initializing devices, or if we're in safe mode,
   // bail out now.
   DriverInitCrashDetection detectCrashes;
@@ -2112,38 +2114,39 @@ gfxWindowsPlatform::InitializeD3D11()
   // This function attempts to initialize our D3D11 devices, if the hardware
   // is not blacklisted for D3D11 layers. This first attempt will try to create
   // a hardware accelerated device. If this creation fails or the hardware is
   // blacklisted, then this function will abort if WARP is disabled, causing us
   // to fallback to D3D9 or Basic layers. If WARP is not disabled it will use
   // a WARP device which should always be available on Windows 7 and higher.
 
   // Check if D3D11 is supported on this hardware.
-  D3D11Status support = CheckD3D11Support();
-  if (support == D3D11Status::Blocked) {
-    mD3D11Status = FeatureStatus::Blacklisted;
+  bool canUseHardware = true;
+  mD3D11Status = CheckD3D11Support(&canUseHardware);
+  if (IsFeatureStatusFailure(mD3D11Status)) {
     return;
   }
 
   // Check if D3D11 is available on this system.
   nsModuleHandle d3d11Module(LoadLibrarySystem32(L"d3d11.dll"));
   sD3D11CreateDeviceFn =
     (decltype(D3D11CreateDevice)*)GetProcAddress(d3d11Module, "D3D11CreateDevice");
   if (!sD3D11CreateDeviceFn) {
     // We should just be on Windows Vista or XP in this case.
     mD3D11Status = FeatureStatus::Unavailable;
     return;
   }
 
-  // If hardware acceleration is allowed, attempt to create a device. If this
-  // fails, we fall back to WARP.
-  if (support == D3D11Status::Ok && !AttemptD3D11DeviceCreation()) {
-    support = D3D11Status::OnlyWARP;
+  // First try to create a hardware accelerated device.
+  if (canUseHardware) {
+    AttemptD3D11DeviceCreation();
   }
-  if (support == D3D11Status::OnlyWARP && CanUseWARP()) {
+
+  // If that failed, see if we can use WARP.
+  if (!mD3D11Device && CanUseWARP()) {
     AttemptWARPDeviceCreation();
   }
 
   if (!mD3D11Device) {
     // Nothing more we can do.
     mD3D11Status = FeatureStatus::Failed;
     return;
   }
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -302,26 +302,20 @@ private:
     void InitializeDevices();
     void InitializeD3D11();
     void InitializeD2D();
     bool InitializeD2D1();
     bool InitDWriteSupport();
 
     void DisableD2D();
 
-    // Used by InitializeD3D11().
-    enum class D3D11Status {
-      Ok,
-      OnlyWARP,
-      Blocked
-    };
-    D3D11Status CheckD3D11Support();
-    bool AttemptD3D11DeviceCreation();
-    bool AttemptWARPDeviceCreation();
-    bool AttemptD3D11ImageBridgeDeviceCreation();
+    mozilla::gfx::FeatureStatus CheckD3D11Support(bool* aCanUseHardware);
+    void AttemptD3D11DeviceCreation();
+    void AttemptWARPDeviceCreation();
+    void AttemptD3D11ImageBridgeDeviceCreation();
     bool AttemptD3D11ContentDeviceCreation();
 
     IDXGIAdapter1 *GetDXGIAdapter();
     bool IsDeviceReset(HRESULT hr, DeviceResetReason* aReason);
 
 #ifdef CAIRO_HAS_DWRITE_FONT
     nsRefPtr<IDWriteFactory> mDWriteFactory;
     nsRefPtr<IDWriteRenderingParams> mRenderingParams[TEXT_RENDERING_COUNT];