OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/paint/PaintLayer.h" | 5 #include "core/paint/PaintLayer.h" |
6 | 6 |
7 #include "core/layout/LayoutBoxModelObject.h" | 7 #include "core/layout/LayoutBoxModelObject.h" |
8 #include "core/layout/LayoutTestHelper.h" | 8 #include "core/layout/LayoutTestHelper.h" |
9 #include "core/layout/LayoutView.h" | 9 #include "core/layout/LayoutView.h" |
| 10 #include "platform/testing/RuntimeEnabledFeaturesTestHelpers.h" |
10 | 11 |
11 namespace blink { | 12 namespace blink { |
12 | 13 |
13 using PaintLayerTest = RenderingTest; | 14 typedef std::pair<bool, bool> SlimmingPaintAndRootLayerScrolling; |
| 15 class PaintLayerTest |
| 16 : public ::testing::WithParamInterface<SlimmingPaintAndRootLayerScrolling>, |
| 17 private ScopedSlimmingPaintV2ForTest, |
| 18 private ScopedRootLayerScrollingForTest, |
| 19 public RenderingTest { |
| 20 public: |
| 21 PaintLayerTest() |
| 22 : ScopedSlimmingPaintV2ForTest(GetParam().first), |
| 23 ScopedRootLayerScrollingForTest(GetParam().second), |
| 24 RenderingTest(SingleChildFrameLoaderClient::create()) {} |
| 25 }; |
14 | 26 |
15 TEST_F(PaintLayerTest, CompositedBoundsAbsPosGrandchild) { | 27 SlimmingPaintAndRootLayerScrolling foo[] = { |
| 28 SlimmingPaintAndRootLayerScrolling(false, false), |
| 29 SlimmingPaintAndRootLayerScrolling(true, false), |
| 30 SlimmingPaintAndRootLayerScrolling(false, true), |
| 31 SlimmingPaintAndRootLayerScrolling(true, true)}; |
| 32 |
| 33 INSTANTIATE_TEST_CASE_P(All, PaintLayerTest, ::testing::ValuesIn(foo)); |
| 34 |
| 35 TEST_P(PaintLayerTest, CompositedBoundsAbsPosGrandchild) { |
| 36 // TODO(chrishtr): fix this test for SPv2 |
| 37 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
| 38 return; |
| 39 |
16 setBodyInnerHTML( | 40 setBodyInnerHTML( |
17 " <div id='parent'><div id='absposparent'><div id='absposchild'>" | 41 " <div id='parent'><div id='absposparent'><div id='absposchild'>" |
18 " </div></div></div>" | 42 " </div></div></div>" |
19 "<style>" | 43 "<style>" |
20 " #parent { position: absolute; z-index: 0; overflow: hidden;" | 44 " #parent { position: absolute; z-index: 0; overflow: hidden;" |
21 " background: lightgray; width: 150px; height: 150px;" | 45 " background: lightgray; width: 150px; height: 150px;" |
22 " will-change: transform; }" | 46 " will-change: transform; }" |
23 " #absposparent { position: absolute; z-index: 0; }" | 47 " #absposparent { position: absolute; z-index: 0; }" |
24 " #absposchild { position: absolute; top: 0px; left: 0px; height: 200px;" | 48 " #absposchild { position: absolute; top: 0px; left: 0px; height: 200px;" |
25 " width: 200px; background: lightblue; }</style>"); | 49 " width: 200px; background: lightblue; }</style>"); |
26 | 50 |
27 PaintLayer* parentLayer = | 51 PaintLayer* parentLayer = |
28 toLayoutBoxModelObject(getLayoutObjectByElementId("parent"))->layer(); | 52 toLayoutBoxModelObject(getLayoutObjectByElementId("parent"))->layer(); |
29 // Since "absposchild" is clipped by "parent", it should not expand the | 53 // Since "absposchild" is clipped by "parent", it should not expand the |
30 // composited bounds for "parent" beyond its intrinsic size of 150x150. | 54 // composited bounds for "parent" beyond its intrinsic size of 150x150. |
31 EXPECT_EQ(LayoutRect(0, 0, 150, 150), | 55 EXPECT_EQ(LayoutRect(0, 0, 150, 150), |
32 parentLayer->boundingBoxForCompositing()); | 56 parentLayer->boundingBoxForCompositing()); |
33 } | 57 } |
34 | 58 |
35 TEST_F(PaintLayerTest, PaintingExtentReflection) { | 59 TEST_P(PaintLayerTest, PaintingExtentReflection) { |
36 setBodyInnerHTML( | 60 setBodyInnerHTML( |
37 "<div id='target' style='background-color: blue; position: absolute;" | 61 "<div id='target' style='background-color: blue; position: absolute;" |
38 " width: 110px; height: 120px; top: 40px; left: 60px;" | 62 " width: 110px; height: 120px; top: 40px; left: 60px;" |
39 " -webkit-box-reflect: below 3px'>" | 63 " -webkit-box-reflect: below 3px'>" |
40 "</div>"); | 64 "</div>"); |
41 | 65 |
42 PaintLayer* layer = | 66 PaintLayer* layer = |
43 toLayoutBoxModelObject(getLayoutObjectByElementId("target"))->layer(); | 67 toLayoutBoxModelObject(getLayoutObjectByElementId("target"))->layer(); |
44 EXPECT_EQ( | 68 EXPECT_EQ( |
45 LayoutRect(60, 40, 110, 243), | 69 LayoutRect(60, 40, 110, 243), |
46 layer->paintingExtent(document().layoutView()->layer(), LayoutSize(), 0)); | 70 layer->paintingExtent(document().layoutView()->layer(), LayoutSize(), 0)); |
47 } | 71 } |
48 | 72 |
49 TEST_F(PaintLayerTest, PaintingExtentReflectionWithTransform) { | 73 TEST_P(PaintLayerTest, PaintingExtentReflectionWithTransform) { |
50 setBodyInnerHTML( | 74 setBodyInnerHTML( |
51 "<div id='target' style='background-color: blue; position: absolute;" | 75 "<div id='target' style='background-color: blue; position: absolute;" |
52 " width: 110px; height: 120px; top: 40px; left: 60px;" | 76 " width: 110px; height: 120px; top: 40px; left: 60px;" |
53 " -webkit-box-reflect: below 3px; transform: translateX(30px)'>" | 77 " -webkit-box-reflect: below 3px; transform: translateX(30px)'>" |
54 "</div>"); | 78 "</div>"); |
55 | 79 |
56 PaintLayer* layer = | 80 PaintLayer* layer = |
57 toLayoutBoxModelObject(getLayoutObjectByElementId("target"))->layer(); | 81 toLayoutBoxModelObject(getLayoutObjectByElementId("target"))->layer(); |
58 EXPECT_EQ( | 82 EXPECT_EQ( |
59 LayoutRect(90, 40, 110, 243), | 83 LayoutRect(90, 40, 110, 243), |
60 layer->paintingExtent(document().layoutView()->layer(), LayoutSize(), 0)); | 84 layer->paintingExtent(document().layoutView()->layer(), LayoutSize(), 0)); |
61 } | 85 } |
62 | 86 |
63 TEST_F(PaintLayerTest, CompositedScrollingNoNeedsRepaint) { | 87 TEST_P(PaintLayerTest, ScrollsWithViewportRelativePosition) { |
| 88 setBodyInnerHTML("<div id='target' style='position: relative'></div>"); |
| 89 |
| 90 PaintLayer* layer = |
| 91 toLayoutBoxModelObject(getLayoutObjectByElementId("target"))->layer(); |
| 92 EXPECT_FALSE(layer->sticksToViewport()); |
| 93 } |
| 94 |
| 95 TEST_P(PaintLayerTest, ScrollsWithViewportFixedPosition) { |
| 96 setBodyInnerHTML("<div id='target' style='position: fixed'></div>"); |
| 97 |
| 98 PaintLayer* layer = |
| 99 toLayoutBoxModelObject(getLayoutObjectByElementId("target"))->layer(); |
| 100 EXPECT_TRUE(layer->sticksToViewport()); |
| 101 } |
| 102 |
| 103 TEST_P(PaintLayerTest, ScrollsWithViewportFixedPositionInsideTransform) { |
| 104 // We don't intend to launch SPv2 without root layer scrolling, so skip this |
| 105 // test in that configuration because it's broken. |
| 106 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && |
| 107 !RuntimeEnabledFeatures::rootLayerScrollingEnabled()) |
| 108 return; |
| 109 setBodyInnerHTML( |
| 110 "<div style='transform: translateZ(0)'>" |
| 111 " <div id='target' style='position: fixed'></div>" |
| 112 "</div>" |
| 113 "<div style='width: 10px; height: 1000px'></div>"); |
| 114 PaintLayer* layer = |
| 115 toLayoutBoxModelObject(getLayoutObjectByElementId("target"))->layer(); |
| 116 EXPECT_FALSE(layer->sticksToViewport()); |
| 117 } |
| 118 |
| 119 TEST_P(PaintLayerTest, |
| 120 ScrollsWithViewportFixedPositionInsideTransformNoScroll) { |
| 121 setBodyInnerHTML( |
| 122 "<div style='transform: translateZ(0)'>" |
| 123 " <div id='target' style='position: fixed'></div>" |
| 124 "</div>"); |
| 125 PaintLayer* layer = |
| 126 toLayoutBoxModelObject(getLayoutObjectByElementId("target"))->layer(); |
| 127 |
| 128 // In SPv2 mode, we correctly determine that the frame doesn't scroll at all, |
| 129 // and so return true. |
| 130 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
| 131 EXPECT_TRUE(layer->sticksToViewport()); |
| 132 else |
| 133 EXPECT_FALSE(layer->sticksToViewport()); |
| 134 } |
| 135 |
| 136 TEST_P(PaintLayerTest, ScrollsWithViewportStickyPosition) { |
| 137 setBodyInnerHTML( |
| 138 "<div style='transform: translateZ(0)'>" |
| 139 " <div id='target' style='position: sticky'></div>" |
| 140 "</div>"); |
| 141 |
| 142 PaintLayer* layer = |
| 143 toLayoutBoxModelObject(getLayoutObjectByElementId("target"))->layer(); |
| 144 EXPECT_TRUE(layer->sticksToViewport()); |
| 145 } |
| 146 |
| 147 TEST_P(PaintLayerTest, ScrollsWithViewportStickyPositionInsideScroller) { |
| 148 setBodyInnerHTML( |
| 149 "<div style='overflow:scroll; width: 100px; height: 100px;'>" |
| 150 " <div id='target' style='position: sticky'></div>" |
| 151 " <div style='width: 50px; height: 1000px;'></div>" |
| 152 "</div>"); |
| 153 |
| 154 PaintLayer* layer = |
| 155 toLayoutBoxModelObject(getLayoutObjectByElementId("target"))->layer(); |
| 156 EXPECT_FALSE(layer->sticksToViewport()); |
| 157 } |
| 158 |
| 159 TEST_P(PaintLayerTest, CompositedScrollingNoNeedsRepaint) { |
| 160 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
| 161 return; |
| 162 |
64 enableCompositing(); | 163 enableCompositing(); |
65 setBodyInnerHTML( | 164 setBodyInnerHTML( |
66 "<div id='scroll' style='width: 100px; height: 100px; overflow: scroll;" | 165 "<div id='scroll' style='width: 100px; height: 100px; overflow: scroll;" |
67 " will-change: transform'>" | 166 " will-change: transform'>" |
68 " <div id='content' style='position: relative; background: blue;" | 167 " <div id='content' style='position: relative; background: blue;" |
69 " width: 2000px; height: 2000px'></div>" | 168 " width: 2000px; height: 2000px'></div>" |
70 "</div>"); | 169 "</div>"); |
71 | 170 |
72 PaintLayer* scrollLayer = | 171 PaintLayer* scrollLayer = |
73 toLayoutBoxModelObject(getLayoutObjectByElementId("scroll"))->layer(); | 172 toLayoutBoxModelObject(getLayoutObjectByElementId("scroll"))->layer(); |
74 EXPECT_EQ(PaintsIntoOwnBacking, scrollLayer->compositingState()); | 173 EXPECT_EQ(PaintsIntoOwnBacking, scrollLayer->compositingState()); |
75 | 174 |
76 PaintLayer* contentLayer = | 175 PaintLayer* contentLayer = |
77 toLayoutBoxModelObject(getLayoutObjectByElementId("content"))->layer(); | 176 toLayoutBoxModelObject(getLayoutObjectByElementId("content"))->layer(); |
78 EXPECT_EQ(NotComposited, contentLayer->compositingState()); | 177 EXPECT_EQ(NotComposited, contentLayer->compositingState()); |
79 EXPECT_EQ(LayoutPoint(), contentLayer->location()); | 178 EXPECT_EQ(LayoutPoint(), contentLayer->location()); |
80 | 179 |
81 scrollLayer->getScrollableArea()->setScrollOffset(ScrollOffset(1000, 1000), | 180 scrollLayer->getScrollableArea()->setScrollOffset(ScrollOffset(1000, 1000), |
82 ProgrammaticScroll); | 181 ProgrammaticScroll); |
83 document().view()->updateAllLifecyclePhasesExceptPaint(); | 182 document().view()->updateAllLifecyclePhasesExceptPaint(); |
84 EXPECT_EQ(LayoutPoint(-1000, -1000), contentLayer->location()); | 183 EXPECT_EQ(LayoutPoint(-1000, -1000), contentLayer->location()); |
85 EXPECT_FALSE(contentLayer->needsRepaint()); | 184 EXPECT_FALSE(contentLayer->needsRepaint()); |
86 EXPECT_FALSE(scrollLayer->needsRepaint()); | 185 EXPECT_FALSE(scrollLayer->needsRepaint()); |
87 document().view()->updateAllLifecyclePhases(); | 186 document().view()->updateAllLifecyclePhases(); |
88 } | 187 } |
89 | 188 |
90 TEST_F(PaintLayerTest, NonCompositedScrollingNeedsRepaint) { | 189 TEST_P(PaintLayerTest, NonCompositedScrollingNeedsRepaint) { |
91 setBodyInnerHTML( | 190 setBodyInnerHTML( |
92 "<div id='scroll' style='width: 100px; height: 100px; overflow: scroll'>" | 191 "<div id='scroll' style='width: 100px; height: 100px; overflow: scroll'>" |
93 " <div id='content' style='position: relative; background: blue;" | 192 " <div id='content' style='position: relative; background: blue;" |
94 " width: 2000px; height: 2000px'></div>" | 193 " width: 2000px; height: 2000px'></div>" |
95 "</div>"); | 194 "</div>"); |
96 | 195 |
97 PaintLayer* scrollLayer = | 196 PaintLayer* scrollLayer = |
98 toLayoutBoxModelObject(getLayoutObjectByElementId("scroll"))->layer(); | 197 toLayoutBoxModelObject(getLayoutObjectByElementId("scroll"))->layer(); |
99 EXPECT_EQ(NotComposited, scrollLayer->compositingState()); | 198 EXPECT_EQ(NotComposited, scrollLayer->compositingState()); |
100 | 199 |
101 PaintLayer* contentLayer = | 200 PaintLayer* contentLayer = |
102 toLayoutBoxModelObject(getLayoutObjectByElementId("content"))->layer(); | 201 toLayoutBoxModelObject(getLayoutObjectByElementId("content"))->layer(); |
103 EXPECT_EQ(NotComposited, scrollLayer->compositingState()); | 202 EXPECT_EQ(NotComposited, scrollLayer->compositingState()); |
104 EXPECT_EQ(LayoutPoint(), contentLayer->location()); | 203 EXPECT_EQ(LayoutPoint(), contentLayer->location()); |
105 | 204 |
106 scrollLayer->getScrollableArea()->setScrollOffset(ScrollOffset(1000, 1000), | 205 scrollLayer->getScrollableArea()->setScrollOffset(ScrollOffset(1000, 1000), |
107 ProgrammaticScroll); | 206 ProgrammaticScroll); |
108 document().view()->updateAllLifecyclePhasesExceptPaint(); | 207 document().view()->updateAllLifecyclePhasesExceptPaint(); |
109 EXPECT_EQ(LayoutPoint(-1000, -1000), contentLayer->location()); | 208 EXPECT_EQ(LayoutPoint(-1000, -1000), contentLayer->location()); |
110 EXPECT_TRUE(contentLayer->needsRepaint()); | 209 EXPECT_TRUE(contentLayer->needsRepaint()); |
111 EXPECT_TRUE(scrollLayer->needsRepaint()); | 210 EXPECT_TRUE(scrollLayer->needsRepaint()); |
112 document().view()->updateAllLifecyclePhases(); | 211 document().view()->updateAllLifecyclePhases(); |
113 } | 212 } |
114 | 213 |
115 TEST_F(PaintLayerTest, HasNonIsolatedDescendantWithBlendMode) { | 214 TEST_P(PaintLayerTest, HasNonIsolatedDescendantWithBlendMode) { |
116 setBodyInnerHTML( | 215 setBodyInnerHTML( |
117 "<div id='stacking-grandparent' style='isolation: isolate'>" | 216 "<div id='stacking-grandparent' style='isolation: isolate'>" |
118 " <div id='stacking-parent' style='isolation: isolate'>" | 217 " <div id='stacking-parent' style='isolation: isolate'>" |
119 " <div id='non-stacking-parent' style='position:relative'>" | 218 " <div id='non-stacking-parent' style='position:relative'>" |
120 " <div id='blend-mode' style='mix-blend-mode: overlay'>" | 219 " <div id='blend-mode' style='mix-blend-mode: overlay'>" |
121 " </div>" | 220 " </div>" |
122 " </div>" | 221 " </div>" |
123 " </div>" | 222 " </div>" |
124 "</div>"); | 223 "</div>"); |
125 PaintLayer* stackingGrandparent = | 224 PaintLayer* stackingGrandparent = |
126 toLayoutBoxModelObject(getLayoutObjectByElementId("stacking-grandparent")) | 225 toLayoutBoxModelObject(getLayoutObjectByElementId("stacking-grandparent")) |
127 ->layer(); | 226 ->layer(); |
128 PaintLayer* stackingParent = | 227 PaintLayer* stackingParent = |
129 toLayoutBoxModelObject(getLayoutObjectByElementId("stacking-parent")) | 228 toLayoutBoxModelObject(getLayoutObjectByElementId("stacking-parent")) |
130 ->layer(); | 229 ->layer(); |
131 PaintLayer* parent = | 230 PaintLayer* parent = |
132 toLayoutBoxModelObject(getLayoutObjectByElementId("non-stacking-parent")) | 231 toLayoutBoxModelObject(getLayoutObjectByElementId("non-stacking-parent")) |
133 ->layer(); | 232 ->layer(); |
134 | 233 |
135 EXPECT_TRUE(parent->hasNonIsolatedDescendantWithBlendMode()); | 234 EXPECT_TRUE(parent->hasNonIsolatedDescendantWithBlendMode()); |
136 EXPECT_TRUE(stackingParent->hasNonIsolatedDescendantWithBlendMode()); | 235 EXPECT_TRUE(stackingParent->hasNonIsolatedDescendantWithBlendMode()); |
137 EXPECT_FALSE(stackingGrandparent->hasNonIsolatedDescendantWithBlendMode()); | 236 EXPECT_FALSE(stackingGrandparent->hasNonIsolatedDescendantWithBlendMode()); |
138 | 237 |
139 EXPECT_FALSE(parent->hasDescendantWithClipPath()); | 238 EXPECT_FALSE(parent->hasDescendantWithClipPath()); |
140 EXPECT_TRUE(parent->hasVisibleDescendant()); | 239 EXPECT_TRUE(parent->hasVisibleDescendant()); |
141 } | 240 } |
142 | 241 |
143 TEST_F(PaintLayerTest, HasDescendantWithClipPath) { | 242 TEST_P(PaintLayerTest, HasDescendantWithClipPath) { |
144 setBodyInnerHTML( | 243 setBodyInnerHTML( |
145 "<div id='parent' style='position:relative'>" | 244 "<div id='parent' style='position:relative'>" |
146 " <div id='clip-path' style='clip-path: circle(50px at 0 100px)'>" | 245 " <div id='clip-path' style='clip-path: circle(50px at 0 100px)'>" |
147 " </div>" | 246 " </div>" |
148 "</div>"); | 247 "</div>"); |
149 PaintLayer* parent = | 248 PaintLayer* parent = |
150 toLayoutBoxModelObject(getLayoutObjectByElementId("parent"))->layer(); | 249 toLayoutBoxModelObject(getLayoutObjectByElementId("parent"))->layer(); |
151 PaintLayer* clipPath = | 250 PaintLayer* clipPath = |
152 toLayoutBoxModelObject(getLayoutObjectByElementId("clip-path"))->layer(); | 251 toLayoutBoxModelObject(getLayoutObjectByElementId("clip-path"))->layer(); |
153 | 252 |
154 EXPECT_TRUE(parent->hasDescendantWithClipPath()); | 253 EXPECT_TRUE(parent->hasDescendantWithClipPath()); |
155 EXPECT_FALSE(clipPath->hasDescendantWithClipPath()); | 254 EXPECT_FALSE(clipPath->hasDescendantWithClipPath()); |
156 | 255 |
157 EXPECT_FALSE(parent->hasNonIsolatedDescendantWithBlendMode()); | 256 EXPECT_FALSE(parent->hasNonIsolatedDescendantWithBlendMode()); |
158 EXPECT_TRUE(parent->hasVisibleDescendant()); | 257 EXPECT_TRUE(parent->hasVisibleDescendant()); |
159 } | 258 } |
160 | 259 |
161 TEST_F(PaintLayerTest, HasVisibleDescendant) { | 260 TEST_P(PaintLayerTest, HasVisibleDescendant) { |
162 enableCompositing(); | 261 enableCompositing(); |
163 setBodyInnerHTML( | 262 setBodyInnerHTML( |
164 "<div id='invisible' style='position:relative'>" | 263 "<div id='invisible' style='position:relative'>" |
165 " <div id='visible' style='visibility: visible; position: relative'>" | 264 " <div id='visible' style='visibility: visible; position: relative'>" |
166 " </div>" | 265 " </div>" |
167 "</div>"); | 266 "</div>"); |
168 PaintLayer* invisible = | 267 PaintLayer* invisible = |
169 toLayoutBoxModelObject(getLayoutObjectByElementId("invisible"))->layer(); | 268 toLayoutBoxModelObject(getLayoutObjectByElementId("invisible"))->layer(); |
170 PaintLayer* visible = | 269 PaintLayer* visible = |
171 toLayoutBoxModelObject(getLayoutObjectByElementId("visible"))->layer(); | 270 toLayoutBoxModelObject(getLayoutObjectByElementId("visible"))->layer(); |
172 | 271 |
173 EXPECT_TRUE(invisible->hasVisibleDescendant()); | 272 EXPECT_TRUE(invisible->hasVisibleDescendant()); |
174 EXPECT_FALSE(visible->hasVisibleDescendant()); | 273 EXPECT_FALSE(visible->hasVisibleDescendant()); |
175 | 274 |
176 EXPECT_FALSE(invisible->hasNonIsolatedDescendantWithBlendMode()); | 275 EXPECT_FALSE(invisible->hasNonIsolatedDescendantWithBlendMode()); |
177 EXPECT_FALSE(invisible->hasDescendantWithClipPath()); | 276 EXPECT_FALSE(invisible->hasDescendantWithClipPath()); |
178 } | 277 } |
179 | 278 |
180 } // namespace blink | 279 } // namespace blink |
OLD | NEW |