Bug 1321412 - Allow controlling the size of the prerendered area via prefs. r=mattwoodrow,birtles draft
authorBotond Ballo <botond@mozilla.com>
Fri, 09 Dec 2016 20:23:42 -0500
changeset 448603 f9d3c476f4a58ce9ef21da59671c173744120f4c
parent 448053 d2bd3668bbe12b3853327f2c41e6a77acf1bbadd
child 448604 c287c114088bae3c99365d7f2e89179fcc31bd64
child 449695 76da9754419e00962b1ac96dd8046032ecce1e77
push id38378
push userbballo@mozilla.com
push dateSun, 11 Dec 2016 09:01:12 +0000
reviewersmattwoodrow, birtles
bugs1321412, 1274991
milestone53.0a1
Bug 1321412 - Allow controlling the size of the prerendered area via prefs. r=mattwoodrow,birtles Note that the default values of the prefs are chosen so as to preserve existing behaviour. The patch also updates a user-visible warning message, which was already out of date as of bug 1274991. MozReview-Commit-ID: AqBBoIucShT
dom/animation/AnimationPerformanceWarning.cpp
dom/animation/test/chrome/test_animation_performance_warning.html
dom/locales/en-US/chrome/layout/layout_errors.properties
gfx/thebes/gfxPrefs.h
layout/painting/nsDisplayList.cpp
modules/libpref/init/all.js
--- a/dom/animation/AnimationPerformanceWarning.cpp
+++ b/dom/animation/AnimationPerformanceWarning.cpp
@@ -36,22 +36,22 @@ AnimationPerformanceWarning::ToLocalized
     case Type::ContentTooSmall:
       MOZ_ASSERT(mParams && mParams->Length() == 2,
                  "Parameter's length should be 2 for ContentTooSmall");
 
       return NS_SUCCEEDED(
         ToLocalizedStringWithIntParams<2>(
           "CompositorAnimationWarningContentTooSmall", aLocalizedString));
     case Type::ContentTooLarge:
-      MOZ_ASSERT(mParams && mParams->Length() == 7,
-                 "Parameter's length should be 7 for ContentTooLarge");
+      MOZ_ASSERT(mParams && mParams->Length() == 6,
+                 "Parameter's length should be 6 for ContentTooLarge");
 
       return NS_SUCCEEDED(
         ToLocalizedStringWithIntParams<7>(
-          "CompositorAnimationWarningContentTooLarge", aLocalizedString));
+          "CompositorAnimationWarningContentTooLarge2", aLocalizedString));
     case Type::TransformBackfaceVisibilityHidden:
       key = "CompositorAnimationWarningTransformBackfaceVisibilityHidden";
       break;
     case Type::TransformPreserve3D:
       key = "CompositorAnimationWarningTransformPreserve3D";
       break;
     case Type::TransformSVG:
       key = "CompositorAnimationWarningTransformSVG";
