Move D3D11 device creation out of gfxWindowsPlatform. (bug 1282364 part 3, r=mattwoodrow)
authorDavid Anderson <danderson@mozilla.com>
Tue, 26 Jul 2016 13:22:13 -0700
changeset 348897 8508083db4ac4a33bfef56e35f3aa6a35b7e01a2
parent 348896 007d791665b898246c13e1bfed3b8abc936a8bd6
child 348898 84237932bc5a203f67024cd1bb37cfe335219e1c
push id1230
push userjlund@mozilla.com
push dateMon, 31 Oct 2016 18:13:35 +0000
treeherdermozilla-release@5e06e3766db2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1282364
milestone50.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Move D3D11 device creation out of gfxWindowsPlatform. (bug 1282364 part 3, r=mattwoodrow)
gfx/src/gfxTelemetry.h
gfx/thebes/D3D11Checks.cpp
gfx/thebes/D3D11Checks.h
gfx/thebes/DeviceManagerD3D11.cpp
gfx/thebes/DeviceManagerD3D11.h
gfx/thebes/gfxWindowsPlatform.cpp
gfx/thebes/gfxWindowsPlatform.h
--- a/gfx/src/gfxTelemetry.h
+++ b/gfx/src/gfxTelemetry.h
@@ -50,12 +50,18 @@ enum class FeatureStatus
   // This feature was attempted but later determined to be broken.
   Broken
 };
 
 const char* FeatureStatusToString(FeatureStatus aStatus);
 bool IsFeatureStatusFailure(FeatureStatus aStatus);
 bool IsFeatureStatusSuccess(FeatureStatus aStatus);
 
+enum class TelemetryDeviceCode : uint32_t {
+  Content = 0,
+  Image = 1,
+  D2D1 = 2
+};
+
 } // namespace gfx
 } // namespace mozilla
 
 #endif // gfx_src_gfxTelemetry_h__
--- a/gfx/thebes/D3D11Checks.cpp
+++ b/gfx/thebes/D3D11Checks.cpp
@@ -116,17 +116,17 @@ D3D11Checks::DoesRenderTargetViewNeedRec
         result = true;
     }
 
     keyedMutex->ReleaseSync(0);
     return result;
 }
 
 /* static */ bool
