Bug 1509552 - MobileViewportManager::UpdateResolution cleanup, part 3. r=kats
authorBotond Ballo <botond@mozilla.com>
Fri, 30 Nov 2018 00:58:56 +0000
changeset 505342 038125c617dca34532412d7d641306c73c011150
parent 505341 8085138baf577e8f849155ab743a9376e5c9e2cd
child 505343 d8064028f0e66760a66105089a0bc1258877b6bf
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1509552
milestone65.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 1509552 - MobileViewportManager::UpdateResolution cleanup, part 3. r=kats Adds an |UpdateType| parameter to UpdateResolution() to better separate the pre-reflow and post-reflow logic. Differential Revision: https://phabricator.services.mozilla.com/D13314
layout/base/MobileViewportManager.cpp
layout/base/MobileViewportManager.h
--- a/layout/base/MobileViewportManager.cpp
+++ b/layout/base/MobileViewportManager.cpp
@@ -237,89 +237,100 @@ ZoomToResolution(CSSToScreenScale aZoom,
   return ViewTargetAs<ParentLayerPixel>(aZoom,
       PixelCastJustification::ScreenIsParentLayerForRoot)
     / aCssToDev * ParentLayerToLayerScale(1);
 }
 
 void
 MobileViewportManager::UpdateResolution(const nsViewportInfo& aViewportInfo,
                                         const ScreenIntSize& aDisplaySize,
-                                        const CSSSize& aViewport,
-                                        const Maybe<float>& aDisplayWidthChangeRatio)
+                                        const CSSSize& aViewportOrContentSize,
+                                        const Maybe<float>& aDisplayWidthChangeRatio,
+                                        UpdateType aType)
 {
   CSSToLayoutDeviceScale cssToDev =
       mPresShell->GetPresContext()->CSSToDevPixelScale();
   LayoutDeviceToLayerScale res(mPresShell->GetResolution());
   CSSToScreenScale zoom = ResolutionToZoom(res, cssToDev);
   Maybe<CSSToScreenScale> newZoom;
 
-  if (mIsFirstPaint) {
-    ScreenIntSize compositionSize = GetCompositionSize(aDisplaySize);
+  ScreenIntSize compositionSize = GetCompositionSize(aDisplaySize);
+  CSSToScreenScale intrinsicScale = ComputeIntrinsicScale(aViewportInfo,
+                                                          compositionSize,
+                                                          aViewportOrContentSize);
 
-    CSSToScreenScale defaultZoom;
-    if (mRestoreResolution) {
-      LayoutDeviceToLayerScale restoreResolution(mRestoreResolution.value());
-      CSSToScreenScale restoreZoom = ResolutionToZoom(restoreResolution, cssToDev);
-      if (mRestoreDisplaySize) {
-        CSSSize prevViewport = mDocument->GetViewportInfo(mRestoreDisplaySize.value()).GetSize();
-        float restoreDisplayWidthChangeRatio = (mRestoreDisplaySize.value().width > 0)
-          ? (float)compositionSize.width / (float)mRestoreDisplaySize.value().width : 1.0f;
+  if (aType == UpdateType::ViewportSize) {
+    const CSSSize& viewportSize = aViewportOrContentSize;
+    if (mIsFirstPaint) {
+      CSSToScreenScale defaultZoom;
+      if (mRestoreResolution) {
+        LayoutDeviceToLayerScale restoreResolution(mRestoreResolution.value());
+        CSSToScreenScale restoreZoom = ResolutionToZoom(restoreResolution, cssToDev);
+        if (mRestoreDisplaySize) {
+          CSSSize prevViewport = mDocument->GetViewportInfo(mRestoreDisplaySize.value()).GetSize();
+          float restoreDisplayWidthChangeRatio = (mRestoreDisplaySize.value().width > 0)
+            ? (float)compositionSize.width / (float)mRestoreDisplaySize.value().width : 1.0f;
 
-        restoreZoom =
-          ScaleZoomWithDisplayWidth(restoreZoom,
-                                    restoreDisplayWidthChangeRatio,
-                                    aViewport,
-                                    prevViewport);
+          restoreZoom =
+            ScaleZoomWithDisplayWidth(restoreZoom,
+                                      restoreDisplayWidthChangeRatio,
+                                      viewportSize,
+                                      prevViewport);
+        }
+        defaultZoom = restoreZoom;
+        MVM_LOG("%p: restored zoom is %f\n", this, defaultZoom.scale);
+        defaultZoom = ClampZoom(defaultZoom, aViewportInfo);
+      } else {
+        defaultZoom = aViewportInfo.GetDefaultZoom();
+        MVM_LOG("%p: default zoom from viewport is %f\n", this, defaultZoom.scale);
+        if (!aViewportInfo.IsDefaultZoomValid()) {
+          defaultZoom = intrinsicScale;
+        }
       }
-      defaultZoom = restoreZoom;
-      MVM_LOG("%p: restored zoom is %f\n", this, defaultZoom.scale);
-      defaultZoom = ClampZoom(defaultZoom, aViewportInfo);
+      MOZ_ASSERT(aViewportInfo.GetMinZoom() <= defaultZoom &&
+        defaultZoom <= aViewportInfo.GetMaxZoom());
+
+      // On first paint, we always consider the zoom to have changed.
+      newZoom = Some(defaultZoom);
     } else {
-      defaultZoom = aViewportInfo.GetDefaultZoom();
-      MVM_LOG("%p: default zoom from viewport is %f\n", this, defaultZoom.scale);
-      if (!aViewportInfo.IsDefaultZoomValid()) {
-        defaultZoom = ComputeIntrinsicScale(aViewportInfo,
-                                            compositionSize,
-                                            aViewport);
+      // If this is not a first paint, then in some cases we want to update the pre-
+      // existing resolution so as to maintain how much actual content is visible
+      // within the display width. Note that "actual content" may be different with
+      // respect to CSS pixels because of the CSS viewport size changing.
+      //
+      // aDisplayWidthChangeRatio is non-empty if:
+      // (a) The meta-viewport tag information changes, and so the CSS viewport
+      //     might change as a result. If this happens after the content has been
+      //     painted, we want to adjust the zoom to compensate. OR
+      // (b) The display size changed from a nonzero value to another nonzero value.
+      //     This covers the case where e.g. the device was rotated, and again we
+      //     want to adjust the zoom to compensate.
+      // Note in particular that aDisplayWidthChangeRatio will be None if all that
+      // happened was a change in the full-zoom. In this case, we still want to
+      // compute a new CSS viewport, but we don't want to update the resolution.
+      //
+      // Given the above, the algorithm below accounts for all types of changes I
+      // can conceive of:
+      // 1. screen size changes, CSS viewport does not (pages with no meta viewport
+      //    or a fixed size viewport)
+      // 2. screen size changes, CSS viewport also does (pages with a device-width
+      //    viewport)
+      // 3. screen size remains constant, but CSS viewport changes (meta viewport
+      //    tag is added or removed)
+      // 4. neither screen size nor CSS viewport changes
+      if (aDisplayWidthChangeRatio) {
+        newZoom = Some(ScaleZoomWithDisplayWidth(zoom, aDisplayWidthChangeRatio.value(),
+          viewportSize, mMobileViewportSize));
       }
     }
-    MOZ_ASSERT(aViewportInfo.GetMinZoom() <= defaultZoom &&
-      defaultZoom <= aViewportInfo.GetMaxZoom());
-
-    // On first paint, we always consider the zoom to have changed.
-    newZoom = Some(defaultZoom);
-  } else {
-    // If this is not a first paint, then in some cases we want to update the pre-
-    // existing resolution so as to maintain how much actual content is visible
-    // within the display width. Note that "actual content" may be different with
-    // respect to CSS pixels because of the CSS viewport size changing.
-    //
-    // aDisplayWidthChangeRatio is non-empty if:
-    // (a) The meta-viewport tag information changes, and so the CSS viewport
-    //     might change as a result. If this happens after the content has been
-    //     painted, we want to adjust the zoom to compensate. OR
-    // (b) The display size changed from a nonzero value to another nonzero value.
-    //     This covers the case where e.g. the device was rotated, and again we
-    //     want to adjust the zoom to compensate.
-    // Note in particular that aDisplayWidthChangeRatio will be None if all that
-    // happened was a change in the full-zoom. In this case, we still want to
-    // compute a new CSS viewport, but we don't want to update the resolution.
-    //
-    // Given the above, the algorithm below accounts for all types of changes I
-    // can conceive of:
-    // 1. screen size changes, CSS viewport does not (pages with no meta viewport
-    //    or a fixed size viewport)
-    // 2. screen size changes, CSS viewport also does (pages with a device-width
-    //    viewport)
-    // 3. screen size remains constant, but CSS viewport changes (meta viewport
-    //    tag is added or removed)
-    // 4. neither screen size nor CSS viewport changes
-    if (aDisplayWidthChangeRatio) {
-      newZoom = Some(ScaleZoomWithDisplayWidth(zoom, aDisplayWidthChangeRatio.value(),
-        aViewport, mMobileViewportSize));
+  } else {  // aType == UpdateType::ContentSize
+    MOZ_ASSERT(aType == UpdateType::ContentSize);
+    MOZ_ASSERT(aDisplayWidthChangeRatio.isNothing());
+    if (zoom != intrinsicScale) {
+      newZoom = Some(intrinsicScale);
     }
   }
 
   // If the zoom has changed, update the pres shell resolution and the
   // visual viewport size accordingly.
   if (newZoom) {
     LayoutDeviceToLayerScale resolution = ZoomToResolution(*newZoom, cssToDev);
     MVM_LOG("%p: setting resolution %f\n", this, resolution.scale);
@@ -462,17 +473,18 @@ MobileViewportManager::RefreshViewportSi
   }
 
   // If it's the first-paint or the viewport changed, we need to update
   // various APZ properties (the zoom and some things that might depend on it)
   MVM_LOG("%p: Updating properties because %d || %d\n", this,
     mIsFirstPaint, mMobileViewportSize != viewport);
 
   if (gfxPrefs::APZAllowZooming()) {
-    UpdateResolution(viewportInfo, displaySize, viewport, displayWidthChangeRatio);
+    UpdateResolution(viewportInfo, displaySize, viewport,
+        displayWidthChangeRatio, UpdateType::ViewportSize);
   }
   if (gfxPlatform::AsyncPanZoomEnabled()) {
     UpdateDisplayPortMargins();
   }
 
   CSSSize oldSize = mMobileViewportSize;
 
   // Update internal state.
@@ -513,11 +525,12 @@ MobileViewportManager::ShrinkToDisplaySi
 
   nsIScrollableFrame* rootScrollableFrame =
     mPresShell->GetRootScrollFrameAsScrollable();
   if (rootScrollableFrame) {
     nsRect scrollableRect =
       nsLayoutUtils::CalculateScrollableRectForFrame(rootScrollableFrame,
                                                      nullptr);
     CSSSize contentSize = CSSSize::FromAppUnits(scrollableRect.Size());
-    UpdateResolution(aViewportInfo, aDisplaySize, contentSize, Nothing());
+    UpdateResolution(aViewportInfo, aDisplaySize, contentSize, Nothing(),
+        UpdateType::ContentSize);
   }
 }
--- a/layout/base/MobileViewportManager.h
+++ b/layout/base/MobileViewportManager.h
@@ -88,21 +88,33 @@ public:
 
   /* Helper to update the given zoom according to changed display and viewport widths. */
   mozilla::CSSToScreenScale
   ScaleZoomWithDisplayWidth(const mozilla::CSSToScreenScale& aZoom,
                             const float& aDisplayWidthChangeRatio,
                             const mozilla::CSSSize& aNewViewport,
                             const mozilla::CSSSize& aOldViewport);
 
+  /* Helper enum for UpdateResolution().
+   * UpdateResolution() is called twice during RefreshViewportSize():
+   * First, to choose an initial resolution based on the viewport size.
+   * Second, after reflow when we know the content size, to make any
+   * necessary adjustments to the resolution.
+   * This enumeration discriminates between the two situations.
+   */
+  enum class UpdateType {
+    ViewportSize, ContentSize
+  };
+
   /* Updates the presShell resolution and the visual viewport size. */
   void UpdateResolution(const nsViewportInfo& aViewportInfo,
                         const mozilla::ScreenIntSize& aDisplaySize,
-                        const mozilla::CSSSize& aViewport,
-                        const mozilla::Maybe<float>& aDisplayWidthChangeRatio);
+                        const mozilla::CSSSize& aViewportOrContentSize,
+                        const mozilla::Maybe<float>& aDisplayWidthChangeRatio,
+                        UpdateType aType);
 
   void UpdateVisualViewportSize(const mozilla::ScreenIntSize& aDisplaySize,
                                 const mozilla::CSSToScreenScale& aZoom);
 
   /* Updates the displayport margins for the presShell's root scrollable frame */
   void UpdateDisplayPortMargins();
 
   /* Helper function for ComputeIntrinsicResolution(). */