Bug 914437 - Don't composite windows that are not open. r=mattwoodrow
authorMarkus Stange <mstange@themasta.com>
Wed, 09 Oct 2013 10:39:22 -0400
changeset 166413 03f9c4191bf0b6b0a52bd4cbd8c1a837ff40f0dc
parent 166412 ececa191d8b5c87f8862d23916b5dc7cb24335e5
child 166414 30c25c68bb3edede082f5248f9ae6763ce8201bf
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
bugs914437
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 914437 - Don't composite windows that are not open. r=mattwoodrow
gfx/layers/composite/LayerManagerComposite.cpp
widget/cocoa/nsChildView.h
widget/cocoa/nsChildView.mm
widget/cocoa/nsCocoaWindow.h
widget/cocoa/nsCocoaWindow.mm
widget/nsIWidget.h
widget/xpwidgets/nsBaseWidget.h
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -321,17 +321,19 @@ LayerManagerComposite::Render()
 
   if (mComposer2D && mComposer2D->TryRender(mRoot, mWorldMatrix)) {
     mCompositor->EndFrameForExternalComposition(mWorldMatrix);
     return;
   }
 
   {
     PROFILER_LABEL("LayerManagerComposite", "PreRender");
-    mCompositor->GetWidget()->PreRender(this);
+    if (!mCompositor->GetWidget()->PreRender(this)) {
+      return;
+    }
   }
 
   nsIntRect clipRect;
   Rect bounds(mRenderBounds.x, mRenderBounds.y, mRenderBounds.width, mRenderBounds.height);
   Rect actualBounds;
   if (mRoot->GetClipRect()) {
     clipRect = *mRoot->GetClipRect();
     WorldTransformRect(clipRect);
--- a/widget/cocoa/nsChildView.h
+++ b/widget/cocoa/nsChildView.h
@@ -340,17 +340,17 @@ enum {
 
 - (BOOL)isPluginView;
 
 // Are we processing an NSLeftMouseDown event that will fail to click through?
 // If so, we shouldn't focus or unfocus a plugin.
 - (BOOL)isInFailingLeftClickThrough;
 
 - (void)setGLContext:(NSOpenGLContext *)aGLContext;
-- (void)preRender:(NSOpenGLContext *)aGLContext;
+- (bool)preRender:(NSOpenGLContext *)aGLContext;
 
 - (BOOL)isCoveringTitlebar;
 
 // Simple gestures support
 //
 // XXX - The swipeWithEvent, beginGestureWithEvent, magnifyWithEvent,
 // rotateWithEvent, and endGestureWithEvent methods are part of a
 // PRIVATE interface exported by nsResponder and reverse-engineering
@@ -548,17 +548,17 @@ public:
 #ifdef ACCESSIBILITY
   already_AddRefed<mozilla::a11y::Accessible> GetDocumentAccessible();
 #endif
 
   virtual void CreateCompositor();
   virtual gfxASurface* GetThebesSurface();
   virtual void PrepareWindowEffects() MOZ_OVERRIDE;
   virtual void CleanupWindowEffects() MOZ_OVERRIDE;
-  virtual void PreRender(LayerManager* aManager) MOZ_OVERRIDE;
+  virtual bool PreRender(LayerManager* aManager) MOZ_OVERRIDE;
   virtual void DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect) MOZ_OVERRIDE;
 
   virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries);
 
   void              HidePlugin();
   void              UpdatePluginPort();
 
   void              ResetParent();
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -2034,25 +2034,25 @@ nsChildView::PrepareWindowEffects()
 void
 nsChildView::CleanupWindowEffects()
 {
   mResizerImage = nullptr;
   mCornerMaskImage = nullptr;
   mTitlebarImage = nullptr;
 }
 
