Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(22)

Side by Side Diff: cc/CCDamageTrackerTest.cpp

Issue 11108020: [cc] Change cc_tests.gyp filenames to Chromium style (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « cc/CCActiveAnimationTest.cpp ('k') | cc/CCDelayBasedTimeSourceTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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
OLDNEW
« no previous file with comments | « cc/CCActiveAnimationTest.cpp ('k') | cc/CCDelayBasedTimeSourceTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698