-D3D11Checks::DoesD3D11DeviceWork()
+D3D11Checks::DoesDeviceWork()
 {
   static bool checked = false;
   static bool result = false;
 
   if (checked)
       return result;
   checked = true;
 
--- a/gfx/thebes/D3D11Checks.h
+++ b/gfx/thebes/D3D11Checks.h
@@ -10,17 +10,17 @@ struct ID3D11Device;
 struct DXGI_ADAPTER_DESC;
 
 namespace mozilla {
 namespace gfx {
 
 struct D3D11Checks
 {
   static bool DoesRenderTargetViewNeedRecreating(ID3D11Device* aDevice);
-  static bool DoesD3D11DeviceWork();
+  static bool DoesDeviceWork();
   static bool DoesTextureSharingWork(ID3D11Device *device);
   static bool DoesAlphaTextureSharingWork(ID3D11Device *device);
   static void WarnOnAdapterMismatch(ID3D11Device* device);
   static bool GetDxgiDesc(ID3D11Device* device, DXGI_ADAPTER_DESC* out);
 };
 
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/thebes/DeviceManagerD3D11.cpp
+++ b/gfx/thebes/DeviceManagerD3D11.cpp
@@ -1,87 +1,678 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * 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 "DeviceManagerD3D11.h"
+#include "D3D11Checks.h"
+#include "gfxConfig.h"
+#include "GfxDriverInfo.h"
+#include "gfxPrefs.h"
 #include "gfxWindowsPlatform.h"
+#include "mozilla/D3DMessageUtils.h"
+#include "mozilla/Telemetry.h"
+#include "mozilla/WindowsVersion.h"
+#include "mozilla/gfx/GraphicsMessages.h"
+#include "mozilla/gfx/Logging.h"
+#include "nsIGfxInfo.h"
+#include "nsWindowsHelpers.h"
 #include <d3d11.h>
 
 namespace mozilla {
 namespace gfx {
 
+using namespace mozilla::widget;
+
 StaticAutoPtr<DeviceManagerD3D11> DeviceManagerD3D11::sInstance;
 
+// 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;
+
 /* static */ void
 DeviceManagerD3D11::Init()
 {
   sInstance = new DeviceManagerD3D11();
 }
 
 /* static */ void
 DeviceManagerD3D11::Shutdown()
 {
   sInstance = nullptr;
 }
 
+DeviceManagerD3D11::DeviceManagerD3D11()
+ : mDeviceLock("gfxWindowsPlatform.mDeviceLock"),
+   mIsWARP(false),
+   mTextureSharingWorks(false)
+{
+  // Set up the D3D11 feature levels we can ask for.
+  if (IsWin8OrLater()) {
+    mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_11_1);
+  }
+  mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_11_0);
+  mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_10_1);
+  mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_10_0);
+  mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_9_3);
+}
+
+static inline bool
+IsWARPStable()
+{
+  // It seems like nvdxgiwrap makes a mess of WARP. See bug 1154703.
+  if (!IsWin8OrLater() || GetModuleHandleA("nvdxgiwrap.dll")) {
+    return false;
+  }
+  return true;
+}
+
+bool
+DeviceManagerD3D11::CanUseD3D11ImageBridge()
+{
+  if (XRE_IsContentProcess()) {
+    if (!gfxPlatform::GetPlatform()->GetParentDevicePrefs().useD3D11ImageBridge()) {
+      return false;
+    }
+  }
+  return !mIsWARP;
+}
+
+void
+DeviceManagerD3D11::CreateDevices()
+{
+  FeatureState& d3d11 = gfxConfig::GetFeature(Feature::D3D11_COMPOSITING);
+  MOZ_ASSERT(d3d11.IsEnabled());
+
+  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",
+                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_LIB"));
+    return;
+  }
+
+  // Check if a failure was injected for testing.
+  if (gfxPrefs::DeviceFailForTesting()) {
+    d3d11.SetFailed(FeatureStatus::Failed, "Direct3D11 device failure simulated by preference",
+                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_SIM"));
+    return;
+  }
+
+  if (XRE_IsParentProcess()) {
+    if (!gfxConfig::UseFallback(Fallback::USE_D3D11_WARP_COMPOSITOR)) {
+      AttemptD3D11DeviceCreation(d3d11);
+      if (d3d11.GetValue() == FeatureStatus::CrashedInHandler) {
+        return;
+      }
+
+      // If we failed to get a device, but WARP is allowed and might work,
+      // re-enable D3D11 and switch to WARP.
+      if (!mCompositorDevice && 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(!mCompositorDevice);
+      MOZ_ASSERT(IsWARPStable() || gfxPrefs::LayersD3D11ForceWARP());
+
+      AttemptWARPDeviceCreation();
+      if (d3d11.GetValue() == FeatureStatus::CrashedInHandler) {
+        return;
+      }
+    }
+
+    // If we still have no device by now, exit.
+    if (!mCompositorDevice) {
+      MOZ_ASSERT(!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING));
+      return;
+    }
+
+    // Either device creation function should have returned Available.
+    MOZ_ASSERT(d3d11.IsEnabled());
+  } 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);
+    mTextureSharingWorks =
+      gfxPlatform::GetPlatform()->GetParentDevicePrefs().d3d11TextureSharingWorks();
+  }
+
+  if (CanUseD3D11ImageBridge()) {
+    if (AttemptD3D11ImageBridgeDeviceCreation() == FeatureStatus::CrashedInHandler) {
+      DisableD3D11AfterCrash();
+      return;
+    }
+  }
+
+  if (AttemptD3D11ContentDeviceCreation() == FeatureStatus::CrashedInHandler) {
+    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();
+}
+
+IDXGIAdapter1*
+DeviceManagerD3D11::GetDXGIAdapter()
+{
+  if (mAdapter) {
+    return mAdapter;
+  }
+
+  nsModuleHandle dxgiModule(LoadLibrarySystem32(L"dxgi.dll"));
+  decltype(CreateDXGIFactory1)* createDXGIFactory1 = (decltype(CreateDXGIFactory1)*)
+    GetProcAddress(dxgiModule, "CreateDXGIFactory1");
+
+  if (!createDXGIFactory1) {
+    return nullptr;
+  }
+
+  // Try to use a DXGI 1.1 adapter in order to share resources
+  // across processes.
+  RefPtr<IDXGIFactory1> factory1;
+  HRESULT hr = createDXGIFactory1(__uuidof(IDXGIFactory1),
+                                  getter_AddRefs(factory1));
+  if (FAILED(hr) || !factory1) {
+    // This seems to happen with some people running the iZ3D driver.
+    // They won't get acceleration.
+    return nullptr;
+  }
+
+  if (!XRE_IsContentProcess()) {
+    // In the parent process, we pick the first adapter.
+    if (FAILED(factory1->EnumAdapters1(0, getter_AddRefs(mAdapter)))) {
+      return nullptr;
+    }
+  } else {
+    const DxgiAdapterDesc& parent =
+      gfxPlatform::GetPlatform()->GetParentDevicePrefs().adapter();
+
+    // In the child process, we search for the adapter that matches the parent
+    // process. The first adapter can be mismatched on dual-GPU systems.
+    for (UINT index = 0; ; index++) {
+      RefPtr<IDXGIAdapter1> adapter;
+      if (FAILED(factory1->EnumAdapters1(index, getter_AddRefs(adapter)))) {
+        break;
+      }
+
+      DXGI_ADAPTER_DESC desc;
+      if (SUCCEEDED(adapter->GetDesc(&desc)) &&
+          desc.AdapterLuid.HighPart == parent.AdapterLuid.HighPart &&
+          desc.AdapterLuid.LowPart == parent.AdapterLuid.LowPart &&
+          desc.VendorId == parent.VendorId &&
+          desc.DeviceId == parent.DeviceId)
+      {
+        mAdapter = adapter.forget();
+        break;
+      }
+    }
+  }
+
+  if (!mAdapter) {
+    return nullptr;
+  }
+
+  // We leak this module everywhere, we might as well do so here as well.
+  dxgiModule.disown();
+  return mAdapter;
+}
+
+bool
+DeviceManagerD3D11::AttemptD3D11DeviceCreationHelper(
+  IDXGIAdapter1* aAdapter, RefPtr<ID3D11Device>& aOutDevice, HRESULT& aResOut)
+{
+  MOZ_SEH_TRY {
+    aResOut =
+      sD3D11CreateDeviceFn(
+        aAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
+        // Use D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
+        // to prevent bug 1092260. IE 11 also uses this flag.
+        D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
+        mFeatureLevels.Elements(), mFeatureLevels.Length(),
+        D3D11_SDK_VERSION, getter_AddRefs(aOutDevice), nullptr, nullptr);
+  } MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
+    return false;
+  }
+  return true;
+}
+
+void
+DeviceManagerD3D11::AttemptD3D11DeviceCreation(FeatureState& d3d11)
+{
+  RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter();
+  if (!adapter) {
+    d3d11.SetFailed(FeatureStatus::Unavailable, "Failed to acquire a DXGI adapter",
+                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_DXGI"));
+    return;
+  }
+
+  HRESULT hr;
+  RefPtr<ID3D11Device> device;
+  if (!AttemptD3D11DeviceCreationHelper(adapter, device, hr)) {
+    gfxCriticalError() << "Crash during D3D11 device creation";
+    d3d11.SetFailed(FeatureStatus::CrashedInHandler, "Crashed trying to acquire a D3D11 device",
+                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_DEVICE1"));
+    return;
+  }
+
+  if (FAILED(hr) || !device) {
+    gfxCriticalError() << "D3D11 device creation failed: " << hexa(hr);
+    d3d11.SetFailed(FeatureStatus::Failed, "Failed to acquire a D3D11 device",
+                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_DEVICE2"));
+    return;
+  }
+  if (!D3D11Checks::DoesDeviceWork()) {
+    d3d11.SetFailed(FeatureStatus::Broken, "Direct3D11 device was determined to be broken",
+                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_BROKEN"));
+    return;
+  }
+
+  {
+    MutexAutoLock lock(mDeviceLock);
+    mCompositorDevice = device;
+  }
+
+  // Only test this when not using WARP since it can fail and cause
+  // GetDeviceRemovedReason to return weird values.
+  mTextureSharingWorks = D3D11Checks::DoesTextureSharingWork(mCompositorDevice);
+
+  if (!mTextureSharingWorks) {
+    gfxConfig::SetFailed(Feature::D3D11_HW_ANGLE,
+                         FeatureStatus::Broken,
+                         "Texture sharing doesn't work");
+  }
+
+  if (D3D11Checks::DoesRenderTargetViewNeedRecreating(mCompositorDevice)) {
+    gfxConfig::SetFailed(Feature::D3D11_HW_ANGLE,
+                         FeatureStatus::Broken,
+                         "RenderTargetViews need recreating");
+  }
+
+  // It seems like this may only happen when we're using the NVIDIA gpu
+  D3D11Checks::WarnOnAdapterMismatch(mCompositorDevice);
+
+  mCompositorDevice->SetExceptionMode(0);
+  mIsWARP = false;
+}
+
+bool
+DeviceManagerD3D11::AttemptWARPDeviceCreationHelper(
+  ScopedGfxFeatureReporter& aReporterWARP,
+  RefPtr<ID3D11Device>& aOutDevice,
+  HRESULT& aResOut)
+{
+  MOZ_SEH_TRY {
+    aResOut =
+      sD3D11CreateDeviceFn(
+        nullptr, D3D_DRIVER_TYPE_WARP, nullptr,
+        // Use D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
+        // to prevent bug 1092260. IE 11 also uses this flag.
+        D3D11_CREATE_DEVICE_BGRA_SUPPORT,
+        mFeatureLevels.Elements(), mFeatureLevels.Length(),
+        D3D11_SDK_VERSION, getter_AddRefs(aOutDevice), nullptr, nullptr);
+
+    aReporterWARP.SetSuccessful();
+  } MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
+    return false;
+  }
+  return true;
+}
+
+void
+DeviceManagerD3D11::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",
+                     NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_WARP_DEVICE"));
+    return;
+  }
+
+  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",
+                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_WARP_DEVICE2"));
+    return;
+  }
+
+  {
+    MutexAutoLock lock(mDeviceLock);
+    mCompositorDevice = 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()) {
+    mTextureSharingWorks = D3D11Checks::DoesTextureSharingWork(mCompositorDevice);
+  }
+  mCompositorDevice->SetExceptionMode(0);
+  mIsWARP = true;
+}
+
+bool
+DeviceManagerD3D11::AttemptD3D11ContentDeviceCreationHelper(
+  IDXGIAdapter1* aAdapter, HRESULT& aResOut)
+{
+  MOZ_SEH_TRY {
+    aResOut =
+      sD3D11CreateDeviceFn(
+        aAdapter, mIsWARP ? D3D_DRIVER_TYPE_WARP : D3D_DRIVER_TYPE_UNKNOWN,
+        nullptr, D3D11_CREATE_DEVICE_BGRA_SUPPORT,
+        mFeatureLevels.Elements(), mFeatureLevels.Length(),
+        D3D11_SDK_VERSION, getter_AddRefs(mContentDevice), nullptr, nullptr);
+
+  } MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
+    return false;
+  }
+  return true;
+}
+
+FeatureStatus
+DeviceManagerD3D11::AttemptD3D11ContentDeviceCreation()
+{
+  RefPtr<IDXGIAdapter1> adapter;
+  if (!mIsWARP) {
+    adapter = GetDXGIAdapter();
+    if (!adapter) {
+      return FeatureStatus::Unavailable;
+    }
+  }
+
+  HRESULT hr;
+  if (!AttemptD3D11ContentDeviceCreationHelper(adapter, hr)) {
+    gfxCriticalNote << "Recovered from crash while creating a D3D11 content device";
+    gfxWindowsPlatform::RecordContentDeviceFailure(TelemetryDeviceCode::Content);
+    return FeatureStatus::CrashedInHandler;
+  }
+
+  if (FAILED(hr) || !mContentDevice) {
+    gfxCriticalNote << "Failed to create a D3D11 content device: " << hexa(hr);
+    gfxWindowsPlatform::RecordContentDeviceFailure(TelemetryDeviceCode::Content);
+    return FeatureStatus::Failed;
+  }
+
+  // InitializeD2D() will abort early if the compositor device did not support
+  // texture sharing. If we're in the content process, we can't rely on the
+  // parent device alone: some systems have dual GPUs that are capable of
+  // binding the parent and child processes to different GPUs. As a safety net,
+  // we re-check texture sharing against the newly created D3D11 content device.
+  // If it fails, we won't use Direct2D.
+  if (XRE_IsContentProcess()) {
+    if (!D3D11Checks::DoesTextureSharingWork(mContentDevice)) {
+      mContentDevice = nullptr;
+      return FeatureStatus::Failed;
+    }
+
+    DebugOnly<bool> ok = ContentAdapterIsParentAdapter(mContentDevice);
+    MOZ_ASSERT(ok);
+  }
+
+  mContentDevice->SetExceptionMode(0);
+
+  RefPtr<ID3D10Multithread> multi;
+  hr = mContentDevice->QueryInterface(__uuidof(ID3D10Multithread), getter_AddRefs(multi));
+  if (SUCCEEDED(hr) && multi) {
+    multi->SetMultithreadProtected(TRUE);
+  }
+  return FeatureStatus::Available;
+}
+
+bool
+DeviceManagerD3D11::AttemptD3D11ImageBridgeDeviceCreationHelper(
+  IDXGIAdapter1* aAdapter,
+  HRESULT& aResOut)
+{
+  MOZ_SEH_TRY {
+    aResOut =
+      sD3D11CreateDeviceFn(GetDXGIAdapter(), D3D_DRIVER_TYPE_UNKNOWN, nullptr,
+                           D3D11_CREATE_DEVICE_BGRA_SUPPORT,
+                           mFeatureLevels.Elements(), mFeatureLevels.Length(),
+                           D3D11_SDK_VERSION, getter_AddRefs(mImageBridgeDevice), nullptr, nullptr);
+  } MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
+    return false;
+  }
+  return true;
+}
+
+FeatureStatus
+DeviceManagerD3D11::AttemptD3D11ImageBridgeDeviceCreation()
+{
+  HRESULT hr;
+  if (!AttemptD3D11ImageBridgeDeviceCreationHelper(GetDXGIAdapter(), hr)) {
+    gfxCriticalNote << "Recovered from crash while creating a D3D11 image bridge device";
+    gfxWindowsPlatform::RecordContentDeviceFailure(TelemetryDeviceCode::Image);
+    return FeatureStatus::CrashedInHandler;
+  }
+
+  if (FAILED(hr) || !mImageBridgeDevice) {
+    gfxCriticalNote << "Failed to create a content image bridge device: " << hexa(hr);
+    gfxWindowsPlatform::RecordContentDeviceFailure(TelemetryDeviceCode::Image);
+    return FeatureStatus::Failed;
+  }
+
+  mImageBridgeDevice->SetExceptionMode(0);
+  if (!D3D11Checks::DoesAlphaTextureSharingWork(mImageBridgeDevice)) {
+    mImageBridgeDevice = nullptr;
+    return FeatureStatus::Failed;
+  }
+
+  if (XRE_IsContentProcess()) {
+    ContentAdapterIsParentAdapter(mImageBridgeDevice);
+  }
+  return FeatureStatus::Available;
+}
+
+bool
+DeviceManagerD3D11::CreateD3D11DecoderDeviceHelper(
+  IDXGIAdapter1* aAdapter, RefPtr<ID3D11Device>& aDevice, HRESULT& aResOut)
+{
+  MOZ_SEH_TRY{
+    aResOut =
+      sD3D11CreateDeviceFn(
+        aAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
+        D3D11_CREATE_DEVICE_VIDEO_SUPPORT,
+        mFeatureLevels.Elements(), mFeatureLevels.Length(),
+        D3D11_SDK_VERSION, getter_AddRefs(aDevice), nullptr, nullptr);
+
+  } MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
+    return false;
+  }
+  return true;
+}
+
+RefPtr<ID3D11Device>
+DeviceManagerD3D11::CreateDecoderDevice()
+{
+   if (!sD3D11CreateDeviceFn) {
+    // We should just be on Windows Vista or XP in this case.
+    return nullptr;
+  }
+
+  RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter();
+  if (!adapter) {
+    return nullptr;
+  }
+
+  RefPtr<ID3D11Device> device;
+
+  HRESULT hr;
+  if (!CreateD3D11DecoderDeviceHelper(adapter, device, hr)) {
+    return nullptr;
+  }
+  if (FAILED(hr) || !device || !D3D11Checks::DoesDeviceWork()) {
+    return nullptr;
+  }
+
+  RefPtr<ID3D10Multithread> multi;
+  device->QueryInterface(__uuidof(ID3D10Multithread), getter_AddRefs(multi));
+
+  multi->SetMultithreadProtected(TRUE);
+  return device;
+}
+
+void
+DeviceManagerD3D11::ResetDevices()
+{
+  MutexAutoLock lock(mDeviceLock);
+
+  mCompositorDevice = nullptr;
+  mContentDevice = nullptr;
+  mImageBridgeDevice = nullptr;
+  Factory::SetDirect3D11Device(nullptr);
+}
+
+bool
+DeviceManagerD3D11::ContentAdapterIsParentAdapter(ID3D11Device* device)
+{
+  DXGI_ADAPTER_DESC desc;
+  if (!D3D11Checks::GetDxgiDesc(device, &desc)) {
+    gfxCriticalNote << "Could not query device DXGI adapter info";
+    return false;
+  }
+
+  const DxgiAdapterDesc& parent =
+    gfxPlatform::GetPlatform()->GetParentDevicePrefs().adapter();
+  if (desc.VendorId != parent.VendorId ||
+      desc.DeviceId != parent.DeviceId ||
+      desc.SubSysId != parent.SubSysId ||
+      desc.AdapterLuid.HighPart != parent.AdapterLuid.HighPart ||
+      desc.AdapterLuid.LowPart != parent.AdapterLuid.LowPart)
+  {
+    gfxCriticalNote << "VendorIDMismatch P " << hexa(parent.VendorId) << " " << hexa(desc.VendorId);
+    return false;
+  }
+
+  return true;
+}
+
+static DeviceResetReason HResultToResetReason(HRESULT hr)
+{
+  switch (hr) {
+  case DXGI_ERROR_DEVICE_HUNG:
+    return DeviceResetReason::HUNG;
+  case DXGI_ERROR_DEVICE_REMOVED:
+    return DeviceResetReason::REMOVED;
+  case DXGI_ERROR_DEVICE_RESET:
+    return DeviceResetReason::RESET;
+  case DXGI_ERROR_DRIVER_INTERNAL_ERROR:
+    return DeviceResetReason::DRIVER_ERROR;
+  case DXGI_ERROR_INVALID_CALL:
+    return DeviceResetReason::INVALID_CALL;
+  case E_OUTOFMEMORY:
+    return DeviceResetReason::OUT_OF_MEMORY;
+  default:
+    MOZ_ASSERT(false);
+  }
+  return DeviceResetReason::UNKNOWN;
+}
+
+static inline bool
+DidDeviceReset(RefPtr<ID3D11Device> aDevice, DeviceResetReason* aOutReason)
+{
+  if (!aDevice) {
+    return false;
+  }
+  HRESULT hr = aDevice->GetDeviceRemovedReason();
+  if (hr == S_OK) {
+    return false;
+  }
+
+  *aOutReason = HResultToResetReason(hr);
+  return true;
+}
+
+bool
+DeviceManagerD3D11::GetAnyDeviceRemovedReason(DeviceResetReason* aOutReason)
+{
+  // Note: this can be called off the main thread, so we need to use
+  // our threadsafe getters.
+  if (DidDeviceReset(GetCompositorDevice(), aOutReason) ||
+      DidDeviceReset(GetImageBridgeDevice(), aOutReason) ||
+      DidDeviceReset(GetContentDevice(), aOutReason))
+  {
+    return true;
+  }
+  return false;
+}
+
+void
+DeviceManagerD3D11::DisableD3D11AfterCrash()
+{
+  gfxConfig::Disable(Feature::D3D11_COMPOSITING,
+    FeatureStatus::CrashedInHandler,
+    "Crashed while acquiring a Direct3D11 device",
+    NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_CRASH"));
+  ResetDevices();
+}
+
 RefPtr<ID3D11Device>
 DeviceManagerD3D11::GetCompositorDevice()
 {
-  RefPtr<ID3D11Device> device;
-  if (!gfxWindowsPlatform::GetPlatform()->GetD3D11Device(&device))
-    return nullptr;
-  return device;
+  MutexAutoLock lock(mDeviceLock);
+  return mCompositorDevice;
 }
 
 RefPtr<ID3D11Device>
 DeviceManagerD3D11::GetImageBridgeDevice()
 {
-  RefPtr<ID3D11Device> device;
-  if (!gfxWindowsPlatform::GetPlatform()->GetD3D11ImageBridgeDevice(&device)) {
-    return nullptr;
-  }
-  return device;
+  MutexAutoLock lock(mDeviceLock);
+  return mImageBridgeDevice;
 }
 
 RefPtr<ID3D11Device>
 DeviceManagerD3D11::GetContentDevice()
 {
-  return gfxWindowsPlatform::GetPlatform()->GetD3D11ContentDevice();
+  MOZ_ASSERT(NS_IsMainThread());
+  return mContentDevice;
 }
 
 RefPtr<ID3D11Device>
 DeviceManagerD3D11::GetDeviceForCurrentThread()
 {
-  RefPtr<ID3D11Device> device;
-  if (!gfxWindowsPlatform::GetPlatform()->GetD3D11DeviceForCurrentThread(&device)) {
-    return nullptr;
+  if (NS_IsMainThread()) {
+    return GetContentDevice();
   }
-  return device;
-}
-
-RefPtr<ID3D11Device>
-DeviceManagerD3D11::CreateDecoderDevice()
-{
-  return gfxWindowsPlatform::GetPlatform()->CreateD3D11DecoderDevice();
+  return GetCompositorDevice();
 }
 
 unsigned
 DeviceManagerD3D11::GetD3D11Version() const
 {
-  return gfxWindowsPlatform::GetPlatform()->GetD3D11Version();
+  MOZ_ASSERT(NS_IsMainThread());
+  if (!mCompositorDevice) {
+    return 0;
+  }
+  return mCompositorDevice->GetFeatureLevel();
 }
 
 bool
 DeviceManagerD3D11::TextureSharingWorks() const
 {
-  return gfxWindowsPlatform::GetPlatform()->CompositorD3D11TextureSharingWorks();
+  return mTextureSharingWorks;
 }
 
 bool
 DeviceManagerD3D11::IsWARP() const
 {
-  return gfxWindowsPlatform::GetPlatform()->IsWARP();
+  return mIsWARP;
 }
 
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/thebes/DeviceManagerD3D11.h
+++ b/gfx/thebes/DeviceManagerD3D11.h
@@ -1,18 +1,22 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * 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_thebes_DeviceManagerD3D11_h
 #define mozilla_gfx_thebes_DeviceManagerD3D11_h
 
+#include "gfxPlatform.h"
+#include "gfxTelemetry.h"
+#include "mozilla/Mutex.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/StaticPtr.h"
+#include "nsTArray.h"
 
 #include <windows.h>
 #include <objbase.h>
 
 #include <dxgi.h>
 
 // This header is available in the June 2010 SDK and in the Win8 SDK
 #include <d3dcommon.h>
@@ -21,38 +25,93 @@
 #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
 
 struct ID3D11Device;
 
 namespace mozilla {
+class ScopedGfxFeatureReporter;
+
 namespace gfx {
+class FeatureState;
 
 class DeviceManagerD3D11 final
 {
 public:
   static void Init();
   static void Shutdown();
 
+  DeviceManagerD3D11();
+
   static DeviceManagerD3D11* Get() {
     return sInstance;
   }
 
   RefPtr<ID3D11Device> GetCompositorDevice();
   RefPtr<ID3D11Device> GetImageBridgeDevice();
   RefPtr<ID3D11Device> GetContentDevice();
   RefPtr<ID3D11Device> GetDeviceForCurrentThread();
   RefPtr<ID3D11Device> CreateDecoderDevice();
 
   unsigned GetD3D11Version() const;
   bool TextureSharingWorks() const;
   bool IsWARP() const;
 
+  void CreateDevices();
+  void ResetDevices();
+
+  // Call GetDeviceRemovedReason on each device until one returns
+  // a failure.
+  bool GetAnyDeviceRemovedReason(DeviceResetReason* aOutReason);
+
+private:
+  IDXGIAdapter1 *GetDXGIAdapter();
+
+  bool CanUseD3D11ImageBridge();
+
+  void DisableD3D11AfterCrash();
+
+  void AttemptD3D11DeviceCreation(mozilla::gfx::FeatureState& d3d11);
+  bool AttemptD3D11DeviceCreationHelper(
+      IDXGIAdapter1* aAdapter,
+      RefPtr<ID3D11Device>& aOutDevice,
+      HRESULT& aResOut);
+
+  void 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);
+
+  // Create a D3D11 device to be used for DXVA decoding.
+  bool CreateD3D11DecoderDeviceHelper(
+      IDXGIAdapter1* aAdapter, RefPtr<ID3D11Device>& aDevice,
+      HRESULT& aResOut);
+
+  bool ContentAdapterIsParentAdapter(ID3D11Device* device);
+
 private:
   static StaticAutoPtr<DeviceManagerD3D11> sInstance;
+
+  mozilla::Mutex mDeviceLock;
+  nsTArray<D3D_FEATURE_LEVEL> mFeatureLevels;
+  RefPtr<IDXGIAdapter1> mAdapter;
+  RefPtr<ID3D11Device> mCompositorDevice;
+  RefPtr<ID3D11Device> mContentDevice;
+  RefPtr<ID3D11Device> mImageBridgeDevice;
+  mozilla::Atomic<bool> mIsWARP;
+  mozilla::Atomic<bool> mTextureSharingWorks;
 };
 
 } // namespace gfx
 } // namespace mozilla
 
 #endif // mozilla_gfx_thebes_DeviceManagerD3D11_h
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -77,22 +77,16 @@
 #include "D3D11Checks.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
 using namespace mozilla::widget;
 using namespace mozilla::image;
 
-enum class TelemetryDeviceCode : uint32_t {
-  Content = 0,
-  Image = 1,
-  D2D1 = 2
-};
-
 DCFromDrawTarget::DCFromDrawTarget(DrawTarget& aDrawTarget)
 {
   mDC = nullptr;
   if (aDrawTarget.GetBackendType() == BackendType::CAIRO) {
     cairo_t* ctx = static_cast<cairo_t*>
       (aDrawTarget.GetNativeSurface(NativeSurfaceType::CAIRO_CONTEXT));
     if (ctx) {
       cairo_surface_t* surf = cairo_get_group_target(ctx);
@@ -333,20 +327,18 @@ public:
   }
 };
 
 NS_IMPL_ISUPPORTS(D3DSharedTexturesReporter, nsIMemoryReporter)
 
 gfxWindowsPlatform::gfxWindowsPlatform()
   : mRenderMode(RENDER_GDI)
   , mDeviceLock("gfxWindowsPlatform.mDeviceLock")
-  , mIsWARP(false)
   , mHasDeviceReset(false)
   , mHasFakeDeviceReset(false)
-  , mCompositorD3D11TextureSharingWorks(false)
   , mHasD3D9DeviceReset(false)
 {
   mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
   mUseClearTypeAlways = UNINITIALIZED_VALUE;
 
   /* 
    * Initialize COM 
    */ 
@@ -356,24 +348,19 @@ gfxWindowsPlatform::gfxWindowsPlatform()
   RegisterStrongMemoryReporter(new GPUAdapterReporter());
   RegisterStrongMemoryReporter(new D3DSharedTexturesReporter());
 }
 
 gfxWindowsPlatform::~gfxWindowsPlatform()
 {
   DeviceManagerD3D11::Shutdown();
   mDeviceManager = nullptr;
-  mD3D11Device = nullptr;
-  mD3D11ContentDevice = nullptr;
-  mD3D11ImageBridgeDevice = nullptr;
 
   mozilla::gfx::Factory::D2DCleanup();
 
-  mAdapter = nullptr;
-
   /* 
    * Uninitialize COM 
    */ 
   CoUninitialize();
 }
 
 static void
 UpdateANGLEConfig()
@@ -403,20 +390,21 @@ gfxWindowsPlatform::InitAcceleration()
   InitializeDevices();
   UpdateANGLEConfig();
   UpdateRenderMode();
 }
 
 bool
 gfxWindowsPlatform::CanUseHardwareVideoDecoding()
 {
-  if (!gfxPrefs::LayersPreferD3D9() && !mCompositorD3D11TextureSharingWorks) {
+  DeviceManagerD3D11* dm = DeviceManagerD3D11::Get();
+  if (!gfxPrefs::LayersPreferD3D9() && !dm->TextureSharingWorks()) {
     return false;
   }
-  return !IsWARP() && gfxPlatform::CanUseHardwareVideoDecoding();
+  return !dm->IsWARP() && gfxPlatform::CanUseHardwareVideoDecoding();
 }
 
 bool
 gfxWindowsPlatform::InitDWriteSupport()
 {
   MOZ_ASSERT(!mDWriteFactory && IsVistaOrLater());
 
   mozilla::ScopedGfxFeatureReporter reporter("DWrite");
@@ -452,25 +440,23 @@ gfxWindowsPlatform::HandleDeviceReset()
     return false;
   }
 
   if (!mHasFakeDeviceReset) {
     Telemetry::Accumulate(Telemetry::DEVICE_RESET_REASON, uint32_t(resetReason));
   }
 
   // Remove devices and adapters.
-  ResetD3D11Devices();
-  mAdapter = nullptr;
+  DeviceManagerD3D11::Get()->ResetDevices();
 
   // Reset local state. Note: we leave feature status variables as-is. They
   // will be recomputed by InitializeDevices().
   mHasDeviceReset = false;
   mHasFakeDeviceReset = false;
   mHasD3D9DeviceReset = false;
-  mCompositorD3D11TextureSharingWorks = false;
   mDeviceResetReason = DeviceResetReason::OK;
 
   imgLoader::NormalLoader()->ClearCache(true);
   imgLoader::NormalLoader()->ClearCache(false);
   imgLoader::PrivateBrowsingLoader()->ClearCache(true);
   imgLoader::PrivateBrowsingLoader()->ClearCache(false);
   gfxAlphaBoxBlur::ShutdownBlurCache();
 
@@ -916,58 +902,23 @@ gfxWindowsPlatform::IsFontFormatSupporte
     if (aFormatFlags != 0) {
         return false;
     }
 
     // no format hint set, need to look at data
     return true;
 }
 
-static DeviceResetReason HResultToResetReason(HRESULT hr)
-{
-  switch (hr) {
-  case DXGI_ERROR_DEVICE_HUNG:
-    return DeviceResetReason::HUNG;
-  case DXGI_ERROR_DEVICE_REMOVED:
-    return DeviceResetReason::REMOVED;
-  case DXGI_ERROR_DEVICE_RESET:
-    return DeviceResetReason::RESET;
-  case DXGI_ERROR_DRIVER_INTERNAL_ERROR:
-    return DeviceResetReason::DRIVER_ERROR;
-  case DXGI_ERROR_INVALID_CALL:
-    return DeviceResetReason::INVALID_CALL;
-  case E_OUTOFMEMORY:
-    return DeviceResetReason::OUT_OF_MEMORY;
-  default:
-    MOZ_ASSERT(false);
-  }
-  return DeviceResetReason::UNKNOWN;
-}
-
 void
 gfxWindowsPlatform::CompositorUpdated()
 {
   ForceDeviceReset(ForcedDeviceResetReason::COMPOSITOR_UPDATED);
   UpdateRenderMode();
 }
 
-bool
-gfxWindowsPlatform::IsDeviceReset(HRESULT hr, DeviceResetReason* aResetReason)
-{
-  if (hr != S_OK) {
-    mDeviceResetReason = HResultToResetReason(hr);
-    mHasDeviceReset = true;
-    if (aResetReason) {
-      *aResetReason = mDeviceResetReason;
-    }
-    return true;
-  }
-  return false;
-}
-
 void
 gfxWindowsPlatform::TestDeviceReset(DeviceResetReason aReason)
 {
   if (mHasDeviceReset) {
     return;
   }
   mHasDeviceReset = true;
   mHasFakeDeviceReset = true;
@@ -982,28 +933,24 @@ gfxWindowsPlatform::DidRenderingDeviceRe
       *aResetReason = mDeviceResetReason;
     }
     return true;
   }
   if (aResetReason) {
     *aResetReason = DeviceResetReason::OK;
   }
 
