Bug 790505, part 3: Add API for scheduling a shadowable-layer mutation to be applied at the next layers transaction. r=mattwoodrow,roc
authorChris Jones <jones.chris.g@gmail.com>
Tue, 02 Oct 2012 22:55:50 -0700
changeset 109312 f3d44e273f4e6cdb2563b021c74355ab7c6b5d1b
parent 109311 d333cf74425fc2890ca822bcf9d10ed8c733377d
child 109313 1cceedd227a7427bfcc764fd583a2631603eaf07
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
reviewersmattwoodrow, roc
bugs790505
milestone18.0a1
Bug 790505, part 3: Add API for scheduling a shadowable-layer mutation to be applied at the next layers transaction. r=mattwoodrow,roc
gfx/layers/Layers.cpp
gfx/layers/Layers.h
gfx/layers/basic/BasicLayerManager.cpp
gfx/layers/d3d10/LayerManagerD3D10.cpp
gfx/layers/d3d9/LayerManagerD3D9.cpp
gfx/layers/opengl/LayerManagerOGL.cpp
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -493,16 +493,25 @@ Layer::SetAnimations(const AnimationArra
         endValue->SetFloatValue(segment.endState().get_float());
       }
     }
   }
 
   Mutated();
 }
 
+void
+Layer::ApplyPendingUpdatesToSubtree()
+{
+  ApplyPendingUpdatesForThisTransaction();
+  for (Layer* child = GetFirstChild(); child; child = child->GetNextSibling()) {
+    child->ApplyPendingUpdatesToSubtree();
+  }
+}
+
 bool
 Layer::CanUseOpaqueSurface()
 {
   // If the visible content in the layer is opaque, there is no need
   // for an alpha channel.
   if (GetContentFlags() & CONTENT_OPAQUE)
     return true;
   // Also, if this layer is the bottommost layer in a container which
@@ -660,16 +669,26 @@ Layer::GetLocalTransform()
     transform = mTransform;
   if (ContainerLayer* c = AsContainerLayer()) {
     transform.Scale(c->GetPreXScale(), c->GetPreYScale(), 1.0f);
   }
   transform.ScalePost(mPostXScale, mPostYScale, 1.0f);
   return transform;
 }
 
+void
+Layer::ApplyPendingUpdatesForThisTransaction()
+{
+  if (mPendingTransform && *mPendingTransform != mTransform) {
+    mTransform = *mPendingTransform;
+    Mutated();
+  }
+  mPendingTransform = nullptr;
+}
+
 const float
 Layer::GetLocalOpacity()
 {
    if (ShadowLayer* shadow = AsShadowLayer())
     return shadow->GetShadowOpacity();
   return mOpacity;
 }
 
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -696,23 +696,37 @@ public:
    * CONSTRUCTION PHASE ONLY
    * Tell this layer what its transform should be. The transformation
    * is applied when compositing the layer into its parent container.
    * XXX Currently only transformations corresponding to 2D affine transforms
    * are supported.
    */
   void SetBaseTransform(const gfx3DMatrix& aMatrix)
   {
+    mPendingTransform = nullptr;
     if (mTransform == aMatrix) {
       return;
     }
     mTransform = aMatrix;
     Mutated();
   }
 
+  /**
+   * Can be called at any time.
+   *
+   * Like SetBaseTransform(), but can be called before the next
+   * transform (i.e. outside an open transaction).  Semantically, this
+   * method enqueues a new transform value to be set immediately after
+   * the next transaction is opened.
+   */
+  void SetBaseTransformForNextTransaction(const gfx3DMatrix& aMatrix)
+  {
+    mPendingTransform = new gfx3DMatrix(aMatrix);
+  }
+
   void SetPostScale(float aXScale, float aYScale)
   {
     mPostXScale = aXScale;
     mPostYScale = aYScale;
     Mutated();
   }
 
   /**
@@ -758,16 +772,25 @@ public:
   float GetPostXScale() { return mPostXScale; }
   float GetPostYScale() { return mPostYScale; }
   bool GetIsFixedPosition() { return mIsFixedPosition; }
   gfxPoint GetFixedPositionAnchor() { return mAnchor; }
   Layer* GetMaskLayer() { return mMaskLayer; }
 
   AnimationArray& GetAnimations() { return mAnimations; }
   InfallibleTArray<AnimData>& GetAnimationData() { return mAnimationData; }
+
+  /**
+   * DRAWING PHASE ONLY
+   *
+   * Apply pending changes to layers before drawing them, if those
+   * pending changes haven't been overridden by later changes.
+   */
+  void ApplyPendingUpdatesToSubtree();
+
   /**
    * DRAWING PHASE ONLY
    *
    * Write layer-subtype-specific attributes into aAttrs.  Used to
    * synchronize layer attributes to their shadows'.
    */
   virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs) { }
 