--- a/dom/animation/test/chrome/test_animation_performance_warning.html
+++ b/dom/animation/test/chrome/test_animation_performance_warning.html
@@ -870,19 +870,19 @@ function start() {
         animation.effect.getProperties(),
         [ { property: 'transform', runningOnCompositor: true } ]);
       animation.effect.target.style = 'width: 10000px; height: 10000px';
       return waitForFrame();
     }).then(function() {
       // viewport depends on test environment.
       var expectedWarning = new RegExp(
         "Animation cannot be run on the compositor because the frame size " +
-        "\\(10000, 10000\\) is bigger than the viewport \\(\\d+, \\d+\\) " +
-        "or the visual rectangle \\(10000, 10000\\) is larger than the " +
-        "maximum allowed value \\(\\d+\\)");
+        "\\(10000, 10000\\) is too large relative to the viewport " + 
+        "\\(larger than \\(\\d+, \\d+\\)\\) or larger than the " +
+        "maximum allowed value \\(\\d+, \\d+\\)");
       assert_animation_property_state_equals(
         animation.effect.getProperties(),
         [ {
           property: 'transform',
           runningOnCompositor: false,
           warning: expectedWarning
         } ]);
       animation.effect.target.style = 'width: 100px; height: 100px';
--- a/dom/locales/en-US/chrome/layout/layout_errors.properties
+++ b/dom/locales/en-US/chrome/layout/layout_errors.properties
@@ -9,22 +9,21 @@ ImageMapPolyWrongNumberOfCoords=The “coords” attribute of the <area shape="poly"> tag is not in the “x1,y1,x2,y2 …” format.
 ImageMapPolyOddNumberOfCoords=The “coords” attribute of the <area shape="poly"> tag is missing the last “y” coordinate (the correct format is “x1,y1,x2,y2 …”).
 
 TablePartRelPosWarning=Relative positioning of table rows and row groups is now supported. This site may need to be updated because it may depend on this feature having no effect.
 ScrollLinkedEffectFound2=This site appears to use a scroll-linked positioning effect. This may not work well with asynchronous panning; see https://developer.mozilla.org/docs/Mozilla/Performance/ScrollLinkedEffects for further details and to join the discussion on related tools and features!
 
 ## LOCALIZATION NOTE(CompositorAnimationWarningContentTooSmall):
 ## (%1$S, %2$S) is a pair of integer values of the frame size
 CompositorAnimationWarningContentTooSmall=Animation cannot be run on the compositor because frame size (%1$S, %2$S) is smaller than (16, 16)
-## LOCALIZATION NOTE(CompositorAnimationWarningContentTooLarge):
+## LOCALIZATION NOTE(CompositorAnimationWarningContentTooLarge2):
 ## (%1$S, %2$S) is a pair of integer values of the frame size
-## (%3$S, %4$S) is a pair of integer values of the viewport size
-## (%5$S, %6$S) is a pair of integer values of the visual rectangle size
-## (%7$S) is an integer value
-CompositorAnimationWarningContentTooLarge=Animation cannot be run on the compositor because the frame size (%1$S, %2$S) is bigger than the viewport (%3$S, %4$S) or the visual rectangle (%5$S, %6$S) is larger than the maximum allowed value (%7$S)
+## (%3$S, %4$S) is a pair of integer values of a limit based on the viewport size
+## (%5$S, %6$S) is a pair of integer values of an absolute limit
+CompositorAnimationWarningContentTooLarge2=Animation cannot be run on the compositor because the frame size (%1$S, %2$S) is too large relative to the viewport (larger than (%3$S, %4$S)) or larger than the maximum allowed value (%5$S, %6$S)
 ## LOCALIZATION NOTE(CompositorAnimationWarningTransformBackfaceVisibilityHidden):
 ## 'backface-visibility: hidden' is a CSS property, don't translate it.
 CompositorAnimationWarningTransformBackfaceVisibilityHidden=Animations of ‘backface-visibility: hidden’ transforms cannot be run on the compositor
 ## LOCALIZATION NOTE(CompositorAnimationWarningTransformPreserve3D):
 ## 'transform-style: preserve-3d' is a CSS property, don't translate it.
 CompositorAnimationWarningTransformPreserve3D=Animations of ‘transform-style: preserve-3d’ transforms cannot be run on the compositor
 ## LOCALIZATION NOTE(CompositorAnimationWarningTransformSVG,
 ##                   CompositorAnimationWarningTransformWithGeometricProperties,
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -523,16 +523,21 @@ private:
   DECL_GFX_PREF(Once, "layers.tiles.edge-padding",             TileEdgePaddingEnabled, bool, true);
   DECL_GFX_PREF(Live, "layers.tiles.fade-in.enabled",          LayerTileFadeInEnabled, bool, false);
   DECL_GFX_PREF(Live, "layers.tiles.fade-in.duration-ms",      LayerTileFadeInDuration, uint32_t, 250);
   DECL_GFX_PREF(Live, "layers.transaction.warning-ms",         LayerTransactionWarning, uint32_t, 200);
   DECL_GFX_PREF(Once, "layers.uniformity-info",                UniformityInfo, bool, false);
   DECL_GFX_PREF(Once, "layers.use-image-offscreen-surfaces",   UseImageOffscreenSurfaces, bool, true);
   DECL_GFX_PREF(Live, "layers.draw-mask-debug",                DrawMaskLayer, bool, false);
 
+  DECL_GFX_PREF(Live, "layout.animation.prerender.viewport-ratio-limit-x", AnimationPrerenderViewportRatioLimitX, float, 1.125f);
+  DECL_GFX_PREF(Live, "layout.animation.prerender.viewport-ratio-limit-y", AnimationPrerenderViewportRatioLimitY, float, 1.125f);
+  DECL_GFX_PREF(Live, "layout.animation.prerender.absolute-limit-x", AnimationPrerenderAbsoluteLimitX, uint32_t, 4096);
+  DECL_GFX_PREF(Live, "layout.animation.prerender.absolute-limit-y", AnimationPrerenderAbsoluteLimitY, uint32_t, 4096);
+
   DECL_GFX_PREF(Live, "layout.css.scroll-behavior.damping-ratio", ScrollBehaviorDampingRatio, float, 1.0f);
   DECL_GFX_PREF(Live, "layout.css.scroll-behavior.enabled",    ScrollBehaviorEnabled, bool, true);
   DECL_GFX_PREF(Live, "layout.css.scroll-behavior.spring-constant", ScrollBehaviorSpringConstant, float, 250.0f);
   DECL_GFX_PREF(Live, "layout.css.scroll-snap.prediction-max-velocity", ScrollSnapPredictionMaxVelocity, int32_t, 2000);
   DECL_GFX_PREF(Live, "layout.css.scroll-snap.prediction-sensitivity", ScrollSnapPredictionSensitivity, float, 0.750f);
   DECL_GFX_PREF(Live, "layout.css.scroll-snap.proximity-threshold", ScrollSnapProximityThreshold, int32_t, 200);
   DECL_GFX_PREF(Live, "layout.css.touch_action.enabled",       TouchActionEnabled, bool, false);
   DECL_GFX_PREF(Live, "layout.display-list.dump",              LayoutDumpDisplayList, bool, false);
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -6169,49 +6169,49 @@ nsDisplayTransform::ShouldPrerenderTrans
     EffectCompositor::SetPerformanceWarning(
       aFrame, eCSSProperty_transform,
       AnimationPerformanceWarning(
         AnimationPerformanceWarning::Type::TransformFrameInactive));
 
     return NoPrerender;
   }
 