-  if (mD3D11Device) {
-    HRESULT hr = mD3D11Device->GetDeviceRemovedReason();
-    if (IsDeviceReset(hr, aResetReason)) {
-      return true;
+  if (DeviceManagerD3D11::Get()->GetAnyDeviceRemovedReason(&mDeviceResetReason)) {
+    mHasDeviceReset = true;
+    if (aResetReason) {
+      *aResetReason = mDeviceResetReason;
     }
+    return true;
   }
-  if (mD3D11ContentDevice) {
-    HRESULT hr = mD3D11ContentDevice->GetDeviceRemovedReason();
-    if (IsDeviceReset(hr, aResetReason)) {
-      return true;
-    }
-  }
+
   if (mHasD3D9DeviceReset) {
     return true;
   }
   if (XRE_IsParentProcess() && gfxPrefs::DeviceResetForTesting()) {
     TestDeviceReset((DeviceResetReason)gfxPrefs::DeviceResetForTesting());
     if (aResetReason) {
       *aResetReason = mDeviceResetReason;
     }
@@ -1411,48 +1358,16 @@ gfxWindowsPlatform::GetD3D9DeviceManager
     }
   }
 
   MutexAutoLock lock(mDeviceLock);
   result = mDeviceManager;
   return result.forget();
 }
 
