Bug 886999 - Wait until composition has finished before tearing down our NSView. r=mattwoodrow
authorMarkus Stange <mstange@themasta.com>
Wed, 09 Oct 2013 10:39:23 -0400
changeset 166419 505f83c2c5b28a79269819706ee20716285f5359
parent 166418 30cead16670909c56c2cd39198812e3e17fc8ddd
child 166420 e197b100ba539654ffd427b6f4d24187180a2ef0
push id428
push userbbajaj@mozilla.com
push dateTue, 28 Jan 2014 00:16:25 +0000
treeherdermozilla-release@cd72a7ff3a75 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs886999
milestone27.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 886999 - Wait until composition has finished before tearing down our NSView. r=mattwoodrow
widget/cocoa/nsChildView.h
widget/cocoa/nsChildView.mm
--- a/widget/cocoa/nsChildView.h
+++ b/widget/cocoa/nsChildView.h
@@ -651,16 +651,20 @@ protected:
   // weak ref to this childview's associated mozAccessible for speed reasons 
   // (we get queried for it *a lot* but don't want to own it)
   nsWeakPtr             mAccessible;
 #endif
 
 
   nsRefPtr<gfxASurface> mTempThebesSurface;
 
+  // Protects the view from being teared down while a composition is in
+  // progress on the compositor thread.
+  mozilla::Mutex mViewTearDownLock;
+
   mozilla::Mutex mEffectsLock;
 
   // May be accessed from any thread, protected
   // by mEffectsLock.
   bool mShowsResizeIndicator;
   nsIntRect mResizeIndicatorRect;
   bool mHasRoundedBottomCorners;
   int mDevPixelCornerRadius;
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -363,16 +363,17 @@ protected:
 } // unnamed namespace
 
 #pragma mark -
 
 nsChildView::nsChildView() : nsBaseWidget()
 , mView(nullptr)
 , mParentView(nullptr)
 , mParentWidget(nullptr)
+, mViewTearDownLock("ChildViewTearDown")
 , mEffectsLock("WidgetEffects")
 , mShowsResizeIndicator(false)
 , mHasRoundedBottomCorners(false)
 , mIsCoveringTitlebar(false)
 , mBackingScaleFactor(0.0)
 , mVisible(false)
 , mDrawing(false)
 , mPluginDrawing(false)
@@ -570,16 +571,20 @@ nsChildView::GetXULWindowWidget()
   }
   return nullptr;
 }
 
 NS_IMETHODIMP nsChildView::Destroy()
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
+  // Make sure that no composition is in progress while disconnecting
+  // ourselves from the view.
+  MutexAutoLock lock(mViewTearDownLock);
+
   if (mOnDestroyCalled)
     return NS_OK;
   mOnDestroyCalled = true;
 
   [mView widgetDestroyed];
 
   nsBaseWidget::Destroy();
 
@@ -2029,29 +2034,41 @@ nsChildView::CleanupWindowEffects()
 
 bool
 nsChildView::PreRender(LayerManager* aManager)
 {
   nsAutoPtr<GLManager> manager(GLManager::CreateGLManager(aManager));
   if (!manager) {
     return true;
   }
+
+  // The lock makes sure that we don't attempt to tear down the view while
+  // compositing. That would make us unable to call postRender on it when the
+  // composition is done, thus keeping the GL context locked forever.
+  mViewTearDownLock.Lock();
+
   NSOpenGLContext *glContext = (NSOpenGLContext *)manager->gl()->GetNativeData(GLContext::NativeGLContext);
-  return [(ChildView*)mView preRender:glContext];
+
+  if (![(ChildView*)mView preRender:glContext]) {
+    mViewTearDownLock.Unlock();
+    return false;
+  }
+  return true;
 }
 
 void
 nsChildView::PostRender(LayerManager* aManager)
 {
   nsAutoPtr<GLManager> manager(GLManager::CreateGLManager(aManager));
   if (!manager) {
     return;
   }
   NSOpenGLContext *glContext = (NSOpenGLContext *)manager->gl()->GetNativeData(GLContext::NativeGLContext);
   [(ChildView*)mView postRender:glContext];
+  mViewTearDownLock.Unlock();
 }
 
 void
 nsChildView::DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect)
 {
   nsAutoPtr<GLManager> manager(GLManager::CreateGLManager(aManager));
   if (manager) {
     DrawWindowOverlay(manager, aRect);