Bug 1191971 part 2 - Add capatiblity to enable DComp r=bas
authorsotaro <sotaro.ikeda.g@gmail.com>
Thu, 29 Mar 2018 11:23:31 +0900
changeset 410537 d328d8eda8e68d669ebc77184c8d8d870cafcb7c
parent 410536 19142efa84a5b041c193b311ff06838e94d1c154
child 410538 614181fad27a9f6886a60f12cbe90a28c28e164f
push id101514
push usersikeda@mozilla.com
push dateThu, 29 Mar 2018 02:23:45 +0000
treeherdermozilla-inbound@d328d8eda8e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbas
bugs1191971
milestone61.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
Bug 1191971 part 2 - Add capatiblity to enable DComp r=bas
gfx/config/gfxVars.h
gfx/ipc/GPUParent.cpp
gfx/layers/ipc/CompositorBridgeParent.cpp
gfx/thebes/DeviceManagerDx.cpp
gfx/thebes/DeviceManagerDx.h
gfx/thebes/gfxPlatform.cpp
gfx/thebes/moz.build
gfx/webrender_bindings/RenderCompositor.h
gfx/webrender_bindings/RenderCompositorANGLE.cpp
gfx/webrender_bindings/RenderCompositorANGLE.h
gfx/webrender_bindings/moz.build
modules/libpref/init/all.js
--- a/gfx/config/gfxVars.h
+++ b/gfx/config/gfxVars.h
@@ -31,16 +31,17 @@ class gfxVarReceiver;
   _(OffscreenFormat,            gfxImageFormat,   mozilla::gfx::SurfaceFormat::X8R8G8B8_UINT32) \
   _(RequiresAcceleratedGLContextForCompositorOGL, bool, false)          \
   _(CanUseHardwareVideoDecoding, bool,            false)                \
   _(PDMWMFDisableD3D11Dlls,     nsCString,        nsCString())          \
   _(PDMWMFDisableD3D9Dlls,      nsCString,        nsCString())          \
   _(DXInterop2Blocked,          bool,             false)                \
   _(UseWebRender,               bool,             false)                \
   _(UseWebRenderANGLE,          bool,             false)                \
+  _(UseWebRenderDCompWin,       bool,             false)                \
   _(UseWebRenderProgramBinary,  bool,             false)                \
   _(WebRenderDebugFlags,        int32_t,          0)                    \
   _(ScreenDepth,                int32_t,          0)                    \
   _(GREDirectory,               nsString,         nsString())           \
   _(UseOMTP,                    bool,             false)                \
   _(AllowD3D11KeyedMutex,       bool,             false)                \
 
   /* Add new entries above this line. */
--- a/gfx/ipc/GPUParent.cpp
+++ b/gfx/ipc/GPUParent.cpp
@@ -214,16 +214,17 @@ GPUParent::RecvInit(nsTArray<GfxPrefSett
     LayerTreeOwnerTracker::Get()->Map(map.layersId(), map.ownerId());
   }
 
 #if defined(XP_WIN)
   if (gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) {
     DeviceManagerDx::Get()->CreateCompositorDevices();
   }
   if (gfxVars::UseWebRender()) {
+    DeviceManagerDx::Get()->CreateDirectCompositionDevice();
     // Ensure to initialize GfxInfo
     nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
     Unused << gfxInfo;
 
     Factory::EnsureDWriteFactory();
   }
 #endif
 
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -1748,17 +1748,17 @@ CompositorBridgeParent::AllocPWebRenderB
 #endif
   MOZ_ASSERT(wr::AsLayersId(aPipelineId) == mRootLayerTreeID);
   MOZ_ASSERT(!mWrBridge);
   MOZ_ASSERT(!mCompositor);
   MOZ_ASSERT(!mCompositorScheduler);
   MOZ_ASSERT(mWidget);
 
 #ifdef XP_WIN
