Backed out 13 changesets (bug 1254899) for test failure in browser_Troubleshoot.js. r=backout
authorSebastian Hengst <archaeopteryx@coole-files.de>
Thu, 28 Apr 2016 10:32:25 +0200
changeset 334240 df82a308881223ce93397787ef45da2aa960737e
parent 334239 36c2c8a36ad9d6521b54e3867b12fd37be488d05
child 334241 e679ec00049ee55f8b5161dcc9e25b434645f581
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1254899
milestone49.0a1
backs outf749ee384012fcc0f9058a05aca0cddf2e217405
1d7eeee5a5c559166c166e726863ab3e73f78e9f
b5ab83af342ced09135b9e743a594422856f3ac9
993906e53329b6eb88b3f0a26507cdae0ae17be0
e8abac801a515dbaa2210c0a78907b9e8f6301e6
e9c311c68e4aa25901a874471778e1b8b98ed7ea
f8f3ae8c5cefa67f2ce509eac3da32dc23289ebd
d17f98a9918a4a5e69566abf73702d8adf59151d
21c8a7ea2b93d6f61b0ad57fc9603c41b926a444
64e58f9625ebb834fb232f01311bf4e17252ca6c
2de214d5d1e098230aa00d80813615104a27f067
f2056259d227bb92c7712e84f61c90f65d502fba
b805df0c8296d6bf85d88e2bd702a790b3bf676d
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
Backed out 13 changesets (bug 1254899) for test failure in browser_Troubleshoot.js. r=backout Backed out changeset f749ee384012 (bug 1254899) Backed out changeset 1d7eeee5a5c5 (bug 1254899) Backed out changeset b5ab83af342c (bug 1254899) Backed out changeset 993906e53329 (bug 1254899) Backed out changeset e8abac801a51 (bug 1254899) Backed out changeset e9c311c68e4a (bug 1254899) Backed out changeset f8f3ae8c5cef (bug 1254899) Backed out changeset d17f98a9918a (bug 1254899) Backed out changeset 21c8a7ea2b93 (bug 1254899) Backed out changeset 64e58f9625eb (bug 1254899) Backed out changeset 2de214d5d1e0 (bug 1254899) Backed out changeset f2056259d227 (bug 1254899) Backed out changeset b805df0c8296 (bug 1254899)
gfx/config/gfxConfig.cpp
gfx/config/gfxConfig.h
gfx/config/gfxFallback.h
gfx/config/gfxFeature.cpp
gfx/config/gfxFeature.h
gfx/config/moz.build
gfx/ipc/GraphicsMessages.ipdlh
gfx/layers/d3d11/CompositorD3D11.cpp
gfx/layers/d3d9/CompositorD3D9.cpp
gfx/layers/opengl/CompositorOGL.cpp
gfx/moz.build
gfx/src/gfxTelemetry.cpp
gfx/src/gfxTelemetry.h
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxPlatform.h
gfx/thebes/gfxPrefs.h
gfx/thebes/gfxWindowsPlatform.cpp
gfx/thebes/gfxWindowsPlatform.h
toolkit/content/aboutSupport.js
toolkit/content/aboutSupport.xhtml
toolkit/locales/en-US/chrome/global/aboutSupport.dtd
toolkit/modules/Troubleshoot.jsm
widget/GfxInfoBase.cpp
widget/GfxInfoBase.h
widget/android/nsWindow.cpp
widget/nsBaseWidget.cpp
widget/nsIGfxInfo.idl
widget/windows/GfxInfo.cpp
widget/windows/nsWindow.cpp
deleted file mode 100644
--- a/gfx/config/gfxConfig.cpp
+++ /dev/null
@@ -1,223 +0,0 @@
-/* -*- 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 "gfxConfig.h"
-#include "plstr.h"
-
-namespace mozilla {
-namespace gfx {
-
-static gfxConfig sConfig;
-
-/* static */ FeatureState&
-gfxConfig::GetFeature(Feature aFeature)
-{
-  return sConfig.GetState(aFeature);
-}
-
-/* static */ bool
-gfxConfig::IsEnabled(Feature aFeature)
-{
-  const FeatureState& state = sConfig.GetState(aFeature);
-  return state.IsEnabled();
-}
-
-/* static */ bool
-gfxConfig::IsDisabledByDefault(Feature aFeature)
-{
-  const FeatureState& state = sConfig.GetState(aFeature);
-  return state.DisabledByDefault();
-}
-
-/* static */ bool
-gfxConfig::IsForcedOnByUser(Feature aFeature)
-{
-  const FeatureState& state = sConfig.GetState(aFeature);
-  return state.IsForcedOnByUser();
-}
-
-/* static */ FeatureStatus
-gfxConfig::GetValue(Feature aFeature)
-{
-  const FeatureState& state = sConfig.GetState(aFeature);
-  return state.GetValue();
-}
-
-/* static */ bool
-gfxConfig::SetDefault(Feature aFeature,
-                      bool aEnable,
-                      FeatureStatus aDisableStatus,
-                      const char* aDisableMessage)
-{
-  FeatureState& state = sConfig.GetState(aFeature);
-  return state.SetDefault(aEnable, aDisableStatus, aDisableMessage);
-}
-
-/* static */ void
-gfxConfig::DisableByDefault(Feature aFeature,
-                            FeatureStatus aDisableStatus,
-                            const char* aDisableMessage)
-{
-  FeatureState& state = sConfig.GetState(aFeature);
-  state.DisableByDefault(aDisableStatus, aDisableMessage);
-}
-
-/* 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);
-}
-
-/* static */ void
-gfxConfig::SetFailed(Feature aFeature, FeatureStatus aStatus, const char* aMessage)
-{
-  FeatureState& state = sConfig.GetState(aFeature);
-  state.SetFailed(aStatus, aMessage);
-}
-
-/* static */ void
-gfxConfig::Disable(Feature aFeature, FeatureStatus aStatus, const char* aMessage)
-{
-  FeatureState& state = sConfig.GetState(aFeature);
-  state.Disable(aStatus, aMessage);
-}
-
-/* static */ void
-gfxConfig::UserEnable(Feature aFeature, const char* aMessage)
-{
-  FeatureState& state = sConfig.GetState(aFeature);
-  state.UserEnable(aMessage);
-}
-
-/* static */ void
-gfxConfig::UserForceEnable(Feature aFeature, const char* aMessage)
-{
-  FeatureState& state = sConfig.GetState(aFeature);
-  state.UserForceEnable(aMessage);
-}
-
-/* static */ void
-gfxConfig::UserDisable(Feature aFeature, const char* aMessage)
-{
-  FeatureState& state = sConfig.GetState(aFeature);
-  state.UserDisable(aMessage);
-}
-
-/* static */ void
-gfxConfig::Reenable(Feature aFeature, Fallback aFallback)
-{
-  FeatureState& state = sConfig.GetState(aFeature);
-  MOZ_ASSERT(IsFeatureStatusFailure(state.GetValue()));
-
-  const char* message = state.GetRuntimeMessage();
-  EnableFallback(aFallback, message);
-  state.SetRuntime(FeatureStatus::Available, nullptr);
-}
-
-/* static */ bool
-gfxConfig::UseFallback(Fallback aFallback)
-{
-  return sConfig.UseFallbackImpl(aFallback);
-}
-
-/* static */ void
-gfxConfig::EnableFallback(Fallback aFallback, const char* aMessage)
-{
-  // Ignore aMessage for now.
-  sConfig.EnableFallbackImpl(aFallback, aMessage);
-}
-
-bool
-gfxConfig::UseFallbackImpl(Fallback aFallback) const
-{
-  return !!(mFallbackBits & (uint64_t(1) << uint64_t(aFallback)));
-}
-
-void
-gfxConfig::EnableFallbackImpl(Fallback aFallback, const char* aMessage)
-{
-  if (!UseFallbackImpl(aFallback)) {
-    MOZ_ASSERT(mNumFallbackLogEntries < kNumFallbacks);
-
-    FallbackLogEntry& entry = mFallbackLog[mNumFallbackLogEntries];
-    mNumFallbackLogEntries++;
-
-    entry.mFallback = aFallback;
-    PL_strncpyz(entry.mMessage, aMessage, sizeof(entry.mMessage));
-  }
-  mFallbackBits |= (uint64_t(1) << uint64_t(aFallback));
-}
-
-struct FeatureInfo {
-  const char* name;
-  const char* description;
-};
-static const FeatureInfo sFeatureInfo[] = {
-#define FOR_EACH_FEATURE(name, type, desc) {#name, desc},
-  GFX_FEATURE_MAP(FOR_EACH_FEATURE)
-#undef FOR_EACH_FEATURE
-  {nullptr, nullptr}
-};
-
-/* static */ void
-gfxConfig::ForEachFeature(const FeatureIterCallback& aCallback)
-{
-  for (size_t i = 0; i < kNumFeatures; i++) {
-    FeatureState& state = GetFeature(static_cast<Feature>(i));
-    if (!state.IsInitialized()) {
-      continue;
-    }
-
-    aCallback(sFeatureInfo[i].name,
-              sFeatureInfo[i].description,
-              state);
-  }
-}
-
-static const char* sFallbackNames[] = {
-#define FOR_EACH_FALLBACK(name) #name,
-  GFX_FALLBACK_MAP(FOR_EACH_FALLBACK)
-#undef FOR_EACH_FALLBACK
-  nullptr
-};
-
-/* static  */ void
-gfxConfig::ForEachFallback(const FallbackIterCallback& aCallback)
-{
-  sConfig.ForEachFallbackImpl(aCallback);
-}
-
-void
-gfxConfig::ForEachFallbackImpl(const FallbackIterCallback& aCallback)
-{
-  for (size_t i = 0; i < mNumFallbackLogEntries; i++) {
-    const FallbackLogEntry& entry = mFallbackLog[i];
-    aCallback(sFallbackNames[size_t(entry.mFallback)], entry.mMessage);
-  }
-}
-
-} // namespace gfx
-} // namespace mozilla
deleted file mode 100644
--- a/gfx/config/gfxConfig.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/* -*- 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/. */
-#ifndef mozilla_gfx_config_gfxConfig_h
-#define mozilla_gfx_config_gfxConfig_h
-
-#include "gfxFeature.h"
-#include "gfxFallback.h"
-#include "mozilla/Assertions.h"
-#include "mozilla/Function.h"
-
-namespace mozilla {
-namespace gfx {
-
-// Manages the history and state of a graphics feature. The flow of a feature
-// is:
-//   - A default value, set by all.js, gfxPrefs, or gfxPlatform.
-//   - A user value, set by an external value or user pref.
-//   - An environment value, determined by system/hardware factors or nsIGfxInfo.
-//   - A runtime value, determined by any failures encountered after enabling
-//     the feature.
-//
-// Each state change for a feature is recorded in this class.
-class gfxConfig
-{
-public:
-  // Return the full state history of a feature.
-  static FeatureState& GetFeature(Feature aFeature);
-
-  // Query whether a parameter is enabled, taking into account any user or
-  // runtime overrides. The algorithm works as follow:
-  //
-  //  1. If a runtime decision disabled the feature, return false.
-  //  2. If the user force-enabled the feature, return true.
-  //  3. If the environment disabled the feature, return false.
-  //  4. If the user specified a decision, return it.
-  //  5. Return the base setting for the feature.
-  static bool IsEnabled(Feature aFeature);
-
-  // 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 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);
-
-  // Initialize the base value of a parameter. The return value is aEnable.
-  static bool SetDefault(Feature aFeature,
-                         bool aEnable,
-                         FeatureStatus aDisableStatus,
-                         const char* aDisableMessage);
-  static void DisableByDefault(Feature aFeature,
-                               FeatureStatus aDisableStatus,
-                               const char* aDisableMessage);
-  static void EnableByDefault(Feature aFeature);
-
-  // Set a environment status that overrides both the default and user
-  // 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
-  // SetFailed(), but the name may be clearer depending on the context.
-  static void ForceDisable(Feature aFeature,
-                           FeatureStatus aStatus,
-                           const char* aMessage)
-  {
-    SetFailed(aFeature, aStatus, aMessage);
-  }
-
-  // Convenience helpers for SetFailed().
-  static bool MaybeSetFailed(Feature aFeature,
-                             bool aEnable,
-                             FeatureStatus aDisableStatus,
-                             const char* aDisableMessage)
-  {
-    if (!aEnable) {
-      SetFailed(aFeature, aDisableStatus, aDisableMessage);
-      return false;
-    }
-    return true;
-  }
-
-  // Convenience helper for SetFailed().
-  static bool MaybeSetFailed(Feature aFeature,
-                             FeatureStatus aStatus,
-                             const char* aDisableMessage)
-  {
-    return MaybeSetFailed(
-      aFeature,
-      (aStatus != FeatureStatus::Available &&
-       aStatus != FeatureStatus::ForceEnabled),
-      aStatus,
-      aDisableMessage);
-  }
-
-  // Re-enables a feature that was previously disabled, by attaching it to a
-  // fallback. The fallback inherits the message that was used for disabling
-  // the feature. This can be used, for example, when D3D11 fails at runtime
-  // but we acquire a second, successful device with WARP.
-  static void Reenable(Feature aFeature, Fallback aFallback);
-
-  // Same as SetDefault, except if the feature already has a default value
-  // set, the new value will be set as a runtime value. This is useful for
-  // when the base value can change (for example, via an update from the
-  // parent process).
-  static bool InitOrUpdate(Feature aFeature,
-                           bool aEnable,
-                           FeatureStatus aDisableStatus,
-                           const char* aDisableMessage);
-
-  // Set a user status that overrides the base value (but not runtime value)
-  // of a parameter.
-  static void UserEnable(Feature aFeature, const char* aMessage);
-  static void UserForceEnable(Feature aFeature, const char* aMessage);
-  static void UserDisable(Feature aFeature, const char* aMessage);
-
-  // Query whether a fallback has been toggled.
-  static bool UseFallback(Fallback aFallback);
-
-  // Enable a fallback.
-  static void EnableFallback(Fallback aFallback, const char* aMessage);
-
-  // Run a callback for each initialized FeatureState.
-  typedef mozilla::function<void(const char* aName,
-                                 const char* aDescription,
-                                 FeatureState& aFeature)> FeatureIterCallback;
-  static void ForEachFeature(const FeatureIterCallback& aCallback);
-
-  // Run a callback for each enabled fallback.
-  typedef mozilla::function<void(const char* aName, const char* aMsg)> 
-    FallbackIterCallback;
-  static void ForEachFallback(const FallbackIterCallback& aCallback);
-
-private:
-  void ForEachFallbackImpl(const FallbackIterCallback& aCallback);
-
-private:
-  FeatureState& GetState(Feature aFeature) {
-    MOZ_ASSERT(size_t(aFeature) < kNumFeatures);
-    return mFeatures[size_t(aFeature)];
-  }
-  const FeatureState& GetState(Feature aFeature) const {
-    MOZ_ASSERT(size_t(aFeature) < kNumFeatures);
-    return mFeatures[size_t(aFeature)];
-  }
-
-  bool UseFallbackImpl(Fallback aFallback) const;
-  void EnableFallbackImpl(Fallback aFallback, const char* aMessage);
-
-private:
-  static const size_t kNumFeatures = size_t(Feature::NumValues);
-  static const size_t kNumFallbacks = size_t(Fallback::NumValues);
-
-private:
-  FeatureState mFeatures[kNumFeatures];
-  uint64_t mFallbackBits;
-
-private:
-  struct FallbackLogEntry {
-    Fallback mFallback;
-    char mMessage[80];
-  };
-
-  FallbackLogEntry mFallbackLog[kNumFallbacks];
-  size_t mNumFallbackLogEntries;
-};
-
-} // namespace gfx
-} // namespace mozilla
-
-#endif // mozilla_gfx_config_gfxConfig_h
deleted file mode 100644
--- a/gfx/config/gfxFallback.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* -*- 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/. */
-#ifndef mozilla_gfx_config_gfxFallback_h
-#define mozilla_gfx_config_gfxFallback_h
-
-#include <stdint.h>
-#include "gfxTelemetry.h"
-
-namespace mozilla {
-namespace gfx {
-
-#define GFX_FALLBACK_MAP(_)                                                       \
-  /* Name */                                                                      \
-  _(USE_D3D11_WARP_COMPOSITOR)                                                    \
-  /* Add new entries above this comment */
-
-enum class Fallback : uint32_t {
-#define MAKE_ENUM(name) name,
-  GFX_FALLBACK_MAP(MAKE_ENUM)
-#undef MAKE_ENUM
-  NumValues
-};
-
-} // namespace gfx
-} // namespace mozilla
-
-#endif // mozilla_gfx_config_gfxFallback_h
deleted file mode 100644
--- a/gfx/config/gfxFeature.cpp
+++ /dev/null
@@ -1,241 +0,0 @@
-/* -*- 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"
-
-namespace mozilla {
-namespace gfx {
-
-bool
-FeatureState::IsEnabled() const
-{
-  return IsFeatureStatusSuccess(GetValue());
-}
-
-FeatureStatus
-FeatureState::GetValue() const
-{
-  AssertInitialized();
-
-  if (mRuntime.mStatus != FeatureStatus::Unused) {
-    return mRuntime.mStatus;
-  }
-  if (mUser.mStatus == FeatureStatus::ForceEnabled) {
-    return FeatureStatus::ForceEnabled;
-  }
-  if (mEnvironment.mStatus != FeatureStatus::Unused) {
-    return mEnvironment.mStatus;
-  }
-  if (mUser.mStatus != FeatureStatus::Unused) {
-    return mUser.mStatus;
-  }
-  return mDefault.mStatus;
-}
-
-bool
-FeatureState::SetDefault(bool aEnable,
-                         FeatureStatus aDisableStatus,
-                         const char* aDisableMessage)
-{
-  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);
-  }
-  return MaybeSetFailed(aEnable, aDisableStatus, aDisableMessage);
-}
-
-void
-FeatureState::UserEnable(const char* aMessage)
-{
-  AssertInitialized();
-  SetUser(FeatureStatus::Available, aMessage);
-}
-
-void
-FeatureState::UserForceEnable(const char* aMessage)
-{
-  AssertInitialized();
-  SetUser(FeatureStatus::ForceEnabled, aMessage);
-}
-
-void
-FeatureState::UserDisable(const char* aMessage)
-{
-  AssertInitialized();
-  SetUser(FeatureStatus::Disabled, aMessage);
-}
-
-void
-FeatureState::Disable(FeatureStatus aStatus, const char* aMessage)
-{
-  AssertInitialized();
-
-  // We should never bother setting an environment status to "enabled," since
-  // it could override an explicit user decision to disable it.
-  MOZ_ASSERT(IsFeatureStatusFailure(aStatus));
-
-  SetEnvironment(aStatus, aMessage);
-}
-
-void
-FeatureState::SetFailed(FeatureStatus aStatus, const char* aMessage)
-{
-  AssertInitialized();
-
-  // We should never bother setting a runtime status to "enabled," since it could
-  // override an explicit user decision to disable it.
-  MOZ_ASSERT(IsFeatureStatusFailure(aStatus));
-
-  SetRuntime(aStatus, aMessage);
-}
-
-bool
-FeatureState::MaybeSetFailed(bool aEnable, FeatureStatus aStatus, const char* aMessage)
-{
-  if (!aEnable) {
-    SetFailed(aStatus, aMessage);
-    return false;
-  }
-  return true;
-}
-
-bool
-FeatureState::MaybeSetFailed(FeatureStatus aStatus, const char* aMessage)
-{
-  return MaybeSetFailed(IsFeatureStatusSuccess(aStatus), aStatus, aMessage);
-}
-
-bool
-FeatureState::DisabledByDefault() const
-{
-  AssertInitialized();
-  return mDefault.mStatus != FeatureStatus::Available;
-}
-
-bool
-FeatureState::IsForcedOnByUser() const
-{
-  AssertInitialized();
-  return mUser.mStatus == FeatureStatus::ForceEnabled;
-}
-
-void
-FeatureState::EnableByDefault()
-{
-  // User/runtime decisions should not have been made yet.
-  MOZ_ASSERT(!mUser.IsInitialized());
-  MOZ_ASSERT(!mEnvironment.IsInitialized());
-  MOZ_ASSERT(!mRuntime.IsInitialized());
-
-  mDefault.Set(FeatureStatus::Available);
-}
-
-void
-FeatureState::DisableByDefault(FeatureStatus aStatus, const char* aMessage)
-{
-  // User/runtime decisions should not have been made yet.
-  MOZ_ASSERT(!mUser.IsInitialized());
-  MOZ_ASSERT(!mEnvironment.IsInitialized());
-  MOZ_ASSERT(!mRuntime.IsInitialized());
-
-  mDefault.Set(aStatus, aMessage);
-}
-
-void
-FeatureState::SetUser(FeatureStatus aStatus, const char* aMessage)
-{
-  // Default decision must have been made, but not runtime or environment.
-  MOZ_ASSERT(mDefault.IsInitialized());
-  MOZ_ASSERT(!mEnvironment.IsInitialized());
-  MOZ_ASSERT(!mRuntime.IsInitialized());
-
-  mUser.Set(aStatus, aMessage);
-}
-
-void
-FeatureState::SetEnvironment(FeatureStatus aStatus, const char* aMessage)
-{
-  // Default decision must have been made, but not runtime.
-  MOZ_ASSERT(mDefault.IsInitialized());
-  MOZ_ASSERT(!mRuntime.IsInitialized());
-
-  mEnvironment.Set(aStatus, aMessage);
-}
-
-void
-FeatureState::SetRuntime(FeatureStatus aStatus, const char* aMessage)
-{
-  AssertInitialized();
-
-  mRuntime.Set(aStatus, aMessage);
-}
-
-const char*
-FeatureState::GetRuntimeMessage() const
-{
-  MOZ_ASSERT(IsFeatureStatusFailure(mRuntime.mStatus));
-  return mRuntime.mMessage;
-}
-
-void
-FeatureState::ForEachStatusChange(const StatusIterCallback& aCallback) const
-{
-  AssertInitialized();
-
-  aCallback("default", mDefault.mStatus, mDefault.MessageOrNull());
-  if (mUser.IsInitialized()) {
-    aCallback("user", mUser.mStatus, mUser.Message());
-  }
-  if (mEnvironment.IsInitialized()) {
-    aCallback("env", mEnvironment.mStatus, mEnvironment.Message());
-  }
-  if (mRuntime.IsInitialized()) {
-    aCallback("runtime", mRuntime.mStatus, mRuntime.Message());
-  }
-}
-
-void
-FeatureState::Instance::Set(FeatureStatus aStatus, const char* aMessage /* = nullptr */)
-{
-  mStatus = aStatus;
-  if (aMessage) {
-    PR_snprintf(mMessage, sizeof(mMessage), "%s", aMessage);
-  }
-}
-
-} // namespace gfx
-} // namespace mozilla
deleted file mode 100644
--- a/gfx/config/gfxFeature.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/* -*- 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/. */
-#ifndef mozilla_gfx_config_gfxFeature_h
-#define mozilla_gfx_config_gfxFeature_h
-
-#include <stdint.h>
-#include "gfxTelemetry.h"
-#include "mozilla/Assertions.h"
-#include "mozilla/Function.h"
-
-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
-};
-
-class FeatureState
-{
-  friend class gfxConfig;
-
- 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);
-  bool MaybeSetFailed(bool aEnable, FeatureStatus aStatus, const char* aMessage);
-  bool MaybeSetFailed(FeatureStatus aStatus, const char* aMessage);
-
-  // aType is "base", "user", "env", or "runtime".
-  // aMessage may be null.
-  typedef mozilla::function<void(const char* aType,
-                                 FeatureStatus aStatus,
-                                 const char* aMessage)> StatusIterCallback;
-  void ForEachStatusChange(const StatusIterCallback& aCallback) const;
-
- private:
-  void SetUser(FeatureStatus aStatus, const char* aMessage);
-  void SetEnvironment(FeatureStatus aStatus, const char* aMessage);
-  void SetRuntime(FeatureStatus aStatus, const char* aMessage);
-  bool IsForcedOnByUser() const;
-  bool DisabledByDefault() const;
-  const char* GetRuntimeMessage() const;
-  bool IsInitialized() const {
-    return mDefault.IsInitialized();
-  }
-
-  void AssertInitialized() const {
-    MOZ_ASSERT(IsInitialized());
-  }
-
- private:
-  struct Instance {
-    char mMessage[64];
-    FeatureStatus mStatus;
-
-    void Set(FeatureStatus aStatus, const char* aMessage = nullptr);
-    bool IsInitialized() const {
-      return mStatus != FeatureStatus::Unused;
-    }
-    const char* MessageOrNull() const {
-      return mMessage[0] != '\0' ? mMessage : nullptr;
-    }
-    const char* Message() const {
-      MOZ_ASSERT(MessageOrNull());
-      return mMessage;
-    }
-  };
-
-  // The default state is the state we decide on startup, based on the operating
-  // system or a base preference.
-  //
-  // The user state factors in any changes to preferences that the user made.
-  //
-  // The environment state factors in any additional decisions made, such as
-  // availability or blacklisting.
-  //
-  // The runtime state factors in any problems discovered at runtime.
-  Instance mDefault;
-  Instance mUser;
-  Instance mEnvironment;
-  Instance mRuntime;
-};
-
-} // namespace gfx
-} // namespace mozilla
-
-#endif // mozilla_gfx_config_gfxFeature_h
deleted file mode 100644
--- a/gfx/config/moz.build
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-EXPORTS += [
-  'gfxConfig.h',
-  'gfxFallback.h',
-  'gfxFeature.h',
-]
-
-UNIFIED_SOURCES += [
-  'gfxConfig.cpp',
-  'gfxFeature.cpp',
-]
-
-FINAL_LIBRARY = 'xul'
--- a/gfx/ipc/GraphicsMessages.ipdlh
+++ b/gfx/ipc/GraphicsMessages.ipdlh
@@ -7,17 +7,17 @@
 
 using struct DxgiAdapterDesc from "mozilla/D3DMessageUtils.h";
 
 namespace mozilla {
 namespace gfx {
 
 struct DeviceInitData
 {
-  bool useHwCompositing;
+  bool useAcceleration;
 
   // Windows only.
   bool useD3D11;
   bool useD3D11WARP;
   bool useD3D11ImageBridge;
   bool d3d11TextureSharingWorks;
   bool useD2D1;
   DxgiAdapterDesc adapter;
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -12,17 +12,16 @@
 #include "gfxWindowsPlatform.h"
 #include "nsIWidget.h"
 #include "nsIGfxInfo.h"
 #include "mozilla/layers/ImageHost.h"
 #include "mozilla/layers/ContentHost.h"
 #include "mozilla/layers/Effects.h"
 #include "nsWindowsHelpers.h"
 #include "gfxPrefs.h"
-#include "gfxConfig.h"
 #include "gfxCrashReporterUtils.h"
 #include "gfxVR.h"
 #include "mozilla/gfx/StackArray.h"
 #include "mozilla/Services.h"
 
 #include "mozilla/EnumeratedArray.h"
 #include "mozilla/Telemetry.h"
 #include "BlendShaderConstants.h"
@@ -192,19 +191,21 @@ CompositorD3D11::~CompositorD3D11()
       delete attachments;
     }
   }
 }
 
 bool
 CompositorD3D11::Initialize()
 {
-  ScopedGfxFeatureReporter reporter("D3D11 Layers");
+  bool force = gfxPrefs::LayersAccelerationForceEnabled();
 
-  MOZ_ASSERT(gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING));
+  ScopedGfxFeatureReporter reporter("D3D11 Layers", force);
+
+  MOZ_ASSERT(gfxPlatform::CanUseDirect3D11());
 
   HRESULT hr;
 
   if (!gfxWindowsPlatform::GetPlatform()->GetD3D11Device(&mDevice)) {
     return false;
   }
 
   mDevice->GetImmediateContext(getter_AddRefs(mContext));
