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 295171 b5ab83af342ced09135b9e743a594422856f3ac9
parent 295170 993906e53329b6eb88b3f0a26507cdae0ae17be0
child 295172 1d7eeee5a5c559166c166e726863ab3e73f78e9f
push id75834
push userdanderson@mozilla.com
push dateThu, 28 Apr 2016 05:58:25 +0000
treeherdermozilla-inbound@f749ee384012 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmilan
bugs1254899
milestone49.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
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);