Replace gfxWindowsPlatform::mD2D1Status with gfxConfig. (bug 1254899 part 10, r=milan)
☠☠ backed out by df82a3088812 ☠ ☠
authorDavid Anderson <danderson@mozilla.com>
Wed, 27 Apr 2016 22:54:26 -0700
changeset 357321 b5ab83af342ced09135b9e743a594422856f3ac9
parent 357320 993906e53329b6eb88b3f0a26507cdae0ae17be0
child 357322 1d7eeee5a5c559166c166e726863ab3e73f78e9f
push id16755
push useryura.zenevich@gmail.com
push dateThu, 28 Apr 2016 15:12:20 +0000
reviewersmilan
bugs1254899
milestone49.0a1
Replace gfxWindowsPlatform::mD2D1Status with gfxConfig. (bug 1254899 part 10, r=milan)
gfx/config/gfxConfig.cpp
gfx/config/gfxConfig.h
gfx/config/gfxFeature.cpp
gfx/config/gfxFeature.h
gfx/thebes/gfxPrefs.h
gfx/thebes/gfxWindowsPlatform.cpp
gfx/thebes/gfxWindowsPlatform.h
widget/windows/GfxInfo.cpp
--- a/gfx/config/gfxConfig.cpp
+++ b/gfx/config/gfxConfig.cpp
@@ -65,16 +65,26 @@ gfxConfig::DisableByDefault(Feature aFea
 
 /* static */ void
 gfxConfig::EnableByDefault(Feature aFeature)
 {
   FeatureState& state = sConfig.GetState(aFeature);
   state.EnableByDefault();
 }
 
+/* static */ void
+gfxConfig::SetDefaultFromPref(Feature aFeature,
+                              const char* aPrefName,
+                              bool aIsEnablePref,
+                              bool aDefaultValue)
+{
+  FeatureState& state = sConfig.GetState(aFeature);
+  return state.SetDefaultFromPref(aPrefName, aIsEnablePref, aDefaultValue);
+}
+
 /* static */ bool
 gfxConfig::InitOrUpdate(Feature aFeature,
                         bool aEnable,
                         FeatureStatus aDisableStatus,
                         const char* aDisableMessage)
 {
   FeatureState& state = sConfig.GetState(aFeature);
   return state.InitOrUpdate(aEnable, aDisableStatus, aDisableMessage);
--- a/gfx/config/gfxConfig.h
+++ b/gfx/config/gfxConfig.h
@@ -40,18 +40,18 @@ public:
 
   // Query the history of a parameter. ForcedOnByUser returns whether or not
   // the user specifically used a "force" preference to enable the parameter.
   // IsDisabledByDefault returns whether or not the initial status of the
   // feature, before adding user prefs and runtime decisions, was disabled.
   static bool IsForcedOnByUser(Feature aFeature);
   static bool IsDisabledByDefault(Feature aFeature);
 
-  // Query the raw computed status value of a parameter. This is computed
-  // similar to IsEnabled:
+  // Query the status value of a parameter. This is computed similar to
+  // IsEnabled:
   //
   //  1. If a runtime failure was set, return it.
   //  2. If the user force-enabled the feature, return ForceEnabled.
   //  3. If an environment status was set, return it.
   //  4. If a user status was set, return it.
   //  5. Return the default status.
   static FeatureStatus GetValue(Feature aFeature);
 
@@ -69,16 +69,24 @@ public:
   // statuses; this should be used to disable features based on system
   // or hardware problems that can be determined up-front. The only
   // status that can override this decision is the user force-enabling
   // the feature.
   static void Disable(Feature aFeature,
                       FeatureStatus aStatus,
                       const char* aMessage);
 
+  // Given a preference name, infer the default value and whether or not the
+  // user has changed it. |aIsEnablePref| specifies whether or not the pref
+  // is intended to enable a feature (true), or disable it (false).
+  static void SetDefaultFromPref(Feature aFeature,
+                                 const char* aPrefName,
+                                 bool aIsEnablePref,
+                                 bool aDefaultValue);
+
   // Disable a parameter based on a runtime decision. This permanently
   // disables the feature, since runtime decisions override all other
   // decisions.
   static void SetFailed(Feature aFeature,
                         FeatureStatus aStatus,
                         const char* aMessage);
 
   // Force a feature to be disabled permanently. This is the same as
--- a/gfx/config/gfxFeature.cpp
+++ b/gfx/config/gfxFeature.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* vim: set sts=2 ts=8 sw=2 tw=99 et: */
 /* 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 "mozilla/Preferences.h"
+#include "prprf.h"
 #include "gfxFeature.h"
-#include "prprf.h"
 
 namespace mozilla {
 namespace gfx {
 
 bool
 FeatureState::IsEnabled() const
 {
   return IsFeatureStatusSuccess(GetValue());
@@ -43,16 +44,34 @@ FeatureState::SetDefault(bool aEnable,
   if (!aEnable) {
     DisableByDefault(aDisableStatus, aDisableMessage);
     return false;
   }
   EnableByDefault();
   return true;
 }
 
+void
+FeatureState::SetDefaultFromPref(const char* aPrefName,
+                                 bool aIsEnablePref,
+                                 bool aDefaultValue)
+{
+  bool baseValue = Preferences::GetDefaultBool(aPrefName, aDefaultValue);
+  SetDefault(baseValue == aIsEnablePref, FeatureStatus::Disabled, "Disabled by default");
+
+  if (Preferences::HasUserValue(aPrefName)) {
+    bool userValue = Preferences::GetBool(aPrefName, aDefaultValue);
+    if (userValue == aIsEnablePref) {
+      UserEnable("Enabled by user preference");
+    } else {
+      UserDisable("Disabled by user preference");
+    }
+  }
+}
+
 bool
 FeatureState::InitOrUpdate(bool aEnable,
                            FeatureStatus aDisableStatus,
                            const char* aDisableMessage)
 {
   if (!IsInitialized()) {
     return SetDefault(aEnable, aDisableStatus, aDisableMessage);
   }
--- a/gfx/config/gfxFeature.h
+++ b/gfx/config/gfxFeature.h
@@ -12,16 +12,17 @@
 
 namespace mozilla {
 namespace gfx {
 
 #define GFX_FEATURE_MAP(_)                                                        \
   /* Name,                        Type,         Description */                    \
   _(HW_COMPOSITING,               Feature,      "Compositing")                    \
   _(D3D11_COMPOSITING,            Feature,      "Direct3D11 Compositing")         \
+  _(DIRECT2D,                     Feature,      "Direct2D")                       \
   /* Add new entries above this comment */
 
 enum class Feature : uint32_t {
 #define MAKE_ENUM(name, type, desc) name,
   GFX_FEATURE_MAP(MAKE_ENUM)
 #undef MAKE_ENUM
   NumValues
 };
@@ -32,20 +33,22 @@ class FeatureState
 
  public:
   bool IsEnabled() const;
   FeatureStatus GetValue() const;
 
   void EnableByDefault();
   void DisableByDefault(FeatureStatus aStatus, const char* aMessage);
   bool SetDefault(bool aEnable, FeatureStatus aDisableStatus, const char* aDisableMessage);
-
   bool InitOrUpdate(bool aEnable,
                     FeatureStatus aDisableStatus,
                     const char* aMessage);
+  void SetDefaultFromPref(const char* aPrefName,
+                          bool aIsEnablePref,
+                          bool aDefaultValue);
   void UserEnable(const char* aMessage);
   void UserForceEnable(const char* aMessage);
   void UserDisable(const char* aMessage);
   void Disable(FeatureStatus aStatus, const char* aMessage);
   void ForceDisable(FeatureStatus aStatus, const char* aMessage) {
     SetFailed(aStatus, aMessage);
   }
   void SetFailed(FeatureStatus aStatus, const char* aMessage);
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -66,16 +66,18 @@ private:                                
 static const char* Get##Name##PrefName() { return Pref; }                     \
 static Type Get##Name##PrefDefault() { return Default; }                      \
 PrefTemplate<UpdatePolicy::Update, Type, Get##Name##PrefDefault, Get##Name##PrefName> mPref##Name
 
 class PreferenceAccessImpl;
 class gfxPrefs;
 class gfxPrefs final
 {
+  friend class gfxWindowsPlatform;
+
 private:
   /// See Logging.h.  This lets Moz2D access preference values it owns.
   PreferenceAccessImpl* mMoz2DPrefAccess;
 
 private:
   // Enums for the update policy.
   enum class UpdatePolicy {
     Skip, // Set the value to default, skip any Preferences calls
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -360,17 +360,16 @@ NS_IMPL_ISUPPORTS(D3D9SharedTextureRepor
 
 gfxWindowsPlatform::gfxWindowsPlatform()
   : mRenderMode(RENDER_GDI)
   , mDeviceLock("gfxWindowsPlatform.mDeviceLock")
   , mIsWARP(false)
   , mHasDeviceReset(false)
   , mHasFakeDeviceReset(false)
   , mCompositorD3D11TextureSharingWorks(false)
-  , mD2D1Status(FeatureStatus::Unused)
   , mHasD3D9DeviceReset(false)
 {
   mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
   mUseClearTypeAlways = UNINITIALIZED_VALUE;
 
   /* 
    * Initialize COM 
    */ 
@@ -495,17 +494,17 @@ gfxWindowsPlatform::HandleDeviceReset()
 static const BackendType SOFTWARE_BACKEND = BackendType::CAIRO;
 
 void
 gfxWindowsPlatform::UpdateBackendPrefs()
 {
   uint32_t canvasMask = BackendTypeBit(SOFTWARE_BACKEND);
   uint32_t contentMask = BackendTypeBit(SOFTWARE_BACKEND);
   BackendType defaultBackend = SOFTWARE_BACKEND;
-  if (GetD2D1Status() == FeatureStatus::Available) {
+  if (gfxConfig::IsEnabled(Feature::DIRECT2D)) {
     contentMask |= BackendTypeBit(BackendType::DIRECT2D1_1);
     canvasMask |= BackendTypeBit(BackendType::DIRECT2D1_1);
     defaultBackend = BackendType::DIRECT2D1_1;
   } else {
     canvasMask |= BackendTypeBit(BackendType::SKIA);
   }
   contentMask |= BackendTypeBit(BackendType::SKIA);
   InitBackendPrefs(canvasMask, defaultBackend, contentMask, defaultBackend);
@@ -527,17 +526,17 @@ gfxWindowsPlatform::UpdateRenderMode()
   if (didReset) {
     mScreenReferenceDrawTarget =
       CreateOffscreenContentDrawTarget(IntSize(1, 1), SurfaceFormat::B8G8R8A8);
     if (!mScreenReferenceDrawTarget) {
       gfxCriticalNote << "Failed to update reference draw target after device reset"
                       << ", D3D11 device:" << hexa(Factory::GetDirect3D11Device())
                       << ", D3D11 status:" << FeatureStatusToString(gfxConfig::GetValue(Feature::D3D11_COMPOSITING))
                       << ", D2D1 device:" << hexa(Factory::GetD2D1Device())
-                      << ", D2D1 status:" << FeatureStatusToString(GetD2D1Status())
+                      << ", D2D1 status:" << FeatureStatusToString(gfxConfig::GetValue(Feature::DIRECT2D))
                       << ", content:" << int(GetDefaultContentBackend())
                       << ", compositor:" << int(GetCompositorBackend());
       MOZ_CRASH("GFX: Failed to update reference draw target after device reset");
     }
   }
 }
 
 void
@@ -571,17 +570,17 @@ gfxWindowsPlatform::CreatePlatformFontLi
         pfl = new gfxDWriteFontList();
         if (NS_SUCCEEDED(pfl->InitFontList())) {
             return pfl;
         }
         // DWrite font initialization failed! Don't know why this would happen,
         // but apparently it can - see bug 594865.
         // So we're going to fall back to GDI fonts & rendering.
         gfxPlatformFontList::Shutdown();
-        DisableD2D();
+        DisableD2D(FeatureStatus::Failed, "Failed to initialize fonts");
     }
 
     pfl = new gfxGDIFontList();
 
     if (NS_SUCCEEDED(pfl->InitFontList())) {
         return pfl;
     }
 
@@ -591,19 +590,19 @@ gfxWindowsPlatform::CreatePlatformFontLi
 
 // This function will permanently disable D2D for the session. It's intended to
 // be used when, after initially chosing to use Direct2D, we encounter a
 // scenario we can't support.
 //
 // This is called during gfxPlatform::Init() so at this point there should be no
 // DrawTargetD2D/1 instances.
 void
-gfxWindowsPlatform::DisableD2D()
+gfxWindowsPlatform::DisableD2D(FeatureStatus aStatus, const char* aMessage)
 {
-  mD2D1Status = FeatureStatus::Failed;
+  gfxConfig::SetFailed(Feature::DIRECT2D, aStatus, aMessage);
   Factory::SetDirect3D11Device(nullptr);
   UpdateBackendPrefs();
 }
 
 already_AddRefed<gfxASurface>
 gfxWindowsPlatform::CreateOffscreenSurface(const IntSize& aSize,
                                            gfxImageFormat aFormat)
 {
@@ -1938,20 +1937,22 @@ IsWARPStable()
   }
   return true;
 }
 
 void
 gfxWindowsPlatform::InitializeConfig()
 {
   if (!XRE_IsParentProcess()) {
+    // Child processes init their configuration via UpdateDeviceInitData().
     return;
   }
 
   InitializeD3D11Config();
+  InitializeD2DConfig();
 }
 
 void
 gfxWindowsPlatform::InitializeD3D11Config()
 {
   MOZ_ASSERT(XRE_IsParentProcess());
 
   FeatureState& d3d11 = gfxConfig::GetFeature(Feature::D3D11_COMPOSITING);
@@ -1999,16 +2000,22 @@ gfxWindowsPlatform::UpdateDeviceInitData
                               FeatureStatus::Disabled,
                               "Disabled by parent process"))
   {
     if (GetParentDevicePrefs().useD3D11WARP()) {
       gfxConfig::EnableFallback(Fallback::USE_D3D11_WARP_COMPOSITOR, "Requested by parent process");
     }
   }
 
+  gfxConfig::InitOrUpdate(
+    Feature::DIRECT2D,
+    GetParentDevicePrefs().useD2D1(),
+    FeatureStatus::Disabled,
+    "Disabled by parent process");
+
   return true;
 }
 
 // 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 InitializeD3D11.
 decltype(D3D11CreateDevice)* sD3D11CreateDeviceFn = nullptr;
 
@@ -2288,48 +2295,52 @@ gfxWindowsPlatform::InitializeDevices()
 {
   // Ask the parent process for an updated list of which devices to create.
   UpdateDeviceInitData();
 
   // If acceleration is disabled, we refuse to initialize anything.
   FeatureStatus compositing = gfxConfig::GetValue(Feature::HW_COMPOSITING);
   if (IsFeatureStatusFailure(compositing)) {
     gfxConfig::DisableByDefault(Feature::D3D11_COMPOSITING, compositing, "Hardware compositing is disabled");
+    gfxConfig::DisableByDefault(Feature::DIRECT2D, compositing, "Hardware compositing is disabled");
     return;
   }
 
   MOZ_ASSERT(!InSafeMode());
 
   // If we previously crashed initializing devices, bail out now.
   D3D11LayersCrashGuard detectCrashes;
   if (detectCrashes.Crashed()) {
     gfxConfig::SetFailed(Feature::HW_COMPOSITING,
                          FeatureStatus::CrashedOnStartup,
                          "Crashed during startup in a previous session");
     gfxConfig::SetFailed(Feature::D3D11_COMPOSITING,
                          FeatureStatus::CrashedOnStartup,
                          "Harware acceleration crashed during startup in a previous session");
+    gfxConfig::SetFailed(Feature::DIRECT2D,
+                         FeatureStatus::CrashedOnStartup,
+                         "Harware acceleration crashed during startup in a previous session");
     return;
   }
 
   // First, initialize D3D11. If this succeeds we attempt to use Direct2D.
   InitializeD3D11();
-
-  // Initialize Direct2D.
-  if (gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) {
-    InitializeD2D();
-  }
-
-  // Usually we want D2D in order to use DWrite, but if the users have it
-  // forced, we'll let them have it, as unsupported configuration.
-  if (gfxPrefs::DirectWriteFontRenderingForceEnabled() &&
-      IsFeatureStatusFailure(mD2D1Status) &&
-      !mDWriteFactory) {
-    gfxCriticalNote << "Attempting DWrite without D2D support";
-    InitDWriteSupport();
+  InitializeD2D();
+
+  if (!gfxConfig::IsEnabled(Feature::DIRECT2D)) {
+    if (XRE_IsContentProcess() && GetParentDevicePrefs().useD2D1()) {
+      RecordContentDeviceFailure(TelemetryDeviceCode::D2D1);
+    }
+
+    // Usually we want D2D in order to use DWrite, but if the users have it
+    // forced, we'll let them have it, as unsupported configuration.
+    if (gfxPrefs::DirectWriteFontRenderingForceEnabled() && !mDWriteFactory) {
+      gfxCriticalNote << "Attempting DWrite without D2D support";
+      InitDWriteSupport();
+    }
   }
 }
 
 bool
 gfxWindowsPlatform::CanUseD3D11ImageBridge()
 {
   if (XRE_IsContentProcess()) {
     if (!GetParentDevicePrefs().useD3D11ImageBridge()) {
@@ -2462,102 +2473,88 @@ IsD2DBlacklisted()
       if (status != nsIGfxInfo::FEATURE_STATUS_OK) {
         return true;
       }
     }
   }
   return false;
 }
 
-// Check whether we can support Direct2D. Although some of these checks will
-// not change after a TDR (like the OS version), we could find a driver change
-// that runs us into the blacklist.
-FeatureStatus
-gfxWindowsPlatform::CheckD2D1Support()
+void
+gfxWindowsPlatform::InitializeD2DConfig()
 {
-  // Don't revive D2D1 support after a failure.
-  if (IsFeatureStatusFailure(mD2D1Status)) {
-    return mD2D1Status;
-  }
-
-  if (!gfxPrefs::Direct2DForceEnabled() && IsD2DBlacklisted()) {
-    return FeatureStatus::Blacklisted;
-  }
-
-  // Do not ever try to use D2D if it's explicitly disabled.
-  if (gfxPrefs::Direct2DDisabled()) {
-    return FeatureStatus::Disabled;
+  FeatureState& d2d1 = gfxConfig::GetFeature(Feature::DIRECT2D);
+
+  if (!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) {
+    d2d1.DisableByDefault(FeatureStatus::Unavailable, "Direct2D requires Direct3D 11 compositing");
+  } else if (!IsVistaOrLater()) {
+    d2d1.DisableByDefault(FeatureStatus::Unavailable, "Direct2D is not available on Windows XP");
+  } else {
+    d2d1.SetDefaultFromPref(
+      gfxPrefs::GetDirect2DDisabledPrefName(),
+      false,
+      gfxPrefs::GetDirect2DDisabledPrefDefault());
   }
-
-  // Direct2D is only Vista or higher, but we require a D3D11 compositor to
-  // use it. (This check may be implied by the fact that we do not get here
-  // without a D3D11 compositor device.)
-  if (!IsVistaOrLater()) {
-    return FeatureStatus::Unavailable;
-  }
-
-  // Normally we don't use D2D content drawing when using WARP. However if
-  // WARP is force-enabled, we will let Direct2D use WARP as well.
-  if (mIsWARP && !gfxPrefs::LayersD3D11ForceWARP()) {
-    return FeatureStatus::Blocked;
+  
+  if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_DIRECT2D)) {
+    d2d1.Disable(FeatureStatus::Blacklisted, "Direct2D is blacklisted on this hardware");
   }
 
-  if (!Factory::SupportsD2D1()) {
-    return FeatureStatus::Unavailable;
+  if (!d2d1.IsEnabled() && gfxPrefs::Direct2DForceEnabled()) {
+    d2d1.UserForceEnable("Force-enabled via user-preference");
   }
-
-  if (XRE_IsContentProcess()) {
-    return GetParentDevicePrefs().useD2D1()
-           ? FeatureStatus::Available
-           : FeatureStatus::Blocked;
-  }
-
-  return FeatureStatus::Available;
 }
 
 void
 gfxWindowsPlatform::InitializeD2D()
 {
   ScopedGfxFeatureReporter d2d1_1("D2D1.1");
 
-  mD2D1Status = CheckD2D1Support();
-  if (IsFeatureStatusFailure(mD2D1Status)) {
-    if (XRE_IsContentProcess() && GetParentDevicePrefs().useD2D1()) {
-      RecordContentDeviceFailure(TelemetryDeviceCode::D2D1);
-    }
+  FeatureState& d2d1 = gfxConfig::GetFeature(Feature::DIRECT2D);
+
+  // We don't know this value ahead of time, but the user can force-override
+  // it, so we use Disable instead of SetFailed.
+  if (mIsWARP) {
+    d2d1.Disable(FeatureStatus::Blocked, "Direct2D is not compatible with Direct3D11 WARP");
+  }
+
+  // If we pass all the initial checks, we can proceed to runtime decisions.
+  if (!d2d1.IsEnabled()) {
     return;
   }
 
-  // If we don't have a content device, don't init
-  // anything else below such as dwrite
+  if (!Factory::SupportsD2D1()) {
+    d2d1.SetFailed(FeatureStatus::Unavailable, "Failed to acquire a Direct2D 1.1 factory");
+    return;
+  }
+
   if (!mD3D11ContentDevice) {
-    mD2D1Status = FeatureStatus::Failed;
+    d2d1.SetFailed(FeatureStatus::Failed, "Failed to acquire a Direct3D 11 content device");
     return;
   }
 
   if (!mCompositorD3D11TextureSharingWorks) {
-    mD2D1Status = FeatureStatus::Failed;
+    d2d1.SetFailed(FeatureStatus::Failed, "Direct3D11 device does not support texture sharing");
     return;
   }
 
   // Using Direct2D depends on DWrite support.
   if (!mDWriteFactory && !InitDWriteSupport()) {
-    mD2D1Status = FeatureStatus::Failed;
+    d2d1.SetFailed(FeatureStatus::Failed, "Failed to initialize DirectWrite support");
     return;
   }
 
   // Verify that Direct2D device creation succeeded.
   if (!Factory::SetDirect3D11Device(mD3D11ContentDevice)) {
-    mD2D1Status = FeatureStatus::Failed;
+    d2d1.SetFailed(FeatureStatus::Failed, "Failed to create a Direct2D device");
     return;
   }
 
+  MOZ_ASSERT(d2d1.IsEnabled());
   d2d1_1.SetSuccessful();
-
-  mD2D1Status = FeatureStatus::Available;
 }
 
 bool
 gfxWindowsPlatform::CreateD3D11DecoderDeviceHelper(
   IDXGIAdapter1* aAdapter, RefPtr<ID3D11Device>& aDevice, HRESULT& aResOut)
 {
   MOZ_SEH_TRY{
     aResOut =
@@ -2911,27 +2908,16 @@ gfxWindowsPlatform::GetAcceleratedCompos
     if (gfxPlatform::CanUseDirect3D9()) {
       aBackends.AppendElement(LayersBackend::LAYERS_D3D9);
     } else {
       NS_WARNING("Direct3D 9-accelerated layers are not supported on this system.");
     }
   }
 }
 
-// Some features are dependent on other features. If this is the case, we
-// try to propagate the status of the parent feature if it wasn't available.
-FeatureStatus
-gfxWindowsPlatform::GetD2D1Status() const
-{
-  if (!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) {
-    return FeatureStatus::Unavailable;
-  }
-  return mD2D1Status;
-}
-
 unsigned
 gfxWindowsPlatform::GetD3D11Version()
 {
   RefPtr<ID3D11Device> device;
   if (!GetD3D11Device(&device)) {
     return 0;
   }
   return device->GetFeatureLevel();
@@ -2949,17 +2935,17 @@ gfxWindowsPlatform::GetDeviceInitData(De
   if (!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) {
     return;
   }
 
   aOut->useD3D11() = true;
   aOut->useD3D11ImageBridge() = !!mD3D11ImageBridgeDevice;
   aOut->d3d11TextureSharingWorks() = mCompositorD3D11TextureSharingWorks;
   aOut->useD3D11WARP() = mIsWARP;
-  aOut->useD2D1() = (GetD2D1Status() == FeatureStatus::Available);
+  aOut->useD2D1() = gfxConfig::IsEnabled(Feature::DIRECT2D);
 
   if (mD3D11Device) {
     DXGI_ADAPTER_DESC desc;
     if (!GetDxgiDesc(mD3D11Device, &desc)) {
       return;
     }
     aOut->adapter() = DxgiAdapterDesc::From(desc);
   }
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -239,20 +239,16 @@ public:
     }
     bool SupportsApzTouchInput() const override;
 
     // Recreate devices as needed for a device reset. Returns true if a device
     // reset occurred.
     bool HandleDeviceReset();
     void UpdateBackendPrefs();
 
-    // Return the diagnostic status of DirectX initialization. If
-    // initialization has not been attempted, this returns
-    // FeatureStatus::Unused.
-    mozilla::gfx::FeatureStatus GetD2D1Status() const;
     unsigned GetD3D11Version();
 
     void TestDeviceReset(DeviceResetReason aReason);
 
     virtual already_AddRefed<mozilla::gfx::VsyncSource> CreateHardwareVsyncSource() override;
     static mozilla::Atomic<size_t> sD3D11MemoryUsed;
     static mozilla::Atomic<size_t> sD3D9MemoryUsed;
     static mozilla::Atomic<size_t> sD3D9SharedTextureUsed;
@@ -282,21 +278,21 @@ private:
     void Init();
     void InitAcceleration() override;
 
     void InitializeDevices();
     void InitializeD3D11();
     void InitializeD2D();
     bool InitDWriteSupport();
 
-    void DisableD2D();
+    void DisableD2D(mozilla::gfx::FeatureStatus aStatus, const char* aMessage);
 
     void InitializeConfig();
     void InitializeD3D11Config();
-    mozilla::gfx::FeatureStatus CheckD2D1Support();
+    void InitializeD2DConfig();
 
     void AttemptD3D11DeviceCreation(mozilla::gfx::FeatureState& d3d11);
     bool AttemptD3D11DeviceCreationHelper(
         IDXGIAdapter1* aAdapter,
         RefPtr<ID3D11Device>& aOutDevice,
         HRESULT& aResOut);
 
     void AttemptWARPDeviceCreation();
@@ -337,16 +333,12 @@ private:
     bool mHasDeviceReset;
     bool mHasFakeDeviceReset;
     bool mCompositorD3D11TextureSharingWorks;
     mozilla::Atomic<bool> mHasD3D9DeviceReset;
     DeviceResetReason mDeviceResetReason;
 
     RefPtr<mozilla::layers::ReadbackManagerD3D11> mD3D11ReadbackManager;
 
-    // These should not be accessed directly. Use the Get[Feature]Status
-    // accessors instead.
-    mozilla::gfx::FeatureStatus mD2D1Status;
-
     nsTArray<D3D_FEATURE_LEVEL> mFeatureLevels;
 };
 
 #endif /* GFX_WINDOWS_PLATFORM_H */
--- a/widget/windows/GfxInfo.cpp
+++ b/widget/windows/GfxInfo.cpp
@@ -1284,17 +1284,17 @@ GfxInfo::DescribeFeatures(JSContext* aCx
         blacklisted = (status != nsIGfxInfo::FEATURE_STATUS_OK);
       }
     }
 
     val = JS::BooleanValue(blacklisted);
     JS_SetProperty(aCx, obj, "blacklisted", val);
   }
 
-  gfx::FeatureStatus d2d = platform->GetD2D1Status();
+  gfx::FeatureStatus d2d = gfxConfig::GetValue(Feature::DIRECT2D);
   if (!InitFeatureObject(aCx, aObj, "d2d", d2d, &obj)) {
     return;
   }
   {
     const char* version = "1.1";
     JS::Rooted<JSString*> str(aCx, JS_NewStringCopyZ(aCx, version));
     JS::Rooted<JS::Value> val(aCx, JS::StringValue(str));
     JS_SetProperty(aCx, obj, "version", val);