Bug 1467363 - Protect access to mTransparentSurface with a lock. r=rhunt, a=IanN CLOSED TREE DONTBUILD SEAMONKEY_2_49_ESR_RELBRANCH
authorBas Schouten <bschouten@mozilla.com>
Thu, 21 Jun 2018 22:17:48 +0200
branchSEAMONKEY_2_49_ESR_RELBRANCH
changeset 357535 f8828ed8d6836a04e990eee5330610fe467129ef
parent 357534 d43a8a8d75310c964f6115a24b4d416dfaf8a19d
child 357536 c88a220931ae59e6270686bb0232f9a6fbcc3bab
push id7834
push userfrgrahl@gmx.net
push dateSun, 13 Jan 2019 12:17:02 +0000
treeherdermozilla-esr52@6e4ad8a8f2e8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrhunt, IanN
bugs1467363
milestone52.9.1
Bug 1467363 - Protect access to mTransparentSurface with a lock. r=rhunt, a=IanN CLOSED TREE DONTBUILD mozilla-esr52 SEAMONKEY_2_49_ESR_RELBRANCH
widget/windows/WinCompositorWidget.cpp
widget/windows/WinCompositorWidget.h
widget/windows/nsWindowGfx.cpp
--- a/widget/windows/WinCompositorWidget.cpp
+++ b/widget/windows/WinCompositorWidget.cpp
@@ -13,20 +13,22 @@
 #include "VsyncDispatcher.h"
 
 #include <ddraw.h>
 
 namespace mozilla {
 namespace widget {
 
 using namespace mozilla::gfx;
+using namespace mozilla;
 
 WinCompositorWidget::WinCompositorWidget(const CompositorWidgetInitData& aInitData)
  : mWidgetKey(aInitData.widgetKey()),
    mWnd(reinterpret_cast<HWND>(aInitData.hWnd())),
+   mTransparentSurfaceLock("mTransparentSurfaceLock"),
    mTransparencyMode(static_cast<nsTransparencyMode>(aInitData.transparencyMode())),
    mMemoryDC(nullptr),
    mCompositeDC(nullptr),
    mLockedBackBufferData(nullptr)
 {
   MOZ_ASSERT(mWnd && ::IsWindow(mWnd));
 
   // mNotDeferEndRemoteDrawing is set on the main thread during init,
@@ -34,16 +36,17 @@ WinCompositorWidget::WinCompositorWidget
   mNotDeferEndRemoteDrawing = gfxPrefs::LayersCompositionFrameRate() == 0 ||
                               gfxPlatform::IsInLayoutAsapMode() ||
                               gfxPlatform::ForceSoftwareVsync();
 }
 
 void
 WinCompositorWidget::OnDestroyWindow()
 {
+  MutexAutoLock lock(mTransparentSurfaceLock);
   mTransparentSurface = nullptr;
   mMemoryDC = nullptr;
 }
 
 bool
 WinCompositorWidget::PreRender(WidgetRenderingContext* aContext)
 {
   // This can block waiting for WM_SETTEXT to finish
@@ -70,16 +73,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
@@ -224,57 +229,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_CompositorWidgetParent_h
 #define widget_windows_CompositorWidgetParent_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 CompositorWidgetDelegate
@@ -78,28 +79,31 @@ public:
 
   HDC GetTransparentDC() const override {
     return mMemoryDC;
   }
   HWND GetHwnd() const {
     return mWnd;
   }
 
+  mozilla::Mutex& GetTransparentSurfaceLock() { return mTransparentSurfaceLock; }
+
 private:
   HDC GetWindowSurface();
   void FreeWindowSurface(HDC dc);
 
   void CreateTransparentSurface(const gfx::IntSize& aSize);
 
 private:
   uintptr_t mWidgetKey;
   HWND mWnd;
   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;
 
--- a/widget/windows/nsWindowGfx.cpp
+++ b/widget/windows/nsWindowGfx.cpp
@@ -315,16 +315,18 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t
     switch (GetLayerManager()->GetBackendType()) {
       case LayersBackend::LAYERS_BASIC:
         {
           RefPtr<gfxASurface> targetSurface;
 
 #if defined(MOZ_XUL)
           // don't support transparency for non-GDI rendering, for now
           if (eTransparencyTransparent == mTransparencyMode) {
+            // This mutex needs to be held when EnsureTransparentSurface is called.
+            MutexAutoLock lock(mBasicLayersSurface->GetTransparentSurfaceLock());
             targetSurface = mBasicLayersSurface->EnsureTransparentSurface();
           }
 #endif
 
           RefPtr<gfxWindowsSurface> targetSurfaceWin;
           if (!targetSurface)
           {
             uint32_t flags = (mTransparencyMode == eTransparencyOpaque) ? 0 :