-bool
-gfxWindowsPlatform::GetD3D11Device(RefPtr<ID3D11Device>* aOutDevice)
-{
-  MutexAutoLock lock(mDeviceLock);
-  *aOutDevice = mD3D11Device;
-  return !!mD3D11Device;
-}
-
-ID3D11Device*
-gfxWindowsPlatform::GetD3D11ContentDevice()
-{
-  return mD3D11ContentDevice;
-}
-
-bool
-gfxWindowsPlatform::GetD3D11ImageBridgeDevice(RefPtr<ID3D11Device>* aOutDevice)
-{
-  MutexAutoLock lock(mDeviceLock);
-  *aOutDevice = mD3D11ImageBridgeDevice;
-  return !!mD3D11ImageBridgeDevice;
-}
-
-bool
-gfxWindowsPlatform::GetD3D11DeviceForCurrentThread(RefPtr<ID3D11Device>* aOutDevice)
-{
-  if (NS_IsMainThread()) {
-    *aOutDevice = mD3D11ContentDevice;
-    return !!mD3D11ContentDevice;
-  }
-  return GetD3D11ImageBridgeDevice(aOutDevice);
-}
-
 ReadbackManagerD3D11*
 gfxWindowsPlatform::GetReadbackManager()
 {
   if (!mD3D11ReadbackManager) {
     mD3D11ReadbackManager = new ReadbackManagerD3D11();
   }
 
   return mD3D11ReadbackManager;
@@ -1470,80 +1385,16 @@ gfxWindowsPlatform::IsOptimus()
             knowIsOptimus = 1;
         } else {
             knowIsOptimus = 0;
         }
     }
     return knowIsOptimus;
 }
 