--- a/gfx/layers/d3d9/CompositorD3D9.cpp
+++ b/gfx/layers/d3d9/CompositorD3D9.cpp
@@ -35,17 +35,19 @@ CompositorD3D9::~CompositorD3D9()
 {
   mSwapChain = nullptr;
   mDeviceManager = nullptr;
 }
 
 bool
 CompositorD3D9::Initialize()
 {
-  ScopedGfxFeatureReporter reporter("D3D9 Layers");
+  bool force = gfxPrefs::LayersAccelerationForceEnabled();
+
+  ScopedGfxFeatureReporter reporter("D3D9 Layers", force);
 
   MOZ_ASSERT(gfxPlatform::CanUseDirect3D9());
 
   mDeviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager();
   if (!mDeviceManager) {
     return false;
   }
 
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -220,17 +220,19 @@ CompositorOGL::CleanupResources()
   mGLContext->MarkDestroyed();
 
   mGLContext = nullptr;
 }
 
 bool
 CompositorOGL::Initialize()
 {
-  ScopedGfxFeatureReporter reporter("GL Layers");
+  bool force = gfxPrefs::LayersAccelerationForceEnabled();
+
+  ScopedGfxFeatureReporter reporter("GL Layers", force);
 
   // Do not allow double initialization
   MOZ_ASSERT(mGLContext == nullptr, "Don't reinitialize CompositorOGL");
 
   mGLContext = CreateContext();
 
 #ifdef MOZ_WIDGET_ANDROID
   if (!mGLContext)
--- a/gfx/moz.build
+++ b/gfx/moz.build
@@ -16,17 +16,16 @@ DIRS += [
     'gl',
     'layers',
     'graphite2/src',
     'harfbuzz/src',
     'ots/src',
     'thebes',
     'ipc',
     'vr',
-    'config',
 ]
 
 if CONFIG['MOZ_ENABLE_SKIA']:
     DIRS += ['skia']
 
 if CONFIG['ENABLE_TESTS']:
     DIRS += ['tests/gtest']
 
--- a/gfx/src/gfxTelemetry.cpp
+++ b/gfx/src/gfxTelemetry.cpp
@@ -11,49 +11,35 @@ namespace gfx {
 const char*
 FeatureStatusToString(FeatureStatus aStatus)
 {
   switch (aStatus) {
     case FeatureStatus::Unused:
       return "unused";
     case FeatureStatus::Unavailable:
       return "unavailable";
-    case FeatureStatus::CrashedInHandler:
+    case FeatureStatus::Crashed:
       return "crashed";
     case FeatureStatus::Blocked:
       return "blocked";
     case FeatureStatus::Blacklisted:
       return "blacklisted";
     case FeatureStatus::Failed:
       return "failed";
     case FeatureStatus::Disabled:
       return "disabled";
     case FeatureStatus::Available:
       return "available";
-    case FeatureStatus::ForceEnabled:
-      return "force_enabled";
-    case FeatureStatus::CrashedOnStartup:
-      return "crashed_on_startup";
-    case FeatureStatus::Broken:
-      return "broken";
     default:
       MOZ_ASSERT_UNREACHABLE("missing status case");
       return "unknown";
   }
 }
 
 bool
 IsFeatureStatusFailure(FeatureStatus aStatus)
 {
-  return !(aStatus == FeatureStatus::Unused ||
-           aStatus == FeatureStatus::Available ||
-           aStatus == FeatureStatus::ForceEnabled);
-}
-
-bool
-IsFeatureStatusSuccess(FeatureStatus aStatus)
-{
-  return aStatus == FeatureStatus::Available ||
-         aStatus == FeatureStatus::ForceEnabled;
+  return aStatus != FeatureStatus::Unused &&
+         aStatus != FeatureStatus::Available;
 }
 
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/src/gfxTelemetry.h
+++ b/gfx/src/gfxTelemetry.h
@@ -16,46 +16,35 @@ enum class FeatureStatus
 {
   // This feature has not been requested.
   Unused,
 
   // This feature is unavailable due to Safe Mode or not being included with
   // the operating system.
   Unavailable,
 
-  // This feature crashed immediately when we tried to initialize it, but we
-  // were able to recover via SEH (or something similar).
-  CrashedInHandler,
+  // This feature crashed immediately when we tried to initialize it.
+  Crashed,
 
   // This feature was blocked for reasons outside the blacklist, such as a
   // runtime test failing.
   Blocked,
 
   // This feature has been blocked by the graphics blacklist.
   Blacklisted,
 
   // This feature was attempted but failed to activate.
   Failed,
 
   // This feature was explicitly disabled by the user.
   Disabled,
 
   // This feature is available for use.
-  Available,
-
-  // This feature was explicitly force-enabled by the user.
-  ForceEnabled,
-
-  // This feature was disabled due to the startup crash guard.
-  CrashedOnStartup,
-
-  // This feature was attempted but later determined to be broken.
-  Broken
+  Available
 };
 
 const char* FeatureStatusToString(FeatureStatus aStatus);
 bool IsFeatureStatusFailure(FeatureStatus aStatus);
-bool IsFeatureStatusSuccess(FeatureStatus aStatus);
 
 } // namespace gfx
 } // namespace mozilla
 
 #endif // gfx_src_gfxTelemetry_h__
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -17,17 +17,16 @@
 #include "mozilla/Services.h"
 #include "prprf.h"
 
 #include "gfxCrashReporterUtils.h"
 #include "gfxPlatform.h"
 #include "gfxPrefs.h"
 #include "gfxEnv.h"
 #include "gfxTextRun.h"