-void
+bool
 nsChildView::PreRender(LayerManager* aManager)
 {
   nsAutoPtr<GLManager> manager(GLManager::CreateGLManager(aManager));
   if (!manager) {
-    return;
+    return true;
   }
   NSOpenGLContext *glContext = (NSOpenGLContext *)manager->gl()->GetNativeData(GLContext::NativeGLContext);
-  [(ChildView*)mView preRender:glContext];
+  return [(ChildView*)mView preRender:glContext];
 }
 
 void
 nsChildView::DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect)
 {
   nsAutoPtr<GLManager> manager(GLManager::CreateGLManager(aManager));
   if (manager) {
     DrawWindowOverlay(manager, aRect);
@@ -2437,17 +2437,19 @@ nsChildView::CleanupRemoteDrawing()
   mResizerImage = nullptr;
   mTitlebarImage = nullptr;
   mGLPresenter = nullptr;
 }
 
 void
 nsChildView::DoRemoteComposition(const nsIntRect& aRenderRect)
 {
-  [(ChildView*)mView preRender:mGLPresenter->GetNSOpenGLContext()];
+  if (![(ChildView*)mView preRender:mGLPresenter->GetNSOpenGLContext()]) {
+    return;
+  }
   mGLPresenter->BeginFrame(aRenderRect.Size());
 
   // Draw the result from the basic compositor.
   mBasicCompositorImage->Draw(mGLPresenter, nsIntPoint(0, 0));
 
   // DrawWindowOverlay doesn't do anything for non-GL, so it didn't paint
   // anything during the basic compositor transaction. Draw the overlay now.
   DrawWindowOverlay(mGLPresenter, aRenderRect);
@@ -2878,28 +2880,36 @@ NSEvent* gLastDragMouseDownEvent = nil;
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   mGLContext = aGLContext;
   [mGLContext retain];
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
--(void)preRender:(NSOpenGLContext *)aGLContext
-{
-  NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
+- (bool)preRender:(NSOpenGLContext *)aGLContext
+{
+  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
 
   if (!mGLContext) {
     [self setGLContext:aGLContext];
   }
 
+  if ([[self window] isKindOfClass:[BaseWindow class]] &&
+      ![(BaseWindow*)[self window] isVisibleOrBeingShown]) {
+    // Before the window is shown, our GL context's front FBO is not
+    // framebuffer complete, so we refuse to render.
+    return false;
+  }
   [aGLContext setView:self];
   [aGLContext update];
 
-  NS_OBJC_END_TRY_ABORT_BLOCK;
+  return true;
+
+  NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
 }
 
 - (void)dealloc
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   [mGLContext release];
   [mPendingDirtyRects release];
--- a/widget/cocoa/nsCocoaWindow.h
+++ b/widget/cocoa/nsCocoaWindow.h
@@ -71,16 +71,18 @@ typedef struct _nsCocoaWindowList {
   BOOL mScheduledShadowInvalidation;
 
   // DPI cache. Getting the physical screen size (CGDisplayScreenSize)
   // is ridiculously slow, so we cache it in the toplevel window for all
   // descendants to use.
   float mDPI;
 
   NSTrackingArea* mTrackingArea;
+
+  BOOL mBeingShown;
 }
 
 - (void)importState:(NSDictionary*)aState;
 - (NSMutableDictionary*)exportState;
 - (void)setDrawsContentsIntoWindowFrame:(BOOL)aState;
 - (BOOL)drawsContentsIntoWindowFrame;
 - (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive;
 - (NSColor*)titlebarColorForActiveWindow:(BOOL)aActive;
@@ -90,16 +92,18 @@ typedef struct _nsCocoaWindowList {
 - (float)getDPI;
 
 - (void)mouseEntered:(NSEvent*)aEvent;
 - (void)mouseExited:(NSEvent*)aEvent;
 - (void)mouseMoved:(NSEvent*)aEvent;
 - (void)updateTrackingArea;
 - (NSView*)trackingAreaView;
 
+- (BOOL)isVisibleOrBeingShown;
+
 - (ChildView*)mainChildView;
 
 - (NSArray*)titlebarControls;
 
 @end
 
 @interface NSWindow (Undocumented)
 
--- a/widget/cocoa/nsCocoaWindow.mm
+++ b/widget/cocoa/nsCocoaWindow.mm
@@ -30,16 +30,17 @@
 #include "nsCocoaFeatures.h"
 #include "nsIScreenManager.h"
 #include "nsIWidgetListener.h"
 #include "nsIPresShell.h"
 
 #include "gfxPlatform.h"
 #include "qcms.h"
 
+#include "mozilla/AutoRestore.h"
 #include "mozilla/BasicEvents.h"
 #include "mozilla/Preferences.h"
 #include <algorithm>
 
 namespace mozilla {
 namespace layers {
 class LayerManager;
 }
@@ -2514,21 +2515,41 @@ GetDPI(NSWindow* aWindow)
   mDrawsIntoWindowFrame = NO;
   [super initWithContentRect:aContentRect styleMask:aStyle backing:aBufferingType defer:aFlag];
   mState = nil;
   mActiveTitlebarColor = nil;
   mInactiveTitlebarColor = nil;
   mScheduledShadowInvalidation = NO;
   mDPI = GetDPI(self);
   mTrackingArea = nil;
+  mBeingShown = NO;
   [self updateTrackingArea];
 
   return self;
 }
 
+- (BOOL)isVisibleOrBeingShown
+{
+  return [super isVisible] || mBeingShown;
+}
+
+- (void)orderFront:(id)sender
+{
+  AutoRestore<BOOL> saveBeingShown(mBeingShown);
+  mBeingShown = YES;
+  [super orderFront:sender];
+}
+
+- (void)makeKeyAndOrderFront:(id)sender
+{
+  AutoRestore<BOOL> saveBeingShown(mBeingShown);
+  mBeingShown = YES;
+  [super makeKeyAndOrderFront:sender];
+}
+
 - (void)dealloc
 {
   [mActiveTitlebarColor release];
   [mInactiveTitlebarColor release];
   [self removeTrackingArea];
   ChildViewMouseTracker::OnDestroyWindow(self);
   [super dealloc];
 }
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -91,18 +91,18 @@ typedef void* nsNativeWidget;
 #ifdef XP_WIN
 #define NS_NATIVE_TSF_THREAD_MGR       100
 #define NS_NATIVE_TSF_CATEGORY_MGR     101
 #define NS_NATIVE_TSF_DISPLAY_ATTR_MGR 102
 #define NS_NATIVE_ICOREWINDOW          103 // winrt specific
 #endif
 
 #define NS_IWIDGET_IID \
-{ 0x1ebdb596, 0x0f90, 0x4f02, \
-  { 0x97, 0x07, 0x4e, 0xc1, 0x16, 0xcd, 0x54, 0xf6 } }
+{ 0x8e2afc1c, 0x7087, 0x4ec2, \
+  { 0xac, 0xc6, 0xd4, 0xf2, 0x3e, 0x13, 0xd2, 0xb7 } }
 
 /*
  * Window shadow styles
  * Also used for the -moz-window-shadow CSS property
  */
 
 #define NS_STYLE_WINDOW_SHADOW_NONE             0
 #define NS_STYLE_WINDOW_SHADOW_DEFAULT          1
@@ -1210,17 +1210,24 @@ class nsIWidget : public nsISupports {
     /**
      * Called when shutting down the LayerManager to clean-up any cached resources.
      *
      * Always called from the compositing thread, which may be the main-thread if
      * OMTC is not enabled.
      */
     virtual void CleanupWindowEffects() = 0;
 
-    virtual void PreRender(LayerManager* aManager) = 0;
+    /**
+     * Called before rendering using OpenGL. Returns false when the widget is
+     * not ready to be rendered (for example while the window is closed).
+     *
+     * Always called from the compositing thread, which may be the main-thread if
+     * OMTC is not enabled.
+     */
+    virtual bool PreRender(LayerManager* aManager) = 0;
 
     /**
      * Called before the LayerManager draws the layer tree.
      *
      * Always called from the compositing thread, which may be the main-thread if
      * OMTC is not enabled.
      */
     virtual void DrawWindowUnderlay(LayerManager* aManager, nsIntRect aRect) = 0;
--- a/widget/xpwidgets/nsBaseWidget.h
+++ b/widget/xpwidgets/nsBaseWidget.h
@@ -131,17 +131,17 @@ public:
                                           LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT,
                                           bool* aAllowRetaining = nullptr);
 
   virtual CompositorParent* NewCompositorParent(int aSurfaceWidth, int aSurfaceHeight);
   virtual void            CreateCompositor();
   virtual void            CreateCompositor(int aWidth, int aHeight);
   virtual void            PrepareWindowEffects() {}
   virtual void            CleanupWindowEffects() {}
-  virtual void            PreRender(LayerManager* aManager) {}
+  virtual bool            PreRender(LayerManager* aManager) { return true; }
   virtual void            DrawWindowUnderlay(LayerManager* aManager, nsIntRect aRect) {}
   virtual void            DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect) {}
   virtual mozilla::TemporaryRef<mozilla::gfx::DrawTarget> StartRemoteDrawing();
   virtual void            EndRemoteDrawing() { };
   virtual void            CleanupRemoteDrawing() { };
   virtual void            UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) {}
   virtual gfxASurface*    GetThebesSurface();
   NS_IMETHOD              SetModal(bool aModal);