+  float viewportRatioX = gfxPrefs::AnimationPrerenderViewportRatioLimitX();
+  float viewportRatioY = gfxPrefs::AnimationPrerenderViewportRatioLimitY();
+  uint32_t absoluteLimitX = gfxPrefs::AnimationPrerenderAbsoluteLimitX();
+  uint32_t absoluteLimitY = gfxPrefs::AnimationPrerenderAbsoluteLimitY();
   nsSize refSize = aBuilder->RootReferenceFrame()->GetSize();
-  // Only prerender if the transformed frame's size is <= the
-  // reference frame size (~viewport), allowing a 1/8th fuzz factor
-  // for shadows, borders, etc.
-  refSize += nsSize(refSize.width / 8, refSize.height / 8);
+  // Only prerender if the transformed frame's size is <= a multiple of the
+  // reference frame size (~viewport), and less than an absolute limit.
+  // Both the ratio and the absolute limit are configurable.
+  nsSize relativeLimit(nscoord(refSize.width * viewportRatioX),
+                       nscoord(refSize.height * viewportRatioY));
+  nsSize absoluteLimit(aFrame->PresContext()->DevPixelsToAppUnits(absoluteLimitX),
+                       aFrame->PresContext()->DevPixelsToAppUnits(absoluteLimitY));
+  nsSize maxSize = Min(relativeLimit, absoluteLimit);
   gfxSize scale = nsLayoutUtils::GetTransformToAncestorScale(aFrame);
   nsRect overflow = aFrame->GetVisualOverflowRectRelativeToSelf();
   nsSize frameSize = nsSize(overflow.Size().width * scale.width,
                             overflow.Size().height * scale.height);
-  nscoord maxInAppUnits = nscoord_MAX;
-  if (frameSize <= refSize) {
-    maxInAppUnits = aFrame->PresContext()->DevPixelsToAppUnits(4096);
-    if (frameSize <= nsSize(maxInAppUnits, maxInAppUnits)) {
-      *aDirtyRect = overflow;
-      return FullPrerender;
-    }
-  }
-
-  nsRect visual = aFrame->GetVisualOverflowRect();
-
+  if (frameSize <= maxSize) {
+    *aDirtyRect = overflow;
+    return FullPrerender;
+  }
 
   EffectCompositor::SetPerformanceWarning(
     aFrame, eCSSProperty_transform,
     AnimationPerformanceWarning(
       AnimationPerformanceWarning::Type::ContentTooLarge,
       {
         nsPresContext::AppUnitsToIntCSSPixels(frameSize.width),
         nsPresContext::AppUnitsToIntCSSPixels(frameSize.height),
-        nsPresContext::AppUnitsToIntCSSPixels(refSize.width),
-        nsPresContext::AppUnitsToIntCSSPixels(refSize.height),
-        nsPresContext::AppUnitsToIntCSSPixels(visual.width),
-        nsPresContext::AppUnitsToIntCSSPixels(visual.height),
-        nsPresContext::AppUnitsToIntCSSPixels(maxInAppUnits)
+        nsPresContext::AppUnitsToIntCSSPixels(relativeLimit.width),
+        nsPresContext::AppUnitsToIntCSSPixels(relativeLimit.height),
+        nsPresContext::AppUnitsToIntCSSPixels(absoluteLimit.width),
+        nsPresContext::AppUnitsToIntCSSPixels(absoluteLimit.height),
       }));
   return NoPrerender;
 }
 
 /* If the matrix is singular, or a hidden backface is shown, the frame won't be visible or hit. */
 static bool IsFrameVisible(nsIFrame* aFrame, const Matrix4x4& aMatrix)
 {
   if (aMatrix.IsSingular()) {
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -2723,16 +2723,23 @@ pref("dom.animations-api.core.enabled", 
 // API) enabled?
 // Note that if dom.animations-api.core.enabled is true, this preference is
 // ignored.
 pref("dom.animations-api.element-animate.enabled", true);
 
 // Pref to throttle offsreen animations
 pref("dom.animations.offscreen-throttling", true);
 
+// Prefs to control the maximum area to pre-render when animating a large
+// element on the compositor.
+pref("layout.animation.prerender.viewport-ratio-limit-x", "1.125");
+pref("layout.animation.prerender.viewport-ratio-limit-y", "1.125");
+pref("layout.animation.prerender.absolute-limit-x", 4096);
+pref("layout.animation.prerender.absolute-limit-y", 4096);
+
 // pref to permit users to make verified SOAP calls by default
 pref("capability.policy.default.SOAPCall.invokeVerifySourceHeader", "allAccess");
 
 // if true, allow plug-ins to override internal imglib decoder mime types in full-page mode
 pref("plugin.override_internal_types", false);
 
 // See bug 136985.  Gives embedders a pref to hook into to show
 // a popup blocker if they choose.