Bug 681033 - Prevent ShadowLayers::RecvUpdate from triggering an immediate repaint. r=cjones
authorAli Juma <ajuma@mozilla.com>
Mon, 26 Sep 2011 09:20:42 -0400
changeset 77576 8fdc985221747ccf25b22639fdc1c3fe505a4b2b
parent 77575 1a11c6516cda06d73a5638129a203434c13a2435
child 77577 a0bac7d8cc0cd502b00690a9db22b9c1aee90771
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewerscjones
bugs681033
milestone9.0a1
Bug 681033 - Prevent ShadowLayers::RecvUpdate from triggering an immediate repaint. r=cjones
gfx/layers/Layers.h
gfx/layers/basic/BasicLayers.cpp
gfx/layers/basic/BasicLayers.h
gfx/layers/d3d10/LayerManagerD3D10.cpp
gfx/layers/d3d10/LayerManagerD3D10.h
gfx/layers/d3d9/LayerManagerD3D9.cpp
gfx/layers/d3d9/LayerManagerD3D9.h
gfx/layers/ipc/ShadowLayersParent.cpp
gfx/layers/opengl/LayerManagerOGL.cpp
gfx/layers/opengl/LayerManagerOGL.h
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -346,25 +346,32 @@ public:
    * 
    * The origin of aContext is 0,0 in the ThebesLayer.
    */
   typedef void (* DrawThebesLayerCallback)(ThebesLayer* aLayer,
                                            gfxContext* aContext,
                                            const nsIntRegion& aRegionToDraw,
                                            const nsIntRegion& aRegionToInvalidate,
                                            void* aCallbackData);
+
+  enum EndTransactionFlags {
+    END_DEFAULT = 0,
+    END_NO_IMMEDIATE_REDRAW = 1 << 0  // Do not perform the drawing phase
+  };
+
   /**
    * Finish the construction phase of the transaction, perform the
    * drawing phase, and end the transaction.
    * During the drawing phase, all ThebesLayers in the tree are
    * drawn in tree order, exactly once each, except for those layers
    * where it is known that the visible region is empty.
    */
   virtual void EndTransaction(DrawThebesLayerCallback aCallback,
-                              void* aCallbackData) = 0;
+                              void* aCallbackData,
+                              EndTransactionFlags aFlags = END_DEFAULT) = 0;
 
   PRBool IsSnappingEffectiveTransforms() { return mSnapEffectiveTransforms; } 
 
   /**
    * CONSTRUCTION PHASE ONLY
    * Set the root layer. The root layer is initially null. If there is
    * no root layer, EndTransaction won't draw anything.
    */
--- a/gfx/layers/basic/BasicLayers.cpp
+++ b/gfx/layers/basic/BasicLayers.cpp
@@ -1556,38 +1556,40 @@ ApplyDoubleBuffering(Layer* aLayer, cons
         ApplyDoubleBuffering(child, newVisibleRect);
       }
     }
   }
 }
 
 void
 BasicLayerManager::EndTransaction(DrawThebesLayerCallback aCallback,
-                                  void* aCallbackData)
+                                  void* aCallbackData,
+                                  EndTransactionFlags aFlags)
 {
-  EndTransactionInternal(aCallback, aCallbackData);
+  EndTransactionInternal(aCallback, aCallbackData, aFlags);
 }
 
 bool
 BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback,
