Bug 1549674: Use the CompositorWindow to draw to when using DoubleBuffering. r=sotaro
authorBas Schouten <bschouten@mozilla.com>
Fri, 10 May 2019 00:10:35 +0200
changeset 473447 e96752781d2d3961d797cec48c5357c4ec293a23
parent 473446 d1e6799af0a63a17a08db30cbe86cb22ce585c43
child 473448 2abcefb31ba7b2a1c573edc5695b772826c6a078
child 473503 77be2a5365737eca914cfcf06129cf21f4024c6c
push id35997
push userdvarga@mozilla.com
push dateFri, 10 May 2019 21:49:31 +0000
treeherdermozilla-central@2abcefb31ba7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssotaro
bugs1549674
milestone68.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 1549674: Use the CompositorWindow to draw to when using DoubleBuffering. r=sotaro Differential Revision: https://phabricator.services.mozilla.com/D30569
gfx/ipc/GPUParent.cpp
gfx/layers/d3d11/CompositorD3D11.cpp
gfx/layers/d3d11/MLGDeviceD3D11.cpp
gfx/layers/ipc/CompositorBridgeParent.cpp
--- a/gfx/ipc/GPUParent.cpp
+++ b/gfx/ipc/GPUParent.cpp
@@ -47,16 +47,18 @@
 #include "VRGPUChild.h"
 #include "VRManager.h"
 #include "VRManagerParent.h"
 #include "VsyncBridgeParent.h"
 #include "cairo.h"
 #include "skia/include/core/SkGraphics.h"
 #if defined(XP_WIN)
 #  include "mozilla/gfx/DeviceManagerDx.h"
+#  include "mozilla/widget/WinCompositorWindowThread.h"
+#  include "mozilla/WindowsVersion.h"
 #  include <process.h>
 #  include <dwrite.h>
 #endif
 #ifdef MOZ_WIDGET_GTK
 #  include <gtk/gtk.h>
 #  include "skia/include/ports/SkTypeface_cairo.h"
 #endif
 #ifdef MOZ_GECKO_PROFILER
@@ -247,16 +249,25 @@ mozilla::ipc::IPCResult GPUParent::RecvI
   }
 #endif
 
   // Make sure to do this *after* we update gfxVars above.
   if (gfxVars::UseWebRender()) {
     wr::RenderThread::Start();
     image::ImageMemoryReporter::InitForWebRender();
   }