-IDXGIAdapter1*
-gfxWindowsPlatform::GetDXGIAdapter()
-{
-  if (mAdapter) {
-    return mAdapter;
-  }
-
-  nsModuleHandle dxgiModule(LoadLibrarySystem32(L"dxgi.dll"));
-  decltype(CreateDXGIFactory1)* createDXGIFactory1 = (decltype(CreateDXGIFactory1)*)
-    GetProcAddress(dxgiModule, "CreateDXGIFactory1");
-
-  if (!createDXGIFactory1) {
-    return nullptr;
-  }
-
-  // Try to use a DXGI 1.1 adapter in order to share resources
-  // across processes.
-  RefPtr<IDXGIFactory1> factory1;
-  HRESULT hr = createDXGIFactory1(__uuidof(IDXGIFactory1),
-                                  getter_AddRefs(factory1));
-  if (FAILED(hr) || !factory1) {
-    // This seems to happen with some people running the iZ3D driver.
-    // They won't get acceleration.
-    return nullptr;
-  }
-
-  if (!XRE_IsContentProcess()) {
-    // In the parent process, we pick the first adapter.
-    if (FAILED(factory1->EnumAdapters1(0, getter_AddRefs(mAdapter)))) {
-      return nullptr;
-    }
-  } else {
-    const DxgiAdapterDesc& parent = GetParentDevicePrefs().adapter();
-
-    // In the child process, we search for the adapter that matches the parent
-    // process. The first adapter can be mismatched on dual-GPU systems.
-    for (UINT index = 0; ; index++) {
-      RefPtr<IDXGIAdapter1> adapter;
-      if (FAILED(factory1->EnumAdapters1(index, getter_AddRefs(adapter)))) {
-        break;
-      }
-
-      DXGI_ADAPTER_DESC desc;
-      if (SUCCEEDED(adapter->GetDesc(&desc)) &&
-          desc.AdapterLuid.HighPart == parent.AdapterLuid.HighPart &&
-          desc.AdapterLuid.LowPart == parent.AdapterLuid.LowPart &&
-          desc.VendorId == parent.VendorId &&
-          desc.DeviceId == parent.DeviceId)
-      {
-        mAdapter = adapter.forget();
-        break;
-      }
-    }
-  }
-
-  if (!mAdapter) {
-    return nullptr;
-  }
-
-  // We leak this module everywhere, we might as well do so here as well.
-  dxgiModule.disown();
-  return mAdapter;
-}
-
 static inline bool
 IsWARPStable()
 {
   // It seems like nvdxgiwrap makes a mess of WARP. See bug 1154703.
   if (!IsWin8OrLater() || GetModuleHandleA("nvdxgiwrap.dll")) {
     return false;
   }
   return true;
@@ -1693,311 +1544,30 @@ gfxWindowsPlatform::UpdateDeviceInitData
     "Disabled by parent process");
 
 
   InitializeANGLEConfig();
 
   return true;
 }
 
