Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / paint / ViewDisplayListTest.cpp
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 "core/paint/ViewDisplayList.h"
7
8 #include "core/paint/ClipRecorder.h"
9 #include "core/paint/DrawingRecorder.h"
10 #include "core/rendering/RenderView.h"
11 #include "core/rendering/RenderingTestHelper.h"
12 #include "core/rendering/compositing/RenderLayerCompositor.h"
13 #include "platform/graphics/GraphicsContext.h"
14 #include <gtest/gtest.h>
15
16 namespace blink {
17 namespace {
18
19 class ViewDisplayListTest : public RenderingTest {
20 public:
21     ViewDisplayListTest() : m_renderView(nullptr) { }
22
23 protected:
24     RenderView* renderView() { return m_renderView; }
25
26 private:
27     virtual void SetUp() override
28     {
29         RuntimeEnabledFeatures::setSlimmingPaintEnabled(true);
30
31         RenderingTest::SetUp();
32
33         m_renderView = document().view()->renderView();
34         ASSERT_TRUE(m_renderView);
35     }
36
37     RenderView* m_renderView;
38 };
39
40 void drawRect(GraphicsContext* context, RenderObject* renderer, PaintPhase phase, const FloatRect& bound)
41 {
42     DrawingRecorder drawingRecorder(context, renderer, phase, bound);
43     IntRect rect(0, 0, 10, 10);
44     context->drawRect(rect);
45 }
46
47 void drawClippedRect(GraphicsContext* context, RenderView* renderView, PaintPhase phase, const FloatRect& bound)
48 {
49     IntRect rect(1, 1, 9, 9);
50     ClipRect clipRect(rect);
51     ClipRecorder clipRecorder(renderView->compositor()->rootRenderLayer(), context, DisplayItem::ClipLayerForeground, clipRect);
52     drawRect(context, renderView, phase, bound);
53 }
54
55 TEST_F(ViewDisplayListTest, ViewDisplayListTest_NestedRecorders)
56 {
57     GraphicsContext* context = new GraphicsContext(nullptr);
58     FloatRect bound = renderView()->viewRect();
59
60     drawClippedRect(context, renderView(), PaintPhaseForeground, bound);
61     EXPECT_EQ((size_t)3, renderView()->viewDisplayList().paintList().size());
62
63     // TODO(schenney): Check that the IDs are what we expect.
64 }
65
66 TEST_F(ViewDisplayListTest, ViewDisplayListTest_UpdateBasic)
67 {
68     setBodyInnerHTML("<div id='first'><div id='second'></div></div>");
69     RenderObject* first = document().body()->firstChild()->renderer();
70     RenderObject* second = document().body()->firstChild()->firstChild()->renderer();
71     GraphicsContext* context = new GraphicsContext(nullptr);
72
73     drawRect(context, first, PaintPhaseBlockBackground, FloatRect(100, 100, 300, 300));
74     drawRect(context, second, PaintPhaseChildBlockBackground, FloatRect(100, 100, 200, 200));
75     drawRect(context, first, PaintPhaseOutline, FloatRect(100, 100, 300, 300));
76
77     EXPECT_EQ((size_t)3, renderView()->viewDisplayList().paintList().size());
78
79     renderView()->viewDisplayList().invalidate(second);
80     drawRect(context, first, PaintPhaseBlockBackground, FloatRect(100, 100, 300, 300));
81     drawRect(context, first, PaintPhaseOutline, FloatRect(100, 100, 300, 300));
82     EXPECT_EQ((size_t)2, renderView()->viewDisplayList().paintList().size());
83 }
84
85 TEST_F(ViewDisplayListTest, ViewDisplayListTest_UpdateSwapOrder)
86 {
87     setBodyInnerHTML("<div id='first'><div id='second'></div></div><div id='unaffected'></div>");
88     RenderObject* first = document().body()->firstChild()->renderer();
89     RenderObject* second = document().body()->firstChild()->firstChild()->renderer();
90     RenderObject* unaffected = document().body()->firstChild()->nextSibling()->renderer();
91     GraphicsContext* context = new GraphicsContext(nullptr);
92
93     drawRect(context, first, PaintPhaseBlockBackground, FloatRect(100, 100, 100, 100));
94     drawRect(context, second, PaintPhaseBlockBackground, FloatRect(100, 100, 50, 200));
95     drawRect(context, unaffected, PaintPhaseBlockBackground, FloatRect(300, 300, 10, 10));
96
97     const PaintList& firstList = renderView()->viewDisplayList().paintList();
98     EXPECT_EQ((size_t)3, firstList.size());
99     EXPECT_EQ(first, firstList[0]->renderer());
100     EXPECT_EQ(second, firstList[1]->renderer());
101     EXPECT_EQ(unaffected, firstList[2]->renderer());
102
103     renderView()->viewDisplayList().invalidate(second);
104     drawRect(context, second, PaintPhaseBlockBackground, FloatRect(100, 100, 50, 200));
105     drawRect(context, first, PaintPhaseBlockBackground, FloatRect(100, 100, 100, 100));
106
107     const PaintList& secondList = renderView()->viewDisplayList().paintList();
108     EXPECT_EQ((size_t)3, secondList.size());
109     EXPECT_EQ(second, secondList[0]->renderer());
110     EXPECT_EQ(first, secondList[1]->renderer());
111     EXPECT_EQ(unaffected, secondList[2]->renderer());
112 }
113
114 TEST_F(ViewDisplayListTest, ViewDisplayListTest_UpdateNewItemInMiddle)
115 {
116     setBodyInnerHTML("<div id='first'><div id='second'><div id='third'></div></div></div>");
117     RenderObject* first = document().body()->firstChild()->renderer();
118     RenderObject* second = document().body()->firstChild()->firstChild()->renderer();
119     RenderObject* third = document().body()->firstChild()->firstChild()->firstChild()->renderer();
120     GraphicsContext* context = new GraphicsContext(nullptr);
121
122     drawRect(context, first, PaintPhaseBlockBackground, FloatRect(100, 100, 100, 100));
123     drawRect(context, second, PaintPhaseBlockBackground, FloatRect(100, 100, 50, 200));
124
125     const PaintList& firstList = renderView()->viewDisplayList().paintList();
126     EXPECT_EQ((size_t)2, firstList.size());
127     EXPECT_EQ(first, firstList[0]->renderer());
128     EXPECT_EQ(second, firstList[1]->renderer());
129
130     renderView()->viewDisplayList().invalidate(third);
131     drawRect(context, first, PaintPhaseBlockBackground, FloatRect(100, 100, 100, 100));
132     drawRect(context, third, PaintPhaseBlockBackground, FloatRect(125, 100, 200, 50));
133     drawRect(context, second, PaintPhaseBlockBackground, FloatRect(100, 100, 50, 200));
134
135     const PaintList& secondList = renderView()->viewDisplayList().paintList();
136     EXPECT_EQ((size_t)3, secondList.size());
137     EXPECT_EQ(first, secondList[0]->renderer());
138     EXPECT_EQ(third, secondList[1]->renderer());
139     EXPECT_EQ(second, secondList[2]->renderer());
140 }
141
142 TEST_F(ViewDisplayListTest, ViewDisplayListTest_UpdateInvalidationWithPhases)
143 {
144     setBodyInnerHTML("<div id='first'><div id='second'></div></div><div id='third'></div>");
145     RenderObject* first = document().body()->firstChild()->renderer();
146     RenderObject* second = document().body()->firstChild()->firstChild()->renderer();
147     RenderObject* third = document().body()->firstChild()->nextSibling()->renderer();
148     GraphicsContext* context = new GraphicsContext(nullptr);
149
150     drawRect(context, first, PaintPhaseBlockBackground, FloatRect(100, 100, 100, 100));
151     drawRect(context, second, PaintPhaseBlockBackground, FloatRect(100, 100, 50, 200));
152     drawRect(context, third, PaintPhaseBlockBackground, FloatRect(300, 100, 50, 50));
153     drawRect(context, first, PaintPhaseForeground, FloatRect(100, 100, 100, 100));
154     drawRect(context, second, PaintPhaseForeground, FloatRect(100, 100, 50, 200));
155     drawRect(context, third, PaintPhaseForeground, FloatRect(300, 100, 50, 50));
156     drawRect(context, first, PaintPhaseOutline, FloatRect(100, 100, 100, 100));
157     drawRect(context, second, PaintPhaseOutline, FloatRect(100, 100, 50, 200));
158     drawRect(context, third, PaintPhaseOutline, FloatRect(300, 100, 50, 50));
159
160     const PaintList& firstList = renderView()->viewDisplayList().paintList();
161     EXPECT_EQ((size_t)9, firstList.size());
162     for (int item = 0; item < 9; item += 3) {
163         EXPECT_EQ(first, firstList[item % 3 + 0]->renderer());
164         EXPECT_EQ(second, firstList[item % 3 + 1]->renderer());
165         EXPECT_EQ(third, firstList[item % 3 + 2]->renderer());
166     }
167
168     renderView()->viewDisplayList().invalidate(second);
169     drawRect(context, first, PaintPhaseBlockBackground, FloatRect(100, 100, 100, 100));
170     drawRect(context, second, PaintPhaseBlockBackground, FloatRect(100, 100, 50, 200));
171     drawRect(context, first, PaintPhaseForeground, FloatRect(100, 100, 100, 100));
172     drawRect(context, second, PaintPhaseForeground, FloatRect(100, 100, 50, 200));
173     drawRect(context, first, PaintPhaseOutline, FloatRect(100, 100, 100, 100));
174     drawRect(context, second, PaintPhaseOutline, FloatRect(100, 100, 50, 200));
175
176     const PaintList& secondList = renderView()->viewDisplayList().paintList();
177     EXPECT_EQ((size_t)9, secondList.size());
178     for (int item = 0; item < 9; item += 3) {
179         EXPECT_EQ(first, secondList[item % 3 + 0]->renderer());
180         EXPECT_EQ(second, secondList[item % 3 + 1]->renderer());
181         EXPECT_EQ(third, secondList[item % 3 + 2]->renderer());
182     }
183
184     renderView()->viewDisplayList().invalidate(second);
185     const PaintList& thirdList = renderView()->viewDisplayList().paintList();
186     EXPECT_EQ((size_t)6, thirdList.size());
187     for (int item = 0; item < 6; item += 2) {
188         EXPECT_EQ(first, thirdList[item % 2 + 0]->renderer());
189         EXPECT_EQ(third, thirdList[item % 2 + 1]->renderer());
190     }
191 }
192
193 TEST_F(ViewDisplayListTest, ViewDisplayListTest_UpdateAddFirstNoOverlap)
194 {
195     setBodyInnerHTML("<div id='first'></div><div id='second'></div>");
196     RenderObject* first = document().body()->firstChild()->renderer();
197     RenderObject* second = document().body()->firstChild()->nextSibling()->renderer();
198     GraphicsContext* context = new GraphicsContext(nullptr);
199
200     drawRect(context, second, PaintPhaseBlockBackground, FloatRect(200, 200, 50, 50));
201     drawRect(context, second, PaintPhaseOutline, FloatRect(200, 200, 50, 50));
202
203     const PaintList& firstList = renderView()->viewDisplayList().paintList();
204     EXPECT_EQ((size_t)2, firstList.size());
205     EXPECT_EQ(second, firstList[0]->renderer());
206     EXPECT_EQ(second, firstList[1]->renderer());
207
208     renderView()->viewDisplayList().invalidate(first);
209     drawRect(context, first, PaintPhaseBlockBackground, FloatRect(100, 100, 50, 50));
210     drawRect(context, first, PaintPhaseOutline, FloatRect(100, 100, 50, 50));
211
212     const PaintList& secondList = renderView()->viewDisplayList().paintList();
213     EXPECT_EQ((size_t)4, secondList.size());
214     EXPECT_EQ(first, secondList[0]->renderer());
215     EXPECT_EQ(first, secondList[1]->renderer());
216     EXPECT_EQ(second, secondList[2]->renderer());
217     EXPECT_EQ(second, secondList[3]->renderer());
218
219     renderView()->viewDisplayList().invalidate(first);
220     const PaintList& thirdList = renderView()->viewDisplayList().paintList();
221     EXPECT_EQ((size_t)2, thirdList.size());
222     EXPECT_EQ(second, thirdList[0]->renderer());
223     EXPECT_EQ(second, thirdList[1]->renderer());
224 }
225
226 TEST_F(ViewDisplayListTest, ViewDisplayListTest_UpdateAddFirstOverlap)
227 {
228     setBodyInnerHTML("<div id='first'></div><div id='second'></div>");
229     RenderObject* first = document().body()->firstChild()->renderer();
230     RenderObject* second = document().body()->firstChild()->nextSibling()->renderer();
231     GraphicsContext* context = new GraphicsContext(nullptr);
232
233     drawRect(context, second, PaintPhaseBlockBackground, FloatRect(200, 200, 50, 50));
234     drawRect(context, second, PaintPhaseOutline, FloatRect(200, 200, 50, 50));
235
236     const PaintList& firstList = renderView()->viewDisplayList().paintList();
237     EXPECT_EQ((size_t)2, firstList.size());
238     EXPECT_EQ(second, firstList[0]->renderer());
239     EXPECT_EQ(second, firstList[1]->renderer());
240
241     renderView()->viewDisplayList().invalidate(first);
242     renderView()->viewDisplayList().invalidate(second);
243     drawRect(context, first, PaintPhaseBlockBackground, FloatRect(100, 100, 150, 150));
244     drawRect(context, first, PaintPhaseOutline, FloatRect(100, 100, 150, 150));
245     drawRect(context, second, PaintPhaseBlockBackground, FloatRect(200, 200, 50, 50));
246     drawRect(context, second, PaintPhaseOutline, FloatRect(200, 200, 50, 50));
247
248     const PaintList& secondList = renderView()->viewDisplayList().paintList();
249     EXPECT_EQ((size_t)4, secondList.size());
250     EXPECT_EQ(first, secondList[0]->renderer());
251     EXPECT_EQ(first, secondList[1]->renderer());
252     EXPECT_EQ(second, secondList[2]->renderer());
253     EXPECT_EQ(second, secondList[3]->renderer());
254
255     renderView()->viewDisplayList().invalidate(first);
256     drawRect(context, second, PaintPhaseBlockBackground, FloatRect(200, 200, 50, 50));
257     drawRect(context, second, PaintPhaseOutline, FloatRect(200, 200, 50, 50));
258
259     const PaintList& thirdList = renderView()->viewDisplayList().paintList();
260     EXPECT_EQ((size_t)2, thirdList.size());
261     EXPECT_EQ(second, thirdList[0]->renderer());
262     EXPECT_EQ(second, thirdList[1]->renderer());
263 }
264
265 TEST_F(ViewDisplayListTest, ViewDisplayListTest_UpdateAddLastNoOverlap)
266 {
267     setBodyInnerHTML("<div id='first'></div><div id='second'></div>");
268     RenderObject* first = document().body()->firstChild()->renderer();
269     RenderObject* second = document().body()->firstChild()->nextSibling()->renderer();
270     GraphicsContext* context = new GraphicsContext(nullptr);
271
272     drawRect(context, first, PaintPhaseBlockBackground, FloatRect(100, 100, 50, 50));
273     drawRect(context, first, PaintPhaseOutline, FloatRect(100, 100, 50, 50));
274
275     const PaintList& firstList = renderView()->viewDisplayList().paintList();
276     EXPECT_EQ((size_t)2, firstList.size());
277     EXPECT_EQ(first, firstList[0]->renderer());
278     EXPECT_EQ(first, firstList[1]->renderer());
279
280     renderView()->viewDisplayList().invalidate(second);
281     drawRect(context, second, PaintPhaseBlockBackground, FloatRect(200, 200, 50, 50));
282     drawRect(context, second, PaintPhaseOutline, FloatRect(200, 200, 50, 50));
283
284     const PaintList& secondList = renderView()->viewDisplayList().paintList();
285     EXPECT_EQ((size_t)4, secondList.size());
286     EXPECT_EQ(second, secondList[0]->renderer());
287     EXPECT_EQ(second, secondList[1]->renderer());
288     EXPECT_EQ(first, secondList[2]->renderer());
289     EXPECT_EQ(first, secondList[3]->renderer());
290
291     renderView()->viewDisplayList().invalidate(second);
292     const PaintList& thirdList = renderView()->viewDisplayList().paintList();
293     EXPECT_EQ((size_t)2, thirdList.size());
294     EXPECT_EQ(first, thirdList[0]->renderer());
295     EXPECT_EQ(first, thirdList[1]->renderer());
296 }
297
298 TEST_F(ViewDisplayListTest, ViewDisplayListTest_UpdateAddLastOverlap)
299 {
300     setBodyInnerHTML("<div id='first'></div><div id='second'></div>");
301     RenderObject* first = document().body()->firstChild()->renderer();
302     RenderObject* second = document().body()->firstChild()->nextSibling()->renderer();
303     GraphicsContext* context = new GraphicsContext(nullptr);
304
305     drawRect(context, first, PaintPhaseBlockBackground, FloatRect(100, 100, 150, 150));
306     drawRect(context, first, PaintPhaseOutline, FloatRect(100, 100, 150, 150));
307
308     const PaintList& firstList = renderView()->viewDisplayList().paintList();
309     EXPECT_EQ((size_t)2, firstList.size());
310     EXPECT_EQ(first, firstList[0]->renderer());
311     EXPECT_EQ(first, firstList[1]->renderer());
312
313     renderView()->viewDisplayList().invalidate(first);
314     renderView()->viewDisplayList().invalidate(second);
315     drawRect(context, first, PaintPhaseBlockBackground, FloatRect(100, 100, 150, 150));
316     drawRect(context, first, PaintPhaseOutline, FloatRect(100, 100, 150, 150));
317     drawRect(context, second, PaintPhaseBlockBackground, FloatRect(200, 200, 50, 50));
318     drawRect(context, second, PaintPhaseOutline, FloatRect(200, 200, 50, 50));
319
320     const PaintList& secondList = renderView()->viewDisplayList().paintList();
321     EXPECT_EQ((size_t)4, secondList.size());
322     EXPECT_EQ(first, secondList[0]->renderer());
323     EXPECT_EQ(first, secondList[1]->renderer());
324     EXPECT_EQ(second, secondList[2]->renderer());
325     EXPECT_EQ(second, secondList[3]->renderer());
326
327     renderView()->viewDisplayList().invalidate(first);
328     renderView()->viewDisplayList().invalidate(second);
329     drawRect(context, first, PaintPhaseBlockBackground, FloatRect(100, 100, 150, 150));
330     drawRect(context, first, PaintPhaseOutline, FloatRect(100, 100, 150, 150));
331
332     const PaintList& thirdList = renderView()->viewDisplayList().paintList();
333     EXPECT_EQ((size_t)2, thirdList.size());
334     EXPECT_EQ(first, thirdList[0]->renderer());
335     EXPECT_EQ(first, thirdList[1]->renderer());
336 }
337
338 }
339
340 }