+#ifdef XP_WIN
+  else {
+    if (gfxPrefs::Direct3D11UseDoubleBuffering() && IsWin10OrLater()) {
+      // This is needed to avoid freezing the window on a device crash on double
+      // buffering, see bug 1549674.
+      widget::WinCompositorWindowThread::Start();
+    }
+  }
+#endif
 
   VRManager::ManagerInit();
   // Send a message to the UI process that we're done.
   GPUDeviceData data;
   RecvGetDeviceStatus(&data);
   Unused << SendInitComplete(data);
 
   Telemetry::AccumulateTimeDelta(Telemetry::GPU_PROCESS_INITIALIZATION_TIME_MS,
@@ -496,16 +507,21 @@ void GPUParent::ActorDestroy(ActorDestro
   }
   VideoDecoderManagerParent::ShutdownVideoBridge();
   CompositorThreadHolder::Shutdown();
   // There is a case that RenderThread exists when gfxVars::UseWebRender() is
   // false. This could happen when WebRender was fallbacked to compositor.
   if (wr::RenderThread::Get()) {
     wr::RenderThread::ShutDown();
   }
+#ifdef XP_WIN
+  else if (gfxPrefs::Direct3D11UseDoubleBuffering() && IsWin10OrLater()) {
+    widget::WinCompositorWindowThread::ShutDown();
+  }
+#endif
 
   image::ImageMemoryReporter::ShutdownForWebRender();
 
   // Shut down the default GL context provider.
   gl::GLContextProvider::Shutdown();
 
 #if defined(XP_WIN)
   // The above shutdown calls operate on the available context providers on
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -1413,16 +1413,18 @@ void CompositorD3D11::PrepareViewport(co
 
   memcpy(&mVSConstants.projection, &aProjection._11,
          sizeof(mVSConstants.projection));
 }
 
 void CompositorD3D11::EnsureSize() { mSize = mWidget->GetClientSize(); }
 
 bool CompositorD3D11::VerifyBufferSize() {
+  mWidget->AsWindows()->UpdateCompositorWndSizeIfNecessary();
+
   DXGI_SWAP_CHAIN_DESC swapDesc;
   HRESULT hr;
 
   hr = mSwapChain->GetDesc(&swapDesc);
   if (FAILED(hr)) {
     gfxCriticalError() << "Failed to get the description " << hexa(hr) << ", "
                        << mSize << ", " << (int)mVerifyBuffersFailed;
     HandleError(hr);
--- a/gfx/layers/d3d11/MLGDeviceD3D11.cpp
+++ b/gfx/layers/d3d11/MLGDeviceD3D11.cpp
@@ -229,25 +229,28 @@ bool MLGSwapChainD3D11::Initialize(Compo
     dxgiDevice->GetAdapter(getter_AddRefs(adapter));
 
     adapter->GetParent(IID_PPV_ARGS(dxgiFactory.StartAssignment()));
   }
 
   RefPtr<IDXGIFactory2> dxgiFactory2;
   if (gfxPrefs::Direct3D11UseDoubleBuffering() &&
       SUCCEEDED(dxgiFactory->QueryInterface(dxgiFactory2.StartAssignment())) &&
-      dxgiFactory2 && IsWin10OrLater()) {
+      dxgiFactory2 && IsWin10OrLater() && XRE_IsGPUProcess()) {
     // DXGI_SCALING_NONE is not available on Windows 7 with the Platform Update:
     // This looks awful for things like the awesome bar and browser window
     // resizing, so we don't use a flip buffer chain here. (Note when using
     // EFFECT_SEQUENTIAL Windows doesn't stretch the surface when resizing).
     //
     // We choose not to run this on platforms earlier than Windows 10 because
     // it appears sometimes this breaks our ability to test ASAP compositing,
     // which breaks Talos.
+    //
+    // When the GPU process is disabled we don't have a compositor window which
+    // can lead to issues with Window re-use so we don't use this.
     DXGI_SWAP_CHAIN_DESC1 desc;
     ::ZeroMemory(&desc, sizeof(desc));
     desc.Width = 0;
     desc.Height = 0;
     desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
     desc.SampleDesc.Count = 1;
     desc.SampleDesc.Quality = 0;
     desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
@@ -370,16 +373,18 @@ void MLGSwapChainD3D11::UpdateBackBuffer
   }
 
   // The back and front buffers are now in sync.
   mBackBufferInvalid = mFrontBufferInvalid;
   MOZ_ASSERT(!mBackBufferInvalid.IsEmpty());
 }
 
 bool MLGSwapChainD3D11::ResizeBuffers(const IntSize& aSize) {
+  mWidget->AsWindows()->UpdateCompositorWndSizeIfNecessary();
+
   // We have to clear all references to the old backbuffer before resizing.
   mRT = nullptr;
 
   // Clear the size before re-allocating. If allocation fails we want to try
   // again, because we had to sacrifice our original backbuffer to try
   // resizing.
   mSize = IntSize(0, 0);
 
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -75,16 +75,17 @@
 #include "nsISupportsImpl.h"  // for MOZ_COUNT_CTOR, etc
 #include "nsIWidget.h"        // for nsIWidget
 #include "nsTArray.h"         // for nsTArray
 #include "nsThreadUtils.h"    // for NS_IsMainThread
 #include "nsXULAppAPI.h"      // for XRE_GetIOMessageLoop
 #ifdef XP_WIN
 #  include "mozilla/layers/CompositorD3D11.h"
 #  include "mozilla/widget/WinCompositorWidget.h"
+#  include "mozilla/WindowsVersion.h"
 #endif
 #include "GeckoProfiler.h"
 #include "mozilla/ipc/ProtocolTypes.h"
 #include "mozilla/Unused.h"
 #include "mozilla/Hal.h"
 #include "mozilla/HalTypes.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/Telemetry.h"
@@ -1545,16 +1546,25 @@ RefPtr<Compositor> CompositorBridgeParen
 
   return nullptr;
 }
 
 PLayerTransactionParent* CompositorBridgeParent::AllocPLayerTransactionParent(
     const nsTArray<LayersBackend>& aBackendHints, const LayersId& aId) {
   MOZ_ASSERT(!aId.IsValid());
 
+#ifdef XP_WIN
+  // This is needed to avoid freezing the window on a device crash on double
+  // buffering, see bug 1549674.
+  if (gfxPrefs::Direct3D11UseDoubleBuffering() && IsWin10OrLater() &&
+      XRE_IsGPUProcess()) {
+    mWidget->AsWindows()->EnsureCompositorWindow();
+  }
+#endif
+
   InitializeLayerManager(aBackendHints);
 
   if (!mLayerManager) {
     NS_WARNING("Failed to initialise Compositor");
     LayerTransactionParent* p = new LayerTransactionParent(
         /* aManager */ nullptr, this, /* aAnimStorage */ nullptr,
         mRootLayerTreeID, mVsyncRate);
     p->AddIPDLReference();