-// We don't have access to the D3D11CreateDevice type in gfxWindowsPlatform.h,
-// since it doesn't include d3d11.h, so we use a static here. It should only
-// be used within InitializeD3D11.
-decltype(D3D11CreateDevice)* sD3D11CreateDeviceFn = nullptr;
-
-bool
-gfxWindowsPlatform::AttemptD3D11DeviceCreationHelper(
-  IDXGIAdapter1* aAdapter, RefPtr<ID3D11Device>& aOutDevice, HRESULT& aResOut)
-{
-  MOZ_SEH_TRY {
-    aResOut =
-      sD3D11CreateDeviceFn(
-        aAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
-        // Use D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
-        // to prevent bug 1092260. IE 11 also uses this flag.
-        D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
-        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)
-{
-  RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter();
-  if (!adapter) {
-    d3d11.SetFailed(FeatureStatus::Unavailable, "Failed to acquire a DXGI adapter",
-                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_DXGI"));
-    return;
-  }
-
-  HRESULT hr;
-  RefPtr<ID3D11Device> device;
-  if (!AttemptD3D11DeviceCreationHelper(adapter, device, hr)) {
-    gfxCriticalError() << "Crash during D3D11 device creation";
-    d3d11.SetFailed(FeatureStatus::CrashedInHandler, "Crashed trying to acquire a D3D11 device",
-                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_DEVICE1"));
-    return;
-  }
-
-  if (FAILED(hr) || !device) {
-    gfxCriticalError() << "D3D11 device creation failed: " << hexa(hr);
-    d3d11.SetFailed(FeatureStatus::Failed, "Failed to acquire a D3D11 device",
-                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_DEVICE2"));
-    return;
-  }
-  if (!D3D11Checks::DoesD3D11DeviceWork()) {
-    d3d11.SetFailed(FeatureStatus::Broken, "Direct3D11 device was determined to be broken",
-                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_BROKEN"));
-    return;
-  }
-
-  {
-    MutexAutoLock lock(mDeviceLock);
-    mD3D11Device = device;
-  }
-
-  // Only test this when not using WARP since it can fail and cause
-  // GetDeviceRemovedReason to return weird values.
-  mCompositorD3D11TextureSharingWorks =
-    D3D11Checks::DoesTextureSharingWork(mD3D11Device);
-
-  if (!mCompositorD3D11TextureSharingWorks) {
-    gfxConfig::SetFailed(Feature::D3D11_HW_ANGLE,
-                         FeatureStatus::Broken,
-                         "Texture sharing doesn't work");
-  }
-
-  if (D3D11Checks::DoesRenderTargetViewNeedRecreating(mD3D11Device)) {
-    gfxConfig::SetFailed(Feature::D3D11_HW_ANGLE,
-                         FeatureStatus::Broken,
-                         "RenderTargetViews need recreating");
-  }
-
-  // It seems like this may only happen when we're using the NVIDIA gpu
-  D3D11Checks::WarnOnAdapterMismatch(mD3D11Device);
-
-  mD3D11Device->SetExceptionMode(0);
-  mIsWARP = false;
-}
-
-bool
-gfxWindowsPlatform::AttemptWARPDeviceCreationHelper(
-  ScopedGfxFeatureReporter& aReporterWARP,
-  RefPtr<ID3D11Device>& aOutDevice,
-  HRESULT& aResOut)
-{
-  MOZ_SEH_TRY {
-    aResOut =
-      sD3D11CreateDeviceFn(
-        nullptr, D3D_DRIVER_TYPE_WARP, nullptr,
-        // Use D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
-        // to prevent bug 1092260. IE 11 also uses this flag.
-        D3D11_CREATE_DEVICE_BGRA_SUPPORT,
-        mFeatureLevels.Elements(), mFeatureLevels.Length(),
-        D3D11_SDK_VERSION, getter_AddRefs(aOutDevice), nullptr, nullptr);
-
-    aReporterWARP.SetSuccessful();
-  } MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
-    return false;
-  }
-  return true;
-}
-
-void
-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",
-                     NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_WARP_DEVICE"));
-    return;
-  }
-
-  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",
-                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_WARP_DEVICE2"));
-    return;
-  }
-
-  {
-    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 =
-      D3D11Checks::DoesTextureSharingWork(mD3D11Device);
-  }
-  mD3D11Device->SetExceptionMode(0);
-  mIsWARP = true;
-}
-
-bool
-gfxWindowsPlatform::ContentAdapterIsParentAdapter(ID3D11Device* device)
-{
-  DXGI_ADAPTER_DESC desc;
-  if (!D3D11Checks::GetDxgiDesc(device, &desc)) {
-    gfxCriticalNote << "Could not query device DXGI adapter info";
-    return false;
-  }
-
-  const DxgiAdapterDesc& parent = GetParentDevicePrefs().adapter();
-  if (desc.VendorId != parent.VendorId ||
-      desc.DeviceId != parent.DeviceId ||
-      desc.SubSysId != parent.SubSysId ||
-      desc.AdapterLuid.HighPart != parent.AdapterLuid.HighPart ||
-      desc.AdapterLuid.LowPart != parent.AdapterLuid.LowPart)
-  {
-    gfxCriticalNote << "VendorIDMismatch P " << hexa(parent.VendorId) << " " << hexa(desc.VendorId);
-    return false;
-  }
-
-  return true;
-}
-
-static void
-RecordContentDeviceFailure(TelemetryDeviceCode aDevice)
+/* static */ void
+gfxWindowsPlatform::RecordContentDeviceFailure(TelemetryDeviceCode aDevice)
 {
   // If the parent process fails to acquire a device, we record this
   // normally as part of the environment. The exceptional case we're
   // looking for here is when the parent process successfully acquires
   // a device, but the content process fails to acquire the same device.
   // This would not normally be displayed in about:support.
   if (!XRE_IsContentProcess()) {
     return;
   }
   Telemetry::Accumulate(Telemetry::GFX_CONTENT_FAILED_TO_ACQUIRE_DEVICE, uint32_t(aDevice));
 }
 
-bool
-gfxWindowsPlatform::AttemptD3D11ContentDeviceCreationHelper(
-  IDXGIAdapter1* aAdapter, HRESULT& aResOut)
-{
-  MOZ_SEH_TRY {
-    aResOut =
-      sD3D11CreateDeviceFn(
-        aAdapter, mIsWARP ? D3D_DRIVER_TYPE_WARP : D3D_DRIVER_TYPE_UNKNOWN,
-        nullptr, D3D11_CREATE_DEVICE_BGRA_SUPPORT,
-        mFeatureLevels.Elements(), mFeatureLevels.Length(),
-        D3D11_SDK_VERSION, getter_AddRefs(mD3D11ContentDevice), nullptr, nullptr);
-
-  } MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
-    return false;
-  }
-  return true;
-}
-
-FeatureStatus
-gfxWindowsPlatform::AttemptD3D11ContentDeviceCreation()
-{
-  RefPtr<IDXGIAdapter1> adapter;
-  if (!mIsWARP) {
-    adapter = GetDXGIAdapter();
-    if (!adapter) {
-      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;
-  }
-
-  if (FAILED(hr) || !mD3D11ContentDevice) {
-    gfxCriticalNote << "Failed to create a D3D11 content device: " << hexa(hr);
-    RecordContentDeviceFailure(TelemetryDeviceCode::Content);
-    return FeatureStatus::Failed;
-  }
-
-  // InitializeD2D() will abort early if the compositor device did not support
-  // texture sharing. If we're in the content process, we can't rely on the
-  // parent device alone: some systems have dual GPUs that are capable of
-  // binding the parent and child processes to different GPUs. As a safety net,
-  // we re-check texture sharing against the newly created D3D11 content device.
-  // If it fails, we won't use Direct2D.
-  if (XRE_IsContentProcess()) {
-    if (!D3D11Checks::DoesTextureSharingWork(mD3D11ContentDevice)) {
-      mD3D11ContentDevice = nullptr;
-      return FeatureStatus::Failed;
-    }
-
-    DebugOnly<bool> ok = ContentAdapterIsParentAdapter(mD3D11ContentDevice);
-    MOZ_ASSERT(ok);
-  }
-
-  mD3D11ContentDevice->SetExceptionMode(0);
-
-  RefPtr<ID3D10Multithread> multi;
-  hr = mD3D11ContentDevice->QueryInterface(__uuidof(ID3D10Multithread), getter_AddRefs(multi));
-  if (SUCCEEDED(hr) && multi) {
-    multi->SetMultithreadProtected(TRUE);
-  }
-  return FeatureStatus::Available;
-}
-
-bool
-gfxWindowsPlatform::AttemptD3D11ImageBridgeDeviceCreationHelper(
-  IDXGIAdapter1* aAdapter,
-  HRESULT& aResOut)
-{
-  MOZ_SEH_TRY {
-    aResOut =
-      sD3D11CreateDeviceFn(GetDXGIAdapter(), D3D_DRIVER_TYPE_UNKNOWN, nullptr,
-                           D3D11_CREATE_DEVICE_BGRA_SUPPORT,
-                           mFeatureLevels.Elements(), mFeatureLevels.Length(),
-                           D3D11_SDK_VERSION, getter_AddRefs(mD3D11ImageBridgeDevice), nullptr, nullptr);
-  } MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
-    return false;
-  }
-  return true;
-}
-
-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;
-  }
-
-  if (FAILED(hr) || !mD3D11ImageBridgeDevice) {
-    gfxCriticalNote << "Failed to create a content image bridge device: " << hexa(hr);
-    RecordContentDeviceFailure(TelemetryDeviceCode::Image);
-    return FeatureStatus::Failed;
-  }
-
-  mD3D11ImageBridgeDevice->SetExceptionMode(0);
-  if (!D3D11Checks::DoesAlphaTextureSharingWork(mD3D11ImageBridgeDevice)) {
-    mD3D11ImageBridgeDevice = nullptr;
-    return FeatureStatus::Failed;
-  }
-
-  if (XRE_IsContentProcess()) {
-    ContentAdapterIsParentAdapter(mD3D11ImageBridgeDevice);
-  }
-  return FeatureStatus::Available;
-}
-
 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.
   if (!gfxConfig::IsEnabled(Feature::HW_COMPOSITING)) {
@@ -2034,140 +1604,31 @@ gfxWindowsPlatform::InitializeDevices()
     // forced, we'll let them have it, as unsupported configuration.
     if (gfxPrefs::DirectWriteFontRenderingForceEnabled() && !mDWriteFactory) {
       gfxCriticalNote << "Attempting DWrite without D2D support";
       InitDWriteSupport();
     }
   }
 }
 
