1 // Copyright 2012 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/trees/occlusion_tracker.h"
7 #include "cc/animation/layer_animation_controller.h"
8 #include "cc/base/math_util.h"
9 #include "cc/layers/layer.h"
10 #include "cc/layers/layer_impl.h"
11 #include "cc/output/copy_output_request.h"
12 #include "cc/output/copy_output_result.h"
13 #include "cc/output/filter_operation.h"
14 #include "cc/output/filter_operations.h"
15 #include "cc/test/animation_test_common.h"
16 #include "cc/test/fake_impl_proxy.h"
17 #include "cc/test/fake_layer_tree_host.h"
18 #include "cc/test/fake_layer_tree_host_impl.h"
19 #include "cc/test/geometry_test_utils.h"
20 #include "cc/test/test_occlusion_tracker.h"
21 #include "cc/trees/layer_tree_host_common.h"
22 #include "cc/trees/single_thread_proxy.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "ui/gfx/transform.h"
30 class TestContentLayer : public Layer {
32 TestContentLayer() : Layer(), override_opaque_contents_rect_(false) {
36 virtual Region VisibleContentOpaqueRegion() const OVERRIDE {
37 if (override_opaque_contents_rect_)
38 return gfx::IntersectRects(opaque_contents_rect_, visible_content_rect());
39 return Layer::VisibleContentOpaqueRegion();
41 void SetOpaqueContentsRect(const gfx::Rect& opaque_contents_rect) {
42 override_opaque_contents_rect_ = true;
43 opaque_contents_rect_ = opaque_contents_rect;
47 virtual ~TestContentLayer() {}
49 bool override_opaque_contents_rect_;
50 gfx::Rect opaque_contents_rect_;
53 class TestContentLayerImpl : public LayerImpl {
55 TestContentLayerImpl(LayerTreeImpl* tree_impl, int id)
56 : LayerImpl(tree_impl, id), override_opaque_contents_rect_(false) {
57 SetDrawsContent(true);
60 virtual Region VisibleContentOpaqueRegion() const OVERRIDE {
61 if (override_opaque_contents_rect_)
62 return gfx::IntersectRects(opaque_contents_rect_, visible_content_rect());
63 return LayerImpl::VisibleContentOpaqueRegion();
65 void SetOpaqueContentsRect(const gfx::Rect& opaque_contents_rect) {
66 override_opaque_contents_rect_ = true;
67 opaque_contents_rect_ = opaque_contents_rect;
71 bool override_opaque_contents_rect_;
72 gfx::Rect opaque_contents_rect_;
75 template <typename LayerType>
76 class TestOcclusionTrackerWithClip : public TestOcclusionTracker<LayerType> {
78 explicit TestOcclusionTrackerWithClip(const gfx::Rect& viewport_rect)
79 : TestOcclusionTracker<LayerType>(viewport_rect) {}
81 bool OccludedLayer(const LayerType* layer,
82 const gfx::Rect& content_rect) const {
83 DCHECK(layer->visible_content_rect().Contains(content_rect));
84 return this->Occluded(
85 layer->render_target(), content_rect, layer->draw_transform());
88 // Gives an unoccluded sub-rect of |content_rect| in the content space of the
89 // layer. Simple wrapper around UnoccludedContentRect.
90 gfx::Rect UnoccludedLayerContentRect(const LayerType* layer,
91 const gfx::Rect& content_rect) const {
92 DCHECK(layer->visible_content_rect().Contains(content_rect));
93 return this->UnoccludedContentRect(content_rect, layer->draw_transform());
96 gfx::Rect UnoccludedSurfaceContentRect(const LayerType* layer,
98 const gfx::Rect& content_rect) const {
99 typename LayerType::RenderSurfaceType* surface = layer->render_surface();
100 gfx::Transform draw_transform = for_replica
101 ? surface->replica_draw_transform()
102 : surface->draw_transform();
103 return this->UnoccludedContributingSurfaceContentRect(content_rect,
108 struct OcclusionTrackerTestMainThreadTypes {
109 typedef Layer LayerType;
110 typedef FakeLayerTreeHost HostType;
111 typedef RenderSurface RenderSurfaceType;
112 typedef TestContentLayer ContentLayerType;
113 typedef scoped_refptr<Layer> LayerPtrType;
114 typedef scoped_refptr<ContentLayerType> ContentLayerPtrType;
115 typedef LayerIterator<Layer> TestLayerIterator;
116 typedef OcclusionTracker<Layer> OcclusionTrackerType;
118 static LayerPtrType CreateLayer(HostType* host) { return Layer::Create(); }
119 static ContentLayerPtrType CreateContentLayer(HostType* host) {
120 return make_scoped_refptr(new ContentLayerType());
123 static LayerPtrType PassLayerPtr(ContentLayerPtrType* layer) {
124 LayerPtrType ref(*layer);
129 static LayerPtrType PassLayerPtr(LayerPtrType* layer) {
130 LayerPtrType ref(*layer);
135 static void DestroyLayer(LayerPtrType* layer) { *layer = NULL; }
138 struct OcclusionTrackerTestImplThreadTypes {
139 typedef LayerImpl LayerType;
140 typedef LayerTreeImpl HostType;
141 typedef RenderSurfaceImpl RenderSurfaceType;
142 typedef TestContentLayerImpl ContentLayerType;
143 typedef scoped_ptr<LayerImpl> LayerPtrType;
144 typedef scoped_ptr<ContentLayerType> ContentLayerPtrType;
145 typedef LayerIterator<LayerImpl> TestLayerIterator;
146 typedef OcclusionTracker<LayerImpl> OcclusionTrackerType;
148 static LayerPtrType CreateLayer(HostType* host) {
149 return LayerImpl::Create(host, next_layer_impl_id++);
151 static ContentLayerPtrType CreateContentLayer(HostType* host) {
152 return make_scoped_ptr(new ContentLayerType(host, next_layer_impl_id++));
154 static int next_layer_impl_id;
156 static LayerPtrType PassLayerPtr(LayerPtrType* layer) {
157 return layer->Pass();
160 static LayerPtrType PassLayerPtr(ContentLayerPtrType* layer) {
161 return layer->PassAs<LayerType>();
164 static void DestroyLayer(LayerPtrType* layer) { layer->reset(); }
167 int OcclusionTrackerTestImplThreadTypes::next_layer_impl_id = 1;
169 template <typename Types> class OcclusionTrackerTest : public testing::Test {
171 explicit OcclusionTrackerTest(bool opaque_layers)
172 : opaque_layers_(opaque_layers), host_(FakeLayerTreeHost::Create()) {}
174 virtual void RunMyTest() = 0;
176 virtual void TearDown() {
177 Types::DestroyLayer(&root_);
178 render_surface_layer_list_.reset();
179 render_surface_layer_list_impl_.clear();
180 replica_layers_.clear();
181 mask_layers_.clear();
184 typename Types::HostType* GetHost();
186 typename Types::ContentLayerType* CreateRoot(const gfx::Transform& transform,
187 const gfx::PointF& position,
188 const gfx::Size& bounds) {
189 typename Types::ContentLayerPtrType layer(
190 Types::CreateContentLayer(GetHost()));
191 typename Types::ContentLayerType* layer_ptr = layer.get();
192 SetProperties(layer_ptr, transform, position, bounds);
194 DCHECK(!root_.get());
195 root_ = Types::PassLayerPtr(&layer);
197 SetRootLayerOnMainThread(layer_ptr);
202 typename Types::LayerType* CreateLayer(typename Types::LayerType* parent,
203 const gfx::Transform& transform,
204 const gfx::PointF& position,
205 const gfx::Size& bounds) {
206 typename Types::LayerPtrType layer(Types::CreateLayer(GetHost()));
207 typename Types::LayerType* layer_ptr = layer.get();
208 SetProperties(layer_ptr, transform, position, bounds);
209 parent->AddChild(Types::PassLayerPtr(&layer));
213 typename Types::LayerType* CreateSurface(typename Types::LayerType* parent,
214 const gfx::Transform& transform,
215 const gfx::PointF& position,
216 const gfx::Size& bounds) {
217 typename Types::LayerType* layer =
218 CreateLayer(parent, transform, position, bounds);
219 layer->SetForceRenderSurface(true);
223 typename Types::ContentLayerType* CreateDrawingLayer(
224 typename Types::LayerType* parent,
225 const gfx::Transform& transform,
226 const gfx::PointF& position,
227 const gfx::Size& bounds,
229 typename Types::ContentLayerPtrType layer(
230 Types::CreateContentLayer(GetHost()));
231 typename Types::ContentLayerType* layer_ptr = layer.get();
232 SetProperties(layer_ptr, transform, position, bounds);
234 if (opaque_layers_) {
235 layer_ptr->SetContentsOpaque(opaque);
237 layer_ptr->SetContentsOpaque(false);
239 layer_ptr->SetOpaqueContentsRect(gfx::Rect(bounds));
241 layer_ptr->SetOpaqueContentsRect(gfx::Rect());
244 parent->AddChild(Types::PassLayerPtr(&layer));
248 typename Types::LayerType* CreateReplicaLayer(
249 typename Types::LayerType* owning_layer,
250 const gfx::Transform& transform,
251 const gfx::PointF& position,
252 const gfx::Size& bounds) {
253 typename Types::ContentLayerPtrType layer(
254 Types::CreateContentLayer(GetHost()));
255 typename Types::ContentLayerType* layer_ptr = layer.get();
256 SetProperties(layer_ptr, transform, position, bounds);
257 SetReplica(owning_layer, Types::PassLayerPtr(&layer));
261 typename Types::LayerType* CreateMaskLayer(
262 typename Types::LayerType* owning_layer,
263 const gfx::Size& bounds) {
264 typename Types::ContentLayerPtrType layer(
265 Types::CreateContentLayer(GetHost()));
266 typename Types::ContentLayerType* layer_ptr = layer.get();
267 SetProperties(layer_ptr, identity_matrix, gfx::PointF(), bounds);
268 SetMask(owning_layer, Types::PassLayerPtr(&layer));
272 typename Types::ContentLayerType* CreateDrawingSurface(
273 typename Types::LayerType* parent,
274 const gfx::Transform& transform,
275 const gfx::PointF& position,
276 const gfx::Size& bounds,
278 typename Types::ContentLayerType* layer =
279 CreateDrawingLayer(parent, transform, position, bounds, opaque);
280 layer->SetForceRenderSurface(true);
285 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {}
287 void AddCopyRequest(Layer* layer) {
288 layer->RequestCopyOfOutput(
289 CopyOutputRequest::CreateBitmapRequest(base::Bind(
290 &OcclusionTrackerTest<Types>::CopyOutputCallback,
291 base::Unretained(this))));
294 void AddCopyRequest(LayerImpl* layer) {
295 ScopedPtrVector<CopyOutputRequest> requests;
297 CopyOutputRequest::CreateBitmapRequest(base::Bind(
298 &OcclusionTrackerTest<Types>::CopyOutputCallback,
299 base::Unretained(this))));
300 layer->PassCopyRequests(&requests);
303 void CalcDrawEtc(TestContentLayerImpl* root) {
304 DCHECK(root == root_.get());
305 DCHECK(!root->render_surface());
307 LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
308 root, root->bounds(), &render_surface_layer_list_impl_);
309 inputs.can_adjust_raster_scales = true;
310 LayerTreeHostCommon::CalculateDrawProperties(&inputs);
312 layer_iterator_ = layer_iterator_begin_ =
313 Types::TestLayerIterator::Begin(&render_surface_layer_list_impl_);
316 void CalcDrawEtc(TestContentLayer* root) {
317 DCHECK(root == root_.get());
318 DCHECK(!root->render_surface());
320 render_surface_layer_list_.reset(new RenderSurfaceLayerList);
321 LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
322 root, root->bounds(), render_surface_layer_list_.get());
323 inputs.can_adjust_raster_scales = true;
324 LayerTreeHostCommon::CalculateDrawProperties(&inputs);
326 layer_iterator_ = layer_iterator_begin_ =
327 Types::TestLayerIterator::Begin(render_surface_layer_list_.get());
330 void EnterLayer(typename Types::LayerType* layer,
331 typename Types::OcclusionTrackerType* occlusion) {
332 ASSERT_EQ(layer, *layer_iterator_);
333 ASSERT_TRUE(layer_iterator_.represents_itself());
334 occlusion->EnterLayer(layer_iterator_);
337 void LeaveLayer(typename Types::LayerType* layer,
338 typename Types::OcclusionTrackerType* occlusion) {
339 ASSERT_EQ(layer, *layer_iterator_);
340 ASSERT_TRUE(layer_iterator_.represents_itself());
341 occlusion->LeaveLayer(layer_iterator_);
345 void VisitLayer(typename Types::LayerType* layer,
346 typename Types::OcclusionTrackerType* occlusion) {
347 EnterLayer(layer, occlusion);
348 LeaveLayer(layer, occlusion);
351 void EnterContributingSurface(
352 typename Types::LayerType* layer,
353 typename Types::OcclusionTrackerType* occlusion) {
354 ASSERT_EQ(layer, *layer_iterator_);
355 ASSERT_TRUE(layer_iterator_.represents_target_render_surface());
356 occlusion->EnterLayer(layer_iterator_);
357 occlusion->LeaveLayer(layer_iterator_);
359 ASSERT_TRUE(layer_iterator_.represents_contributing_render_surface());
360 occlusion->EnterLayer(layer_iterator_);
363 void LeaveContributingSurface(
364 typename Types::LayerType* layer,
365 typename Types::OcclusionTrackerType* occlusion) {
366 ASSERT_EQ(layer, *layer_iterator_);
367 ASSERT_TRUE(layer_iterator_.represents_contributing_render_surface());
368 occlusion->LeaveLayer(layer_iterator_);
372 void VisitContributingSurface(
373 typename Types::LayerType* layer,
374 typename Types::OcclusionTrackerType* occlusion) {
375 EnterContributingSurface(layer, occlusion);
376 LeaveContributingSurface(layer, occlusion);
379 void ResetLayerIterator() { layer_iterator_ = layer_iterator_begin_; }
381 const gfx::Transform identity_matrix;
384 void SetRootLayerOnMainThread(Layer* root) {
385 host_->SetRootLayer(scoped_refptr<Layer>(root));
388 void SetRootLayerOnMainThread(LayerImpl* root) {}
390 void SetBaseProperties(typename Types::LayerType* layer,
391 const gfx::Transform& transform,
392 const gfx::PointF& position,
393 const gfx::Size& bounds) {
394 layer->SetTransform(transform);
395 layer->SetPosition(position);
396 layer->SetBounds(bounds);
399 void SetProperties(Layer* layer,
400 const gfx::Transform& transform,
401 const gfx::PointF& position,
402 const gfx::Size& bounds) {
403 SetBaseProperties(layer, transform, position, bounds);
406 void SetProperties(LayerImpl* layer,
407 const gfx::Transform& transform,
408 const gfx::PointF& position,
409 const gfx::Size& bounds) {
410 SetBaseProperties(layer, transform, position, bounds);
412 layer->SetContentBounds(layer->bounds());
415 void SetReplica(Layer* owning_layer, scoped_refptr<Layer> layer) {
416 owning_layer->SetReplicaLayer(layer.get());
417 replica_layers_.push_back(layer);
420 void SetReplica(LayerImpl* owning_layer, scoped_ptr<LayerImpl> layer) {
421 owning_layer->SetReplicaLayer(layer.Pass());
424 void SetMask(Layer* owning_layer, scoped_refptr<Layer> layer) {
425 owning_layer->SetMaskLayer(layer.get());
426 mask_layers_.push_back(layer);
429 void SetMask(LayerImpl* owning_layer, scoped_ptr<LayerImpl> layer) {
430 owning_layer->SetMaskLayer(layer.Pass());
434 scoped_ptr<FakeLayerTreeHost> host_;
435 // These hold ownership of the layers for the duration of the test.
436 typename Types::LayerPtrType root_;
437 scoped_ptr<RenderSurfaceLayerList> render_surface_layer_list_;
438 LayerImplList render_surface_layer_list_impl_;
439 typename Types::TestLayerIterator layer_iterator_begin_;
440 typename Types::TestLayerIterator layer_iterator_;
441 typename Types::LayerType* last_layer_visited_;
442 LayerList replica_layers_;
443 LayerList mask_layers_;
448 OcclusionTrackerTest<OcclusionTrackerTestMainThreadTypes>::GetHost() {
454 OcclusionTrackerTest<OcclusionTrackerTestImplThreadTypes>::GetHost() {
455 return host_->host_impl()->active_tree();
458 #define RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \
459 class ClassName##MainThreadOpaqueLayers \
460 : public ClassName<OcclusionTrackerTestMainThreadTypes> { \
461 public: /* NOLINT(whitespace/indent) */ \
462 ClassName##MainThreadOpaqueLayers() \
463 : ClassName<OcclusionTrackerTestMainThreadTypes>(true) {} \
465 TEST_F(ClassName##MainThreadOpaqueLayers, RunTest) { RunMyTest(); }
466 #define RUN_TEST_MAIN_THREAD_OPAQUE_PAINTS(ClassName) \
467 class ClassName##MainThreadOpaquePaints \
468 : public ClassName<OcclusionTrackerTestMainThreadTypes> { \
469 public: /* NOLINT(whitespace/indent) */ \
470 ClassName##MainThreadOpaquePaints() \
471 : ClassName<OcclusionTrackerTestMainThreadTypes>(false) {} \
473 TEST_F(ClassName##MainThreadOpaquePaints, RunTest) { RunMyTest(); }
475 #define RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) \
476 class ClassName##ImplThreadOpaqueLayers \
477 : public ClassName<OcclusionTrackerTestImplThreadTypes> { \
478 public: /* NOLINT(whitespace/indent) */ \
479 ClassName##ImplThreadOpaqueLayers() \
480 : ClassName<OcclusionTrackerTestImplThreadTypes>(true) {} \
482 TEST_F(ClassName##ImplThreadOpaqueLayers, RunTest) { RunMyTest(); }
483 #define RUN_TEST_IMPL_THREAD_OPAQUE_PAINTS(ClassName) \
484 class ClassName##ImplThreadOpaquePaints \
485 : public ClassName<OcclusionTrackerTestImplThreadTypes> { \
486 public: /* NOLINT(whitespace/indent) */ \
487 ClassName##ImplThreadOpaquePaints() \
488 : ClassName<OcclusionTrackerTestImplThreadTypes>(false) {} \
490 TEST_F(ClassName##ImplThreadOpaquePaints, RunTest) { RunMyTest(); }
492 #define ALL_OCCLUSIONTRACKER_TEST(ClassName) \
493 RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \
494 RUN_TEST_MAIN_THREAD_OPAQUE_PAINTS(ClassName) \
495 RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) \
496 RUN_TEST_IMPL_THREAD_OPAQUE_PAINTS(ClassName)
498 #define MAIN_THREAD_TEST(ClassName) \
499 RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName)
501 #define IMPL_THREAD_TEST(ClassName) \
502 RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName)
504 #define MAIN_AND_IMPL_THREAD_TEST(ClassName) \
505 RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \
506 RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName)
508 template <class Types>
509 class OcclusionTrackerTestIdentityTransforms
510 : public OcclusionTrackerTest<Types> {
512 explicit OcclusionTrackerTestIdentityTransforms(bool opaque_layers)
513 : OcclusionTrackerTest<Types>(opaque_layers) {}
516 typename Types::ContentLayerType* root = this->CreateRoot(
517 this->identity_matrix, gfx::PointF(), gfx::Size(200, 200));
518 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
519 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
520 typename Types::ContentLayerType* layer =
521 this->CreateDrawingLayer(parent,
522 this->identity_matrix,
523 gfx::PointF(30.f, 30.f),
526 parent->SetMasksToBounds(true);
527 this->CalcDrawEtc(root);
529 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
530 gfx::Rect(0, 0, 1000, 1000));
532 this->VisitLayer(layer, &occlusion);
533 this->EnterLayer(parent, &occlusion);
535 EXPECT_EQ(gfx::Rect().ToString(),
536 occlusion.occlusion_from_outside_target().ToString());
537 EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(),
538 occlusion.occlusion_from_inside_target().ToString());
540 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 70, 70)));
541 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 30, 70, 70)));
542 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 29, 70, 70)));
543 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 30, 69, 70)));
544 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 31, 70, 69)));
546 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
547 parent, gfx::Rect(30, 30, 70, 70)).IsEmpty());
548 EXPECT_RECT_EQ(gfx::Rect(29, 30, 1, 70),
549 occlusion.UnoccludedLayerContentRect(
550 parent, gfx::Rect(29, 30, 70, 70)));
551 EXPECT_RECT_EQ(gfx::Rect(29, 29, 70, 70),
552 occlusion.UnoccludedLayerContentRect(
553 parent, gfx::Rect(29, 29, 70, 70)));
554 EXPECT_RECT_EQ(gfx::Rect(30, 29, 70, 1),
555 occlusion.UnoccludedLayerContentRect(
556 parent, gfx::Rect(30, 29, 70, 70)));
557 EXPECT_RECT_EQ(gfx::Rect(31, 29, 69, 1),
558 occlusion.UnoccludedLayerContentRect(
559 parent, gfx::Rect(31, 29, 69, 70)));
560 EXPECT_RECT_EQ(gfx::Rect(),
561 occlusion.UnoccludedLayerContentRect(
562 parent, gfx::Rect(31, 30, 69, 70)));
563 EXPECT_RECT_EQ(gfx::Rect(),
564 occlusion.UnoccludedLayerContentRect(
565 parent, gfx::Rect(31, 31, 69, 69)));
566 EXPECT_RECT_EQ(gfx::Rect(),
567 occlusion.UnoccludedLayerContentRect(
568 parent, gfx::Rect(30, 31, 70, 69)));
569 EXPECT_RECT_EQ(gfx::Rect(29, 31, 1, 69),
570 occlusion.UnoccludedLayerContentRect(
571 parent, gfx::Rect(29, 31, 70, 69)));
575 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestIdentityTransforms);
577 template <class Types>
578 class OcclusionTrackerTestQuadsMismatchLayer
579 : public OcclusionTrackerTest<Types> {
581 explicit OcclusionTrackerTestQuadsMismatchLayer(bool opaque_layers)
582 : OcclusionTrackerTest<Types>(opaque_layers) {}
584 gfx::Transform layer_transform;
585 layer_transform.Translate(10.0, 10.0);
587 typename Types::ContentLayerType* parent = this->CreateRoot(
588 this->identity_matrix, gfx::Point(0, 0), gfx::Size(100, 100));
589 typename Types::ContentLayerType* layer1 = this->CreateDrawingLayer(
590 parent, layer_transform, gfx::PointF(), gfx::Size(90, 90), true);
591 typename Types::ContentLayerType* layer2 = this->CreateDrawingLayer(
592 layer1, layer_transform, gfx::PointF(), gfx::Size(50, 50), true);
593 this->CalcDrawEtc(parent);
595 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
596 gfx::Rect(0, 0, 1000, 1000));
598 this->VisitLayer(layer2, &occlusion);
599 this->EnterLayer(layer1, &occlusion);
601 EXPECT_EQ(gfx::Rect().ToString(),
602 occlusion.occlusion_from_outside_target().ToString());
603 EXPECT_EQ(gfx::Rect(20, 20, 50, 50).ToString(),
604 occlusion.occlusion_from_inside_target().ToString());
606 // This checks cases where the quads don't match their "containing"
607 // layers, e.g. in terms of transforms or clip rect. This is typical for
608 // DelegatedRendererLayer.
610 gfx::Transform quad_transform;
611 quad_transform.Translate(30.0, 30.0);
613 EXPECT_TRUE(occlusion.UnoccludedContentRect(gfx::Rect(0, 0, 10, 10),
614 quad_transform).IsEmpty());
615 EXPECT_RECT_EQ(gfx::Rect(40, 40, 10, 10),
616 occlusion.UnoccludedContentRect(gfx::Rect(40, 40, 10, 10),
618 EXPECT_RECT_EQ(gfx::Rect(40, 30, 5, 10),
619 occlusion.UnoccludedContentRect(gfx::Rect(35, 30, 10, 10),
624 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestQuadsMismatchLayer);
626 template <class Types>
627 class OcclusionTrackerTestRotatedChild : public OcclusionTrackerTest<Types> {
629 explicit OcclusionTrackerTestRotatedChild(bool opaque_layers)
630 : OcclusionTrackerTest<Types>(opaque_layers) {}
632 gfx::Transform layer_transform;
633 layer_transform.Translate(250.0, 250.0);
634 layer_transform.Rotate(90.0);
635 layer_transform.Translate(-250.0, -250.0);
637 typename Types::ContentLayerType* root = this->CreateRoot(
638 this->identity_matrix, gfx::Point(0, 0), gfx::Size(200, 200));
639 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
640 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
641 typename Types::ContentLayerType* layer =
642 this->CreateDrawingLayer(parent,
644 gfx::PointF(30.f, 30.f),
647 parent->SetMasksToBounds(true);
648 this->CalcDrawEtc(root);
650 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
651 gfx::Rect(0, 0, 1000, 1000));
653 this->VisitLayer(layer, &occlusion);
654 this->EnterLayer(parent, &occlusion);
656 EXPECT_EQ(gfx::Rect().ToString(),
657 occlusion.occlusion_from_outside_target().ToString());
658 EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(),
659 occlusion.occlusion_from_inside_target().ToString());
661 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 70, 70)));
662 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 30, 70, 70)));
663 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 29, 70, 70)));
664 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 30, 69, 70)));
665 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 31, 70, 69)));
667 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
668 parent, gfx::Rect(30, 30, 70, 70)).IsEmpty());
669 EXPECT_RECT_EQ(gfx::Rect(29, 30, 1, 70),
670 occlusion.UnoccludedLayerContentRect(
671 parent, gfx::Rect(29, 30, 69, 70)));
672 EXPECT_RECT_EQ(gfx::Rect(29, 29, 70, 70),
673 occlusion.UnoccludedLayerContentRect(
674 parent, gfx::Rect(29, 29, 70, 70)));
675 EXPECT_RECT_EQ(gfx::Rect(30, 29, 70, 1),
676 occlusion.UnoccludedLayerContentRect(
677 parent, gfx::Rect(30, 29, 70, 70)));
678 EXPECT_RECT_EQ(gfx::Rect(31, 29, 69, 1),
679 occlusion.UnoccludedLayerContentRect(
680 parent, gfx::Rect(31, 29, 69, 70)));
681 EXPECT_RECT_EQ(gfx::Rect(),
682 occlusion.UnoccludedLayerContentRect(
683 parent, gfx::Rect(31, 30, 69, 70)));
684 EXPECT_RECT_EQ(gfx::Rect(),
685 occlusion.UnoccludedLayerContentRect(
686 parent, gfx::Rect(31, 31, 69, 69)));
687 EXPECT_RECT_EQ(gfx::Rect(),
688 occlusion.UnoccludedLayerContentRect(
689 parent, gfx::Rect(30, 31, 70, 69)));
690 EXPECT_RECT_EQ(gfx::Rect(29, 31, 1, 69),
691 occlusion.UnoccludedLayerContentRect(
692 parent, gfx::Rect(29, 31, 70, 69)));
696 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestRotatedChild);
698 template <class Types>
699 class OcclusionTrackerTestTranslatedChild : public OcclusionTrackerTest<Types> {
701 explicit OcclusionTrackerTestTranslatedChild(bool opaque_layers)
702 : OcclusionTrackerTest<Types>(opaque_layers) {}
704 gfx::Transform layer_transform;
705 layer_transform.Translate(20.0, 20.0);
707 typename Types::ContentLayerType* root = this->CreateRoot(
708 this->identity_matrix, gfx::PointF(), gfx::Size(200, 200));
709 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
710 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
711 typename Types::ContentLayerType* layer =
712 this->CreateDrawingLayer(parent,
714 gfx::PointF(30.f, 30.f),
717 parent->SetMasksToBounds(true);
718 this->CalcDrawEtc(root);
720 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
721 gfx::Rect(0, 0, 1000, 1000));
723 this->VisitLayer(layer, &occlusion);
724 this->EnterLayer(parent, &occlusion);
726 EXPECT_EQ(gfx::Rect().ToString(),
727 occlusion.occlusion_from_outside_target().ToString());
728 EXPECT_EQ(gfx::Rect(50, 50, 50, 50).ToString(),
729 occlusion.occlusion_from_inside_target().ToString());
731 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(50, 50, 50, 50)));
732 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(49, 50, 50, 50)));
733 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(50, 49, 50, 50)));
734 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(51, 50, 49, 50)));
735 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(50, 51, 50, 49)));
737 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
738 parent, gfx::Rect(50, 50, 50, 50)).IsEmpty());
739 EXPECT_RECT_EQ(gfx::Rect(49, 50, 1, 50),
740 occlusion.UnoccludedLayerContentRect(
741 parent, gfx::Rect(49, 50, 50, 50)));
742 EXPECT_RECT_EQ(gfx::Rect(49, 49, 50, 50),
743 occlusion.UnoccludedLayerContentRect(
744 parent, gfx::Rect(49, 49, 50, 50)));
745 EXPECT_RECT_EQ(gfx::Rect(50, 49, 50, 1),
746 occlusion.UnoccludedLayerContentRect(
747 parent, gfx::Rect(50, 49, 50, 50)));
748 EXPECT_RECT_EQ(gfx::Rect(51, 49, 49, 1),
749 occlusion.UnoccludedLayerContentRect(
750 parent, gfx::Rect(51, 49, 49, 50)));
751 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
752 parent, gfx::Rect(51, 50, 49, 50)).IsEmpty());
753 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
754 parent, gfx::Rect(51, 51, 49, 49)).IsEmpty());
755 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
756 parent, gfx::Rect(50, 51, 50, 49)).IsEmpty());
757 EXPECT_RECT_EQ(gfx::Rect(49, 51, 1, 49),
758 occlusion.UnoccludedLayerContentRect(
759 parent, gfx::Rect(49, 51, 50, 49)));
763 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestTranslatedChild);
765 template <class Types>
766 class OcclusionTrackerTestChildInRotatedChild
767 : public OcclusionTrackerTest<Types> {
769 explicit OcclusionTrackerTestChildInRotatedChild(bool opaque_layers)
770 : OcclusionTrackerTest<Types>(opaque_layers) {}
772 gfx::Transform child_transform;
773 child_transform.Translate(250.0, 250.0);
774 child_transform.Rotate(90.0);
775 child_transform.Translate(-250.0, -250.0);
777 typename Types::ContentLayerType* parent = this->CreateRoot(
778 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
779 parent->SetMasksToBounds(true);
780 typename Types::LayerType* child = this->CreateSurface(
781 parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500));
782 child->SetMasksToBounds(true);
783 typename Types::ContentLayerType* layer =
784 this->CreateDrawingLayer(child,
785 this->identity_matrix,
786 gfx::PointF(10.f, 10.f),
789 this->CalcDrawEtc(parent);
791 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
792 gfx::Rect(0, 0, 1000, 1000));
794 this->VisitLayer(layer, &occlusion);
795 this->EnterContributingSurface(child, &occlusion);
797 EXPECT_EQ(gfx::Rect().ToString(),
798 occlusion.occlusion_from_outside_target().ToString());
799 EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(),
800 occlusion.occlusion_from_inside_target().ToString());
802 this->LeaveContributingSurface(child, &occlusion);
803 this->EnterLayer(parent, &occlusion);
805 EXPECT_EQ(gfx::Rect().ToString(),
806 occlusion.occlusion_from_outside_target().ToString());
807 EXPECT_EQ(gfx::Rect(30, 40, 70, 60).ToString(),
808 occlusion.occlusion_from_inside_target().ToString());
810 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 40, 70, 60)));
811 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 40, 70, 60)));
812 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 39, 70, 60)));
813 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 40, 69, 60)));
814 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 41, 70, 59)));
816 /* Justification for the above occlusion from |layer|:
818 +---------------------+
821 | 30 + ---------------------------------+
823 | |10+---------------------------------+
827 +----|--|-------------+ | |
835 +--|-------------------------------+ |
837 +---------------------------------+
840 +---------------------+
841 | |30 Visible region of |layer|: /////
843 | +---------------------------------+
845 | +---------------------------------+ |
846 | | |///////////////| 420 | |
847 | | |///////////////|60 | |
848 | | |///////////////| | |
849 +--|--|---------------+ | |
857 | +------------------------------|--+
859 +---------------------------------+
866 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestChildInRotatedChild);
868 template <class Types>
869 class OcclusionTrackerTestScaledRenderSurface
870 : public OcclusionTrackerTest<Types> {
872 explicit OcclusionTrackerTestScaledRenderSurface(bool opaque_layers)
873 : OcclusionTrackerTest<Types>(opaque_layers) {}
876 typename Types::ContentLayerType* parent = this->CreateRoot(
877 this->identity_matrix, gfx::PointF(), gfx::Size(200, 200));
879 gfx::Transform layer1_matrix;
880 layer1_matrix.Scale(2.0, 2.0);
881 typename Types::ContentLayerType* layer1 = this->CreateDrawingLayer(
882 parent, layer1_matrix, gfx::PointF(), gfx::Size(100, 100), true);
883 layer1->SetForceRenderSurface(true);
885 gfx::Transform layer2_matrix;
886 layer2_matrix.Translate(25.0, 25.0);
887 typename Types::ContentLayerType* layer2 = this->CreateDrawingLayer(
888 layer1, layer2_matrix, gfx::PointF(), gfx::Size(50, 50), true);
889 typename Types::ContentLayerType* occluder =
890 this->CreateDrawingLayer(parent,
891 this->identity_matrix,
892 gfx::PointF(100.f, 100.f),
895 this->CalcDrawEtc(parent);
897 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
898 gfx::Rect(0, 0, 1000, 1000));
900 this->VisitLayer(occluder, &occlusion);
901 this->EnterLayer(layer2, &occlusion);
903 EXPECT_EQ(gfx::Rect(100, 100, 100, 100).ToString(),
904 occlusion.occlusion_from_outside_target().ToString());
905 EXPECT_EQ(gfx::Rect().ToString(),
906 occlusion.occlusion_from_inside_target().ToString());
909 gfx::Rect(0, 0, 25, 25),
910 occlusion.UnoccludedLayerContentRect(layer2, gfx::Rect(0, 0, 25, 25)));
911 EXPECT_RECT_EQ(gfx::Rect(10, 25, 15, 25),
912 occlusion.UnoccludedLayerContentRect(
913 layer2, gfx::Rect(10, 25, 25, 25)));
914 EXPECT_RECT_EQ(gfx::Rect(25, 10, 25, 15),
915 occlusion.UnoccludedLayerContentRect(
916 layer2, gfx::Rect(25, 10, 25, 25)));
917 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
918 layer2, gfx::Rect(25, 25, 25, 25)).IsEmpty());
922 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestScaledRenderSurface);
924 template <class Types>
925 class OcclusionTrackerTestVisitTargetTwoTimes
926 : public OcclusionTrackerTest<Types> {
928 explicit OcclusionTrackerTestVisitTargetTwoTimes(bool opaque_layers)
929 : OcclusionTrackerTest<Types>(opaque_layers) {}
931 gfx::Transform child_transform;
932 child_transform.Translate(250.0, 250.0);
933 child_transform.Rotate(90.0);
934 child_transform.Translate(-250.0, -250.0);
936 typename Types::ContentLayerType* root = this->CreateRoot(
937 this->identity_matrix, gfx::PointF(), gfx::Size(200, 200));
938 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
939 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
940 parent->SetMasksToBounds(true);
941 typename Types::LayerType* child = this->CreateSurface(
942 parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500));
943 child->SetMasksToBounds(true);
944 typename Types::ContentLayerType* layer =
945 this->CreateDrawingLayer(child,
946 this->identity_matrix,
947 gfx::PointF(10.f, 10.f),
950 // |child2| makes |parent|'s surface get considered by OcclusionTracker
951 // first, instead of |child|'s. This exercises different code in
952 // LeaveToRenderTarget, as the target surface has already been seen.
953 typename Types::ContentLayerType* child2 =
954 this->CreateDrawingLayer(parent,
955 this->identity_matrix,
956 gfx::PointF(30.f, 30.f),
959 this->CalcDrawEtc(root);
961 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
962 gfx::Rect(0, 0, 1000, 1000));
964 this->VisitLayer(child2, &occlusion);
966 EXPECT_EQ(gfx::Rect().ToString(),
967 occlusion.occlusion_from_outside_target().ToString());
968 EXPECT_EQ(gfx::Rect(30, 30, 60, 20).ToString(),
969 occlusion.occlusion_from_inside_target().ToString());
971 this->VisitLayer(layer, &occlusion);
973 EXPECT_EQ(gfx::Rect(0, 440, 20, 60).ToString(),
974 occlusion.occlusion_from_outside_target().ToString());
975 EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(),
976 occlusion.occlusion_from_inside_target().ToString());
978 this->EnterContributingSurface(child, &occlusion);
980 EXPECT_EQ(gfx::Rect(0, 440, 20, 60).ToString(),
981 occlusion.occlusion_from_outside_target().ToString());
982 EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(),
983 occlusion.occlusion_from_inside_target().ToString());
985 // Occlusion in |child2| should get merged with the |child| surface we are
987 this->LeaveContributingSurface(child, &occlusion);
988 this->EnterLayer(parent, &occlusion);
990 EXPECT_EQ(gfx::Rect().ToString(),
991 occlusion.occlusion_from_outside_target().ToString());
992 EXPECT_EQ(UnionRegions(gfx::Rect(30, 30, 60, 10), gfx::Rect(30, 40, 70, 60))
994 occlusion.occlusion_from_inside_target().ToString());
996 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 70, 70)));
997 EXPECT_RECT_EQ(gfx::Rect(90, 30, 10, 10),
998 occlusion.UnoccludedLayerContentRect(
999 parent, gfx::Rect(30, 30, 70, 70)));
1001 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 60, 10)));
1002 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 30, 60, 10)));
1003 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 29, 60, 10)));
1004 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(31, 30, 60, 10)));
1005 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 31, 60, 10)));
1007 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 40, 70, 60)));
1008 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 40, 70, 60)));
1009 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 39, 70, 60)));
1011 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
1012 parent, gfx::Rect(30, 30, 60, 10)).IsEmpty());
1013 EXPECT_RECT_EQ(gfx::Rect(29, 30, 1, 10),
1014 occlusion.UnoccludedLayerContentRect(
1015 parent, gfx::Rect(29, 30, 60, 10)));
1016 EXPECT_RECT_EQ(gfx::Rect(30, 29, 60, 1),
1017 occlusion.UnoccludedLayerContentRect(
1018 parent, gfx::Rect(30, 29, 60, 10)));
1019 EXPECT_RECT_EQ(gfx::Rect(90, 30, 1, 10),
1020 occlusion.UnoccludedLayerContentRect(
1021 parent, gfx::Rect(31, 30, 60, 10)));
1022 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
1023 parent, gfx::Rect(30, 31, 60, 10)).IsEmpty());
1025 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
1026 parent, gfx::Rect(30, 40, 70, 60)).IsEmpty());
1027 EXPECT_RECT_EQ(gfx::Rect(29, 40, 1, 60),
1028 occlusion.UnoccludedLayerContentRect(
1029 parent, gfx::Rect(29, 40, 70, 60)));
1030 // This rect is mostly occluded by |child2|.
1031 EXPECT_RECT_EQ(gfx::Rect(90, 39, 10, 1),
1032 occlusion.UnoccludedLayerContentRect(
1033 parent, gfx::Rect(30, 39, 70, 60)));
1034 // This rect extends past top/right ends of |child2|.
1035 EXPECT_RECT_EQ(gfx::Rect(30, 29, 70, 11),
1036 occlusion.UnoccludedLayerContentRect(
1037 parent, gfx::Rect(30, 29, 70, 70)));
1038 // This rect extends past left/right ends of |child2|.
1039 EXPECT_RECT_EQ(gfx::Rect(20, 39, 80, 60),
1040 occlusion.UnoccludedLayerContentRect(
1041 parent, gfx::Rect(20, 39, 80, 60)));
1042 EXPECT_RECT_EQ(gfx::Rect(),
1043 occlusion.UnoccludedLayerContentRect(
1044 parent, gfx::Rect(31, 40, 69, 60)));
1045 EXPECT_RECT_EQ(gfx::Rect(),
1046 occlusion.UnoccludedLayerContentRect(
1047 parent, gfx::Rect(30, 41, 70, 59)));
1049 /* Justification for the above occlusion from |layer|:
1051 +---------------------+
1054 | 30 + ------------+--------------------+
1055 100 | | 10 | | | ==>
1056 | |10+----------|----------------------+
1057 | + ------------+ | | |
1060 +----|--|-------------+ | |
1068 +--|-------------------------------+ |
1070 +---------------------------------+
1074 +---------------------+
1075 | |30 Visible region of |layer|: /////
1076 | 30 60 | |child2|: \\\\\
1077 | 30 +------------+--------------------+
1078 | |\\\\\\\\\\\\| |10 |
1079 | +--|\\\\\\\\\\\\|-----------------+ |
1080 | | +------------+//| 420 | |
1081 | | |///////////////|60 | |
1082 | | |///////////////| | |
1083 +--|--|---------------+ | |
1091 | +------------------------------|--+
1093 +---------------------------------+
1099 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestVisitTargetTwoTimes);
1101 template <class Types>
1102 class OcclusionTrackerTestSurfaceRotatedOffAxis
1103 : public OcclusionTrackerTest<Types> {
1105 explicit OcclusionTrackerTestSurfaceRotatedOffAxis(bool opaque_layers)
1106 : OcclusionTrackerTest<Types>(opaque_layers) {}
1108 gfx::Transform child_transform;
1109 child_transform.Translate(250.0, 250.0);
1110 child_transform.Rotate(95.0);
1111 child_transform.Translate(-250.0, -250.0);
1113 gfx::Transform layer_transform;
1114 layer_transform.Translate(10.0, 10.0);
1116 typename Types::ContentLayerType* root = this->CreateRoot(
1117 this->identity_matrix, gfx::PointF(), gfx::Size(1000, 1000));
1118 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
1119 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
1120 typename Types::LayerType* child = this->CreateLayer(
1121 parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500));
1122 child->SetMasksToBounds(true);
1123 typename Types::ContentLayerType* layer = this->CreateDrawingLayer(
1124 child, layer_transform, gfx::PointF(), gfx::Size(500, 500), true);
1125 this->CalcDrawEtc(root);
1127 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1128 gfx::Rect(0, 0, 1000, 1000));
1130 gfx::Rect clipped_layer_in_child = MathUtil::MapEnclosingClippedRect(
1131 layer_transform, layer->visible_content_rect());
1133 this->VisitLayer(layer, &occlusion);
1134 this->EnterContributingSurface(child, &occlusion);
1136 EXPECT_EQ(gfx::Rect().ToString(),
1137 occlusion.occlusion_from_outside_target().ToString());
1138 EXPECT_EQ(clipped_layer_in_child.ToString(),
1139 occlusion.occlusion_from_inside_target().ToString());
1141 this->LeaveContributingSurface(child, &occlusion);
1142 this->EnterLayer(parent, &occlusion);
1144 EXPECT_EQ(gfx::Rect().ToString(),
1145 occlusion.occlusion_from_outside_target().ToString());
1146 EXPECT_EQ(gfx::Rect().ToString(),
1147 occlusion.occlusion_from_inside_target().ToString());
1149 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(75, 55, 1, 1)));
1151 gfx::Rect(75, 55, 1, 1),
1152 occlusion.UnoccludedLayerContentRect(parent, gfx::Rect(75, 55, 1, 1)));
1156 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceRotatedOffAxis);
1158 template <class Types>
1159 class OcclusionTrackerTestSurfaceWithTwoOpaqueChildren
1160 : public OcclusionTrackerTest<Types> {
1162 explicit OcclusionTrackerTestSurfaceWithTwoOpaqueChildren(bool opaque_layers)
1163 : OcclusionTrackerTest<Types>(opaque_layers) {}
1165 gfx::Transform child_transform;
1166 child_transform.Translate(250.0, 250.0);
1167 child_transform.Rotate(90.0);
1168 child_transform.Translate(-250.0, -250.0);
1170 typename Types::ContentLayerType* root = this->CreateRoot(
1171 this->identity_matrix, gfx::PointF(), gfx::Size(1000, 1000));
1172 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
1173 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
1174 parent->SetMasksToBounds(true);
1175 typename Types::ContentLayerType* child =
1176 this->CreateDrawingSurface(parent,
1178 gfx::PointF(30.f, 30.f),
1179 gfx::Size(500, 500),
1181 child->SetMasksToBounds(true);
1182 typename Types::ContentLayerType* layer1 =
1183 this->CreateDrawingLayer(child,
1184 this->identity_matrix,
1185 gfx::PointF(10.f, 10.f),
1186 gfx::Size(500, 500),
1188 typename Types::ContentLayerType* layer2 =
1189 this->CreateDrawingLayer(child,
1190 this->identity_matrix,
1191 gfx::PointF(10.f, 450.f),
1194 this->CalcDrawEtc(root);
1196 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1197 gfx::Rect(0, 0, 1000, 1000));
1199 this->VisitLayer(layer2, &occlusion);
1200 this->VisitLayer(layer1, &occlusion);
1201 this->VisitLayer(child, &occlusion);
1202 this->EnterContributingSurface(child, &occlusion);
1204 EXPECT_EQ(gfx::Rect().ToString(),
1205 occlusion.occlusion_from_outside_target().ToString());
1206 EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(),
1207 occlusion.occlusion_from_inside_target().ToString());
1209 EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(10, 430, 60, 70)));
1210 EXPECT_FALSE(occlusion.OccludedLayer(child, gfx::Rect(9, 430, 60, 70)));
1211 EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(11, 430, 59, 70)));
1212 EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(10, 431, 60, 69)));
1214 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
1215 child, gfx::Rect(10, 430, 60, 70)).IsEmpty());
1217 gfx::Rect(9, 430, 1, 70),
1218 occlusion.UnoccludedLayerContentRect(child, gfx::Rect(9, 430, 60, 70)));
1219 EXPECT_RECT_EQ(gfx::Rect(),
1220 occlusion.UnoccludedLayerContentRect(
1221 child, gfx::Rect(11, 430, 59, 70)));
1222 EXPECT_RECT_EQ(gfx::Rect(),
1223 occlusion.UnoccludedLayerContentRect(
1224 child, gfx::Rect(10, 431, 60, 69)));
1226 this->LeaveContributingSurface(child, &occlusion);
1227 this->EnterLayer(parent, &occlusion);
1229 EXPECT_EQ(gfx::Rect().ToString(),
1230 occlusion.occlusion_from_outside_target().ToString());
1231 EXPECT_EQ(gfx::Rect(30, 40, 70, 60).ToString(),
1232 occlusion.occlusion_from_inside_target().ToString());
1234 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 40, 70, 60)));
1235 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 40, 70, 60)));
1236 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 39, 70, 60)));
1238 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
1239 parent, gfx::Rect(30, 40, 70, 60)).IsEmpty());
1240 EXPECT_RECT_EQ(gfx::Rect(29, 40, 1, 60),
1241 occlusion.UnoccludedLayerContentRect(
1242 parent, gfx::Rect(29, 40, 70, 60)));
1243 EXPECT_RECT_EQ(gfx::Rect(30, 39, 70, 1),
1244 occlusion.UnoccludedLayerContentRect(
1245 parent, gfx::Rect(30, 39, 70, 60)));
1246 EXPECT_RECT_EQ(gfx::Rect(),
1247 occlusion.UnoccludedLayerContentRect(
1248 parent, gfx::Rect(31, 40, 69, 60)));
1249 EXPECT_RECT_EQ(gfx::Rect(),
1250 occlusion.UnoccludedLayerContentRect(
1251 parent, gfx::Rect(30, 41, 70, 59)));
1253 /* Justification for the above occlusion from |layer1| and |layer2|:
1255 +---------------------+
1256 | |30 Visible region of |layer1|: /////
1257 | | Visible region of |layer2|: \\\\\
1258 | +---------------------------------+
1260 | +---------------+-----------------+ |
1261 | | |\\\\\\\\\\\\|//| 420 | |
1262 | | |\\\\\\\\\\\\|//|60 | |
1263 | | |\\\\\\\\\\\\|//| | |
1264 +--|--|------------|--+ | |
1272 | +------------|-----------------|--+
1274 +---------------+-----------------+
1280 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceWithTwoOpaqueChildren);
1282 template <class Types>
1283 class OcclusionTrackerTestOverlappingSurfaceSiblings
1284 : public OcclusionTrackerTest<Types> {
1286 explicit OcclusionTrackerTestOverlappingSurfaceSiblings(bool opaque_layers)
1287 : OcclusionTrackerTest<Types>(opaque_layers) {}
1289 gfx::Transform child_transform;
1290 child_transform.Translate(250.0, 250.0);
1291 child_transform.Rotate(90.0);
1292 child_transform.Translate(-250.0, -250.0);
1294 typename Types::ContentLayerType* parent = this->CreateRoot(
1295 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
1296 parent->SetMasksToBounds(true);
1297 typename Types::LayerType* child1 = this->CreateSurface(
1298 parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(10, 10));
1299 typename Types::LayerType* child2 = this->CreateSurface(
1300 parent, child_transform, gfx::PointF(20.f, 40.f), gfx::Size(10, 10));
1301 typename Types::ContentLayerType* layer1 =
1302 this->CreateDrawingLayer(child1,
1303 this->identity_matrix,
1304 gfx::PointF(-10.f, -10.f),
1305 gfx::Size(510, 510),
1307 typename Types::ContentLayerType* layer2 =
1308 this->CreateDrawingLayer(child2,
1309 this->identity_matrix,
1310 gfx::PointF(-10.f, -10.f),
1311 gfx::Size(510, 510),
1313 this->CalcDrawEtc(parent);
1315 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1316 gfx::Rect(0, 0, 1000, 1000));
1318 this->VisitLayer(layer2, &occlusion);
1319 this->EnterContributingSurface(child2, &occlusion);
1321 EXPECT_EQ(gfx::Rect().ToString(),
1322 occlusion.occlusion_from_outside_target().ToString());
1323 EXPECT_EQ(gfx::Rect(-10, 420, 70, 80).ToString(),
1324 occlusion.occlusion_from_inside_target().ToString());
1326 // There is nothing above child2's surface in the z-order.
1327 EXPECT_RECT_EQ(gfx::Rect(-10, 420, 70, 80),
1328 occlusion.UnoccludedSurfaceContentRect(
1329 child2, false, gfx::Rect(-10, 420, 70, 80)));
1331 this->LeaveContributingSurface(child2, &occlusion);
1332 this->VisitLayer(layer1, &occlusion);
1333 this->EnterContributingSurface(child1, &occlusion);
1335 EXPECT_EQ(gfx::Rect(0, 430, 70, 80).ToString(),
1336 occlusion.occlusion_from_outside_target().ToString());
1337 EXPECT_EQ(gfx::Rect(-10, 430, 80, 70).ToString(),
1338 occlusion.occlusion_from_inside_target().ToString());
1340 // child2's contents will occlude child1 below it.
1341 EXPECT_RECT_EQ(gfx::Rect(-10, 430, 10, 70),
1342 occlusion.UnoccludedSurfaceContentRect(
1343 child1, false, gfx::Rect(-10, 430, 80, 70)));
1345 this->LeaveContributingSurface(child1, &occlusion);
1346 this->EnterLayer(parent, &occlusion);
1348 EXPECT_EQ(gfx::Rect().ToString(),
1349 occlusion.occlusion_from_outside_target().ToString());
1350 EXPECT_EQ(UnionRegions(gfx::Rect(30, 20, 70, 10), gfx::Rect(20, 30, 80, 70))
1352 occlusion.occlusion_from_inside_target().ToString());
1354 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(20, 20, 80, 80)));
1356 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 20, 70, 80)));
1357 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 20, 70, 80)));
1358 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 19, 70, 80)));
1360 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(20, 30, 80, 70)));
1361 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(19, 30, 80, 70)));
1362 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(20, 29, 80, 70)));
1364 /* Justification for the above occlusion:
1366 +---------------------+
1368 | 30+ ---------------------------------+
1369 100 | 30| | layer2 |
1370 |20+----------------------------------+ |
1374 +--|-|----------------+ | |
1382 | +--------------------------------|-+
1384 +----------------------------------+
1390 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestOverlappingSurfaceSiblings);
1392 template <class Types>
1393 class OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms
1394 : public OcclusionTrackerTest<Types> {
1396 explicit OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms(
1398 : OcclusionTrackerTest<Types>(opaque_layers) {}
1400 gfx::Transform child1_transform;
1401 child1_transform.Translate(250.0, 250.0);
1402 child1_transform.Rotate(-90.0);
1403 child1_transform.Translate(-250.0, -250.0);
1405 gfx::Transform child2_transform;
1406 child2_transform.Translate(250.0, 250.0);
1407 child2_transform.Rotate(90.0);
1408 child2_transform.Translate(-250.0, -250.0);
1410 typename Types::ContentLayerType* parent = this->CreateRoot(
1411 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
1412 parent->SetMasksToBounds(true);
1413 typename Types::LayerType* child1 = this->CreateSurface(
1414 parent, child1_transform, gfx::PointF(30.f, 20.f), gfx::Size(10, 10));
1415 typename Types::LayerType* child2 =
1416 this->CreateDrawingSurface(parent,
1418 gfx::PointF(20.f, 40.f),
1421 typename Types::ContentLayerType* layer1 =
1422 this->CreateDrawingLayer(child1,
1423 this->identity_matrix,
1424 gfx::PointF(-10.f, -20.f),
1425 gfx::Size(510, 510),
1427 typename Types::ContentLayerType* layer2 =
1428 this->CreateDrawingLayer(child2,
1429 this->identity_matrix,
1430 gfx::PointF(-10.f, -10.f),
1431 gfx::Size(510, 510),
1433 this->CalcDrawEtc(parent);
1435 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1436 gfx::Rect(0, 0, 1000, 1000));
1438 this->VisitLayer(layer2, &occlusion);
1439 this->EnterLayer(child2, &occlusion);
1441 EXPECT_EQ(gfx::Rect().ToString(),
1442 occlusion.occlusion_from_outside_target().ToString());
1443 EXPECT_EQ(gfx::Rect(-10, 420, 70, 80).ToString(),
1444 occlusion.occlusion_from_inside_target().ToString());
1446 this->LeaveLayer(child2, &occlusion);
1447 this->EnterContributingSurface(child2, &occlusion);
1449 // There is nothing above child2's surface in the z-order.
1450 EXPECT_RECT_EQ(gfx::Rect(-10, 420, 70, 80),
1451 occlusion.UnoccludedSurfaceContentRect(
1452 child2, false, gfx::Rect(-10, 420, 70, 80)));
1454 this->LeaveContributingSurface(child2, &occlusion);
1455 this->VisitLayer(layer1, &occlusion);
1456 this->EnterContributingSurface(child1, &occlusion);
1458 EXPECT_EQ(gfx::Rect(420, -10, 70, 80).ToString(),
1459 occlusion.occlusion_from_outside_target().ToString());
1460 EXPECT_EQ(gfx::Rect(420, -20, 80, 90).ToString(),
1461 occlusion.occlusion_from_inside_target().ToString());
1463 // child2's contents will occlude child1 below it.
1464 EXPECT_EQ(gfx::Rect(20, 30, 80, 70).ToString(),
1465 occlusion.occlusion_on_contributing_surface_from_inside_target()
1467 EXPECT_EQ(gfx::Rect().ToString(),
1468 occlusion.occlusion_on_contributing_surface_from_outside_target()
1471 this->LeaveContributingSurface(child1, &occlusion);
1472 this->EnterLayer(parent, &occlusion);
1474 EXPECT_EQ(gfx::Rect().ToString(),
1475 occlusion.occlusion_from_outside_target().ToString());
1476 EXPECT_EQ(gfx::Rect(10, 20, 90, 80).ToString(),
1477 occlusion.occlusion_from_inside_target().ToString());
1479 /* Justification for the above occlusion:
1481 +---------------------+
1483 10+----------------------------------+
1484 100 || 30 | layer2 |
1485 |20+----------------------------------+
1489 +|-|------------------+ | |
1497 +----------------------------------+ |
1499 +----------------------------------+
1505 ALL_OCCLUSIONTRACKER_TEST(
1506 OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms);
1508 template <class Types>
1509 class OcclusionTrackerTestFilters : public OcclusionTrackerTest<Types> {
1511 explicit OcclusionTrackerTestFilters(bool opaque_layers)
1512 : OcclusionTrackerTest<Types>(opaque_layers) {}
1514 gfx::Transform layer_transform;
1515 layer_transform.Translate(250.0, 250.0);
1516 layer_transform.Rotate(90.0);
1517 layer_transform.Translate(-250.0, -250.0);
1519 typename Types::ContentLayerType* parent = this->CreateRoot(
1520 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
1521 parent->SetMasksToBounds(true);
1522 typename Types::ContentLayerType* blur_layer =
1523 this->CreateDrawingLayer(parent,
1525 gfx::PointF(30.f, 30.f),
1526 gfx::Size(500, 500),
1528 typename Types::ContentLayerType* opaque_layer =
1529 this->CreateDrawingLayer(parent,
1531 gfx::PointF(30.f, 30.f),
1532 gfx::Size(500, 500),
1534 typename Types::ContentLayerType* opacity_layer =
1535 this->CreateDrawingLayer(parent,
1537 gfx::PointF(30.f, 30.f),
1538 gfx::Size(500, 500),
1541 FilterOperations filters;
1542 filters.Append(FilterOperation::CreateBlurFilter(10.f));
1543 blur_layer->SetFilters(filters);
1546 filters.Append(FilterOperation::CreateGrayscaleFilter(0.5f));
1547 opaque_layer->SetFilters(filters);
1550 filters.Append(FilterOperation::CreateOpacityFilter(0.5f));
1551 opacity_layer->SetFilters(filters);
1553 this->CalcDrawEtc(parent);
1555 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1556 gfx::Rect(0, 0, 1000, 1000));
1558 // Opacity layer won't contribute to occlusion.
1559 this->VisitLayer(opacity_layer, &occlusion);
1560 this->EnterContributingSurface(opacity_layer, &occlusion);
1562 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1563 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1565 // And has nothing to contribute to its parent surface.
1566 this->LeaveContributingSurface(opacity_layer, &occlusion);
1567 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1568 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1570 // Opaque layer will contribute to occlusion.
1571 this->VisitLayer(opaque_layer, &occlusion);
1572 this->EnterContributingSurface(opaque_layer, &occlusion);
1574 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1575 EXPECT_EQ(gfx::Rect(0, 430, 70, 70).ToString(),
1576 occlusion.occlusion_from_inside_target().ToString());
1578 // And it gets translated to the parent surface.
1579 this->LeaveContributingSurface(opaque_layer, &occlusion);
1580 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1581 EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(),
1582 occlusion.occlusion_from_inside_target().ToString());
1584 // The blur layer needs to throw away any occlusion from outside its
1586 this->EnterLayer(blur_layer, &occlusion);
1587 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1588 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1590 // And it won't contribute to occlusion.
1591 this->LeaveLayer(blur_layer, &occlusion);
1592 this->EnterContributingSurface(blur_layer, &occlusion);
1593 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1594 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1596 // But the opaque layer's occlusion is preserved on the parent.
1597 this->LeaveContributingSurface(blur_layer, &occlusion);
1598 this->EnterLayer(parent, &occlusion);
1599 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1600 EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(),
1601 occlusion.occlusion_from_inside_target().ToString());
1605 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestFilters);
1607 template <class Types>
1608 class OcclusionTrackerTestReplicaDoesOcclude
1609 : public OcclusionTrackerTest<Types> {
1611 explicit OcclusionTrackerTestReplicaDoesOcclude(bool opaque_layers)
1612 : OcclusionTrackerTest<Types>(opaque_layers) {}
1614 typename Types::ContentLayerType* parent = this->CreateRoot(
1615 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
1616 typename Types::LayerType* surface =
1617 this->CreateDrawingSurface(parent,
1618 this->identity_matrix,
1619 gfx::PointF(0.f, 100.f),
1622 this->CreateReplicaLayer(
1623 surface, this->identity_matrix, gfx::PointF(50.f, 50.f), gfx::Size());
1624 this->CalcDrawEtc(parent);
1626 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1627 gfx::Rect(0, 0, 1000, 1000));
1629 this->VisitLayer(surface, &occlusion);
1631 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
1632 occlusion.occlusion_from_inside_target().ToString());
1634 this->VisitContributingSurface(surface, &occlusion);
1635 this->EnterLayer(parent, &occlusion);
1637 // The surface and replica should both be occluding the parent.
1639 UnionRegions(gfx::Rect(0, 100, 50, 50),
1640 gfx::Rect(50, 150, 50, 50)).ToString(),
1641 occlusion.occlusion_from_inside_target().ToString());
1645 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaDoesOcclude);
1647 template <class Types>
1648 class OcclusionTrackerTestReplicaWithClipping
1649 : public OcclusionTrackerTest<Types> {
1651 explicit OcclusionTrackerTestReplicaWithClipping(bool opaque_layers)
1652 : OcclusionTrackerTest<Types>(opaque_layers) {}
1654 typename Types::ContentLayerType* parent = this->CreateRoot(
1655 this->identity_matrix, gfx::PointF(), gfx::Size(100, 170));
1656 parent->SetMasksToBounds(true);
1657 typename Types::LayerType* surface =
1658 this->CreateDrawingSurface(parent,
1659 this->identity_matrix,
1660 gfx::PointF(0.f, 100.f),
1663 this->CreateReplicaLayer(
1664 surface, this->identity_matrix, gfx::PointF(50.f, 50.f), gfx::Size());
1665 this->CalcDrawEtc(parent);
1667 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1668 gfx::Rect(0, 0, 1000, 1000));
1670 this->VisitLayer(surface, &occlusion);
1672 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
1673 occlusion.occlusion_from_inside_target().ToString());
1675 this->VisitContributingSurface(surface, &occlusion);
1676 this->EnterLayer(parent, &occlusion);
1678 // The surface and replica should both be occluding the parent.
1680 UnionRegions(gfx::Rect(0, 100, 50, 50),
1681 gfx::Rect(50, 150, 50, 20)).ToString(),
1682 occlusion.occlusion_from_inside_target().ToString());
1686 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaWithClipping);
1688 template <class Types>
1689 class OcclusionTrackerTestReplicaWithMask : public OcclusionTrackerTest<Types> {
1691 explicit OcclusionTrackerTestReplicaWithMask(bool opaque_layers)
1692 : OcclusionTrackerTest<Types>(opaque_layers) {}
1694 typename Types::ContentLayerType* parent = this->CreateRoot(
1695 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
1696 typename Types::LayerType* surface =
1697 this->CreateDrawingSurface(parent,
1698 this->identity_matrix,
1699 gfx::PointF(0.f, 100.f),
1702 typename Types::LayerType* replica = this->CreateReplicaLayer(
1703 surface, this->identity_matrix, gfx::PointF(50.f, 50.f), gfx::Size());
1704 this->CreateMaskLayer(replica, gfx::Size(10, 10));
1705 this->CalcDrawEtc(parent);
1707 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1708 gfx::Rect(0, 0, 1000, 1000));
1710 this->VisitLayer(surface, &occlusion);
1712 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
1713 occlusion.occlusion_from_inside_target().ToString());
1715 this->VisitContributingSurface(surface, &occlusion);
1716 this->EnterLayer(parent, &occlusion);
1718 // The replica should not be occluding the parent, since it has a mask
1720 EXPECT_EQ(gfx::Rect(0, 100, 50, 50).ToString(),
1721 occlusion.occlusion_from_inside_target().ToString());
1725 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaWithMask);
1727 template <class Types>
1728 class OcclusionTrackerTestOpaqueContentsRegionEmpty
1729 : public OcclusionTrackerTest<Types> {
1731 explicit OcclusionTrackerTestOpaqueContentsRegionEmpty(bool opaque_layers)
1732 : OcclusionTrackerTest<Types>(opaque_layers) {}
1734 typename Types::ContentLayerType* parent = this->CreateRoot(
1735 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1736 typename Types::ContentLayerType* layer =
1737 this->CreateDrawingSurface(parent,
1738 this->identity_matrix,
1740 gfx::Size(200, 200),
1742 this->CalcDrawEtc(parent);
1744 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1745 gfx::Rect(0, 0, 1000, 1000));
1746 this->EnterLayer(layer, &occlusion);
1748 EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 100, 100)));
1749 EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 0, 100, 100)));
1750 EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 100, 100, 100)));
1751 EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 100, 100, 100)));
1753 this->LeaveLayer(layer, &occlusion);
1754 this->VisitContributingSurface(layer, &occlusion);
1755 this->EnterLayer(parent, &occlusion);
1757 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1761 MAIN_AND_IMPL_THREAD_TEST(OcclusionTrackerTestOpaqueContentsRegionEmpty);
1763 template <class Types>
1764 class OcclusionTrackerTestOpaqueContentsRegionNonEmpty
1765 : public OcclusionTrackerTest<Types> {
1767 explicit OcclusionTrackerTestOpaqueContentsRegionNonEmpty(bool opaque_layers)
1768 : OcclusionTrackerTest<Types>(opaque_layers) {}
1770 typename Types::ContentLayerType* parent = this->CreateRoot(
1771 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1772 typename Types::ContentLayerType* layer =
1773 this->CreateDrawingLayer(parent,
1774 this->identity_matrix,
1775 gfx::PointF(100.f, 100.f),
1776 gfx::Size(200, 200),
1778 this->CalcDrawEtc(parent);
1780 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1781 gfx::Rect(0, 0, 1000, 1000));
1782 layer->SetOpaqueContentsRect(gfx::Rect(0, 0, 100, 100));
1784 this->ResetLayerIterator();
1785 this->VisitLayer(layer, &occlusion);
1786 this->EnterLayer(parent, &occlusion);
1788 EXPECT_EQ(gfx::Rect(100, 100, 100, 100).ToString(),
1789 occlusion.occlusion_from_inside_target().ToString());
1792 occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100)));
1794 occlusion.OccludedLayer(parent, gfx::Rect(100, 100, 100, 100)));
1796 occlusion.OccludedLayer(parent, gfx::Rect(200, 200, 100, 100)));
1799 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1800 gfx::Rect(0, 0, 1000, 1000));
1801 layer->SetOpaqueContentsRect(gfx::Rect(20, 20, 180, 180));
1803 this->ResetLayerIterator();
1804 this->VisitLayer(layer, &occlusion);
1805 this->EnterLayer(parent, &occlusion);
1807 EXPECT_EQ(gfx::Rect(120, 120, 180, 180).ToString(),
1808 occlusion.occlusion_from_inside_target().ToString());
1811 occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100)));
1813 occlusion.OccludedLayer(parent, gfx::Rect(100, 100, 100, 100)));
1815 occlusion.OccludedLayer(parent, gfx::Rect(200, 200, 100, 100)));
1818 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1819 gfx::Rect(0, 0, 1000, 1000));
1820 layer->SetOpaqueContentsRect(gfx::Rect(150, 150, 100, 100));
1822 this->ResetLayerIterator();
1823 this->VisitLayer(layer, &occlusion);
1824 this->EnterLayer(parent, &occlusion);
1826 EXPECT_EQ(gfx::Rect(250, 250, 50, 50).ToString(),
1827 occlusion.occlusion_from_inside_target().ToString());
1830 occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100)));
1832 occlusion.OccludedLayer(parent, gfx::Rect(100, 100, 100, 100)));
1834 occlusion.OccludedLayer(parent, gfx::Rect(200, 200, 100, 100)));
1839 MAIN_AND_IMPL_THREAD_TEST(OcclusionTrackerTestOpaqueContentsRegionNonEmpty);
1841 template <class Types>
1842 class OcclusionTrackerTest3dTransform : public OcclusionTrackerTest<Types> {
1844 explicit OcclusionTrackerTest3dTransform(bool opaque_layers)
1845 : OcclusionTrackerTest<Types>(opaque_layers) {}
1847 gfx::Transform transform;
1848 transform.RotateAboutYAxis(30.0);
1850 typename Types::ContentLayerType* parent = this->CreateRoot(
1851 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1852 typename Types::LayerType* container = this->CreateLayer(
1853 parent, this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1854 typename Types::ContentLayerType* layer =
1855 this->CreateDrawingLayer(container,
1857 gfx::PointF(100.f, 100.f),
1858 gfx::Size(200, 200),
1860 this->CalcDrawEtc(parent);
1862 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1863 gfx::Rect(0, 0, 1000, 1000));
1864 this->EnterLayer(layer, &occlusion);
1866 // The layer is rotated in 3d but without preserving 3d, so it only gets
1869 gfx::Rect(0, 0, 200, 200),
1870 occlusion.UnoccludedLayerContentRect(layer, gfx::Rect(0, 0, 200, 200)));
1874 MAIN_AND_IMPL_THREAD_TEST(OcclusionTrackerTest3dTransform);
1876 template <class Types>
1877 class OcclusionTrackerTestUnsorted3dLayers
1878 : public OcclusionTrackerTest<Types> {
1880 explicit OcclusionTrackerTestUnsorted3dLayers(bool opaque_layers)
1881 : OcclusionTrackerTest<Types>(opaque_layers) {}
1883 // Currently, The main thread layer iterator does not iterate over 3d items
1884 // in sorted order, because layer sorting is not performed on the main
1885 // thread. Because of this, the occlusion tracker cannot assume that a 3d
1886 // layer occludes other layers that have not yet been iterated over. For
1887 // now, the expected behavior is that a 3d layer simply does not add any
1888 // occlusion to the occlusion tracker.
1890 gfx::Transform translation_to_front;
1891 translation_to_front.Translate3d(0.0, 0.0, -10.0);
1892 gfx::Transform translation_to_back;
1893 translation_to_front.Translate3d(0.0, 0.0, -100.0);
1895 typename Types::ContentLayerType* parent = this->CreateRoot(
1896 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1897 typename Types::ContentLayerType* child1 = this->CreateDrawingLayer(
1898 parent, translation_to_back, gfx::PointF(), gfx::Size(100, 100), true);
1899 typename Types::ContentLayerType* child2 =
1900 this->CreateDrawingLayer(parent,
1901 translation_to_front,
1902 gfx::PointF(50.f, 50.f),
1903 gfx::Size(100, 100),
1905 parent->SetShouldFlattenTransform(false);
1906 parent->Set3dSortingContextId(1);
1907 child1->Set3dSortingContextId(1);
1908 child2->Set3dSortingContextId(1);
1910 this->CalcDrawEtc(parent);
1912 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1913 gfx::Rect(0, 0, 1000, 1000));
1914 this->VisitLayer(child2, &occlusion);
1915 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1916 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1918 this->VisitLayer(child1, &occlusion);
1919 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1920 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1924 // This test will have different layer ordering on the impl thread; the test
1925 // will only work on the main thread.
1926 MAIN_THREAD_TEST(OcclusionTrackerTestUnsorted3dLayers);
1928 template <class Types>
1929 class OcclusionTrackerTestPerspectiveTransform
1930 : public OcclusionTrackerTest<Types> {
1932 explicit OcclusionTrackerTestPerspectiveTransform(bool opaque_layers)
1933 : OcclusionTrackerTest<Types>(opaque_layers) {}
1935 gfx::Transform transform;
1936 transform.Translate(150.0, 150.0);
1937 transform.ApplyPerspectiveDepth(400.0);
1938 transform.RotateAboutXAxis(-30.0);
1939 transform.Translate(-150.0, -150.0);
1941 typename Types::ContentLayerType* parent = this->CreateRoot(
1942 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1943 typename Types::LayerType* container = this->CreateLayer(
1944 parent, this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1945 typename Types::ContentLayerType* layer =
1946 this->CreateDrawingLayer(container,
1948 gfx::PointF(100.f, 100.f),
1949 gfx::Size(200, 200),
1951 container->SetShouldFlattenTransform(false);
1952 container->Set3dSortingContextId(1);
1953 layer->Set3dSortingContextId(1);
1954 layer->SetShouldFlattenTransform(false);
1956 this->CalcDrawEtc(parent);
1958 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1959 gfx::Rect(0, 0, 1000, 1000));
1960 this->EnterLayer(layer, &occlusion);
1963 gfx::Rect(0, 0, 200, 200),
1964 occlusion.UnoccludedLayerContentRect(layer, gfx::Rect(0, 0, 200, 200)));
1968 // This test requires accumulating occlusion of 3d layers, which are skipped by
1969 // the occlusion tracker on the main thread. So this test should run on the impl
1971 IMPL_THREAD_TEST(OcclusionTrackerTestPerspectiveTransform);
1972 template <class Types>
1973 class OcclusionTrackerTestPerspectiveTransformBehindCamera
1974 : public OcclusionTrackerTest<Types> {
1976 explicit OcclusionTrackerTestPerspectiveTransformBehindCamera(
1978 : OcclusionTrackerTest<Types>(opaque_layers) {}
1980 // This test is based on the platform/chromium/compositing/3d-corners.html
1982 gfx::Transform transform;
1983 transform.Translate(250.0, 50.0);
1984 transform.ApplyPerspectiveDepth(10.0);
1985 transform.Translate(-250.0, -50.0);
1986 transform.Translate(250.0, 50.0);
1987 transform.RotateAboutXAxis(-167.0);
1988 transform.Translate(-250.0, -50.0);
1990 typename Types::ContentLayerType* parent = this->CreateRoot(
1991 this->identity_matrix, gfx::PointF(), gfx::Size(500, 100));
1992 typename Types::LayerType* container = this->CreateLayer(
1993 parent, this->identity_matrix, gfx::PointF(), gfx::Size(500, 500));
1994 typename Types::ContentLayerType* layer = this->CreateDrawingLayer(
1995 container, transform, gfx::PointF(), gfx::Size(500, 500), true);
1996 container->SetShouldFlattenTransform(false);
1997 container->Set3dSortingContextId(1);
1998 layer->SetShouldFlattenTransform(false);
1999 layer->Set3dSortingContextId(1);
2000 this->CalcDrawEtc(parent);
2002 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2003 gfx::Rect(0, 0, 1000, 1000));
2004 this->EnterLayer(layer, &occlusion);
2006 // The bottom 11 pixel rows of this layer remain visible inside the
2007 // container, after translation to the target surface. When translated back,
2008 // this will include many more pixels but must include at least the bottom
2010 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
2011 layer, gfx::Rect(0, 26, 500, 474)).
2012 Contains(gfx::Rect(0, 489, 500, 11)));
2016 // This test requires accumulating occlusion of 3d layers, which are skipped by
2017 // the occlusion tracker on the main thread. So this test should run on the impl
2019 IMPL_THREAD_TEST(OcclusionTrackerTestPerspectiveTransformBehindCamera);
2021 template <class Types>
2022 class OcclusionTrackerTestLayerBehindCameraDoesNotOcclude
2023 : public OcclusionTrackerTest<Types> {
2025 explicit OcclusionTrackerTestLayerBehindCameraDoesNotOcclude(
2027 : OcclusionTrackerTest<Types>(opaque_layers) {}
2029 gfx::Transform transform;
2030 transform.Translate(50.0, 50.0);
2031 transform.ApplyPerspectiveDepth(100.0);
2032 transform.Translate3d(0.0, 0.0, 110.0);
2033 transform.Translate(-50.0, -50.0);
2035 typename Types::ContentLayerType* parent = this->CreateRoot(
2036 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
2037 typename Types::ContentLayerType* layer = this->CreateDrawingLayer(
2038 parent, transform, gfx::PointF(), gfx::Size(100, 100), true);
2039 parent->SetShouldFlattenTransform(false);
2040 parent->Set3dSortingContextId(1);
2041 layer->SetShouldFlattenTransform(false);
2042 layer->Set3dSortingContextId(1);
2043 this->CalcDrawEtc(parent);
2045 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2046 gfx::Rect(0, 0, 1000, 1000));
2048 // The |layer| is entirely behind the camera and should not occlude.
2049 this->VisitLayer(layer, &occlusion);
2050 this->EnterLayer(parent, &occlusion);
2051 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
2052 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
2056 // This test requires accumulating occlusion of 3d layers, which are skipped by
2057 // the occlusion tracker on the main thread. So this test should run on the impl
2059 IMPL_THREAD_TEST(OcclusionTrackerTestLayerBehindCameraDoesNotOcclude);
2061 template <class Types>
2062 class OcclusionTrackerTestLargePixelsOccludeInsideClipRect
2063 : public OcclusionTrackerTest<Types> {
2065 explicit OcclusionTrackerTestLargePixelsOccludeInsideClipRect(
2067 : OcclusionTrackerTest<Types>(opaque_layers) {}
2069 gfx::Transform transform;
2070 transform.Translate(50.0, 50.0);
2071 transform.ApplyPerspectiveDepth(100.0);
2072 transform.Translate3d(0.0, 0.0, 99.0);
2073 transform.Translate(-50.0, -50.0);
2075 typename Types::ContentLayerType* parent = this->CreateRoot(
2076 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
2077 parent->SetMasksToBounds(true);
2078 typename Types::ContentLayerType* layer = this->CreateDrawingLayer(
2079 parent, transform, gfx::PointF(), gfx::Size(100, 100), true);
2080 parent->SetShouldFlattenTransform(false);
2081 parent->Set3dSortingContextId(1);
2082 layer->SetShouldFlattenTransform(false);
2083 layer->Set3dSortingContextId(1);
2084 this->CalcDrawEtc(parent);
2086 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2087 gfx::Rect(0, 0, 1000, 1000));
2089 // This is very close to the camera, so pixels in its visible_content_rect()
2090 // will actually go outside of the layer's clip rect. Ensure that those
2091 // pixels don't occlude things outside the clip rect.
2092 this->VisitLayer(layer, &occlusion);
2093 this->EnterLayer(parent, &occlusion);
2094 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
2095 occlusion.occlusion_from_inside_target().ToString());
2096 EXPECT_EQ(gfx::Rect().ToString(),
2097 occlusion.occlusion_from_outside_target().ToString());
2101 // This test requires accumulating occlusion of 3d layers, which are skipped by
2102 // the occlusion tracker on the main thread. So this test should run on the impl
2104 IMPL_THREAD_TEST(OcclusionTrackerTestLargePixelsOccludeInsideClipRect);
2106 template <class Types>
2107 class OcclusionTrackerTestAnimationOpacity1OnMainThread
2108 : public OcclusionTrackerTest<Types> {
2110 explicit OcclusionTrackerTestAnimationOpacity1OnMainThread(bool opaque_layers)
2111 : OcclusionTrackerTest<Types>(opaque_layers) {}
2116 // | +--surface_child
2117 // | +--surface_child2
2121 typename Types::ContentLayerType* parent = this->CreateRoot(
2122 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
2123 typename Types::ContentLayerType* layer =
2124 this->CreateDrawingLayer(parent,
2125 this->identity_matrix,
2127 gfx::Size(300, 300),
2129 typename Types::ContentLayerType* surface =
2130 this->CreateDrawingSurface(parent,
2131 this->identity_matrix,
2133 gfx::Size(300, 300),
2135 typename Types::ContentLayerType* surface_child =
2136 this->CreateDrawingLayer(surface,
2137 this->identity_matrix,
2139 gfx::Size(200, 300),
2141 typename Types::ContentLayerType* surface_child2 =
2142 this->CreateDrawingLayer(surface,
2143 this->identity_matrix,
2145 gfx::Size(100, 300),
2147 typename Types::ContentLayerType* parent2 =
2148 this->CreateDrawingLayer(parent,
2149 this->identity_matrix,
2151 gfx::Size(300, 300),
2153 typename Types::ContentLayerType* topmost =
2154 this->CreateDrawingLayer(parent,
2155 this->identity_matrix,
2156 gfx::PointF(250.f, 0.f),
2160 AddOpacityTransitionToController(
2161 layer->layer_animation_controller(), 10.0, 0.f, 1.f, false);
2162 AddOpacityTransitionToController(
2163 surface->layer_animation_controller(), 10.0, 0.f, 1.f, false);
2164 this->CalcDrawEtc(parent);
2166 EXPECT_TRUE(layer->draw_opacity_is_animating());
2167 EXPECT_FALSE(surface->draw_opacity_is_animating());
2168 EXPECT_TRUE(surface->render_surface()->draw_opacity_is_animating());
2170 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2171 gfx::Rect(0, 0, 1000, 1000));
2173 this->VisitLayer(topmost, &occlusion);
2174 this->EnterLayer(parent2, &occlusion);
2175 // This occlusion will affect all surfaces.
2176 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2177 occlusion.occlusion_from_inside_target().ToString());
2178 EXPECT_EQ(gfx::Rect().ToString(),
2179 occlusion.occlusion_from_outside_target().ToString());
2180 EXPECT_EQ(gfx::Rect(0, 0, 250, 300).ToString(),
2181 occlusion.UnoccludedLayerContentRect(
2182 parent2, gfx::Rect(0, 0, 300, 300)).ToString());
2183 this->LeaveLayer(parent2, &occlusion);
2185 this->VisitLayer(surface_child2, &occlusion);
2186 this->EnterLayer(surface_child, &occlusion);
2187 EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(),
2188 occlusion.occlusion_from_inside_target().ToString());
2189 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2190 occlusion.occlusion_from_outside_target().ToString());
2191 EXPECT_RECT_EQ(gfx::Rect(100, 0, 100, 300),
2192 occlusion.UnoccludedLayerContentRect(
2193 surface_child, gfx::Rect(0, 0, 200, 300)));
2194 this->LeaveLayer(surface_child, &occlusion);
2195 this->EnterLayer(surface, &occlusion);
2196 EXPECT_EQ(gfx::Rect(0, 0, 200, 300).ToString(),
2197 occlusion.occlusion_from_inside_target().ToString());
2198 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2199 occlusion.occlusion_from_outside_target().ToString());
2200 EXPECT_RECT_EQ(gfx::Rect(200, 0, 50, 300),
2201 occlusion.UnoccludedLayerContentRect(
2202 surface, gfx::Rect(0, 0, 300, 300)));
2203 this->LeaveLayer(surface, &occlusion);
2205 this->EnterContributingSurface(surface, &occlusion);
2206 // Occlusion within the surface is lost when leaving the animating surface.
2207 EXPECT_EQ(gfx::Rect().ToString(),
2208 occlusion.occlusion_from_inside_target().ToString());
2209 EXPECT_EQ(gfx::Rect().ToString(),
2210 occlusion.occlusion_from_outside_target().ToString());
2211 EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
2212 occlusion.UnoccludedSurfaceContentRect(
2213 surface, false, gfx::Rect(0, 0, 300, 300)));
2214 this->LeaveContributingSurface(surface, &occlusion);
2216 // Occlusion from outside the animating surface still exists.
2217 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2218 occlusion.occlusion_from_inside_target().ToString());
2219 EXPECT_EQ(gfx::Rect().ToString(),
2220 occlusion.occlusion_from_outside_target().ToString());
2222 this->VisitLayer(layer, &occlusion);
2223 this->EnterLayer(parent, &occlusion);
2225 // Occlusion is not added for the animating |layer|.
2226 EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
2227 occlusion.UnoccludedLayerContentRect(
2228 parent, gfx::Rect(0, 0, 300, 300)));
2232 MAIN_THREAD_TEST(OcclusionTrackerTestAnimationOpacity1OnMainThread);
2234 template <class Types>
2235 class OcclusionTrackerTestAnimationOpacity0OnMainThread
2236 : public OcclusionTrackerTest<Types> {
2238 explicit OcclusionTrackerTestAnimationOpacity0OnMainThread(bool opaque_layers)
2239 : OcclusionTrackerTest<Types>(opaque_layers) {}
2241 typename Types::ContentLayerType* parent = this->CreateRoot(
2242 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
2243 typename Types::ContentLayerType* layer =
2244 this->CreateDrawingLayer(parent,
2245 this->identity_matrix,
2247 gfx::Size(300, 300),
2249 typename Types::ContentLayerType* surface =
2250 this->CreateDrawingSurface(parent,
2251 this->identity_matrix,
2253 gfx::Size(300, 300),
2255 typename Types::ContentLayerType* surface_child =
2256 this->CreateDrawingLayer(surface,
2257 this->identity_matrix,
2259 gfx::Size(200, 300),
2261 typename Types::ContentLayerType* surface_child2 =
2262 this->CreateDrawingLayer(surface,
2263 this->identity_matrix,
2265 gfx::Size(100, 300),
2267 typename Types::ContentLayerType* parent2 =
2268 this->CreateDrawingLayer(parent,
2269 this->identity_matrix,
2271 gfx::Size(300, 300),
2273 typename Types::ContentLayerType* topmost =
2274 this->CreateDrawingLayer(parent,
2275 this->identity_matrix,
2276 gfx::PointF(250.f, 0.f),
2280 AddOpacityTransitionToController(
2281 layer->layer_animation_controller(), 10.0, 1.f, 0.f, false);
2282 AddOpacityTransitionToController(
2283 surface->layer_animation_controller(), 10.0, 1.f, 0.f, false);
2284 this->CalcDrawEtc(parent);
2286 EXPECT_TRUE(layer->draw_opacity_is_animating());
2287 EXPECT_FALSE(surface->draw_opacity_is_animating());
2288 EXPECT_TRUE(surface->render_surface()->draw_opacity_is_animating());
2290 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2291 gfx::Rect(0, 0, 1000, 1000));
2293 this->VisitLayer(topmost, &occlusion);
2294 this->EnterLayer(parent2, &occlusion);
2295 // This occlusion will affect all surfaces.
2296 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2297 occlusion.occlusion_from_inside_target().ToString());
2298 EXPECT_EQ(gfx::Rect().ToString(),
2299 occlusion.occlusion_from_outside_target().ToString());
2300 EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
2301 occlusion.UnoccludedLayerContentRect(
2302 parent, gfx::Rect(0, 0, 300, 300)));
2303 this->LeaveLayer(parent2, &occlusion);
2305 this->VisitLayer(surface_child2, &occlusion);
2306 this->EnterLayer(surface_child, &occlusion);
2307 EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(),
2308 occlusion.occlusion_from_inside_target().ToString());
2309 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2310 occlusion.occlusion_from_outside_target().ToString());
2311 EXPECT_RECT_EQ(gfx::Rect(100, 0, 100, 300),
2312 occlusion.UnoccludedLayerContentRect(
2313 surface_child, gfx::Rect(0, 0, 200, 300)));
2314 this->LeaveLayer(surface_child, &occlusion);
2315 this->EnterLayer(surface, &occlusion);
2316 EXPECT_EQ(gfx::Rect(0, 0, 200, 300).ToString(),
2317 occlusion.occlusion_from_inside_target().ToString());
2318 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2319 occlusion.occlusion_from_outside_target().ToString());
2320 EXPECT_RECT_EQ(gfx::Rect(200, 0, 50, 300),
2321 occlusion.UnoccludedLayerContentRect(
2322 surface, gfx::Rect(0, 0, 300, 300)));
2323 this->LeaveLayer(surface, &occlusion);
2325 this->EnterContributingSurface(surface, &occlusion);
2326 // Occlusion within the surface is lost when leaving the animating surface.
2327 EXPECT_EQ(gfx::Rect().ToString(),
2328 occlusion.occlusion_from_inside_target().ToString());
2329 EXPECT_EQ(gfx::Rect().ToString(),
2330 occlusion.occlusion_from_outside_target().ToString());
2331 EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
2332 occlusion.UnoccludedSurfaceContentRect(
2333 surface, false, gfx::Rect(0, 0, 300, 300)));
2334 this->LeaveContributingSurface(surface, &occlusion);
2336 // Occlusion from outside the animating surface still exists.
2337 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2338 occlusion.occlusion_from_inside_target().ToString());
2339 EXPECT_EQ(gfx::Rect().ToString(),
2340 occlusion.occlusion_from_outside_target().ToString());
2342 this->VisitLayer(layer, &occlusion);
2343 this->EnterLayer(parent, &occlusion);
2345 // Occlusion is not added for the animating |layer|.
2346 EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
2347 occlusion.UnoccludedLayerContentRect(
2348 parent, gfx::Rect(0, 0, 300, 300)));
2352 MAIN_THREAD_TEST(OcclusionTrackerTestAnimationOpacity0OnMainThread);
2354 template <class Types>
2355 class OcclusionTrackerTestAnimationTranslateOnMainThread
2356 : public OcclusionTrackerTest<Types> {
2358 explicit OcclusionTrackerTestAnimationTranslateOnMainThread(
2360 : OcclusionTrackerTest<Types>(opaque_layers) {}
2362 typename Types::ContentLayerType* parent = this->CreateRoot(
2363 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
2364 typename Types::ContentLayerType* layer =
2365 this->CreateDrawingLayer(parent,
2366 this->identity_matrix,
2368 gfx::Size(300, 300),
2370 typename Types::ContentLayerType* surface =
2371 this->CreateDrawingSurface(parent,
2372 this->identity_matrix,
2374 gfx::Size(300, 300),
2376 typename Types::ContentLayerType* surface_child =
2377 this->CreateDrawingLayer(surface,
2378 this->identity_matrix,
2380 gfx::Size(200, 300),
2382 typename Types::ContentLayerType* surface_child2 =
2383 this->CreateDrawingLayer(surface,
2384 this->identity_matrix,
2386 gfx::Size(100, 300),
2388 typename Types::ContentLayerType* surface2 = this->CreateDrawingSurface(
2389 parent, this->identity_matrix, gfx::PointF(), gfx::Size(50, 300), true);
2391 AddAnimatedTransformToController(
2392 layer->layer_animation_controller(), 10.0, 30, 0);
2393 AddAnimatedTransformToController(
2394 surface->layer_animation_controller(), 10.0, 30, 0);
2395 AddAnimatedTransformToController(
2396 surface_child->layer_animation_controller(), 10.0, 30, 0);
2397 this->CalcDrawEtc(parent);
2399 EXPECT_TRUE(layer->draw_transform_is_animating());
2400 EXPECT_TRUE(layer->screen_space_transform_is_animating());
2402 surface->render_surface()->target_surface_transforms_are_animating());
2404 surface->render_surface()->screen_space_transforms_are_animating());
2405 // The surface owning layer doesn't animate against its own surface.
2406 EXPECT_FALSE(surface->draw_transform_is_animating());
2407 EXPECT_TRUE(surface->screen_space_transform_is_animating());
2408 EXPECT_TRUE(surface_child->draw_transform_is_animating());
2409 EXPECT_TRUE(surface_child->screen_space_transform_is_animating());
2411 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2412 gfx::Rect(0, 0, 1000, 1000));
2414 this->VisitLayer(surface2, &occlusion);
2415 this->EnterContributingSurface(surface2, &occlusion);
2417 EXPECT_EQ(gfx::Rect(0, 0, 50, 300).ToString(),
2418 occlusion.occlusion_from_inside_target().ToString());
2420 this->LeaveContributingSurface(surface2, &occlusion);
2421 this->EnterLayer(surface_child2, &occlusion);
2422 // surface_child2 is moving in screen space but not relative to its target,
2423 // so occlusion should happen in its target space only. It also means that
2424 // things occluding from outside the target (e.g. surface2) cannot occlude
2426 EXPECT_EQ(gfx::Rect().ToString(),
2427 occlusion.occlusion_from_outside_target().ToString());
2428 EXPECT_EQ(gfx::Rect().ToString(),
2429 occlusion.occlusion_from_inside_target().ToString());
2431 this->LeaveLayer(surface_child2, &occlusion);
2432 this->EnterLayer(surface_child, &occlusion);
2433 // surface_child2 added to the occlusion since it is not moving relative
2435 EXPECT_EQ(gfx::Rect().ToString(),
2436 occlusion.occlusion_from_outside_target().ToString());
2437 EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(),
2438 occlusion.occlusion_from_inside_target().ToString());
2440 this->LeaveLayer(surface_child, &occlusion);
2441 // surface_child is moving relative to its target, so it does not add
2443 EXPECT_EQ(gfx::Rect().ToString(),
2444 occlusion.occlusion_from_outside_target().ToString());
2445 EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(),
2446 occlusion.occlusion_from_inside_target().ToString());
2448 this->EnterLayer(surface, &occlusion);
2449 EXPECT_EQ(gfx::Rect().ToString(),
2450 occlusion.occlusion_from_outside_target().ToString());
2451 EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(),
2452 occlusion.occlusion_from_inside_target().ToString());
2454 this->LeaveLayer(surface, &occlusion);
2455 // The surface's owning layer is moving in screen space but not relative to
2456 // its target, so it adds to the occlusion.
2457 EXPECT_EQ(gfx::Rect().ToString(),
2458 occlusion.occlusion_from_outside_target().ToString());
2459 EXPECT_EQ(gfx::Rect(0, 0, 300, 300).ToString(),
2460 occlusion.occlusion_from_inside_target().ToString());
2462 this->EnterContributingSurface(surface, &occlusion);
2463 this->LeaveContributingSurface(surface, &occlusion);
2464 // The |surface| is moving in the screen and in its target, so all occlusion
2465 // within the surface is lost when leaving it. Only the |surface2| occlusion
2467 EXPECT_EQ(gfx::Rect().ToString(),
2468 occlusion.occlusion_from_outside_target().ToString());
2469 EXPECT_EQ(gfx::Rect(0, 0, 50, 300).ToString(),
2470 occlusion.occlusion_from_inside_target().ToString());
2472 this->VisitLayer(layer, &occlusion);
2473 // The |layer| is animating in the screen and in its target, so no occlusion
2475 EXPECT_EQ(gfx::Rect().ToString(),
2476 occlusion.occlusion_from_outside_target().ToString());
2477 EXPECT_EQ(gfx::Rect(0, 0, 50, 300).ToString(),
2478 occlusion.occlusion_from_inside_target().ToString());
2482 MAIN_THREAD_TEST(OcclusionTrackerTestAnimationTranslateOnMainThread);
2484 template <class Types>
2485 class OcclusionTrackerTestSurfaceOcclusionTranslatesToParent
2486 : public OcclusionTrackerTest<Types> {
2488 explicit OcclusionTrackerTestSurfaceOcclusionTranslatesToParent(
2490 : OcclusionTrackerTest<Types>(opaque_layers) {}
2492 gfx::Transform surface_transform;
2493 surface_transform.Translate(300.0, 300.0);
2494 surface_transform.Scale(2.0, 2.0);
2495 surface_transform.Translate(-150.0, -150.0);
2497 typename Types::ContentLayerType* parent = this->CreateRoot(
2498 this->identity_matrix, gfx::PointF(), gfx::Size(500, 500));
2499 typename Types::ContentLayerType* surface = this->CreateDrawingSurface(
2500 parent, surface_transform, gfx::PointF(), gfx::Size(300, 300), false);
2501 typename Types::ContentLayerType* surface2 =
2502 this->CreateDrawingSurface(parent,
2503 this->identity_matrix,
2504 gfx::PointF(50.f, 50.f),
2505 gfx::Size(300, 300),
2507 surface->SetOpaqueContentsRect(gfx::Rect(0, 0, 200, 200));
2508 surface2->SetOpaqueContentsRect(gfx::Rect(0, 0, 200, 200));
2509 this->CalcDrawEtc(parent);
2511 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2512 gfx::Rect(0, 0, 1000, 1000));
2514 this->VisitLayer(surface2, &occlusion);
2515 this->VisitContributingSurface(surface2, &occlusion);
2517 EXPECT_EQ(gfx::Rect().ToString(),
2518 occlusion.occlusion_from_outside_target().ToString());
2519 EXPECT_EQ(gfx::Rect(50, 50, 200, 200).ToString(),
2520 occlusion.occlusion_from_inside_target().ToString());
2522 // Clear any stored occlusion.
2523 occlusion.set_occlusion_from_outside_target(Region());
2524 occlusion.set_occlusion_from_inside_target(Region());
2526 this->VisitLayer(surface, &occlusion);
2527 this->VisitContributingSurface(surface, &occlusion);
2529 EXPECT_EQ(gfx::Rect().ToString(),
2530 occlusion.occlusion_from_outside_target().ToString());
2531 EXPECT_EQ(gfx::Rect(0, 0, 400, 400).ToString(),
2532 occlusion.occlusion_from_inside_target().ToString());
2536 MAIN_AND_IMPL_THREAD_TEST(
2537 OcclusionTrackerTestSurfaceOcclusionTranslatesToParent);
2539 template <class Types>
2540 class OcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping
2541 : public OcclusionTrackerTest<Types> {
2543 explicit OcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping(
2545 : OcclusionTrackerTest<Types>(opaque_layers) {}
2547 typename Types::ContentLayerType* parent = this->CreateRoot(
2548 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
2549 parent->SetMasksToBounds(true);
2550 typename Types::ContentLayerType* surface =
2551 this->CreateDrawingSurface(parent,
2552 this->identity_matrix,
2554 gfx::Size(500, 300),
2556 surface->SetOpaqueContentsRect(gfx::Rect(0, 0, 400, 200));
2557 this->CalcDrawEtc(parent);
2559 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2560 gfx::Rect(0, 0, 1000, 1000));
2562 this->VisitLayer(surface, &occlusion);
2563 this->VisitContributingSurface(surface, &occlusion);
2565 EXPECT_EQ(gfx::Rect().ToString(),
2566 occlusion.occlusion_from_outside_target().ToString());
2567 EXPECT_EQ(gfx::Rect(0, 0, 300, 200).ToString(),
2568 occlusion.occlusion_from_inside_target().ToString());
2572 MAIN_AND_IMPL_THREAD_TEST(
2573 OcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping);
2575 template <class Types>
2576 class OcclusionTrackerTestReplicaOccluded : public OcclusionTrackerTest<Types> {
2578 explicit OcclusionTrackerTestReplicaOccluded(bool opaque_layers)
2579 : OcclusionTrackerTest<Types>(opaque_layers) {}
2581 typename Types::ContentLayerType* parent = this->CreateRoot(
2582 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
2583 typename Types::LayerType* surface =
2584 this->CreateDrawingSurface(parent,
2585 this->identity_matrix,
2587 gfx::Size(100, 100),
2589 this->CreateReplicaLayer(surface,
2590 this->identity_matrix,
2591 gfx::PointF(0.f, 100.f),
2592 gfx::Size(100, 100));
2593 typename Types::LayerType* topmost =
2594 this->CreateDrawingLayer(parent,
2595 this->identity_matrix,
2596 gfx::PointF(0.f, 100.f),
2597 gfx::Size(100, 100),
2599 this->CalcDrawEtc(parent);
2601 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2602 gfx::Rect(0, 0, 1000, 1000));
2604 // |topmost| occludes the replica, but not the surface itself.
2605 this->VisitLayer(topmost, &occlusion);
2607 EXPECT_EQ(gfx::Rect().ToString(),
2608 occlusion.occlusion_from_outside_target().ToString());
2609 EXPECT_EQ(gfx::Rect(0, 100, 100, 100).ToString(),
2610 occlusion.occlusion_from_inside_target().ToString());
2612 this->VisitLayer(surface, &occlusion);
2614 // Render target with replica ignores occlusion from outside.
2615 EXPECT_EQ(gfx::Rect().ToString(),
2616 occlusion.occlusion_from_outside_target().ToString());
2617 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
2618 occlusion.occlusion_from_inside_target().ToString());
2620 this->EnterContributingSurface(surface, &occlusion);
2622 // Surface is not occluded so it shouldn't think it is.
2623 EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 100),
2624 occlusion.UnoccludedSurfaceContentRect(
2625 surface, false, gfx::Rect(0, 0, 100, 100)));
2629 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaOccluded);
2631 template <class Types>
2632 class OcclusionTrackerTestSurfaceWithReplicaUnoccluded
2633 : public OcclusionTrackerTest<Types> {
2635 explicit OcclusionTrackerTestSurfaceWithReplicaUnoccluded(bool opaque_layers)
2636 : OcclusionTrackerTest<Types>(opaque_layers) {}
2638 typename Types::ContentLayerType* parent = this->CreateRoot(
2639 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
2640 typename Types::LayerType* surface =
2641 this->CreateDrawingSurface(parent,
2642 this->identity_matrix,
2644 gfx::Size(100, 100),
2646 this->CreateReplicaLayer(surface,
2647 this->identity_matrix,
2648 gfx::PointF(0.f, 100.f),
2649 gfx::Size(100, 100));
2650 typename Types::LayerType* topmost =
2651 this->CreateDrawingLayer(parent,
2652 this->identity_matrix,
2654 gfx::Size(100, 110),
2656 this->CalcDrawEtc(parent);
2658 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2659 gfx::Rect(0, 0, 1000, 1000));
2661 // |topmost| occludes the surface, but not the entire surface's replica.
2662 this->VisitLayer(topmost, &occlusion);
2664 EXPECT_EQ(gfx::Rect().ToString(),
2665 occlusion.occlusion_from_outside_target().ToString());
2666 EXPECT_EQ(gfx::Rect(0, 0, 100, 110).ToString(),
2667 occlusion.occlusion_from_inside_target().ToString());
2669 this->VisitLayer(surface, &occlusion);
2671 // Render target with replica ignores occlusion from outside.
2672 EXPECT_EQ(gfx::Rect().ToString(),
2673 occlusion.occlusion_from_outside_target().ToString());
2674 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
2675 occlusion.occlusion_from_inside_target().ToString());
2677 this->EnterContributingSurface(surface, &occlusion);
2679 // Surface is occluded, but only the top 10px of the replica.
2680 EXPECT_RECT_EQ(gfx::Rect(0, 0, 0, 0),
2681 occlusion.UnoccludedSurfaceContentRect(
2682 surface, false, gfx::Rect(0, 0, 100, 100)));
2683 EXPECT_RECT_EQ(gfx::Rect(0, 10, 100, 90),
2684 occlusion.UnoccludedSurfaceContentRect(
2685 surface, true, gfx::Rect(0, 0, 100, 100)));
2689 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceWithReplicaUnoccluded);
2691 template <class Types>
2692 class OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently
2693 : public OcclusionTrackerTest<Types> {
2695 explicit OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently(
2697 : OcclusionTrackerTest<Types>(opaque_layers) {}
2699 typename Types::ContentLayerType* parent = this->CreateRoot(
2700 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
2701 typename Types::LayerType* surface =
2702 this->CreateDrawingSurface(parent,
2703 this->identity_matrix,
2705 gfx::Size(100, 100),
2707 this->CreateReplicaLayer(surface,
2708 this->identity_matrix,
2709 gfx::PointF(0.f, 100.f),
2710 gfx::Size(100, 100));
2711 typename Types::LayerType* over_surface = this->CreateDrawingLayer(
2712 parent, this->identity_matrix, gfx::PointF(), gfx::Size(40, 100), true);
2713 typename Types::LayerType* over_replica =
2714 this->CreateDrawingLayer(parent,
2715 this->identity_matrix,
2716 gfx::PointF(0.f, 100.f),
2719 this->CalcDrawEtc(parent);
2721 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2722 gfx::Rect(0, 0, 1000, 1000));
2724 // These occlude the surface and replica differently, so we can test each
2726 this->VisitLayer(over_replica, &occlusion);
2727 this->VisitLayer(over_surface, &occlusion);
2729 EXPECT_EQ(gfx::Rect().ToString(),
2730 occlusion.occlusion_from_outside_target().ToString());
2731 EXPECT_EQ(UnionRegions(gfx::Rect(0, 0, 40, 100), gfx::Rect(0, 100, 50, 100))
2733 occlusion.occlusion_from_inside_target().ToString());
2735 this->VisitLayer(surface, &occlusion);
2737 // Render target with replica ignores occlusion from outside.
2738 EXPECT_EQ(gfx::Rect().ToString(),
2739 occlusion.occlusion_from_outside_target().ToString());
2740 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
2741 occlusion.occlusion_from_inside_target().ToString());
2743 this->EnterContributingSurface(surface, &occlusion);
2745 // Surface and replica are occluded different amounts.
2746 EXPECT_RECT_EQ(gfx::Rect(40, 0, 60, 100),
2747 occlusion.UnoccludedSurfaceContentRect(
2748 surface, false, gfx::Rect(0, 0, 100, 100)));
2749 EXPECT_RECT_EQ(gfx::Rect(50, 0, 50, 100),
2750 occlusion.UnoccludedSurfaceContentRect(
2751 surface, true, gfx::Rect(0, 0, 100, 100)));
2755 ALL_OCCLUSIONTRACKER_TEST(
2756 OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently);
2758 template <class Types>
2759 class OcclusionTrackerTestSurfaceChildOfSurface
2760 : public OcclusionTrackerTest<Types> {
2762 explicit OcclusionTrackerTestSurfaceChildOfSurface(bool opaque_layers)
2763 : OcclusionTrackerTest<Types>(opaque_layers) {}
2765 // This test verifies that the surface cliprect does not end up empty and
2766 // clip away the entire unoccluded rect.
2768 typename Types::ContentLayerType* parent = this->CreateRoot(
2769 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
2770 typename Types::LayerType* surface =
2771 this->CreateDrawingSurface(parent,
2772 this->identity_matrix,
2774 gfx::Size(100, 100),
2776 typename Types::LayerType* surface_child =
2777 this->CreateDrawingSurface(surface,
2778 this->identity_matrix,
2779 gfx::PointF(0.f, 10.f),
2782 typename Types::LayerType* topmost = this->CreateDrawingLayer(
2783 parent, this->identity_matrix, gfx::PointF(), gfx::Size(100, 50), true);
2784 this->CalcDrawEtc(parent);
2786 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2787 gfx::Rect(-100, -100, 1000, 1000));
2789 // |topmost| occludes everything partially so we know occlusion is happening
2791 this->VisitLayer(topmost, &occlusion);
2793 EXPECT_EQ(gfx::Rect().ToString(),
2794 occlusion.occlusion_from_outside_target().ToString());
2795 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
2796 occlusion.occlusion_from_inside_target().ToString());
2798 this->VisitLayer(surface_child, &occlusion);
2800 // surface_child increases the occlusion in the screen by a narrow sliver.
2801 EXPECT_EQ(gfx::Rect(0, -10, 100, 50).ToString(),
2802 occlusion.occlusion_from_outside_target().ToString());
2803 // In its own surface, surface_child is at 0,0 as is its occlusion.
2804 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
2805 occlusion.occlusion_from_inside_target().ToString());
2807 // The root layer always has a clip rect. So the parent of |surface| has a
2808 // clip rect. However, the owning layer for |surface| does not mask to
2809 // bounds, so it doesn't have a clip rect of its own. Thus the parent of
2810 // |surface_child| exercises different code paths as its parent does not
2811 // have a clip rect.
2813 this->EnterContributingSurface(surface_child, &occlusion);
2814 // The surface_child's parent does not have a clip rect as it owns a render
2815 // surface. Make sure the unoccluded rect does not get clipped away
2817 EXPECT_RECT_EQ(gfx::Rect(0, 40, 100, 10),
2818 occlusion.UnoccludedSurfaceContentRect(
2819 surface_child, false, gfx::Rect(0, 0, 100, 50)));
2820 this->LeaveContributingSurface(surface_child, &occlusion);
2822 // When the surface_child's occlusion is transformed up to its parent, make
2823 // sure it is not clipped away inappropriately also.
2824 this->EnterLayer(surface, &occlusion);
2825 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
2826 occlusion.occlusion_from_outside_target().ToString());
2827 EXPECT_EQ(gfx::Rect(0, 10, 100, 50).ToString(),
2828 occlusion.occlusion_from_inside_target().ToString());
2829 this->LeaveLayer(surface, &occlusion);
2831 this->EnterContributingSurface(surface, &occlusion);
2832 // The surface's parent does have a clip rect as it is the root layer.
2833 EXPECT_RECT_EQ(gfx::Rect(0, 50, 100, 50),
2834 occlusion.UnoccludedSurfaceContentRect(
2835 surface, false, gfx::Rect(0, 0, 100, 100)));
2839 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceChildOfSurface);
2841 template <class Types>
2842 class OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter
2843 : public OcclusionTrackerTest<Types> {
2845 explicit OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter(
2847 : OcclusionTrackerTest<Types>(opaque_layers) {}
2849 gfx::Transform scale_by_half;
2850 scale_by_half.Scale(0.5, 0.5);
2852 // Make a 50x50 filtered surface that is completely surrounded by opaque
2853 // layers which are above it in the z-order. The surface is scaled to test
2854 // that the pixel moving is done in the target space, where the background
2855 // filter is applied.
2856 typename Types::ContentLayerType* parent = this->CreateRoot(
2857 this->identity_matrix, gfx::PointF(), gfx::Size(200, 150));
2858 typename Types::LayerType* filtered_surface =
2859 this->CreateDrawingLayer(parent,
2861 gfx::PointF(50.f, 50.f),
2862 gfx::Size(100, 100),
2864 typename Types::LayerType* occluding_layer1 = this->CreateDrawingLayer(
2865 parent, this->identity_matrix, gfx::PointF(), gfx::Size(200, 50), true);
2866 typename Types::LayerType* occluding_layer2 =
2867 this->CreateDrawingLayer(parent,
2868 this->identity_matrix,
2869 gfx::PointF(0.f, 100.f),
2872 typename Types::LayerType* occluding_layer3 =
2873 this->CreateDrawingLayer(parent,
2874 this->identity_matrix,
2875 gfx::PointF(0.f, 50.f),
2878 typename Types::LayerType* occluding_layer4 =
2879 this->CreateDrawingLayer(parent,
2880 this->identity_matrix,
2881 gfx::PointF(100.f, 50.f),
2885 // Filters make the layer own a surface.
2886 FilterOperations filters;
2887 filters.Append(FilterOperation::CreateBlurFilter(10.f));
2888 filtered_surface->SetBackgroundFilters(filters);
2890 // Save the distance of influence for the blur effect.
2891 int outset_top, outset_right, outset_bottom, outset_left;
2893 &outset_top, &outset_right, &outset_bottom, &outset_left);
2895 this->CalcDrawEtc(parent);
2897 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2898 gfx::Rect(0, 0, 1000, 1000));
2900 // These layers occlude pixels directly beside the filtered_surface. Because
2901 // filtered surface blends pixels in a radius, it will need to see some of
2902 // the pixels (up to radius far) underneath the occluding layers.
2903 this->VisitLayer(occluding_layer4, &occlusion);
2904 this->VisitLayer(occluding_layer3, &occlusion);
2905 this->VisitLayer(occluding_layer2, &occlusion);
2906 this->VisitLayer(occluding_layer1, &occlusion);
2908 Region expected_occlusion;
2909 expected_occlusion.Union(gfx::Rect(0, 0, 200, 50));
2910 expected_occlusion.Union(gfx::Rect(0, 50, 50, 50));
2911 expected_occlusion.Union(gfx::Rect(100, 50, 100, 50));
2912 expected_occlusion.Union(gfx::Rect(0, 100, 200, 50));
2914 EXPECT_EQ(expected_occlusion.ToString(),
2915 occlusion.occlusion_from_inside_target().ToString());
2916 EXPECT_EQ(gfx::Rect().ToString(),
2917 occlusion.occlusion_from_outside_target().ToString());
2919 this->VisitLayer(filtered_surface, &occlusion);
2921 // The filtered layer does not occlude.
2922 Region expected_occlusion_outside_surface;
2923 expected_occlusion_outside_surface.Union(gfx::Rect(-50, -50, 200, 50));
2924 expected_occlusion_outside_surface.Union(gfx::Rect(-50, 0, 50, 50));
2925 expected_occlusion_outside_surface.Union(gfx::Rect(50, 0, 100, 50));
2926 expected_occlusion_outside_surface.Union(gfx::Rect(-50, 50, 200, 50));
2928 EXPECT_EQ(expected_occlusion_outside_surface.ToString(),
2929 occlusion.occlusion_from_outside_target().ToString());
2930 EXPECT_EQ(gfx::Rect().ToString(),
2931 occlusion.occlusion_from_inside_target().ToString());
2933 // The surface has a background blur, so it needs pixels that are currently
2934 // considered occluded in order to be drawn. So the pixels it needs should
2935 // be removed some the occluded area so that when we get to the parent they
2937 this->VisitContributingSurface(filtered_surface, &occlusion);
2939 this->EnterLayer(parent, &occlusion);
2941 Region expected_blurred_occlusion;
2942 expected_blurred_occlusion.Union(gfx::Rect(0, 0, 200, 50 - outset_top));
2943 expected_blurred_occlusion.Union(gfx::Rect(
2944 0, 50 - outset_top, 50 - outset_left, 50 + outset_top + outset_bottom));
2945 expected_blurred_occlusion.Union(
2946 gfx::Rect(100 + outset_right,
2949 50 + outset_top + outset_bottom));
2950 expected_blurred_occlusion.Union(
2951 gfx::Rect(0, 100 + outset_bottom, 200, 50 - outset_bottom));
2953 EXPECT_EQ(expected_blurred_occlusion.ToString(),
2954 occlusion.occlusion_from_inside_target().ToString());
2955 EXPECT_EQ(gfx::Rect().ToString(),
2956 occlusion.occlusion_from_outside_target().ToString());
2958 gfx::Rect outset_rect;
2959 gfx::Rect test_rect;
2961 // Nothing in the blur outsets for the filtered_surface is occluded.
2962 outset_rect = gfx::Rect(50 - outset_left,
2964 50 + outset_left + outset_right,
2965 50 + outset_top + outset_bottom);
2966 test_rect = outset_rect;
2968 outset_rect.ToString(),
2969 occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
2971 // Stuff outside the blur outsets is still occluded though.
2972 test_rect = outset_rect;
2973 test_rect.Inset(0, 0, -1, 0);
2975 outset_rect.ToString(),
2976 occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
2977 test_rect = outset_rect;
2978 test_rect.Inset(0, 0, 0, -1);
2980 outset_rect.ToString(),
2981 occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
2982 test_rect = outset_rect;
2983 test_rect.Inset(-1, 0, 0, 0);
2985 outset_rect.ToString(),
2986 occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
2987 test_rect = outset_rect;
2988 test_rect.Inset(0, -1, 0, 0);
2990 outset_rect.ToString(),
2991 occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
2995 ALL_OCCLUSIONTRACKER_TEST(
2996 OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter);
2998 template <class Types>
2999 class OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice
3000 : public OcclusionTrackerTest<Types> {
3002 explicit OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice(
3004 : OcclusionTrackerTest<Types>(opaque_layers) {}
3006 gfx::Transform scale_by_half;
3007 scale_by_half.Scale(0.5, 0.5);
3009 // Makes two surfaces that completely cover |parent|. The occlusion both
3010 // above and below the filters will be reduced by each of them.
3011 typename Types::ContentLayerType* root = this->CreateRoot(
3012 this->identity_matrix, gfx::PointF(), gfx::Size(75, 75));
3013 typename Types::LayerType* parent = this->CreateSurface(
3014 root, scale_by_half, gfx::PointF(), gfx::Size(150, 150));
3015 parent->SetMasksToBounds(true);
3016 typename Types::LayerType* filtered_surface1 = this->CreateDrawingLayer(
3017 parent, scale_by_half, gfx::PointF(), gfx::Size(300, 300), false);
3018 typename Types::LayerType* filtered_surface2 = this->CreateDrawingLayer(
3019 parent, scale_by_half, gfx::PointF(), gfx::Size(300, 300), false);
3020 typename Types::LayerType* occluding_layer_above =
3021 this->CreateDrawingLayer(parent,
3022 this->identity_matrix,
3023 gfx::PointF(100.f, 100.f),
3027 // Filters make the layers own surfaces.
3028 FilterOperations filters;
3029 filters.Append(FilterOperation::CreateBlurFilter(1.f));
3030 filtered_surface1->SetBackgroundFilters(filters);
3031 filtered_surface2->SetBackgroundFilters(filters);
3033 // Save the distance of influence for the blur effect.
3034 int outset_top, outset_right, outset_bottom, outset_left;
3036 &outset_top, &outset_right, &outset_bottom, &outset_left);
3038 this->CalcDrawEtc(root);
3040 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3041 gfx::Rect(0, 0, 1000, 1000));
3043 this->VisitLayer(occluding_layer_above, &occlusion);
3044 EXPECT_EQ(gfx::Rect().ToString(),
3045 occlusion.occlusion_from_outside_target().ToString());
3046 EXPECT_EQ(gfx::Rect(100 / 2, 100 / 2, 50 / 2, 50 / 2).ToString(),
3047 occlusion.occlusion_from_inside_target().ToString());
3049 this->VisitLayer(filtered_surface2, &occlusion);
3050 this->VisitContributingSurface(filtered_surface2, &occlusion);
3051 this->VisitLayer(filtered_surface1, &occlusion);
3052 this->VisitContributingSurface(filtered_surface1, &occlusion);
3054 // Test expectations in the target.
3055 gfx::Rect expected_occlusion =
3056 gfx::Rect(100 / 2 + outset_right * 2,
3057 100 / 2 + outset_bottom * 2,
3058 50 / 2 - (outset_left + outset_right) * 2,
3059 50 / 2 - (outset_top + outset_bottom) * 2);
3060 EXPECT_EQ(expected_occlusion.ToString(),
3061 occlusion.occlusion_from_inside_target().ToString());
3063 // Test expectations in the screen are the same as in the target, as the
3064 // render surface is 1:1 with the screen.
3065 EXPECT_EQ(expected_occlusion.ToString(),
3066 occlusion.occlusion_from_outside_target().ToString());
3070 ALL_OCCLUSIONTRACKER_TEST(
3071 OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice);
3073 template <class Types>
3074 class OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter
3075 : public OcclusionTrackerTest<Types> {
3077 explicit OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter(
3079 : OcclusionTrackerTest<Types>(opaque_layers) {}
3081 gfx::Transform scale_by_half;
3082 scale_by_half.Scale(0.5, 0.5);
3084 // Make a surface and its replica, each 50x50, with a smaller 30x30 layer
3085 // centered below each. The surface is scaled to test that the pixel moving
3086 // is done in the target space, where the background filter is applied, but
3087 // the surface appears at 50, 50 and the replica at 200, 50.
3088 typename Types::ContentLayerType* parent = this->CreateRoot(
3089 this->identity_matrix, gfx::PointF(), gfx::Size(300, 150));
3090 typename Types::LayerType* behind_surface_layer =
3091 this->CreateDrawingLayer(parent,
3092 this->identity_matrix,
3093 gfx::PointF(60.f, 60.f),
3096 typename Types::LayerType* behind_replica_layer =
3097 this->CreateDrawingLayer(parent,
3098 this->identity_matrix,
3099 gfx::PointF(210.f, 60.f),
3102 typename Types::LayerType* filtered_surface =
3103 this->CreateDrawingLayer(parent,
3105 gfx::PointF(50.f, 50.f),
3106 gfx::Size(100, 100),
3108 this->CreateReplicaLayer(filtered_surface,
3109 this->identity_matrix,
3110 gfx::PointF(300.f, 0.f),
3113 // Filters make the layer own a surface.
3114 FilterOperations filters;
3115 filters.Append(FilterOperation::CreateBlurFilter(3.f));
3116 filtered_surface->SetBackgroundFilters(filters);
3118 this->CalcDrawEtc(parent);
3120 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3121 gfx::Rect(0, 0, 1000, 1000));
3123 // The surface has a background blur, so it blurs non-opaque pixels below
3125 this->VisitLayer(filtered_surface, &occlusion);
3126 this->VisitContributingSurface(filtered_surface, &occlusion);
3128 this->VisitLayer(behind_replica_layer, &occlusion);
3129 this->VisitLayer(behind_surface_layer, &occlusion);
3131 // The layers behind the surface are not blurred, and their occlusion does
3132 // not change, until we leave the surface. So it should not be modified by
3134 gfx::Rect occlusion_behind_surface = gfx::Rect(60, 60, 30, 30);
3135 gfx::Rect occlusion_behind_replica = gfx::Rect(210, 60, 30, 30);
3137 Region expected_opaque_bounds =
3138 UnionRegions(occlusion_behind_surface, occlusion_behind_replica);
3139 EXPECT_EQ(expected_opaque_bounds.ToString(),
3140 occlusion.occlusion_from_inside_target().ToString());
3142 EXPECT_EQ(gfx::Rect().ToString(),
3143 occlusion.occlusion_from_outside_target().ToString());
3147 ALL_OCCLUSIONTRACKER_TEST(
3148 OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter);
3150 template <class Types>
3151 class OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded
3152 : public OcclusionTrackerTest<Types> {
3154 explicit OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded(
3156 : OcclusionTrackerTest<Types>(opaque_layers) {}
3158 gfx::Transform scale_by_half;
3159 scale_by_half.Scale(0.5, 0.5);
3161 // Make a 50x50 filtered surface that is completely occluded by an opaque
3162 // layer which is above it in the z-order. The surface is
3163 // scaled to test that the pixel moving is done in the target space, where
3164 // the background filter is applied, but the surface appears at 50, 50.
3165 typename Types::ContentLayerType* parent = this->CreateRoot(
3166 this->identity_matrix, gfx::PointF(), gfx::Size(200, 150));
3167 typename Types::LayerType* filtered_surface =
3168 this->CreateDrawingLayer(parent,
3170 gfx::PointF(50.f, 50.f),
3171 gfx::Size(100, 100),
3173 typename Types::LayerType* occluding_layer =
3174 this->CreateDrawingLayer(parent,
3175 this->identity_matrix,
3176 gfx::PointF(50.f, 50.f),
3180 // Filters make the layer own a surface.
3181 FilterOperations filters;
3182 filters.Append(FilterOperation::CreateBlurFilter(3.f));
3183 filtered_surface->SetBackgroundFilters(filters);
3185 this->CalcDrawEtc(parent);
3187 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3188 gfx::Rect(0, 0, 1000, 1000));
3190 this->VisitLayer(occluding_layer, &occlusion);
3192 this->VisitLayer(filtered_surface, &occlusion);
3194 // The layers above the filtered surface occlude from outside.
3195 gfx::Rect occlusion_above_surface = gfx::Rect(0, 0, 50, 50);
3197 EXPECT_EQ(gfx::Rect().ToString(),
3198 occlusion.occlusion_from_inside_target().ToString());
3199 EXPECT_EQ(occlusion_above_surface.ToString(),
3200 occlusion.occlusion_from_outside_target().ToString());
3203 // The surface has a background blur, so it blurs non-opaque pixels below
3205 this->VisitContributingSurface(filtered_surface, &occlusion);
3207 // The filter is completely occluded, so it should not blur anything and
3208 // reduce any occlusion.
3209 gfx::Rect occlusion_above_surface = gfx::Rect(50, 50, 50, 50);
3211 EXPECT_EQ(occlusion_above_surface.ToString(),
3212 occlusion.occlusion_from_inside_target().ToString());
3213 EXPECT_EQ(gfx::Rect().ToString(),
3214 occlusion.occlusion_from_outside_target().ToString());
3219 ALL_OCCLUSIONTRACKER_TEST(
3220 OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded);
3222 template <class Types>
3223 class OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded
3224 : public OcclusionTrackerTest<Types> {
3227 OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded(
3229 : OcclusionTrackerTest<Types>(opaque_layers) {}
3231 gfx::Transform scale_by_half;
3232 scale_by_half.Scale(0.5, 0.5);
3234 // Make a surface and its replica, each 50x50, that are partially occluded
3235 // by opaque layers which are above them in the z-order. The surface is
3236 // scaled to test that the pixel moving is done in the target space, where
3237 // the background filter is applied, but the surface appears at 50, 50 and
3238 // the replica at 200, 50.
3239 typename Types::ContentLayerType* parent = this->CreateRoot(
3240 this->identity_matrix, gfx::PointF(), gfx::Size(300, 150));
3241 typename Types::LayerType* filtered_surface =
3242 this->CreateDrawingLayer(parent,
3244 gfx::PointF(50.f, 50.f),
3245 gfx::Size(100, 100),
3247 this->CreateReplicaLayer(filtered_surface,
3248 this->identity_matrix,
3249 gfx::PointF(300.f, 0.f),
3251 typename Types::LayerType* above_surface_layer =
3252 this->CreateDrawingLayer(parent,
3253 this->identity_matrix,
3254 gfx::PointF(70.f, 50.f),
3257 typename Types::LayerType* above_replica_layer =
3258 this->CreateDrawingLayer(parent,
3259 this->identity_matrix,
3260 gfx::PointF(200.f, 50.f),
3263 typename Types::LayerType* beside_surface_layer =
3264 this->CreateDrawingLayer(parent,
3265 this->identity_matrix,
3266 gfx::PointF(90.f, 40.f),
3269 typename Types::LayerType* beside_replica_layer =
3270 this->CreateDrawingLayer(parent,
3271 this->identity_matrix,
3272 gfx::PointF(200.f, 40.f),
3276 // Filters make the layer own a surface.
3277 FilterOperations filters;
3278 filters.Append(FilterOperation::CreateBlurFilter(3.f));
3279 filtered_surface->SetBackgroundFilters(filters);
3281 // Save the distance of influence for the blur effect.
3282 int outset_top, outset_right, outset_bottom, outset_left;
3284 &outset_top, &outset_right, &outset_bottom, &outset_left);
3286 this->CalcDrawEtc(parent);
3288 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3289 gfx::Rect(0, 0, 1000, 1000));
3291 this->VisitLayer(beside_replica_layer, &occlusion);
3292 this->VisitLayer(beside_surface_layer, &occlusion);
3293 this->VisitLayer(above_replica_layer, &occlusion);
3294 this->VisitLayer(above_surface_layer, &occlusion);
3296 // The surface has a background blur, so it blurs non-opaque pixels below
3298 this->VisitLayer(filtered_surface, &occlusion);
3299 this->VisitContributingSurface(filtered_surface, &occlusion);
3301 // The filter in the surface and replica are partially unoccluded. Only the
3302 // unoccluded parts should reduce occlusion. This means it will push back
3303 // the occlusion that touches the unoccluded part (occlusion_above___), but
3304 // it will not touch occlusion_beside____ since that is not beside the
3305 // unoccluded part of the surface, even though it is beside the occluded
3306 // part of the surface.
3307 gfx::Rect occlusion_above_surface =
3308 gfx::Rect(70 + outset_right, 50, 30 - outset_right, 50);
3309 gfx::Rect occlusion_above_replica =
3310 gfx::Rect(200, 50, 30 - outset_left, 50);
3311 gfx::Rect occlusion_beside_surface = gfx::Rect(90, 40, 10, 10);
3312 gfx::Rect occlusion_beside_replica = gfx::Rect(200, 40, 10, 10);
3314 Region expected_occlusion;
3315 expected_occlusion.Union(occlusion_above_surface);
3316 expected_occlusion.Union(occlusion_above_replica);
3317 expected_occlusion.Union(occlusion_beside_surface);
3318 expected_occlusion.Union(occlusion_beside_replica);
3320 ASSERT_EQ(expected_occlusion.ToString(),
3321 occlusion.occlusion_from_inside_target().ToString());
3322 EXPECT_EQ(gfx::Rect().ToString(),
3323 occlusion.occlusion_from_outside_target().ToString());
3325 Region::Iterator expected_rects(expected_occlusion);
3326 Region::Iterator target_surface_rects(
3327 occlusion.occlusion_from_inside_target());
3328 for (; expected_rects.has_rect();
3329 expected_rects.next(), target_surface_rects.next()) {
3330 ASSERT_TRUE(target_surface_rects.has_rect());
3331 EXPECT_EQ(expected_rects.rect(), target_surface_rects.rect());
3336 ALL_OCCLUSIONTRACKER_TEST(
3337 OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded);
3339 template <class Types>
3340 class OcclusionTrackerTestMinimumTrackingSize
3341 : public OcclusionTrackerTest<Types> {
3343 explicit OcclusionTrackerTestMinimumTrackingSize(bool opaque_layers)
3344 : OcclusionTrackerTest<Types>(opaque_layers) {}
3346 gfx::Size tracking_size(100, 100);
3347 gfx::Size below_tracking_size(99, 99);
3349 typename Types::ContentLayerType* parent = this->CreateRoot(
3350 this->identity_matrix, gfx::PointF(), gfx::Size(400, 400));
3351 typename Types::LayerType* large = this->CreateDrawingLayer(
3352 parent, this->identity_matrix, gfx::PointF(), tracking_size, true);
3353 typename Types::LayerType* small =
3354 this->CreateDrawingLayer(parent,
3355 this->identity_matrix,
3357 below_tracking_size,
3359 this->CalcDrawEtc(parent);
3361 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3362 gfx::Rect(0, 0, 1000, 1000));
3363 occlusion.set_minimum_tracking_size(tracking_size);
3365 // The small layer is not tracked because it is too small.
3366 this->VisitLayer(small, &occlusion);
3368 EXPECT_EQ(gfx::Rect().ToString(),
3369 occlusion.occlusion_from_outside_target().ToString());
3370 EXPECT_EQ(gfx::Rect().ToString(),
3371 occlusion.occlusion_from_inside_target().ToString());
3373 // The large layer is tracked as it is large enough.
3374 this->VisitLayer(large, &occlusion);
3376 EXPECT_EQ(gfx::Rect().ToString(),
3377 occlusion.occlusion_from_outside_target().ToString());
3378 EXPECT_EQ(gfx::Rect(tracking_size).ToString(),
3379 occlusion.occlusion_from_inside_target().ToString());
3383 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestMinimumTrackingSize);
3385 template <class Types>
3386 class OcclusionTrackerTestScaledLayerIsClipped
3387 : public OcclusionTrackerTest<Types> {
3389 explicit OcclusionTrackerTestScaledLayerIsClipped(bool opaque_layers)
3390 : OcclusionTrackerTest<Types>(opaque_layers) {}
3392 gfx::Transform scale_transform;
3393 scale_transform.Scale(512.0, 512.0);
3395 typename Types::ContentLayerType* parent = this->CreateRoot(
3396 this->identity_matrix, gfx::PointF(), gfx::Size(400, 400));
3397 typename Types::LayerType* clip = this->CreateLayer(parent,
3398 this->identity_matrix,
3399 gfx::PointF(10.f, 10.f),
3401 clip->SetMasksToBounds(true);
3402 typename Types::LayerType* scale = this->CreateLayer(
3403 clip, scale_transform, gfx::PointF(), gfx::Size(1, 1));
3404 typename Types::LayerType* scaled = this->CreateDrawingLayer(
3405 scale, this->identity_matrix, gfx::PointF(), gfx::Size(500, 500), true);
3406 this->CalcDrawEtc(parent);
3408 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3409 gfx::Rect(0, 0, 1000, 1000));
3411 this->VisitLayer(scaled, &occlusion);
3413 EXPECT_EQ(gfx::Rect().ToString(),
3414 occlusion.occlusion_from_outside_target().ToString());
3415 EXPECT_EQ(gfx::Rect(10, 10, 50, 50).ToString(),
3416 occlusion.occlusion_from_inside_target().ToString());
3420 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestScaledLayerIsClipped)
3422 template <class Types>
3423 class OcclusionTrackerTestScaledLayerInSurfaceIsClipped
3424 : public OcclusionTrackerTest<Types> {
3426 explicit OcclusionTrackerTestScaledLayerInSurfaceIsClipped(bool opaque_layers)
3427 : OcclusionTrackerTest<Types>(opaque_layers) {}
3429 gfx::Transform scale_transform;
3430 scale_transform.Scale(512.0, 512.0);
3432 typename Types::ContentLayerType* parent = this->CreateRoot(
3433 this->identity_matrix, gfx::PointF(), gfx::Size(400, 400));
3434 typename Types::LayerType* clip = this->CreateLayer(parent,
3435 this->identity_matrix,
3436 gfx::PointF(10.f, 10.f),
3438 clip->SetMasksToBounds(true);
3439 typename Types::LayerType* surface = this->CreateDrawingSurface(
3440 clip, this->identity_matrix, gfx::PointF(), gfx::Size(400, 30), false);
3441 typename Types::LayerType* scale = this->CreateLayer(
3442 surface, scale_transform, gfx::PointF(), gfx::Size(1, 1));
3443 typename Types::LayerType* scaled = this->CreateDrawingLayer(
3444 scale, this->identity_matrix, gfx::PointF(), gfx::Size(500, 500), true);
3445 this->CalcDrawEtc(parent);
3447 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3448 gfx::Rect(0, 0, 1000, 1000));
3450 this->VisitLayer(scaled, &occlusion);
3451 this->VisitLayer(surface, &occlusion);
3452 this->VisitContributingSurface(surface, &occlusion);
3454 EXPECT_EQ(gfx::Rect().ToString(),
3455 occlusion.occlusion_from_outside_target().ToString());
3456 EXPECT_EQ(gfx::Rect(10, 10, 50, 50).ToString(),
3457 occlusion.occlusion_from_inside_target().ToString());
3461 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestScaledLayerInSurfaceIsClipped)
3463 template <class Types>
3464 class OcclusionTrackerTestCopyRequestDoesOcclude
3465 : public OcclusionTrackerTest<Types> {
3467 explicit OcclusionTrackerTestCopyRequestDoesOcclude(bool opaque_layers)
3468 : OcclusionTrackerTest<Types>(opaque_layers) {}
3470 typename Types::ContentLayerType* root = this->CreateRoot(
3471 this->identity_matrix, gfx::Point(), gfx::Size(400, 400));
3472 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
3473 root, this->identity_matrix, gfx::Point(), gfx::Size(400, 400), true);
3474 typename Types::LayerType* copy = this->CreateLayer(parent,
3475 this->identity_matrix,
3477 gfx::Size(200, 400));
3478 this->AddCopyRequest(copy);
3479 typename Types::LayerType* copy_child = this->CreateDrawingLayer(
3481 this->identity_matrix,
3483 gfx::Size(200, 400),
3485 this->CalcDrawEtc(root);
3487 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3488 gfx::Rect(0, 0, 1000, 1000));
3490 this->VisitLayer(copy_child, &occlusion);
3491 EXPECT_EQ(gfx::Rect().ToString(),
3492 occlusion.occlusion_from_outside_target().ToString());
3493 EXPECT_EQ(gfx::Rect(200, 400).ToString(),
3494 occlusion.occlusion_from_inside_target().ToString());
3496 // CopyRequests cause the layer to own a surface.
3497 this->VisitContributingSurface(copy, &occlusion);
3499 // The occlusion from the copy should be kept.
3500 EXPECT_EQ(gfx::Rect().ToString(),
3501 occlusion.occlusion_from_outside_target().ToString());
3502 EXPECT_EQ(gfx::Rect(100, 0, 200, 400).ToString(),
3503 occlusion.occlusion_from_inside_target().ToString());
3507 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestCopyRequestDoesOcclude)
3509 template <class Types>
3510 class OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude
3511 : public OcclusionTrackerTest<Types> {
3513 explicit OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude(
3515 : OcclusionTrackerTest<Types>(opaque_layers) {}
3517 typename Types::ContentLayerType* root = this->CreateRoot(
3518 this->identity_matrix, gfx::Point(), gfx::Size(400, 400));
3519 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
3520 root, this->identity_matrix, gfx::Point(), gfx::Size(400, 400), true);
3521 typename Types::LayerType* hide = this->CreateLayer(
3522 parent, this->identity_matrix, gfx::Point(), gfx::Size());
3523 typename Types::LayerType* copy = this->CreateLayer(
3524 hide, this->identity_matrix, gfx::Point(100, 0), gfx::Size(200, 400));
3525 this->AddCopyRequest(copy);
3526 typename Types::LayerType* copy_child = this->CreateDrawingLayer(
3527 copy, this->identity_matrix, gfx::PointF(), gfx::Size(200, 400), true);
3529 // The |copy| layer is hidden but since it is being copied, it will be
3531 hide->SetHideLayerAndSubtree(true);
3533 this->CalcDrawEtc(root);
3535 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3536 gfx::Rect(0, 0, 1000, 1000));
3538 this->VisitLayer(copy_child, &occlusion);
3539 EXPECT_EQ(gfx::Rect().ToString(),
3540 occlusion.occlusion_from_outside_target().ToString());
3541 EXPECT_EQ(gfx::Rect(200, 400).ToString(),
3542 occlusion.occlusion_from_inside_target().ToString());
3544 // CopyRequests cause the layer to own a surface.
3545 this->VisitContributingSurface(copy, &occlusion);
3547 // The occlusion from the copy should be dropped since it is hidden.
3548 EXPECT_EQ(gfx::Rect().ToString(),
3549 occlusion.occlusion_from_outside_target().ToString());
3550 EXPECT_EQ(gfx::Rect().ToString(),
3551 occlusion.occlusion_from_inside_target().ToString());
3555 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude)