Bug 811950 - Fix async scrolling of position:fixed. r=cjones
authorAnthony Jones <ajones@mozilla.com>
Sun, 23 Dec 2012 10:50:04 -0500
changeset 122527 955a8b88d7969843d5d8cae39b0728331d98bfbb
parent 122526 1310b5aab1f4dc95a69d2d90cd613e1c966af20a
child 122528 0e5744e4e2f61b25b9a6cf83deee90cd3c32a3b0
push idunknown
push userunknown
push dateunknown
reviewerscjones
bugs811950
milestone20.0a1
Bug 811950 - Fix async scrolling of position:fixed. r=cjones
gfx/layers/ipc/AsyncPanZoomController.cpp
gfx/layers/ipc/AsyncPanZoomController.h
gfx/layers/ipc/CompositorParent.cpp
--- a/gfx/layers/ipc/AsyncPanZoomController.cpp
+++ b/gfx/layers/ipc/AsyncPanZoomController.cpp
@@ -976,17 +976,17 @@ void AsyncPanZoomController::RequestCont
   mWaitingForContentToPaint = true;
 
   // Set the zoom back to what it was for the purpose of logic control.
   mFrameMetrics.mZoom = gfxSize(actualZoom, actualZoom);
 }
 
 bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSampleTime,
                                                             ContainerLayer* aLayer,
-                                                            gfx3DMatrix* aNewTransform) {
+                                                            ViewTransform* aNewTransform) {
   // The eventual return value of this function. The compositor needs to know
   // whether or not to advance by a frame as soon as it can. For example, if a
   // fling is happening, it has to keep compositing so that the animation is
   // smooth. If an animation frame is requested, it is the compositor's
   // responsibility to schedule a composite.
   bool requestAnimationFrame = false;
 
   const gfx3DMatrix& currentTransform = aLayer->GetTransform();
@@ -1059,28 +1059,17 @@ bool AsyncPanZoomController::SampleConte
 
     scrollOffset = mFrameMetrics.mScrollOffset;
   }
 
   nsIntPoint scrollCompensation(
     NS_lround((scrollOffset.x / rootScaleX - metricsScrollOffset.x) * localScaleX),
     NS_lround((scrollOffset.y / rootScaleY - metricsScrollOffset.y) * localScaleY));
 
-  ViewTransform treeTransform(-scrollCompensation, localScaleX, localScaleY);
-  *aNewTransform = gfx3DMatrix(treeTransform) * currentTransform;
-
-  // The transform already takes the resolution scale into account.  Since we
-  // will apply the resolution scale again when computing the effective
-  // transform, we must apply the inverse resolution scale here.
-  aNewTransform->Scale(1.0f/aLayer->GetPreXScale(),
-                       1.0f/aLayer->GetPreYScale(),
-                       1);
-  aNewTransform->ScalePost(1.0f/aLayer->GetPostXScale(),
-                           1.0f/aLayer->GetPostYScale(),
-                           1);
+  *aNewTransform = ViewTransform(-scrollCompensation, localScaleX, localScaleY);
 
   mLastSampleTime = aSampleTime;
 
   return requestAnimationFrame;
 }
 
 void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFrame, bool aIsFirstPaint) {
   MonitorAutoLock monitor(mMonitor);
--- a/gfx/layers/ipc/AsyncPanZoomController.h
+++ b/gfx/layers/ipc/AsyncPanZoomController.h
@@ -20,16 +20,17 @@
 #include "base/message_loop.h"
 
 namespace mozilla {
 namespace layers {
 
 class CompositorParent;
 class GestureEventListener;
 class ContainerLayer;
+class ViewTransform;
 
 /**
  * Controller for all panning and zooming logic. Any time a user input is
  * detected and it must be processed in some way to affect what the user sees,
  * it goes through here. Listens for any input event from InputData and can
  * optionally handle nsGUIEvent-derived touch events, but this must be done on
  * the main thread. Note that this class completely cross-platform.
  *
@@ -154,17 +155,17 @@ public:
    * this internally with |aLayer|'s transform).
    *
    * Return value indicates whether or not any currently running animation
    * should continue. That is, if true, the compositor should schedule another
    * composite.
    */
   bool SampleContentTransformForFrame(const TimeStamp& aSampleTime,
                                       ContainerLayer* aLayer,
-                                      gfx3DMatrix* aNewTransform);
+                                      ViewTransform* aTransform);
 
   /**
    * A shadow layer update has arrived. |aViewportFrame| is the new FrameMetrics
    * for the top-level frame. |aIsFirstPaint| is a flag passed from the shadow
    * layers code indicating that the frame metrics being sent with this call are
    * the initial metrics and the initial paint of the frame has just happened.
    */
   void NotifyLayersUpdated(const FrameMetrics& aViewportFrame, bool aIsFirstPaint);
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -850,23 +850,39 @@ CompositorParent::ApplyAsyncContentTrans
   } else {
     // Check if a derived implementation provides a default AsyncPanZoomController.
     controller = GetDefaultPanZoomController();
   }
 
   if (controller) {
     ShadowLayer* shadow = aLayer->AsShadowLayer();
 
-    gfx3DMatrix newTransform;
+    ViewTransform treeTransform;
     *aWantNextFrame |=
       controller->SampleContentTransformForFrame(aCurrentFrame,
                                                  container,
-                                                 &newTransform);
+                                                 &treeTransform);
 
-    shadow->SetShadowTransform(newTransform);
+    gfx3DMatrix transform(gfx3DMatrix(treeTransform) * aLayer->GetTransform());
+    // The transform already takes the resolution scale into account.  Since we
+    // will apply the resolution scale again when computing the effective
+    // transform, we must apply the inverse resolution scale here.
+    transform.Scale(1.0f/container->GetPreXScale(),
+                    1.0f/container->GetPreYScale(),
+                    1);
+    transform.ScalePost(1.0f/aLayer->GetPostXScale(),
+                        1.0f/aLayer->GetPostYScale(),
+                        1);
+    shadow->SetShadowTransform(transform);
+
+    TransformFixedLayers(
+      aLayer,
+      -gfxPoint(treeTransform.mTranslation.x / treeTransform.mXScale,
+                treeTransform.mTranslation.y / treeTransform.mYScale),
+      gfxPoint(treeTransform.mXScale, treeTransform.mYScale));
 
     appliedTransform = true;
   }
 
   return appliedTransform;
 }
 
 bool