-#include "gfxConfig.h"
 
 #ifdef XP_WIN
 #include <process.h>
 #define getpid _getpid
 #else
 #include <unistd.h>
 #endif
 
@@ -147,17 +146,16 @@ void InitGralloc();
 #endif
 void ShutdownTileCache();
 } // namespace layers
 } // namespace mozilla
 
 using namespace mozilla;
 using namespace mozilla::layers;
 using namespace mozilla::gl;
-using namespace mozilla::gfx;
 
 gfxPlatform *gPlatform = nullptr;
 static bool gEverInitialized = false;
 
 static Mutex* gGfxPlatformPrefsLock = nullptr;
 
 // These two may point to the same profile
 static qcms_profile *gCMSOutputProfile = nullptr;
@@ -165,26 +163,24 @@ static qcms_profile *gCMSsRGBProfile = n
 
 static qcms_transform *gCMSRGBTransform = nullptr;
 static qcms_transform *gCMSInverseRGBTransform = nullptr;
 static qcms_transform *gCMSRGBATransform = nullptr;
 
 static bool gCMSInitialized = false;
 static eCMSMode gCMSMode = eCMSMode_Off;
 
-// Device init data should only be used on child processes, so we protect it
-// behind a getter here.
-static DeviceInitData sDeviceInitDataDoNotUseDirectly;
-
 static void ShutdownCMS();
 
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/SourceSurfaceCairo.h"
 using namespace mozilla::gfx;
 
+void InitLayersAccelerationPrefs();
+
 /* Class to listen for pref changes so that chrome code can dynamically
    force sRGB as an output profile. See Bug #452125. */
 class SRGBOverrideObserver final : public nsIObserver,
                                    public nsSupportsWeakReference
 {
     ~SRGBOverrideObserver() {}
 public:
     NS_DECL_ISUPPORTS
@@ -600,18 +596,18 @@ gfxPlatform::Init()
       // D2D prefs
       forcedPrefs.AppendPrintf("FP(D%d%d%d",
                                gfxPrefs::Direct2DDisabled(),
                                gfxPrefs::Direct2DForceEnabled(),
                                gfxPrefs::DirectWriteFontRenderingForceEnabled());
       // Layers prefs
       forcedPrefs.AppendPrintf("-L%d%d%d%d%d",
                                gfxPrefs::LayersAMDSwitchableGfxEnabled(),
-                               gfxPrefs::LayersAccelerationDisabledDoNotUseDirectly(),
-                               gfxPrefs::LayersAccelerationForceEnabledDoNotUseDirectly(),
+                               gfxPrefs::LayersAccelerationDisabled(),
+                               gfxPrefs::LayersAccelerationForceEnabled(),
                                gfxPrefs::LayersD3D11DisableWARP(),
                                gfxPrefs::LayersD3D11ForceWARP());
       // WebGL prefs
       forcedPrefs.AppendPrintf("-W%d%d%d%d%d%d%d%d",
                                gfxPrefs::WebGLANGLEForceD3D11(),
                                gfxPrefs::WebGLANGLEForceWARP(),
                                gfxPrefs::WebGLDisabled(),
                                gfxPrefs::WebGLDisableANGLE(),
@@ -656,26 +652,26 @@ gfxPlatform::Init()
     gPlatform = new gfxPlatformGtk;
 #elif defined(MOZ_WIDGET_QT)
     gPlatform = new gfxQtPlatform;
 #elif defined(ANDROID)
     gPlatform = new gfxAndroidPlatform;
 #else
     #error "No gfxPlatform implementation available"
 #endif
-    gPlatform->InitAcceleration();
 
 #ifdef USE_SKIA
     SkGraphics::Init();
 #endif
 
 #ifdef MOZ_GL_DEBUG
     GLContext::StaticInit();
 #endif
 
+    InitLayersAccelerationPrefs();
     InitLayersIPC();
 
     gPlatform->PopulateScreenInfo();
     gPlatform->ComputeTileSize();
 
     nsresult rv;
 
     bool usePlatformFontList = true;
@@ -2051,141 +2047,146 @@ gfxPlatform::OptimalFormatForContent(gfx
 /**
  * There are a number of layers acceleration (or layers in general) preferences
  * that should be consistent for the lifetime of the application (bug 840967).
  * As such, we will evaluate them all as soon as one of them is evaluated
  * and remember the values.  Changing these preferences during the run will
  * not have any effect until we restart.
  */
 static bool sLayersSupportsD3D9 = false;
+static bool sLayersSupportsD3D11 = false;
 bool gANGLESupportsD3D11 = false;
 static bool sLayersSupportsHardwareVideoDecoding = false;
 static bool sLayersHardwareVideoDecodingFailed = false;
 static bool sBufferRotationCheckPref = true;
 static bool sPrefBrowserTabsRemoteAutostart = false;
 
 static bool sLayersAccelerationPrefsInitialized = false;
 
 void
-gfxPlatform::InitAcceleration()
+InitLayersAccelerationPrefs()
 {
-  if (sLayersAccelerationPrefsInitialized) {
-    return;
-  }
+  if (!sLayersAccelerationPrefsInitialized)
+  {
+    // If this is called for the first time on a non-main thread, we're screwed.
+    // At the moment there's no explicit guarantee that the main thread calls
+    // this before the compositor thread, but let's at least make the assumption
+    // explicit.
+    MOZ_ASSERT(NS_IsMainThread(), "can only initialize prefs on the main thread");
 
-  InitCompositorAccelerationPrefs();
-
-  // If this is called for the first time on a non-main thread, we're screwed.
-  // At the moment there's no explicit guarantee that the main thread calls
-  // this before the compositor thread, but let's at least make the assumption
-  // explicit.
-  MOZ_ASSERT(NS_IsMainThread(), "can only initialize prefs on the main thread");
+    gfxPrefs::GetSingleton();
+    sPrefBrowserTabsRemoteAutostart = BrowserTabsRemoteAutostart();
 
-  gfxPrefs::GetSingleton();
-  sPrefBrowserTabsRemoteAutostart = BrowserTabsRemoteAutostart();
-
-  nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
-  nsCString discardFailureId;
-  int32_t status;
+    nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
+    nsCString discardFailureId;
+    int32_t status;
 #ifdef XP_WIN
-  if (gfxConfig::IsForcedOnByUser(Feature::HW_COMPOSITING)) {
-    sLayersSupportsD3D9 = true;
-  } else if (!gfxPrefs::LayersAccelerationDisabledDoNotUseDirectly() && gfxInfo) {
-    if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, discardFailureId, &status))) {
-      if (status == nsIGfxInfo::FEATURE_STATUS_OK) {
-        MOZ_ASSERT(!sPrefBrowserTabsRemoteAutostart || IsVistaOrLater());
-        sLayersSupportsD3D9 = true;
+    if (gfxPrefs::LayersAccelerationForceEnabled()) {
+      sLayersSupportsD3D9 = true;
+      sLayersSupportsD3D11 = true;
+    } else if (!gfxPrefs::LayersAccelerationDisabled() && gfxInfo) {
+      if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, discardFailureId, &status))) {
+        if (status == nsIGfxInfo::FEATURE_STATUS_OK) {
+          MOZ_ASSERT(!sPrefBrowserTabsRemoteAutostart || IsVistaOrLater());
+          sLayersSupportsD3D9 = true;
+        }
+      }
+      if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS, discardFailureId, &status))) {
+        if (status == nsIGfxInfo::FEATURE_STATUS_OK) {
+          sLayersSupportsD3D11 = true;
+        }
+      }
+      if (!gfxPrefs::LayersD3D11DisableWARP()) {
+        // Always support D3D11 when WARP is allowed.
+        sLayersSupportsD3D11 = true;
+      }
+      if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_11_ANGLE, discardFailureId, &status))) {
+        if (status == nsIGfxInfo::FEATURE_STATUS_OK) {
+          gANGLESupportsD3D11 = true;
+        }
       }
     }
-    if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_11_ANGLE, discardFailureId, &status))) {
-      if (status == nsIGfxInfo::FEATURE_STATUS_OK) {
-        gANGLESupportsD3D11 = true;
-      }
-    }
-  }
 #endif
 
-  if (Preferences::GetBool("media.hardware-video-decoding.enabled", false) &&
+    if (Preferences::GetBool("media.hardware-video-decoding.enabled", false) &&
 #ifdef XP_WIN
-    Preferences::GetBool("media.windows-media-foundation.use-dxva", true) &&
+        Preferences::GetBool("media.windows-media-foundation.use-dxva", true) &&
 #endif
-      NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
+        NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
                                                discardFailureId, &status))) {
-      if (status == nsIGfxInfo::FEATURE_STATUS_OK || gfxPrefs::HardwareVideoDecodingForceEnabled()) {
-         sLayersSupportsHardwareVideoDecoding = true;
+        if (status == nsIGfxInfo::FEATURE_STATUS_OK || gfxPrefs::HardwareVideoDecodingForceEnabled()) {
+           sLayersSupportsHardwareVideoDecoding = true;
+      }
     }
-  }
-
-  Preferences::AddBoolVarCache(&sLayersHardwareVideoDecodingFailed,
-                               "media.hardware-video-decoding.failed",
-                               false);
-
-  sLayersAccelerationPrefsInitialized = true;
-}
-
-void
-gfxPlatform::InitCompositorAccelerationPrefs()
-{
-  const char *acceleratedEnv = PR_GetEnv("MOZ_ACCELERATED");
-
-  FeatureState& feature = gfxConfig::GetFeature(Feature::HW_COMPOSITING);
 
-  // Base value - does the platform allow acceleration?
-  if (feature.SetDefault(AccelerateLayersByDefault(),
-                         FeatureStatus::Blocked,
-                         "Acceleration blocked by platform"))
-  {
-    if (gfxPrefs::LayersAccelerationDisabledDoNotUseDirectly()) {
-      feature.UserDisable("Disabled by pref");
-    } else if (acceleratedEnv && *acceleratedEnv == '0') {
-      feature.UserDisable("Disabled by envvar");
-    }
-  } else {
-    if (acceleratedEnv && *acceleratedEnv == '1') {
-      feature.UserEnable("Enabled by envvar");
-    }
-  }
+    Preferences::AddBoolVarCache(&sLayersHardwareVideoDecodingFailed,
+                                 "media.hardware-video-decoding.failed",
+                                 false);
 
-  // This has specific meaning elsewhere, so we always record it.
-  if (gfxPrefs::LayersAccelerationForceEnabledDoNotUseDirectly()) {
-    feature.UserForceEnable("Force-enabled by pref");
-  }
-
-  // Safe mode trumps everything.
-  if (InSafeMode()) {
-    feature.ForceDisable(FeatureStatus::Blocked, "Acceleration blocked by safe-mode");
+    sLayersAccelerationPrefsInitialized = true;
   }
 }
 
 bool
 gfxPlatform::CanUseDirect3D9()
 {
   // this function is called from the compositor thread, so it is not
   // safe to init the prefs etc. from here.
   MOZ_ASSERT(sLayersAccelerationPrefsInitialized);
   return sLayersSupportsD3D9;
 }
 
 bool
