OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "config.h" | |
6 #include "platform/graphics/paint/DisplayItemList.h" | |
7 | |
8 #include "platform/RuntimeEnabledFeatures.h" | |
9 #include "platform/graphics/GraphicsContext.h" | |
10 #include "platform/graphics/paint/CachedDisplayItem.h" | |
11 #include "platform/graphics/paint/ClipPathRecorder.h" | |
12 #include "platform/graphics/paint/ClipRecorder.h" | |
13 #include "platform/graphics/paint/DrawingDisplayItem.h" | |
14 #include "platform/graphics/paint/DrawingRecorder.h" | |
15 #include "platform/graphics/paint/SubsequenceRecorder.h" | |
16 #include <gtest/gtest.h> | |
17 | |
18 namespace blink { | |
19 | |
20 class DisplayItemListTest : public ::testing::Test { | |
21 public: | |
22 DisplayItemListTest() | |
23 : m_displayItemList(DisplayItemList::create()) | |
24 , m_originalSlimmingPaintSubsequenceCachingEnabled(RuntimeEnabledFeature
s::slimmingPaintSubsequenceCachingEnabled()) | |
25 , m_originalSlimmingPaintV2Enabled(RuntimeEnabledFeatures::slimmingPaint
V2Enabled()) { } | |
26 | |
27 protected: | |
28 DisplayItemList& displayItemList() { return *m_displayItemList; } | |
29 | |
30 private: | |
31 void TearDown() override | |
32 { | |
33 RuntimeEnabledFeatures::setSlimmingPaintSubsequenceCachingEnabled(m_orig
inalSlimmingPaintSubsequenceCachingEnabled); | |
34 RuntimeEnabledFeatures::setSlimmingPaintV2Enabled(m_originalSlimmingPain
tV2Enabled); | |
35 } | |
36 | |
37 OwnPtr<DisplayItemList> m_displayItemList; | |
38 bool m_originalSlimmingPaintSubsequenceCachingEnabled; | |
39 bool m_originalSlimmingPaintV2Enabled; | |
40 }; | |
41 | |
42 const DisplayItem::Type foregroundDrawingType = static_cast<DisplayItem::Type>(D
isplayItem::DrawingPaintPhaseFirst + 4); | |
43 const DisplayItem::Type backgroundDrawingType = DisplayItem::DrawingPaintPhaseFi
rst; | |
44 const DisplayItem::Type clipType = DisplayItem::ClipFirst; | |
45 const DisplayItem::Type subsequenceType = DisplayItem::SubsequenceNormalFlowAndP
ositiveZOrder; | |
46 const DisplayItem::Type endSubsequenceType = DisplayItem::subsequenceTypeToEndSu
bsequenceType(subsequenceType); | |
47 const DisplayItem::Type cachedSubsequenceType = DisplayItem::subsequenceTypeToCa
chedSubsequenceType(subsequenceType); | |
48 | |
49 class TestDisplayItemClient { | |
50 public: | |
51 TestDisplayItemClient(const String& name) | |
52 : m_name(name) | |
53 { } | |
54 | |
55 DisplayItemClient displayItemClient() const { return toDisplayItemClient(thi
s); } | |
56 String debugName() const { return m_name; } | |
57 | |
58 private: | |
59 String m_name; | |
60 }; | |
61 | |
62 class TestDisplayItem final : public DisplayItem { | |
63 public: | |
64 TestDisplayItem(const TestDisplayItemClient& client, Type type) : DisplayIte
m(client, type, sizeof(*this)) { } | |
65 | |
66 void replay(GraphicsContext&) const final { ASSERT_NOT_REACHED(); } | |
67 void appendToWebDisplayItemList(WebDisplayItemList*) const final { ASSERT_NO
T_REACHED(); } | |
68 }; | |
69 | |
70 #ifndef NDEBUG | |
71 #define TRACE_DISPLAY_ITEMS(i, expected, actual) \ | |
72 String trace = String::format("%d: ", (int)i) + "Expected: " + (expected).as
DebugString() + " Actual: " + (actual).asDebugString(); \ | |
73 SCOPED_TRACE(trace.utf8().data()); | |
74 #else | |
75 #define TRACE_DISPLAY_ITEMS(i, expected, actual) | |
76 #endif | |
77 | |
78 #define EXPECT_DISPLAY_LIST(actual, expectedSize, ...) \ | |
79 do { \ | |
80 EXPECT_EQ((size_t)expectedSize, actual.size()); \ | |
81 if (expectedSize != actual.size()) \ | |
82 break; \ | |
83 const TestDisplayItem expected[] = { __VA_ARGS__ }; \ | |
84 for (size_t index = 0; index < std::min<size_t>(actual.size(), expectedS
ize); index++) { \ | |
85 TRACE_DISPLAY_ITEMS(index, expected[index], actual[index]); \ | |
86 EXPECT_EQ(expected[index].client(), actual[index].client()); \ | |
87 EXPECT_EQ(expected[index].type(), actual[index].type()); \ | |
88 } \ | |
89 } while (false); | |
90 | |
91 void drawRect(GraphicsContext& context, const TestDisplayItemClient& client, Dis
playItem::Type type, const FloatRect& bounds) | |
92 { | |
93 if (DrawingRecorder::useCachedDrawingIfPossible(context, client, type)) | |
94 return; | |
95 DrawingRecorder drawingRecorder(context, client, type, bounds); | |
96 IntRect rect(0, 0, 10, 10); | |
97 context.drawRect(rect); | |
98 } | |
99 | |
100 void drawClippedRect(GraphicsContext& context, const TestDisplayItemClient& clie
nt, DisplayItem::Type clipType, DisplayItem::Type drawingType, const FloatRect&
bound) | |
101 { | |
102 ClipRecorder clipRecorder(context, client, clipType, LayoutRect(1, 1, 9, 9))
; | |
103 drawRect(context, client, drawingType, bound); | |
104 } | |
105 | |
106 TEST_F(DisplayItemListTest, NestedRecorders) | |
107 { | |
108 GraphicsContext context(&displayItemList()); | |
109 | |
110 TestDisplayItemClient client("client"); | |
111 | |
112 drawClippedRect(context, client, clipType, backgroundDrawingType, FloatRect(
100, 100, 200, 200)); | |
113 displayItemList().commitNewDisplayItems(); | |
114 | |
115 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 3, | |
116 TestDisplayItem(client, clipType), | |
117 TestDisplayItem(client, backgroundDrawingType), | |
118 TestDisplayItem(client, DisplayItem::clipTypeToEndClipType(clipType))); | |
119 } | |
120 | |
121 TEST_F(DisplayItemListTest, UpdateBasic) | |
122 { | |
123 TestDisplayItemClient first("first"); | |
124 TestDisplayItemClient second("second"); | |
125 GraphicsContext context(&displayItemList()); | |
126 | |
127 drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 300, 300
)); | |
128 drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 200, 20
0)); | |
129 drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 300, 300
)); | |
130 displayItemList().commitNewDisplayItems(); | |
131 | |
132 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 3, | |
133 TestDisplayItem(first, backgroundDrawingType), | |
134 TestDisplayItem(second, backgroundDrawingType), | |
135 TestDisplayItem(first, foregroundDrawingType)); | |
136 | |
137 displayItemList().invalidate(second, PaintInvalidationFull, IntRect(), IntRe
ct()); | |
138 drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 300, 300
)); | |
139 drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 300, 300
)); | |
140 displayItemList().commitNewDisplayItems(); | |
141 | |
142 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 2, | |
143 TestDisplayItem(first, backgroundDrawingType), | |
144 TestDisplayItem(first, foregroundDrawingType)); | |
145 } | |
146 | |
147 TEST_F(DisplayItemListTest, UpdateSwapOrder) | |
148 { | |
149 TestDisplayItemClient first("first"); | |
150 TestDisplayItemClient second("second"); | |
151 TestDisplayItemClient unaffected("unaffected"); | |
152 GraphicsContext context(&displayItemList()); | |
153 | |
154 drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 100, 100
)); | |
155 drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 50, 200
)); | |
156 drawRect(context, unaffected, backgroundDrawingType, FloatRect(300, 300, 10,
10)); | |
157 displayItemList().commitNewDisplayItems(); | |
158 | |
159 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 3, | |
160 TestDisplayItem(first, backgroundDrawingType), | |
161 TestDisplayItem(second, backgroundDrawingType), | |
162 TestDisplayItem(unaffected, backgroundDrawingType)); | |
163 | |
164 displayItemList().invalidate(second, PaintInvalidationFull, IntRect(), IntRe
ct()); | |
165 drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 50, 200
)); | |
166 drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 100, 100
)); | |
167 drawRect(context, unaffected, backgroundDrawingType, FloatRect(300, 300, 10,
10)); | |
168 displayItemList().commitNewDisplayItems(); | |
169 | |
170 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 3, | |
171 TestDisplayItem(second, backgroundDrawingType), | |
172 TestDisplayItem(first, backgroundDrawingType), | |
173 TestDisplayItem(unaffected, backgroundDrawingType)); | |
174 } | |
175 | |
176 TEST_F(DisplayItemListTest, UpdateNewItemInMiddle) | |
177 { | |
178 TestDisplayItemClient first("first"); | |
179 TestDisplayItemClient second("second"); | |
180 TestDisplayItemClient third("third"); | |
181 GraphicsContext context(&displayItemList()); | |
182 | |
183 drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 100, 100
)); | |
184 drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 50, 200
)); | |
185 displayItemList().commitNewDisplayItems(); | |
186 | |
187 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 2, | |
188 TestDisplayItem(first, backgroundDrawingType), | |
189 TestDisplayItem(second, backgroundDrawingType)); | |
190 | |
191 drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 100, 100
)); | |
192 drawRect(context, third, backgroundDrawingType, FloatRect(125, 100, 200, 50)
); | |
193 drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 50, 200
)); | |
194 displayItemList().commitNewDisplayItems(); | |
195 | |
196 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 3, | |
197 TestDisplayItem(first, backgroundDrawingType), | |
198 TestDisplayItem(third, backgroundDrawingType), | |
199 TestDisplayItem(second, backgroundDrawingType)); | |
200 } | |
201 | |
202 TEST_F(DisplayItemListTest, UpdateInvalidationWithPhases) | |
203 { | |
204 TestDisplayItemClient first("first"); | |
205 TestDisplayItemClient second("second"); | |
206 TestDisplayItemClient third("third"); | |
207 GraphicsContext context(&displayItemList()); | |
208 | |
209 drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 100, 100
)); | |
210 drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 50, 200
)); | |
211 drawRect(context, third, backgroundDrawingType, FloatRect(300, 100, 50, 50))
; | |
212 drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 100, 100
)); | |
213 drawRect(context, second, foregroundDrawingType, FloatRect(100, 100, 50, 200
)); | |
214 drawRect(context, third, foregroundDrawingType, FloatRect(300, 100, 50, 50))
; | |
215 displayItemList().commitNewDisplayItems(); | |
216 | |
217 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 6, | |
218 TestDisplayItem(first, backgroundDrawingType), | |
219 TestDisplayItem(second, backgroundDrawingType), | |
220 TestDisplayItem(third, backgroundDrawingType), | |
221 TestDisplayItem(first, foregroundDrawingType), | |
222 TestDisplayItem(second, foregroundDrawingType), | |
223 TestDisplayItem(third, foregroundDrawingType)); | |
224 | |
225 displayItemList().invalidate(second, PaintInvalidationFull, IntRect(), IntRe
ct()); | |
226 drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 100, 100
)); | |
227 drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 50, 200
)); | |
228 drawRect(context, third, backgroundDrawingType, FloatRect(300, 100, 50, 50))
; | |
229 drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 100, 100
)); | |
230 drawRect(context, second, foregroundDrawingType, FloatRect(100, 100, 50, 200
)); | |
231 drawRect(context, third, foregroundDrawingType, FloatRect(300, 100, 50, 50))
; | |
232 displayItemList().commitNewDisplayItems(); | |
233 | |
234 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 6, | |
235 TestDisplayItem(first, backgroundDrawingType), | |
236 TestDisplayItem(second, backgroundDrawingType), | |
237 TestDisplayItem(third, backgroundDrawingType), | |
238 TestDisplayItem(first, foregroundDrawingType), | |
239 TestDisplayItem(second, foregroundDrawingType), | |
240 TestDisplayItem(third, foregroundDrawingType)); | |
241 } | |
242 | |
243 TEST_F(DisplayItemListTest, UpdateAddFirstOverlap) | |
244 { | |
245 TestDisplayItemClient first("first"); | |
246 TestDisplayItemClient second("second"); | |
247 GraphicsContext context(&displayItemList()); | |
248 | |
249 drawRect(context, second, backgroundDrawingType, FloatRect(200, 200, 50, 50)
); | |
250 drawRect(context, second, foregroundDrawingType, FloatRect(200, 200, 50, 50)
); | |
251 displayItemList().commitNewDisplayItems(); | |
252 | |
253 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 2, | |
254 TestDisplayItem(second, backgroundDrawingType), | |
255 TestDisplayItem(second, foregroundDrawingType)); | |
256 | |
257 displayItemList().invalidate(first, PaintInvalidationFull, IntRect(), IntRec
t()); | |
258 displayItemList().invalidate(second, PaintInvalidationFull, IntRect(), IntRe
ct()); | |
259 drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 150, 150
)); | |
260 drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 150, 150
)); | |
261 drawRect(context, second, backgroundDrawingType, FloatRect(200, 200, 50, 50)
); | |
262 drawRect(context, second, foregroundDrawingType, FloatRect(200, 200, 50, 50)
); | |
263 displayItemList().commitNewDisplayItems(); | |
264 | |
265 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 4, | |
266 TestDisplayItem(first, backgroundDrawingType), | |
267 TestDisplayItem(first, foregroundDrawingType), | |
268 TestDisplayItem(second, backgroundDrawingType), | |
269 TestDisplayItem(second, foregroundDrawingType)); | |
270 | |
271 displayItemList().invalidate(first, PaintInvalidationFull, IntRect(), IntRec
t()); | |
272 drawRect(context, second, backgroundDrawingType, FloatRect(200, 200, 50, 50)
); | |
273 drawRect(context, second, foregroundDrawingType, FloatRect(200, 200, 50, 50)
); | |
274 displayItemList().commitNewDisplayItems(); | |
275 | |
276 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 2, | |
277 TestDisplayItem(second, backgroundDrawingType), | |
278 TestDisplayItem(second, foregroundDrawingType)); | |
279 } | |
280 | |
281 TEST_F(DisplayItemListTest, UpdateAddLastOverlap) | |
282 { | |
283 TestDisplayItemClient first("first"); | |
284 TestDisplayItemClient second("second"); | |
285 GraphicsContext context(&displayItemList()); | |
286 | |
287 drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 150, 150
)); | |
288 drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 150, 150
)); | |
289 displayItemList().commitNewDisplayItems(); | |
290 | |
291 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 2, | |
292 TestDisplayItem(first, backgroundDrawingType), | |
293 TestDisplayItem(first, foregroundDrawingType)); | |
294 | |
295 displayItemList().invalidate(first, PaintInvalidationFull, IntRect(), IntRec
t()); | |
296 displayItemList().invalidate(second, PaintInvalidationFull, IntRect(), IntRe
ct()); | |
297 drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 150, 150
)); | |
298 drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 150, 150
)); | |
299 drawRect(context, second, backgroundDrawingType, FloatRect(200, 200, 50, 50)
); | |
300 drawRect(context, second, foregroundDrawingType, FloatRect(200, 200, 50, 50)
); | |
301 displayItemList().commitNewDisplayItems(); | |
302 | |
303 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 4, | |
304 TestDisplayItem(first, backgroundDrawingType), | |
305 TestDisplayItem(first, foregroundDrawingType), | |
306 TestDisplayItem(second, backgroundDrawingType), | |
307 TestDisplayItem(second, foregroundDrawingType)); | |
308 | |
309 displayItemList().invalidate(first, PaintInvalidationFull, IntRect(), IntRec
t()); | |
310 displayItemList().invalidate(second, PaintInvalidationFull, IntRect(), IntRe
ct()); | |
311 drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 150, 150
)); | |
312 drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 150, 150
)); | |
313 displayItemList().commitNewDisplayItems(); | |
314 | |
315 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 2, | |
316 TestDisplayItem(first, backgroundDrawingType), | |
317 TestDisplayItem(first, foregroundDrawingType)); | |
318 } | |
319 | |
320 TEST_F(DisplayItemListTest, UpdateClip) | |
321 { | |
322 TestDisplayItemClient first("first"); | |
323 TestDisplayItemClient second("second"); | |
324 GraphicsContext context(&displayItemList()); | |
325 | |
326 { | |
327 ClipRecorder clipRecorder(context, first, clipType, LayoutRect(1, 1, 2,
2)); | |
328 drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 150,
150)); | |
329 drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 150
, 150)); | |
330 } | |
331 displayItemList().commitNewDisplayItems(); | |
332 | |
333 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 4, | |
334 TestDisplayItem(first, clipType), | |
335 TestDisplayItem(first, backgroundDrawingType), | |
336 TestDisplayItem(second, backgroundDrawingType), | |
337 TestDisplayItem(first, DisplayItem::clipTypeToEndClipType(clipType))); | |
338 | |
339 displayItemList().invalidate(first, PaintInvalidationFull, IntRect(), IntRec
t()); | |
340 drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 150, 150
)); | |
341 drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 150, 15
0)); | |
342 displayItemList().commitNewDisplayItems(); | |
343 | |
344 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 2, | |
345 TestDisplayItem(first, backgroundDrawingType), | |
346 TestDisplayItem(second, backgroundDrawingType)); | |
347 | |
348 displayItemList().invalidate(second, PaintInvalidationFull, IntRect(), IntRe
ct()); | |
349 drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 150, 150
)); | |
350 { | |
351 ClipRecorder clipRecorder(context, second, clipType, LayoutRect(1, 1, 2,
2)); | |
352 drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 150
, 150)); | |
353 } | |
354 displayItemList().commitNewDisplayItems(); | |
355 | |
356 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 4, | |
357 TestDisplayItem(first, backgroundDrawingType), | |
358 TestDisplayItem(second, clipType), | |
359 TestDisplayItem(second, backgroundDrawingType), | |
360 TestDisplayItem(second, DisplayItem::clipTypeToEndClipType(clipType))); | |
361 } | |
362 | |
363 TEST_F(DisplayItemListTest, CachedDisplayItems) | |
364 { | |
365 TestDisplayItemClient first("first"); | |
366 TestDisplayItemClient second("second"); | |
367 GraphicsContext context(&displayItemList()); | |
368 | |
369 drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 150, 150
)); | |
370 drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 150, 15
0)); | |
371 displayItemList().commitNewDisplayItems(); | |
372 | |
373 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 2, | |
374 TestDisplayItem(first, backgroundDrawingType), | |
375 TestDisplayItem(second, backgroundDrawingType)); | |
376 EXPECT_TRUE(displayItemList().clientCacheIsValid(first.displayItemClient()))
; | |
377 EXPECT_TRUE(displayItemList().clientCacheIsValid(second.displayItemClient())
); | |
378 const SkPicture* firstPicture = static_cast<const DrawingDisplayItem&>(displ
ayItemList().displayItems()[0]).picture(); | |
379 const SkPicture* secondPicture = static_cast<const DrawingDisplayItem&>(disp
layItemList().displayItems()[1]).picture(); | |
380 | |
381 displayItemList().invalidate(first, PaintInvalidationFull, IntRect(), IntRec
t()); | |
382 EXPECT_FALSE(displayItemList().clientCacheIsValid(first.displayItemClient())
); | |
383 EXPECT_TRUE(displayItemList().clientCacheIsValid(second.displayItemClient())
); | |
384 | |
385 drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 150, 150
)); | |
386 drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 150, 15
0)); | |
387 displayItemList().commitNewDisplayItems(); | |
388 | |
389 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 2, | |
390 TestDisplayItem(first, backgroundDrawingType), | |
391 TestDisplayItem(second, backgroundDrawingType)); | |
392 // The first display item should be updated. | |
393 EXPECT_NE(firstPicture, static_cast<const DrawingDisplayItem&>(displayItemLi
st().displayItems()[0]).picture()); | |
394 // The second display item should be cached. | |
395 EXPECT_EQ(secondPicture, static_cast<const DrawingDisplayItem&>(displayItemL
ist().displayItems()[1]).picture()); | |
396 EXPECT_TRUE(displayItemList().clientCacheIsValid(first.displayItemClient()))
; | |
397 EXPECT_TRUE(displayItemList().clientCacheIsValid(second.displayItemClient())
); | |
398 | |
399 displayItemList().invalidateAll(); | |
400 EXPECT_FALSE(displayItemList().clientCacheIsValid(first.displayItemClient())
); | |
401 EXPECT_FALSE(displayItemList().clientCacheIsValid(second.displayItemClient()
)); | |
402 } | |
403 | |
404 TEST_F(DisplayItemListTest, ComplexUpdateSwapOrder) | |
405 { | |
406 TestDisplayItemClient container1("container1"); | |
407 TestDisplayItemClient content1("content1"); | |
408 TestDisplayItemClient container2("container2"); | |
409 TestDisplayItemClient content2("content2"); | |
410 GraphicsContext context(&displayItemList()); | |
411 | |
412 drawRect(context, container1, backgroundDrawingType, FloatRect(100, 100, 100
, 100)); | |
413 drawRect(context, content1, backgroundDrawingType, FloatRect(100, 100, 50, 2
00)); | |
414 drawRect(context, content1, foregroundDrawingType, FloatRect(100, 100, 50, 2
00)); | |
415 drawRect(context, container1, foregroundDrawingType, FloatRect(100, 100, 100
, 100)); | |
416 drawRect(context, container2, backgroundDrawingType, FloatRect(100, 200, 100
, 100)); | |
417 drawRect(context, content2, backgroundDrawingType, FloatRect(100, 200, 50, 2
00)); | |
418 drawRect(context, content2, foregroundDrawingType, FloatRect(100, 200, 50, 2
00)); | |
419 drawRect(context, container2, foregroundDrawingType, FloatRect(100, 200, 100
, 100)); | |
420 displayItemList().commitNewDisplayItems(); | |
421 | |
422 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 8, | |
423 TestDisplayItem(container1, backgroundDrawingType), | |
424 TestDisplayItem(content1, backgroundDrawingType), | |
425 TestDisplayItem(content1, foregroundDrawingType), | |
426 TestDisplayItem(container1, foregroundDrawingType), | |
427 TestDisplayItem(container2, backgroundDrawingType), | |
428 TestDisplayItem(content2, backgroundDrawingType), | |
429 TestDisplayItem(content2, foregroundDrawingType), | |
430 TestDisplayItem(container2, foregroundDrawingType)); | |
431 | |
432 // Simulate the situation when container1 e.g. gets a z-index that is now gr
eater than container2. | |
433 displayItemList().invalidate(container1, PaintInvalidationFull, IntRect(), I
ntRect()); | |
434 drawRect(context, container2, backgroundDrawingType, FloatRect(100, 200, 100
, 100)); | |
435 drawRect(context, content2, backgroundDrawingType, FloatRect(100, 200, 50, 2
00)); | |
436 drawRect(context, content2, foregroundDrawingType, FloatRect(100, 200, 50, 2
00)); | |
437 drawRect(context, container2, foregroundDrawingType, FloatRect(100, 200, 100
, 100)); | |
438 drawRect(context, container1, backgroundDrawingType, FloatRect(100, 100, 100
, 100)); | |
439 drawRect(context, content1, backgroundDrawingType, FloatRect(100, 100, 50, 2
00)); | |
440 drawRect(context, content1, foregroundDrawingType, FloatRect(100, 100, 50, 2
00)); | |
441 drawRect(context, container1, foregroundDrawingType, FloatRect(100, 100, 100
, 100)); | |
442 displayItemList().commitNewDisplayItems(); | |
443 | |
444 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 8, | |
445 TestDisplayItem(container2, backgroundDrawingType), | |
446 TestDisplayItem(content2, backgroundDrawingType), | |
447 TestDisplayItem(content2, foregroundDrawingType), | |
448 TestDisplayItem(container2, foregroundDrawingType), | |
449 TestDisplayItem(container1, backgroundDrawingType), | |
450 TestDisplayItem(content1, backgroundDrawingType), | |
451 TestDisplayItem(content1, foregroundDrawingType), | |
452 TestDisplayItem(container1, foregroundDrawingType)); | |
453 } | |
454 | |
455 TEST_F(DisplayItemListTest, CachedSubsequenceSwapOrder) | |
456 { | |
457 RuntimeEnabledFeatures::setSlimmingPaintSubsequenceCachingEnabled(true); | |
458 | |
459 TestDisplayItemClient container1("container1"); | |
460 TestDisplayItemClient content1("content1"); | |
461 TestDisplayItemClient container2("container2"); | |
462 TestDisplayItemClient content2("content2"); | |
463 GraphicsContext context(&displayItemList()); | |
464 | |
465 { | |
466 SubsequenceRecorder r(context, container1, subsequenceType); | |
467 drawRect(context, container1, backgroundDrawingType, FloatRect(100, 100,
100, 100)); | |
468 drawRect(context, content1, backgroundDrawingType, FloatRect(100, 100, 5
0, 200)); | |
469 drawRect(context, content1, foregroundDrawingType, FloatRect(100, 100, 5
0, 200)); | |
470 drawRect(context, container1, foregroundDrawingType, FloatRect(100, 100,
100, 100)); | |
471 } | |
472 { | |
473 SubsequenceRecorder r(context, container2, subsequenceType); | |
474 drawRect(context, container2, backgroundDrawingType, FloatRect(100, 200,
100, 100)); | |
475 drawRect(context, content2, backgroundDrawingType, FloatRect(100, 200, 5
0, 200)); | |
476 drawRect(context, content2, foregroundDrawingType, FloatRect(100, 200, 5
0, 200)); | |
477 drawRect(context, container2, foregroundDrawingType, FloatRect(100, 200,
100, 100)); | |
478 } | |
479 displayItemList().commitNewDisplayItems(); | |
480 | |
481 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 12, | |
482 TestDisplayItem(container1, subsequenceType), | |
483 TestDisplayItem(container1, backgroundDrawingType), | |
484 TestDisplayItem(content1, backgroundDrawingType), | |
485 TestDisplayItem(content1, foregroundDrawingType), | |
486 TestDisplayItem(container1, foregroundDrawingType), | |
487 TestDisplayItem(container1, endSubsequenceType), | |
488 | |
489 TestDisplayItem(container2, subsequenceType), | |
490 TestDisplayItem(container2, backgroundDrawingType), | |
491 TestDisplayItem(content2, backgroundDrawingType), | |
492 TestDisplayItem(content2, foregroundDrawingType), | |
493 TestDisplayItem(container2, foregroundDrawingType), | |
494 TestDisplayItem(container2, endSubsequenceType)); | |
495 | |
496 // Simulate the situation when container1 e.g. gets a z-index that is now gr
eater than container2. | |
497 EXPECT_TRUE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, con
tainer2, subsequenceType)); | |
498 EXPECT_TRUE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, con
tainer1, subsequenceType)); | |
499 | |
500 EXPECT_DISPLAY_LIST(displayItemList().newDisplayItems(), 2, | |
501 TestDisplayItem(container2, cachedSubsequenceType), | |
502 TestDisplayItem(container1, cachedSubsequenceType)); | |
503 | |
504 displayItemList().commitNewDisplayItems(); | |
505 | |
506 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 12, | |
507 TestDisplayItem(container2, subsequenceType), | |
508 TestDisplayItem(container2, backgroundDrawingType), | |
509 TestDisplayItem(content2, backgroundDrawingType), | |
510 TestDisplayItem(content2, foregroundDrawingType), | |
511 TestDisplayItem(container2, foregroundDrawingType), | |
512 TestDisplayItem(container2, endSubsequenceType), | |
513 | |
514 TestDisplayItem(container1, subsequenceType), | |
515 TestDisplayItem(container1, backgroundDrawingType), | |
516 TestDisplayItem(content1, backgroundDrawingType), | |
517 TestDisplayItem(content1, foregroundDrawingType), | |
518 TestDisplayItem(container1, foregroundDrawingType), | |
519 TestDisplayItem(container1, endSubsequenceType)); | |
520 } | |
521 | |
522 TEST_F(DisplayItemListTest, OutOfOrderNoCrash) | |
523 { | |
524 TestDisplayItemClient client("client"); | |
525 GraphicsContext context(&displayItemList()); | |
526 | |
527 const DisplayItem::Type type1 = DisplayItem::DrawingFirst; | |
528 const DisplayItem::Type type2 = static_cast<DisplayItem::Type>(DisplayItem::
DrawingFirst + 1); | |
529 const DisplayItem::Type type3 = static_cast<DisplayItem::Type>(DisplayItem::
DrawingFirst + 2); | |
530 const DisplayItem::Type type4 = static_cast<DisplayItem::Type>(DisplayItem::
DrawingFirst + 3); | |
531 | |
532 drawRect(context, client, type1, FloatRect(100, 100, 100, 100)); | |
533 drawRect(context, client, type2, FloatRect(100, 100, 50, 200)); | |
534 drawRect(context, client, type3, FloatRect(100, 100, 50, 200)); | |
535 drawRect(context, client, type4, FloatRect(100, 100, 100, 100)); | |
536 | |
537 displayItemList().commitNewDisplayItems(); | |
538 | |
539 drawRect(context, client, type2, FloatRect(100, 100, 50, 200)); | |
540 drawRect(context, client, type3, FloatRect(100, 100, 50, 200)); | |
541 drawRect(context, client, type1, FloatRect(100, 100, 100, 100)); | |
542 drawRect(context, client, type4, FloatRect(100, 100, 100, 100)); | |
543 | |
544 displayItemList().commitNewDisplayItems(); | |
545 } | |
546 | |
547 TEST_F(DisplayItemListTest, CachedNestedSubsequenceUpdate) | |
548 { | |
549 RuntimeEnabledFeatures::setSlimmingPaintSubsequenceCachingEnabled(true); | |
550 | |
551 TestDisplayItemClient container1("container1"); | |
552 TestDisplayItemClient content1("content1"); | |
553 TestDisplayItemClient container2("container2"); | |
554 TestDisplayItemClient content2("content2"); | |
555 GraphicsContext context(&displayItemList()); | |
556 | |
557 { | |
558 SubsequenceRecorder r(context, container1, subsequenceType); | |
559 drawRect(context, container1, backgroundDrawingType, FloatRect(100, 100,
100, 100)); | |
560 { | |
561 SubsequenceRecorder r(context, content1, subsequenceType); | |
562 drawRect(context, content1, backgroundDrawingType, FloatRect(100, 10
0, 50, 200)); | |
563 drawRect(context, content1, foregroundDrawingType, FloatRect(100, 10
0, 50, 200)); | |
564 } | |
565 drawRect(context, container1, foregroundDrawingType, FloatRect(100, 100,
100, 100)); | |
566 } | |
567 { | |
568 SubsequenceRecorder r(context, container2, subsequenceType); | |
569 drawRect(context, container2, backgroundDrawingType, FloatRect(100, 200,
100, 100)); | |
570 { | |
571 SubsequenceRecorder r(context, content2, subsequenceType); | |
572 drawRect(context, content2, backgroundDrawingType, FloatRect(100, 20
0, 50, 200)); | |
573 } | |
574 } | |
575 displayItemList().commitNewDisplayItems(); | |
576 | |
577 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 14, | |
578 TestDisplayItem(container1, subsequenceType), | |
579 TestDisplayItem(container1, backgroundDrawingType), | |
580 TestDisplayItem(content1, subsequenceType), | |
581 TestDisplayItem(content1, backgroundDrawingType), | |
582 TestDisplayItem(content1, foregroundDrawingType), | |
583 TestDisplayItem(content1, endSubsequenceType), | |
584 TestDisplayItem(container1, foregroundDrawingType), | |
585 TestDisplayItem(container1, endSubsequenceType), | |
586 | |
587 TestDisplayItem(container2, subsequenceType), | |
588 TestDisplayItem(container2, backgroundDrawingType), | |
589 TestDisplayItem(content2, subsequenceType), | |
590 TestDisplayItem(content2, backgroundDrawingType), | |
591 TestDisplayItem(content2, endSubsequenceType), | |
592 TestDisplayItem(container2, endSubsequenceType)); | |
593 | |
594 // Invalidate container1 but not content1. | |
595 displayItemList().invalidate(container1, PaintInvalidationFull, IntRect(), I
ntRect()); | |
596 | |
597 // Container2 itself now becomes empty (but still has the 'content2' child), | |
598 // and chooses not to output subsequence info. | |
599 | |
600 displayItemList().invalidate(container2, PaintInvalidationFull, IntRect(), I
ntRect()); | |
601 displayItemList().invalidate(content2, PaintInvalidationFull, IntRect(), Int
Rect()); | |
602 EXPECT_FALSE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, co
ntainer2, subsequenceType)); | |
603 EXPECT_FALSE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, co
ntent2, subsequenceType)); | |
604 // Content2 now outputs foreground only. | |
605 { | |
606 SubsequenceRecorder r(context, content2, subsequenceType); | |
607 drawRect(context, content2, foregroundDrawingType, FloatRect(100, 200, 5
0, 200)); | |
608 } | |
609 // Repaint container1 with foreground only. | |
610 { | |
611 EXPECT_FALSE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context
, container1, subsequenceType)); | |
612 SubsequenceRecorder r(context, container1, subsequenceType); | |
613 // Use cached subsequence of content1. | |
614 EXPECT_TRUE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context,
content1, subsequenceType)); | |
615 drawRect(context, container1, foregroundDrawingType, FloatRect(100, 100,
100, 100)); | |
616 } | |
617 EXPECT_DISPLAY_LIST(displayItemList().newDisplayItems(), 7, | |
618 TestDisplayItem(content2, subsequenceType), | |
619 TestDisplayItem(content2, foregroundDrawingType), | |
620 TestDisplayItem(content2, endSubsequenceType), | |
621 TestDisplayItem(container1, subsequenceType), | |
622 TestDisplayItem(content1, cachedSubsequenceType), | |
623 TestDisplayItem(container1, foregroundDrawingType), | |
624 TestDisplayItem(container1, endSubsequenceType)); | |
625 | |
626 displayItemList().commitNewDisplayItems(); | |
627 | |
628 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 10, | |
629 TestDisplayItem(content2, subsequenceType), | |
630 TestDisplayItem(content2, foregroundDrawingType), | |
631 TestDisplayItem(content2, endSubsequenceType), | |
632 | |
633 TestDisplayItem(container1, subsequenceType), | |
634 TestDisplayItem(content1, subsequenceType), | |
635 TestDisplayItem(content1, backgroundDrawingType), | |
636 TestDisplayItem(content1, foregroundDrawingType), | |
637 TestDisplayItem(content1, endSubsequenceType), | |
638 TestDisplayItem(container1, foregroundDrawingType), | |
639 TestDisplayItem(container1, endSubsequenceType)); | |
640 } | |
641 | |
642 TEST_F(DisplayItemListTest, Scope) | |
643 { | |
644 TestDisplayItemClient multicol("multicol"); | |
645 TestDisplayItemClient content("content"); | |
646 GraphicsContext context(&displayItemList()); | |
647 | |
648 FloatRect rect1(100, 100, 50, 50); | |
649 FloatRect rect2(150, 100, 50, 50); | |
650 FloatRect rect3(200, 100, 50, 50); | |
651 | |
652 drawRect(context, multicol, backgroundDrawingType, FloatRect(100, 200, 100,
100)); | |
653 | |
654 displayItemList().beginScope(); | |
655 drawRect(context, content, foregroundDrawingType, rect1); | |
656 displayItemList().endScope(); | |
657 | |
658 displayItemList().beginScope(); | |
659 drawRect(context, content, foregroundDrawingType, rect2); | |
660 displayItemList().endScope(); | |
661 displayItemList().commitNewDisplayItems(); | |
662 | |
663 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 3, | |
664 TestDisplayItem(multicol, backgroundDrawingType), | |
665 TestDisplayItem(content, foregroundDrawingType), | |
666 TestDisplayItem(content, foregroundDrawingType)); | |
667 RefPtr<const SkPicture> picture1 = static_cast<const DrawingDisplayItem&>(di
splayItemList().displayItems()[1]).picture(); | |
668 RefPtr<const SkPicture> picture2 = static_cast<const DrawingDisplayItem&>(di
splayItemList().displayItems()[2]).picture(); | |
669 EXPECT_NE(picture1, picture2); | |
670 | |
671 // Draw again with nothing invalidated. | |
672 EXPECT_TRUE(displayItemList().clientCacheIsValid(multicol.displayItemClient(
))); | |
673 drawRect(context, multicol, backgroundDrawingType, FloatRect(100, 200, 100,
100)); | |
674 displayItemList().beginScope(); | |
675 drawRect(context, content, foregroundDrawingType, rect1); | |
676 displayItemList().endScope(); | |
677 | |
678 displayItemList().beginScope(); | |
679 drawRect(context, content, foregroundDrawingType, rect2); | |
680 displayItemList().endScope(); | |
681 | |
682 EXPECT_DISPLAY_LIST(displayItemList().newDisplayItems(), 3, | |
683 TestDisplayItem(multicol, DisplayItem::drawingTypeToCachedDrawingType(ba
ckgroundDrawingType)), | |
684 TestDisplayItem(content, foregroundDrawingType), | |
685 TestDisplayItem(content, foregroundDrawingType)); | |
686 | |
687 displayItemList().commitNewDisplayItems(); | |
688 | |
689 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 3, | |
690 TestDisplayItem(multicol, backgroundDrawingType), | |
691 TestDisplayItem(content, foregroundDrawingType), | |
692 TestDisplayItem(content, foregroundDrawingType)); | |
693 EXPECT_NE(picture1, static_cast<const DrawingDisplayItem&>(displayItemList()
.displayItems()[1]).picture()); | |
694 EXPECT_NE(picture2, static_cast<const DrawingDisplayItem&>(displayItemList()
.displayItems()[2]).picture()); | |
695 | |
696 // Now the multicol becomes 3 columns and repaints. | |
697 displayItemList().invalidate(multicol, PaintInvalidationFull, IntRect(), Int
Rect()); | |
698 drawRect(context, multicol, backgroundDrawingType, FloatRect(100, 100, 100,
100)); | |
699 | |
700 displayItemList().beginScope(); | |
701 drawRect(context, content, foregroundDrawingType, rect1); | |
702 displayItemList().endScope(); | |
703 | |
704 displayItemList().beginScope(); | |
705 drawRect(context, content, foregroundDrawingType, rect2); | |
706 displayItemList().endScope(); | |
707 | |
708 displayItemList().beginScope(); | |
709 drawRect(context, content, foregroundDrawingType, rect3); | |
710 displayItemList().endScope(); | |
711 | |
712 // We should repaint everything on invalidation of the scope container. | |
713 EXPECT_DISPLAY_LIST(displayItemList().newDisplayItems(), 4, | |
714 TestDisplayItem(multicol, backgroundDrawingType), | |
715 TestDisplayItem(content, foregroundDrawingType), | |
716 TestDisplayItem(content, foregroundDrawingType), | |
717 TestDisplayItem(content, foregroundDrawingType)); | |
718 EXPECT_NE(picture1, static_cast<const DrawingDisplayItem&>(displayItemList()
.newDisplayItems()[1]).picture()); | |
719 EXPECT_NE(picture2, static_cast<const DrawingDisplayItem&>(displayItemList()
.newDisplayItems()[2]).picture()); | |
720 | |
721 displayItemList().commitNewDisplayItems(); | |
722 } | |
723 | |
724 TEST_F(DisplayItemListTest, OptimizeNoopPairs) | |
725 { | |
726 TestDisplayItemClient first("first"); | |
727 TestDisplayItemClient second("second"); | |
728 TestDisplayItemClient third("third"); | |
729 | |
730 GraphicsContext context(&displayItemList()); | |
731 drawRect(context, first, backgroundDrawingType, FloatRect(0, 0, 100, 100)); | |
732 { | |
733 ClipPathRecorder clipRecorder(context, second, Path()); | |
734 drawRect(context, second, backgroundDrawingType, FloatRect(0, 0, 100, 10
0)); | |
735 } | |
736 drawRect(context, third, backgroundDrawingType, FloatRect(0, 0, 100, 100)); | |
737 | |
738 displayItemList().commitNewDisplayItems(); | |
739 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 5, | |
740 TestDisplayItem(first, backgroundDrawingType), | |
741 TestDisplayItem(second, DisplayItem::BeginClipPath), | |
742 TestDisplayItem(second, backgroundDrawingType), | |
743 TestDisplayItem(second, DisplayItem::EndClipPath), | |
744 TestDisplayItem(third, backgroundDrawingType)); | |
745 | |
746 displayItemList().invalidate(second, PaintInvalidationFull, IntRect(), IntRe
ct()); | |
747 drawRect(context, first, backgroundDrawingType, FloatRect(0, 0, 100, 100)); | |
748 { | |
749 ClipRecorder clipRecorder(context, second, clipType, LayoutRect(1, 1, 2,
2)); | |
750 // Do not draw anything for second. | |
751 } | |
752 drawRect(context, third, backgroundDrawingType, FloatRect(0, 0, 100, 100)); | |
753 displayItemList().commitNewDisplayItems(); | |
754 | |
755 // Empty clips should have been optimized out. | |
756 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 2, | |
757 TestDisplayItem(first, backgroundDrawingType), | |
758 TestDisplayItem(third, backgroundDrawingType)); | |
759 | |
760 displayItemList().invalidate(second, PaintInvalidationFull, IntRect(), IntRe
ct()); | |
761 drawRect(context, first, backgroundDrawingType, FloatRect(0, 0, 100, 100)); | |
762 { | |
763 ClipRecorder clipRecorder(context, second, clipType, LayoutRect(1, 1, 2,
2)); | |
764 { | |
765 ClipPathRecorder clipPathRecorder(context, second, Path()); | |
766 // Do not draw anything for second. | |
767 } | |
768 } | |
769 drawRect(context, third, backgroundDrawingType, FloatRect(0, 0, 100, 100)); | |
770 displayItemList().commitNewDisplayItems(); | |
771 | |
772 // Empty clips should have been optimized out. | |
773 EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 2, | |
774 TestDisplayItem(first, backgroundDrawingType), | |
775 TestDisplayItem(third, backgroundDrawingType)); | |
776 } | |
777 | |
778 TEST_F(DisplayItemListTest, SmallDisplayItemListHasOnePaintChunk) | |
779 { | |
780 RuntimeEnabledFeatures::setSlimmingPaintV2Enabled(true); | |
781 TestDisplayItemClient client("test client"); | |
782 | |
783 GraphicsContext context(&displayItemList()); | |
784 drawRect(context, client, backgroundDrawingType, FloatRect(0, 0, 100, 100)); | |
785 | |
786 displayItemList().commitNewDisplayItems(); | |
787 const auto& paintChunks = displayItemList().paintChunks(); | |
788 ASSERT_EQ(1u, paintChunks.size()); | |
789 EXPECT_EQ(0u, paintChunks[0].beginIndex); | |
790 EXPECT_EQ(1u, paintChunks[0].endIndex); | |
791 } | |
792 | |
793 } // namespace blink | |
OLD | NEW |