-                                          void* aCallbackData)
+                                          void* aCallbackData,
+                                          EndTransactionFlags aFlags)
 {
 #ifdef MOZ_LAYERS_HAVE_LOG
   MOZ_LAYERS_LOG(("  ----- (beginning paint)"));
   Log();
 #endif
 
   NS_ASSERTION(InConstruction(), "Should be in construction phase");
 #ifdef DEBUG
   mPhase = PHASE_DRAWING;
 #endif
 
   mTransactionIncomplete = false;
 
-  if (mTarget && mRoot) {
+  if (mTarget && mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
     nsIntRect clipRect;
     if (HasShadowManager()) {
       // If this has a shadow manager, the clip extents of mTarget are meaningless.
       // So instead just use the root layer's visible region bounds.
       const nsIntRect& bounds = mRoot->GetVisibleRegion().GetBounds();
       gfxRect deviceRect =
           mTarget->UserToDevice(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height));
       clipRect = ToOutsideIntRect(deviceRect);
@@ -3255,19 +3257,20 @@ BasicShadowLayerManager::BeginTransactio
   if (HasShadowManager()) {
     ShadowLayerForwarder::BeginTransaction();
   }
   BasicLayerManager::BeginTransactionWithTarget(aTarget);
 }
 
 void
 BasicShadowLayerManager::EndTransaction(DrawThebesLayerCallback aCallback,
-                                        void* aCallbackData)
+                                        void* aCallbackData,
+                                        EndTransactionFlags aFlags)
 {
-  BasicLayerManager::EndTransaction(aCallback, aCallbackData);
+  BasicLayerManager::EndTransaction(aCallback, aCallbackData, aFlags);
   ForwardTransaction();
 }
 
 bool
 BasicShadowLayerManager::EndEmptyTransaction()
 {
   if (!BasicLayerManager::EndEmptyTransaction()) {
     // Return without calling ForwardTransaction. This leaves the
--- a/gfx/layers/basic/BasicLayers.h
+++ b/gfx/layers/basic/BasicLayers.h
@@ -117,17 +117,18 @@ public:
 
   nsIWidget* GetRetainerWidget() { return mWidget; }
   void ClearRetainerWidget() { mWidget = nsnull; }
 
   virtual void BeginTransaction();
   virtual void BeginTransactionWithTarget(gfxContext* aTarget);
   virtual bool EndEmptyTransaction();
   virtual void EndTransaction(DrawThebesLayerCallback aCallback,
-                              void* aCallbackData);
+                              void* aCallbackData,
+                              EndTransactionFlags aFlags = END_DEFAULT);
 
   virtual void SetRoot(Layer* aLayer);
 
   virtual already_AddRefed<ThebesLayer> CreateThebesLayer();
   virtual already_AddRefed<ContainerLayer> CreateContainerLayer();
   virtual already_AddRefed<ImageLayer> CreateImageLayer();
   virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
   virtual already_AddRefed<ImageContainer> CreateImageContainer();
@@ -191,17 +192,18 @@ protected:
                   DrawThebesLayerCallback aCallback,
                   void* aCallbackData,
                   ReadbackProcessor* aReadback);
 
   // Clear the contents of a layer
   void ClearLayer(Layer* aLayer);
 
   bool EndTransactionInternal(DrawThebesLayerCallback aCallback,
-                              void* aCallbackData);
+                              void* aCallbackData,
+                              EndTransactionFlags aFlags = END_DEFAULT);
 
   // Widget whose surface should be used as the basis for ThebesLayer
   // buffers.
   nsIWidget* mWidget;
   // The default context for BeginTransaction.
   nsRefPtr<gfxContext> mDefaultTarget;
   // The context to draw into.
   nsRefPtr<gfxContext> mTarget;
@@ -232,17 +234,18 @@ public:
   virtual ShadowLayerManager* AsShadowManager()
   {
     return this;
   }
 
   virtual void BeginTransactionWithTarget(gfxContext* aTarget);
   virtual bool EndEmptyTransaction();
   virtual void EndTransaction(DrawThebesLayerCallback aCallback,
-                              void* aCallbackData);
+                              void* aCallbackData,
+                              EndTransactionFlags aFlags = END_DEFAULT);
 
   virtual void SetRoot(Layer* aLayer);
 
   virtual void Mutated(Layer* aLayer);
 
   virtual already_AddRefed<ThebesLayer> CreateThebesLayer();
   virtual already_AddRefed<ContainerLayer> CreateContainerLayer();
   virtual already_AddRefed<ImageLayer> CreateImageLayer();
--- a/gfx/layers/d3d10/LayerManagerD3D10.cpp
+++ b/gfx/layers/d3d10/LayerManagerD3D10.cpp
@@ -331,19 +331,20 @@ LayerManagerD3D10::EndEmptyTransaction()
     return false;
 
   EndTransaction(nsnull, nsnull);
   return true;
 }
 
 void
 LayerManagerD3D10::EndTransaction(DrawThebesLayerCallback aCallback,
-                                  void* aCallbackData)
+                                  void* aCallbackData,
+                                  EndTransactionFlags aFlags)
 {
-  if (mRoot) {
+  if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
     mCurrentCallbackInfo.Callback = aCallback;
     mCurrentCallbackInfo.CallbackData = aCallbackData;
 
     // The results of our drawing always go directly into a pixel buffer,
     // so we don't need to pass any global transform here.
     mRoot->ComputeEffectiveTransforms(gfx3DMatrix());
 
 #ifdef MOZ_LAYERS_HAVE_LOG
--- a/gfx/layers/d3d10/LayerManagerD3D10.h
+++ b/gfx/layers/d3d10/LayerManagerD3D10.h
@@ -122,17 +122,18 @@ public:
   virtual bool EndEmptyTransaction();
 
   struct CallbackInfo {
     DrawThebesLayerCallback Callback;
     void *CallbackData;
   };
 
   virtual void EndTransaction(DrawThebesLayerCallback aCallback,
-                              void* aCallbackData);
+                              void* aCallbackData,
+                              EndTransactionFlags aFlags = END_DEFAULT);
 
   const CallbackInfo &GetCallbackInfo() { return mCurrentCallbackInfo; }
 
   // D3D10 guarantees textures can be at least this size
   enum {
     MAX_TEXTURE_SIZE = 8192
   };
   virtual bool CanUseCanvasLayerForSize(const gfxIntSize &aSize)
--- a/gfx/layers/d3d9/LayerManagerD3D9.cpp
+++ b/gfx/layers/d3d9/LayerManagerD3D9.cpp
@@ -163,21 +163,22 @@ LayerManagerD3D9::EndEmptyTransaction()
     return false;
 
   EndTransaction(nsnull, nsnull);
   return true;
 }
 
 void
 LayerManagerD3D9::EndTransaction(DrawThebesLayerCallback aCallback,
-                                 void* aCallbackData)
+                                 void* aCallbackData,
+                                 EndTransactionFlags aFlags)
 {
   mDeviceResetCount = mDeviceManager->GetDeviceResetCount();
 
-  if (mRoot) {
+  if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
     mCurrentCallbackInfo.Callback = aCallback;
     mCurrentCallbackInfo.CallbackData = aCallbackData;
 
     // The results of our drawing always go directly into a pixel buffer,
     // so we don't need to pass any global transform here.
     mRoot->ComputeEffectiveTransforms(gfx3DMatrix());
 
     Render();
--- a/gfx/layers/d3d9/LayerManagerD3D9.h
+++ b/gfx/layers/d3d9/LayerManagerD3D9.h
@@ -133,17 +133,18 @@ public:
   virtual bool EndEmptyTransaction();
 
   struct CallbackInfo {
     DrawThebesLayerCallback Callback;
     void *CallbackData;
   };
 
   virtual void EndTransaction(DrawThebesLayerCallback aCallback,
-                              void* aCallbackData);
+                              void* aCallbackData,
+                              EndTransactionFlags aFlags = END_DEFAULT);
 
   const CallbackInfo &GetCallbackInfo() { return mCurrentCallbackInfo; }
 
   void SetRoot(Layer* aLayer);
 
   virtual bool CanUseCanvasLayerForSize(const gfxIntSize &aSize)
   {
     if (!mDeviceManager)
--- a/gfx/layers/ipc/ShadowLayersParent.cpp
+++ b/gfx/layers/ipc/ShadowLayersParent.cpp
@@ -444,17 +444,17 @@ ShadowLayersParent::RecvUpdate(const Inf
       break;
     }
 
     default:
       NS_RUNTIMEABORT("not reached");
     }
   }
 
-  layer_manager()->EndTransaction(NULL, NULL);
+  layer_manager()->EndTransaction(NULL, NULL, LayerManager::END_NO_IMMEDIATE_REDRAW);
 
   reply->SetCapacity(replyv.size());
   if (replyv.size() > 0) {
     reply->AppendElements(&replyv.front(), replyv.size());
   }
 
   // Ensure that any pending operations involving back and front
   // buffers have completed, so that neither process stomps on the
--- a/gfx/layers/opengl/LayerManagerOGL.cpp
+++ b/gfx/layers/opengl/LayerManagerOGL.cpp
@@ -397,29 +397,30 @@ LayerManagerOGL::EndEmptyTransaction()
     return false;
 
   EndTransaction(nsnull, nsnull);
   return true;
 }
 
 void
 LayerManagerOGL::EndTransaction(DrawThebesLayerCallback aCallback,
-                                void* aCallbackData)
+                                void* aCallbackData,
+                                EndTransactionFlags aFlags)
 {
 #ifdef MOZ_LAYERS_HAVE_LOG
   MOZ_LAYERS_LOG(("  ----- (beginning paint)"));
   Log();
 #endif
 
   if (mDestroyed) {
     NS_WARNING("Call on destroyed layer manager");
     return;
   }
 
-  if (mRoot) {
+  if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
     // The results of our drawing always go directly into a pixel buffer,
     // so we don't need to pass any global transform here.
     mRoot->ComputeEffectiveTransforms(gfx3DMatrix());
 
     mThebesLayerCallback = aCallback;
     mThebesLayerCallbackData = aCallbackData;
 
     Render();
--- a/gfx/layers/opengl/LayerManagerOGL.h
+++ b/gfx/layers/opengl/LayerManagerOGL.h
@@ -134,17 +134,18 @@ public:
   void BeginTransaction();
 
   void BeginTransactionWithTarget(gfxContext* aTarget);
 
   void EndConstruction();
 
   virtual bool EndEmptyTransaction();
   virtual void EndTransaction(DrawThebesLayerCallback aCallback,
-                              void* aCallbackData);
+                              void* aCallbackData,
+                              EndTransactionFlags aFlags = END_DEFAULT);
 
   virtual void SetRoot(Layer* aLayer) { mRoot = aLayer; }
 
   virtual bool CanUseCanvasLayerForSize(const gfxIntSize &aSize)
   {
       if (!mGLContext)
           return false;
       PRInt32 maxSize = mGLContext->GetMaxTextureSize();