+gfxPlatform::CanUseDirect3D11()
+{
+  // this function is called from the compositor thread, so it is not
+  // safe to init the prefs etc. from here.
+  MOZ_ASSERT(sLayersAccelerationPrefsInitialized);
+  return sLayersSupportsD3D11;
+}
+
+bool
 gfxPlatform::CanUseHardwareVideoDecoding()
 {
   // this function is called from the compositor thread, so it is not
   // safe to init the prefs etc. from here.
   MOZ_ASSERT(sLayersAccelerationPrefsInitialized);
   return sLayersSupportsHardwareVideoDecoding && !sLayersHardwareVideoDecodingFailed;
 }
 
 bool
 gfxPlatform::CanUseDirect3D11ANGLE()
 {
   MOZ_ASSERT(sLayersAccelerationPrefsInitialized);
   return gANGLESupportsD3D11;
 }
 
 bool
+gfxPlatform::ShouldUseLayersAcceleration()
+{
+  const char *acceleratedEnv = PR_GetEnv("MOZ_ACCELERATED");
+  if (gfxPrefs::LayersAccelerationDisabled() ||
+      InSafeMode() ||
+      (acceleratedEnv && *acceleratedEnv == '0'))
+  {
+    return false;
+  }
+  if (gfxPrefs::LayersAccelerationForceEnabled()) {
+    return true;
+  }
+  if (AccelerateLayersByDefault()) {
+    return true;
+  }
+  if (acceleratedEnv && *acceleratedEnv != '0') {
+    return true;
+  }
+  return false;
+}
+
+bool
 gfxPlatform::AccelerateLayersByDefault()
 {
 #if defined(MOZ_GL_PROVIDER) || defined(MOZ_WIDGET_UIKIT)
   return true;
 #else
   return false;
 #endif
 }
@@ -2214,37 +2215,30 @@ gfxPlatform::GetScaledFontForFontWithCai
         nativeFont.mType = NativeFontType::CAIRO_FONT_FACE;
         nativeFont.mFont = aFont->GetCairoScaledFont();
         return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
     }
 
     return nullptr;
 }
 
-/* static */ DeviceInitData&
-gfxPlatform::GetParentDevicePrefs()
-{
-  MOZ_ASSERT(XRE_IsContentProcess());
-  return sDeviceInitDataDoNotUseDirectly;
-}
-
 /* static */ bool
 gfxPlatform::UsesOffMainThreadCompositing()
 {
   static bool firstTime = true;
   static bool result = false;
 
   if (firstTime) {
-    MOZ_ASSERT(sLayersAccelerationPrefsInitialized);
+    InitLayersAccelerationPrefs();
     result =
       sPrefBrowserTabsRemoteAutostart ||
       !gfxPrefs::LayersOffMainThreadCompositionForceDisabled();
 #if defined(MOZ_WIDGET_GTK)
     // Linux users who chose OpenGL are being grandfathered in to OMTC
-    result |= gfxPrefs::LayersAccelerationForceEnabledDoNotUseDirectly();
+    result |= gfxPrefs::LayersAccelerationForceEnabled();
 
 #endif
     firstTime = false;
   }
 
   return result;
 }
 
@@ -2364,17 +2358,17 @@ AllowOpenGL(bool* aWhitelisted)
     if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_OPENGL_LAYERS, discardFailureId, &status))) {
       if (status == nsIGfxInfo::FEATURE_STATUS_OK) {
         *aWhitelisted = true;
         return true;
       }
     }
   }
 
-  return gfxConfig::IsForcedOnByUser(Feature::HW_COMPOSITING);
+  return gfxPrefs::LayersAccelerationForceEnabled();
 }
 
 void
 gfxPlatform::GetAcceleratedCompositorBackends(nsTArray<LayersBackend>& aBackends)
 {
   // Being whitelisted is not enough to accelerate, but not being whitelisted is
   // enough not to:
   bool whitelisted = false;
@@ -2427,39 +2421,31 @@ gfxPlatform::NotifyCompositorCreated(Lay
     }
   }));
 }
 
 void
 gfxPlatform::GetDeviceInitData(mozilla::gfx::DeviceInitData* aOut)
 {
   MOZ_ASSERT(XRE_IsParentProcess());
-  aOut->useHwCompositing() = gfxConfig::IsEnabled(Feature::HW_COMPOSITING);
+  aOut->useAcceleration() = ShouldUseLayersAcceleration();
 }
 
-bool
+void
 gfxPlatform::UpdateDeviceInitData()
 {
   if (XRE_IsParentProcess()) {
     // The parent process figures out device initialization on its own.
-    return false;
+    return;
   }
 
   mozilla::gfx::DeviceInitData data;
   mozilla::dom::ContentChild::GetSingleton()->SendGetGraphicsDeviceInitData(&data);
 
-  sDeviceInitDataDoNotUseDirectly = data;
-
-  // Ensure that child processes have inherited the HW_COMPOSITING pref.
-  gfxConfig::InitOrUpdate(
-    Feature::HW_COMPOSITING,
-    GetParentDevicePrefs().useHwCompositing(),
-    FeatureStatus::Blocked,
-    "Hardware-accelerated compositing disabled in parent process");
-  return true;
+  SetDeviceInitData(data);
 }
 
 bool
 gfxPlatform::SupportsApzDragInput() const
 {
   return gfxPrefs::APZDragEnabled();
 }
 
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -445,19 +445,24 @@ public:
     }
 
     // Are we in safe mode?
     static bool InSafeMode();
 
     static bool OffMainThreadCompositingEnabled();
 
     static bool CanUseDirect3D9();
+    static bool CanUseDirect3D11();
     virtual bool CanUseHardwareVideoDecoding();
     static bool CanUseDirect3D11ANGLE();
 
+    // Returns whether or not layers acceleration should be used. This should
+    // only be called on the parent process.
+    bool ShouldUseLayersAcceleration();
+
     // Returns a prioritized list of all available compositor backends.
     void GetCompositorBackends(bool useAcceleration, nsTArray<mozilla::layers::LayersBackend>& aBackends);
 
     /**
      * Is it possible to use buffer rotation.  Note that these
      * check the preference, but also allow for the override to
      * disable it using DisableBufferRotation.
      */
@@ -655,18 +660,16 @@ public:
     uint64_t GetDeviceCounter() const {
       return mDeviceCounter;
     }
 
 protected:
     gfxPlatform();
     virtual ~gfxPlatform();
 
-    virtual void InitAcceleration();
-
     /**
      * Initialized hardware vsync based on each platform.
      */
     virtual already_AddRefed<mozilla::gfx::VsyncSource> CreateHardwareVsyncSource();
 
     // Returns whether or not layers should be accelerated by default on this platform.
     virtual bool AccelerateLayersByDefault();
 
@@ -678,27 +681,32 @@ protected:
      * aBackendBitmask specifies the backends which are acceptable to the caller.
      * The backend used is determined by aBackendBitmask and the order specified
      * by the gfx.canvas.azure.backends pref.
      */
     void InitBackendPrefs(uint32_t aCanvasBitmask, mozilla::gfx::BackendType aCanvasDefault,
                           uint32_t aContentBitmask, mozilla::gfx::BackendType aContentDefault);
 
     /**
-     * If in a child process, triggers a refresh of device preferences, then returns true.
-     * In a parent process, nothing happens and false is returned.
+     * If in a child process, triggers a refresh of device preferences.
      */
-    virtual bool UpdateDeviceInitData();
+    void UpdateDeviceInitData();
 
     /**
      * Increase the global device counter after a device has been removed/reset.
      */
     void BumpDeviceCounter();
 
     /**
+     * Called when new device preferences are available.
+     */
+    virtual void SetDeviceInitData(mozilla::gfx::DeviceInitData& aData)
+    {}
+
+    /**
      * returns the first backend named in the pref gfx.canvas.azure.backends
      * which is a component of aBackendBitmask, a bitmask of backend types
      */
     static mozilla::gfx::BackendType GetCanvasBackendPref(uint32_t aBackendBitmask);
 
     /**
      * returns the first backend named in the pref gfx.content.azure.backend
      * which is a component of aBackendBitmask, a bitmask of backend types
@@ -716,18 +724,16 @@ protected:
     /**
      * Decode the backend enumberation from a string.
      */
     static mozilla::gfx::BackendType BackendTypeForName(const nsCString& aName);
 
     static already_AddRefed<mozilla::gfx::ScaledFont>
       GetScaledFontForFontWithCairoSkia(mozilla::gfx::DrawTarget* aTarget, gfxFont* aFont);
 
-    static mozilla::gfx::DeviceInitData& GetParentDevicePrefs();
-
     int8_t  mAllowDownloadableFonts;
     int8_t  mGraphiteShapingEnabled;
     int8_t  mOpenTypeSVGEnabled;
 
     int8_t  mBidiNumeralOption;
 
     // whether to always search font cmaps globally 
     // when doing system font fallback
@@ -767,18 +773,16 @@ private:
      */
     void ComputeTileSize();
 
     /**
      * This uses nsIScreenManager to determine the screen size and color depth
      */
     void PopulateScreenInfo();
 
-    void InitCompositorAccelerationPrefs();
-
     RefPtr<gfxASurface> mScreenReferenceSurface;
     nsCOMPtr<nsIObserver> mSRGBOverrideObserver;
     nsCOMPtr<nsIObserver> mFontPrefsObserver;
     nsCOMPtr<nsIObserver> mMemoryPressureObserver;
 
     // The preferred draw target backend to use for canvas
     mozilla::gfx::BackendType mPreferredCanvasBackend;
     // The fallback draw target backend to use for canvas, if the preferred backend fails
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -66,18 +66,16 @@ 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
@@ -322,21 +320,21 @@ private:
   DECL_GFX_PREF(Once, "image.mem.surfacecache.max_size_kb",    ImageMemSurfaceCacheMaxSizeKB, uint32_t, 100 * 1024);
   DECL_GFX_PREF(Once, "image.mem.surfacecache.min_expiration_ms", ImageMemSurfaceCacheMinExpirationMS, uint32_t, 60*1000);
   DECL_GFX_PREF(Once, "image.mem.surfacecache.size_factor",    ImageMemSurfaceCacheSizeFactor, uint32_t, 64);
   DECL_GFX_PREF(Live, "image.mozsamplesize.enabled",           ImageMozSampleSizeEnabled, bool, false);
   DECL_GFX_PREF(Once, "image.multithreaded_decoding.limit",    ImageMTDecodingLimit, int32_t, -1);
   DECL_GFX_PREF(Live, "image.single-color-optimization.enabled", ImageSingleColorOptimizationEnabled, bool, true);
 
   DECL_GFX_PREF(Live, "layers.child-process-shutdown",         ChildProcessShutdown, bool, true);
-  DECL_GFX_PREF(Once, "layers.acceleration.disabled",          LayersAccelerationDisabledDoNotUseDirectly, bool, false);
+  DECL_GFX_PREF(Once, "layers.acceleration.disabled",          LayersAccelerationDisabled, bool, false);
   DECL_GFX_PREF(Live, "layers.acceleration.draw-fps",          LayersDrawFPS, bool, false);
   DECL_GFX_PREF(Live, "layers.acceleration.draw-fps.print-histogram",  FPSPrintHistogram, bool, false);
   DECL_GFX_PREF(Live, "layers.acceleration.draw-fps.write-to-file", WriteFPSToFile, bool, false);
-  DECL_GFX_PREF(Once, "layers.acceleration.force-enabled",     LayersAccelerationForceEnabledDoNotUseDirectly, bool, false);
+  DECL_GFX_PREF(Once, "layers.acceleration.force-enabled",     LayersAccelerationForceEnabled, bool, false);
   DECL_GFX_PREF(Once, "layers.allow-d3d9-fallback",            LayersAllowD3D9Fallback, bool, false);
   DECL_GFX_PREF(Once, "layers.amd-switchable-gfx.enabled",     LayersAMDSwitchableGfxEnabled, bool, false);
   DECL_GFX_PREF(Once, "layers.async-pan-zoom.enabled",         AsyncPanZoomEnabledDoNotUseDirectly, bool, true);
   DECL_GFX_PREF(Once, "layers.async-pan-zoom.separate-event-thread", AsyncPanZoomSeparateEventThread, bool, false);
   DECL_GFX_PREF(Live, "layers.bench.enabled",                  LayersBenchEnabled, bool, false);
   DECL_GFX_PREF(Once, "layers.bufferrotation.enabled",         BufferRotationEnabled, bool, true);
 #ifdef MOZ_GFX_OPTIMIZE_MOBILE
   // If MOZ_GFX_OPTIMIZE_MOBILE is defined, we force component alpha off
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -64,17 +64,16 @@
 #include <d3d11.h>
 
 #include "nsIMemoryReporter.h"
 #include <winternl.h>
 #include "d3dkmtQueryStatistics.h"
 
 #include "SurfaceCache.h"
 #include "gfxPrefs.h"
-#include "gfxConfig.h"
 
 #include "VsyncSource.h"
 #include "DriverCrashGuard.h"
 #include "mozilla/dom/ContentParent.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
@@ -353,75 +352,82 @@ public:
     return MOZ_COLLECT_REPORT("d3d9-shared-texture", KIND_OTHER, UNITS_BYTES,
                               gfxWindowsPlatform::sD3D9SharedTextureUsed,
                               "Memory used for D3D9 shared textures");
   }
 };
 
 NS_IMPL_ISUPPORTS(D3D9SharedTextureReporter, nsIMemoryReporter)
 
