summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc')
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc446
1 files changed, 226 insertions, 220 deletions
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc
index 4fadc94b899..9728634781a 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/paint_controller_paint_test.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
+#include "third_party/blink/renderer/platform/testing/find_cc_layer.h"
#include "third_party/blink/renderer/platform/testing/paint_property_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
@@ -22,23 +23,6 @@ class PaintLayerPainterTest : public PaintControllerPaintTest {
USING_FAST_MALLOC(PaintLayerPainterTest);
public:
- void ExpectPaintedOutputInvisibleAndPaintsWithTransparency(
- const char* element_name,
- bool expected_invisible,
- bool expected_paints_with_transparency) {
- // The optimization to skip painting for effectively-invisible content is
- // limited to pre-CAP.
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- return;
-
- PaintLayer* target_layer = GetPaintLayerByElementId(element_name);
- bool invisible = PaintLayerPainter::PaintedOutputInvisible(
- target_layer->GetLayoutObject().StyleRef());
- EXPECT_EQ(expected_invisible, invisible);
- EXPECT_EQ(expected_paints_with_transparency,
- target_layer->PaintsWithTransparency(kGlobalPaintNormalPhase));
- }
-
PaintController& MainGraphicsLayerPaintController() {
return GetLayoutView()
.Layer()
@@ -82,8 +66,10 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceAndChunksWithBackgrounds) {
auto* filler2 = GetLayoutObjectByElementId("filler2");
auto* container1_layer = To<LayoutBoxModelObject>(container1)->Layer();
+ auto* content1_layer = To<LayoutBoxModelObject>(content1)->Layer();
auto* filler1_layer = To<LayoutBoxModelObject>(filler1)->Layer();
auto* container2_layer = To<LayoutBoxModelObject>(container2)->Layer();
+ auto* content2_layer = To<LayoutBoxModelObject>(content2)->Layer();
auto* filler2_layer = To<LayoutBoxModelObject>(filler2)->Layer();
auto chunk_state = GetLayoutView().FirstFragment().ContentsProperties();
@@ -106,27 +92,36 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceAndChunksWithBackgrounds) {
// Check that new paint chunks were forced for the layers.
auto chunks = ContentPaintChunks();
- EXPECT_SUBSEQUENCE_FROM_CHUNK(*container1_layer, chunks.begin() + 1, 1);
- EXPECT_SUBSEQUENCE_FROM_CHUNK(*filler1_layer, chunks.begin() + 2, 1);
- EXPECT_SUBSEQUENCE_FROM_CHUNK(*container2_layer, chunks.begin() + 3, 1);
- EXPECT_SUBSEQUENCE_FROM_CHUNK(*filler2_layer, chunks.begin() + 4, 1);
+ auto chunk_it = chunks.begin();
+ EXPECT_SUBSEQUENCE_FROM_CHUNK(*container1_layer, chunk_it + 1, 2);
+ EXPECT_SUBSEQUENCE_FROM_CHUNK(*content1_layer, chunk_it + 2, 1);
+ EXPECT_SUBSEQUENCE_FROM_CHUNK(*filler1_layer, chunk_it + 3, 1);
+ EXPECT_SUBSEQUENCE_FROM_CHUNK(*container2_layer, chunk_it + 4, 2);
+ EXPECT_SUBSEQUENCE_FROM_CHUNK(*content2_layer, chunk_it + 5, 1);
+ EXPECT_SUBSEQUENCE_FROM_CHUNK(*filler2_layer, chunk_it + 6, 1);
EXPECT_THAT(
chunks,
ElementsAre(
VIEW_SCROLLING_BACKGROUND_CHUNK_COMMON,
IsPaintChunk(
- 1, 3,
+ 1, 2,
PaintChunk::Id(*container1_layer, DisplayItem::kLayerChunk),
chunk_state, nullptr, IntRect(0, 0, 200, 200)),
IsPaintChunk(
+ 2, 3, PaintChunk::Id(*content1_layer, DisplayItem::kLayerChunk),
+ chunk_state, nullptr, IntRect(0, 0, 100, 100)),
+ IsPaintChunk(
3, 4, PaintChunk::Id(*filler1_layer, DisplayItem::kLayerChunk),
chunk_state, nullptr, IntRect(0, 200, 20, 20)),
IsPaintChunk(
- 4, 6,
+ 4, 5,
PaintChunk::Id(*container2_layer, DisplayItem::kLayerChunk),
chunk_state, nullptr, IntRect(0, 220, 200, 200)),
IsPaintChunk(
+ 5, 6, PaintChunk::Id(*content2_layer, DisplayItem::kLayerChunk),
+ chunk_state, nullptr, IntRect(0, 220, 100, 100)),
+ IsPaintChunk(
6, 7, PaintChunk::Id(*filler2_layer, DisplayItem::kLayerChunk),
chunk_state, nullptr, IntRect(0, 420, 20, 20))));
};
@@ -137,10 +132,10 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceAndChunksWithBackgrounds) {
->setAttribute(html_names::kStyleAttr,
"position: absolute; width: 100px; height: 100px; "
"background-color: green");
- CachedItemAndSubsequenceCounter counter;
+ PaintController::CounterForTesting counter;
UpdateAllLifecyclePhasesForTest();
- EXPECT_EQ(6u, counter.NumNewCachedItems());
- EXPECT_EQ(3u, counter.NumNewCachedSubsequences());
+ EXPECT_EQ(6u, counter.num_cached_items);
+ EXPECT_EQ(4u, counter.num_cached_subsequences);
// We should still have the paint chunks forced by the cached subsequences.
check_results();
@@ -181,9 +176,10 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceAndChunksWithoutBackgrounds) {
auto* filler_layer = To<LayoutBoxModelObject>(filler)->Layer();
auto chunks = ContentPaintChunks();
- EXPECT_SUBSEQUENCE_FROM_CHUNK(*container_layer, chunks.begin() + 1, 4);
- EXPECT_SUBSEQUENCE_FROM_CHUNK(*content_layer, chunks.begin() + 3, 1);
- EXPECT_SUBSEQUENCE_FROM_CHUNK(*filler_layer, chunks.begin() + 4, 1);
+ EXPECT_SUBSEQUENCE_FROM_CHUNK(*container_layer, chunks.begin() + 1, 5);
+ EXPECT_SUBSEQUENCE_FROM_CHUNK(*content_layer, chunks.begin() + 3, 2);
+ EXPECT_SUBSEQUENCE_FROM_CHUNK(*inner_content_layer, chunks.begin() + 4, 1);
+ EXPECT_SUBSEQUENCE_FROM_CHUNK(*filler_layer, chunks.begin() + 5, 1);
auto container_properties =
container->FirstFragment().LocalBorderBoxProperties();
@@ -207,6 +203,10 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceAndChunksWithoutBackgrounds) {
PaintChunk::Id(*content_layer, DisplayItem::kLayerChunk),
content_properties, nullptr, IntRect(0, 0, 200, 100)),
IsPaintChunk(
+ 1, 1,
+ PaintChunk::Id(*inner_content_layer, DisplayItem::kLayerChunk),
+ content_properties, nullptr, IntRect(0, 0, 100, 100)),
+ IsPaintChunk(
1, 1, PaintChunk::Id(*filler_layer, DisplayItem::kLayerChunk),
content_properties, nullptr, IntRect(0, 100, 300, 300))));
@@ -214,8 +214,12 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceAndChunksWithoutBackgrounds) {
->setAttribute(html_names::kStyleAttr,
"position: absolute; width: 100px; height: 100px; "
"top: 100px; background-color: green");
+ PaintController::CounterForTesting counter;
UpdateAllLifecyclePhasesForTest();
+ EXPECT_EQ(1u, counter.num_cached_items); // view background.
+ EXPECT_EQ(1u, counter.num_cached_subsequences); // filler layer.
+
EXPECT_THAT(
ContentDisplayItems(),
ElementsAre(VIEW_SCROLLING_BACKGROUND_DISPLAY_ITEM,
@@ -225,6 +229,7 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceAndChunksWithoutBackgrounds) {
chunks = ContentPaintChunks();
EXPECT_SUBSEQUENCE_FROM_CHUNK(*container_layer, chunks.begin() + 1, 5);
EXPECT_SUBSEQUENCE_FROM_CHUNK(*content_layer, chunks.begin() + 3, 2);
+ EXPECT_SUBSEQUENCE_FROM_CHUNK(*inner_content_layer, chunks.begin() + 4, 1);
EXPECT_SUBSEQUENCE_FROM_CHUNK(*filler_layer, chunks.begin() + 5, 1);
EXPECT_THAT(
@@ -250,12 +255,6 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceAndChunksWithoutBackgrounds) {
}
TEST_P(PaintLayerPainterTest, CachedSubsequenceOnCullRectChange) {
- // This test doesn't work in CompositeAfterPaint mode because we always paint
- // from the local root frame view, and we always expand cull rect for
- // scrolling.
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<div id='container1' style='position: relative; z-index: 1;
width: 200px; height: 200px; background-color: blue'>
@@ -310,15 +309,15 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceOnCullRectChange) {
IsSameId(&content3, kBackgroundType)));
UpdateAllLifecyclePhasesExceptPaint();
- CachedItemAndSubsequenceCounter counter;
+ PaintController::CounterForTesting counter;
PaintContents(IntRect(0, 100, 300, 1000));
// Container1 becomes partly in the interest rect, but uses cached subsequence
// because it was fully painted before;
// Container2's intersection with the interest rect changes;
// Content2b is out of the interest rect and outputs nothing;
// Container3 becomes out of the interest rect and outputs nothing.
- EXPECT_EQ(5u, counter.NumNewCachedItems());
- EXPECT_EQ(1u, counter.NumNewCachedSubsequences());
+ EXPECT_EQ(5u, counter.num_cached_items);
+ EXPECT_EQ(2u, counter.num_cached_subsequences);
EXPECT_THAT(ContentDisplayItems(),
ElementsAre(VIEW_SCROLLING_BACKGROUND_DISPLAY_ITEM,
@@ -356,12 +355,12 @@ TEST_P(PaintLayerPainterTest,
SetBodyInnerHTML(R"HTML(
<div id='container1' style='position: relative; z-index: 1;
width: 200px; height: 200px; background-color: blue'>
- <div id='content1' style='position: absolute; width: 100px;
+ <div id='content1' style='overflow: hidden; width: 100px;
height: 100px; background-color: red'></div>
</div>
<div id='container2' style='position: relative; z-index: 1;
width: 200px; height: 200px; background-color: blue'>
- <div id='content2' style='position: absolute; width: 100px;
+ <div id='content2' style='overflow: hidden; width: 100px;
height: 100px; background-color: green'></div>
</div>
)HTML");
@@ -390,10 +389,9 @@ TEST_P(PaintLayerPainterTest,
"position: absolute; width: 100px; height: 100px; "
"background-color: green");
UpdateAllLifecyclePhasesExceptPaint();
- CachedItemAndSubsequenceCounter counter;
+ PaintController::CounterForTesting counter;
PaintContents(IntRect(0, 0, 50, 300));
- EXPECT_EQ(4u, counter.NumNewCachedItems());
- EXPECT_EQ(1u, counter.NumNewCachedSubsequences());
+ EXPECT_EQ(4u, counter.num_cached_items);
EXPECT_THAT(ContentDisplayItems(),
ElementsAre(VIEW_SCROLLING_BACKGROUND_DISPLAY_ITEM,
@@ -450,10 +448,10 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceRetainsPreviousPaintResult) {
"display: block");
UpdateAllLifecyclePhasesExceptPaint();
EXPECT_FALSE(target_layer->SelfNeedsRepaint());
- CachedItemAndSubsequenceCounter counter;
+ PaintController::CounterForTesting counter;
UpdateAllLifecyclePhasesForTest();
- EXPECT_EQ(2u, counter.NumNewCachedItems());
- EXPECT_EQ(1u, counter.NumNewCachedSubsequences());
+ EXPECT_EQ(2u, counter.num_cached_items);
+ EXPECT_EQ(1u, counter.num_cached_subsequences);
// |target| is still partially painted.
EXPECT_EQ(kMayBeClippedByCullRect, target_layer->PreviousPaintResult());
@@ -494,8 +492,8 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceRetainsPreviousPaintResult) {
counter.Reset();
UpdateAllLifecyclePhasesForTest();
- EXPECT_EQ(2u, counter.NumNewCachedItems());
- EXPECT_EQ(0u, counter.NumNewCachedSubsequences());
+ EXPECT_EQ(2u, counter.num_cached_items);
+ EXPECT_EQ(0u, counter.num_cached_subsequences);
// |target| is still partially painted.
EXPECT_EQ(kMayBeClippedByCullRect, target_layer->PreviousPaintResult());
@@ -527,12 +525,13 @@ TEST_P(PaintLayerPainterTest, HintedPaintChunksWithBackgrounds) {
div { background: blue }
</style>
<div id='container1' style='position: relative; height: 150px; z-index: 1'>
- <div id='content1a' style='position: relative; height: 100px'></div>
- <div id='content1b' style='position: relative; height: 100px'></div>
+ <div id='content1a' style='overflow: hidden; height: 100px'></div>
+ <div id='content1b' style='overflow: hidden; height: 100px'></div>
</div>
<div id='container2' style='position: relative; z-index: 1'>
- <div id='content2a' style='position: relative; height: 100px'></div>
- <div id='content2b' style='position: relative; z-index: -1; height: 100px'></div>
+ <div id='content2a' style='overflow: hidden; height: 100px'></div>
+ <div id='content2b'
+ style='position: relative; z-index: -1; height: 100px'></div>
</div>
)HTML");
@@ -559,14 +558,9 @@ TEST_P(PaintLayerPainterTest, HintedPaintChunksWithBackgrounds) {
VIEW_SCROLLING_BACKGROUND_CHUNK_COMMON,
// Includes |container1| and |content1a|.
IsPaintChunk(
- 1, 3,
+ 1, 4,
PaintChunk::Id(*container1->Layer(), DisplayItem::kLayerChunk),
- chunk_state, nullptr, IntRect(0, 0, 800, 150)),
- // Includes |content1b| which overflows |container1|.
- IsPaintChunk(
- 3, 4,
- PaintChunk::Id(*content1b->Layer(), DisplayItem::kLayerChunk),
- chunk_state, nullptr, IntRect(0, 100, 800, 100)),
+ chunk_state, nullptr, IntRect(0, 0, 800, 200)),
IsPaintChunk(
4, 5,
PaintChunk::Id(*container2->Layer(), DisplayItem::kLayerChunk),
@@ -575,10 +569,10 @@ TEST_P(PaintLayerPainterTest, HintedPaintChunksWithBackgrounds) {
5, 6,
PaintChunk::Id(*content2b->Layer(), DisplayItem::kLayerChunk),
chunk_state, nullptr, IntRect(0, 250, 800, 100)),
- IsPaintChunk(
- 6, 7,
- PaintChunk::Id(*content2a->Layer(), DisplayItem::kLayerChunk),
- chunk_state, nullptr, IntRect(0, 150, 800, 100))));
+ IsPaintChunk(6, 7,
+ PaintChunk::Id(*container2->Layer(),
+ DisplayItem::kLayerChunkForeground),
+ chunk_state, nullptr, IntRect(0, 150, 800, 100))));
}
TEST_P(PaintLayerPainterTest, HintedPaintChunksWithoutBackgrounds) {
@@ -588,20 +582,18 @@ TEST_P(PaintLayerPainterTest, HintedPaintChunksWithoutBackgrounds) {
SetBodyInnerHTML(R"HTML(
<style>body { margin: 0 }</style>
<div id='container1' style='position: relative; height: 150px; z-index: 1'>
- <div id='content1a' style='position: relative; height: 100px'></div>
- <div id='content1b' style='position: relative; height: 100px'></div>
+ <div id='content1a' style='overflow: hidden; height: 100px'></div>
+ <div id='content1b' style='overflow: hidden; height: 100px'></div>
</div>
<div id='container2' style='position: relative; z-index: 1'>
- <div id='content2a' style='position: relative; height: 100px'></div>
+ <div id='content2a' style='overflow: hidden; height: 100px'></div>
<div id='content2b'
style='position: relative; z-index: -1; height: 100px'></div>
</div>
)HTML");
auto* container1 = GetLayoutBoxByElementId("container1");
- auto* content1b = GetLayoutBoxByElementId("content1b");
auto* container2 = GetLayoutBoxByElementId("container2");
- auto* content2a = GetLayoutBoxByElementId("content2a");
auto* content2b = GetLayoutBoxByElementId("content2b");
auto chunk_state = GetLayoutView().FirstFragment().ContentsProperties();
@@ -615,11 +607,7 @@ TEST_P(PaintLayerPainterTest, HintedPaintChunksWithoutBackgrounds) {
IsPaintChunk(
1, 1,
PaintChunk::Id(*container1->Layer(), DisplayItem::kLayerChunk),
- chunk_state, nullptr, IntRect(0, 0, 800, 150)),
- IsPaintChunk(
- 1, 1,
- PaintChunk::Id(*content1b->Layer(), DisplayItem::kLayerChunk),
- chunk_state, nullptr, IntRect(0, 100, 800, 100)),
+ chunk_state, nullptr, IntRect(0, 0, 800, 200)),
IsPaintChunk(
1, 1,
PaintChunk::Id(*container2->Layer(), DisplayItem::kLayerChunk),
@@ -628,10 +616,10 @@ TEST_P(PaintLayerPainterTest, HintedPaintChunksWithoutBackgrounds) {
1, 1,
PaintChunk::Id(*content2b->Layer(), DisplayItem::kLayerChunk),
chunk_state, nullptr, IntRect(0, 250, 800, 100)),
- IsPaintChunk(
- 1, 1,
- PaintChunk::Id(*content2a->Layer(), DisplayItem::kLayerChunk),
- chunk_state, nullptr, IntRect(0, 150, 800, 100))));
+ IsPaintChunk(1, 1,
+ PaintChunk::Id(*container2->Layer(),
+ DisplayItem::kLayerChunkForeground),
+ chunk_state, nullptr, IntRect(0, 150, 800, 100))));
}
TEST_P(PaintLayerPainterTest, PaintPhaseOutline) {
@@ -891,149 +879,6 @@ TEST_P(PaintLayerPainterTest, PaintPhasesUpdateOnBecomingNonSelfPainting) {
EXPECT_TRUE(html_layer.NeedsPaintPhaseDescendantOutlines());
}
-TEST_P(PaintLayerPainterTest, DontPaintWithTinyOpacity) {
- SetBodyInnerHTML(
- "<div id='target' style='background: blue; opacity: 0.0001'></div>");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", true, true);
-}
-
-TEST_P(PaintLayerPainterTest, DoPaintWithTinyOpacityAndWillChangeOpacity) {
- SetBodyInnerHTML(
- "<div id='target' style='background: blue; opacity: 0.0001; "
- " will-change: opacity'></div>");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", false, false);
-}
-
-TEST_P(PaintLayerPainterTest, DoPaintWithTinyOpacityAndBackdropFilter) {
- SetBodyInnerHTML(
- "<div id='target' style='background: blue; opacity: 0.0001;"
- " backdrop-filter: blur(2px);'></div>");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", false, false);
-}
-
-TEST_P(PaintLayerPainterTest,
- DoPaintWithTinyOpacityAndBackdropFilterAndWillChangeOpacity) {
- SetBodyInnerHTML(
- "<div id='target' style='background: blue; opacity: 0.0001;"
- " backdrop-filter: blur(2px); will-change: opacity'></div>");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", false, false);
-}
-
-TEST_P(PaintLayerPainterTest, DoPaintWithCompositedTinyOpacity) {
- SetBodyInnerHTML(
- "<div id='target' style='background: blue; opacity: 0.0001;"
- " will-change: transform'></div>");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", true, false);
-}
-
-TEST_P(PaintLayerPainterTest, DoPaintWithNonTinyOpacity) {
- SetBodyInnerHTML(
- "<div id='target' style='background: blue; opacity: 0.1'></div>");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", false, true);
-}
-
-TEST_P(PaintLayerPainterTest, DoPaintWithEffectAnimationZeroOpacity) {
- SetBodyInnerHTML(R"HTML(
- <style>
- div {
- width: 100px;
- height: 100px;
- animation-name: example;
- animation-duration: 4s;
- }
- @keyframes example {
- from { opacity: 0.0;}
- to { opacity: 1.0;}
- }
- </style>
- <div id='target'></div>
- )HTML");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", true, false);
-}
-
-TEST_P(PaintLayerPainterTest, DoPaintWithTransformAnimationZeroOpacity) {
- SetBodyInnerHTML(R"HTML(
- <style>
- div#target {
- animation-name: example;
- animation-duration: 4s;
- opacity: 0.0;
- }
- @keyframes example {
- from { transform: translate(0px, 0px); }
- to { transform: translate(3em, 0px); }
- }
- </style>
- <div id='target'>x</div></div>
- )HTML");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", true, false);
-}
-
-TEST_P(PaintLayerPainterTest,
- DoPaintWithTransformAnimationZeroOpacityWillChangeOpacity) {
- SetBodyInnerHTML(R"HTML(
- <style>
- div#target {
- animation-name: example;
- animation-duration: 4s;
- opacity: 0.0;
- will-change: opacity;
- }
- @keyframes example {
- from { transform: translate(0px, 0px); }
- to { transform: translate(3em, 0px); }
- }
- </style>
- <div id='target'>x</div></div>
- )HTML");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", false, false);
-}
-
-TEST_P(PaintLayerPainterTest, DoPaintWithWillChangeOpacity) {
- SetBodyInnerHTML(R"HTML(
- <style>
- div {
- width: 100px;
- height: 100px;
- will-change: opacity;
- }
- </style>
- <div id='target'></div>
- )HTML");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", false, false);
-}
-
-TEST_P(PaintLayerPainterTest, DoPaintWithZeroOpacityAndWillChangeOpacity) {
- SetBodyInnerHTML(R"HTML(
- <style>
- div {
- width: 100px;
- height: 100px;
- opacity: 0;
- will-change: opacity;
- }
- </style>
- <div id='target'></div>
- )HTML");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", false, false);
-}
-
-TEST_P(PaintLayerPainterTest,
- DoPaintWithNoContentAndZeroOpacityAndWillChangeOpacity) {
- SetBodyInnerHTML(R"HTML(
- <style>
- div {
- width: 100px;
- height: 100px;
- opacity: 0;
- will-change: opacity;
- }
- </style>
- <div id='target'></div>
- )HTML");
- ExpectPaintedOutputInvisibleAndPaintsWithTransparency("target", false, false);
-}
-
using PaintLayerPainterTestCAP = PaintLayerPainterTest;
INSTANTIATE_CAP_TEST_SUITE_P(PaintLayerPainterTestCAP);
@@ -1214,6 +1059,33 @@ TEST_P(PaintLayerPainterTestCAP, ScaledAndRotatedCullRect) {
GetCullRect(*GetPaintLayerByElementId("target")).Rect());
}
+// This is a testcase for https://crbug.com/1227907 where repeated cull rect
+// updates are expensive on the motionmark microbenchmark.
+TEST_P(PaintLayerPainterTestCAP, OptimizeNonCompositedTransformUpdate) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #target {
+ width: 50px;
+ height: 50px;
+ background: green;
+ transform: translate(-8px, -8px);
+ }
+ </style>
+ <div id='target'></div>
+ )HTML");
+
+ // The cull rect should be correctly calculated on first paint.
+ EXPECT_EQ(IntRect(0, 0, 800, 600),
+ GetCullRect(*GetPaintLayerByElementId("target")).Rect());
+
+ // On subsequent paints, fall back to an infinite cull rect.
+ GetDocument().getElementById("target")->setAttribute(
+ html_names::kStyleAttr, "transform: rotate(10deg);");
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_EQ(CullRect::Infinite().Rect(),
+ GetCullRect(*GetPaintLayerByElementId("target")).Rect());
+}
+
TEST_P(PaintLayerPainterTestCAP, 3DRotated90DegreesCullRect) {
GetDocument().GetSettings()->SetPreferCompositingToLCDTextEnabled(true);
SetBodyInnerHTML(R"HTML(
@@ -1381,4 +1253,138 @@ TEST_P(PaintLayerPainterTestCAP, ClippedBigLayer) {
GetCullRect(*GetPaintLayerByElementId("target")).Rect());
}
+class PaintLayerPainterPaintedOutputInvisibleTest
+ : public PaintLayerPainterTest {
+ protected:
+ void RunTest() {
+ SetBodyInnerHTML(R"HTML(
+ <div id="parent">
+ <div id="target">
+ <div id="child"></div>
+ </div>
+ </div>
+ <style>
+ #parent {
+ width: 10px;
+ height: 10px;
+ will-change: transform;
+ }
+ #target {
+ width: 100px;
+ height: 100px;
+ opacity: 0.0001;
+ }
+ #child {
+ width: 200px;
+ height: 50px;
+ opacity: 0.9;
+ }
+ )HTML" + additional_style_ +
+ "</style>");
+
+ auto* parent = GetLayoutObjectByElementId("parent");
+ auto* parent_layer = To<LayoutBox>(parent)->Layer();
+ auto* target = GetLayoutObjectByElementId("target");
+ auto* target_layer = To<LayoutBox>(target)->Layer();
+ auto* child = GetLayoutObjectByElementId("child");
+ auto* child_layer = To<LayoutBox>(child)->Layer();
+
+ EXPECT_EQ(expected_invisible_,
+ PaintLayerPainter::PaintedOutputInvisible(
+ target_layer->GetLayoutObject().StyleRef()));
+
+ auto* cc_layer =
+ CcLayersByDOMElementId(GetDocument().View()->RootCcLayer(),
+ expected_composited_ ? "target" : "parent")[0];
+ ASSERT_TRUE(cc_layer);
+ EXPECT_EQ(gfx::Size(200, 100), cc_layer->bounds());
+
+ auto chunks = ContentPaintChunks();
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ EXPECT_THAT(
+ chunks,
+ ElementsAre(
+ VIEW_SCROLLING_BACKGROUND_CHUNK_COMMON,
+ IsPaintChunk(
+ 1, 1, PaintChunk::Id(*parent_layer, DisplayItem::kLayerChunk),
+ parent->FirstFragment().LocalBorderBoxProperties(), nullptr,
+ IntRect(0, 0, 10, 10)),
+ IsPaintChunk(
+ 1, 1, PaintChunk::Id(*target_layer, DisplayItem::kLayerChunk),
+ target->FirstFragment().LocalBorderBoxProperties(), nullptr,
+ IntRect(0, 0, 100, 100)),
+ IsPaintChunk(
+ 1, 1, PaintChunk::Id(*child_layer, DisplayItem::kLayerChunk),
+ child->FirstFragment().LocalBorderBoxProperties(), nullptr,
+ IntRect(0, 0, 200, 50))));
+ EXPECT_FALSE((chunks.begin() + 1)->effectively_invisible);
+ EXPECT_EQ(expected_invisible_,
+ (chunks.begin() + 2)->effectively_invisible);
+ EXPECT_EQ(expected_invisible_,
+ (chunks.begin() + 3)->effectively_invisible);
+ } else {
+ EXPECT_EQ(expected_paints_with_transparency_,
+ target_layer->PaintsWithTransparency(kGlobalPaintNormalPhase));
+ }
+ }
+
+ String additional_style_;
+ bool expected_composited_ = false;
+ bool expected_invisible_ = true;
+ bool expected_paints_with_transparency_ = true;
+};
+
+INSTANTIATE_PAINT_TEST_SUITE_P(PaintLayerPainterPaintedOutputInvisibleTest);
+
+TEST_P(PaintLayerPainterPaintedOutputInvisibleTest, TinyOpacity) {
+ expected_composited_ = false;
+ expected_invisible_ = true;
+ expected_paints_with_transparency_ = true;
+ RunTest();
+}
+
+TEST_P(PaintLayerPainterPaintedOutputInvisibleTest,
+ TinyOpacityAndWillChangeOpacity) {
+ additional_style_ = "#target { will-change: opacity; }";
+ expected_composited_ = true;
+ expected_invisible_ = false;
+ expected_paints_with_transparency_ = false;
+ RunTest();
+}
+
+TEST_P(PaintLayerPainterPaintedOutputInvisibleTest,
+ TinyOpacityAndBackdropFilter) {
+ additional_style_ = "#target { backdrop-filter: blur(2px); }";
+ expected_composited_ = true;
+ expected_invisible_ = false;
+ expected_paints_with_transparency_ = false;
+ RunTest();
+}
+
+TEST_P(PaintLayerPainterPaintedOutputInvisibleTest,
+ TinyOpacityAndWillChangeTransform) {
+ additional_style_ = "#target { will-change: transform; }";
+ expected_composited_ = true;
+ expected_invisible_ = true;
+ expected_paints_with_transparency_ = false;
+ RunTest();
+}
+
+TEST_P(PaintLayerPainterPaintedOutputInvisibleTest, NonTinyOpacity) {
+ additional_style_ = "#target { opacity: 0.5; }";
+ expected_composited_ = false;
+ expected_invisible_ = false;
+ expected_paints_with_transparency_ = true;
+ RunTest();
+}
+
+TEST_P(PaintLayerPainterPaintedOutputInvisibleTest,
+ NonTinyOpacityAndWillChangeOpacity) {
+ additional_style_ = "#target { opacity: 1; will-change: opacity; }";
+ expected_composited_ = true;
+ expected_invisible_ = false;
+ expected_paints_with_transparency_ = false;
+ RunTest();
+}
+
} // namespace blink