Bug 626962. Implement empty transactions for GL. r=bas,a=blocking
authorRobert O'Callahan <robert@ocallahan.org>
Tue, 25 Jan 2011 21:45:17 +1300
changeset 61836 2a13f323dfa05b3a249110a06e0ff219c795c982
parent 61835 b4e9a17e7fe2f98f46c528af4ead056527e1d7b7
child 61837 c5b8aa1d4c8ac937c1ceeb518103f50ce3e99af1
push idunknown
push userunknown
push dateunknown
reviewersbas, blocking
bugs626962
milestone2.0b12pre
Bug 626962. Implement empty transactions for GL. r=bas,a=blocking
gfx/layers/Layers.h
gfx/layers/opengl/LayerManagerOGL.cpp
gfx/layers/opengl/LayerManagerOGL.h
gfx/layers/opengl/ThebesLayerOGL.cpp
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -296,20 +296,18 @@ public:
   /**
    * Attempts to end an "empty transaction". There must have been no
    * changes to the layer tree since the BeginTransaction().
    * It's possible for this to fail; ThebesLayers may need to be updated
    * due to VRAM data being lost, for example. In such cases this method
    * returns false, and the caller must proceed with a normal layer tree
    * update and EndTransaction.
    */
-  virtual bool EndEmptyTransaction()
-  {
-    return false;
-  }
+  virtual bool EndEmptyTransaction() = 0;
+
   /**
    * Function called to draw the contents of each ThebesLayer.
    * aRegionToDraw contains the region that needs to be drawn.
    * This would normally be a subregion of the visible region.
    * The callee must draw all of aRegionToDraw. Drawing outside
    * aRegionToDraw will be clipped out or ignored.
    * The callee must draw all of aRegionToDraw.
    * This region is relative to 0,0 in the ThebesLayer.
--- a/gfx/layers/opengl/LayerManagerOGL.cpp
+++ b/gfx/layers/opengl/LayerManagerOGL.cpp
@@ -387,16 +387,26 @@ LayerManagerOGL::BeginTransactionWithTar
   if (mDestroyed) {
     NS_WARNING("Call on destroyed layer manager");
     return;
   }
 
   mTarget = aTarget;
 }
 
+bool
+LayerManagerOGL::EndEmptyTransaction()
+{
+  if (!mRoot)
+    return false;
+
+  EndTransaction(nsnull, nsnull);
+  return true;
+}
+
 void
 LayerManagerOGL::EndTransaction(DrawThebesLayerCallback aCallback,
                                 void* aCallbackData)
 {
 #ifdef MOZ_LAYERS_HAVE_LOG
   MOZ_LAYERS_LOG(("  ----- (beginning paint)"));
   Log();
 #endif
@@ -408,20 +418,17 @@ LayerManagerOGL::EndTransaction(DrawTheb
 
   // 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;
 
-  // NULL callback means "non-painting transaction"
-  if (aCallback) {
-    Render();
-  }
+  Render();
 
   mThebesLayerCallback = nsnull;
   mThebesLayerCallbackData = nsnull;
 
   mTarget = NULL;
 
 #ifdef MOZ_LAYERS_HAVE_LOG
   Log();
--- a/gfx/layers/opengl/LayerManagerOGL.h
+++ b/gfx/layers/opengl/LayerManagerOGL.h
@@ -131,16 +131,17 @@ public:
    * LayerManager implementation.
    */
   void BeginTransaction();
 
   void BeginTransactionWithTarget(gfxContext* aTarget);
 
   void EndConstruction();
 
+  virtual bool EndEmptyTransaction();
   virtual void EndTransaction(DrawThebesLayerCallback aCallback,
                               void* aCallbackData);
 
   virtual void SetRoot(Layer* aLayer) { mRoot = aLayer; }
 
   virtual already_AddRefed<ThebesLayer> CreateThebesLayer();
 
   virtual already_AddRefed<ContainerLayer> CreateContainerLayer();
--- a/gfx/layers/opengl/ThebesLayerOGL.cpp
+++ b/gfx/layers/opengl/ThebesLayerOGL.cpp
@@ -688,24 +688,28 @@ ThebesLayerOGL::RenderLayer(int aPreviou
   Buffer::PaintState state = mBuffer->BeginPaint(contentType);
   mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
 
   if (state.mContext) {
     state.mRegionToInvalidate.And(state.mRegionToInvalidate, mVisibleRegion);
 
     LayerManager::DrawThebesLayerCallback callback =
       mOGLManager->GetThebesLayerCallback();
-    void* callbackData = mOGLManager->GetThebesLayerCallbackData();
-    callback(this, state.mContext, state.mRegionToDraw,
-             state.mRegionToInvalidate, callbackData);
-    // Everything that's visible has been validated. Do this instead of
-    // OR-ing with aRegionToDraw, since that can lead to a very complex region
-    // here (OR doesn't automatically simplify to the simplest possible
-    // representation of a region.)
-    mValidRegion.Or(mValidRegion, mVisibleRegion);
+    if (!callback) {
+      NS_ERROR("GL should never need to update ThebesLayers in an empty transaction");
+    } else {
+      void* callbackData = mOGLManager->GetThebesLayerCallbackData();
+      callback(this, state.mContext, state.mRegionToDraw,
+               state.mRegionToInvalidate, callbackData);
+      // Everything that's visible has been validated. Do this instead of
+      // OR-ing with aRegionToDraw, since that can lead to a very complex region
+      // here (OR doesn't automatically simplify to the simplest possible
+      // representation of a region.)
+      mValidRegion.Or(mValidRegion, mVisibleRegion);
+    }
   }
 
   DEBUG_GL_ERROR_CHECK(gl());
 
   gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer);
   mBuffer->RenderTo(aOffset, mOGLManager);
   DEBUG_GL_ERROR_CHECK(gl());
 }