+// Device init data should only be used on child processes, so we protect it
+// behind a getter here.
+static DeviceInitData sDeviceInitDataDoNotUseDirectly;
+static inline DeviceInitData&
+GetParentDevicePrefs()
+{
+  MOZ_ASSERT(XRE_IsContentProcess());
+  return sDeviceInitDataDoNotUseDirectly;
+}
+
 gfxWindowsPlatform::gfxWindowsPlatform()
   : mRenderMode(RENDER_GDI)
   , mDeviceLock("gfxWindowsPlatform.mDeviceLock")
   , mIsWARP(false)
   , mHasDeviceReset(false)
   , mHasFakeDeviceReset(false)
   , mCompositorD3D11TextureSharingWorks(false)
+  , mAcceleration(FeatureStatus::Unused)
+  , mD3D11Status(FeatureStatus::Unused)
+  , mD2D1Status(FeatureStatus::Unused)
   , mHasD3D9DeviceReset(false)
 {
-  mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
-  mUseClearTypeAlways = UNINITIALIZED_VALUE;
-
-  /* 
-   * Initialize COM 
-   */ 
-  CoInitialize(nullptr); 
-
-  RegisterStrongMemoryReporter(new GfxD2DVramReporter());
-
-  RegisterStrongMemoryReporter(new GPUAdapterReporter());
-  RegisterStrongMemoryReporter(new D3D11TextureReporter());
-  RegisterStrongMemoryReporter(new D3D9TextureReporter());
-  RegisterStrongMemoryReporter(new D3D9SharedTextureReporter());
+    mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
+    mUseClearTypeAlways = UNINITIALIZED_VALUE;
+
+    /* 
+     * Initialize COM 
+     */ 
+    CoInitialize(nullptr); 
+
+    RegisterStrongMemoryReporter(new GfxD2DVramReporter());
+
+    // 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);
+    mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_9_3);
+
+    UpdateDeviceInitData();
+    InitializeDevices();
+    UpdateRenderMode();
+
+    RegisterStrongMemoryReporter(new GPUAdapterReporter());
+    RegisterStrongMemoryReporter(new D3D11TextureReporter());
+    RegisterStrongMemoryReporter(new D3D9TextureReporter());
+    RegisterStrongMemoryReporter(new D3D9SharedTextureReporter());
 }
 
 gfxWindowsPlatform::~gfxWindowsPlatform()
 {
-  mDeviceManager = nullptr;
-  mD3D11Device = nullptr;
-  mD3D11ContentDevice = nullptr;
-  mD3D11ImageBridgeDevice = nullptr;
-
-  mozilla::gfx::Factory::D2DCleanup();
-
-  mAdapter = nullptr;
-
-  /* 
-   * Uninitialize COM 
-   */ 
-  CoUninitialize();
-}
-
-void
-gfxWindowsPlatform::InitAcceleration()
-{
-  gfxPlatform::InitAcceleration();
-
-  // 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);
-  mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_9_3);
-
-  InitializeConfig();
-  InitializeDevices();
-  UpdateRenderMode();
+    mDeviceManager = nullptr;
+    mD3D11Device = nullptr;
+    mD3D11ContentDevice = nullptr;
+    mD3D11ImageBridgeDevice = nullptr;
+
+    mozilla::gfx::Factory::D2DCleanup();
+
+    mAdapter = nullptr;
+
+    /* 
+     * Uninitialize COM 
+     */ 
+    CoUninitialize();
 }
 
 bool
 gfxWindowsPlatform::CanUseHardwareVideoDecoding()
 {
   if (!gfxPrefs::LayersPreferD3D9() && !mCompositorD3D11TextureSharingWorks) {
     return false;
   }
@@ -481,30 +487,33 @@ gfxWindowsPlatform::HandleDeviceReset()
   mHasD3D9DeviceReset = false;
   mCompositorD3D11TextureSharingWorks = false;
   mDeviceResetReason = DeviceResetReason::OK;
 
   imgLoader::Singleton()->ClearCache(true);
   imgLoader::Singleton()->ClearCache(false);
   gfxAlphaBoxBlur::ShutdownBlurCache();
 
+  // Since we got a device reset, we must ask the parent process for an updated
+  // list of which devices to create.
+  UpdateDeviceInitData();
   InitializeDevices();
   BumpDeviceCounter();
   return true;
 }
 
 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 (gfxConfig::IsEnabled(Feature::DIRECT2D)) {
+  if (GetD2D1Status() == FeatureStatus::Available) {
     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);
@@ -524,19 +533,19 @@ gfxWindowsPlatform::UpdateRenderMode()
   UpdateBackendPrefs();
 
   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))
+                      << ", D3D11 status:" << FeatureStatusToString(GetD3D11Status())
                       << ", D2D1 device:" << hexa(Factory::GetD2D1Device())
-                      << ", D2D1 status:" << FeatureStatusToString(gfxConfig::GetValue(Feature::DIRECT2D))
+                      << ", D2D1 status:" << FeatureStatusToString(GetD2D1Status())
                       << ", content:" << int(GetDefaultContentBackend())
                       << ", compositor:" << int(GetCompositorBackend());
       MOZ_CRASH("GFX: Failed to update reference draw target after device reset");
     }
   }
 }
 
 void
@@ -570,17 +579,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(FeatureStatus::Failed, "Failed to initialize fonts");
+        DisableD2D();
     }
 
     pfl = new gfxGDIFontList();
 
     if (NS_SUCCEEDED(pfl->InitFontList())) {
         return pfl;
     }
 
@@ -590,19 +599,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(FeatureStatus aStatus, const char* aMessage)
+gfxWindowsPlatform::DisableD2D()
 {
-  gfxConfig::SetFailed(Feature::DIRECT2D, aStatus, aMessage);
+  mD2D1Status = FeatureStatus::Failed;
   Factory::SetDirect3D11Device(nullptr);
   UpdateBackendPrefs();
 }
 
 already_AddRefed<gfxASurface>
 gfxWindowsPlatform::CreateOffscreenSurface(const IntSize& aSize,
                                            gfxImageFormat aFormat)
 {
@@ -1547,17 +1556,17 @@ bool DoesD3D11DeviceWork()
   static bool checked = false;
   static bool result = false;
 
   if (checked)
       return result;
   checked = true;
 
   if (gfxPrefs::Direct2DForceEnabled() ||
-      gfxConfig::IsForcedOnByUser(Feature::HW_COMPOSITING))
+      gfxPrefs::LayersAccelerationForceEnabled())
   {
     result = true;
     return true;
   }
 
   if (GetModuleHandleW(L"igd10umd32.dll")) {
     const wchar_t* checkModules[] = {L"dlumd32.dll",
                                      L"dlumd11.dll",
@@ -1746,17 +1755,17 @@ bool DoesD3D11TextureSharingWorkInternal
 {
   // CreateTexture2D is known to crash on lower feature levels, see bugs
   // 1170211 and 1089413.
   if (device->GetFeatureLevel() < D3D_FEATURE_LEVEL_10_0) {
     return false;
   }
 
   if (gfxPrefs::Direct2DForceEnabled() ||
-      gfxConfig::IsForcedOnByUser(Feature::HW_COMPOSITING))
+      gfxPrefs::LayersAccelerationForceEnabled())
   {
     return true;
   }
 
   if (GetModuleHandleW(L"atidxx32.dll")) {
     nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
     if (gfxInfo) {
       nsString vendorID, vendorID2;
@@ -1907,116 +1916,80 @@ bool DoesD3D11TextureSharingWork(ID3D11D
 }
 
 bool DoesD3D11AlphaTextureSharingWork(ID3D11Device *device)
 {
   return DoesD3D11TextureSharingWorkInternal(device, DXGI_FORMAT_R8_UNORM, D3D11_BIND_SHADER_RESOURCE);
 }
 
 static inline bool
-IsGfxInfoStatusOkay(int32_t aFeature)
+CanUseWARP()
 {
-  nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
-  if (!gfxInfo) {
+  if (gfxPrefs::LayersD3D11ForceWARP()) {
     return true;
   }
 
-  int32_t status;
-  nsCString discardFailureId;
-  if (FAILED(gfxInfo->GetFeatureStatus(aFeature, discardFailureId, &status))) {
-    return true;
+  // The child process can only use WARP if the parent process is also using
+  // WARP.
+  if (XRE_IsContentProcess()) {
+    return GetParentDevicePrefs().useD3D11WARP();
   }
 
-  return status == nsIGfxInfo::FEATURE_STATUS_OK;
-}
-
-static inline bool
-IsWARPStable()
-{
   // It seems like nvdxgiwrap makes a mess of WARP. See bug 1154703.
-  if (!IsWin8OrLater() || GetModuleHandleA("nvdxgiwrap.dll")) {
+  if (!IsWin8OrLater() ||
+      gfxPrefs::LayersD3D11DisableWARP() ||
+      GetModuleHandleA("nvdxgiwrap.dll"))
+  {
     return false;
   }
   return true;
 }
 
-void
-gfxWindowsPlatform::InitializeConfig()
-{
-  if (!XRE_IsParentProcess()) {
-    // Child processes init their configuration via UpdateDeviceInitData().
-    return;
-  }
-
-  InitializeD3D11Config();
-  InitializeD2DConfig();
-}
-
-void
-gfxWindowsPlatform::InitializeD3D11Config()
+FeatureStatus
+gfxWindowsPlatform::CheckD3D11Support(bool* aCanUseHardware)
 {
-  MOZ_ASSERT(XRE_IsParentProcess());
-
-  FeatureState& d3d11 = gfxConfig::GetFeature(Feature::D3D11_COMPOSITING);
-
-  d3d11.EnableByDefault();
-
-  // If the user prefers D3D9, act as though they disabled D3D11.
-  if (gfxPrefs::LayersPreferD3D9()) {
-    d3d11.UserDisable("Disabled due to user preference for Direct3D 9");
-    return;
+  // Don't revive D3D11 support after a failure.
+  if (IsFeatureStatusFailure(mD3D11Status)) {
+    return mD3D11Status;
+  }
+
+  if (XRE_IsContentProcess()) {
+    if (!GetParentDevicePrefs().useD3D11()) {
+      return FeatureStatus::Blocked;
+    }
+    *aCanUseHardware = !GetParentDevicePrefs().useD3D11WARP();
+    return FeatureStatus::Available;
+  }
+
+  if (gfxPrefs::LayersD3D11ForceWARP()) {
+    *aCanUseHardware = false;
+    return FeatureStatus::Available;
   }
-
-  if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS)) {
-    if (IsWARPStable() && !gfxPrefs::LayersD3D11DisableWARP()) {
-      // We do not expect hardware D3D11 to work, so we'll try WARP.
-      gfxConfig::EnableFallback(
-        Fallback::USE_D3D11_WARP_COMPOSITOR,
-        "Hardware-accelerated Direct3D11 compositing is blocklisted");
-    } else {
-      // There is little to no chance of D3D11 working, so just disable it.
-      d3d11.Disable(FeatureStatus::Blacklisted, "Hardware-accelerated Direct3D11 compositing is blocklisted");
+  if (gfxPrefs::LayersAccelerationForceEnabled()) {
+    *aCanUseHardware = true;
+    return FeatureStatus::Available;
+  }
+
+  if (nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo()) {
+    int32_t status;
+    nsCString discardFailureId;
+    if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS, discardFailureId, &status))) {
+      if (status != nsIGfxInfo::FEATURE_STATUS_OK) {
+        if (CanUseWARP()) {
+          *aCanUseHardware = false;
+          return FeatureStatus::Available;
+        }
+        return FeatureStatus::Blacklisted;
+      }
     }
   }
 
-  // Check if the user really, really wants WARP.
-  if (gfxPrefs::LayersD3D11ForceWARP()) {
-    // Force D3D11 on even if we disabled it.
-    d3d11.UserForceEnable("User force-enabled WARP on disabled hardware");
-
-    gfxConfig::EnableFallback(
-      Fallback::USE_D3D11_WARP_COMPOSITOR,
-      "Force-enabled by user preference");
-  }
-}
-
-bool
-gfxWindowsPlatform::UpdateDeviceInitData()
-{
-  if (!gfxPlatform::UpdateDeviceInitData()) {
-    return false;
-  }
-
-  if (gfxConfig::InitOrUpdate(Feature::D3D11_COMPOSITING,
-                              GetParentDevicePrefs().useD3D11(),
-                              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;
+  // If we've used WARP once, we continue to use it after device resets.
+  *aCanUseHardware = !mIsWARP;
+  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 InitializeD3D11.
 decltype(D3D11CreateDevice)* sD3D11CreateDeviceFn = nullptr;
 
 bool
@@ -2033,58 +2006,55 @@ gfxWindowsPlatform::AttemptD3D11DeviceCr
         mFeatureLevels.Elements(), mFeatureLevels.Length(),
         D3D11_SDK_VERSION, getter_AddRefs(aOutDevice), nullptr, nullptr);
   } MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
     return false;
   }
   return true;
 }
 
-void
-gfxWindowsPlatform::AttemptD3D11DeviceCreation(FeatureState& d3d11)
+FeatureStatus
+gfxWindowsPlatform::AttemptD3D11DeviceCreation()
 {
   RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter();
   if (!adapter) {
-    d3d11.SetFailed(FeatureStatus::Unavailable, "Failed to acquire a DXGI adapter");
-    return;
+    return FeatureStatus::Unavailable;
   }
 
   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");
-    return;
+    return FeatureStatus::Crashed;
   }
 
   if (FAILED(hr) || !device) {
     gfxCriticalError() << "D3D11 device creation failed: " << hexa(hr);
-    d3d11.SetFailed(FeatureStatus::Failed, "Failed to acquire a D3D11 device");
-    return;
+    return FeatureStatus::Failed;
   }
   if (!DoesD3D11DeviceWork()) {
-    d3d11.SetFailed(FeatureStatus::Broken, "Direct3D11 device was determined to be broken");
-    return;
+    return FeatureStatus::Blocked;
   }
 
   {
     MutexAutoLock lock(mDeviceLock);
     mD3D11Device = device;
   }
 
   // Only test this when not using WARP since it can fail and cause
   // GetDeviceRemovedReason to return weird values.
   mCompositorD3D11TextureSharingWorks = ::DoesD3D11TextureSharingWork(mD3D11Device);
 
-  if (!mCompositorD3D11TextureSharingWorks || DoesRenderTargetViewNeedsRecreating(mD3D11Device)) {
-    gANGLESupportsD3D11 = false;
+  if (!mCompositorD3D11TextureSharingWorks || !DoesRenderTargetViewNeedsRecreating(mD3D11Device)) {
+      gANGLESupportsD3D11 = false;
   }
 
   mD3D11Device->SetExceptionMode(0);
   mIsWARP = false;
+  return FeatureStatus::Available;
 }
 
 bool
 gfxWindowsPlatform::AttemptWARPDeviceCreationHelper(
   ScopedGfxFeatureReporter& aReporterWARP,
   RefPtr<ID3D11Device>& aOutDevice,
   HRESULT& aResOut)
 {
@@ -2100,49 +2070,47 @@ gfxWindowsPlatform::AttemptWARPDeviceCre
 
     aReporterWARP.SetSuccessful();
   } MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
     return false;
   }
   return true;
 }
 
-void
+FeatureStatus
 gfxWindowsPlatform::AttemptWARPDeviceCreation()
 {
   ScopedGfxFeatureReporter reporterWARP("D3D11-WARP", gfxPrefs::LayersD3D11ForceWARP());
-  FeatureState& d3d11 = gfxConfig::GetFeature(Feature::D3D11_COMPOSITING);
 
   HRESULT hr;
   RefPtr<ID3D11Device> device;
   if (!AttemptWARPDeviceCreationHelper(reporterWARP, device, hr)) {
     gfxCriticalError() << "Exception occurred initializing WARP D3D11 device!";
-    d3d11.SetFailed(FeatureStatus::CrashedInHandler, "Crashed creating a D3D11 WARP device");
-    return;
+    return FeatureStatus::Crashed;
   }
 
   if (FAILED(hr) || !device) {
     // This should always succeed... in theory.
     gfxCriticalError() << "Failed to initialize WARP D3D11 device! " << hexa(hr);
-    d3d11.SetFailed(FeatureStatus::Failed, "Failed to create a D3D11 WARP device");
-    return;
+    return FeatureStatus::Failed;
   }
 
   {
     MutexAutoLock lock(mDeviceLock);
     mD3D11Device = device;
   }
 
   // Only test for texture sharing on Windows 8 since it puts the device into
   // an unusable state if used on Windows 7
   if (IsWin8OrLater()) {
     mCompositorD3D11TextureSharingWorks = ::DoesD3D11TextureSharingWork(mD3D11Device);
   }
   mD3D11Device->SetExceptionMode(0);
   mIsWARP = true;
+  return FeatureStatus::Available;
 }
 
 bool
 gfxWindowsPlatform::ContentAdapterIsParentAdapter(ID3D11Device* device)
 {
   DXGI_ADAPTER_DESC desc;
   if (!GetDxgiDesc(device, &desc)) {
     gfxCriticalNote << "Could not query device DXGI adapter info";
@@ -2205,17 +2173,17 @@ gfxWindowsPlatform::AttemptD3D11ContentD
       return FeatureStatus::Unavailable;
     }
   }
 
   HRESULT hr;
   if (!AttemptD3D11ContentDeviceCreationHelper(adapter, hr)) {
     gfxCriticalNote << "Recovered from crash while creating a D3D11 content device";
     RecordContentDeviceFailure(TelemetryDeviceCode::Content);
-    return FeatureStatus::CrashedInHandler;
+    return FeatureStatus::Crashed;
   }
 
   if (FAILED(hr) || !mD3D11ContentDevice) {
     gfxCriticalNote << "Failed to create a D3D11 content device: " << hexa(hr);
     RecordContentDeviceFailure(TelemetryDeviceCode::Content);
     return FeatureStatus::Failed;
   }
 
@@ -2264,17 +2232,17 @@ gfxWindowsPlatform::AttemptD3D11ImageBri
 
 FeatureStatus
 gfxWindowsPlatform::AttemptD3D11ImageBridgeDeviceCreation()
 {
   HRESULT hr;
   if (!AttemptD3D11ImageBridgeDeviceCreationHelper(GetDXGIAdapter(), hr)) {
     gfxCriticalNote << "Recovered from crash while creating a D3D11 image bridge device";
     RecordContentDeviceFailure(TelemetryDeviceCode::Image);
-    return FeatureStatus::CrashedInHandler;
+    return FeatureStatus::Crashed;
   }
 
   if (FAILED(hr) || !mD3D11ImageBridgeDevice) {
     gfxCriticalNote << "Failed to create a content image bridge device: " << hexa(hr);
     RecordContentDeviceFailure(TelemetryDeviceCode::Image);
     return FeatureStatus::Failed;
   }
 
@@ -2286,64 +2254,86 @@ gfxWindowsPlatform::AttemptD3D11ImageBri
 
   if (XRE_IsContentProcess()) {
     ContentAdapterIsParentAdapter(mD3D11ImageBridgeDevice);
   }
   return FeatureStatus::Available;
 }
 
 void
+gfxWindowsPlatform::SetDeviceInitData(mozilla::gfx::DeviceInitData& aData)
+{
+  MOZ_ASSERT(XRE_IsContentProcess());
+  sDeviceInitDataDoNotUseDirectly = aData;
+}
+
+void
 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");
+  mAcceleration = CheckAccelerationSupport();
+  if (IsFeatureStatusFailure(mAcceleration)) {
     return;
   }
 
-  MOZ_ASSERT(!InSafeMode());
-
-  // If we previously crashed initializing devices, bail out now.
+  // If we previously crashed initializing devices, bail out now. This is
+  // effectively a parent-process only check, since the content process
+  // cannot create a lock file.
   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");
+    mAcceleration = FeatureStatus::Blocked;
+    return;
+  }
+
+  // If we're going to prefer D3D9, stop here. The rest of this function
+  // attempts to use D3D11 features.
+  if (gfxPrefs::LayersPreferD3D9()) {
+    mD3D11Status = FeatureStatus::Disabled;
     return;
   }
 
   // First, initialize D3D11. If this succeeds we attempt to use Direct2D.
   InitializeD3D11();
-  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();
-    }
+
+  // Initialize Direct2D.
+  if (mD3D11Status == FeatureStatus::Available) {
+    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();
   }
 }
 
