Bug 1246290 - Add a pref to allow disabling APZ on documents which have scroll-linked effects. r=botond
MozReview-Commit-ID: 9sjYFLf0nWl
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -150,16 +150,24 @@ using mozilla::gfx::PointTyped;
* goes from y=0...1000 and the visible portion is y=250...750 then
* we're far from checkerboarding. If we get to y=490...990 though then we're
* only 10 pixels away from showing checkerboarding so we are probably in
* a state where we can't keep up with scrolling. The danger zone prefs specify
* how wide this margin is; in the above example a y-axis danger zone of 10
* pixels would make us drop to low-res at y=490...990.\n
* This value is in layer pixels.
*
+ * \li\b apz.disable_for_scroll_linked_effects
+ * Setting this pref to true will disable APZ scrolling on documents where
+ * scroll-linked effects are detected. A scroll linked effect is detected if
+ * positioning or transform properties are updated inside a scroll event
+ * dispatch; we assume that such an update is in response to the scroll event
+ * and is therefore a scroll-linked effect which will be laggy with APZ
+ * scrolling.
+ *
* \li\b apz.displayport_expiry_ms
* While a scrollable frame is scrolling async, we set a displayport on it
* to make sure it is layerized. However this takes up memory, so once the
* scrolling stops we want to remove the displayport. This pref controls how
* long after scrolling stops the displayport is removed. A value of 0 will
* disable the expiry behavior entirely.
* Units: milliseconds
*
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -143,16 +143,17 @@ private:
DECL_GFX_PREF(Live, "apz.axis_lock.breakout_angle", APZAxisBreakoutAngle, float, float(M_PI / 8.0) /* 22.5 degrees */);
DECL_GFX_PREF(Live, "apz.axis_lock.breakout_threshold", APZAxisBreakoutThreshold, float, 1.0f / 32.0f);
DECL_GFX_PREF(Live, "apz.axis_lock.direct_pan_angle", APZAllowedDirectPanAngle, float, float(M_PI / 3.0) /* 60 degrees */);
DECL_GFX_PREF(Live, "apz.axis_lock.lock_angle", APZAxisLockAngle, float, float(M_PI / 6.0) /* 30 degrees */);
DECL_GFX_PREF(Live, "apz.axis_lock.mode", APZAxisLockMode, int32_t, 0);
DECL_GFX_PREF(Live, "apz.content_response_timeout", APZContentResponseTimeout, int32_t, 300);
DECL_GFX_PREF(Live, "apz.danger_zone_x", APZDangerZoneX, int32_t, 50);
DECL_GFX_PREF(Live, "apz.danger_zone_y", APZDangerZoneY, int32_t, 100);
+ DECL_GFX_PREF(Live, "apz.disable_for_scroll_linked_effects", APZDisableForScrollLinkedEffects, bool, false);
DECL_GFX_PREF(Live, "apz.displayport_expiry_ms", APZDisplayPortExpiryTime, uint32_t, 15000);
DECL_GFX_PREF(Live, "apz.drag.enabled", APZDragEnabled, bool, false);
DECL_GFX_PREF(Live, "apz.enlarge_displayport_when_clipped", APZEnlargeDisplayPortWhenClipped, bool, false);
DECL_GFX_PREF(Live, "apz.fling_accel_base_mult", APZFlingAccelBaseMultiplier, float, 1.0f);
DECL_GFX_PREF(Live, "apz.fling_accel_interval_ms", APZFlingAccelInterval, int32_t, 500);
DECL_GFX_PREF(Live, "apz.fling_accel_supplemental_mult", APZFlingAccelSupplementalMultiplier, float, 1.0f);
DECL_GFX_PREF(Once, "apz.fling_curve_function_x1", APZCurveFunctionX1, float, 0.0f);
DECL_GFX_PREF(Once, "apz.fling_curve_function_x2", APZCurveFunctionX2, float, 1.0f);
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1054,16 +1054,26 @@ GetDisplayPortFromMarginsData(nsIContent
nsRect expandedScrollableRect =
nsLayoutUtils::CalculateExpandedScrollableRect(frame);
result = result.MoveInsideAndClamp(expandedScrollableRect - scrollPos);
return result;
}
static bool
+ShouldDisableApzForElement(nsIContent* aContent)
+{
+ if (gfxPrefs::APZDisableForScrollLinkedEffects() && aContent) {
+ nsIDocument* doc = aContent->GetComposedDoc();
+ return (doc && doc->HasScrollLinkedEffect());
+ }
+ return false;
+}
+
+static bool
GetDisplayPortImpl(nsIContent* aContent, nsRect *aResult, float aMultiplier)
{
DisplayPortPropertyData* rectData =
static_cast<DisplayPortPropertyData*>(aContent->GetProperty(nsGkAtoms::DisplayPort));
DisplayPortMarginsPropertyData* marginsData =
static_cast<DisplayPortMarginsPropertyData*>(aContent->GetProperty(nsGkAtoms::DisplayPortMargins));
if (!rectData && !marginsData) {
@@ -1087,17 +1097,17 @@ GetDisplayPortImpl(nsIContent* aContent,
}
NS_ASSERTION((rectData == nullptr) != (marginsData == nullptr),
"Only one of rectData or marginsData should be set!");
nsRect result;
if (rectData) {
result = GetDisplayPortFromRectData(aContent, rectData, aMultiplier);
- } else if (APZCCallbackHelper::IsDisplayportSuppressed()) {
+ } else if (APZCCallbackHelper::IsDisplayportSuppressed() || ShouldDisableApzForElement(aContent)) {
DisplayPortMarginsPropertyData noMargins(ScreenMargin(), 1);
result = GetDisplayPortFromMarginsData(aContent, &noMargins, aMultiplier);
} else {
result = GetDisplayPortFromMarginsData(aContent, marginsData, aMultiplier);
}
if (!gfxPrefs::LayersTilesEnabled()) {
// Either we should have gotten a valid rect directly from the displayport
@@ -8791,16 +8801,20 @@ nsLayoutUtils::ComputeFrameMetrics(nsIFr
nsStyleContext* backgroundStyle;
if (nsCSSRendering::FindBackground(aScrollFrame, &backgroundStyle)) {
metrics.SetBackgroundColor(Color::FromABGR(
backgroundStyle->StyleBackground()->mBackgroundColor));
}
}
}
+ if (ShouldDisableApzForElement(aContent)) {
+ metrics.SetForceDisableApz(true);
+ }
+
return metrics;
}
/* static */ bool
nsLayoutUtils::ContainsMetricsWithId(const Layer* aLayer, const ViewID& aScrollId)
{
for (uint32_t i = aLayer->GetFrameMetricsCount(); i > 0; i--) {
if (aLayer->GetFrameMetrics(i-1).GetScrollId() == aScrollId) {
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -562,16 +562,17 @@ pref("apz.axis_lock.mode", 0);
pref("apz.axis_lock.lock_angle", "0.5235987"); // PI / 6 (30 degrees)
pref("apz.axis_lock.breakout_threshold", "0.03125"); // 1/32 inches
pref("apz.axis_lock.breakout_angle", "0.3926991"); // PI / 8 (22.5 degrees)
pref("apz.axis_lock.direct_pan_angle", "1.047197"); // PI / 3 (60 degrees)
pref("apz.content_response_timeout", 300);
pref("apz.drag.enabled", false);
pref("apz.danger_zone_x", 50);
pref("apz.danger_zone_y", 100);
+pref("apz.disable_for_scroll_linked_effects", false);
pref("apz.displayport_expiry_ms", 15000);
pref("apz.enlarge_displayport_when_clipped", false);
pref("apz.fling_accel_base_mult", "1.0");
pref("apz.fling_accel_interval_ms", 500);
pref("apz.fling_accel_supplemental_mult", "1.0");
pref("apz.fling_curve_function_x1", "0.0");
pref("apz.fling_curve_function_y1", "0.0");
pref("apz.fling_curve_function_x2", "1.0");