OLD | NEW |
| (Empty) |
1 // Copyright 2011 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 | |
7 #include "CCDamageTracker.h" | |
8 | |
9 #include "CCGeometryTestUtils.h" | |
10 #include "CCLayerImpl.h" | |
11 #include "CCLayerSorter.h" | |
12 #include "CCLayerTreeHostCommon.h" | |
13 #include "CCMathUtil.h" | |
14 #include "CCSingleThreadProxy.h" | |
15 #include "testing/gtest/include/gtest/gtest.h" | |
16 #include <public/WebFilterOperation.h> | |
17 #include <public/WebFilterOperations.h> | |
18 | |
19 using namespace cc; | |
20 using namespace WebKit; | |
21 using namespace WTF; | |
22 using namespace WebKitTests; | |
23 | |
24 namespace { | |
25 | |
26 void executeCalculateDrawTransformsAndVisibility(CCLayerImpl* root, std::vector<
CCLayerImpl*>& renderSurfaceLayerList) | |
27 { | |
28 CCLayerSorter layerSorter; | |
29 int dummyMaxTextureSize = 512; | |
30 | |
31 // Sanity check: The test itself should create the root layer's render surfa
ce, so | |
32 // that the surface (and its damage tracker) can persist acros
s multiple | |
33 // calls to this function. | |
34 ASSERT_TRUE(root->renderSurface()); | |
35 ASSERT_FALSE(renderSurfaceLayerList.size()); | |
36 | |
37 CCLayerTreeHostCommon::calculateDrawTransforms(root, root->bounds(), 1, &lay
erSorter, dummyMaxTextureSize, renderSurfaceLayerList); | |
38 } | |
39 | |
40 void clearDamageForAllSurfaces(CCLayerImpl* layer) | |
41 { | |
42 if (layer->renderSurface()) | |
43 layer->renderSurface()->damageTracker()->didDrawDamagedArea(); | |
44 | |
45 // Recursively clear damage for any existing surface. | |
46 for (size_t i = 0; i < layer->children().size(); ++i) | |
47 clearDamageForAllSurfaces(layer->children()[i]); | |
48 } | |
49 | |
50 void emulateDrawingOneFrame(CCLayerImpl* root) | |
51 { | |
52 // This emulates only the steps that are relevant to testing the damage trac
ker: | |
53 // 1. computing the render passes and layerlists | |
54 // 2. updating all damage trackers in the correct order | |
55 // 3. resetting all updateRects and propertyChanged flags for all layers a
nd surfaces. | |
56 | |
57 std::vector<CCLayerImpl*> renderSurfaceLayerList; | |
58 executeCalculateDrawTransformsAndVisibility(root, renderSurfaceLayerList); | |
59 | |
60 // Iterate back-to-front, so that damage correctly propagates from descendan
t surfaces to ancestors. | |
61 for (int i = renderSurfaceLayerList.size() - 1; i >= 0; --i) { | |
62 CCRenderSurface* targetSurface = renderSurfaceLayerList[i]->renderSurfac
e(); | |
63 targetSurface->damageTracker()->updateDamageTrackingState(targetSurface-
>layerList(), targetSurface->owningLayerId(), targetSurface->surfacePropertyChan
gedOnlyFromDescendant(), targetSurface->contentRect(), renderSurfaceLayerList[i]
->maskLayer(), renderSurfaceLayerList[i]->filters()); | |
64 } | |
65 | |
66 root->resetAllChangeTrackingForSubtree(); | |
67 } | |
68 | |
69 scoped_ptr<CCLayerImpl> createTestTreeWithOneSurface() | |
70 { | |
71 scoped_ptr<CCLayerImpl> root = CCLayerImpl::create(1); | |
72 scoped_ptr<CCLayerImpl> child = CCLayerImpl::create(2); | |
73 | |
74 root->setPosition(FloatPoint::zero()); | |
75 root->setAnchorPoint(FloatPoint::zero()); | |
76 root->setBounds(IntSize(500, 500)); | |
77 root->setContentBounds(IntSize(500, 500)); | |
78 root->setDrawsContent(true); | |
79 root->createRenderSurface(); | |
80 root->renderSurface()->setContentRect(IntRect(IntPoint(), IntSize(500, 500))
); | |
81 | |
82 child->setPosition(FloatPoint(100, 100)); | |
83 child->setAnchorPoint(FloatPoint::zero()); | |
84 child->setBounds(IntSize(30, 30)); | |
85 child->setContentBounds(IntSize(30, 30)); | |
86 child->setDrawsContent(true); | |
87 root->addChild(child.Pass()); | |
88 | |
89 return root.Pass(); | |
90 } | |
91 | |
92 scoped_ptr<CCLayerImpl> createTestTreeWithTwoSurfaces() | |
93 { | |
94 // This test tree has two render surfaces: one for the root, and one for | |
95 // child1. Additionally, the root has a second child layer, and child1 has t
wo | |
96 // children of its own. | |
97 | |
98 scoped_ptr<CCLayerImpl> root = CCLayerImpl::create(1); | |
99 scoped_ptr<CCLayerImpl> child1 = CCLayerImpl::create(2); | |
100 scoped_ptr<CCLayerImpl> child2 = CCLayerImpl::create(3); | |
101 scoped_ptr<CCLayerImpl> grandChild1 = CCLayerImpl::create(4); | |
102 scoped_ptr<CCLayerImpl> grandChild2 = CCLayerImpl::create(5); | |
103 | |
104 root->setPosition(FloatPoint::zero()); | |
105 root->setAnchorPoint(FloatPoint::zero()); | |
106 root->setBounds(IntSize(500, 500)); | |
107 root->setContentBounds(IntSize(500, 500)); | |
108 root->setDrawsContent(true); | |
109 root->createRenderSurface(); | |
110 root->renderSurface()->setContentRect(IntRect(IntPoint(), IntSize(500, 500))
); | |
111 | |
112 child1->setPosition(FloatPoint(100, 100)); | |
113 child1->setAnchorPoint(FloatPoint::zero()); | |
114 child1->setBounds(IntSize(30, 30)); | |
115 child1->setContentBounds(IntSize(30, 30)); | |
116 child1->setOpacity(0.5); // with a child that drawsContent, this will cause
the layer to create its own renderSurface. | |
117 child1->setDrawsContent(false); // this layer does not draw, but is intended
to create its own renderSurface. | |
118 | |
119 child2->setPosition(FloatPoint(11, 11)); | |
120 child2->setAnchorPoint(FloatPoint::zero()); | |
121 child2->setBounds(IntSize(18, 18)); | |
122 child2->setContentBounds(IntSize(18, 18)); | |
123 child2->setDrawsContent(true); | |
124 | |
125 grandChild1->setPosition(FloatPoint(200, 200)); | |
126 grandChild1->setAnchorPoint(FloatPoint::zero()); | |
127 grandChild1->setBounds(IntSize(6, 8)); | |
128 grandChild1->setContentBounds(IntSize(6, 8)); | |
129 grandChild1->setDrawsContent(true); | |
130 | |
131 grandChild2->setPosition(FloatPoint(190, 190)); | |
132 grandChild2->setAnchorPoint(FloatPoint::zero()); | |
133 grandChild2->setBounds(IntSize(6, 8)); | |
134 grandChild2->setContentBounds(IntSize(6, 8)); | |
135 grandChild2->setDrawsContent(true); | |
136 | |
137 child1->addChild(grandChild1.Pass()); | |
138 child1->addChild(grandChild2.Pass()); | |
139 root->addChild(child1.Pass()); | |
140 root->addChild(child2.Pass()); | |
141 | |
142 return root.Pass(); | |
143 } | |
144 | |
145 scoped_ptr<CCLayerImpl> createAndSetUpTestTreeWithOneSurface() | |
146 { | |
147 scoped_ptr<CCLayerImpl> root = createTestTreeWithOneSurface(); | |
148 | |
149 // Setup includes going past the first frame which always damages everything
, so | |
150 // that we can actually perform specific tests. | |
151 emulateDrawingOneFrame(root.get()); | |
152 | |
153 return root.Pass(); | |
154 } | |
155 | |
156 scoped_ptr<CCLayerImpl> createAndSetUpTestTreeWithTwoSurfaces() | |
157 { | |
158 scoped_ptr<CCLayerImpl> root = createTestTreeWithTwoSurfaces(); | |
159 | |
160 // Setup includes going past the first frame which always damages everything
, so | |
161 // that we can actually perform specific tests. | |
162 emulateDrawingOneFrame(root.get()); | |
163 | |
164 return root.Pass(); | |
165 } | |
166 | |
167 class CCDamageTrackerTest : public testing::Test { | |
168 private: | |
169 // For testing purposes, fake that we are on the impl thread. | |
170 DebugScopedSetImplThread setImplThread; | |
171 }; | |
172 | |
173 TEST_F(CCDamageTrackerTest, sanityCheckTestTreeWithOneSurface) | |
174 { | |
175 // Sanity check that the simple test tree will actually produce the expected
render | |
176 // surfaces and layer lists. | |
177 | |
178 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithOneSurface(); | |
179 | |
180 EXPECT_EQ(2u, root->renderSurface()->layerList().size()); | |
181 EXPECT_EQ(1, root->renderSurface()->layerList()[0]->id()); | |
182 EXPECT_EQ(2, root->renderSurface()->layerList()[1]->id()); | |
183 | |
184 FloatRect rootDamageRect = root->renderSurface()->damageTracker()->currentDa
mageRect(); | |
185 EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 500, 500), rootDamageRect); | |
186 } | |
187 | |
188 TEST_F(CCDamageTrackerTest, sanityCheckTestTreeWithTwoSurfaces) | |
189 { | |
190 // Sanity check that the complex test tree will actually produce the expecte
d render | |
191 // surfaces and layer lists. | |
192 | |
193 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces(); | |
194 | |
195 CCLayerImpl* child1 = root->children()[0]; | |
196 CCLayerImpl* child2 = root->children()[1]; | |
197 FloatRect childDamageRect = child1->renderSurface()->damageTracker()->curren
tDamageRect(); | |
198 FloatRect rootDamageRect = root->renderSurface()->damageTracker()->currentDa
mageRect(); | |
199 | |
200 ASSERT_TRUE(child1->renderSurface()); | |
201 EXPECT_FALSE(child2->renderSurface()); | |
202 EXPECT_EQ(3u, root->renderSurface()->layerList().size()); | |
203 EXPECT_EQ(2u, child1->renderSurface()->layerList().size()); | |
204 | |
205 // The render surface for child1 only has a contentRect that encloses grandC
hild1 and grandChild2, because child1 does not draw content. | |
206 EXPECT_FLOAT_RECT_EQ(FloatRect(190, 190, 16, 18), childDamageRect); | |
207 EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 500, 500), rootDamageRect); | |
208 } | |
209 | |
210 TEST_F(CCDamageTrackerTest, verifyDamageForUpdateRects) | |
211 { | |
212 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithOneSurface(); | |
213 CCLayerImpl* child = root->children()[0]; | |
214 | |
215 // CASE 1: Setting the update rect should cause the corresponding damage to
the surface. | |
216 // | |
217 clearDamageForAllSurfaces(root.get()); | |
218 child->setUpdateRect(FloatRect(10, 11, 12, 13)); | |
219 emulateDrawingOneFrame(root.get()); | |
220 | |
221 // Damage position on the surface should be: position of updateRect (10, 11)
relative to the child (100, 100). | |
222 FloatRect rootDamageRect = root->renderSurface()->damageTracker()->currentDa
mageRect(); | |
223 EXPECT_FLOAT_RECT_EQ(FloatRect(110, 111, 12, 13), rootDamageRect); | |
224 | |
225 // CASE 2: The same update rect twice in a row still produces the same damag
e. | |
226 // | |
227 clearDamageForAllSurfaces(root.get()); | |
228 child->setUpdateRect(FloatRect(10, 11, 12, 13)); | |
229 emulateDrawingOneFrame(root.get()); | |
230 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
231 EXPECT_FLOAT_RECT_EQ(FloatRect(110, 111, 12, 13), rootDamageRect); | |
232 | |
233 // CASE 3: Setting a different update rect should cause damage on the new up
date region, but no additional exposed old region. | |
234 // | |
235 clearDamageForAllSurfaces(root.get()); | |
236 child->setUpdateRect(FloatRect(20, 25, 1, 2)); | |
237 emulateDrawingOneFrame(root.get()); | |
238 | |
239 // Damage position on the surface should be: position of updateRect (20, 25)
relative to the child (100, 100). | |
240 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
241 EXPECT_FLOAT_RECT_EQ(FloatRect(120, 125, 1, 2), rootDamageRect); | |
242 } | |
243 | |
244 TEST_F(CCDamageTrackerTest, verifyDamageForPropertyChanges) | |
245 { | |
246 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithOneSurface(); | |
247 CCLayerImpl* child = root->children()[0]; | |
248 | |
249 // CASE 1: The layer's property changed flag takes priority over update rect
. | |
250 // | |
251 clearDamageForAllSurfaces(root.get()); | |
252 child->setUpdateRect(FloatRect(10, 11, 12, 13)); | |
253 child->setOpacity(0.5); | |
254 emulateDrawingOneFrame(root.get()); | |
255 | |
256 // Sanity check - we should not have accidentally created a separate render
surface for the translucent layer. | |
257 ASSERT_FALSE(child->renderSurface()); | |
258 ASSERT_EQ(2u, root->renderSurface()->layerList().size()); | |
259 | |
260 // Damage should be the entire child layer in targetSurface space. | |
261 FloatRect expectedRect = FloatRect(100, 100, 30, 30); | |
262 FloatRect rootDamageRect = root->renderSurface()->damageTracker()->currentDa
mageRect(); | |
263 EXPECT_FLOAT_RECT_EQ(expectedRect, rootDamageRect); | |
264 | |
265 // CASE 2: If a layer moves due to property change, it damages both the new
location | |
266 // and the old (exposed) location. The old location is the entire ol
d layer, | |
267 // not just the updateRect. | |
268 | |
269 // Cycle one frame of no change, just to sanity check that the next rect is
not because of the old damage state. | |
270 clearDamageForAllSurfaces(root.get()); | |
271 emulateDrawingOneFrame(root.get()); | |
272 EXPECT_TRUE(root->renderSurface()->damageTracker()->currentDamageRect().isEm
pty()); | |
273 | |
274 // Then, test the actual layer movement. | |
275 clearDamageForAllSurfaces(root.get()); | |
276 child->setPosition(FloatPoint(200, 230)); | |
277 emulateDrawingOneFrame(root.get()); | |
278 | |
279 // Expect damage to be the combination of the previous one and the new one. | |
280 expectedRect.uniteIfNonZero(FloatRect(200, 230, 30, 30)); | |
281 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
282 EXPECT_FLOAT_RECT_EQ(expectedRect, rootDamageRect); | |
283 } | |
284 | |
285 TEST_F(CCDamageTrackerTest, verifyDamageForTransformedLayer) | |
286 { | |
287 // If a layer is transformed, the damage rect should still enclose the entir
e | |
288 // transformed layer. | |
289 | |
290 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithOneSurface(); | |
291 CCLayerImpl* child = root->children()[0]; | |
292 | |
293 WebTransformationMatrix rotation; | |
294 rotation.rotate(45); | |
295 | |
296 clearDamageForAllSurfaces(root.get()); | |
297 child->setAnchorPoint(FloatPoint(0.5, 0.5)); | |
298 child->setPosition(FloatPoint(85, 85)); | |
299 emulateDrawingOneFrame(root.get()); | |
300 | |
301 // Sanity check that the layer actually moved to (85, 85), damaging its old
location and new location. | |
302 FloatRect rootDamageRect = root->renderSurface()->damageTracker()->currentDa
mageRect(); | |
303 EXPECT_FLOAT_RECT_EQ(FloatRect(85, 85, 45, 45), rootDamageRect); | |
304 | |
305 // With the anchor on the layer's center, now we can test the rotation more | |
306 // intuitively, since it applies about the layer's anchor. | |
307 clearDamageForAllSurfaces(root.get()); | |
308 child->setTransform(rotation); | |
309 emulateDrawingOneFrame(root.get()); | |
310 | |
311 // Since the child layer is square, rotation by 45 degrees about the center
should | |
312 // increase the size of the expected rect by sqrt(2), centered around (100,
100). The | |
313 // old exposed region should be fully contained in the new region. | |
314 double expectedWidth = 30 * sqrt(2.0); | |
315 double expectedPosition = 100 - 0.5 * expectedWidth; | |
316 FloatRect expectedRect(expectedPosition, expectedPosition, expectedWidth, ex
pectedWidth); | |
317 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
318 EXPECT_FLOAT_RECT_EQ(expectedRect, rootDamageRect); | |
319 } | |
320 | |
321 TEST_F(CCDamageTrackerTest, verifyDamageForPerspectiveClippedLayer) | |
322 { | |
323 // If a layer has a perspective transform that causes w < 0, then not clippi
ng the | |
324 // layer can cause an invalid damage rect. This test checks that the w < 0 c
ase is | |
325 // tracked properly. | |
326 // | |
327 // The transform is constructed so that if w < 0 clipping is not performed,
the | |
328 // incorrect rect will be very small, specifically: position (500.972504, 49
8.544617) and size 0.056610 x 2.910767. | |
329 // Instead, the correctly transformed rect should actually be very huge (i.e
. in theory, -infinity on the left), | |
330 // and positioned so that the right-most bound rect will be approximately 50
1 units in root surface space. | |
331 // | |
332 | |
333 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithOneSurface(); | |
334 CCLayerImpl* child = root->children()[0]; | |
335 | |
336 WebTransformationMatrix transform; | |
337 transform.translate3d(500, 500, 0); | |
338 transform.applyPerspective(1); | |
339 transform.rotate3d(0, 45, 0); | |
340 transform.translate3d(-50, -50, 0); | |
341 | |
342 // Set up the child | |
343 child->setPosition(FloatPoint(0, 0)); | |
344 child->setBounds(IntSize(100, 100)); | |
345 child->setContentBounds(IntSize(100, 100)); | |
346 child->setTransform(transform); | |
347 emulateDrawingOneFrame(root.get()); | |
348 | |
349 // Sanity check that the child layer's bounds would actually get clipped by
w < 0, | |
350 // otherwise this test is not actually testing the intended scenario. | |
351 FloatQuad testQuad(FloatRect(FloatPoint::zero(), FloatSize(100, 100))); | |
352 bool clipped = false; | |
353 CCMathUtil::mapQuad(transform, testQuad, clipped); | |
354 EXPECT_TRUE(clipped); | |
355 | |
356 // Damage the child without moving it. | |
357 clearDamageForAllSurfaces(root.get()); | |
358 child->setOpacity(0.5); | |
359 emulateDrawingOneFrame(root.get()); | |
360 | |
361 // The expected damage should cover the entire root surface (500x500), but w
e don't | |
362 // care whether the damage rect was clamped or is larger than the surface fo
r this test. | |
363 FloatRect rootDamageRect = root->renderSurface()->damageTracker()->currentDa
mageRect(); | |
364 FloatRect damageWeCareAbout = FloatRect(FloatPoint::zero(), FloatSize(500, 5
00)); | |
365 EXPECT_TRUE(rootDamageRect.contains(damageWeCareAbout)); | |
366 } | |
367 | |
368 TEST_F(CCDamageTrackerTest, verifyDamageForBlurredSurface) | |
369 { | |
370 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithOneSurface(); | |
371 CCLayerImpl* child = root->children()[0]; | |
372 | |
373 WebFilterOperations filters; | |
374 filters.append(WebFilterOperation::createBlurFilter(5)); | |
375 int outsetTop, outsetRight, outsetBottom, outsetLeft; | |
376 filters.getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft); | |
377 | |
378 // Setting the filter will damage the whole surface. | |
379 clearDamageForAllSurfaces(root.get()); | |
380 root->setFilters(filters); | |
381 emulateDrawingOneFrame(root.get()); | |
382 | |
383 // Setting the update rect should cause the corresponding damage to the surf
ace, blurred based on the size of the blur filter. | |
384 clearDamageForAllSurfaces(root.get()); | |
385 child->setUpdateRect(FloatRect(10, 11, 12, 13)); | |
386 emulateDrawingOneFrame(root.get()); | |
387 | |
388 // Damage position on the surface should be: position of updateRect (10, 11)
relative to the child (100, 100), but expanded by the blur outsets. | |
389 FloatRect rootDamageRect = root->renderSurface()->damageTracker()->currentDa
mageRect(); | |
390 FloatRect expectedDamageRect = FloatRect(110, 111, 12, 13); | |
391 expectedDamageRect.move(-outsetLeft, -outsetTop); | |
392 expectedDamageRect.expand(outsetLeft + outsetRight, outsetTop + outsetBottom
); | |
393 EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect); | |
394 } | |
395 | |
396 TEST_F(CCDamageTrackerTest, verifyDamageForBackgroundBlurredChild) | |
397 { | |
398 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces(); | |
399 CCLayerImpl* child1 = root->children()[0]; | |
400 CCLayerImpl* child2 = root->children()[1]; | |
401 | |
402 // Allow us to set damage on child1 too. | |
403 child1->setDrawsContent(true); | |
404 | |
405 WebFilterOperations filters; | |
406 filters.append(WebFilterOperation::createBlurFilter(2)); | |
407 int outsetTop, outsetRight, outsetBottom, outsetLeft; | |
408 filters.getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft); | |
409 | |
410 // Setting the filter will damage the whole surface. | |
411 clearDamageForAllSurfaces(root.get()); | |
412 child1->setBackgroundFilters(filters); | |
413 emulateDrawingOneFrame(root.get()); | |
414 | |
415 // CASE 1: Setting the update rect should cause the corresponding damage to | |
416 // the surface, blurred based on the size of the child's background blur | |
417 // filter. | |
418 clearDamageForAllSurfaces(root.get()); | |
419 root->setUpdateRect(FloatRect(297, 297, 2, 2)); | |
420 emulateDrawingOneFrame(root.get()); | |
421 | |
422 FloatRect rootDamageRect = root->renderSurface()->damageTracker()->currentDa
mageRect(); | |
423 // Damage position on the surface should be a composition of the damage on t
he root and on child2. | |
424 // Damage on the root should be: position of updateRect (297, 297), but expa
nded by the blur outsets. | |
425 FloatRect expectedDamageRect = FloatRect(297, 297, 2, 2); | |
426 expectedDamageRect.move(-outsetLeft, -outsetTop); | |
427 expectedDamageRect.expand(outsetLeft + outsetRight, outsetTop + outsetBottom
); | |
428 EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect); | |
429 | |
430 // CASE 2: Setting the update rect should cause the corresponding damage to | |
431 // the surface, blurred based on the size of the child's background blur | |
432 // filter. Since the damage extends to the right/bottom outside of the | |
433 // blurred layer, only the left/top should end up expanded. | |
434 clearDamageForAllSurfaces(root.get()); | |
435 root->setUpdateRect(FloatRect(297, 297, 30, 30)); | |
436 emulateDrawingOneFrame(root.get()); | |
437 | |
438 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
439 // Damage position on the surface should be a composition of the damage on t
he root and on child2. | |
440 // Damage on the root should be: position of updateRect (297, 297), but expa
nded on the left/top | |
441 // by the blur outsets. | |
442 expectedDamageRect = FloatRect(297, 297, 30, 30); | |
443 expectedDamageRect.move(-outsetLeft, -outsetTop); | |
444 expectedDamageRect.expand(outsetLeft, outsetTop); | |
445 EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect); | |
446 | |
447 // CASE 3: Setting this update rect outside the blurred contentBounds of the
blurred | |
448 // child1 will not cause it to be expanded. | |
449 clearDamageForAllSurfaces(root.get()); | |
450 root->setUpdateRect(FloatRect(30, 30, 2, 2)); | |
451 emulateDrawingOneFrame(root.get()); | |
452 | |
453 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
454 // Damage on the root should be: position of updateRect (30, 30), not | |
455 // expanded. | |
456 expectedDamageRect = FloatRect(30, 30, 2, 2); | |
457 EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect); | |
458 | |
459 // CASE 4: Setting this update rect inside the blurred contentBounds but out
side the | |
460 // original contentBounds of the blurred child1 will cause it to be expanded
. | |
461 clearDamageForAllSurfaces(root.get()); | |
462 root->setUpdateRect(FloatRect(99, 99, 1, 1)); | |
463 emulateDrawingOneFrame(root.get()); | |
464 | |
465 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
466 // Damage on the root should be: position of updateRect (99, 99), expanded | |
467 // by the blurring on child1, but since it is 1 pixel outside the layer, the | |
468 // expanding should be reduced by 1. | |
469 expectedDamageRect = FloatRect(99, 99, 1, 1); | |
470 expectedDamageRect.move(-outsetLeft + 1, -outsetTop + 1); | |
471 expectedDamageRect.expand(outsetLeft + outsetRight - 1, outsetTop + outsetBo
ttom - 1); | |
472 EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect); | |
473 | |
474 // CASE 5: Setting the update rect on child2, which is above child1, will | |
475 // not get blurred by child1, so it does not need to get expanded. | |
476 clearDamageForAllSurfaces(root.get()); | |
477 child2->setUpdateRect(FloatRect(0, 0, 1, 1)); | |
478 emulateDrawingOneFrame(root.get()); | |
479 | |
480 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
481 // Damage on child2 should be: position of updateRect offset by the child's
position (11, 11), and not expanded by anything. | |
482 expectedDamageRect = FloatRect(11, 11, 1, 1); | |
483 EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect); | |
484 | |
485 // CASE 6: Setting the update rect on child1 will also blur the damage, so | |
486 // that any pixels needed for the blur are redrawn in the current frame. | |
487 clearDamageForAllSurfaces(root.get()); | |
488 child1->setUpdateRect(FloatRect(0, 0, 1, 1)); | |
489 emulateDrawingOneFrame(root.get()); | |
490 | |
491 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
492 // Damage on child1 should be: position of updateRect offset by the child's
position (100, 100), and expanded by the damage. | |
493 expectedDamageRect = FloatRect(100, 100, 1, 1); | |
494 expectedDamageRect.move(-outsetLeft, -outsetTop); | |
495 expectedDamageRect.expand(outsetLeft + outsetRight, outsetTop + outsetBottom
); | |
496 EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect); | |
497 } | |
498 | |
499 TEST_F(CCDamageTrackerTest, verifyDamageForAddingAndRemovingLayer) | |
500 { | |
501 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithOneSurface(); | |
502 CCLayerImpl* child1 = root->children()[0]; | |
503 | |
504 // CASE 1: Adding a new layer should cause the appropriate damage. | |
505 // | |
506 clearDamageForAllSurfaces(root.get()); | |
507 { | |
508 scoped_ptr<CCLayerImpl> child2 = CCLayerImpl::create(3); | |
509 child2->setPosition(FloatPoint(400, 380)); | |
510 child2->setAnchorPoint(FloatPoint::zero()); | |
511 child2->setBounds(IntSize(6, 8)); | |
512 child2->setContentBounds(IntSize(6, 8)); | |
513 child2->setDrawsContent(true); | |
514 root->addChild(child2.Pass()); | |
515 } | |
516 emulateDrawingOneFrame(root.get()); | |
517 | |
518 // Sanity check - all 3 layers should be on the same render surface; render
surfaces are tested elsewhere. | |
519 ASSERT_EQ(3u, root->renderSurface()->layerList().size()); | |
520 | |
521 FloatRect rootDamageRect = root->renderSurface()->damageTracker()->currentDa
mageRect(); | |
522 EXPECT_FLOAT_RECT_EQ(FloatRect(400, 380, 6, 8), rootDamageRect); | |
523 | |
524 // CASE 2: If the layer is removed, its entire old layer becomes exposed, no
t just the | |
525 // last update rect. | |
526 | |
527 // Advance one frame without damage so that we know the damage rect is not l
eftover from the previous case. | |
528 clearDamageForAllSurfaces(root.get()); | |
529 emulateDrawingOneFrame(root.get()); | |
530 EXPECT_TRUE(root->renderSurface()->damageTracker()->currentDamageRect().isEm
pty()); | |
531 | |
532 // Then, test removing child1. | |
533 child1->removeFromParent(); | |
534 emulateDrawingOneFrame(root.get()); | |
535 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
536 EXPECT_FLOAT_RECT_EQ(FloatRect(100, 100, 30, 30), rootDamageRect); | |
537 } | |
538 | |
539 TEST_F(CCDamageTrackerTest, verifyDamageForNewUnchangedLayer) | |
540 { | |
541 // If child2 is added to the layer tree, but it doesn't have any explicit da
mage of | |
542 // its own, it should still indeed damage the target surface. | |
543 | |
544 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithOneSurface(); | |
545 | |
546 clearDamageForAllSurfaces(root.get()); | |
547 { | |
548 scoped_ptr<CCLayerImpl> child2 = CCLayerImpl::create(3); | |
549 child2->setPosition(FloatPoint(400, 380)); | |
550 child2->setAnchorPoint(FloatPoint::zero()); | |
551 child2->setBounds(IntSize(6, 8)); | |
552 child2->setContentBounds(IntSize(6, 8)); | |
553 child2->setDrawsContent(true); | |
554 child2->resetAllChangeTrackingForSubtree(); | |
555 // Sanity check the initial conditions of the test, if these asserts tri
gger, it | |
556 // means the test no longer actually covers the intended scenario. | |
557 ASSERT_FALSE(child2->layerPropertyChanged()); | |
558 ASSERT_TRUE(child2->updateRect().isEmpty()); | |
559 root->addChild(child2.Pass()); | |
560 } | |
561 emulateDrawingOneFrame(root.get()); | |
562 | |
563 // Sanity check - all 3 layers should be on the same render surface; render
surfaces are tested elsewhere. | |
564 ASSERT_EQ(3u, root->renderSurface()->layerList().size()); | |
565 | |
566 FloatRect rootDamageRect = root->renderSurface()->damageTracker()->currentDa
mageRect(); | |
567 EXPECT_FLOAT_RECT_EQ(FloatRect(400, 380, 6, 8), rootDamageRect); | |
568 } | |
569 | |
570 TEST_F(CCDamageTrackerTest, verifyDamageForMultipleLayers) | |
571 { | |
572 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithOneSurface(); | |
573 CCLayerImpl* child1 = root->children()[0]; | |
574 | |
575 // In this test we don't want the above tree manipulation to be considered p
art of the same frame. | |
576 clearDamageForAllSurfaces(root.get()); | |
577 { | |
578 scoped_ptr<CCLayerImpl> child2 = CCLayerImpl::create(3); | |
579 child2->setPosition(FloatPoint(400, 380)); | |
580 child2->setAnchorPoint(FloatPoint::zero()); | |
581 child2->setBounds(IntSize(6, 8)); | |
582 child2->setContentBounds(IntSize(6, 8)); | |
583 child2->setDrawsContent(true); | |
584 root->addChild(child2.Pass()); | |
585 } | |
586 CCLayerImpl* child2 = root->children()[1]; | |
587 emulateDrawingOneFrame(root.get()); | |
588 | |
589 // Damaging two layers simultaneously should cause combined damage. | |
590 // - child1 update rect in surface space: FloatRect(100, 100, 1, 2); | |
591 // - child2 update rect in surface space: FloatRect(400, 380, 3, 4); | |
592 clearDamageForAllSurfaces(root.get()); | |
593 child1->setUpdateRect(FloatRect(0, 0, 1, 2)); | |
594 child2->setUpdateRect(FloatRect(0, 0, 3, 4)); | |
595 emulateDrawingOneFrame(root.get()); | |
596 FloatRect rootDamageRect = root->renderSurface()->damageTracker()->currentDa
mageRect(); | |
597 EXPECT_FLOAT_RECT_EQ(FloatRect(100, 100, 303, 284), rootDamageRect); | |
598 } | |
599 | |
600 TEST_F(CCDamageTrackerTest, verifyDamageForNestedSurfaces) | |
601 { | |
602 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces(); | |
603 CCLayerImpl* child1 = root->children()[0]; | |
604 CCLayerImpl* child2 = root->children()[1]; | |
605 CCLayerImpl* grandChild1 = root->children()[0]->children()[0]; | |
606 FloatRect childDamageRect; | |
607 FloatRect rootDamageRect; | |
608 | |
609 // CASE 1: Damage to a descendant surface should propagate properly to ances
tor surface. | |
610 // | |
611 clearDamageForAllSurfaces(root.get()); | |
612 grandChild1->setOpacity(0.5); | |
613 emulateDrawingOneFrame(root.get()); | |
614 childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRec
t(); | |
615 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
616 EXPECT_FLOAT_RECT_EQ(FloatRect(200, 200, 6, 8), childDamageRect); | |
617 EXPECT_FLOAT_RECT_EQ(FloatRect(300, 300, 6, 8), rootDamageRect); | |
618 | |
619 // CASE 2: Same as previous case, but with additional damage elsewhere that
should be properly unioned. | |
620 // - child1 surface damage in root surface space: FloatRect(300, 300, 6, 8); | |
621 // - child2 damage in root surface space: FloatRect(11, 11, 18, 18); | |
622 clearDamageForAllSurfaces(root.get()); | |
623 grandChild1->setOpacity(0.7f); | |
624 child2->setOpacity(0.7f); | |
625 emulateDrawingOneFrame(root.get()); | |
626 childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRec
t(); | |
627 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
628 EXPECT_FLOAT_RECT_EQ(FloatRect(200, 200, 6, 8), childDamageRect); | |
629 EXPECT_FLOAT_RECT_EQ(FloatRect(11, 11, 295, 297), rootDamageRect); | |
630 } | |
631 | |
632 TEST_F(CCDamageTrackerTest, verifyDamageForSurfaceChangeFromDescendantLayer) | |
633 { | |
634 // If descendant layer changes and affects the content bounds of the render
surface, | |
635 // then the entire descendant surface should be damaged, and it should damag
e its | |
636 // ancestor surface with the old and new surface regions. | |
637 | |
638 // This is a tricky case, since only the first grandChild changes, but the e
ntire | |
639 // surface should be marked dirty. | |
640 | |
641 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces(); | |
642 CCLayerImpl* child1 = root->children()[0]; | |
643 CCLayerImpl* grandChild1 = root->children()[0]->children()[0]; | |
644 FloatRect childDamageRect; | |
645 FloatRect rootDamageRect; | |
646 | |
647 clearDamageForAllSurfaces(root.get()); | |
648 grandChild1->setPosition(FloatPoint(195, 205)); | |
649 emulateDrawingOneFrame(root.get()); | |
650 childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRec
t(); | |
651 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
652 | |
653 // The new surface bounds should be damaged entirely, even though only one o
f the layers changed. | |
654 EXPECT_FLOAT_RECT_EQ(FloatRect(190, 190, 11, 23), childDamageRect); | |
655 | |
656 // Damage to the root surface should be the union of child1's *entire* rende
r surface | |
657 // (in target space), and its old exposed area (also in target space). | |
658 EXPECT_FLOAT_RECT_EQ(FloatRect(290, 290, 16, 23), rootDamageRect); | |
659 } | |
660 | |
661 TEST_F(CCDamageTrackerTest, verifyDamageForSurfaceChangeFromAncestorLayer) | |
662 { | |
663 // An ancestor/owning layer changes that affects the position/transform of t
he render | |
664 // surface. Note that in this case, the layerPropertyChanged flag already pr
opagates | |
665 // to the subtree (tested in CCLayerImpltest), which damages the entire chil
d1 | |
666 // surface, but the damage tracker still needs the correct logic to compute
the | |
667 // exposed region on the root surface. | |
668 | |
669 // FIXME: the expectations of this test case should change when we add suppo
rt for a | |
670 // unique scissorRect per renderSurface. In that case, the child1 sur
face | |
671 // should be completely unchanged, since we are only transforming it,
while the | |
672 // root surface would be damaged appropriately. | |
673 | |
674 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces(); | |
675 CCLayerImpl* child1 = root->children()[0]; | |
676 FloatRect childDamageRect; | |
677 FloatRect rootDamageRect; | |
678 | |
679 clearDamageForAllSurfaces(root.get()); | |
680 child1->setPosition(FloatPoint(50, 50)); | |
681 emulateDrawingOneFrame(root.get()); | |
682 childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRec
t(); | |
683 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
684 | |
685 // The new surface bounds should be damaged entirely. | |
686 EXPECT_FLOAT_RECT_EQ(FloatRect(190, 190, 16, 18), childDamageRect); | |
687 | |
688 // The entire child1 surface and the old exposed child1 surface should damag
e the root surface. | |
689 // - old child1 surface in target space: FloatRect(290, 290, 16, 18) | |
690 // - new child1 surface in target space: FloatRect(240, 240, 16, 18) | |
691 EXPECT_FLOAT_RECT_EQ(FloatRect(240, 240, 66, 68), rootDamageRect); | |
692 } | |
693 | |
694 TEST_F(CCDamageTrackerTest, verifyDamageForAddingAndRemovingRenderSurfaces) | |
695 { | |
696 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces(); | |
697 CCLayerImpl* child1 = root->children()[0]; | |
698 FloatRect childDamageRect; | |
699 FloatRect rootDamageRect; | |
700 | |
701 // CASE 1: If a descendant surface disappears, its entire old area becomes e
xposed. | |
702 // | |
703 clearDamageForAllSurfaces(root.get()); | |
704 child1->setOpacity(1); | |
705 emulateDrawingOneFrame(root.get()); | |
706 | |
707 // Sanity check that there is only one surface now. | |
708 ASSERT_FALSE(child1->renderSurface()); | |
709 ASSERT_EQ(4u, root->renderSurface()->layerList().size()); | |
710 | |
711 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
712 EXPECT_FLOAT_RECT_EQ(FloatRect(290, 290, 16, 18), rootDamageRect); | |
713 | |
714 // CASE 2: If a descendant surface appears, its entire old area becomes expo
sed. | |
715 | |
716 // Cycle one frame of no change, just to sanity check that the next rect is
not because of the old damage state. | |
717 clearDamageForAllSurfaces(root.get()); | |
718 emulateDrawingOneFrame(root.get()); | |
719 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
720 EXPECT_TRUE(rootDamageRect.isEmpty()); | |
721 | |
722 // Then change the tree so that the render surface is added back. | |
723 clearDamageForAllSurfaces(root.get()); | |
724 child1->setOpacity(0.5); | |
725 emulateDrawingOneFrame(root.get()); | |
726 | |
727 // Sanity check that there is a new surface now. | |
728 ASSERT_TRUE(child1->renderSurface()); | |
729 EXPECT_EQ(3u, root->renderSurface()->layerList().size()); | |
730 EXPECT_EQ(2u, child1->renderSurface()->layerList().size()); | |
731 | |
732 childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRec
t(); | |
733 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
734 EXPECT_FLOAT_RECT_EQ(FloatRect(190, 190, 16, 18), childDamageRect); | |
735 EXPECT_FLOAT_RECT_EQ(FloatRect(290, 290, 16, 18), rootDamageRect); | |
736 } | |
737 | |
738 TEST_F(CCDamageTrackerTest, verifyNoDamageWhenNothingChanged) | |
739 { | |
740 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces(); | |
741 CCLayerImpl* child1 = root->children()[0]; | |
742 FloatRect childDamageRect; | |
743 FloatRect rootDamageRect; | |
744 | |
745 // CASE 1: If nothing changes, the damage rect should be empty. | |
746 // | |
747 clearDamageForAllSurfaces(root.get()); | |
748 emulateDrawingOneFrame(root.get()); | |
749 childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRec
t(); | |
750 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
751 EXPECT_TRUE(childDamageRect.isEmpty()); | |
752 EXPECT_TRUE(rootDamageRect.isEmpty()); | |
753 | |
754 // CASE 2: If nothing changes twice in a row, the damage rect should still b
e empty. | |
755 // | |
756 clearDamageForAllSurfaces(root.get()); | |
757 emulateDrawingOneFrame(root.get()); | |
758 childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRec
t(); | |
759 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
760 EXPECT_TRUE(childDamageRect.isEmpty()); | |
761 EXPECT_TRUE(rootDamageRect.isEmpty()); | |
762 } | |
763 | |
764 TEST_F(CCDamageTrackerTest, verifyNoDamageForUpdateRectThatDoesNotDrawContent) | |
765 { | |
766 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces(); | |
767 CCLayerImpl* child1 = root->children()[0]; | |
768 FloatRect childDamageRect; | |
769 FloatRect rootDamageRect; | |
770 | |
771 // In our specific tree, the update rect of child1 should not cause any dama
ge to any | |
772 // surface because it does not actually draw content. | |
773 clearDamageForAllSurfaces(root.get()); | |
774 child1->setUpdateRect(FloatRect(0, 0, 1, 2)); | |
775 emulateDrawingOneFrame(root.get()); | |
776 childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRec
t(); | |
777 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
778 EXPECT_TRUE(childDamageRect.isEmpty()); | |
779 EXPECT_TRUE(rootDamageRect.isEmpty()); | |
780 } | |
781 | |
782 TEST_F(CCDamageTrackerTest, verifyDamageForReplica) | |
783 { | |
784 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces(); | |
785 CCLayerImpl* child1 = root->children()[0]; | |
786 CCLayerImpl* grandChild1 = child1->children()[0]; | |
787 CCLayerImpl* grandChild2 = child1->children()[1]; | |
788 | |
789 // Damage on a surface that has a reflection should cause the target surface
to | |
790 // receive the surface's damage and the surface's reflected damage. | |
791 | |
792 // For this test case, we modify grandChild2, and add grandChild3 to extend
the bounds | |
793 // of child1's surface. This way, we can test reflection changes without cha
nging | |
794 // contentBounds of the surface. | |
795 grandChild2->setPosition(FloatPoint(180, 180)); | |
796 { | |
797 scoped_ptr<CCLayerImpl> grandChild3 = CCLayerImpl::create(6); | |
798 grandChild3->setPosition(FloatPoint(240, 240)); | |
799 grandChild3->setAnchorPoint(FloatPoint::zero()); | |
800 grandChild3->setBounds(IntSize(10, 10)); | |
801 grandChild3->setContentBounds(IntSize(10, 10)); | |
802 grandChild3->setDrawsContent(true); | |
803 child1->addChild(grandChild3.Pass()); | |
804 } | |
805 child1->setOpacity(0.5); | |
806 emulateDrawingOneFrame(root.get()); | |
807 | |
808 // CASE 1: adding a reflection about the left edge of grandChild1. | |
809 // | |
810 clearDamageForAllSurfaces(root.get()); | |
811 { | |
812 scoped_ptr<CCLayerImpl> grandChild1Replica = CCLayerImpl::create(7); | |
813 grandChild1Replica->setPosition(FloatPoint::zero()); | |
814 grandChild1Replica->setAnchorPoint(FloatPoint::zero()); | |
815 WebTransformationMatrix reflection; | |
816 reflection.scale3d(-1, 1, 1); | |
817 grandChild1Replica->setTransform(reflection); | |
818 grandChild1->setReplicaLayer(grandChild1Replica.Pass()); | |
819 } | |
820 emulateDrawingOneFrame(root.get()); | |
821 | |
822 FloatRect grandChildDamageRect = grandChild1->renderSurface()->damageTracker
()->currentDamageRect(); | |
823 FloatRect childDamageRect = child1->renderSurface()->damageTracker()->curren
tDamageRect(); | |
824 FloatRect rootDamageRect = root->renderSurface()->damageTracker()->currentDa
mageRect(); | |
825 | |
826 // The grandChild surface damage should not include its own replica. The chi
ld | |
827 // surface damage should include the normal and replica surfaces. | |
828 EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 6, 8), grandChildDamageRect); | |
829 EXPECT_FLOAT_RECT_EQ(FloatRect(194, 200, 12, 8), childDamageRect); | |
830 EXPECT_FLOAT_RECT_EQ(FloatRect(294, 300, 12, 8), rootDamageRect); | |
831 | |
832 // CASE 2: moving the descendant surface should cause both the original and
reflected | |
833 // areas to be damaged on the target. | |
834 clearDamageForAllSurfaces(root.get()); | |
835 IntRect oldContentRect = child1->renderSurface()->contentRect(); | |
836 grandChild1->setPosition(FloatPoint(195, 205)); | |
837 emulateDrawingOneFrame(root.get()); | |
838 ASSERT_EQ(oldContentRect.width(), child1->renderSurface()->contentRect().wid
th()); | |
839 ASSERT_EQ(oldContentRect.height(), child1->renderSurface()->contentRect().he
ight()); | |
840 | |
841 grandChildDamageRect = grandChild1->renderSurface()->damageTracker()->curren
tDamageRect(); | |
842 childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRec
t(); | |
843 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
844 | |
845 // The child surface damage should include normal and replica surfaces for b
oth old and new locations. | |
846 // - old location in target space: FloatRect(194, 200, 12, 8) | |
847 // - new location in target space: FloatRect(189, 205, 12, 8) | |
848 EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 6, 8), grandChildDamageRect); | |
849 EXPECT_FLOAT_RECT_EQ(FloatRect(189, 200, 17, 13), childDamageRect); | |
850 EXPECT_FLOAT_RECT_EQ(FloatRect(289, 300, 17, 13), rootDamageRect); | |
851 | |
852 // CASE 3: removing the reflection should cause the entire region including
reflection | |
853 // to damage the target surface. | |
854 clearDamageForAllSurfaces(root.get()); | |
855 grandChild1->setReplicaLayer(scoped_ptr<CCLayerImpl>()); | |
856 emulateDrawingOneFrame(root.get()); | |
857 ASSERT_EQ(oldContentRect.width(), child1->renderSurface()->contentRect().wid
th()); | |
858 ASSERT_EQ(oldContentRect.height(), child1->renderSurface()->contentRect().he
ight()); | |
859 | |
860 EXPECT_FALSE(grandChild1->renderSurface()); | |
861 childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRec
t(); | |
862 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
863 | |
864 EXPECT_FLOAT_RECT_EQ(FloatRect(189, 205, 12, 8), childDamageRect); | |
865 EXPECT_FLOAT_RECT_EQ(FloatRect(289, 305, 12, 8), rootDamageRect); | |
866 } | |
867 | |
868 TEST_F(CCDamageTrackerTest, verifyDamageForMask) | |
869 { | |
870 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithOneSurface(); | |
871 CCLayerImpl* child = root->children()[0]; | |
872 | |
873 // In the current implementation of the damage tracker, changes to mask laye
rs should | |
874 // damage the entire corresponding surface. | |
875 | |
876 clearDamageForAllSurfaces(root.get()); | |
877 | |
878 // Set up the mask layer. | |
879 { | |
880 scoped_ptr<CCLayerImpl> maskLayer = CCLayerImpl::create(3); | |
881 maskLayer->setPosition(child->position()); | |
882 maskLayer->setAnchorPoint(FloatPoint::zero()); | |
883 maskLayer->setBounds(child->bounds()); | |
884 maskLayer->setContentBounds(child->bounds()); | |
885 child->setMaskLayer(maskLayer.Pass()); | |
886 } | |
887 CCLayerImpl* maskLayer = child->maskLayer(); | |
888 | |
889 // Add opacity and a grandChild so that the render surface persists even aft
er we remove the mask. | |
890 child->setOpacity(0.5); | |
891 { | |
892 scoped_ptr<CCLayerImpl> grandChild = CCLayerImpl::create(4); | |
893 grandChild->setPosition(FloatPoint(2, 2)); | |
894 grandChild->setAnchorPoint(FloatPoint::zero()); | |
895 grandChild->setBounds(IntSize(2, 2)); | |
896 grandChild->setContentBounds(IntSize(2, 2)); | |
897 grandChild->setDrawsContent(true); | |
898 child->addChild(grandChild.Pass()); | |
899 } | |
900 emulateDrawingOneFrame(root.get()); | |
901 | |
902 // Sanity check that a new surface was created for the child. | |
903 ASSERT_TRUE(child->renderSurface()); | |
904 | |
905 // CASE 1: the updateRect on a mask layer should damage the entire target su
rface. | |
906 // | |
907 clearDamageForAllSurfaces(root.get()); | |
908 maskLayer->setUpdateRect(FloatRect(1, 2, 3, 4)); | |
909 emulateDrawingOneFrame(root.get()); | |
910 FloatRect childDamageRect = child->renderSurface()->damageTracker()->current
DamageRect(); | |
911 EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 30, 30), childDamageRect); | |
912 | |
913 // CASE 2: a property change on the mask layer should damage the entire targ
et surface. | |
914 // | |
915 | |
916 // Advance one frame without damage so that we know the damage rect is not l
eftover from the previous case. | |
917 clearDamageForAllSurfaces(root.get()); | |
918 emulateDrawingOneFrame(root.get()); | |
919 childDamageRect = child->renderSurface()->damageTracker()->currentDamageRect
(); | |
920 EXPECT_TRUE(childDamageRect.isEmpty()); | |
921 | |
922 // Then test the property change. | |
923 clearDamageForAllSurfaces(root.get()); | |
924 maskLayer->setStackingOrderChanged(true); | |
925 | |
926 emulateDrawingOneFrame(root.get()); | |
927 childDamageRect = child->renderSurface()->damageTracker()->currentDamageRect
(); | |
928 EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 30, 30), childDamageRect); | |
929 | |
930 // CASE 3: removing the mask also damages the entire target surface. | |
931 // | |
932 | |
933 // Advance one frame without damage so that we know the damage rect is not l
eftover from the previous case. | |
934 clearDamageForAllSurfaces(root.get()); | |
935 emulateDrawingOneFrame(root.get()); | |
936 childDamageRect = child->renderSurface()->damageTracker()->currentDamageRect
(); | |
937 EXPECT_TRUE(childDamageRect.isEmpty()); | |
938 | |
939 // Then test mask removal. | |
940 clearDamageForAllSurfaces(root.get()); | |
941 child->setMaskLayer(scoped_ptr<CCLayerImpl>()); | |
942 ASSERT_TRUE(child->layerPropertyChanged()); | |
943 emulateDrawingOneFrame(root.get()); | |
944 | |
945 // Sanity check that a render surface still exists. | |
946 ASSERT_TRUE(child->renderSurface()); | |
947 | |
948 childDamageRect = child->renderSurface()->damageTracker()->currentDamageRect
(); | |
949 EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 30, 30), childDamageRect); | |
950 } | |
951 | |
952 TEST_F(CCDamageTrackerTest, verifyDamageForReplicaMask) | |
953 { | |
954 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces(); | |
955 CCLayerImpl* child1 = root->children()[0]; | |
956 CCLayerImpl* grandChild1 = child1->children()[0]; | |
957 | |
958 // Changes to a replica's mask should not damage the original surface, becau
se it is | |
959 // not masked. But it does damage the ancestor target surface. | |
960 | |
961 clearDamageForAllSurfaces(root.get()); | |
962 | |
963 // Create a reflection about the left edge of grandChild1. | |
964 { | |
965 scoped_ptr<CCLayerImpl> grandChild1Replica = CCLayerImpl::create(6); | |
966 grandChild1Replica->setPosition(FloatPoint::zero()); | |
967 grandChild1Replica->setAnchorPoint(FloatPoint::zero()); | |
968 WebTransformationMatrix reflection; | |
969 reflection.scale3d(-1, 1, 1); | |
970 grandChild1Replica->setTransform(reflection); | |
971 grandChild1->setReplicaLayer(grandChild1Replica.Pass()); | |
972 } | |
973 CCLayerImpl* grandChild1Replica = grandChild1->replicaLayer(); | |
974 | |
975 // Set up the mask layer on the replica layer | |
976 { | |
977 scoped_ptr<CCLayerImpl> replicaMaskLayer = CCLayerImpl::create(7); | |
978 replicaMaskLayer->setPosition(FloatPoint::zero()); | |
979 replicaMaskLayer->setAnchorPoint(FloatPoint::zero()); | |
980 replicaMaskLayer->setBounds(grandChild1->bounds()); | |
981 replicaMaskLayer->setContentBounds(grandChild1->bounds()); | |
982 grandChild1Replica->setMaskLayer(replicaMaskLayer.Pass()); | |
983 } | |
984 CCLayerImpl* replicaMaskLayer = grandChild1Replica->maskLayer(); | |
985 | |
986 emulateDrawingOneFrame(root.get()); | |
987 | |
988 // Sanity check that the appropriate render surfaces were created | |
989 ASSERT_TRUE(grandChild1->renderSurface()); | |
990 | |
991 // CASE 1: a property change on the mask should damage only the reflected re
gion on the target surface. | |
992 clearDamageForAllSurfaces(root.get()); | |
993 replicaMaskLayer->setStackingOrderChanged(true); | |
994 emulateDrawingOneFrame(root.get()); | |
995 | |
996 FloatRect grandChildDamageRect = grandChild1->renderSurface()->damageTracker
()->currentDamageRect(); | |
997 FloatRect childDamageRect = child1->renderSurface()->damageTracker()->curren
tDamageRect(); | |
998 | |
999 EXPECT_TRUE(grandChildDamageRect.isEmpty()); | |
1000 EXPECT_FLOAT_RECT_EQ(FloatRect(194, 200, 6, 8), childDamageRect); | |
1001 | |
1002 // CASE 2: removing the replica mask damages only the reflected region on th
e target surface. | |
1003 // | |
1004 clearDamageForAllSurfaces(root.get()); | |
1005 grandChild1Replica->setMaskLayer(scoped_ptr<CCLayerImpl>()); | |
1006 emulateDrawingOneFrame(root.get()); | |
1007 | |
1008 grandChildDamageRect = grandChild1->renderSurface()->damageTracker()->curren
tDamageRect(); | |
1009 childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRec
t(); | |
1010 | |
1011 EXPECT_TRUE(grandChildDamageRect.isEmpty()); | |
1012 EXPECT_FLOAT_RECT_EQ(FloatRect(194, 200, 6, 8), childDamageRect); | |
1013 } | |
1014 | |
1015 TEST_F(CCDamageTrackerTest, verifyDamageForReplicaMaskWithAnchor) | |
1016 { | |
1017 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces(); | |
1018 CCLayerImpl* child1 = root->children()[0]; | |
1019 CCLayerImpl* grandChild1 = child1->children()[0]; | |
1020 | |
1021 // Verify that the correct replicaOriginTransform is used for the replicaMas
k; | |
1022 clearDamageForAllSurfaces(root.get()); | |
1023 | |
1024 grandChild1->setAnchorPoint(FloatPoint(1, 0)); // This is not exactly the an
chor being tested, but by convention its expected to be the same as the replica'
s anchor point. | |
1025 | |
1026 { | |
1027 scoped_ptr<CCLayerImpl> grandChild1Replica = CCLayerImpl::create(6); | |
1028 grandChild1Replica->setPosition(FloatPoint::zero()); | |
1029 grandChild1Replica->setAnchorPoint(FloatPoint(1, 0)); // This is the anc
hor being tested. | |
1030 WebTransformationMatrix reflection; | |
1031 reflection.scale3d(-1, 1, 1); | |
1032 grandChild1Replica->setTransform(reflection); | |
1033 grandChild1->setReplicaLayer(grandChild1Replica.Pass()); | |
1034 } | |
1035 CCLayerImpl* grandChild1Replica = grandChild1->replicaLayer(); | |
1036 | |
1037 // Set up the mask layer on the replica layer | |
1038 { | |
1039 scoped_ptr<CCLayerImpl> replicaMaskLayer = CCLayerImpl::create(7); | |
1040 replicaMaskLayer->setPosition(FloatPoint::zero()); | |
1041 replicaMaskLayer->setAnchorPoint(FloatPoint::zero()); // note, this is n
ot the anchor being tested. | |
1042 replicaMaskLayer->setBounds(grandChild1->bounds()); | |
1043 replicaMaskLayer->setContentBounds(grandChild1->bounds()); | |
1044 grandChild1Replica->setMaskLayer(replicaMaskLayer.Pass()); | |
1045 } | |
1046 CCLayerImpl* replicaMaskLayer = grandChild1Replica->maskLayer(); | |
1047 | |
1048 emulateDrawingOneFrame(root.get()); | |
1049 | |
1050 // Sanity check that the appropriate render surfaces were created | |
1051 ASSERT_TRUE(grandChild1->renderSurface()); | |
1052 | |
1053 // A property change on the replicaMask should damage the reflected region o
n the target surface. | |
1054 clearDamageForAllSurfaces(root.get()); | |
1055 replicaMaskLayer->setStackingOrderChanged(true); | |
1056 | |
1057 emulateDrawingOneFrame(root.get()); | |
1058 | |
1059 FloatRect childDamageRect = child1->renderSurface()->damageTracker()->curren
tDamageRect(); | |
1060 EXPECT_FLOAT_RECT_EQ(FloatRect(206, 200, 6, 8), childDamageRect); | |
1061 } | |
1062 | |
1063 TEST_F(CCDamageTrackerTest, verifyDamageWhenForcedFullDamage) | |
1064 { | |
1065 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithOneSurface(); | |
1066 CCLayerImpl* child = root->children()[0]; | |
1067 | |
1068 // Case 1: This test ensures that when the tracker is forced to have full da
mage, that | |
1069 // it takes priority over any other partial damage. | |
1070 // | |
1071 clearDamageForAllSurfaces(root.get()); | |
1072 child->setUpdateRect(FloatRect(10, 11, 12, 13)); | |
1073 root->renderSurface()->damageTracker()->forceFullDamageNextUpdate(); | |
1074 emulateDrawingOneFrame(root.get()); | |
1075 FloatRect rootDamageRect = root->renderSurface()->damageTracker()->currentDa
mageRect(); | |
1076 EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 500, 500), rootDamageRect); | |
1077 | |
1078 // Case 2: An additional sanity check that forcing full damage works even wh
en nothing | |
1079 // on the layer tree changed. | |
1080 // | |
1081 clearDamageForAllSurfaces(root.get()); | |
1082 root->renderSurface()->damageTracker()->forceFullDamageNextUpdate(); | |
1083 emulateDrawingOneFrame(root.get()); | |
1084 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
1085 EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 500, 500), rootDamageRect); | |
1086 } | |
1087 | |
1088 TEST_F(CCDamageTrackerTest, verifyDamageForEmptyLayerList) | |
1089 { | |
1090 // Though it should never happen, its a good idea to verify that the damage
tracker | |
1091 // does not crash when it receives an empty layerList. | |
1092 | |
1093 scoped_ptr<CCLayerImpl> root = CCLayerImpl::create(1); | |
1094 root->createRenderSurface(); | |
1095 | |
1096 ASSERT_TRUE(root == root->renderTarget()); | |
1097 CCRenderSurface* targetSurface = root->renderSurface(); | |
1098 targetSurface->clearLayerLists(); | |
1099 targetSurface->damageTracker()->updateDamageTrackingState(targetSurface->lay
erList(), targetSurface->owningLayerId(), false, IntRect(), 0, WebFilterOperatio
ns()); | |
1100 | |
1101 FloatRect damageRect = targetSurface->damageTracker()->currentDamageRect(); | |
1102 EXPECT_TRUE(damageRect.isEmpty()); | |
1103 } | |
1104 | |
1105 TEST_F(CCDamageTrackerTest, verifyDamageAccumulatesUntilReset) | |
1106 { | |
1107 // If damage is not cleared, it should accumulate. | |
1108 | |
1109 scoped_ptr<CCLayerImpl> root = createAndSetUpTestTreeWithOneSurface(); | |
1110 CCLayerImpl* child = root->children()[0]; | |
1111 | |
1112 clearDamageForAllSurfaces(root.get()); | |
1113 child->setUpdateRect(FloatRect(10, 11, 1, 2)); | |
1114 emulateDrawingOneFrame(root.get()); | |
1115 | |
1116 // Sanity check damage after the first frame; this isnt the actual test yet. | |
1117 FloatRect rootDamageRect = root->renderSurface()->damageTracker()->currentDa
mageRect(); | |
1118 EXPECT_FLOAT_RECT_EQ(FloatRect(110, 111, 1, 2), rootDamageRect); | |
1119 | |
1120 // New damage, without having cleared the previous damage, should be unioned
to the previous one. | |
1121 child->setUpdateRect(FloatRect(20, 25, 1, 2)); | |
1122 emulateDrawingOneFrame(root.get()); | |
1123 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
1124 EXPECT_FLOAT_RECT_EQ(FloatRect(110, 111, 11, 16), rootDamageRect); | |
1125 | |
1126 // If we notify the damage tracker that we drew the damaged area, then damag
e should be emptied. | |
1127 root->renderSurface()->damageTracker()->didDrawDamagedArea(); | |
1128 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
1129 EXPECT_TRUE(rootDamageRect.isEmpty()); | |
1130 | |
1131 // Damage should remain empty even after one frame, since there's yet no new
damage | |
1132 emulateDrawingOneFrame(root.get()); | |
1133 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect()
; | |
1134 EXPECT_TRUE(rootDamageRect.isEmpty()); | |
1135 } | |
1136 | |
1137 } // namespace | |
OLD | NEW |