+FeatureStatus
+gfxWindowsPlatform::CheckAccelerationSupport()
+{
+  // Don't retry acceleration if it failed earlier.
+  if (IsFeatureStatusFailure(mAcceleration)) {
+    return mAcceleration;
+  }
+  if (XRE_IsContentProcess()) {
+    return GetParentDevicePrefs().useAcceleration()
+           ? FeatureStatus::Available
+           : FeatureStatus::Blocked;
+  }
+  if (InSafeMode()) {
+    return FeatureStatus::Blocked;
+  }
+  if (!ShouldUseLayersAcceleration()) {
+    return FeatureStatus::Disabled;
+  }
+  return FeatureStatus::Available;
+}
+
 bool
 gfxWindowsPlatform::CanUseD3D11ImageBridge()
 {
   if (XRE_IsContentProcess()) {
     if (!GetParentDevicePrefs().useD3D11ImageBridge()) {
       return false;
     }
   }
@@ -2356,103 +2346,95 @@ 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.
-  FeatureState& d3d11 = gfxConfig::GetFeature(Feature::D3D11_COMPOSITING);
-  if (!d3d11.IsEnabled()) {
+  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.
-    d3d11.SetFailed(FeatureStatus::Unavailable, "Direct3D11 not available on this computer");
+    mD3D11Status = FeatureStatus::Unavailable;
     return;
   }
 
   // Check if a failure was injected for testing.
   if (gfxPrefs::DeviceFailForTesting()) {
-    d3d11.SetFailed(FeatureStatus::Failed, "Direct3D11 device failure simulated by preference");
+    mD3D11Status = FeatureStatus::Failed;
     return;
   }
 
   if (XRE_IsParentProcess()) {
-    if (!gfxConfig::UseFallback(Fallback::USE_D3D11_WARP_COMPOSITOR)) {
-      AttemptD3D11DeviceCreation(d3d11);
-      if (d3d11.GetValue() == FeatureStatus::CrashedInHandler) {
+    // First try to create a hardware accelerated device.
+    if (canUseHardware) {
+      mD3D11Status = AttemptD3D11DeviceCreation();
+      if (mD3D11Status == FeatureStatus::Crashed) {
         return;
       }
-
-      // If we failed to get a device, but WARP is allowed and might work,
-      // re-enable D3D11 and switch to WARP.
-      if (!mD3D11Device && IsWARPStable() && !gfxPrefs::LayersD3D11DisableWARP()) {
-        gfxConfig::Reenable(Feature::D3D11_COMPOSITING, Fallback::USE_D3D11_WARP_COMPOSITOR);
-      }
     }
 
     // If that failed, see if we can use WARP.
-    if (gfxConfig::UseFallback(Fallback::USE_D3D11_WARP_COMPOSITOR)) {
-      MOZ_ASSERT(d3d11.IsEnabled());
-      MOZ_ASSERT(!mD3D11Device);
-      MOZ_ASSERT(IsWARPStable() || gfxPrefs::LayersD3D11ForceWARP());
-
-      AttemptWARPDeviceCreation();
-      if (d3d11.GetValue() == FeatureStatus::CrashedInHandler) {
+    if (!mD3D11Device) {
+      if (!CanUseWARP()) {
+        mD3D11Status = FeatureStatus::Blocked;
         return;
       }
+      mD3D11Status = AttemptWARPDeviceCreation();
     }
 
     // If we still have no device by now, exit.
     if (!mD3D11Device) {
-      MOZ_ASSERT(!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING));
+      MOZ_ASSERT(IsFeatureStatusFailure(mD3D11Status));
       return;
     }
 
     // Either device creation function should have returned Available.
-    MOZ_ASSERT(d3d11.IsEnabled());
+    MOZ_ASSERT(mD3D11Status == FeatureStatus::Available);
   } else {
     // Child processes do not need a compositor, but they do need to know
     // whether the parent process is using WARP and whether or not texture
     // sharing works.
-    mIsWARP = gfxConfig::UseFallback(Fallback::USE_D3D11_WARP_COMPOSITOR);
+    mIsWARP = !canUseHardware;
     mCompositorD3D11TextureSharingWorks = GetParentDevicePrefs().d3d11TextureSharingWorks();
+    mD3D11Status = FeatureStatus::Available;
   }
 
   if (CanUseD3D11ImageBridge()) {
-    if (AttemptD3D11ImageBridgeDeviceCreation() == FeatureStatus::CrashedInHandler) {
+    if (AttemptD3D11ImageBridgeDeviceCreation() == FeatureStatus::Crashed) {
       DisableD3D11AfterCrash();
       return;
     }
   }
 
-  if (AttemptD3D11ContentDeviceCreation() == FeatureStatus::CrashedInHandler) {
+  if (AttemptD3D11ContentDeviceCreation() == FeatureStatus::Crashed) {
     DisableD3D11AfterCrash();
     return;
   }
 
   // We leak these everywhere and we need them our entire runtime anyway, let's
   // leak it here as well. We keep the pointer to sD3D11CreateDeviceFn around
   // as well for D2D1 and device resets.
   d3d11Module.disown();
 }
 
 void
 gfxWindowsPlatform::DisableD3D11AfterCrash()
 {
-  gfxConfig::Disable(Feature::D3D11_COMPOSITING,
-    FeatureStatus::CrashedInHandler,
-    "Crashed while acquiring a Direct3D11 device");
+  mD3D11Status = FeatureStatus::Crashed;
   ResetD3D11Devices();
 }
 
 void
 gfxWindowsPlatform::ResetD3D11Devices()
 {
   MutexAutoLock lock(mDeviceLock);
 
@@ -2473,88 +2455,102 @@ IsD2DBlacklisted()
       if (status != nsIGfxInfo::FEATURE_STATUS_OK) {
         return true;
       }
     }
   }
   return false;
 }
 
-void
-gfxWindowsPlatform::InitializeD2DConfig()
+// 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()
 {
-  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());
+  // 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;
   }
-  
-  if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_DIRECT2D)) {
-    d2d1.Disable(FeatureStatus::Blacklisted, "Direct2D is blacklisted on this hardware");
+
+  // 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 (!d2d1.IsEnabled() && gfxPrefs::Direct2DForceEnabled()) {
-    d2d1.UserForceEnable("Force-enabled via user-preference");
+  if (!Factory::SupportsD2D1()) {
+    return FeatureStatus::Unavailable;
   }
+
+  if (XRE_IsContentProcess()) {
+    return GetParentDevicePrefs().useD2D1()
+           ? FeatureStatus::Available
+           : FeatureStatus::Blocked;
+  }
+
+  return FeatureStatus::Available;
 }
 
 void
 gfxWindowsPlatform::InitializeD2D()
 {
   ScopedGfxFeatureReporter d2d1_1("D2D1.1");
 
-  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()) {
+  mD2D1Status = CheckD2D1Support();
+  if (IsFeatureStatusFailure(mD2D1Status)) {
+    if (XRE_IsContentProcess() && GetParentDevicePrefs().useD2D1()) {
+      RecordContentDeviceFailure(TelemetryDeviceCode::D2D1);
+    }
     return;
   }
 
-  if (!Factory::SupportsD2D1()) {
-    d2d1.SetFailed(FeatureStatus::Unavailable, "Failed to acquire a Direct2D 1.1 factory");
-    return;
-  }
-
+  // If we don't have a content device, don't init
+  // anything else below such as dwrite
   if (!mD3D11ContentDevice) {
-    d2d1.SetFailed(FeatureStatus::Failed, "Failed to acquire a Direct3D 11 content device");
+    mD2D1Status = FeatureStatus::Failed;
     return;
   }
 
   if (!mCompositorD3D11TextureSharingWorks) {
-    d2d1.SetFailed(FeatureStatus::Failed, "Direct3D11 device does not support texture sharing");
+    mD2D1Status = FeatureStatus::Failed;
     return;
   }
 
   // Using Direct2D depends on DWrite support.
   if (!mDWriteFactory && !InitDWriteSupport()) {
-    d2d1.SetFailed(FeatureStatus::Failed, "Failed to initialize DirectWrite support");
+    mD2D1Status = FeatureStatus::Failed;
     return;
   }
 
   // Verify that Direct2D device creation succeeded.
   if (!Factory::SetDirect3D11Device(mD3D11ContentDevice)) {
-    d2d1.SetFailed(FeatureStatus::Failed, "Failed to create a Direct2D device");
+    mD2D1Status = FeatureStatus::Failed;
     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 =
@@ -2890,17 +2886,17 @@ void
 gfxWindowsPlatform::GetAcceleratedCompositorBackends(nsTArray<LayersBackend>& aBackends)
 {
   if (gfxPrefs::LayersPreferOpenGL()) {
     aBackends.AppendElement(LayersBackend::LAYERS_OPENGL);
   }
 
   bool allowTryingD3D9 = false;
   if (!gfxPrefs::LayersPreferD3D9()) {
-    if (mD3D11Device) {
+    if (gfxPlatform::CanUseDirect3D11() && mD3D11Device) {
       aBackends.AppendElement(LayersBackend::LAYERS_D3D11);
     } else {
       allowTryingD3D9 = gfxPrefs::LayersAllowD3D9Fallback();
       NS_WARNING("Direct3D 11-accelerated layers are not supported on this system.");
     }
   }
 
   if (gfxPrefs::LayersPreferD3D9() || !IsVistaOrLater() || allowTryingD3D9) {
@@ -2908,16 +2904,36 @@ 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::GetD3D11Status() const
+{
+  if (mAcceleration != FeatureStatus::Available) {
+    return mAcceleration;
+  }
+  return mD3D11Status;
+}
+
+FeatureStatus
+gfxWindowsPlatform::GetD2D1Status() const
+{
+  if (GetD3D11Status() != FeatureStatus::Available) {
+    return FeatureStatus::Unavailable;
+  }
+  return mD2D1Status;
+}
+
 unsigned
 gfxWindowsPlatform::GetD3D11Version()
 {
   RefPtr<ID3D11Device> device;
   if (!GetD3D11Device(&device)) {
     return 0;
   }
   return device->GetFeatureLevel();
@@ -2927,25 +2943,25 @@ void
 gfxWindowsPlatform::GetDeviceInitData(DeviceInitData* aOut)
 {
   // Check for device resets before giving back new graphics information.
   UpdateRenderMode();
 
   gfxPlatform::GetDeviceInitData(aOut);
 
   // IPDL initializes each field to false for us so we can early return.
-  if (!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) {
+  if (GetD3D11Status() != FeatureStatus::Available) {
     return;
   }
 
   aOut->useD3D11() = true;
   aOut->useD3D11ImageBridge() = !!mD3D11ImageBridgeDevice;
   aOut->d3d11TextureSharingWorks() = mCompositorD3D11TextureSharingWorks;
   aOut->useD3D11WARP() = mIsWARP;
-  aOut->useD2D1() = gfxConfig::IsEnabled(Feature::DIRECT2D);
+  aOut->useD2D1() = (GetD2D1Status() == FeatureStatus::Available);
 
   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
@@ -41,17 +41,16 @@
 #define D3D_FEATURE_LEVEL_11_1 static_cast<D3D_FEATURE_LEVEL>(0xb100)
 #define D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION 2048
 #define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096
 #endif
 
 namespace mozilla {
 namespace gfx {
 class DrawTarget;
-class FeatureState;
 }
 namespace layers {
 class DeviceManagerD3D9;
 class ReadbackManagerD3D11;
 }
 }
 struct IDirect3DDevice9;
 struct ID3D11Device;
@@ -239,16 +238,21 @@ 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 GetD3D11Status() const;
+    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;
@@ -261,60 +265,58 @@ public:
     bool SupportsPluginDirectDXGIDrawing();
 
 protected:
     bool AccelerateLayersByDefault() override {
       return true;
     }
     void GetAcceleratedCompositorBackends(nsTArray<mozilla::layers::LayersBackend>& aBackends) override;
     virtual void GetPlatformCMSOutputProfile(void* &mem, size_t &size) override;
-    bool UpdateDeviceInitData() override;
+    void SetDeviceInitData(mozilla::gfx::DeviceInitData& aData) override;
 
 protected:
     RenderMode mRenderMode;
 
     int8_t mUseClearTypeForDownloadableFonts;
     int8_t mUseClearTypeAlways;
 
 private:
     void Init();
-    void InitAcceleration() override;
 
     void InitializeDevices();
     void InitializeD3D11();
     void InitializeD2D();
     bool InitDWriteSupport();
 
-    void DisableD2D(mozilla::gfx::FeatureStatus aStatus, const char* aMessage);
+    void DisableD2D();
 
-    void InitializeConfig();
-    void InitializeD3D11Config();
-    void InitializeD2DConfig();
+    mozilla::gfx::FeatureStatus CheckAccelerationSupport();
+    mozilla::gfx::FeatureStatus CheckD3D11Support(bool* aCanUseHardware);
+    mozilla::gfx::FeatureStatus CheckD2D1Support();
 
-    void AttemptD3D11DeviceCreation(mozilla::gfx::FeatureState& d3d11);
+    mozilla::gfx::FeatureStatus AttemptD3D11DeviceCreation();
     bool AttemptD3D11DeviceCreationHelper(
         IDXGIAdapter1* aAdapter,
         RefPtr<ID3D11Device>& aOutDevice,
         HRESULT& aResOut);
 
-    void AttemptWARPDeviceCreation();
+    mozilla::gfx::FeatureStatus AttemptWARPDeviceCreation();
     bool AttemptWARPDeviceCreationHelper(
         mozilla::ScopedGfxFeatureReporter& aReporterWARP,
         RefPtr<ID3D11Device>& aOutDevice,
         HRESULT& aResOut);
 
     bool AttemptD3D11ImageBridgeDeviceCreationHelper(
         IDXGIAdapter1* aAdapter, HRESULT& aResOut);
     mozilla::gfx::FeatureStatus AttemptD3D11ImageBridgeDeviceCreation();
 
     mozilla::gfx::FeatureStatus AttemptD3D11ContentDeviceCreation();
     bool AttemptD3D11ContentDeviceCreationHelper(
         IDXGIAdapter1* aAdapter, HRESULT& aResOut);
 
-    bool CanUseWARP();
     bool CanUseD3D11ImageBridge();
     bool ContentAdapterIsParentAdapter(ID3D11Device* device);
 
     void DisableD3D11AfterCrash();
     void ResetD3D11Devices();
 
     IDXGIAdapter1 *GetDXGIAdapter();
     bool IsDeviceReset(HRESULT hr, DeviceResetReason* aReason);
@@ -333,12 +335,18 @@ 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 mAcceleration;
+    mozilla::gfx::FeatureStatus mD3D11Status;
+    mozilla::gfx::FeatureStatus mD2D1Status;
+
     nsTArray<D3D_FEATURE_LEVEL> mFeatureLevels;
 };
 
 #endif /* GFX_WINDOWS_PLATFORM_H */
--- a/toolkit/content/aboutSupport.js
+++ b/toolkit/content/aboutSupport.js
@@ -414,54 +414,16 @@ var snapshotFormatters = {
 
     // Remove adapter keys.
     for (let [prop, key] of adapterKeys) {
       delete data[prop];
       delete data[prop + "2"];
     }
     delete data.isGPU2Active;
 
-    let featureLog = data.featureLog;
-    delete data.featureLog;
-
-    let features = [];
-    for (let feature of featureLog.features) {
-      // Only add interesting decisions - ones that were not automatic based on
-      // all.js/gfxPrefs defaults.
-      if (feature.log.length > 1 || feature.log[0].status != "available") {
-        features.push(feature);
-      }
-    }
-
-    if (features.length) {
-      for (let feature of features) {
-        let trs = [];
-        for (let entry of feature.log) {
-          if (entry.type == "default" && entry.status == "available")
-            continue;
-
-          let text = entry.status + " by " + entry.type + ": " + entry.message;
-          trs.push($.new("tr", [
-            $.new("td", text),
-          ]));
-        }
-        addRow("decisions", feature.name, [$.new("table", trs)]);
-      }
-    } else {
-      $("graphics-decisions-tbody").style.display = "none";
-    }
-
-    if (featureLog.fallbacks.length) {
-      for (let fallback of featureLog.fallbacks) {
-        addRow("workarounds", fallback.name, fallback.message);
-      }
-    } else {
-      $("graphics-workarounds-tbody").style.display = "none";
-    }
-
     // Now that we're done, grab any remaining keys in data and drop them into
     // the diagnostics section.
     for (let key in data) {
       addRow("diagnostics", key, data[key]);
     }
   },
 
   javaScript: function javaScript(data) {
@@ -825,28 +787,18 @@ Serializer.prototype = {
     for (let i = startRow; i < trs.length; i++) {
       if (this._ignoreElement(trs[i]))
         continue;
       let children = trs[i].querySelectorAll("th,td");
       let rowHeading = this._nodeText(children[0]).trim();
       if (children[0].classList.contains("title-column")) {
         if (!this._isHiddenSubHeading(children[0]))
           this._appendText(rowHeading);
-      } else if (children.length == 1) {
-        // This is a single-cell row.
-        this._appendText(rowHeading);
       } else {
-        let childTables = trs[i].querySelectorAll("table");
-        if (childTables.length) {
-          // If we have child tables, don't use nodeText - its trs are already
-          // queued up from querySelectorAll earlier.
-          this._appendText(rowHeading + ": ");
-        } else {
-          this._appendText(rowHeading + ": " + this._nodeText(children[1]).trim());
-        }
+        this._appendText(rowHeading + ": " + this._nodeText(children[1]).trim());
       }
       this._startNewLine();
     }
     this._startNewLine();
   },
 
   _ignoreElement: function (elem) {
     return elem.classList.contains("no-copy");
--- a/toolkit/content/aboutSupport.xhtml
+++ b/toolkit/content/aboutSupport.xhtml
@@ -329,32 +329,16 @@
         <tbody id="graphics-diagnostics-tbody">
           <tr>
             <th colspan="2" class="title-column">
               &aboutSupport.graphicsDiagnosticsTitle;
             </th>
           </tr>
         </tbody>
 
-        <tbody id="graphics-decisions-tbody">
-          <tr>
-            <th colspan="2" class="title-column">
-              &aboutSupport.graphicsDecisionLogTitle;
-            </th>
-          </tr>
-        </tbody>
-
-        <tbody id="graphics-workarounds-tbody">
-          <tr>
-            <th colspan="2" class="title-column">
-              &aboutSupport.graphicsWorkaroundsTitle;
-            </th>
-          </tr>
-        </tbody>
-
         <tbody id="graphics-failures-tbody">
           <tr>
             <th colspan="2" class="title-column">
               &aboutSupport.graphicsFailureLogTitle;
             </th>
           </tr>
         </tbody>
       </table>
--- a/toolkit/locales/en-US/chrome/global/aboutSupport.dtd
+++ b/toolkit/locales/en-US/chrome/global/aboutSupport.dtd
@@ -109,10 +109,8 @@ variant of aboutSupport.showDir.label. -
 <!ENTITY aboutSupport.safeModeTitle "Try Safe Mode">
 <!ENTITY aboutSupport.restartInSafeMode.label "Restart with Add-ons Disabled…">
 
 <!ENTITY aboutSupport.graphicsFeaturesTitle "Features">
 <!ENTITY aboutSupport.graphicsDiagnosticsTitle "Diagnostics">
 <!ENTITY aboutSupport.graphicsFailureLogTitle "Failure Log">
 <!ENTITY aboutSupport.graphicsGPU1Title "GPU #1">
 <!ENTITY aboutSupport.graphicsGPU2Title "GPU #2">
-<!ENTITY aboutSupport.graphicsDecisionLogTitle "Decision Log">
-<!ENTITY aboutSupport.graphicsWorkaroundsTitle "Workarounds">
--- a/toolkit/modules/Troubleshoot.jsm
+++ b/toolkit/modules/Troubleshoot.jsm
@@ -469,18 +469,16 @@ var dataProviders = {
     let failures = gfxInfo.getFailures(failureCount, failureIndices);
     if (failures.length) {
       data.failures = failures;
       if (failureIndices.value.length == failures.length) {
         data.indices = failureIndices.value;
       }
     }
 
-    data.featureLog = gfxInfo.getFeatureLog();
-
     completed();
   },
 
   javaScript: function javaScript(done) {
     let data = {};
     let winEnumer = Services.ww.getWindowEnumerator();
     if (winEnumer.hasMoreElements())
       data.incrementalGCEnabled = winEnumer.getNext().
--- a/widget/GfxInfoBase.cpp
+++ b/widget/GfxInfoBase.cpp
@@ -28,17 +28,16 @@
 #include "nsXULAppAPI.h"
 #include "nsIXULAppInfo.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/Logging.h"
 #include "gfxPrefs.h"
 #include "gfxPlatform.h"
-#include "gfxConfig.h"
 
 #if defined(MOZ_CRASHREPORTER)
 #include "nsExceptionHandler.h"
 #endif
 
 using namespace mozilla::widget;
 using namespace mozilla;
 using mozilla::MutexAutoLock;
@@ -1272,172 +1271,44 @@ GetLayersBackendName(layers::LayersBacke
     case layers::LayersBackend::LAYERS_BASIC:
       return "basic";
     default:
       MOZ_ASSERT_UNREACHABLE("unknown layers backend");
       return "unknown";
   }
 }
 
-static inline bool
-SetJSPropertyString(JSContext* aCx, JS::Handle<JSObject*> aObj,
-                    const char* aProp, const char* aString)
-{
-  JS::Rooted<JSString*> str(aCx, JS_NewStringCopyZ(aCx, aString));
-  if (!str) {
-    return false;
-  }
-
-  JS::Rooted<JS::Value> val(aCx, JS::StringValue(str));
-  return JS_SetProperty(aCx, aObj, aProp, val);
-}
-
-template <typename T>
-static inline bool
-AppendJSElement(JSContext* aCx, JS::Handle<JSObject*> aObj, const T& aValue)
-{
-  uint32_t index;
-  if (!JS_GetArrayLength(aCx, aObj, &index)) {
-    return false;
-  }
-  return JS_SetElement(aCx, aObj, index, aValue);
-}
-
 nsresult
 GfxInfoBase::GetFeatures(JSContext* aCx, JS::MutableHandle<JS::Value> aOut)
 {
   JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
   if (!obj) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
   aOut.setObject(*obj);
 
   layers::LayersBackend backend = gfxPlatform::Initialized()
                                   ? gfxPlatform::GetPlatform()->GetCompositorBackend()
                                   : layers::LayersBackend::LAYERS_NONE;
   const char* backendName = GetLayersBackendName(backend);
-  SetJSPropertyString(aCx, obj, "compositor", backendName);
+  {
+    JS::Rooted<JSString*> str(aCx, JS_NewStringCopyZ(aCx, backendName));
+    JS::Rooted<JS::Value> val(aCx, StringValue(str));
+    JS_SetProperty(aCx, obj, "compositor", val);
+  }
 
   // If graphics isn't initialized yet, just stop now.
   if (!gfxPlatform::Initialized()) {
     return NS_OK;
   }
 
   DescribeFeatures(aCx, obj);
   return NS_OK;
 }
 
-nsresult GfxInfoBase::GetFeatureLog(JSContext* aCx, JS::MutableHandle<JS::Value> aOut)
-{
-  JS::Rooted<JSObject*> containerObj(aCx, JS_NewPlainObject(aCx));
-  if (!containerObj) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  aOut.setObject(*containerObj);
-
-  JS::Rooted<JSObject*> featureArray(aCx, JS_NewArrayObject(aCx, 0));
-  if (!featureArray) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
-  // Collect features.
-  gfxConfig::ForEachFeature([&](const char* aName,
-                                const char* aDescription,
-                                FeatureState& aFeature) -> void {
-    JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
-    if (!obj) {
-      return;
-    }
-    if (!SetJSPropertyString(aCx, obj, "name", aName) ||
-        !SetJSPropertyString(aCx, obj, "description", aDescription) ||
-        !SetJSPropertyString(aCx, obj, "status", FeatureStatusToString(aFeature.GetValue())))
-    {
-      return;
-    }
-
-    JS::Rooted<JS::Value> log(aCx);
-    if (!BuildFeatureStateLog(aCx, aFeature, &log)) {
-      return;
-    }
-    if (!JS_SetProperty(aCx, obj, "log", log)) {
-      return;
-    }
-
-    if (!AppendJSElement(aCx, featureArray, obj)) {
-      return;
-    }
-  });
-
-  JS::Rooted<JSObject*> fallbackArray(aCx, JS_NewArrayObject(aCx, 0));
-  if (!fallbackArray) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
-  // Collect fallbacks.
-  gfxConfig::ForEachFallback([&](const char* aName, const char* aMessage) -> void {
-    JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
-    if (!obj) {
-      return;
-    }
-
-    if (!SetJSPropertyString(aCx, obj, "name", aName) ||
-        !SetJSPropertyString(aCx, obj, "message", aMessage))
-    {
-      return;
-    }
-
-    if (!AppendJSElement(aCx, fallbackArray, obj)) {
-      return;
-    }
-  });
-
-  JS::Rooted<JS::Value> val(aCx);
-
-  val = JS::ObjectValue(*featureArray);
-  JS_SetProperty(aCx, containerObj, "features", val);
-
-  val = JS::ObjectValue(*fallbackArray);
-  JS_SetProperty(aCx, containerObj, "fallbacks", val);
-
-  return NS_OK;
-}
-
-bool
-GfxInfoBase::BuildFeatureStateLog(JSContext* aCx, const FeatureState& aFeature,
-                                  JS::MutableHandle<JS::Value> aOut)
-{
-  JS::Rooted<JSObject*> log(aCx, JS_NewArrayObject(aCx, 0));
-  if (!log) {
-    return false;
-  }
-  aOut.setObject(*log);
-
-  aFeature.ForEachStatusChange([&](const char* aType,
-                                   FeatureStatus aStatus,
-                                   const char* aMessage) -> void {
-    JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
-    if (!obj) {
-      return;
-    }
-
-    if (!SetJSPropertyString(aCx, obj, "type", aType) ||
-        !SetJSPropertyString(aCx, obj, "status", FeatureStatusToString(aStatus)) ||
-        (aMessage && !SetJSPropertyString(aCx, obj, "message", aMessage)))
-    {
-      return;
-    }
-
-    if (!AppendJSElement(aCx, log, obj)) {
-      return;
-    }
-  });
-
-  return true;
-}
-
 void
 GfxInfoBase::DescribeFeatures(JSContext* cx, JS::Handle<JSObject*> aOut)
 {
 }
 
 bool
 GfxInfoBase::InitFeatureObject(JSContext* aCx,
                                JS::Handle<JSObject*> aContainer,
--- a/widget/GfxInfoBase.h
+++ b/widget/GfxInfoBase.h
@@ -12,17 +12,16 @@
 #include "nsCOMPtr.h"
 #include "nsIObserver.h"
 #include "nsWeakReference.h"
 #include "GfxDriverInfo.h"
 #include "nsTArray.h"
 #include "nsString.h"
 #include "GfxInfoCollector.h"
 #include "gfxTelemetry.h"
-#include "gfxFeature.h"
 #include "nsIGfxInfoDebug.h"
 #include "mozilla/Mutex.h"
 #include "js/Value.h"
 #include "mozilla/Attributes.h"
 
 namespace mozilla {
 namespace widget {  
 
@@ -50,17 +49,16 @@ public:
   NS_IMETHOD GetFeatureSuggestedDriverVersion(int32_t aFeature, nsAString & _retval) override;
   NS_IMETHOD GetWebGLParameter(const nsAString & aParam, nsAString & _retval) override;
 
   NS_IMETHOD GetMonitors(JSContext* cx, JS::MutableHandleValue _retval) override;
   NS_IMETHOD GetFailures(uint32_t *failureCount, int32_t** indices, char ***failures) override;
   NS_IMETHOD_(void) LogFailure(const nsACString &failure) override;
   NS_IMETHOD GetInfo(JSContext*, JS::MutableHandle<JS::Value>) override;
   NS_IMETHOD GetFeatures(JSContext*, JS::MutableHandle<JS::Value>) override;
-  NS_IMETHOD GetFeatureLog(JSContext*, JS::MutableHandle<JS::Value>) override;
 
   // Initialization function. If you override this, you must call this class's
   // version of Init first.
   // We need Init to be called separately from the constructor so we can
   // register as an observer after all derived classes have been constructed
   // and we know we have a non-zero refcount.
   // Ideally, Init() would be void-return, but the rules of
   // NS_GENERIC_FACTORY_CONSTRUCTOR_INIT require it be nsresult return.
@@ -114,19 +112,16 @@ private:
   virtual int32_t FindBlocklistedDeviceInList(const nsTArray<GfxDriverInfo>& aDriverInfo,
                                               nsAString& aSuggestedVersion,
                                               int32_t aFeature,
                                               nsACString &aFailureId,
                                               OperatingSystem os);
 
   void EvaluateDownloadedBlacklist(nsTArray<GfxDriverInfo>& aDriverInfo);
 
-  bool BuildFeatureStateLog(JSContext* aCx, const gfx::FeatureState& aFeature,
-                            JS::MutableHandle<JS::Value> aOut);
-
   Mutex mMutex;
 
 };
 
 } // namespace widget
 } // namespace mozilla
 
 #endif /* __mozilla_widget_GfxInfoBase_h__ */
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -1778,19 +1778,16 @@ nsWindow::CreateLayerManager(int aCompos
     }
 
     nsWindow *topLevelWindow = FindTopLevel();
     if (!topLevelWindow || topLevelWindow->mWindowType == eWindowType_invisible) {
         // don't create a layer manager for an invisible top-level window
         return;
     }
 
-    // Ensure that gfxPlatform is initialized first.
-    gfxPlatform::GetPlatform();
-
     if (ShouldUseOffMainThreadCompositing()) {
         CreateCompositor(aCompositorWidth, aCompositorHeight);
         if (mLayerManager) {
             return;
         }
 
         // If we get here, then off main thread compositing failed to initialize.
         sFailedToCreateGLContext = true;
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -64,17 +64,16 @@
 #include "nsRefPtrHashtable.h"
 #include "TouchEvents.h"
 #include "WritingModes.h"
 #include "InputData.h"
 #include "FrameLayerBuilder.h"
 #ifdef ACCESSIBILITY
 #include "nsAccessibilityService.h"
 #endif
-#include "gfxConfig.h"
 
 #ifdef DEBUG
 #include "nsIObserver.h"
 
 static void debug_RegisterPrefCallbacks();
 
 #endif
 
@@ -922,17 +921,17 @@ nsBaseWidget::AutoLayerManagerSetup::~Au
     mLayerManager->SetDefaultTarget(nullptr);
     mLayerManager->SetDefaultTargetConfiguration(mozilla::layers::BufferMode::BUFFER_NONE, ROTATION_0);
   }
 }
 
 bool
 nsBaseWidget::ComputeShouldAccelerate()
 {
-  return gfx::gfxConfig::IsEnabled(gfx::Feature::HW_COMPOSITING);
+  return gfxPlatform::GetPlatform()->ShouldUseLayersAcceleration();
 }
 
 CompositorBridgeParent* nsBaseWidget::NewCompositorBridgeParent(int aSurfaceWidth,
                                                     int aSurfaceHeight)
 {
   return new CompositorBridgeParent(this, false, aSurfaceWidth, aSurfaceHeight);
 }
 
--- a/widget/nsIGfxInfo.idl
+++ b/widget/nsIGfxInfo.idl
@@ -154,45 +154,16 @@ interface nsIGfxInfo : nsISupports
   DOMString getWebGLParameter(in DOMString aParam);
 
   // only useful on X11
   [noscript, notxpcom] void GetData();
 
   [implicit_jscontext]
   jsval getInfo();
 
-  // Return an object describing all features that have been configured:
-  //
-  //   "features": [
-  //     // For each feature:
-  //     {
-  //       "name": <string>,
-  //       "description": <string>,
-  //       "status": <string>,
-  //       "log": [
-  //          // One or more log entries, the first denotes the default value.
-  //          {
-  //            "type": <string>,    // "base", "user", "env", or "runtime"
-  //            "status": <string>,
-  //            "message": <string>  // Set unless type is "base" and status is "available".
-  //          }
-  //       ]
-  //     }
-  //   ]
-  //   "fallbacks": [
-  //     // For each workaround:
-  //     {
-  //       "name:" <string>,
-  //       "description": <string>,
-  //       "message": <string>
-  //     ]
-  //   }
-  [implicit_jscontext]
-  jsval getFeatureLog();
-
   // Returns an object containing information about graphics features. It is
   // intended to be directly included into the Telemetry environment.
   //
   //   "layers":
   //   {
   //     "compositor": "d3d9", "d3d11", "opengl", "basic", or "none"
   //                   // ("none" indicates no compositors have been created)
   //     // Feature is one of "d3d9", "d3d11", "opengl", "basic", or "d2d".
--- a/widget/windows/GfxInfo.cpp
+++ b/widget/windows/GfxInfo.cpp
@@ -2,17 +2,16 @@
 /* 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/ArrayUtils.h"
 
 #include <windows.h>
 #include <setupapi.h>
-#include "gfxConfig.h"
 #include "gfxWindowsPlatform.h"
 #include "GfxInfo.h"
 #include "GfxInfoWebGL.h"
 #include "nsUnicharUtils.h"
 #include "prenv.h"
 #include "prprf.h"
 #include "GfxDriverInfo.h"
 #include "mozilla/Preferences.h"
@@ -22,17 +21,16 @@
 
 #if defined(MOZ_CRASHREPORTER)
 #include "nsExceptionHandler.h"
 #include "nsICrashReporter.h"
 #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
 #endif
 
 using namespace mozilla;
-using namespace mozilla::gfx;
 using namespace mozilla::widget;
 
 #ifdef DEBUG
 NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfoDebug)
 #endif
 
 static const uint32_t allWindowsVersions = 0xffffffff;
 
@@ -1257,44 +1255,35 @@ GfxInfo::FindMonitors(JSContext* aCx, JS
 
 void
 GfxInfo::DescribeFeatures(JSContext* aCx, JS::Handle<JSObject*> aObj)
 {
   JS::Rooted<JSObject*> obj(aCx);
 
   gfxWindowsPlatform* platform = gfxWindowsPlatform::GetPlatform();
 
-  gfx::FeatureStatus d3d11 = gfxConfig::GetValue(Feature::D3D11_COMPOSITING);
+  gfx::FeatureStatus d3d11 = platform->GetD3D11Status();
   if (!InitFeatureObject(aCx, aObj, "d3d11", d3d11, &obj)) {
     return;
   }
   if (d3d11 == gfx::FeatureStatus::Available) {
     JS::Rooted<JS::Value> val(aCx, JS::Int32Value(platform->GetD3D11Version()));
     JS_SetProperty(aCx, obj, "version", val);
 
     val = JS::BooleanValue(platform->IsWARP());
     JS_SetProperty(aCx, obj, "warp", val);
 
     val = JS::BooleanValue(platform->CompositorD3D11TextureSharingWorks());
     JS_SetProperty(aCx, obj, "textureSharing", val);
 
-    bool blacklisted = false;
-    if (nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo()) {
-      int32_t status;
-      nsCString discardFailureId;
-      if (SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS, discardFailureId, &status))) {
-        blacklisted = (status != nsIGfxInfo::FEATURE_STATUS_OK);
-      }
-    }
-
-    val = JS::BooleanValue(blacklisted);
+    val = JS::BooleanValue(!platform->CanUseDirect3D11());
     JS_SetProperty(aCx, obj, "blacklisted", val);
   }
 
-  gfx::FeatureStatus d2d = gfxConfig::GetValue(Feature::DIRECT2D);
+  gfx::FeatureStatus d2d = platform->GetD2D1Status();
   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);
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -133,18 +133,16 @@
 #include "nsToolkitCompsCID.h"
 #include "nsIAppStartup.h"
 #include "mozilla/WindowsVersion.h"
 #include "mozilla/TextEvents.h" // For WidgetKeyboardEvent
 #include "mozilla/TextEventDispatcherListener.h"
 #include "mozilla/widget/WinNativeEventData.h"
 #include "nsThemeConstants.h"
 #include "nsBidiKeyboard.h"
-#include "nsThemeConstants.h"
-#include "gfxConfig.h"
 
 #include "nsIGfxInfo.h"
 #include "nsUXThemeConstants.h"
 #include "KeyboardLayout.h"
 #include "nsNativeDragTarget.h"
 #include <mmsystem.h> // needed for WIN32_LEAN_AND_MEAN
 #include <zmouse.h>
 #include <richedit.h>
@@ -6855,27 +6853,27 @@ nsWindow::HasBogusPopupsDropShadowOnMult
   if (sHasBogusPopupsDropShadowOnMultiMonitor == TRI_UNKNOWN) {
     // Since any change in the preferences requires a restart, this can be
     // done just once.
     // Check for Direct2D first.
     sHasBogusPopupsDropShadowOnMultiMonitor =
       gfxWindowsPlatform::GetPlatform()->IsDirect2DBackend() ? TRI_TRUE : TRI_FALSE;
     if (!sHasBogusPopupsDropShadowOnMultiMonitor) {
       // Otherwise check if Direct3D 9 may be used.
-      if (gfxConfig::IsEnabled(Feature::HW_COMPOSITING) &&
+      if (gfxPlatform::GetPlatform()->ShouldUseLayersAcceleration() &&
           !gfxPrefs::LayersPreferOpenGL())
       {
         nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
         if (gfxInfo) {
           int32_t status;
           nsCString discardFailureId;
           if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS,
                                                      discardFailureId, &status))) {
             if (status == nsIGfxInfo::FEATURE_STATUS_OK ||
-                gfxConfig::IsForcedOnByUser(Feature::HW_COMPOSITING))
+                gfxPrefs::LayersAccelerationForceEnabled())
             {
               sHasBogusPopupsDropShadowOnMultiMonitor = TRI_TRUE;
             }
           }
         }
       }
     }
   }