-bool
-gfxWindowsPlatform::CanUseD3D11ImageBridge()
-{
-  if (XRE_IsContentProcess()) {
-    if (!GetParentDevicePrefs().useD3D11ImageBridge()) {
-      return false;
-    }
-  }
-  return !mIsWARP;
-}
-
 void
 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()) {
     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",
-                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_LIB"));
-    return;
-  }
-
-  // Check if a failure was injected for testing.
-  if (gfxPrefs::DeviceFailForTesting()) {
-    d3d11.SetFailed(FeatureStatus::Failed, "Direct3D11 device failure simulated by preference",
-                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_SIM"));
-    return;
-  }
-
-  if (XRE_IsParentProcess()) {
-    if (!gfxConfig::UseFallback(Fallback::USE_D3D11_WARP_COMPOSITOR)) {
-      AttemptD3D11DeviceCreation(d3d11);
-      if (d3d11.GetValue() == FeatureStatus::CrashedInHandler) {
-        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) {
-        return;
-      }
-    }
-
-    // If we still have no device by now, exit.
-    if (!mD3D11Device) {
-      MOZ_ASSERT(!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING));
-      return;
-    }
-
-    // Either device creation function should have returned Available.
-    MOZ_ASSERT(d3d11.IsEnabled());
-  } 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);
-    mCompositorD3D11TextureSharingWorks = GetParentDevicePrefs().d3d11TextureSharingWorks();
-  }
-
-  if (CanUseD3D11ImageBridge()) {
-    if (AttemptD3D11ImageBridgeDeviceCreation() == FeatureStatus::CrashedInHandler) {
-      DisableD3D11AfterCrash();
-      return;
-    }
-  }
-
-  if (AttemptD3D11ContentDeviceCreation() == FeatureStatus::CrashedInHandler) {
-    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",
-    NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_CRASH"));
-  ResetD3D11Devices();
-}
-
-void
-gfxWindowsPlatform::ResetD3D11Devices()
-{
-  MutexAutoLock lock(mDeviceLock);
-
-  mD3D11Device = nullptr;
-  mD3D11ContentDevice = nullptr;
-  mD3D11ImageBridgeDevice = nullptr;
-  Factory::SetDirect3D11Device(nullptr);
+  DeviceManagerD3D11::Get()->CreateDevices();
 }
 
 void
 gfxWindowsPlatform::InitializeD2DConfig()
 {
   FeatureState& d2d1 = gfxConfig::GetFeature(Feature::DIRECT2D);
 
   if (!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) {
@@ -2199,116 +1660,68 @@ gfxWindowsPlatform::InitializeD2DConfig(
 
 void
 gfxWindowsPlatform::InitializeD2D()
 {
   ScopedGfxFeatureReporter d2d1_1("D2D1.1");
 
   FeatureState& d2d1 = gfxConfig::GetFeature(Feature::DIRECT2D);
 
+  DeviceManagerD3D11* dm = DeviceManagerD3D11::Get();
+
   // 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) {
+  if (dm->IsWARP()) {
     d2d1.Disable(FeatureStatus::Blocked, "Direct2D is not compatible with Direct3D11 WARP",
                  NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_WARP_BLOCK"));
   }
 
   // If we pass all the initial checks, we can proceed to runtime decisions.
   if (!d2d1.IsEnabled()) {
     return;
   }
 
   if (!Factory::SupportsD2D1()) {
     d2d1.SetFailed(FeatureStatus::Unavailable, "Failed to acquire a Direct2D 1.1 factory",
                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_FACTORY"));
     return;
   }
 
-  if (!mD3D11ContentDevice) {
+  if (!dm->GetContentDevice()) {
     d2d1.SetFailed(FeatureStatus::Failed, "Failed to acquire a Direct3D 11 content device",
                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_DEVICE"));
     return;
   }
 
-  if (!mCompositorD3D11TextureSharingWorks) {
+  if (!dm->TextureSharingWorks()) {
     d2d1.SetFailed(FeatureStatus::Failed, "Direct3D11 device does not support texture sharing",
                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_TXT_SHARING"));
     return;
   }
 
   // Using Direct2D depends on DWrite support.
   if (!mDWriteFactory && !InitDWriteSupport()) {
     d2d1.SetFailed(FeatureStatus::Failed, "Failed to initialize DirectWrite support",
                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_DWRITE"));
     return;
   }
 
   // Verify that Direct2D device creation succeeded.
-  if (!Factory::SetDirect3D11Device(mD3D11ContentDevice)) {
+  RefPtr<ID3D11Device> contentDevice = dm->GetContentDevice();
+  if (!Factory::SetDirect3D11Device(contentDevice)) {
     d2d1.SetFailed(FeatureStatus::Failed, "Failed to create a Direct2D device",
                    NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_CREATE_FAILED"));
     return;
   }
 
   MOZ_ASSERT(d2d1.IsEnabled());
   d2d1_1.SetSuccessful();
 }
 
 bool
-gfxWindowsPlatform::CreateD3D11DecoderDeviceHelper(
-  IDXGIAdapter1* aAdapter, RefPtr<ID3D11Device>& aDevice, HRESULT& aResOut)
-{
-  MOZ_SEH_TRY{
-    aResOut =
-      sD3D11CreateDeviceFn(
-        aAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
-        D3D11_CREATE_DEVICE_VIDEO_SUPPORT,
-        mFeatureLevels.Elements(), mFeatureLevels.Length(),
-        D3D11_SDK_VERSION, getter_AddRefs(aDevice), nullptr, nullptr);
-
-  } MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
-    return false;
-  }
-  return true;
-}
-
-already_AddRefed<ID3D11Device>
-gfxWindowsPlatform::CreateD3D11DecoderDevice()
-{
-   if (!sD3D11CreateDeviceFn) {
-    // We should just be on Windows Vista or XP in this case.
-    return nullptr;
-  }
-
-  RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter();
-
-  if (!adapter) {
-    return nullptr;
-  }
-
-  RefPtr<ID3D11Device> device;
-
-  HRESULT hr;
-  if (!CreateD3D11DecoderDeviceHelper(adapter, device, hr)) {
-    return nullptr;
-  }
-
-  if (FAILED(hr) || !device || !D3D11Checks::DoesD3D11DeviceWork()) {
-    return nullptr;
-  }
-
-  RefPtr<ID3D10Multithread> multi;
-  device->QueryInterface(__uuidof(ID3D10Multithread), getter_AddRefs(multi));
-
-  multi->SetMultithreadProtected(TRUE);
-
-  return device.forget();
-}
-
-bool
 gfxWindowsPlatform::DwmCompositionEnabled()
 {
   if (!IsVistaOrLater()) {
     return false;
   }
 
   MOZ_ASSERT(WinUtils::dwmIsCompositionEnabledPtr);
   BOOL dwmEnabled = false;
@@ -2597,65 +2010,58 @@ gfxWindowsPlatform::GetAcceleratedCompos
   if (gfxConfig::IsEnabled(Feature::OPENGL_COMPOSITING) && gfxPrefs::LayersPreferOpenGL()) {
     aBackends.AppendElement(LayersBackend::LAYERS_OPENGL);
   }
 
   if (gfxConfig::IsEnabled(Feature::D3D9_COMPOSITING) && gfxPrefs::LayersPreferD3D9()) {
     aBackends.AppendElement(LayersBackend::LAYERS_D3D9);
   }
 
-  if (mD3D11Device) {
+  if (DeviceManagerD3D11::Get()->GetCompositorDevice()) {
     aBackends.AppendElement(LayersBackend::LAYERS_D3D11);
   } else {
     NS_WARNING("Direct3D 11-accelerated layers are not supported on this system.");
   }
 
   if (gfxConfig::IsEnabled(Feature::D3D9_COMPOSITING) && !gfxPrefs::LayersPreferD3D9()) {
     aBackends.AppendElement(LayersBackend::LAYERS_D3D9);
   }
 }
 
-unsigned
-gfxWindowsPlatform::GetD3D11Version()
-{
-  RefPtr<ID3D11Device> device;
-  if (!GetD3D11Device(&device)) {
-    return 0;
-  }
-  return device->GetFeatureLevel();
-}
-
 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)) {
     return;
   }
 
+  DeviceManagerD3D11* dm = DeviceManagerD3D11::Get();
+
   aOut->useD3D11() = true;
-  aOut->useD3D11ImageBridge() = !!mD3D11ImageBridgeDevice;
-  aOut->d3d11TextureSharingWorks() = mCompositorD3D11TextureSharingWorks;
-  aOut->useD3D11WARP() = mIsWARP;
+  aOut->useD3D11ImageBridge() = !!dm->GetImageBridgeDevice();
+  aOut->d3d11TextureSharingWorks() = dm->TextureSharingWorks();
+  aOut->useD3D11WARP() = dm->IsWARP();
   aOut->useD2D1() = gfxConfig::IsEnabled(Feature::DIRECT2D);
 
-  if (mD3D11Device) {
+  if (RefPtr<ID3D11Device> device = dm->GetCompositorDevice()) {
     DXGI_ADAPTER_DESC desc;
-    if (!D3D11Checks::GetDxgiDesc(mD3D11Device, &desc)) {
+    if (!D3D11Checks::GetDxgiDesc(device, &desc)) {
       return;
     }
     aOut->adapter() = DxgiAdapterDesc::From(desc);
   }
 }
 
 bool
 gfxWindowsPlatform::SupportsPluginDirectDXGIDrawing()
 {
-  if (!GetD3D11ContentDevice() || !CompositorD3D11TextureSharingWorks()) {
+  DeviceManagerD3D11* dm = DeviceManagerD3D11::Get();
+  if (!dm->GetContentDevice() || !dm->TextureSharingWorks()) {
     return false;
   }
   return true;
 }
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -205,36 +205,16 @@ public:
 
     IDWriteFactory *GetDWriteFactory() { return mDWriteFactory; }
     inline bool DWriteEnabled() { return !!mDWriteFactory; }
     inline DWRITE_MEASURING_MODE DWriteMeasuringMode() { return mMeasuringMode; }
 
     IDWriteRenderingParams *GetRenderingParams(TextRenderingMode aRenderMode)
     { return mRenderingParams[aRenderMode]; }
 
-private:
-    bool GetD3D11Device(RefPtr<ID3D11Device>* aOutDevice);
-    bool GetD3D11ImageBridgeDevice(RefPtr<ID3D11Device>* aOutDevice);
-    bool GetD3D11DeviceForCurrentThread(RefPtr<ID3D11Device>* aOutDevice);
-    ID3D11Device *GetD3D11ContentDevice();
-    already_AddRefed<ID3D11Device> CreateD3D11DecoderDevice();
-    unsigned GetD3D11Version();
-
-    // Create a D3D11 device to be used for DXVA decoding.
-    bool CreateD3D11DecoderDeviceHelper(
-      IDXGIAdapter1* aAdapter, RefPtr<ID3D11Device>& aDevice,
-      HRESULT& aResOut);
-
-    // Returns whether the compositor's D3D11 device supports texture sharing.
-    bool CompositorD3D11TextureSharingWorks() const {
-      return mCompositorD3D11TextureSharingWorks;
-    }
-
-    bool IsWARP() const { return mIsWARP; }
-
 public:
     void OnDeviceManagerDestroy(mozilla::layers::DeviceManagerD3D9* aDeviceManager);
     already_AddRefed<mozilla::layers::DeviceManagerD3D9> GetD3D9DeviceManager();
     IDirect3DDevice9* GetD3D9Device();
     void D3D9DeviceReset();
 
     bool DwmCompositionEnabled();
 
@@ -260,16 +240,18 @@ public:
 
     void GetDeviceInitData(mozilla::gfx::DeviceInitData* aOut) override;
 
     bool SupportsPluginDirectBitmapDrawing() override {
       return true;
     }
     bool SupportsPluginDirectDXGIDrawing();
 
+    static void RecordContentDeviceFailure(mozilla::gfx::TelemetryDeviceCode aDevice);
+
 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;
 
@@ -291,60 +273,24 @@ private:
     void DisableD2D(mozilla::gfx::FeatureStatus aStatus, const char* aMessage,
                     const nsACString& aFailureId);
 
     void InitializeConfig();
     void InitializeD3D9Config();
     void InitializeD3D11Config();
     void InitializeD2DConfig();
 
-    void AttemptD3D11DeviceCreation(mozilla::gfx::FeatureState& d3d11);
-    bool AttemptD3D11DeviceCreationHelper(
-        IDXGIAdapter1* aAdapter,
-        RefPtr<ID3D11Device>& aOutDevice,
-        HRESULT& aResOut);
-
-    void 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);
-
     RefPtr<IDWriteFactory> mDWriteFactory;
     RefPtr<IDWriteRenderingParams> mRenderingParams[TEXT_RENDERING_COUNT];
     DWRITE_MEASURING_MODE mMeasuringMode;
 
     mozilla::Mutex mDeviceLock;
-    RefPtr<IDXGIAdapter1> mAdapter;
-    RefPtr<ID3D11Device> mD3D11Device;
-    RefPtr<ID3D11Device> mD3D11ContentDevice;
-    RefPtr<ID3D11Device> mD3D11ImageBridgeDevice;
     RefPtr<mozilla::layers::DeviceManagerD3D9> mDeviceManager;
-    mozilla::Atomic<bool> mIsWARP;
     bool mHasDeviceReset;
     bool mHasFakeDeviceReset;
-    mozilla::Atomic<bool> mCompositorD3D11TextureSharingWorks;
     mozilla::Atomic<bool> mHasD3D9DeviceReset;
     DeviceResetReason mDeviceResetReason;
 
     RefPtr<mozilla::layers::ReadbackManagerD3D11> mD3D11ReadbackManager;
 
     nsTArray<D3D_FEATURE_LEVEL> mFeatureLevels;
 };