Use SCHEME_HTTP for HTTPS proxies on Android.
[chromium-blink-merge.git] / cc / damage_tracker_unittest.cc
blobaec754b7e8e04552a6c5b8d52a39615e5f320b7d
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.
5 #include "cc/damage_tracker.h"
7 #include "cc/layer_impl.h"
8 #include "cc/layer_tree_host_common.h"
9 #include "cc/math_util.h"
10 #include "cc/single_thread_proxy.h"
11 #include "cc/test/fake_impl_proxy.h"
12 #include "cc/test/fake_layer_tree_host_impl.h"
13 #include "cc/test/geometry_test_utils.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "third_party/skia/include/effects/SkBlurImageFilter.h"
16 #include "ui/gfx/quad_f.h"
17 #include <public/WebFilterOperation.h>
18 #include <public/WebFilterOperations.h>
20 using namespace WebKit;
21 using namespace WebKitTests;
23 namespace cc {
24 namespace {
26 void executeCalculateDrawProperties(LayerImpl* root, std::vector<LayerImpl*>& renderSurfaceLayerList)
28 int dummyMaxTextureSize = 512;
30 // Sanity check: The test itself should create the root layer's render surface, so
31 // that the surface (and its damage tracker) can persist across multiple
32 // calls to this function.
33 ASSERT_TRUE(root->renderSurface());
34 ASSERT_FALSE(renderSurfaceLayerList.size());
36 LayerTreeHostCommon::calculateDrawProperties(root, root->bounds(), 1, 1, dummyMaxTextureSize, renderSurfaceLayerList);
39 void clearDamageForAllSurfaces(LayerImpl* layer)
41 if (layer->renderSurface())
42 layer->renderSurface()->damageTracker()->didDrawDamagedArea();
44 // Recursively clear damage for any existing surface.
45 for (size_t i = 0; i < layer->children().size(); ++i)
46 clearDamageForAllSurfaces(layer->children()[i]);
49 void emulateDrawingOneFrame(LayerImpl* root)
51 // This emulates only the steps that are relevant to testing the damage tracker:
52 // 1. computing the render passes and layerlists
53 // 2. updating all damage trackers in the correct order
54 // 3. resetting all updateRects and propertyChanged flags for all layers and surfaces.
56 std::vector<LayerImpl*> renderSurfaceLayerList;
57 executeCalculateDrawProperties(root, renderSurfaceLayerList);
59 // Iterate back-to-front, so that damage correctly propagates from descendant surfaces to ancestors.
60 for (int i = renderSurfaceLayerList.size() - 1; i >= 0; --i) {
61 RenderSurfaceImpl* targetSurface = renderSurfaceLayerList[i]->renderSurface();
62 targetSurface->damageTracker()->updateDamageTrackingState(targetSurface->layerList(), targetSurface->owningLayerId(), targetSurface->surfacePropertyChangedOnlyFromDescendant(), targetSurface->contentRect(), renderSurfaceLayerList[i]->maskLayer(), renderSurfaceLayerList[i]->filters(), renderSurfaceLayerList[i]->filter().get());
65 root->resetAllChangeTrackingForSubtree();
68 class DamageTrackerTest : public testing::Test {
69 public:
70 DamageTrackerTest()
71 : m_hostImpl(&m_proxy)
75 scoped_ptr<LayerImpl> createTestTreeWithOneSurface()
77 scoped_ptr<LayerImpl> root = LayerImpl::create(&m_hostImpl, 1);
78 scoped_ptr<LayerImpl> child = LayerImpl::create(&m_hostImpl, 2);
80 root->setPosition(gfx::PointF());
81 root->setAnchorPoint(gfx::PointF());
82 root->setBounds(gfx::Size(500, 500));
83 root->setContentBounds(gfx::Size(500, 500));
84 root->setDrawsContent(true);
85 root->createRenderSurface();
86 root->renderSurface()->setContentRect(gfx::Rect(gfx::Point(), gfx::Size(500, 500)));
88 child->setPosition(gfx::PointF(100, 100));
89 child->setAnchorPoint(gfx::PointF());
90 child->setBounds(gfx::Size(30, 30));
91 child->setContentBounds(gfx::Size(30, 30));
92 child->setDrawsContent(true);
93 root->addChild(child.Pass());
95 return root.Pass();
98 scoped_ptr<LayerImpl> createTestTreeWithTwoSurfaces()
100 // This test tree has two render surfaces: one for the root, and one for
101 // child1. Additionally, the root has a second child layer, and child1 has two
102 // children of its own.
104 scoped_ptr<LayerImpl> root = LayerImpl::create(&m_hostImpl, 1);
105 scoped_ptr<LayerImpl> child1 = LayerImpl::create(&m_hostImpl, 2);
106 scoped_ptr<LayerImpl> child2 = LayerImpl::create(&m_hostImpl, 3);
107 scoped_ptr<LayerImpl> grandChild1 = LayerImpl::create(&m_hostImpl, 4);
108 scoped_ptr<LayerImpl> grandChild2 = LayerImpl::create(&m_hostImpl, 5);
110 root->setPosition(gfx::PointF());
111 root->setAnchorPoint(gfx::PointF());
112 root->setBounds(gfx::Size(500, 500));
113 root->setContentBounds(gfx::Size(500, 500));
114 root->setDrawsContent(true);
115 root->createRenderSurface();
116 root->renderSurface()->setContentRect(gfx::Rect(gfx::Point(), gfx::Size(500, 500)));
118 child1->setPosition(gfx::PointF(100, 100));
119 child1->setAnchorPoint(gfx::PointF());
120 child1->setBounds(gfx::Size(30, 30));
121 child1->setContentBounds(gfx::Size(30, 30));
122 child1->setOpacity(0.5); // with a child that drawsContent, this will cause the layer to create its own renderSurface.
123 child1->setDrawsContent(false); // this layer does not draw, but is intended to create its own renderSurface.
124 child1->setForceRenderSurface(true);
126 child2->setPosition(gfx::PointF(11, 11));
127 child2->setAnchorPoint(gfx::PointF());
128 child2->setBounds(gfx::Size(18, 18));
129 child2->setContentBounds(gfx::Size(18, 18));
130 child2->setDrawsContent(true);
132 grandChild1->setPosition(gfx::PointF(200, 200));
133 grandChild1->setAnchorPoint(gfx::PointF());
134 grandChild1->setBounds(gfx::Size(6, 8));
135 grandChild1->setContentBounds(gfx::Size(6, 8));
136 grandChild1->setDrawsContent(true);
138 grandChild2->setPosition(gfx::PointF(190, 190));
139 grandChild2->setAnchorPoint(gfx::PointF());
140 grandChild2->setBounds(gfx::Size(6, 8));
141 grandChild2->setContentBounds(gfx::Size(6, 8));
142 grandChild2->setDrawsContent(true);
144 child1->addChild(grandChild1.Pass());
145 child1->addChild(grandChild2.Pass());
146 root->addChild(child1.Pass());
147 root->addChild(child2.Pass());
149 return root.Pass();
152 scoped_ptr<LayerImpl> createAndSetUpTestTreeWithOneSurface()
154 scoped_ptr<LayerImpl> root = createTestTreeWithOneSurface();
156 // Setup includes going past the first frame which always damages everything, so
157 // that we can actually perform specific tests.
158 emulateDrawingOneFrame(root.get());
160 return root.Pass();
163 scoped_ptr<LayerImpl> createAndSetUpTestTreeWithTwoSurfaces()
165 scoped_ptr<LayerImpl> root = createTestTreeWithTwoSurfaces();
167 // Setup includes going past the first frame which always damages everything, so
168 // that we can actually perform specific tests.
169 emulateDrawingOneFrame(root.get());
171 return root.Pass();
174 protected:
175 FakeImplProxy m_proxy;
176 FakeLayerTreeHostImpl m_hostImpl;
179 TEST_F(DamageTrackerTest, sanityCheckTestTreeWithOneSurface)
181 // Sanity check that the simple test tree will actually produce the expected render
182 // surfaces and layer lists.
184 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithOneSurface();
186 EXPECT_EQ(2u, root->renderSurface()->layerList().size());
187 EXPECT_EQ(1, root->renderSurface()->layerList()[0]->id());
188 EXPECT_EQ(2, root->renderSurface()->layerList()[1]->id());
190 gfx::RectF rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
191 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 500, 500), rootDamageRect);
194 TEST_F(DamageTrackerTest, sanityCheckTestTreeWithTwoSurfaces)
196 // Sanity check that the complex test tree will actually produce the expected render
197 // surfaces and layer lists.
199 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces();
201 LayerImpl* child1 = root->children()[0];
202 LayerImpl* child2 = root->children()[1];
203 gfx::RectF childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRect();
204 gfx::RectF rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
206 ASSERT_TRUE(child1->renderSurface());
207 EXPECT_FALSE(child2->renderSurface());
208 EXPECT_EQ(3u, root->renderSurface()->layerList().size());
209 EXPECT_EQ(2u, child1->renderSurface()->layerList().size());
211 // The render surface for child1 only has a contentRect that encloses grandChild1 and grandChild2, because child1 does not draw content.
212 EXPECT_FLOAT_RECT_EQ(gfx::RectF(190, 190, 16, 18), childDamageRect);
213 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 500, 500), rootDamageRect);
216 TEST_F(DamageTrackerTest, verifyDamageForUpdateRects)
218 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithOneSurface();
219 LayerImpl* child = root->children()[0];
221 // CASE 1: Setting the update rect should cause the corresponding damage to the surface.
223 clearDamageForAllSurfaces(root.get());
224 child->setUpdateRect(gfx::RectF(10, 11, 12, 13));
225 emulateDrawingOneFrame(root.get());
227 // Damage position on the surface should be: position of updateRect (10, 11) relative to the child (100, 100).
228 gfx::RectF rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
229 EXPECT_FLOAT_RECT_EQ(gfx::RectF(110, 111, 12, 13), rootDamageRect);
231 // CASE 2: The same update rect twice in a row still produces the same damage.
233 clearDamageForAllSurfaces(root.get());
234 child->setUpdateRect(gfx::RectF(10, 11, 12, 13));
235 emulateDrawingOneFrame(root.get());
236 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
237 EXPECT_FLOAT_RECT_EQ(gfx::RectF(110, 111, 12, 13), rootDamageRect);
239 // CASE 3: Setting a different update rect should cause damage on the new update region, but no additional exposed old region.
241 clearDamageForAllSurfaces(root.get());
242 child->setUpdateRect(gfx::RectF(20, 25, 1, 2));
243 emulateDrawingOneFrame(root.get());
245 // Damage position on the surface should be: position of updateRect (20, 25) relative to the child (100, 100).
246 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
247 EXPECT_FLOAT_RECT_EQ(gfx::RectF(120, 125, 1, 2), rootDamageRect);
250 TEST_F(DamageTrackerTest, verifyDamageForPropertyChanges)
252 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithOneSurface();
253 LayerImpl* child = root->children()[0];
255 // CASE 1: The layer's property changed flag takes priority over update rect.
257 clearDamageForAllSurfaces(root.get());
258 child->setUpdateRect(gfx::RectF(10, 11, 12, 13));
259 child->setOpacity(0.5);
260 emulateDrawingOneFrame(root.get());
262 // Sanity check - we should not have accidentally created a separate render surface for the translucent layer.
263 ASSERT_FALSE(child->renderSurface());
264 ASSERT_EQ(2u, root->renderSurface()->layerList().size());
266 // Damage should be the entire child layer in targetSurface space.
267 gfx::RectF expectedRect = gfx::RectF(100, 100, 30, 30);
268 gfx::RectF rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
269 EXPECT_FLOAT_RECT_EQ(expectedRect, rootDamageRect);
271 // CASE 2: If a layer moves due to property change, it damages both the new location
272 // and the old (exposed) location. The old location is the entire old layer,
273 // not just the updateRect.
275 // Cycle one frame of no change, just to sanity check that the next rect is not because of the old damage state.
276 clearDamageForAllSurfaces(root.get());
277 emulateDrawingOneFrame(root.get());
278 EXPECT_TRUE(root->renderSurface()->damageTracker()->currentDamageRect().IsEmpty());
280 // Then, test the actual layer movement.
281 clearDamageForAllSurfaces(root.get());
282 child->setPosition(gfx::PointF(200, 230));
283 emulateDrawingOneFrame(root.get());
285 // Expect damage to be the combination of the previous one and the new one.
286 expectedRect.Union(gfx::RectF(200, 230, 30, 30));
287 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
288 EXPECT_FLOAT_RECT_EQ(expectedRect, rootDamageRect);
291 TEST_F(DamageTrackerTest, verifyDamageForTransformedLayer)
293 // If a layer is transformed, the damage rect should still enclose the entire
294 // transformed layer.
296 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithOneSurface();
297 LayerImpl* child = root->children()[0];
299 gfx::Transform rotation;
300 rotation.Rotate(45);
302 clearDamageForAllSurfaces(root.get());
303 child->setAnchorPoint(gfx::PointF(0.5, 0.5));
304 child->setPosition(gfx::PointF(85, 85));
305 emulateDrawingOneFrame(root.get());
307 // Sanity check that the layer actually moved to (85, 85), damaging its old location and new location.
308 gfx::RectF rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
309 EXPECT_FLOAT_RECT_EQ(gfx::RectF(85, 85, 45, 45), rootDamageRect);
311 // With the anchor on the layer's center, now we can test the rotation more
312 // intuitively, since it applies about the layer's anchor.
313 clearDamageForAllSurfaces(root.get());
314 child->setTransform(rotation);
315 emulateDrawingOneFrame(root.get());
317 // Since the child layer is square, rotation by 45 degrees about the center should
318 // increase the size of the expected rect by sqrt(2), centered around (100, 100). The
319 // old exposed region should be fully contained in the new region.
320 double expectedWidth = 30 * sqrt(2.0);
321 double expectedPosition = 100 - 0.5 * expectedWidth;
322 gfx::RectF expectedRect(expectedPosition, expectedPosition, expectedWidth, expectedWidth);
323 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
324 EXPECT_FLOAT_RECT_EQ(expectedRect, rootDamageRect);
327 TEST_F(DamageTrackerTest, verifyDamageForPerspectiveClippedLayer)
329 // If a layer has a perspective transform that causes w < 0, then not clipping the
330 // layer can cause an invalid damage rect. This test checks that the w < 0 case is
331 // tracked properly.
333 // The transform is constructed so that if w < 0 clipping is not performed, the
334 // incorrect rect will be very small, specifically: position (500.972504, 498.544617) and size 0.056610 x 2.910767.
335 // Instead, the correctly transformed rect should actually be very huge (i.e. in theory, -infinity on the left),
336 // and positioned so that the right-most bound rect will be approximately 501 units in root surface space.
339 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithOneSurface();
340 LayerImpl* child = root->children()[0];
342 gfx::Transform transform;
343 transform.Translate3d(500, 500, 0);
344 transform.ApplyPerspectiveDepth(1);
345 MathUtil::rotateEulerAngles(&transform, 0, 45, 0);
346 transform.Translate3d(-50, -50, 0);
348 // Set up the child
349 child->setPosition(gfx::PointF(0, 0));
350 child->setBounds(gfx::Size(100, 100));
351 child->setContentBounds(gfx::Size(100, 100));
352 child->setTransform(transform);
353 emulateDrawingOneFrame(root.get());
355 // Sanity check that the child layer's bounds would actually get clipped by w < 0,
356 // otherwise this test is not actually testing the intended scenario.
357 gfx::QuadF testQuad(gfx::RectF(gfx::PointF(), gfx::SizeF(100, 100)));
358 bool clipped = false;
359 MathUtil::mapQuad(transform, testQuad, clipped);
360 EXPECT_TRUE(clipped);
362 // Damage the child without moving it.
363 clearDamageForAllSurfaces(root.get());
364 child->setOpacity(0.5);
365 emulateDrawingOneFrame(root.get());
367 // The expected damage should cover the entire root surface (500x500), but we don't
368 // care whether the damage rect was clamped or is larger than the surface for this test.
369 gfx::RectF rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
370 gfx::RectF damageWeCareAbout = gfx::RectF(gfx::PointF(), gfx::SizeF(500, 500));
371 EXPECT_TRUE(rootDamageRect.Contains(damageWeCareAbout));
374 TEST_F(DamageTrackerTest, verifyDamageForBlurredSurface)
376 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithOneSurface();
377 LayerImpl* child = root->children()[0];
379 WebFilterOperations filters;
380 filters.append(WebFilterOperation::createBlurFilter(5));
381 int outsetTop, outsetRight, outsetBottom, outsetLeft;
382 filters.getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft);
384 // Setting the filter will damage the whole surface.
385 clearDamageForAllSurfaces(root.get());
386 root->setFilters(filters);
387 emulateDrawingOneFrame(root.get());
389 // Setting the update rect should cause the corresponding damage to the surface, blurred based on the size of the blur filter.
390 clearDamageForAllSurfaces(root.get());
391 child->setUpdateRect(gfx::RectF(10, 11, 12, 13));
392 emulateDrawingOneFrame(root.get());
394 // Damage position on the surface should be: position of updateRect (10, 11) relative to the child (100, 100), but expanded by the blur outsets.
395 gfx::RectF rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
396 gfx::RectF expectedDamageRect = gfx::RectF(110, 111, 12, 13);
397 expectedDamageRect.Inset(-outsetLeft, -outsetTop, -outsetRight, -outsetBottom);
398 EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect);
401 TEST_F(DamageTrackerTest, verifyDamageForImageFilter)
403 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithOneSurface();
404 LayerImpl* child = root->children()[0];
405 gfx::RectF rootDamageRect, childDamageRect;
407 // Allow us to set damage on child too.
408 child->setDrawsContent(true);
410 skia::RefPtr<SkImageFilter> filter = skia::AdoptRef(new SkBlurImageFilter(SkIntToScalar(2), SkIntToScalar(2)));
411 // Setting the filter will damage the whole surface.
412 clearDamageForAllSurfaces(root.get());
413 child->setFilter(filter);
414 emulateDrawingOneFrame(root.get());
415 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
416 childDamageRect = child->renderSurface()->damageTracker()->currentDamageRect();
417 EXPECT_FLOAT_RECT_EQ(gfx::RectF(100, 100, 30, 30), rootDamageRect);
418 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 30, 30), childDamageRect);
420 // CASE 1: Setting the update rect should damage the whole surface (for now)
421 clearDamageForAllSurfaces(root.get());
422 child->setUpdateRect(gfx::RectF(0, 0, 1, 1));
423 emulateDrawingOneFrame(root.get());
425 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
426 childDamageRect = child->renderSurface()->damageTracker()->currentDamageRect();
427 EXPECT_FLOAT_RECT_EQ(gfx::RectF(100, 100, 30, 30), rootDamageRect);
428 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 30, 30), childDamageRect);
431 TEST_F(DamageTrackerTest, verifyDamageForBackgroundBlurredChild)
433 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces();
434 LayerImpl* child1 = root->children()[0];
435 LayerImpl* child2 = root->children()[1];
437 // Allow us to set damage on child1 too.
438 child1->setDrawsContent(true);
440 WebFilterOperations filters;
441 filters.append(WebFilterOperation::createBlurFilter(2));
442 int outsetTop, outsetRight, outsetBottom, outsetLeft;
443 filters.getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft);
445 // Setting the filter will damage the whole surface.
446 clearDamageForAllSurfaces(root.get());
447 child1->setBackgroundFilters(filters);
448 emulateDrawingOneFrame(root.get());
450 // CASE 1: Setting the update rect should cause the corresponding damage to
451 // the surface, blurred based on the size of the child's background blur
452 // filter.
453 clearDamageForAllSurfaces(root.get());
454 root->setUpdateRect(gfx::RectF(297, 297, 2, 2));
455 emulateDrawingOneFrame(root.get());
457 gfx::RectF rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
458 // Damage position on the surface should be a composition of the damage on the root and on child2.
459 // Damage on the root should be: position of updateRect (297, 297), but expanded by the blur outsets.
460 gfx::RectF expectedDamageRect = gfx::RectF(297, 297, 2, 2);
461 expectedDamageRect.Inset(-outsetLeft, -outsetTop, -outsetRight, -outsetBottom);
462 EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect);
464 // CASE 2: Setting the update rect should cause the corresponding damage to
465 // the surface, blurred based on the size of the child's background blur
466 // filter. Since the damage extends to the right/bottom outside of the
467 // blurred layer, only the left/top should end up expanded.
468 clearDamageForAllSurfaces(root.get());
469 root->setUpdateRect(gfx::RectF(297, 297, 30, 30));
470 emulateDrawingOneFrame(root.get());
472 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
473 // Damage position on the surface should be a composition of the damage on the root and on child2.
474 // Damage on the root should be: position of updateRect (297, 297), but expanded on the left/top
475 // by the blur outsets.
476 expectedDamageRect = gfx::RectF(297, 297, 30, 30);
477 expectedDamageRect.Inset(-outsetLeft, -outsetTop, 0, 0);
478 EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect);
480 // CASE 3: Setting this update rect outside the blurred contentBounds of the blurred
481 // child1 will not cause it to be expanded.
482 clearDamageForAllSurfaces(root.get());
483 root->setUpdateRect(gfx::RectF(30, 30, 2, 2));
484 emulateDrawingOneFrame(root.get());
486 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
487 // Damage on the root should be: position of updateRect (30, 30), not
488 // expanded.
489 expectedDamageRect = gfx::RectF(30, 30, 2, 2);
490 EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect);
492 // CASE 4: Setting this update rect inside the blurred contentBounds but outside the
493 // original contentBounds of the blurred child1 will cause it to be expanded.
494 clearDamageForAllSurfaces(root.get());
495 root->setUpdateRect(gfx::RectF(99, 99, 1, 1));
496 emulateDrawingOneFrame(root.get());
498 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
499 // Damage on the root should be: position of updateRect (99, 99), expanded
500 // by the blurring on child1, but since it is 1 pixel outside the layer, the
501 // expanding should be reduced by 1.
502 expectedDamageRect = gfx::RectF(99, 99, 1, 1);
503 expectedDamageRect.Inset(-outsetLeft + 1, -outsetTop + 1, -outsetRight, -outsetBottom);
504 EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect);
506 // CASE 5: Setting the update rect on child2, which is above child1, will
507 // not get blurred by child1, so it does not need to get expanded.
508 clearDamageForAllSurfaces(root.get());
509 child2->setUpdateRect(gfx::RectF(0, 0, 1, 1));
510 emulateDrawingOneFrame(root.get());
512 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
513 // Damage on child2 should be: position of updateRect offset by the child's position (11, 11), and not expanded by anything.
514 expectedDamageRect = gfx::RectF(11, 11, 1, 1);
515 EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect);
517 // CASE 6: Setting the update rect on child1 will also blur the damage, so
518 // that any pixels needed for the blur are redrawn in the current frame.
519 clearDamageForAllSurfaces(root.get());
520 child1->setUpdateRect(gfx::RectF(0, 0, 1, 1));
521 emulateDrawingOneFrame(root.get());
523 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
524 // Damage on child1 should be: position of updateRect offset by the child's position (100, 100), and expanded by the damage.
525 expectedDamageRect = gfx::RectF(100, 100, 1, 1);
526 expectedDamageRect.Inset(-outsetLeft, -outsetTop, -outsetRight, -outsetBottom);
527 EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect);
530 TEST_F(DamageTrackerTest, verifyDamageForAddingAndRemovingLayer)
532 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithOneSurface();
533 LayerImpl* child1 = root->children()[0];
535 // CASE 1: Adding a new layer should cause the appropriate damage.
537 clearDamageForAllSurfaces(root.get());
539 scoped_ptr<LayerImpl> child2 = LayerImpl::create(&m_hostImpl, 3);
540 child2->setPosition(gfx::PointF(400, 380));
541 child2->setAnchorPoint(gfx::PointF());
542 child2->setBounds(gfx::Size(6, 8));
543 child2->setContentBounds(gfx::Size(6, 8));
544 child2->setDrawsContent(true);
545 root->addChild(child2.Pass());
547 emulateDrawingOneFrame(root.get());
549 // Sanity check - all 3 layers should be on the same render surface; render surfaces are tested elsewhere.
550 ASSERT_EQ(3u, root->renderSurface()->layerList().size());
552 gfx::RectF rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
553 EXPECT_FLOAT_RECT_EQ(gfx::RectF(400, 380, 6, 8), rootDamageRect);
555 // CASE 2: If the layer is removed, its entire old layer becomes exposed, not just the
556 // last update rect.
558 // Advance one frame without damage so that we know the damage rect is not leftover from the previous case.
559 clearDamageForAllSurfaces(root.get());
560 emulateDrawingOneFrame(root.get());
561 EXPECT_TRUE(root->renderSurface()->damageTracker()->currentDamageRect().IsEmpty());
563 // Then, test removing child1.
564 root->removeChild(child1);
565 child1 = NULL;
566 emulateDrawingOneFrame(root.get());
567 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
568 EXPECT_FLOAT_RECT_EQ(gfx::RectF(100, 100, 30, 30), rootDamageRect);
571 TEST_F(DamageTrackerTest, verifyDamageForNewUnchangedLayer)
573 // If child2 is added to the layer tree, but it doesn't have any explicit damage of
574 // its own, it should still indeed damage the target surface.
576 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithOneSurface();
578 clearDamageForAllSurfaces(root.get());
580 scoped_ptr<LayerImpl> child2 = LayerImpl::create(&m_hostImpl, 3);
581 child2->setPosition(gfx::PointF(400, 380));
582 child2->setAnchorPoint(gfx::PointF());
583 child2->setBounds(gfx::Size(6, 8));
584 child2->setContentBounds(gfx::Size(6, 8));
585 child2->setDrawsContent(true);
586 child2->resetAllChangeTrackingForSubtree();
587 // Sanity check the initial conditions of the test, if these asserts trigger, it
588 // means the test no longer actually covers the intended scenario.
589 ASSERT_FALSE(child2->layerPropertyChanged());
590 ASSERT_TRUE(child2->updateRect().IsEmpty());
591 root->addChild(child2.Pass());
593 emulateDrawingOneFrame(root.get());
595 // Sanity check - all 3 layers should be on the same render surface; render surfaces are tested elsewhere.
596 ASSERT_EQ(3u, root->renderSurface()->layerList().size());
598 gfx::RectF rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
599 EXPECT_FLOAT_RECT_EQ(gfx::RectF(400, 380, 6, 8), rootDamageRect);
602 TEST_F(DamageTrackerTest, verifyDamageForMultipleLayers)
604 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithOneSurface();
605 LayerImpl* child1 = root->children()[0];
607 // In this test we don't want the above tree manipulation to be considered part of the same frame.
608 clearDamageForAllSurfaces(root.get());
610 scoped_ptr<LayerImpl> child2 = LayerImpl::create(&m_hostImpl, 3);
611 child2->setPosition(gfx::PointF(400, 380));
612 child2->setAnchorPoint(gfx::PointF());
613 child2->setBounds(gfx::Size(6, 8));
614 child2->setContentBounds(gfx::Size(6, 8));
615 child2->setDrawsContent(true);
616 root->addChild(child2.Pass());
618 LayerImpl* child2 = root->children()[1];
619 emulateDrawingOneFrame(root.get());
621 // Damaging two layers simultaneously should cause combined damage.
622 // - child1 update rect in surface space: gfx::RectF(100, 100, 1, 2);
623 // - child2 update rect in surface space: gfx::RectF(400, 380, 3, 4);
624 clearDamageForAllSurfaces(root.get());
625 child1->setUpdateRect(gfx::RectF(0, 0, 1, 2));
626 child2->setUpdateRect(gfx::RectF(0, 0, 3, 4));
627 emulateDrawingOneFrame(root.get());
628 gfx::RectF rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
629 EXPECT_FLOAT_RECT_EQ(gfx::RectF(100, 100, 303, 284), rootDamageRect);
632 TEST_F(DamageTrackerTest, verifyDamageForNestedSurfaces)
634 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces();
635 LayerImpl* child1 = root->children()[0];
636 LayerImpl* child2 = root->children()[1];
637 LayerImpl* grandChild1 = root->children()[0]->children()[0];
638 gfx::RectF childDamageRect;
639 gfx::RectF rootDamageRect;
641 // CASE 1: Damage to a descendant surface should propagate properly to ancestor surface.
643 clearDamageForAllSurfaces(root.get());
644 grandChild1->setOpacity(0.5);
645 emulateDrawingOneFrame(root.get());
646 childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRect();
647 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
648 EXPECT_FLOAT_RECT_EQ(gfx::RectF(200, 200, 6, 8), childDamageRect);
649 EXPECT_FLOAT_RECT_EQ(gfx::RectF(300, 300, 6, 8), rootDamageRect);
651 // CASE 2: Same as previous case, but with additional damage elsewhere that should be properly unioned.
652 // - child1 surface damage in root surface space: gfx::RectF(300, 300, 6, 8);
653 // - child2 damage in root surface space: gfx::RectF(11, 11, 18, 18);
654 clearDamageForAllSurfaces(root.get());
655 grandChild1->setOpacity(0.7f);
656 child2->setOpacity(0.7f);
657 emulateDrawingOneFrame(root.get());
658 childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRect();
659 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
660 EXPECT_FLOAT_RECT_EQ(gfx::RectF(200, 200, 6, 8), childDamageRect);
661 EXPECT_FLOAT_RECT_EQ(gfx::RectF(11, 11, 295, 297), rootDamageRect);
664 TEST_F(DamageTrackerTest, verifyDamageForSurfaceChangeFromDescendantLayer)
666 // If descendant layer changes and affects the content bounds of the render surface,
667 // then the entire descendant surface should be damaged, and it should damage its
668 // ancestor surface with the old and new surface regions.
670 // This is a tricky case, since only the first grandChild changes, but the entire
671 // surface should be marked dirty.
673 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces();
674 LayerImpl* child1 = root->children()[0];
675 LayerImpl* grandChild1 = root->children()[0]->children()[0];
676 gfx::RectF childDamageRect;
677 gfx::RectF rootDamageRect;
679 clearDamageForAllSurfaces(root.get());
680 grandChild1->setPosition(gfx::PointF(195, 205));
681 emulateDrawingOneFrame(root.get());
682 childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRect();
683 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
685 // The new surface bounds should be damaged entirely, even though only one of the layers changed.
686 EXPECT_FLOAT_RECT_EQ(gfx::RectF(190, 190, 11, 23), childDamageRect);
688 // Damage to the root surface should be the union of child1's *entire* render surface
689 // (in target space), and its old exposed area (also in target space).
690 EXPECT_FLOAT_RECT_EQ(gfx::RectF(290, 290, 16, 23), rootDamageRect);
693 TEST_F(DamageTrackerTest, verifyDamageForSurfaceChangeFromAncestorLayer)
695 // An ancestor/owning layer changes that affects the position/transform of the render
696 // surface. Note that in this case, the layerPropertyChanged flag already propagates
697 // to the subtree (tested in LayerImpltest), which damages the entire child1
698 // surface, but the damage tracker still needs the correct logic to compute the
699 // exposed region on the root surface.
701 // FIXME: the expectations of this test case should change when we add support for a
702 // unique scissorRect per renderSurface. In that case, the child1 surface
703 // should be completely unchanged, since we are only transforming it, while the
704 // root surface would be damaged appropriately.
706 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces();
707 LayerImpl* child1 = root->children()[0];
708 gfx::RectF childDamageRect;
709 gfx::RectF rootDamageRect;
711 clearDamageForAllSurfaces(root.get());
712 child1->setPosition(gfx::PointF(50, 50));
713 emulateDrawingOneFrame(root.get());
714 childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRect();
715 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
717 // The new surface bounds should be damaged entirely.
718 EXPECT_FLOAT_RECT_EQ(gfx::RectF(190, 190, 16, 18), childDamageRect);
720 // The entire child1 surface and the old exposed child1 surface should damage the root surface.
721 // - old child1 surface in target space: gfx::RectF(290, 290, 16, 18)
722 // - new child1 surface in target space: gfx::RectF(240, 240, 16, 18)
723 EXPECT_FLOAT_RECT_EQ(gfx::RectF(240, 240, 66, 68), rootDamageRect);
726 TEST_F(DamageTrackerTest, verifyDamageForAddingAndRemovingRenderSurfaces)
728 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces();
729 LayerImpl* child1 = root->children()[0];
730 gfx::RectF childDamageRect;
731 gfx::RectF rootDamageRect;
733 // CASE 1: If a descendant surface disappears, its entire old area becomes exposed.
735 clearDamageForAllSurfaces(root.get());
736 child1->setOpacity(1);
737 child1->setForceRenderSurface(false);
738 emulateDrawingOneFrame(root.get());
740 // Sanity check that there is only one surface now.
741 ASSERT_FALSE(child1->renderSurface());
742 ASSERT_EQ(4u, root->renderSurface()->layerList().size());
744 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
745 EXPECT_FLOAT_RECT_EQ(gfx::RectF(290, 290, 16, 18), rootDamageRect);
747 // CASE 2: If a descendant surface appears, its entire old area becomes exposed.
749 // Cycle one frame of no change, just to sanity check that the next rect is not because of the old damage state.
750 clearDamageForAllSurfaces(root.get());
751 emulateDrawingOneFrame(root.get());
752 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
753 EXPECT_TRUE(rootDamageRect.IsEmpty());
755 // Then change the tree so that the render surface is added back.
756 clearDamageForAllSurfaces(root.get());
757 child1->setOpacity(0.5);
758 child1->setForceRenderSurface(true);
759 emulateDrawingOneFrame(root.get());
761 // Sanity check that there is a new surface now.
762 ASSERT_TRUE(child1->renderSurface());
763 EXPECT_EQ(3u, root->renderSurface()->layerList().size());
764 EXPECT_EQ(2u, child1->renderSurface()->layerList().size());
766 childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRect();
767 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
768 EXPECT_FLOAT_RECT_EQ(gfx::RectF(190, 190, 16, 18), childDamageRect);
769 EXPECT_FLOAT_RECT_EQ(gfx::RectF(290, 290, 16, 18), rootDamageRect);
772 TEST_F(DamageTrackerTest, verifyNoDamageWhenNothingChanged)
774 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces();
775 LayerImpl* child1 = root->children()[0];
776 gfx::RectF childDamageRect;
777 gfx::RectF rootDamageRect;
779 // CASE 1: If nothing changes, the damage rect should be empty.
781 clearDamageForAllSurfaces(root.get());
782 emulateDrawingOneFrame(root.get());
783 childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRect();
784 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
785 EXPECT_TRUE(childDamageRect.IsEmpty());
786 EXPECT_TRUE(rootDamageRect.IsEmpty());
788 // CASE 2: If nothing changes twice in a row, the damage rect should still be empty.
790 clearDamageForAllSurfaces(root.get());
791 emulateDrawingOneFrame(root.get());
792 childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRect();
793 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
794 EXPECT_TRUE(childDamageRect.IsEmpty());
795 EXPECT_TRUE(rootDamageRect.IsEmpty());
798 TEST_F(DamageTrackerTest, verifyNoDamageForUpdateRectThatDoesNotDrawContent)
800 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces();
801 LayerImpl* child1 = root->children()[0];
802 gfx::RectF childDamageRect;
803 gfx::RectF rootDamageRect;
805 // In our specific tree, the update rect of child1 should not cause any damage to any
806 // surface because it does not actually draw content.
807 clearDamageForAllSurfaces(root.get());
808 child1->setUpdateRect(gfx::RectF(0, 0, 1, 2));
809 emulateDrawingOneFrame(root.get());
810 childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRect();
811 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
812 EXPECT_TRUE(childDamageRect.IsEmpty());
813 EXPECT_TRUE(rootDamageRect.IsEmpty());
816 TEST_F(DamageTrackerTest, verifyDamageForReplica)
818 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces();
819 LayerImpl* child1 = root->children()[0];
820 LayerImpl* grandChild1 = child1->children()[0];
821 LayerImpl* grandChild2 = child1->children()[1];
823 // Damage on a surface that has a reflection should cause the target surface to
824 // receive the surface's damage and the surface's reflected damage.
826 // For this test case, we modify grandChild2, and add grandChild3 to extend the bounds
827 // of child1's surface. This way, we can test reflection changes without changing
828 // contentBounds of the surface.
829 grandChild2->setPosition(gfx::PointF(180, 180));
831 scoped_ptr<LayerImpl> grandChild3 = LayerImpl::create(&m_hostImpl, 6);
832 grandChild3->setPosition(gfx::PointF(240, 240));
833 grandChild3->setAnchorPoint(gfx::PointF());
834 grandChild3->setBounds(gfx::Size(10, 10));
835 grandChild3->setContentBounds(gfx::Size(10, 10));
836 grandChild3->setDrawsContent(true);
837 child1->addChild(grandChild3.Pass());
839 child1->setOpacity(0.5);
840 emulateDrawingOneFrame(root.get());
842 // CASE 1: adding a reflection about the left edge of grandChild1.
844 clearDamageForAllSurfaces(root.get());
846 scoped_ptr<LayerImpl> grandChild1Replica = LayerImpl::create(&m_hostImpl, 7);
847 grandChild1Replica->setPosition(gfx::PointF());
848 grandChild1Replica->setAnchorPoint(gfx::PointF());
849 gfx::Transform reflection;
850 reflection.Scale3d(-1, 1, 1);
851 grandChild1Replica->setTransform(reflection);
852 grandChild1->setReplicaLayer(grandChild1Replica.Pass());
854 emulateDrawingOneFrame(root.get());
856 gfx::RectF grandChildDamageRect = grandChild1->renderSurface()->damageTracker()->currentDamageRect();
857 gfx::RectF childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRect();
858 gfx::RectF rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
860 // The grandChild surface damage should not include its own replica. The child
861 // surface damage should include the normal and replica surfaces.
862 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 6, 8), grandChildDamageRect);
863 EXPECT_FLOAT_RECT_EQ(gfx::RectF(194, 200, 12, 8), childDamageRect);
864 EXPECT_FLOAT_RECT_EQ(gfx::RectF(294, 300, 12, 8), rootDamageRect);
866 // CASE 2: moving the descendant surface should cause both the original and reflected
867 // areas to be damaged on the target.
868 clearDamageForAllSurfaces(root.get());
869 gfx::Rect oldContentRect = child1->renderSurface()->contentRect();
870 grandChild1->setPosition(gfx::PointF(195, 205));
871 emulateDrawingOneFrame(root.get());
872 ASSERT_EQ(oldContentRect.width(), child1->renderSurface()->contentRect().width());
873 ASSERT_EQ(oldContentRect.height(), child1->renderSurface()->contentRect().height());
875 grandChildDamageRect = grandChild1->renderSurface()->damageTracker()->currentDamageRect();
876 childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRect();
877 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
879 // The child surface damage should include normal and replica surfaces for both old and new locations.
880 // - old location in target space: gfx::RectF(194, 200, 12, 8)
881 // - new location in target space: gfx::RectF(189, 205, 12, 8)
882 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 6, 8), grandChildDamageRect);
883 EXPECT_FLOAT_RECT_EQ(gfx::RectF(189, 200, 17, 13), childDamageRect);
884 EXPECT_FLOAT_RECT_EQ(gfx::RectF(289, 300, 17, 13), rootDamageRect);
886 // CASE 3: removing the reflection should cause the entire region including reflection
887 // to damage the target surface.
888 clearDamageForAllSurfaces(root.get());
889 grandChild1->setReplicaLayer(scoped_ptr<LayerImpl>());
890 emulateDrawingOneFrame(root.get());
891 ASSERT_EQ(oldContentRect.width(), child1->renderSurface()->contentRect().width());
892 ASSERT_EQ(oldContentRect.height(), child1->renderSurface()->contentRect().height());
894 EXPECT_FALSE(grandChild1->renderSurface());
895 childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRect();
896 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
898 EXPECT_FLOAT_RECT_EQ(gfx::RectF(189, 205, 12, 8), childDamageRect);
899 EXPECT_FLOAT_RECT_EQ(gfx::RectF(289, 305, 12, 8), rootDamageRect);
902 TEST_F(DamageTrackerTest, verifyDamageForMask)
904 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithOneSurface();
905 LayerImpl* child = root->children()[0];
907 // In the current implementation of the damage tracker, changes to mask layers should
908 // damage the entire corresponding surface.
910 clearDamageForAllSurfaces(root.get());
912 // Set up the mask layer.
914 scoped_ptr<LayerImpl> maskLayer = LayerImpl::create(&m_hostImpl, 3);
915 maskLayer->setPosition(child->position());
916 maskLayer->setAnchorPoint(gfx::PointF());
917 maskLayer->setBounds(child->bounds());
918 maskLayer->setContentBounds(child->bounds());
919 child->setMaskLayer(maskLayer.Pass());
921 LayerImpl* maskLayer = child->maskLayer();
923 // Add opacity and a grandChild so that the render surface persists even after we remove the mask.
924 child->setOpacity(0.5);
926 scoped_ptr<LayerImpl> grandChild = LayerImpl::create(&m_hostImpl, 4);
927 grandChild->setPosition(gfx::PointF(2, 2));
928 grandChild->setAnchorPoint(gfx::PointF());
929 grandChild->setBounds(gfx::Size(2, 2));
930 grandChild->setContentBounds(gfx::Size(2, 2));
931 grandChild->setDrawsContent(true);
932 child->addChild(grandChild.Pass());
934 emulateDrawingOneFrame(root.get());
936 // Sanity check that a new surface was created for the child.
937 ASSERT_TRUE(child->renderSurface());
939 // CASE 1: the updateRect on a mask layer should damage the entire target surface.
941 clearDamageForAllSurfaces(root.get());
942 maskLayer->setUpdateRect(gfx::RectF(1, 2, 3, 4));
943 emulateDrawingOneFrame(root.get());
944 gfx::RectF childDamageRect = child->renderSurface()->damageTracker()->currentDamageRect();
945 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 30, 30), childDamageRect);
947 // CASE 2: a property change on the mask layer should damage the entire target surface.
950 // Advance one frame without damage so that we know the damage rect is not leftover from the previous case.
951 clearDamageForAllSurfaces(root.get());
952 emulateDrawingOneFrame(root.get());
953 childDamageRect = child->renderSurface()->damageTracker()->currentDamageRect();
954 EXPECT_TRUE(childDamageRect.IsEmpty());
956 // Then test the property change.
957 clearDamageForAllSurfaces(root.get());
958 maskLayer->setStackingOrderChanged(true);
960 emulateDrawingOneFrame(root.get());
961 childDamageRect = child->renderSurface()->damageTracker()->currentDamageRect();
962 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 30, 30), childDamageRect);
964 // CASE 3: removing the mask also damages the entire target surface.
967 // Advance one frame without damage so that we know the damage rect is not leftover from the previous case.
968 clearDamageForAllSurfaces(root.get());
969 emulateDrawingOneFrame(root.get());
970 childDamageRect = child->renderSurface()->damageTracker()->currentDamageRect();
971 EXPECT_TRUE(childDamageRect.IsEmpty());
973 // Then test mask removal.
974 clearDamageForAllSurfaces(root.get());
975 child->setMaskLayer(scoped_ptr<LayerImpl>());
976 ASSERT_TRUE(child->layerPropertyChanged());
977 emulateDrawingOneFrame(root.get());
979 // Sanity check that a render surface still exists.
980 ASSERT_TRUE(child->renderSurface());
982 childDamageRect = child->renderSurface()->damageTracker()->currentDamageRect();
983 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 30, 30), childDamageRect);
986 TEST_F(DamageTrackerTest, verifyDamageForReplicaMask)
988 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces();
989 LayerImpl* child1 = root->children()[0];
990 LayerImpl* grandChild1 = child1->children()[0];
992 // Changes to a replica's mask should not damage the original surface, because it is
993 // not masked. But it does damage the ancestor target surface.
995 clearDamageForAllSurfaces(root.get());
997 // Create a reflection about the left edge of grandChild1.
999 scoped_ptr<LayerImpl> grandChild1Replica = LayerImpl::create(&m_hostImpl, 6);
1000 grandChild1Replica->setPosition(gfx::PointF());
1001 grandChild1Replica->setAnchorPoint(gfx::PointF());
1002 gfx::Transform reflection;
1003 reflection.Scale3d(-1, 1, 1);
1004 grandChild1Replica->setTransform(reflection);
1005 grandChild1->setReplicaLayer(grandChild1Replica.Pass());
1007 LayerImpl* grandChild1Replica = grandChild1->replicaLayer();
1009 // Set up the mask layer on the replica layer
1011 scoped_ptr<LayerImpl> replicaMaskLayer = LayerImpl::create(&m_hostImpl, 7);
1012 replicaMaskLayer->setPosition(gfx::PointF());
1013 replicaMaskLayer->setAnchorPoint(gfx::PointF());
1014 replicaMaskLayer->setBounds(grandChild1->bounds());
1015 replicaMaskLayer->setContentBounds(grandChild1->bounds());
1016 grandChild1Replica->setMaskLayer(replicaMaskLayer.Pass());
1018 LayerImpl* replicaMaskLayer = grandChild1Replica->maskLayer();
1020 emulateDrawingOneFrame(root.get());
1022 // Sanity check that the appropriate render surfaces were created
1023 ASSERT_TRUE(grandChild1->renderSurface());
1025 // CASE 1: a property change on the mask should damage only the reflected region on the target surface.
1026 clearDamageForAllSurfaces(root.get());
1027 replicaMaskLayer->setStackingOrderChanged(true);
1028 emulateDrawingOneFrame(root.get());
1030 gfx::RectF grandChildDamageRect = grandChild1->renderSurface()->damageTracker()->currentDamageRect();
1031 gfx::RectF childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRect();
1033 EXPECT_TRUE(grandChildDamageRect.IsEmpty());
1034 EXPECT_FLOAT_RECT_EQ(gfx::RectF(194, 200, 6, 8), childDamageRect);
1036 // CASE 2: removing the replica mask damages only the reflected region on the target surface.
1038 clearDamageForAllSurfaces(root.get());
1039 grandChild1Replica->setMaskLayer(scoped_ptr<LayerImpl>());
1040 emulateDrawingOneFrame(root.get());
1042 grandChildDamageRect = grandChild1->renderSurface()->damageTracker()->currentDamageRect();
1043 childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRect();
1045 EXPECT_TRUE(grandChildDamageRect.IsEmpty());
1046 EXPECT_FLOAT_RECT_EQ(gfx::RectF(194, 200, 6, 8), childDamageRect);
1049 TEST_F(DamageTrackerTest, verifyDamageForReplicaMaskWithAnchor)
1051 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces();
1052 LayerImpl* child1 = root->children()[0];
1053 LayerImpl* grandChild1 = child1->children()[0];
1055 // Verify that the correct replicaOriginTransform is used for the replicaMask;
1056 clearDamageForAllSurfaces(root.get());
1058 grandChild1->setAnchorPoint(gfx::PointF(1, 0)); // This is not exactly the anchor being tested, but by convention its expected to be the same as the replica's anchor point.
1061 scoped_ptr<LayerImpl> grandChild1Replica = LayerImpl::create(&m_hostImpl, 6);
1062 grandChild1Replica->setPosition(gfx::PointF());
1063 grandChild1Replica->setAnchorPoint(gfx::PointF(1, 0)); // This is the anchor being tested.
1064 gfx::Transform reflection;
1065 reflection.Scale3d(-1, 1, 1);
1066 grandChild1Replica->setTransform(reflection);
1067 grandChild1->setReplicaLayer(grandChild1Replica.Pass());
1069 LayerImpl* grandChild1Replica = grandChild1->replicaLayer();
1071 // Set up the mask layer on the replica layer
1073 scoped_ptr<LayerImpl> replicaMaskLayer = LayerImpl::create(&m_hostImpl, 7);
1074 replicaMaskLayer->setPosition(gfx::PointF());
1075 replicaMaskLayer->setAnchorPoint(gfx::PointF()); // note, this is not the anchor being tested.
1076 replicaMaskLayer->setBounds(grandChild1->bounds());
1077 replicaMaskLayer->setContentBounds(grandChild1->bounds());
1078 grandChild1Replica->setMaskLayer(replicaMaskLayer.Pass());
1080 LayerImpl* replicaMaskLayer = grandChild1Replica->maskLayer();
1082 emulateDrawingOneFrame(root.get());
1084 // Sanity check that the appropriate render surfaces were created
1085 ASSERT_TRUE(grandChild1->renderSurface());
1087 // A property change on the replicaMask should damage the reflected region on the target surface.
1088 clearDamageForAllSurfaces(root.get());
1089 replicaMaskLayer->setStackingOrderChanged(true);
1091 emulateDrawingOneFrame(root.get());
1093 gfx::RectF childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRect();
1094 EXPECT_FLOAT_RECT_EQ(gfx::RectF(206, 200, 6, 8), childDamageRect);
1097 TEST_F(DamageTrackerTest, verifyDamageWhenForcedFullDamage)
1099 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithOneSurface();
1100 LayerImpl* child = root->children()[0];
1102 // Case 1: This test ensures that when the tracker is forced to have full damage, that
1103 // it takes priority over any other partial damage.
1105 clearDamageForAllSurfaces(root.get());
1106 child->setUpdateRect(gfx::RectF(10, 11, 12, 13));
1107 root->renderSurface()->damageTracker()->forceFullDamageNextUpdate();
1108 emulateDrawingOneFrame(root.get());
1109 gfx::RectF rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
1110 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 500, 500), rootDamageRect);
1112 // Case 2: An additional sanity check that forcing full damage works even when nothing
1113 // on the layer tree changed.
1115 clearDamageForAllSurfaces(root.get());
1116 root->renderSurface()->damageTracker()->forceFullDamageNextUpdate();
1117 emulateDrawingOneFrame(root.get());
1118 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
1119 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 500, 500), rootDamageRect);
1122 TEST_F(DamageTrackerTest, verifyDamageForEmptyLayerList)
1124 // Though it should never happen, its a good idea to verify that the damage tracker
1125 // does not crash when it receives an empty layerList.
1127 scoped_ptr<LayerImpl> root = LayerImpl::create(&m_hostImpl, 1);
1128 root->createRenderSurface();
1130 ASSERT_TRUE(root == root->renderTarget());
1131 RenderSurfaceImpl* targetSurface = root->renderSurface();
1132 targetSurface->clearLayerLists();
1133 targetSurface->damageTracker()->updateDamageTrackingState(targetSurface->layerList(), targetSurface->owningLayerId(), false, gfx::Rect(), 0, WebFilterOperations(), 0);
1135 gfx::RectF damageRect = targetSurface->damageTracker()->currentDamageRect();
1136 EXPECT_TRUE(damageRect.IsEmpty());
1139 TEST_F(DamageTrackerTest, verifyDamageAccumulatesUntilReset)
1141 // If damage is not cleared, it should accumulate.
1143 scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithOneSurface();
1144 LayerImpl* child = root->children()[0];
1146 clearDamageForAllSurfaces(root.get());
1147 child->setUpdateRect(gfx::RectF(10, 11, 1, 2));
1148 emulateDrawingOneFrame(root.get());
1150 // Sanity check damage after the first frame; this isnt the actual test yet.
1151 gfx::RectF rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
1152 EXPECT_FLOAT_RECT_EQ(gfx::RectF(110, 111, 1, 2), rootDamageRect);
1154 // New damage, without having cleared the previous damage, should be unioned to the previous one.
1155 child->setUpdateRect(gfx::RectF(20, 25, 1, 2));
1156 emulateDrawingOneFrame(root.get());
1157 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
1158 EXPECT_FLOAT_RECT_EQ(gfx::RectF(110, 111, 11, 16), rootDamageRect);
1160 // If we notify the damage tracker that we drew the damaged area, then damage should be emptied.
1161 root->renderSurface()->damageTracker()->didDrawDamagedArea();
1162 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
1163 EXPECT_TRUE(rootDamageRect.IsEmpty());
1165 // Damage should remain empty even after one frame, since there's yet no new damage
1166 emulateDrawingOneFrame(root.get());
1167 rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
1168 EXPECT_TRUE(rootDamageRect.IsEmpty());
1171 } // namespace
1172 } // namespace cc