Bug 1467363: Protect access to mTransparentSurface with a lock. r=rhunt
☠☠ backed out by 6c29e4fc89c7 ☠ ☠
authorBas Schouten <bschouten@mozilla.com>
Thu, 21 Jun 2018 22:17:48 +0200
changeset 477520 0ef199e4d83dad031c14f97d9524a30f0b0cf97e
parent 477519 9d9f90b47174476dca400ab03cf88512c41cce68
child 477521 2a08d68ca8f3bde85b102fd4958182b99bf0886c
push id9385
push userdluca@mozilla.com
push dateFri, 22 Jun 2018 15:47:18 +0000
treeherdermozilla-beta@82a9a1027e2b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrhunt
bugs1467363
milestone62.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 1467363: Protect access to mTransparentSurface with a lock. r=rhunt MozReview-Commit-ID: 6E9YpDIcuQk
widget/windows/WinCompositorWidget.cpp
widget/windows/WinCompositorWidget.h
--- a/widget/windows/WinCompositorWidget.cpp
+++ b/widget/windows/WinCompositorWidget.cpp
@@ -14,23 +14,25 @@
 #include "WinCompositorWindowThread.h"
 
 #include <ddraw.h>
 
 namespace mozilla {
 namespace widget {
 
 using namespace mozilla::gfx;
+using namespace mozilla;
 
 WinCompositorWidget::WinCompositorWidget(const WinCompositorWidgetInitData& aInitData,
                                          const layers::CompositorOptions& aOptions)
  : CompositorWidget(aOptions)
  , mWidgetKey(aInitData.widgetKey()),
    mWnd(reinterpret_cast<HWND>(aInitData.hWnd())),
    mCompositorWnd(nullptr),
+   mTransparentSurfaceLock("mTransparentSurfaceLock"),
    mTransparencyMode(aInitData.transparencyMode()),
    mMemoryDC(nullptr),
    mCompositeDC(nullptr),
    mLockedBackBufferData(nullptr)
 {
   MOZ_ASSERT(mWnd && ::IsWindow(mWnd));
 
   // mNotDeferEndRemoteDrawing is set on the main thread during init,
@@ -43,16 +45,17 @@ WinCompositorWidget::WinCompositorWidget
 WinCompositorWidget::~WinCompositorWidget()
 {
   DestroyCompositorWindow();
 }
 
 void
 WinCompositorWidget::OnDestroyWindow()
 {
+  MutexAutoLock lock(mTransparentSurfaceLock);
   mTransparentSurface = nullptr;
   mMemoryDC = nullptr;
 }
 
 bool
 WinCompositorWidget::PreRender(WidgetRenderingContext* aContext)
 {
   // This can block waiting for WM_SETTEXT to finish
@@ -79,16 +82,18 @@ WinCompositorWidget::GetClientSize()
   return LayoutDeviceIntSize(
     r.right - r.left,
     r.bottom - r.top);
 }
 
 already_AddRefed<gfx::DrawTarget>
 WinCompositorWidget::StartRemoteDrawing()
 {
+  MutexAutoLock lock(mTransparentSurfaceLock);
+
   MOZ_ASSERT(!mCompositeDC);
 
   RefPtr<gfxASurface> surf;
   if (mTransparencyMode == eTransparencyTransparent) {
     surf = EnsureTransparentSurface();
   }
 
   // Must call this after EnsureTransparentSurface(), since it could update
@@ -239,57 +244,61 @@ void
 WinCompositorWidget::LeavePresentLock()
 {
   mPresentLock.Leave();
 }
 
 RefPtr<gfxASurface>
 WinCompositorWidget::EnsureTransparentSurface()
 {
+  mTransparentSurfaceLock.AssertCurrentThreadOwns();
   MOZ_ASSERT(mTransparencyMode == eTransparencyTransparent);
 
   IntSize size = GetClientSize().ToUnknownSize();
   if (!mTransparentSurface || mTransparentSurface->GetSize() != size) {
     mTransparentSurface = nullptr;
     mMemoryDC = nullptr;
     CreateTransparentSurface(size);
   }
 
   RefPtr<gfxASurface> surface = mTransparentSurface;
   return surface.forget();
 }
 
 void
 WinCompositorWidget::CreateTransparentSurface(const gfx::IntSize& aSize)
 {
+  mTransparentSurfaceLock.AssertCurrentThreadOwns();
   MOZ_ASSERT(!mTransparentSurface && !mMemoryDC);
   RefPtr<gfxWindowsSurface> surface = new gfxWindowsSurface(aSize, SurfaceFormat::A8R8G8B8_UINT32);
   mTransparentSurface = surface;
   mMemoryDC = surface->GetDC();
 }
 
 void
 WinCompositorWidget::UpdateTransparency(nsTransparencyMode aMode)
 {
+  MutexAutoLock lock(mTransparentSurfaceLock);
   if (mTransparencyMode == aMode) {
     return;
   }
 
   mTransparencyMode = aMode;
   mTransparentSurface = nullptr;
   mMemoryDC = nullptr;
 
   if (mTransparencyMode == eTransparencyTransparent) {
     EnsureTransparentSurface();
   }
 }
 
 void
 WinCompositorWidget::ClearTransparentWindow()
 {
+  MutexAutoLock lock(mTransparentSurfaceLock);
   if (!mTransparentSurface) {
     return;
   }
 
   EnsureTransparentSurface();
 
   IntSize size = mTransparentSurface->GetSize();
   if (!size.IsEmpty()) {
--- a/widget/windows/WinCompositorWidget.h
+++ b/widget/windows/WinCompositorWidget.h
@@ -5,16 +5,17 @@
 
 #ifndef widget_windows_WinCompositorWidget_h
 #define widget_windows_WinCompositorWidget_h
 
 #include "CompositorWidget.h"
 #include "gfxASurface.h"
 #include "mozilla/gfx/CriticalSection.h"
 #include "mozilla/gfx/Point.h"
+#include "mozilla/Mutex.h"
 #include "nsIWidget.h"
 
 class nsWindow;
 
 namespace mozilla {
 namespace widget {
 
 class PlatformCompositorWidgetDelegate
@@ -119,16 +120,17 @@ private:
   HWND mWnd;
 
   HWND mCompositorWnd;
   LayoutDeviceIntSize mLastCompositorWndSize;
 
   gfx::CriticalSection mPresentLock;
 
   // Transparency handling.
+  mozilla::Mutex mTransparentSurfaceLock;
   nsTransparencyMode mTransparencyMode;
   RefPtr<gfxASurface> mTransparentSurface;
   HDC mMemoryDC;
   HDC mCompositeDC;
 
   // Locked back buffer of BasicCompositor
   uint8_t* mLockedBackBufferData;