Bug 1201529 - Fall back to rootmost metrics if there is no root content document metrics. r=botond
authorKartikaya Gupta <kgupta@mozilla.com>
Fri, 11 Sep 2015 21:58:15 -0400
changeset 294689 10892d37b75518bba9953e5b4801ec1f069d2155
parent 294688 5962e3f3deb84d0e1189847e619034a6b8220c2d
child 294690 10cbae31c4b7af412519f1d5c6c9ee9ec9cdb6f5
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbotond
bugs1201529
milestone43.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 1201529 - Fall back to rootmost metrics if there is no root content document metrics. r=botond
gfx/layers/composite/AsyncCompositionManager.cpp
gfx/layers/composite/AsyncCompositionManager.h
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -581,23 +581,24 @@ AdjustForClip(const Matrix4x4& asyncTran
     if (shadowClipRect->TopLeft() != ParentLayerIntPoint()) {  // avoid a gratuitous change of basis
       result.ChangeBasis(shadowClipRect->x, shadowClipRect->y, 0);
     }
   }
   return result;
 }
 
 bool
-AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer)
+AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer,
+                                                          bool* aOutFoundRoot)
 {
   bool appliedTransform = false;
   for (Layer* child = aLayer->GetFirstChild();
       child; child = child->GetNextSibling()) {
     appliedTransform |=
-      ApplyAsyncContentTransformToTree(child);
+      ApplyAsyncContentTransformToTree(child, aOutFoundRoot);
   }
 
   Matrix4x4 oldTransform = aLayer->GetTransform();
 
   Matrix4x4 combinedAsyncTransform;
   bool hasAsyncTransform = false;
   ScreenMargin fixedLayerMargins(0, 0, 0, 0);
 
@@ -642,39 +643,40 @@ AsyncCompositionManager::ApplyAsyncConte
     }
 
     const FrameMetrics& metrics = aLayer->GetFrameMetrics(i);
     // TODO: When we enable APZ on Fennec, we'll need to call SyncFrameMetrics here.
     // When doing so, it might be useful to look at how it was called here before
     // bug 1036967 removed the (dead) call.
 
 #if defined(MOZ_ANDROID_APZ)
-    bool rootContentLayer = metrics.IsRootContent();
-#ifdef MOZ_B2GDROID
-    // B2GDroid is a special snowflake since it doesn't seem to have any root
-    // content document. However we still need to send a setFirstPaintViewport
-    // message, so we use the root of the layer tree as the root content layer
-    // instead. For the most part this should work fine; the Java code will just
-    // think the root layer is the "main" content, which in a manner of speaking,
-    // it is.
-    rootContentLayer = (aLayer->GetParent() == nullptr);
-#endif // MOZ_B2GDROID
-    if (rootContentLayer) {
-      if (mIsFirstPaint) {
-        CSSToLayerScale geckoZoom = metrics.LayersPixelsPerCSSPixel().ToScaleFactor();
-        LayerIntPoint scrollOffsetLayerPixels = RoundedToInt(metrics.GetScrollOffset() * geckoZoom);
-        mContentRect = metrics.GetScrollableRect();
-        SetFirstPaintViewport(scrollOffsetLayerPixels,
-                              geckoZoom,
-                              mContentRect);
+    // If we find a metrics which is the root content doc, use that. If not, use
+    // the root layer. Since this function recurses on children first we should
+    // only end up using the root layer if the entire tree was devoid of a
+    // root content metrics. This is a temporary solution; in the long term we
+    // should not need the root content metrics at all. See bug 1201529 comment
+    // 6 for details.
+    if (!(*aOutFoundRoot)) {
+      *aOutFoundRoot = metrics.IsRootContent() ||       /* RCD */
+            (aLayer->GetParent() == nullptr &&          /* rootmost metrics */
+             i + 1 >= aLayer->GetFrameMetricsCount());
+      if (*aOutFoundRoot) {
+        if (mIsFirstPaint) {
+          CSSToLayerScale geckoZoom = metrics.LayersPixelsPerCSSPixel().ToScaleFactor();
+          LayerIntPoint scrollOffsetLayerPixels = RoundedToInt(metrics.GetScrollOffset() * geckoZoom);
+          mContentRect = metrics.GetScrollableRect();
+          SetFirstPaintViewport(scrollOffsetLayerPixels,
+                                geckoZoom,
+                                mContentRect);
+        }
+        mIsFirstPaint = false;
+        mLayersUpdated = false;
       }
-      mIsFirstPaint = false;
-      mLayersUpdated = false;
     }
-#endif // MOZ_ANDROID_APZ
+#endif
 
     // Transform the current local clip by this APZC's async transform. If we're
     // using containerful scrolling, then the clip is not part of the scrolled
     // frame and should not be transformed.
     if (asyncClip && !metrics.UsesContainerScrolling()) {
       MOZ_ASSERT(asyncTransform.Is2D());
       asyncClip = Some(TransformTo<ParentLayerPixel>(asyncTransform, *asyncClip));
     }
@@ -1155,17 +1157,22 @@ AsyncCompositionManager::TransformShadow
     // an async pan zoom controller (which means that it is rendered
     // async using Gecko). If this fails, fall back to transforming the
     // primary scrollable layer.  "Failing" here means that we don't
     // find a frame that is async scrollable.  Note that the fallback
     // code also includes Fennec which is rendered async.  Fennec uses
     // its own platform-specific async rendering that is done partially
     // in Gecko and partially in Java.
     wantNextFrame |= SampleAPZAnimations(LayerMetricsWrapper(root), aCurrentFrame);
-    if (!ApplyAsyncContentTransformToTree(root)) {
+    bool foundRoot = false;
+    if (ApplyAsyncContentTransformToTree(root, &foundRoot)) {
+#if defined(MOZ_ANDROID_APZ)
+      MOZ_ASSERT(foundRoot);
+#endif
+    } else {
       nsAutoTArray<Layer*,1> scrollableLayers;
 #ifdef MOZ_WIDGET_ANDROID
       mLayerManager->GetRootScrollableLayers(scrollableLayers);
 #else
       mLayerManager->GetScrollableLayers(scrollableLayers);
 #endif
 
       for (uint32_t i = 0; i < scrollableLayers.Length(); i++) {
--- a/gfx/layers/composite/AsyncCompositionManager.h
+++ b/gfx/layers/composite/AsyncCompositionManager.h
@@ -123,18 +123,21 @@ public:
 
   // GetFrameUniformity will return the frame uniformity for each layer attached to an APZ
   // from the recorded data in RecordShadowTransform
   void GetFrameUniformity(FrameUniformityData* aFrameUniformityData);
 
 private:
   void TransformScrollableLayer(Layer* aLayer);
   // Return true if an AsyncPanZoomController content transform was
-  // applied for |aLayer|.
-  bool ApplyAsyncContentTransformToTree(Layer* aLayer);
+  // applied for |aLayer|. |*aOutFoundRoot| is set to true on Android only, if
+  // one of the metrics on one of the layers was determined to be the "root"
+  // and its state was synced to the Java front-end. |aOutFoundRoot| must be
+  // non-null.
+  bool ApplyAsyncContentTransformToTree(Layer* aLayer, bool* aOutFoundRoot);
   /**
    * Update the shadow transform for aLayer assuming that is a scrollbar,
    * so that it stays in sync with the content that is being scrolled by APZ.
    */
   void ApplyAsyncTransformToScrollbar(Layer* aLayer);
 
   void SetFirstPaintViewport(const LayerIntPoint& aOffset,
                              const CSSToLayerScale& aZoom,