-  if (XRE_IsGPUProcess() && gfx::gfxVars::UseWebRenderANGLE() && mWidget) {
+  if (DeviceManagerDx::Get()->CanUseDComp() && mWidget) {
     mWidget->AsWindows()->EnsureCompositorWindow();
   }
 #endif
 
   RefPtr<widget::CompositorWidget> widget = mWidget;
   RefPtr<wr::WebRenderAPI> api = wr::WebRenderAPI::Create(this, Move(widget), aSize);
   if (!api) {
     mWrBridge = WebRenderBridgeParent::CreateDestroyed(aPipelineId);
@@ -1798,17 +1798,17 @@ CompositorBridgeParent::DeallocPWebRende
   {
     MonitorAutoLock lock(*sIndirectLayerTreesLock);
     auto it = sIndirectLayerTrees.find(wr::AsLayersId(parent->PipelineId()));
     if (it != sIndirectLayerTrees.end()) {
       it->second.mWrBridge = nullptr;
     }
   }
 #ifdef XP_WIN
-  if (XRE_IsGPUProcess() && gfx::gfxVars::UseWebRenderANGLE() && mWidget) {
+  if (DeviceManagerDx::Get()->CanUseDComp() && mWidget) {
     mWidget->AsWindows()->DestroyCompositorWindow();
   }
 #endif
   parent->Release(); // IPDL reference
   return true;
 }
 
 RefPtr<WebRenderBridgeParent>
--- a/gfx/thebes/DeviceManagerDx.cpp
+++ b/gfx/thebes/DeviceManagerDx.cpp
@@ -20,32 +20,40 @@
 #include "mozilla/layers/CompositorThread.h"
 #include "mozilla/layers/DeviceAttachmentsD3D11.h"
 #include "mozilla/layers/MLGDeviceD3D11.h"
 #include "mozilla/layers/PaintThread.h"
 #include "nsExceptionHandler.h"
 #include "nsIGfxInfo.h"
 #include "nsPrintfCString.h"
 #include "nsString.h"
+
+#undef NTDDI_VERSION
+#define NTDDI_VERSION NTDDI_WIN8
+
 #include <d3d11.h>
+#include <dcomp.h>
 #include <ddraw.h>
 
 namespace mozilla {
 namespace gfx {
 
 using namespace mozilla::widget;
 using namespace mozilla::layers;
 
 StaticAutoPtr<DeviceManagerDx> DeviceManagerDx::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;
 
+typedef HRESULT(WINAPI * PFN_DCOMPOSITION_CREATE_DEVICE)(IDXGIDevice * dxgiDevice, REFIID iid, void **dcompositionDevice);
+PFN_DCOMPOSITION_CREATE_DEVICE sDcompCreateDeviceFn = nullptr;
+
 // We don't have access to the DirectDrawCreateEx type in gfxWindowsPlatform.h,
 // since it doesn't include ddraw.h, so we use a static here. It should only
 // be used within InitializeDirectDrawConfig.
 decltype(DirectDrawCreateEx)* sDirectDrawCreateExFn = nullptr;
 
 /* static */ void
 DeviceManagerDx::Init()
 {
@@ -96,16 +104,45 @@ DeviceManagerDx::LoadD3D11()
                     NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_FUNCPTR"));
     return false;
   }
 
   mD3D11Module.steal(module);
   return true;
 }
 
+bool
+DeviceManagerDx::LoadDcomp()
+{
+  FeatureState& d3d11 = gfxConfig::GetFeature(Feature::D3D11_COMPOSITING);
+  MOZ_ASSERT(d3d11.IsEnabled());
+  MOZ_ASSERT(gfxVars::UseWebRender());
+  MOZ_ASSERT(gfxVars::UseWebRenderANGLE());
+  MOZ_ASSERT(gfxVars::UseWebRenderDCompWin());
+
+  if (sDcompCreateDeviceFn) {
+    return true;
+  }
+
+  nsModuleHandle module(LoadLibrarySystem32(L"dcomp.dll"));
+  if (!module) {
+    return false;
+  }
+
+  sDcompCreateDeviceFn =
+    reinterpret_cast<PFN_DCOMPOSITION_CREATE_DEVICE>(
+      ::GetProcAddress(module, "DCompositionCreateDevice"));
+  if (!sDcompCreateDeviceFn) {
+    return false;
+  }
+
+  mDcompModule.steal(module);
+  return true;
+}
+
 void
 DeviceManagerDx::ReleaseD3D11()
 {
   MOZ_ASSERT(!mCompositorDevice);
   MOZ_ASSERT(!mContentDevice);
   MOZ_ASSERT(!mVRDevice);
   MOZ_ASSERT(!mDecoderDevice);
 
@@ -203,16 +240,51 @@ DeviceManagerDx::CreateVRDevice()
     NS_WARNING("Failed to acquire a D3D11 device for VR");
     return false;
   }
 
   return true;
 }
 
 void
+DeviceManagerDx::CreateDirectCompositionDevice()
+{
+  if (!gfxVars::UseWebRenderDCompWin()) {
+    return;
+  }
+
+  if (!mCompositorDevice) {
+    return;
+  }
+
+  if (!LoadDcomp()) {
+    return;
+  }
+
+  RefPtr<IDXGIDevice> dxgiDevice;
+  if (mCompositorDevice->QueryInterface(IID_PPV_ARGS((IDXGIDevice**)getter_AddRefs(dxgiDevice))) != S_OK) {
+    return;
+  }
+
+  HRESULT hr;
+  RefPtr<IDCompositionDevice> compositionDevice;
+  MOZ_SEH_TRY {
+    hr = sDcompCreateDeviceFn(dxgiDevice, IID_PPV_ARGS((IDCompositionDevice**)getter_AddRefs(compositionDevice)));
+  } MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
+    return;
+  }
+
+  if (!SUCCEEDED(hr)) {
+    return;
+  }
+
+  mDirectCompositionDevice = compositionDevice;
+}
+
+void
 DeviceManagerDx::ImportDeviceInfo(const D3D11DeviceStatus& aDeviceStatus)
 {
   MOZ_ASSERT(!ProcessOwnsCompositor());
 
   mDeviceStatus = Some(aDeviceStatus);
 }
 
 void
@@ -986,16 +1058,23 @@ DeviceManagerDx::GetVRDevice()
 {
   MutexAutoLock lock(mDeviceLock);
   if (!mVRDevice) {
     CreateVRDevice();
   }
   return mVRDevice;
 }
 
+RefPtr<IDCompositionDevice>
+DeviceManagerDx::GetDirectCompositionDevice()
+{
+  MutexAutoLock lock(mDeviceLock);
+  return mDirectCompositionDevice;
+}
+
 unsigned
 DeviceManagerDx::GetCompositorFeatureLevel() const
 {
   if (!mDeviceStatus) {
     return 0;
   }
   return mDeviceStatus->featureLevel();
 }
@@ -1059,16 +1138,23 @@ DeviceManagerDx::CanUseNV12()
 {
   MutexAutoLock lock(mDeviceLock);
   if (!mDeviceStatus) {
     return false;
   }
   return mDeviceStatus->useNV12();
 }
 
+bool
+DeviceManagerDx::CanUseDComp()
+{
+  MutexAutoLock lock(mDeviceLock);
+  return !!mDirectCompositionDevice;
+}
+
 void
 DeviceManagerDx::InitializeDirectDraw()
 {
   MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread());
 
   if (mDirectDraw) {
     // Already initialized.
     return;
--- a/gfx/thebes/DeviceManagerDx.h
+++ b/gfx/thebes/DeviceManagerDx.h
@@ -26,16 +26,17 @@
 // Win 8.0 SDK types we'll need when building using older sdks.
 #if !defined(D3D_FEATURE_LEVEL_11_1) // defined in the 8.0 SDK only
 #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;
+struct IDCompositionDevice;
 struct IDirectDraw7;
 
 namespace mozilla {
 class ScopedGfxFeatureReporter;
 namespace layers {
 class DeviceAttachmentsD3D11;
 class MLGDevice;
 } // namespace layers
@@ -52,39 +53,42 @@ public:
   DeviceManagerDx();
 
   static DeviceManagerDx* Get() {
     return sInstance;
   }
 
   RefPtr<ID3D11Device> GetCompositorDevice();
   RefPtr<ID3D11Device> GetContentDevice();
+  RefPtr<IDCompositionDevice> GetDirectCompositionDevice();
   RefPtr<ID3D11Device> GetVRDevice();
   RefPtr<ID3D11Device> CreateDecoderDevice();
   RefPtr<layers::MLGDevice> GetMLGDevice();
   IDirectDraw7* GetDirectDraw();
 
   unsigned GetCompositorFeatureLevel() const;
   bool TextureSharingWorks();
   bool IsWARP();
   bool CanUseNV12();
+  bool CanUseDComp();
 
   // Returns true if we can create a texture with
   // D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX and also
   // upload texture data during the CreateTexture2D
   // call. This crashes on some devices, so we might
   // need to avoid it.
   bool CanInitializeKeyedMutexTextures();
 
   // Intel devices on older windows versions seem to occasionally have
   // stability issues when supplying InitData to CreateTexture2D.
   bool HasCrashyInitData();
 
   bool CreateCompositorDevices();
   void CreateContentDevices();
+  void CreateDirectCompositionDevice();
 
   void GetCompositorDevices(RefPtr<ID3D11Device>* aOutDevice,
                             RefPtr<layers::DeviceAttachmentsD3D11>* aOutAttachments);
 
   void ImportDeviceInfo(const D3D11DeviceStatus& aDeviceStatus);
   void ExportDeviceInfo(D3D11DeviceStatus* aOut);
 
   void ResetDevices();
@@ -132,37 +136,42 @@ private:
                     D3D_DRIVER_TYPE aDriverType,
                     UINT aFlags,
                     HRESULT& aResOut,
                     RefPtr<ID3D11Device>& aOutDevice);
 
   bool ContentAdapterIsParentAdapter(ID3D11Device* device);
 
   bool LoadD3D11();
+  bool LoadDcomp();
   void ReleaseD3D11();
 
   // Call GetDeviceRemovedReason on each device until one returns
   // a failure.
   bool GetAnyDeviceRemovedReason(DeviceResetReason* aOutReason);
 
 private:
   static StaticAutoPtr<DeviceManagerDx> sInstance;
 
   // This is assigned during device creation. Afterwards, it is released if
   // devices failed, and "forgotten" if devices succeeded (meaning, we leak
   // the ref and unassign the module).
   nsModuleHandle mD3D11Module;
 
+  nsModuleHandle mDcompModule;
+
   mozilla::Mutex mDeviceLock;
   nsTArray<D3D_FEATURE_LEVEL> mFeatureLevels;
   RefPtr<IDXGIAdapter1> mAdapter;
   RefPtr<ID3D11Device> mCompositorDevice;
   RefPtr<ID3D11Device> mContentDevice;
   RefPtr<ID3D11Device> mVRDevice;
   RefPtr<ID3D11Device> mDecoderDevice;
+  RefPtr<IDCompositionDevice> mDirectCompositionDevice;
+
   RefPtr<layers::DeviceAttachmentsD3D11> mCompositorAttachments;
   RefPtr<layers::MLGDevice> mMLGDevice;
   bool mCompositorDeviceSupportsVideo;
 
   Maybe<D3D11DeviceStatus> mDeviceStatus;
 
   nsModuleHandle mDirectDrawDLL;
   RefPtr<IDirectDraw7> mDirectDraw;
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -2595,16 +2595,27 @@ gfxPlatform::InitWebRenderConfig()
     gfxVars::SetUseWebRender(true);
     reporter.SetSuccessful();
 
     if (XRE_IsParentProcess()) {
       Preferences::RegisterPrefixCallbackAndCall(WebRenderDebugPrefChangeCallback,
                                                  WR_DEBUG_PREF);
     }
   }
+
+#ifdef XP_WIN
+  if (Preferences::GetBool("gfx.webrender.dcomp-win.enabled", false)) {
+    // XXX relax win version to windows 8.
+    if (IsWin10OrLater() &&
+        gfxVars::UseWebRender() &&
+        gfxVars::UseWebRenderANGLE()) {
+      gfxVars::SetUseWebRenderDCompWin(true);
+    }
+  }
+#endif
 }
 
 void
 gfxPlatform::InitOMTPConfig()
 {
   ScopedGfxFeatureReporter reporter("OMTP");
 
   FeatureState& omtp = gfxConfig::GetFeature(Feature::OMTP);
--- a/gfx/thebes/moz.build
+++ b/gfx/thebes/moz.build
@@ -214,16 +214,18 @@ UNIFIED_SOURCES += [
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     UNIFIED_SOURCES += [
         'gfxMacPlatformFontList.mm',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     UNIFIED_SOURCES += [
         'D3D11Checks.cpp',
+    ]
+    SOURCES += [
         'DeviceManagerDx.cpp',
     ]
     if CONFIG['MOZ_ENABLE_SKIA_PDF']:
         EXPORTS.mozilla.gfx += [
             'PrintTargetEMF.h',
         ]
         UNIFIED_SOURCES += [
             'PrintTargetEMF.cpp',
--- a/gfx/webrender_bindings/RenderCompositor.h
+++ b/gfx/webrender_bindings/RenderCompositor.h
@@ -3,16 +3,18 @@
 /* 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_RENDERCOMPOSITOR_H
 #define MOZILLA_GFX_RENDERCOMPOSITOR_H
 
 #include "mozilla/RefPtr.h"
+#include "mozilla/UniquePtr.h"
+#include "Units.h"
 
 namespace mozilla {
 
 namespace gl {
 class GLContext;
 }
 
 namespace layers {
--- a/gfx/webrender_bindings/RenderCompositorANGLE.cpp
+++ b/gfx/webrender_bindings/RenderCompositorANGLE.cpp
@@ -5,23 +5,28 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "RenderCompositorANGLE.h"
 
 #include "GLContext.h"
 #include "GLContextEGL.h"
 #include "GLContextProvider.h"
 #include "mozilla/gfx/DeviceManagerDx.h"
+#include "mozilla/gfx/Logging.h"
 #include "mozilla/layers/HelpersD3D11.h"
 #include "mozilla/layers/SyncObject.h"
 #include "mozilla/widget/CompositorWidget.h"
 #include "mozilla/widget/WinCompositorWidget.h"
 #include "mozilla/WindowsVersion.h"
 
+#undef NTDDI_VERSION
+#define NTDDI_VERSION NTDDI_WIN8
+
 #include <d3d11.h>
+#include <dcomp.h>
 #include <dxgi1_2.h>
 
 namespace mozilla {
 namespace wr {
 
 /* static */ UniquePtr<RenderCompositor>
 RenderCompositorANGLE::Create(RefPtr<widget::CompositorWidget>&& aWidget)
 {
@@ -96,19 +101,24 @@ RenderCompositorANGLE::Initialize()
   {
     RefPtr<IDXGIAdapter> adapter;
     dxgiDevice->GetAdapter(getter_AddRefs(adapter));
 
     adapter->GetParent(IID_PPV_ARGS((IDXGIFactory**)getter_AddRefs(dxgiFactory)));
   }
 
   RefPtr<IDXGIFactory2> dxgiFactory2;
-  if (SUCCEEDED(dxgiFactory->QueryInterface((IDXGIFactory2**)getter_AddRefs(dxgiFactory2))) &&
-      dxgiFactory2 &&
-      IsWin8OrLater())
+  HRESULT hr = dxgiFactory->QueryInterface((IDXGIFactory2**)getter_AddRefs(dxgiFactory2));
+  if (FAILED(hr)) {
+    dxgiFactory2 = nullptr;
+  }
+
+  CreateSwapChainForDCompIfPossible(dxgiFactory2);
+
+  if (!mSwapChain && dxgiFactory2 && IsWin8OrLater())
   {
     RefPtr<IDXGISwapChain1> swapChain1;
 
     DXGI_SWAP_CHAIN_DESC1 desc{};
     desc.Width = 0;
     desc.Height = 0;
     desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
     desc.SampleDesc.Count = 1;
@@ -117,19 +127,19 @@ RenderCompositorANGLE::Initialize()
     // Do not use DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, since it makes HWND unreusable.
     //desc.BufferCount = 2;
     //desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
     desc.BufferCount = 1;
     desc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
     desc.Scaling = DXGI_SCALING_NONE;
     desc.Flags = 0;
 
-    HRESULT hr = dxgiFactory2->CreateSwapChainForHwnd(mDevice, hwnd, &desc,
-                                                      nullptr, nullptr,
-                                                      getter_AddRefs(swapChain1));
+    hr = dxgiFactory2->CreateSwapChainForHwnd(mDevice, hwnd, &desc,
+                                              nullptr, nullptr,
+                                              getter_AddRefs(swapChain1));
     if (SUCCEEDED(hr) && swapChain1) {
       DXGI_RGBA color = { 1.0f, 1.0f, 1.0f, 1.0f };
       swapChain1->SetBackgroundColor(&color);
       mSwapChain = swapChain1;
     }
   }
 
   if (!mSwapChain) {
@@ -188,16 +198,85 @@ RenderCompositorANGLE::Initialize()
 
   if (!ResizeBufferIfNeeded()) {
     return false;
   }
 
   return true;
 }
 
+void
+RenderCompositorANGLE::CreateSwapChainForDCompIfPossible(IDXGIFactory2* aDXGIFactory2)
+{
+  if (!aDXGIFactory2) {
+    return;
+  }
+
+  RefPtr<IDCompositionDevice> dCompDevice = gfx::DeviceManagerDx::Get()->GetDirectCompositionDevice();
+  if (!dCompDevice) {
+    return;
+  }
+  MOZ_ASSERT(XRE_IsGPUProcess());
+
+  RefPtr<IDXGIDevice> dxgiDevice;
+  mDevice->QueryInterface((IDXGIDevice**)getter_AddRefs(dxgiDevice));
+
+  RefPtr<IDXGIFactory> dxgiFactory;
+  {
+    RefPtr<IDXGIAdapter> adapter;
+    dxgiDevice->GetAdapter(getter_AddRefs(adapter));
+    adapter->GetParent(IID_PPV_ARGS((IDXGIFactory**)getter_AddRefs(dxgiFactory)));
+  }
+
+  HWND hwnd = mWidget->AsWindows()->GetCompositorHwnd();
+  if (!hwnd) {
+    gfxCriticalNote << "Compositor window was not created ";
+    return;
+  }
+
+  HRESULT hr = dCompDevice->CreateTargetForHwnd(hwnd, TRUE, getter_AddRefs(mCompositionTarget));
+  if (FAILED(hr)) {
+    gfxCriticalNote << "Could not create DCompositionTarget: " << gfx::hexa(hr);
+    return;
+  }
+
+  hr = dCompDevice->CreateVisual(getter_AddRefs(mVisual));
+  if (FAILED(hr)) {
+    gfxCriticalNote << "Could not create DCompositionVisualt: " << gfx::hexa(hr);
+    return;
+  }
+
+  RefPtr<IDXGISwapChain1> swapChain1;
+
+  DXGI_SWAP_CHAIN_DESC1 desc{};
+  // DXGI does not like 0x0 swapchains. Swap chain creation failed when 0x0 was set.
+  desc.Width = 1;
+  desc.Height = 1;
+  desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+  desc.SampleDesc.Count = 1;
+  desc.SampleDesc.Quality = 0;
+  desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+  desc.BufferCount = 2;
+  // DXGI_SCALING_NONE caused swap chain creation failure.
+  desc.Scaling     = DXGI_SCALING_STRETCH;
+  desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+  desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
+  desc.Flags         = 0;
+
+  hr = aDXGIFactory2->CreateSwapChainForComposition(mDevice, &desc, nullptr, getter_AddRefs(swapChain1));
+  if (SUCCEEDED(hr) && swapChain1) {
+    DXGI_RGBA color = { 1.0f, 1.0f, 1.0f, 1.0f };
+    swapChain1->SetBackgroundColor(&color);
+    mSwapChain = swapChain1;
+    mVisual->SetContent(swapChain1);
+    mCompositionTarget->SetRoot(mVisual);
+    mCompositionDevice = dCompDevice;
+  }
+}
+
 bool
 RenderCompositorANGLE::BeginFrame()
 {
   mWidget->AsWindows()->UpdateCompositorWndSizeIfNecessary();
 
   if (!ResizeBufferIfNeeded()) {
     return false;
   }
@@ -216,16 +295,20 @@ RenderCompositorANGLE::BeginFrame()
 
 void
 RenderCompositorANGLE::EndFrame()
 {
   InsertPresentWaitQuery();
 
   mSwapChain->Present(0, 0);
 
+  if (mCompositionDevice) {
+    mCompositionDevice->Commit();
+  }
+
   // Note: this waits on the query we inserted in the previous frame,
   // not the one we just inserted now. Example:
   //   Insert query #1
   //   Present #1
   //   (first frame, no wait)
   //   Insert query #2
   //   Present #2
   //   Wait for query #1.
@@ -239,19 +322,20 @@ RenderCompositorANGLE::EndFrame()
 
 bool
 RenderCompositorANGLE::ResizeBufferIfNeeded()
 {
   MOZ_ASSERT(mSwapChain);
 
   LayoutDeviceIntSize size = mWidget->GetClientSize();
 
-  // Set size to non negative.
-  size.width = std::max(size.width, 0);
-  size.height = std::max(size.height, 0);
+  // DXGI does not like 0x0 swapchains. ResizeBuffers() failed when 0x0 was set
+  // when DComp is used.
+  size.width = std::max(size.width, 1);
+  size.height = std::max(size.height, 1);
 
   if (mBufferSize.isSome() && mBufferSize.ref() == size) {
     MOZ_ASSERT(mEGLSurface);
     return true;
   }
 
   HRESULT hr;
   RefPtr<ID3D11Texture2D> backBuf;
@@ -347,17 +431,17 @@ RenderCompositorANGLE::GetBufferSize()
 }
 
 void
 RenderCompositorANGLE::InsertPresentWaitQuery()
 {
   CD3D11_QUERY_DESC desc(D3D11_QUERY_EVENT);
   HRESULT hr = mDevice->CreateQuery(&desc, getter_AddRefs(mNextWaitForPresentQuery));
   if (FAILED(hr) || !mNextWaitForPresentQuery) {
-    gfxWarning() << "Could not create D3D11_QUERY_EVENT: " << hexa(hr);
+    gfxWarning() << "Could not create D3D11_QUERY_EVENT: " << gfx::hexa(hr);
     return;
   }
 
   mCtx->End(mNextWaitForPresentQuery);
 }
 
 void
 RenderCompositorANGLE::WaitForPreviousPresentQuery()
--- a/gfx/webrender_bindings/RenderCompositorANGLE.h
+++ b/gfx/webrender_bindings/RenderCompositorANGLE.h
@@ -2,22 +2,27 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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_RENDERCOMPOSITOR_ANGLE_H
 #define MOZILLA_GFX_RENDERCOMPOSITOR_ANGLE_H
 
+#include "GLTypes.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/webrender/RenderCompositor.h"
 
 struct ID3D11DeviceContext;
 struct ID3D11Device;
 struct ID3D11Query;
+struct IDCompositionDevice;
+struct IDCompositionTarget;
+struct IDCompositionVisual;
+struct IDXGIFactory2;
 struct IDXGISwapChain;
 
 namespace mozilla {
 
 namespace wr {
 
 class RenderCompositorANGLE : public RenderCompositor
 {
@@ -40,25 +45,30 @@ public:
   LayoutDeviceIntSize GetBufferSize() override;
 
 protected:
   void InsertPresentWaitQuery();
   void WaitForPreviousPresentQuery();
   bool ResizeBufferIfNeeded();
   void DestroyEGLSurface();
   ID3D11Device* GetDeviceOfEGLDisplay();
+  void CreateSwapChainForDCompIfPossible(IDXGIFactory2* aDXGIFactory2);
 
   RefPtr<gl::GLContext> mGL;
   EGLConfig mEGLConfig;
   EGLSurface mEGLSurface;
 
   RefPtr<ID3D11Device> mDevice;
   RefPtr<ID3D11DeviceContext> mCtx;
   RefPtr<IDXGISwapChain> mSwapChain;
 
+  RefPtr<IDCompositionDevice> mCompositionDevice;
+  RefPtr<IDCompositionTarget> mCompositionTarget;
+  RefPtr<IDCompositionVisual> mVisual;
+
   RefPtr<ID3D11Query> mWaitForPresentQuery;
   RefPtr<ID3D11Query> mNextWaitForPresentQuery;
 
   Maybe<LayoutDeviceIntSize> mBufferSize;
 };
 
 } // namespace wr
 } // namespace mozilla
--- a/gfx/webrender_bindings/moz.build
+++ b/gfx/webrender_bindings/moz.build
@@ -46,18 +46,20 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco
 
 if CONFIG['MOZ_ENABLE_D3D10_LAYER']:
     DEFINES['MOZ_ENABLE_D3D10_LAYER'] = True
     EXPORTS.mozilla.webrender += [
         'RenderCompositorANGLE.h',
         'RenderD3D11TextureHostOGL.h',
     ]
     UNIFIED_SOURCES += [
+        'RenderD3D11TextureHostOGL.cpp',
+    ]
+    SOURCES += [
         'RenderCompositorANGLE.cpp',
-        'RenderD3D11TextureHostOGL.cpp',
     ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk3'):
     CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
     CXXFLAGS += CONFIG['CAIRO_FT_CFLAGS']
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -910,16 +910,17 @@ pref("gfx.ycbcr.accurate-conversion", fa
 pref("gfx.webrender.all", false);
 #ifdef MOZ_ENABLE_WEBRENDER
 pref("gfx.webrender.enabled", true);
 #else
 pref("gfx.webrender.enabled", false);
 #endif
 #ifdef XP_WIN
 pref("gfx.webrender.force-angle", true);
+pref("gfx.webrender.dcomp-win.enabled", true);
 pref("gfx.webrender.program-binary", true);
 #endif
 
 #ifdef XP_MACOSX
 pref("gfx.compositor.glcontext.opaque", false);
 #endif
 
 pref("gfx.webrender.highlight-painted-layers", false);