@@ -974,16 +997,17 @@ public:
   void AddInvalidRect(const nsIntRect& aRect) { mInvalidRegion.Or(mInvalidRegion, aRect); }
 
   /**
    * Clear the invalid rect, marking the layer as being identical to what is currently
    * composited.
    */
   void ClearInvalidRect() { mInvalidRegion.SetEmpty(); }
 
+  void ApplyPendingUpdatesForThisTransaction();
 
 #ifdef DEBUG
   void SetDebugColorIndex(uint32_t aIndex) { mDebugColorIndex = aIndex; }
   uint32_t GetDebugColorIndex() { return mDebugColorIndex; }
 #endif
 
 protected:
   Layer(LayerManager* aManager, void* aImplData);
@@ -1028,16 +1052,20 @@ protected:
   ContainerLayer* mParent;
   Layer* mNextSibling;
   Layer* mPrevSibling;
   void* mImplData;
   nsRefPtr<Layer> mMaskLayer;
   gfx::UserData mUserData;
   nsIntRegion mVisibleRegion;
   gfx3DMatrix mTransform;
+  // A mutation of |mTransform| that we've queued to be applied at the
+  // end of the next transaction (if nothing else overrides it in the
+  // meantime).
+  nsAutoPtr<gfx3DMatrix> mPendingTransform;
   float mPostXScale;
   float mPostYScale;
   gfx3DMatrix mEffectiveTransform;
   AnimationArray mAnimations;
   InfallibleTArray<AnimData> mAnimationData;
   float mOpacity;
   nsIntRect mClipRect;
   nsIntRect mTileSourceRect;
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -547,16 +547,22 @@ BasicLayerManager::EndTransactionInterna
           mTarget->UserToDevice(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height));
       clipRect = ToOutsideIntRect(deviceRect);
     } else {
       gfxContextMatrixAutoSaveRestore save(mTarget);
       mTarget->SetMatrix(gfxMatrix());
       clipRect = ToOutsideIntRect(mTarget->GetClipExtents());
     }
 
+    if (aFlags & END_NO_COMPOSITE) {
+      // Apply pending tree updates before recomputing effective
+      // properties.
+      aLayer->ApplyPendingUpdatesToSubtree();
+    }
+
     // Need to do this before we call ApplyDoubleBuffering,
     // which depends on correct effective transforms
     mSnapEffectiveTransforms =
       !(mTarget->GetFlags() & gfxContext::FLAG_DISABLE_SNAPPING);
     mRoot->ComputeEffectiveTransforms(gfx3DMatrix::From2D(mTarget->CurrentMatrix()));
 
     if (IsRetained()) {
       nsIntRegion region;
--- a/gfx/layers/d3d10/LayerManagerD3D10.cpp
+++ b/gfx/layers/d3d10/LayerManagerD3D10.cpp
@@ -355,16 +355,22 @@ LayerManagerD3D10::EndTransaction(DrawTh
                                   EndTransactionFlags aFlags)
 {
   mInTransaction = false;
 
   if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
     mCurrentCallbackInfo.Callback = aCallback;
     mCurrentCallbackInfo.CallbackData = aCallbackData;
 
+    if (aFlags & END_NO_COMPOSITE) {
+      // Apply pending tree updates before recomputing effective
+      // properties.
+      mRoot->ApplyPendingUpdatesToSubtree();
+    }
+
     // 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
     MOZ_LAYERS_LOG(("  ----- (beginning paint)"));
     Log();
 #endif
--- a/gfx/layers/d3d9/LayerManagerD3D9.cpp
+++ b/gfx/layers/d3d9/LayerManagerD3D9.cpp
@@ -146,16 +146,22 @@ LayerManagerD3D9::EndTransaction(DrawThe
   mInTransaction = false;
 
   mDeviceResetCount = mDeviceManager->GetDeviceResetCount();
 
   if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
     mCurrentCallbackInfo.Callback = aCallback;
     mCurrentCallbackInfo.CallbackData = aCallbackData;
 
+    if (aFlags & END_NO_COMPOSITE) {
+      // Apply pending tree updates before recomputing effective
+      // properties.
+      mRoot->ApplyPendingUpdatesToSubtree();
+    }
+
     // 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());
 
     SetCompositingDisabled(aFlags & END_NO_COMPOSITE);
     Render();
     /* Clean this out for sanity */
     mCurrentCallbackInfo.Callback = NULL;
--- a/gfx/layers/opengl/LayerManagerOGL.cpp
+++ b/gfx/layers/opengl/LayerManagerOGL.cpp
@@ -636,16 +636,22 @@ LayerManagerOGL::EndTransaction(DrawTheb
 #endif
 
   if (mDestroyed) {
     NS_WARNING("Call on destroyed layer manager");
     return;
   }
 
   if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
+    if (aFlags & END_NO_COMPOSITE) {
+      // Apply pending tree updates before recomputing effective
+      // properties.
+      mRoot->ApplyPendingUpdatesToSubtree();
+    }
+
     // 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;
     SetCompositingDisabled(aFlags & END_NO_COMPOSITE);