Commit f18788ff authored by Yi Gu's avatar Yi Gu Committed by Commit Bot

Reland "Experiment on not compositing small scrollers"

The previous patch https://chromium-review.googlesource.com/c/585290/
got reverted because it added a unit test which failed Android Nexus 4
bot. For select elements, it looks like that we create paint layers on
most platforms but not on Nexus 4. Therefore ASSERT_TRUE(paint_layer)
failed on that bot. The only difference between this patch and the
previous one is now I use:
 ASSERT_TRUE(!paint_layer || !paint_layer->HasCompositedLayerMapping())
instead of:
 ASSERT_TRUE(paint_layer);
 ASSERT_FALSE(paint_layer->HasCompositedLayerMapping());

Bug: 684631, 746018
Cq-Include-Trybots: master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2
Change-Id: I9d8f68bced170bdb74cacee3aeb3096e99a07b53
Reviewed-on: https://chromium-review.googlesource.com/596207Reviewed-by: default avatarChris Harrelson <chrishtr@chromium.org>
Commit-Queue: Yi Gu <yigu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#491023}
parent 9a93b23c
......@@ -312,8 +312,7 @@ void CompositingRequirementsUpdater::UpdateRecursive(
// needsCompositedScrolling ignoring LCD to correctly add the
// CompositingReasonOverflowScrollingTouch reason to layers that can
// support it with grayscale AA text.
layer->GetScrollableArea()->UpdateNeedsCompositedScrolling(
PaintLayerScrollableArea::kIgnoreLCDText);
layer->GetScrollableArea()->UpdateNeedsCompositedScrolling(true);
if (layer->NeedsCompositedScrolling())
reasons_to_composite |= kCompositingReasonOverflowScrollingTouch;
}
......
......@@ -87,6 +87,7 @@
#include "platform/graphics/paint/DrawingRecorder.h"
#include "platform/scroll/ScrollAnimatorBase.h"
#include "platform/scroll/ScrollbarTheme.h"
#include "platform/wtf/CheckedNumeric.h"
#include "public/platform/Platform.h"
namespace blink {
......@@ -97,6 +98,11 @@ namespace {
// minimum size used by firefox is 15x15.
static const int kDefaultMinimumWidthForResizing = 15;
static const int kDefaultMinimumHeightForResizing = 15;
// By not compositing scrollers smaller than 160000px (400 * 400), on android
// devices we might affect roughly 90% scrollers for memory saving while at
// most 30% scrolls may be slowed down. On non-android devices, it affects
// roughly 50% scrollers and 13% scrolls.
static constexpr int kSmallScrollerThreshold = 160000;
} // namespace
......@@ -1920,7 +1926,7 @@ static bool LayerNodeMayNeedCompositedScrolling(const PaintLayer* layer) {
}
bool PaintLayerScrollableArea::ComputeNeedsCompositedScrolling(
const LCDTextMode mode,
const bool layer_has_been_composited,
const PaintLayer* layer) {
non_composited_main_thread_scrolling_reasons_ = 0;
......@@ -1938,8 +1944,19 @@ bool PaintLayerScrollableArea::ComputeNeedsCompositedScrolling(
if (layer->size().IsEmpty())
return false;
if (!LayerNodeMayNeedCompositedScrolling(layer))
// This is for an experiment aiming at memory save by not compositing certain
// scrollers. See http://crbug.com/746018, http://crbug.com/684631.
// TODO(yigu): Report this main thread scrolling reason once the patch is
// landed.
CheckedNumeric<int> size = VisibleContentRect().Width();
size *= VisibleContentRect().Height();
if (!layer_has_been_composited &&
((RuntimeEnabledFeatures::SkipCompositingSmallScrollersEnabled() &&
size.ValueOrDefault(std::numeric_limits<int>::max()) <
kSmallScrollerThreshold) ||
!LayerNodeMayNeedCompositedScrolling(layer))) {
return false;
}
bool needs_composited_scrolling = true;
......@@ -1955,7 +1972,7 @@ bool PaintLayerScrollableArea::ComputeNeedsCompositedScrolling(
ToLayoutBox(layer->GetLayoutObject()).PaddingBoxRect()) &&
!layer->CompositesWithTransform() && !layer->CompositesWithOpacity();
if (mode == PaintLayerScrollableArea::kConsiderLCDText &&
if (!layer_has_been_composited &&
!layer->Compositor()->PreferCompositingToLCDTextEnabled() &&
!background_supports_lcd_text) {
if (layer->CompositesWithOpacity()) {
......@@ -2001,9 +2018,9 @@ bool PaintLayerScrollableArea::ComputeNeedsCompositedScrolling(
}
void PaintLayerScrollableArea::UpdateNeedsCompositedScrolling(
LCDTextMode mode) {
bool layer_has_been_composited) {
const bool needs_composited_scrolling =
ComputeNeedsCompositedScrolling(mode, Layer());
ComputeNeedsCompositedScrolling(layer_has_been_composited, Layer());
if (static_cast<bool>(needs_composited_scrolling_) !=
needs_composited_scrolling) {
......
......@@ -412,9 +412,7 @@ class CORE_EXPORT PaintLayerScrollableArea final
// Rectangle encompassing the scroll corner and resizer rect.
IntRect ScrollCornerAndResizerRect() const final;
enum LCDTextMode { kConsiderLCDText, kIgnoreLCDText };
void UpdateNeedsCompositedScrolling(LCDTextMode = kConsiderLCDText);
void UpdateNeedsCompositedScrolling(bool layer_has_been_composited = false);
bool NeedsCompositedScrolling() const { return needs_composited_scrolling_; }
// These are used during compositing updates to determine if the overflow
......@@ -557,7 +555,7 @@ class CORE_EXPORT PaintLayerScrollableArea final
return *rare_data_.get();
}
bool ComputeNeedsCompositedScrolling(const LCDTextMode, const PaintLayer*);
bool ComputeNeedsCompositedScrolling(const bool, const PaintLayer*);
PaintLayer& layer_;
PaintLayer* next_topmost_scroll_child_;
......
......@@ -455,6 +455,166 @@ TEST_F(PaintLayerScrollableAreaTest, OnlyOpaqueLayersPromoted) {
EXPECT_FALSE(paint_layer->GraphicsLayerBacking());
}
// Test that small scrollers (area < 160000px) don't get promoted.
TEST_F(PaintLayerScrollableAreaTest, SmallScrollerPromotionTest) {
GetDocument().GetFrame()->GetSettings()->SetPreferCompositingToLCDTextEnabled(
true);
RuntimeEnabledFeatures::SetSkipCompositingSmallScrollersEnabled(true);
SetBodyInnerHTML(
"<!DOCTYPE html>"
"<style>"
" .smallBox { overflow: scroll; width: 100px; height: 100px; }"
" .spacer { height: 2000px; }"
"</style>"
"<div id='small' class='smallBox'><div class='spacer'></div></div>");
GetDocument().View()->UpdateAllLifecyclePhases();
EXPECT_TRUE(RuntimeEnabledFeatures::SkipCompositingSmallScrollersEnabled());
Element* small_scroller = GetDocument().getElementById("small");
PaintLayer* small_layer =
ToLayoutBoxModelObject(small_scroller->GetLayoutObject())->Layer();
ASSERT_TRUE(small_layer);
EXPECT_FALSE(small_layer->NeedsCompositedScrolling());
}
// Test that large scrollers get promoted with PreferCompositingToLCDEnabled or
// other compositing reasons like will-change:transform.
TEST_F(PaintLayerScrollableAreaTest, LargeScrollerPromotionTest) {
GetDocument().GetFrame()->GetSettings()->SetPreferCompositingToLCDTextEnabled(
false);
RuntimeEnabledFeatures::SetSkipCompositingSmallScrollersEnabled(true);
SetBodyInnerHTML(
"<!DOCTYPE html>"
"<style>"
" .largeBox { overflow: scroll; width: 400px; height: 400px; }"
" .composited { will-change: transform; }"
" .spacer { height: 2000px; }"
"</style>"
"<div id='largeBox1' class='composited largeBox'>"
" <div class='spacer'></div>"
"</div>"
"<div id='largeBox2' class='largeBox'><div class='spacer'></div></div>");
GetDocument().View()->UpdateAllLifecyclePhases();
EXPECT_TRUE(RuntimeEnabledFeatures::SkipCompositingSmallScrollersEnabled());
Element* large_scroller = GetDocument().getElementById("largeBox1");
PaintLayer* large_layer =
ToLayoutBoxModelObject(large_scroller->GetLayoutObject())->Layer();
ASSERT_TRUE(large_layer);
EXPECT_TRUE(large_layer->NeedsCompositedScrolling());
large_scroller = GetDocument().getElementById("largeBox2");
large_layer =
ToLayoutBoxModelObject(large_scroller->GetLayoutObject())->Layer();
ASSERT_TRUE(large_layer);
EXPECT_FALSE(large_layer->NeedsCompositedScrolling());
GetDocument().GetFrame()->GetSettings()->SetPreferCompositingToLCDTextEnabled(
true);
GetDocument().View()->UpdateAllLifecyclePhases();
EXPECT_TRUE(large_layer->NeedsCompositedScrolling());
}
// Test that small scrollers with separate compositing reasons get promoted.
TEST_F(PaintLayerScrollableAreaTest,
SmallScrollerWithSeparateCompositingReasonPromotionTest) {
GetDocument().GetFrame()->GetSettings()->SetPreferCompositingToLCDTextEnabled(
true);
RuntimeEnabledFeatures::SetSkipCompositingSmallScrollersEnabled(true);
SetBodyInnerHTML(
"<!DOCTYPE html>"
"<style>"
" .smallBox { overflow: scroll; width: 100px; height: 100px; }"
" .composited { backface-visibility: hidden; }"
" .composited2 { will-change: transform; }"
" .spacer { height: 2000px; }"
"</style>"
"<div id='box1' class='composited smallBox'>"
" <div class='spacer'></div>"
"</div>"
"<div id='box2' class='composited2 smallBox'>"
" <div class='spacer'></div>"
"</div>"
"<div class='composited smallBox'>"
" <div id='box3' style='opacity: 0.5;' class='smallBox'>"
" <div class='spacer'></div>"
" </div>"
" <div class='spacer'></div>"
"</div>");
GetDocument().View()->UpdateAllLifecyclePhases();
EXPECT_TRUE(RuntimeEnabledFeatures::SkipCompositingSmallScrollersEnabled());
Element* small_scroller = GetDocument().getElementById("box1");
PaintLayer* small_layer =
ToLayoutBoxModelObject(small_scroller->GetLayoutObject())->Layer();
ASSERT_TRUE(small_layer);
EXPECT_TRUE(small_layer->NeedsCompositedScrolling());
small_scroller = GetDocument().getElementById("box2");
small_layer =
ToLayoutBoxModelObject(small_scroller->GetLayoutObject())->Layer();
ASSERT_TRUE(small_layer);
EXPECT_TRUE(small_layer->NeedsCompositedScrolling());
small_scroller = GetDocument().getElementById("box3");
small_layer =
ToLayoutBoxModelObject(small_scroller->GetLayoutObject())->Layer();
ASSERT_TRUE(small_layer);
EXPECT_TRUE(small_layer->NeedsCompositedScrolling());
}
// Test that <input> elements get promoted with "will-change:transform".
TEST_F(PaintLayerScrollableAreaTest, InputElementPromotionTest) {
SetBodyInnerHTML(
"<!DOCTYPE html>"
"<style>"
" .composited { will-change: transform; }"
"</style>"
"<input id='input' width=10 style='font-size:40pt;'/>");
GetDocument().View()->UpdateAllLifecyclePhases();
Element* element = GetDocument().getElementById("input");
PaintLayer* paint_layer =
ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
ASSERT_FALSE(paint_layer);
element->setAttribute("class", "composited");
GetDocument().View()->UpdateAllLifecyclePhases();
paint_layer = ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
ASSERT_TRUE(paint_layer->HasCompositedLayerMapping());
}
// Test that <select> elements get promoted with "will-change:transform".
TEST_F(PaintLayerScrollableAreaTest, SelectElementPromotionTest) {
SetBodyInnerHTML(
"<!DOCTYPE html>"
"<style>"
" .composited { will-change: transform; }"
"</style>"
"<select id='select' size='2'>"
" <option> value 1</option>"
" <option> value 2</option>"
" <option> value 3</option>"
" <option> value 4</option>"
"</select>");
GetDocument().View()->UpdateAllLifecyclePhases();
Element* element = GetDocument().getElementById("select");
PaintLayer* paint_layer =
ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
// Paint layer is created on most platforms but not on all of them, e.g.
// Android Nexus 4. It's better not to check paint_layer separately.
ASSERT_TRUE(!paint_layer || !paint_layer->HasCompositedLayerMapping());
element->setAttribute("class", "composited");
GetDocument().View()->UpdateAllLifecyclePhases();
paint_layer = ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
ASSERT_TRUE(paint_layer->HasCompositedLayerMapping());
}
// Ensure OverlayScrollbarColorTheme get updated when page load
TEST_F(PaintLayerScrollableAreaTest, OverlayScrollbarColorThemeUpdated) {
SetBodyInnerHTML(
......
......@@ -989,7 +989,6 @@
},
{
name: "SkipCompositingSmallScrollers",
status: "test",
},
{
name: "SlimmingPaintStrictCullRectClipping",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment