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; }
137 static void RecursiveUpdateNumChildren(LayerType* layerType) {}
140 struct OcclusionTrackerTestImplThreadTypes {
141 typedef LayerImpl LayerType;
142 typedef LayerTreeImpl HostType;
143 typedef RenderSurfaceImpl RenderSurfaceType;
144 typedef TestContentLayerImpl ContentLayerType;
145 typedef scoped_ptr<LayerImpl> LayerPtrType;
146 typedef scoped_ptr<ContentLayerType> ContentLayerPtrType;
147 typedef LayerIterator<LayerImpl> TestLayerIterator;
148 typedef OcclusionTracker<LayerImpl> OcclusionTrackerType;
150 static LayerPtrType CreateLayer(HostType* host) {
151 return LayerImpl::Create(host, next_layer_impl_id++);
153 static ContentLayerPtrType CreateContentLayer(HostType* host) {
154 return make_scoped_ptr(new ContentLayerType(host, next_layer_impl_id++));
156 static int next_layer_impl_id;
158 static LayerPtrType PassLayerPtr(LayerPtrType* layer) {
159 return layer->Pass();
162 static LayerPtrType PassLayerPtr(ContentLayerPtrType* layer) {
163 return layer->PassAs<LayerType>();
166 static void DestroyLayer(LayerPtrType* layer) { layer->reset(); }
168 static void RecursiveUpdateNumChildren(LayerType* layer) {
169 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(layer);
173 int OcclusionTrackerTestImplThreadTypes::next_layer_impl_id = 1;
175 template <typename Types> class OcclusionTrackerTest : public testing::Test {
177 explicit OcclusionTrackerTest(bool opaque_layers)
178 : opaque_layers_(opaque_layers), host_(FakeLayerTreeHost::Create()) {}
180 virtual void RunMyTest() = 0;
182 virtual void TearDown() {
183 Types::DestroyLayer(&root_);
184 render_surface_layer_list_.reset();
185 render_surface_layer_list_impl_.clear();
186 replica_layers_.clear();
187 mask_layers_.clear();
190 typename Types::HostType* GetHost();
192 typename Types::ContentLayerType* CreateRoot(const gfx::Transform& transform,
193 const gfx::PointF& position,
194 const gfx::Size& bounds) {
195 typename Types::ContentLayerPtrType layer(
196 Types::CreateContentLayer(GetHost()));
197 typename Types::ContentLayerType* layer_ptr = layer.get();
198 SetProperties(layer_ptr, transform, position, bounds);
200 DCHECK(!root_.get());
201 root_ = Types::PassLayerPtr(&layer);
203 SetRootLayerOnMainThread(layer_ptr);
208 typename Types::LayerType* CreateLayer(typename Types::LayerType* parent,
209 const gfx::Transform& transform,
210 const gfx::PointF& position,
211 const gfx::Size& bounds) {
212 typename Types::LayerPtrType layer(Types::CreateLayer(GetHost()));
213 typename Types::LayerType* layer_ptr = layer.get();
214 SetProperties(layer_ptr, transform, position, bounds);
215 parent->AddChild(Types::PassLayerPtr(&layer));
219 typename Types::LayerType* CreateSurface(typename Types::LayerType* parent,
220 const gfx::Transform& transform,
221 const gfx::PointF& position,
222 const gfx::Size& bounds) {
223 typename Types::LayerType* layer =
224 CreateLayer(parent, transform, position, bounds);
225 layer->SetForceRenderSurface(true);
229 typename Types::ContentLayerType* CreateDrawingLayer(
230 typename Types::LayerType* parent,
231 const gfx::Transform& transform,
232 const gfx::PointF& position,
233 const gfx::Size& bounds,
235 typename Types::ContentLayerPtrType layer(
236 Types::CreateContentLayer(GetHost()));
237 typename Types::ContentLayerType* layer_ptr = layer.get();
238 SetProperties(layer_ptr, transform, position, bounds);
240 if (opaque_layers_) {
241 layer_ptr->SetContentsOpaque(opaque);
243 layer_ptr->SetContentsOpaque(false);
245 layer_ptr->SetOpaqueContentsRect(gfx::Rect(bounds));
247 layer_ptr->SetOpaqueContentsRect(gfx::Rect());
250 parent->AddChild(Types::PassLayerPtr(&layer));
254 typename Types::LayerType* CreateReplicaLayer(
255 typename Types::LayerType* owning_layer,
256 const gfx::Transform& transform,
257 const gfx::PointF& position,
258 const gfx::Size& bounds) {
259 typename Types::ContentLayerPtrType layer(
260 Types::CreateContentLayer(GetHost()));
261 typename Types::ContentLayerType* layer_ptr = layer.get();
262 SetProperties(layer_ptr, transform, position, bounds);
263 SetReplica(owning_layer, Types::PassLayerPtr(&layer));
267 typename Types::LayerType* CreateMaskLayer(
268 typename Types::LayerType* owning_layer,
269 const gfx::Size& bounds) {
270 typename Types::ContentLayerPtrType layer(
271 Types::CreateContentLayer(GetHost()));
272 typename Types::ContentLayerType* layer_ptr = layer.get();
273 SetProperties(layer_ptr, identity_matrix, gfx::PointF(), bounds);
274 SetMask(owning_layer, Types::PassLayerPtr(&layer));
278 typename Types::ContentLayerType* CreateDrawingSurface(
279 typename Types::LayerType* parent,
280 const gfx::Transform& transform,
281 const gfx::PointF& position,
282 const gfx::Size& bounds,
284 typename Types::ContentLayerType* layer =
285 CreateDrawingLayer(parent, transform, position, bounds, opaque);
286 layer->SetForceRenderSurface(true);
291 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {}
293 void AddCopyRequest(Layer* layer) {
294 layer->RequestCopyOfOutput(
295 CopyOutputRequest::CreateBitmapRequest(base::Bind(
296 &OcclusionTrackerTest<Types>::CopyOutputCallback,
297 base::Unretained(this))));
300 void AddCopyRequest(LayerImpl* layer) {
301 ScopedPtrVector<CopyOutputRequest> requests;
303 CopyOutputRequest::CreateBitmapRequest(base::Bind(
304 &OcclusionTrackerTest<Types>::CopyOutputCallback,
305 base::Unretained(this))));
306 layer->PassCopyRequests(&requests);
309 void CalcDrawEtc(TestContentLayerImpl* root) {
310 DCHECK(root == root_.get());
311 DCHECK(!root->render_surface());
313 Types::RecursiveUpdateNumChildren(root);
314 LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
315 root, root->bounds(), &render_surface_layer_list_impl_);
316 inputs.can_adjust_raster_scales = true;
317 LayerTreeHostCommon::CalculateDrawProperties(&inputs);
319 layer_iterator_ = layer_iterator_begin_ =
320 Types::TestLayerIterator::Begin(&render_surface_layer_list_impl_);
323 void CalcDrawEtc(TestContentLayer* root) {
324 DCHECK(root == root_.get());
325 DCHECK(!root->render_surface());
327 render_surface_layer_list_.reset(new RenderSurfaceLayerList);
328 LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
329 root, root->bounds(), render_surface_layer_list_.get());
330 inputs.can_adjust_raster_scales = true;
331 LayerTreeHostCommon::CalculateDrawProperties(&inputs);
333 layer_iterator_ = layer_iterator_begin_ =
334 Types::TestLayerIterator::Begin(render_surface_layer_list_.get());
337 void EnterLayer(typename Types::LayerType* layer,
338 typename Types::OcclusionTrackerType* occlusion) {
339 ASSERT_EQ(layer, *layer_iterator_);
340 ASSERT_TRUE(layer_iterator_.represents_itself());
341 occlusion->EnterLayer(layer_iterator_);
344 void LeaveLayer(typename Types::LayerType* layer,
345 typename Types::OcclusionTrackerType* occlusion) {
346 ASSERT_EQ(layer, *layer_iterator_);
347 ASSERT_TRUE(layer_iterator_.represents_itself());
348 occlusion->LeaveLayer(layer_iterator_);
352 void VisitLayer(typename Types::LayerType* layer,
353 typename Types::OcclusionTrackerType* occlusion) {
354 EnterLayer(layer, occlusion);
355 LeaveLayer(layer, occlusion);
358 void EnterContributingSurface(
359 typename Types::LayerType* layer,
360 typename Types::OcclusionTrackerType* occlusion) {
361 ASSERT_EQ(layer, *layer_iterator_);
362 ASSERT_TRUE(layer_iterator_.represents_target_render_surface());
363 occlusion->EnterLayer(layer_iterator_);
364 occlusion->LeaveLayer(layer_iterator_);
366 ASSERT_TRUE(layer_iterator_.represents_contributing_render_surface());
367 occlusion->EnterLayer(layer_iterator_);
370 void LeaveContributingSurface(
371 typename Types::LayerType* layer,
372 typename Types::OcclusionTrackerType* occlusion) {
373 ASSERT_EQ(layer, *layer_iterator_);
374 ASSERT_TRUE(layer_iterator_.represents_contributing_render_surface());
375 occlusion->LeaveLayer(layer_iterator_);
379 void VisitContributingSurface(
380 typename Types::LayerType* layer,
381 typename Types::OcclusionTrackerType* occlusion) {
382 EnterContributingSurface(layer, occlusion);
383 LeaveContributingSurface(layer, occlusion);
386 void ResetLayerIterator() { layer_iterator_ = layer_iterator_begin_; }
388 const gfx::Transform identity_matrix;
391 void SetRootLayerOnMainThread(Layer* root) {
392 host_->SetRootLayer(scoped_refptr<Layer>(root));
395 void SetRootLayerOnMainThread(LayerImpl* root) {}
397 void SetBaseProperties(typename Types::LayerType* layer,
398 const gfx::Transform& transform,
399 const gfx::PointF& position,
400 const gfx::Size& bounds) {
401 layer->SetTransform(transform);
402 layer->SetPosition(position);
403 layer->SetBounds(bounds);
406 void SetProperties(Layer* layer,
407 const gfx::Transform& transform,
408 const gfx::PointF& position,
409 const gfx::Size& bounds) {
410 SetBaseProperties(layer, transform, position, bounds);
413 void SetProperties(LayerImpl* layer,
414 const gfx::Transform& transform,
415 const gfx::PointF& position,
416 const gfx::Size& bounds) {
417 SetBaseProperties(layer, transform, position, bounds);
419 layer->SetContentBounds(layer->bounds());
422 void SetReplica(Layer* owning_layer, scoped_refptr<Layer> layer) {
423 owning_layer->SetReplicaLayer(layer.get());
424 replica_layers_.push_back(layer);
427 void SetReplica(LayerImpl* owning_layer, scoped_ptr<LayerImpl> layer) {
428 owning_layer->SetReplicaLayer(layer.Pass());
431 void SetMask(Layer* owning_layer, scoped_refptr<Layer> layer) {
432 owning_layer->SetMaskLayer(layer.get());
433 mask_layers_.push_back(layer);
436 void SetMask(LayerImpl* owning_layer, scoped_ptr<LayerImpl> layer) {
437 owning_layer->SetMaskLayer(layer.Pass());
441 scoped_ptr<FakeLayerTreeHost> host_;
442 // These hold ownership of the layers for the duration of the test.
443 typename Types::LayerPtrType root_;
444 scoped_ptr<RenderSurfaceLayerList> render_surface_layer_list_;
445 LayerImplList render_surface_layer_list_impl_;
446 typename Types::TestLayerIterator layer_iterator_begin_;
447 typename Types::TestLayerIterator layer_iterator_;
448 typename Types::LayerType* last_layer_visited_;
449 LayerList replica_layers_;
450 LayerList mask_layers_;
455 OcclusionTrackerTest<OcclusionTrackerTestMainThreadTypes>::GetHost() {
461 OcclusionTrackerTest<OcclusionTrackerTestImplThreadTypes>::GetHost() {
462 return host_->host_impl()->active_tree();
465 #define RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \
466 class ClassName##MainThreadOpaqueLayers \
467 : public ClassName<OcclusionTrackerTestMainThreadTypes> { \
468 public: /* NOLINT(whitespace/indent) */ \
469 ClassName##MainThreadOpaqueLayers() \
470 : ClassName<OcclusionTrackerTestMainThreadTypes>(true) {} \
472 TEST_F(ClassName##MainThreadOpaqueLayers, RunTest) { RunMyTest(); }
473 #define RUN_TEST_MAIN_THREAD_OPAQUE_PAINTS(ClassName) \
474 class ClassName##MainThreadOpaquePaints \
475 : public ClassName<OcclusionTrackerTestMainThreadTypes> { \
476 public: /* NOLINT(whitespace/indent) */ \
477 ClassName##MainThreadOpaquePaints() \
478 : ClassName<OcclusionTrackerTestMainThreadTypes>(false) {} \
480 TEST_F(ClassName##MainThreadOpaquePaints, RunTest) { RunMyTest(); }
482 #define RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) \
483 class ClassName##ImplThreadOpaqueLayers \
484 : public ClassName<OcclusionTrackerTestImplThreadTypes> { \
485 public: /* NOLINT(whitespace/indent) */ \
486 ClassName##ImplThreadOpaqueLayers() \
487 : ClassName<OcclusionTrackerTestImplThreadTypes>(true) {} \
489 TEST_F(ClassName##ImplThreadOpaqueLayers, RunTest) { RunMyTest(); }
490 #define RUN_TEST_IMPL_THREAD_OPAQUE_PAINTS(ClassName) \
491 class ClassName##ImplThreadOpaquePaints \
492 : public ClassName<OcclusionTrackerTestImplThreadTypes> { \
493 public: /* NOLINT(whitespace/indent) */ \
494 ClassName##ImplThreadOpaquePaints() \
495 : ClassName<OcclusionTrackerTestImplThreadTypes>(false) {} \
497 TEST_F(ClassName##ImplThreadOpaquePaints, RunTest) { RunMyTest(); }
499 #define ALL_OCCLUSIONTRACKER_TEST(ClassName) \
500 RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \
501 RUN_TEST_MAIN_THREAD_OPAQUE_PAINTS(ClassName) \
502 RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) \
503 RUN_TEST_IMPL_THREAD_OPAQUE_PAINTS(ClassName)
505 #define MAIN_THREAD_TEST(ClassName) \
506 RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName)
508 #define IMPL_THREAD_TEST(ClassName) \
509 RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName)
511 #define MAIN_AND_IMPL_THREAD_TEST(ClassName) \
512 RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \
513 RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName)
515 template <class Types>
516 class OcclusionTrackerTestIdentityTransforms
517 : public OcclusionTrackerTest<Types> {
519 explicit OcclusionTrackerTestIdentityTransforms(bool opaque_layers)
520 : OcclusionTrackerTest<Types>(opaque_layers) {}
523 typename Types::ContentLayerType* root = this->CreateRoot(
524 this->identity_matrix, gfx::PointF(), gfx::Size(200, 200));
525 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
526 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
527 typename Types::ContentLayerType* layer =
528 this->CreateDrawingLayer(parent,
529 this->identity_matrix,
530 gfx::PointF(30.f, 30.f),
533 parent->SetMasksToBounds(true);
534 this->CalcDrawEtc(root);
536 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
537 gfx::Rect(0, 0, 1000, 1000));
539 this->VisitLayer(layer, &occlusion);
540 this->EnterLayer(parent, &occlusion);
542 EXPECT_EQ(gfx::Rect().ToString(),
543 occlusion.occlusion_from_outside_target().ToString());
544 EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(),
545 occlusion.occlusion_from_inside_target().ToString());
547 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 70, 70)));
548 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 30, 70, 70)));
549 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 29, 70, 70)));
550 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 30, 69, 70)));
551 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 31, 70, 69)));
553 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
554 parent, gfx::Rect(30, 30, 70, 70)).IsEmpty());
555 EXPECT_RECT_EQ(gfx::Rect(29, 30, 1, 70),
556 occlusion.UnoccludedLayerContentRect(
557 parent, gfx::Rect(29, 30, 70, 70)));
558 EXPECT_RECT_EQ(gfx::Rect(29, 29, 70, 70),
559 occlusion.UnoccludedLayerContentRect(
560 parent, gfx::Rect(29, 29, 70, 70)));
561 EXPECT_RECT_EQ(gfx::Rect(30, 29, 70, 1),
562 occlusion.UnoccludedLayerContentRect(
563 parent, gfx::Rect(30, 29, 70, 70)));
564 EXPECT_RECT_EQ(gfx::Rect(31, 29, 69, 1),
565 occlusion.UnoccludedLayerContentRect(
566 parent, gfx::Rect(31, 29, 69, 70)));
567 EXPECT_RECT_EQ(gfx::Rect(),
568 occlusion.UnoccludedLayerContentRect(
569 parent, gfx::Rect(31, 30, 69, 70)));
570 EXPECT_RECT_EQ(gfx::Rect(),
571 occlusion.UnoccludedLayerContentRect(
572 parent, gfx::Rect(31, 31, 69, 69)));
573 EXPECT_RECT_EQ(gfx::Rect(),
574 occlusion.UnoccludedLayerContentRect(
575 parent, gfx::Rect(30, 31, 70, 69)));
576 EXPECT_RECT_EQ(gfx::Rect(29, 31, 1, 69),
577 occlusion.UnoccludedLayerContentRect(
578 parent, gfx::Rect(29, 31, 70, 69)));
582 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestIdentityTransforms);
584 template <class Types>
585 class OcclusionTrackerTestQuadsMismatchLayer
586 : public OcclusionTrackerTest<Types> {
588 explicit OcclusionTrackerTestQuadsMismatchLayer(bool opaque_layers)
589 : OcclusionTrackerTest<Types>(opaque_layers) {}
591 gfx::Transform layer_transform;
592 layer_transform.Translate(10.0, 10.0);
594 typename Types::ContentLayerType* parent = this->CreateRoot(
595 this->identity_matrix, gfx::Point(0, 0), gfx::Size(100, 100));
596 typename Types::ContentLayerType* layer1 = this->CreateDrawingLayer(
597 parent, layer_transform, gfx::PointF(), gfx::Size(90, 90), true);
598 typename Types::ContentLayerType* layer2 = this->CreateDrawingLayer(
599 layer1, layer_transform, gfx::PointF(), gfx::Size(50, 50), true);
600 this->CalcDrawEtc(parent);
602 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
603 gfx::Rect(0, 0, 1000, 1000));
605 this->VisitLayer(layer2, &occlusion);
606 this->EnterLayer(layer1, &occlusion);
608 EXPECT_EQ(gfx::Rect().ToString(),
609 occlusion.occlusion_from_outside_target().ToString());
610 EXPECT_EQ(gfx::Rect(20, 20, 50, 50).ToString(),
611 occlusion.occlusion_from_inside_target().ToString());
613 // This checks cases where the quads don't match their "containing"
614 // layers, e.g. in terms of transforms or clip rect. This is typical for
615 // DelegatedRendererLayer.
617 gfx::Transform quad_transform;
618 quad_transform.Translate(30.0, 30.0);
620 EXPECT_TRUE(occlusion.UnoccludedContentRect(gfx::Rect(0, 0, 10, 10),
621 quad_transform).IsEmpty());
622 EXPECT_RECT_EQ(gfx::Rect(40, 40, 10, 10),
623 occlusion.UnoccludedContentRect(gfx::Rect(40, 40, 10, 10),
625 EXPECT_RECT_EQ(gfx::Rect(40, 30, 5, 10),
626 occlusion.UnoccludedContentRect(gfx::Rect(35, 30, 10, 10),
631 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestQuadsMismatchLayer);
633 template <class Types>
634 class OcclusionTrackerTestRotatedChild : public OcclusionTrackerTest<Types> {
636 explicit OcclusionTrackerTestRotatedChild(bool opaque_layers)
637 : OcclusionTrackerTest<Types>(opaque_layers) {}
639 gfx::Transform layer_transform;
640 layer_transform.Translate(250.0, 250.0);
641 layer_transform.Rotate(90.0);
642 layer_transform.Translate(-250.0, -250.0);
644 typename Types::ContentLayerType* root = this->CreateRoot(
645 this->identity_matrix, gfx::Point(0, 0), gfx::Size(200, 200));
646 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
647 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
648 typename Types::ContentLayerType* layer =
649 this->CreateDrawingLayer(parent,
651 gfx::PointF(30.f, 30.f),
654 parent->SetMasksToBounds(true);
655 this->CalcDrawEtc(root);
657 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
658 gfx::Rect(0, 0, 1000, 1000));
660 this->VisitLayer(layer, &occlusion);
661 this->EnterLayer(parent, &occlusion);
663 EXPECT_EQ(gfx::Rect().ToString(),
664 occlusion.occlusion_from_outside_target().ToString());
665 EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(),
666 occlusion.occlusion_from_inside_target().ToString());
668 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 70, 70)));
669 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 30, 70, 70)));
670 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 29, 70, 70)));
671 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 30, 69, 70)));
672 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 31, 70, 69)));
674 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
675 parent, gfx::Rect(30, 30, 70, 70)).IsEmpty());
676 EXPECT_RECT_EQ(gfx::Rect(29, 30, 1, 70),
677 occlusion.UnoccludedLayerContentRect(
678 parent, gfx::Rect(29, 30, 69, 70)));
679 EXPECT_RECT_EQ(gfx::Rect(29, 29, 70, 70),
680 occlusion.UnoccludedLayerContentRect(
681 parent, gfx::Rect(29, 29, 70, 70)));
682 EXPECT_RECT_EQ(gfx::Rect(30, 29, 70, 1),
683 occlusion.UnoccludedLayerContentRect(
684 parent, gfx::Rect(30, 29, 70, 70)));
685 EXPECT_RECT_EQ(gfx::Rect(31, 29, 69, 1),
686 occlusion.UnoccludedLayerContentRect(
687 parent, gfx::Rect(31, 29, 69, 70)));
688 EXPECT_RECT_EQ(gfx::Rect(),
689 occlusion.UnoccludedLayerContentRect(
690 parent, gfx::Rect(31, 30, 69, 70)));
691 EXPECT_RECT_EQ(gfx::Rect(),
692 occlusion.UnoccludedLayerContentRect(
693 parent, gfx::Rect(31, 31, 69, 69)));
694 EXPECT_RECT_EQ(gfx::Rect(),
695 occlusion.UnoccludedLayerContentRect(
696 parent, gfx::Rect(30, 31, 70, 69)));
697 EXPECT_RECT_EQ(gfx::Rect(29, 31, 1, 69),
698 occlusion.UnoccludedLayerContentRect(
699 parent, gfx::Rect(29, 31, 70, 69)));
703 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestRotatedChild);
705 template <class Types>
706 class OcclusionTrackerTestTranslatedChild : public OcclusionTrackerTest<Types> {
708 explicit OcclusionTrackerTestTranslatedChild(bool opaque_layers)
709 : OcclusionTrackerTest<Types>(opaque_layers) {}
711 gfx::Transform layer_transform;
712 layer_transform.Translate(20.0, 20.0);
714 typename Types::ContentLayerType* root = this->CreateRoot(
715 this->identity_matrix, gfx::PointF(), gfx::Size(200, 200));
716 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
717 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
718 typename Types::ContentLayerType* layer =
719 this->CreateDrawingLayer(parent,
721 gfx::PointF(30.f, 30.f),
724 parent->SetMasksToBounds(true);
725 this->CalcDrawEtc(root);
727 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
728 gfx::Rect(0, 0, 1000, 1000));
730 this->VisitLayer(layer, &occlusion);
731 this->EnterLayer(parent, &occlusion);
733 EXPECT_EQ(gfx::Rect().ToString(),
734 occlusion.occlusion_from_outside_target().ToString());
735 EXPECT_EQ(gfx::Rect(50, 50, 50, 50).ToString(),
736 occlusion.occlusion_from_inside_target().ToString());
738 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(50, 50, 50, 50)));
739 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(49, 50, 50, 50)));
740 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(50, 49, 50, 50)));
741 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(51, 50, 49, 50)));
742 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(50, 51, 50, 49)));
744 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
745 parent, gfx::Rect(50, 50, 50, 50)).IsEmpty());
746 EXPECT_RECT_EQ(gfx::Rect(49, 50, 1, 50),
747 occlusion.UnoccludedLayerContentRect(
748 parent, gfx::Rect(49, 50, 50, 50)));
749 EXPECT_RECT_EQ(gfx::Rect(49, 49, 50, 50),
750 occlusion.UnoccludedLayerContentRect(
751 parent, gfx::Rect(49, 49, 50, 50)));
752 EXPECT_RECT_EQ(gfx::Rect(50, 49, 50, 1),
753 occlusion.UnoccludedLayerContentRect(
754 parent, gfx::Rect(50, 49, 50, 50)));
755 EXPECT_RECT_EQ(gfx::Rect(51, 49, 49, 1),
756 occlusion.UnoccludedLayerContentRect(
757 parent, gfx::Rect(51, 49, 49, 50)));
758 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
759 parent, gfx::Rect(51, 50, 49, 50)).IsEmpty());
760 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
761 parent, gfx::Rect(51, 51, 49, 49)).IsEmpty());
762 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
763 parent, gfx::Rect(50, 51, 50, 49)).IsEmpty());
764 EXPECT_RECT_EQ(gfx::Rect(49, 51, 1, 49),
765 occlusion.UnoccludedLayerContentRect(
766 parent, gfx::Rect(49, 51, 50, 49)));
770 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestTranslatedChild);
772 template <class Types>
773 class OcclusionTrackerTestChildInRotatedChild
774 : public OcclusionTrackerTest<Types> {
776 explicit OcclusionTrackerTestChildInRotatedChild(bool opaque_layers)
777 : OcclusionTrackerTest<Types>(opaque_layers) {}
779 gfx::Transform child_transform;
780 child_transform.Translate(250.0, 250.0);
781 child_transform.Rotate(90.0);
782 child_transform.Translate(-250.0, -250.0);
784 typename Types::ContentLayerType* parent = this->CreateRoot(
785 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
786 parent->SetMasksToBounds(true);
787 typename Types::LayerType* child = this->CreateSurface(
788 parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500));
789 child->SetMasksToBounds(true);
790 typename Types::ContentLayerType* layer =
791 this->CreateDrawingLayer(child,
792 this->identity_matrix,
793 gfx::PointF(10.f, 10.f),
796 this->CalcDrawEtc(parent);
798 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
799 gfx::Rect(0, 0, 1000, 1000));
801 this->VisitLayer(layer, &occlusion);
802 this->EnterContributingSurface(child, &occlusion);
804 EXPECT_EQ(gfx::Rect().ToString(),
805 occlusion.occlusion_from_outside_target().ToString());
806 EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(),
807 occlusion.occlusion_from_inside_target().ToString());
809 this->LeaveContributingSurface(child, &occlusion);
810 this->EnterLayer(parent, &occlusion);
812 EXPECT_EQ(gfx::Rect().ToString(),
813 occlusion.occlusion_from_outside_target().ToString());
814 EXPECT_EQ(gfx::Rect(30, 40, 70, 60).ToString(),
815 occlusion.occlusion_from_inside_target().ToString());
817 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 40, 70, 60)));
818 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 40, 70, 60)));
819 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 39, 70, 60)));
820 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 40, 69, 60)));
821 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 41, 70, 59)));
823 /* Justification for the above occlusion from |layer|:
825 +---------------------+
828 | 30 + ---------------------------------+
830 | |10+---------------------------------+
834 +----|--|-------------+ | |
842 +--|-------------------------------+ |
844 +---------------------------------+
847 +---------------------+
848 | |30 Visible region of |layer|: /////
850 | +---------------------------------+
852 | +---------------------------------+ |
853 | | |///////////////| 420 | |
854 | | |///////////////|60 | |
855 | | |///////////////| | |
856 +--|--|---------------+ | |
864 | +------------------------------|--+
866 +---------------------------------+
873 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestChildInRotatedChild);
875 template <class Types>
876 class OcclusionTrackerTestScaledRenderSurface
877 : public OcclusionTrackerTest<Types> {
879 explicit OcclusionTrackerTestScaledRenderSurface(bool opaque_layers)
880 : OcclusionTrackerTest<Types>(opaque_layers) {}
883 typename Types::ContentLayerType* parent = this->CreateRoot(
884 this->identity_matrix, gfx::PointF(), gfx::Size(200, 200));
886 gfx::Transform layer1_matrix;
887 layer1_matrix.Scale(2.0, 2.0);
888 typename Types::ContentLayerType* layer1 = this->CreateDrawingLayer(
889 parent, layer1_matrix, gfx::PointF(), gfx::Size(100, 100), true);
890 layer1->SetForceRenderSurface(true);
892 gfx::Transform layer2_matrix;
893 layer2_matrix.Translate(25.0, 25.0);
894 typename Types::ContentLayerType* layer2 = this->CreateDrawingLayer(
895 layer1, layer2_matrix, gfx::PointF(), gfx::Size(50, 50), true);
896 typename Types::ContentLayerType* occluder =
897 this->CreateDrawingLayer(parent,
898 this->identity_matrix,
899 gfx::PointF(100.f, 100.f),
902 this->CalcDrawEtc(parent);
904 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
905 gfx::Rect(0, 0, 1000, 1000));
907 this->VisitLayer(occluder, &occlusion);
908 this->EnterLayer(layer2, &occlusion);
910 EXPECT_EQ(gfx::Rect(100, 100, 100, 100).ToString(),
911 occlusion.occlusion_from_outside_target().ToString());
912 EXPECT_EQ(gfx::Rect().ToString(),
913 occlusion.occlusion_from_inside_target().ToString());
916 gfx::Rect(0, 0, 25, 25),
917 occlusion.UnoccludedLayerContentRect(layer2, gfx::Rect(0, 0, 25, 25)));
918 EXPECT_RECT_EQ(gfx::Rect(10, 25, 15, 25),
919 occlusion.UnoccludedLayerContentRect(
920 layer2, gfx::Rect(10, 25, 25, 25)));
921 EXPECT_RECT_EQ(gfx::Rect(25, 10, 25, 15),
922 occlusion.UnoccludedLayerContentRect(
923 layer2, gfx::Rect(25, 10, 25, 25)));
924 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
925 layer2, gfx::Rect(25, 25, 25, 25)).IsEmpty());
929 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestScaledRenderSurface);
931 template <class Types>
932 class OcclusionTrackerTestVisitTargetTwoTimes
933 : public OcclusionTrackerTest<Types> {
935 explicit OcclusionTrackerTestVisitTargetTwoTimes(bool opaque_layers)
936 : OcclusionTrackerTest<Types>(opaque_layers) {}
938 gfx::Transform child_transform;
939 child_transform.Translate(250.0, 250.0);
940 child_transform.Rotate(90.0);
941 child_transform.Translate(-250.0, -250.0);
943 typename Types::ContentLayerType* root = this->CreateRoot(
944 this->identity_matrix, gfx::PointF(), gfx::Size(200, 200));
945 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
946 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
947 parent->SetMasksToBounds(true);
948 typename Types::LayerType* child = this->CreateSurface(
949 parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500));
950 child->SetMasksToBounds(true);
951 typename Types::ContentLayerType* layer =
952 this->CreateDrawingLayer(child,
953 this->identity_matrix,
954 gfx::PointF(10.f, 10.f),
957 // |child2| makes |parent|'s surface get considered by OcclusionTracker
958 // first, instead of |child|'s. This exercises different code in
959 // LeaveToRenderTarget, as the target surface has already been seen.
960 typename Types::ContentLayerType* child2 =
961 this->CreateDrawingLayer(parent,
962 this->identity_matrix,
963 gfx::PointF(30.f, 30.f),
966 this->CalcDrawEtc(root);
968 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
969 gfx::Rect(0, 0, 1000, 1000));
971 this->VisitLayer(child2, &occlusion);
973 EXPECT_EQ(gfx::Rect().ToString(),
974 occlusion.occlusion_from_outside_target().ToString());
975 EXPECT_EQ(gfx::Rect(30, 30, 60, 20).ToString(),
976 occlusion.occlusion_from_inside_target().ToString());
978 this->VisitLayer(layer, &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 this->EnterContributingSurface(child, &occlusion);
987 EXPECT_EQ(gfx::Rect(0, 440, 20, 60).ToString(),
988 occlusion.occlusion_from_outside_target().ToString());
989 EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(),
990 occlusion.occlusion_from_inside_target().ToString());
992 // Occlusion in |child2| should get merged with the |child| surface we are
994 this->LeaveContributingSurface(child, &occlusion);
995 this->EnterLayer(parent, &occlusion);
997 EXPECT_EQ(gfx::Rect().ToString(),
998 occlusion.occlusion_from_outside_target().ToString());
999 EXPECT_EQ(UnionRegions(gfx::Rect(30, 30, 60, 10), gfx::Rect(30, 40, 70, 60))
1001 occlusion.occlusion_from_inside_target().ToString());
1003 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 70, 70)));
1004 EXPECT_RECT_EQ(gfx::Rect(90, 30, 10, 10),
1005 occlusion.UnoccludedLayerContentRect(
1006 parent, gfx::Rect(30, 30, 70, 70)));
1008 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 60, 10)));
1009 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 30, 60, 10)));
1010 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 29, 60, 10)));
1011 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(31, 30, 60, 10)));
1012 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 31, 60, 10)));
1014 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 40, 70, 60)));
1015 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 40, 70, 60)));
1016 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 39, 70, 60)));
1018 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
1019 parent, gfx::Rect(30, 30, 60, 10)).IsEmpty());
1020 EXPECT_RECT_EQ(gfx::Rect(29, 30, 1, 10),
1021 occlusion.UnoccludedLayerContentRect(
1022 parent, gfx::Rect(29, 30, 60, 10)));
1023 EXPECT_RECT_EQ(gfx::Rect(30, 29, 60, 1),
1024 occlusion.UnoccludedLayerContentRect(
1025 parent, gfx::Rect(30, 29, 60, 10)));
1026 EXPECT_RECT_EQ(gfx::Rect(90, 30, 1, 10),
1027 occlusion.UnoccludedLayerContentRect(
1028 parent, gfx::Rect(31, 30, 60, 10)));
1029 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
1030 parent, gfx::Rect(30, 31, 60, 10)).IsEmpty());
1032 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
1033 parent, gfx::Rect(30, 40, 70, 60)).IsEmpty());
1034 EXPECT_RECT_EQ(gfx::Rect(29, 40, 1, 60),
1035 occlusion.UnoccludedLayerContentRect(
1036 parent, gfx::Rect(29, 40, 70, 60)));
1037 // This rect is mostly occluded by |child2|.
1038 EXPECT_RECT_EQ(gfx::Rect(90, 39, 10, 1),
1039 occlusion.UnoccludedLayerContentRect(
1040 parent, gfx::Rect(30, 39, 70, 60)));
1041 // This rect extends past top/right ends of |child2|.
1042 EXPECT_RECT_EQ(gfx::Rect(30, 29, 70, 11),
1043 occlusion.UnoccludedLayerContentRect(
1044 parent, gfx::Rect(30, 29, 70, 70)));
1045 // This rect extends past left/right ends of |child2|.
1046 EXPECT_RECT_EQ(gfx::Rect(20, 39, 80, 60),
1047 occlusion.UnoccludedLayerContentRect(
1048 parent, gfx::Rect(20, 39, 80, 60)));
1049 EXPECT_RECT_EQ(gfx::Rect(),
1050 occlusion.UnoccludedLayerContentRect(
1051 parent, gfx::Rect(31, 40, 69, 60)));
1052 EXPECT_RECT_EQ(gfx::Rect(),
1053 occlusion.UnoccludedLayerContentRect(
1054 parent, gfx::Rect(30, 41, 70, 59)));
1056 /* Justification for the above occlusion from |layer|:
1058 +---------------------+
1061 | 30 + ------------+--------------------+
1062 100 | | 10 | | | ==>
1063 | |10+----------|----------------------+
1064 | + ------------+ | | |
1067 +----|--|-------------+ | |
1075 +--|-------------------------------+ |
1077 +---------------------------------+
1081 +---------------------+
1082 | |30 Visible region of |layer|: /////
1083 | 30 60 | |child2|: \\\\\
1084 | 30 +------------+--------------------+
1085 | |\\\\\\\\\\\\| |10 |
1086 | +--|\\\\\\\\\\\\|-----------------+ |
1087 | | +------------+//| 420 | |
1088 | | |///////////////|60 | |
1089 | | |///////////////| | |
1090 +--|--|---------------+ | |
1098 | +------------------------------|--+
1100 +---------------------------------+
1106 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestVisitTargetTwoTimes);
1108 template <class Types>
1109 class OcclusionTrackerTestSurfaceRotatedOffAxis
1110 : public OcclusionTrackerTest<Types> {
1112 explicit OcclusionTrackerTestSurfaceRotatedOffAxis(bool opaque_layers)
1113 : OcclusionTrackerTest<Types>(opaque_layers) {}
1115 gfx::Transform child_transform;
1116 child_transform.Translate(250.0, 250.0);
1117 child_transform.Rotate(95.0);
1118 child_transform.Translate(-250.0, -250.0);
1120 gfx::Transform layer_transform;
1121 layer_transform.Translate(10.0, 10.0);
1123 typename Types::ContentLayerType* root = this->CreateRoot(
1124 this->identity_matrix, gfx::PointF(), gfx::Size(1000, 1000));
1125 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
1126 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
1127 typename Types::LayerType* child = this->CreateLayer(
1128 parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500));
1129 child->SetMasksToBounds(true);
1130 typename Types::ContentLayerType* layer = this->CreateDrawingLayer(
1131 child, layer_transform, gfx::PointF(), gfx::Size(500, 500), true);
1132 this->CalcDrawEtc(root);
1134 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1135 gfx::Rect(0, 0, 1000, 1000));
1137 gfx::Rect clipped_layer_in_child = MathUtil::MapEnclosingClippedRect(
1138 layer_transform, layer->visible_content_rect());
1140 this->VisitLayer(layer, &occlusion);
1141 this->EnterContributingSurface(child, &occlusion);
1143 EXPECT_EQ(gfx::Rect().ToString(),
1144 occlusion.occlusion_from_outside_target().ToString());
1145 EXPECT_EQ(clipped_layer_in_child.ToString(),
1146 occlusion.occlusion_from_inside_target().ToString());
1148 this->LeaveContributingSurface(child, &occlusion);
1149 this->EnterLayer(parent, &occlusion);
1151 EXPECT_EQ(gfx::Rect().ToString(),
1152 occlusion.occlusion_from_outside_target().ToString());
1153 EXPECT_EQ(gfx::Rect().ToString(),
1154 occlusion.occlusion_from_inside_target().ToString());
1156 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(75, 55, 1, 1)));
1158 gfx::Rect(75, 55, 1, 1),
1159 occlusion.UnoccludedLayerContentRect(parent, gfx::Rect(75, 55, 1, 1)));
1163 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceRotatedOffAxis);
1165 template <class Types>
1166 class OcclusionTrackerTestSurfaceWithTwoOpaqueChildren
1167 : public OcclusionTrackerTest<Types> {
1169 explicit OcclusionTrackerTestSurfaceWithTwoOpaqueChildren(bool opaque_layers)
1170 : OcclusionTrackerTest<Types>(opaque_layers) {}
1172 gfx::Transform child_transform;
1173 child_transform.Translate(250.0, 250.0);
1174 child_transform.Rotate(90.0);
1175 child_transform.Translate(-250.0, -250.0);
1177 typename Types::ContentLayerType* root = this->CreateRoot(
1178 this->identity_matrix, gfx::PointF(), gfx::Size(1000, 1000));
1179 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
1180 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
1181 parent->SetMasksToBounds(true);
1182 typename Types::ContentLayerType* child =
1183 this->CreateDrawingSurface(parent,
1185 gfx::PointF(30.f, 30.f),
1186 gfx::Size(500, 500),
1188 child->SetMasksToBounds(true);
1189 typename Types::ContentLayerType* layer1 =
1190 this->CreateDrawingLayer(child,
1191 this->identity_matrix,
1192 gfx::PointF(10.f, 10.f),
1193 gfx::Size(500, 500),
1195 typename Types::ContentLayerType* layer2 =
1196 this->CreateDrawingLayer(child,
1197 this->identity_matrix,
1198 gfx::PointF(10.f, 450.f),
1201 this->CalcDrawEtc(root);
1203 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1204 gfx::Rect(0, 0, 1000, 1000));
1206 this->VisitLayer(layer2, &occlusion);
1207 this->VisitLayer(layer1, &occlusion);
1208 this->VisitLayer(child, &occlusion);
1209 this->EnterContributingSurface(child, &occlusion);
1211 EXPECT_EQ(gfx::Rect().ToString(),
1212 occlusion.occlusion_from_outside_target().ToString());
1213 EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(),
1214 occlusion.occlusion_from_inside_target().ToString());
1216 EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(10, 430, 60, 70)));
1217 EXPECT_FALSE(occlusion.OccludedLayer(child, gfx::Rect(9, 430, 60, 70)));
1218 EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(11, 430, 59, 70)));
1219 EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(10, 431, 60, 69)));
1221 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
1222 child, gfx::Rect(10, 430, 60, 70)).IsEmpty());
1224 gfx::Rect(9, 430, 1, 70),
1225 occlusion.UnoccludedLayerContentRect(child, gfx::Rect(9, 430, 60, 70)));
1226 EXPECT_RECT_EQ(gfx::Rect(),
1227 occlusion.UnoccludedLayerContentRect(
1228 child, gfx::Rect(11, 430, 59, 70)));
1229 EXPECT_RECT_EQ(gfx::Rect(),
1230 occlusion.UnoccludedLayerContentRect(
1231 child, gfx::Rect(10, 431, 60, 69)));
1233 this->LeaveContributingSurface(child, &occlusion);
1234 this->EnterLayer(parent, &occlusion);
1236 EXPECT_EQ(gfx::Rect().ToString(),
1237 occlusion.occlusion_from_outside_target().ToString());
1238 EXPECT_EQ(gfx::Rect(30, 40, 70, 60).ToString(),
1239 occlusion.occlusion_from_inside_target().ToString());
1241 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 40, 70, 60)));
1242 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 40, 70, 60)));
1243 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 39, 70, 60)));
1245 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
1246 parent, gfx::Rect(30, 40, 70, 60)).IsEmpty());
1247 EXPECT_RECT_EQ(gfx::Rect(29, 40, 1, 60),
1248 occlusion.UnoccludedLayerContentRect(
1249 parent, gfx::Rect(29, 40, 70, 60)));
1250 EXPECT_RECT_EQ(gfx::Rect(30, 39, 70, 1),
1251 occlusion.UnoccludedLayerContentRect(
1252 parent, gfx::Rect(30, 39, 70, 60)));
1253 EXPECT_RECT_EQ(gfx::Rect(),
1254 occlusion.UnoccludedLayerContentRect(
1255 parent, gfx::Rect(31, 40, 69, 60)));
1256 EXPECT_RECT_EQ(gfx::Rect(),
1257 occlusion.UnoccludedLayerContentRect(
1258 parent, gfx::Rect(30, 41, 70, 59)));
1260 /* Justification for the above occlusion from |layer1| and |layer2|:
1262 +---------------------+
1263 | |30 Visible region of |layer1|: /////
1264 | | Visible region of |layer2|: \\\\\
1265 | +---------------------------------+
1267 | +---------------+-----------------+ |
1268 | | |\\\\\\\\\\\\|//| 420 | |
1269 | | |\\\\\\\\\\\\|//|60 | |
1270 | | |\\\\\\\\\\\\|//| | |
1271 +--|--|------------|--+ | |
1279 | +------------|-----------------|--+
1281 +---------------+-----------------+
1287 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceWithTwoOpaqueChildren);
1289 template <class Types>
1290 class OcclusionTrackerTestOverlappingSurfaceSiblings
1291 : public OcclusionTrackerTest<Types> {
1293 explicit OcclusionTrackerTestOverlappingSurfaceSiblings(bool opaque_layers)
1294 : OcclusionTrackerTest<Types>(opaque_layers) {}
1296 gfx::Transform child_transform;
1297 child_transform.Translate(250.0, 250.0);
1298 child_transform.Rotate(90.0);
1299 child_transform.Translate(-250.0, -250.0);
1301 typename Types::ContentLayerType* parent = this->CreateRoot(
1302 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
1303 parent->SetMasksToBounds(true);
1304 typename Types::LayerType* child1 = this->CreateSurface(
1305 parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(10, 10));
1306 typename Types::LayerType* child2 = this->CreateSurface(
1307 parent, child_transform, gfx::PointF(20.f, 40.f), gfx::Size(10, 10));
1308 typename Types::ContentLayerType* layer1 =
1309 this->CreateDrawingLayer(child1,
1310 this->identity_matrix,
1311 gfx::PointF(-10.f, -10.f),
1312 gfx::Size(510, 510),
1314 typename Types::ContentLayerType* layer2 =
1315 this->CreateDrawingLayer(child2,
1316 this->identity_matrix,
1317 gfx::PointF(-10.f, -10.f),
1318 gfx::Size(510, 510),
1320 this->CalcDrawEtc(parent);
1322 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1323 gfx::Rect(0, 0, 1000, 1000));
1325 this->VisitLayer(layer2, &occlusion);
1326 this->EnterContributingSurface(child2, &occlusion);
1328 EXPECT_EQ(gfx::Rect().ToString(),
1329 occlusion.occlusion_from_outside_target().ToString());
1330 EXPECT_EQ(gfx::Rect(-10, 420, 70, 80).ToString(),
1331 occlusion.occlusion_from_inside_target().ToString());
1333 // There is nothing above child2's surface in the z-order.
1334 EXPECT_RECT_EQ(gfx::Rect(-10, 420, 70, 80),
1335 occlusion.UnoccludedSurfaceContentRect(
1336 child2, false, gfx::Rect(-10, 420, 70, 80)));
1338 this->LeaveContributingSurface(child2, &occlusion);
1339 this->VisitLayer(layer1, &occlusion);
1340 this->EnterContributingSurface(child1, &occlusion);
1342 EXPECT_EQ(gfx::Rect(0, 430, 70, 80).ToString(),
1343 occlusion.occlusion_from_outside_target().ToString());
1344 EXPECT_EQ(gfx::Rect(-10, 430, 80, 70).ToString(),
1345 occlusion.occlusion_from_inside_target().ToString());
1347 // child2's contents will occlude child1 below it.
1348 EXPECT_RECT_EQ(gfx::Rect(-10, 430, 10, 70),
1349 occlusion.UnoccludedSurfaceContentRect(
1350 child1, false, gfx::Rect(-10, 430, 80, 70)));
1352 this->LeaveContributingSurface(child1, &occlusion);
1353 this->EnterLayer(parent, &occlusion);
1355 EXPECT_EQ(gfx::Rect().ToString(),
1356 occlusion.occlusion_from_outside_target().ToString());
1357 EXPECT_EQ(UnionRegions(gfx::Rect(30, 20, 70, 10), gfx::Rect(20, 30, 80, 70))
1359 occlusion.occlusion_from_inside_target().ToString());
1361 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(20, 20, 80, 80)));
1363 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 20, 70, 80)));
1364 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 20, 70, 80)));
1365 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 19, 70, 80)));
1367 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(20, 30, 80, 70)));
1368 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(19, 30, 80, 70)));
1369 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(20, 29, 80, 70)));
1371 /* Justification for the above occlusion:
1373 +---------------------+
1375 | 30+ ---------------------------------+
1376 100 | 30| | layer2 |
1377 |20+----------------------------------+ |
1381 +--|-|----------------+ | |
1389 | +--------------------------------|-+
1391 +----------------------------------+
1397 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestOverlappingSurfaceSiblings);
1399 template <class Types>
1400 class OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms
1401 : public OcclusionTrackerTest<Types> {
1403 explicit OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms(
1405 : OcclusionTrackerTest<Types>(opaque_layers) {}
1407 gfx::Transform child1_transform;
1408 child1_transform.Translate(250.0, 250.0);
1409 child1_transform.Rotate(-90.0);
1410 child1_transform.Translate(-250.0, -250.0);
1412 gfx::Transform child2_transform;
1413 child2_transform.Translate(250.0, 250.0);
1414 child2_transform.Rotate(90.0);
1415 child2_transform.Translate(-250.0, -250.0);
1417 typename Types::ContentLayerType* parent = this->CreateRoot(
1418 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
1419 parent->SetMasksToBounds(true);
1420 typename Types::LayerType* child1 = this->CreateSurface(
1421 parent, child1_transform, gfx::PointF(30.f, 20.f), gfx::Size(10, 10));
1422 typename Types::LayerType* child2 =
1423 this->CreateDrawingSurface(parent,
1425 gfx::PointF(20.f, 40.f),
1428 typename Types::ContentLayerType* layer1 =
1429 this->CreateDrawingLayer(child1,
1430 this->identity_matrix,
1431 gfx::PointF(-10.f, -20.f),
1432 gfx::Size(510, 510),
1434 typename Types::ContentLayerType* layer2 =
1435 this->CreateDrawingLayer(child2,
1436 this->identity_matrix,
1437 gfx::PointF(-10.f, -10.f),
1438 gfx::Size(510, 510),
1440 this->CalcDrawEtc(parent);
1442 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1443 gfx::Rect(0, 0, 1000, 1000));
1445 this->VisitLayer(layer2, &occlusion);
1446 this->EnterLayer(child2, &occlusion);
1448 EXPECT_EQ(gfx::Rect().ToString(),
1449 occlusion.occlusion_from_outside_target().ToString());
1450 EXPECT_EQ(gfx::Rect(-10, 420, 70, 80).ToString(),
1451 occlusion.occlusion_from_inside_target().ToString());
1453 this->LeaveLayer(child2, &occlusion);
1454 this->EnterContributingSurface(child2, &occlusion);
1456 // There is nothing above child2's surface in the z-order.
1457 EXPECT_RECT_EQ(gfx::Rect(-10, 420, 70, 80),
1458 occlusion.UnoccludedSurfaceContentRect(
1459 child2, false, gfx::Rect(-10, 420, 70, 80)));
1461 this->LeaveContributingSurface(child2, &occlusion);
1462 this->VisitLayer(layer1, &occlusion);
1463 this->EnterContributingSurface(child1, &occlusion);
1465 EXPECT_EQ(gfx::Rect(420, -10, 70, 80).ToString(),
1466 occlusion.occlusion_from_outside_target().ToString());
1467 EXPECT_EQ(gfx::Rect(420, -20, 80, 90).ToString(),
1468 occlusion.occlusion_from_inside_target().ToString());
1470 // child2's contents will occlude child1 below it.
1471 EXPECT_EQ(gfx::Rect(20, 30, 80, 70).ToString(),
1472 occlusion.occlusion_on_contributing_surface_from_inside_target()
1474 EXPECT_EQ(gfx::Rect().ToString(),
1475 occlusion.occlusion_on_contributing_surface_from_outside_target()
1478 this->LeaveContributingSurface(child1, &occlusion);
1479 this->EnterLayer(parent, &occlusion);
1481 EXPECT_EQ(gfx::Rect().ToString(),
1482 occlusion.occlusion_from_outside_target().ToString());
1483 EXPECT_EQ(gfx::Rect(10, 20, 90, 80).ToString(),
1484 occlusion.occlusion_from_inside_target().ToString());
1486 /* Justification for the above occlusion:
1488 +---------------------+
1490 10+----------------------------------+
1491 100 || 30 | layer2 |
1492 |20+----------------------------------+
1496 +|-|------------------+ | |
1504 +----------------------------------+ |
1506 +----------------------------------+
1512 ALL_OCCLUSIONTRACKER_TEST(
1513 OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms);
1515 template <class Types>
1516 class OcclusionTrackerTestFilters : public OcclusionTrackerTest<Types> {
1518 explicit OcclusionTrackerTestFilters(bool opaque_layers)
1519 : OcclusionTrackerTest<Types>(opaque_layers) {}
1521 gfx::Transform layer_transform;
1522 layer_transform.Translate(250.0, 250.0);
1523 layer_transform.Rotate(90.0);
1524 layer_transform.Translate(-250.0, -250.0);
1526 typename Types::ContentLayerType* parent = this->CreateRoot(
1527 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
1528 parent->SetMasksToBounds(true);
1529 typename Types::ContentLayerType* blur_layer =
1530 this->CreateDrawingLayer(parent,
1532 gfx::PointF(30.f, 30.f),
1533 gfx::Size(500, 500),
1535 typename Types::ContentLayerType* opaque_layer =
1536 this->CreateDrawingLayer(parent,
1538 gfx::PointF(30.f, 30.f),
1539 gfx::Size(500, 500),
1541 typename Types::ContentLayerType* opacity_layer =
1542 this->CreateDrawingLayer(parent,
1544 gfx::PointF(30.f, 30.f),
1545 gfx::Size(500, 500),
1548 FilterOperations filters;
1549 filters.Append(FilterOperation::CreateBlurFilter(10.f));
1550 blur_layer->SetFilters(filters);
1553 filters.Append(FilterOperation::CreateGrayscaleFilter(0.5f));
1554 opaque_layer->SetFilters(filters);
1557 filters.Append(FilterOperation::CreateOpacityFilter(0.5f));
1558 opacity_layer->SetFilters(filters);
1560 this->CalcDrawEtc(parent);
1562 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1563 gfx::Rect(0, 0, 1000, 1000));
1565 // Opacity layer won't contribute to occlusion.
1566 this->VisitLayer(opacity_layer, &occlusion);
1567 this->EnterContributingSurface(opacity_layer, &occlusion);
1569 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1570 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1572 // And has nothing to contribute to its parent surface.
1573 this->LeaveContributingSurface(opacity_layer, &occlusion);
1574 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1575 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1577 // Opaque layer will contribute to occlusion.
1578 this->VisitLayer(opaque_layer, &occlusion);
1579 this->EnterContributingSurface(opaque_layer, &occlusion);
1581 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1582 EXPECT_EQ(gfx::Rect(0, 430, 70, 70).ToString(),
1583 occlusion.occlusion_from_inside_target().ToString());
1585 // And it gets translated to the parent surface.
1586 this->LeaveContributingSurface(opaque_layer, &occlusion);
1587 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1588 EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(),
1589 occlusion.occlusion_from_inside_target().ToString());
1591 // The blur layer needs to throw away any occlusion from outside its
1593 this->EnterLayer(blur_layer, &occlusion);
1594 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1595 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1597 // And it won't contribute to occlusion.
1598 this->LeaveLayer(blur_layer, &occlusion);
1599 this->EnterContributingSurface(blur_layer, &occlusion);
1600 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1601 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1603 // But the opaque layer's occlusion is preserved on the parent.
1604 this->LeaveContributingSurface(blur_layer, &occlusion);
1605 this->EnterLayer(parent, &occlusion);
1606 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1607 EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(),
1608 occlusion.occlusion_from_inside_target().ToString());
1612 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestFilters);
1614 template <class Types>
1615 class OcclusionTrackerTestReplicaDoesOcclude
1616 : public OcclusionTrackerTest<Types> {
1618 explicit OcclusionTrackerTestReplicaDoesOcclude(bool opaque_layers)
1619 : OcclusionTrackerTest<Types>(opaque_layers) {}
1621 typename Types::ContentLayerType* parent = this->CreateRoot(
1622 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
1623 typename Types::LayerType* surface =
1624 this->CreateDrawingSurface(parent,
1625 this->identity_matrix,
1626 gfx::PointF(0.f, 100.f),
1629 this->CreateReplicaLayer(
1630 surface, this->identity_matrix, gfx::PointF(50.f, 50.f), gfx::Size());
1631 this->CalcDrawEtc(parent);
1633 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1634 gfx::Rect(0, 0, 1000, 1000));
1636 this->VisitLayer(surface, &occlusion);
1638 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
1639 occlusion.occlusion_from_inside_target().ToString());
1641 this->VisitContributingSurface(surface, &occlusion);
1642 this->EnterLayer(parent, &occlusion);
1644 // The surface and replica should both be occluding the parent.
1646 UnionRegions(gfx::Rect(0, 100, 50, 50),
1647 gfx::Rect(50, 150, 50, 50)).ToString(),
1648 occlusion.occlusion_from_inside_target().ToString());
1652 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaDoesOcclude);
1654 template <class Types>
1655 class OcclusionTrackerTestReplicaWithClipping
1656 : public OcclusionTrackerTest<Types> {
1658 explicit OcclusionTrackerTestReplicaWithClipping(bool opaque_layers)
1659 : OcclusionTrackerTest<Types>(opaque_layers) {}
1661 typename Types::ContentLayerType* parent = this->CreateRoot(
1662 this->identity_matrix, gfx::PointF(), gfx::Size(100, 170));
1663 parent->SetMasksToBounds(true);
1664 typename Types::LayerType* surface =
1665 this->CreateDrawingSurface(parent,
1666 this->identity_matrix,
1667 gfx::PointF(0.f, 100.f),
1670 this->CreateReplicaLayer(
1671 surface, this->identity_matrix, gfx::PointF(50.f, 50.f), gfx::Size());
1672 this->CalcDrawEtc(parent);
1674 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1675 gfx::Rect(0, 0, 1000, 1000));
1677 this->VisitLayer(surface, &occlusion);
1679 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
1680 occlusion.occlusion_from_inside_target().ToString());
1682 this->VisitContributingSurface(surface, &occlusion);
1683 this->EnterLayer(parent, &occlusion);
1685 // The surface and replica should both be occluding the parent.
1687 UnionRegions(gfx::Rect(0, 100, 50, 50),
1688 gfx::Rect(50, 150, 50, 20)).ToString(),
1689 occlusion.occlusion_from_inside_target().ToString());
1693 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaWithClipping);
1695 template <class Types>
1696 class OcclusionTrackerTestReplicaWithMask : public OcclusionTrackerTest<Types> {
1698 explicit OcclusionTrackerTestReplicaWithMask(bool opaque_layers)
1699 : OcclusionTrackerTest<Types>(opaque_layers) {}
1701 typename Types::ContentLayerType* parent = this->CreateRoot(
1702 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
1703 typename Types::LayerType* surface =
1704 this->CreateDrawingSurface(parent,
1705 this->identity_matrix,
1706 gfx::PointF(0.f, 100.f),
1709 typename Types::LayerType* replica = this->CreateReplicaLayer(
1710 surface, this->identity_matrix, gfx::PointF(50.f, 50.f), gfx::Size());
1711 this->CreateMaskLayer(replica, gfx::Size(10, 10));
1712 this->CalcDrawEtc(parent);
1714 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1715 gfx::Rect(0, 0, 1000, 1000));
1717 this->VisitLayer(surface, &occlusion);
1719 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
1720 occlusion.occlusion_from_inside_target().ToString());
1722 this->VisitContributingSurface(surface, &occlusion);
1723 this->EnterLayer(parent, &occlusion);
1725 // The replica should not be occluding the parent, since it has a mask
1727 EXPECT_EQ(gfx::Rect(0, 100, 50, 50).ToString(),
1728 occlusion.occlusion_from_inside_target().ToString());
1732 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaWithMask);
1734 template <class Types>
1735 class OcclusionTrackerTestOpaqueContentsRegionEmpty
1736 : public OcclusionTrackerTest<Types> {
1738 explicit OcclusionTrackerTestOpaqueContentsRegionEmpty(bool opaque_layers)
1739 : OcclusionTrackerTest<Types>(opaque_layers) {}
1741 typename Types::ContentLayerType* parent = this->CreateRoot(
1742 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1743 typename Types::ContentLayerType* layer =
1744 this->CreateDrawingSurface(parent,
1745 this->identity_matrix,
1747 gfx::Size(200, 200),
1749 this->CalcDrawEtc(parent);
1751 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1752 gfx::Rect(0, 0, 1000, 1000));
1753 this->EnterLayer(layer, &occlusion);
1755 EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 100, 100)));
1756 EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 0, 100, 100)));
1757 EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 100, 100, 100)));
1758 EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 100, 100, 100)));
1760 this->LeaveLayer(layer, &occlusion);
1761 this->VisitContributingSurface(layer, &occlusion);
1762 this->EnterLayer(parent, &occlusion);
1764 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1768 MAIN_AND_IMPL_THREAD_TEST(OcclusionTrackerTestOpaqueContentsRegionEmpty);
1770 template <class Types>
1771 class OcclusionTrackerTestOpaqueContentsRegionNonEmpty
1772 : public OcclusionTrackerTest<Types> {
1774 explicit OcclusionTrackerTestOpaqueContentsRegionNonEmpty(bool opaque_layers)
1775 : OcclusionTrackerTest<Types>(opaque_layers) {}
1777 typename Types::ContentLayerType* parent = this->CreateRoot(
1778 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1779 typename Types::ContentLayerType* layer =
1780 this->CreateDrawingLayer(parent,
1781 this->identity_matrix,
1782 gfx::PointF(100.f, 100.f),
1783 gfx::Size(200, 200),
1785 this->CalcDrawEtc(parent);
1787 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1788 gfx::Rect(0, 0, 1000, 1000));
1789 layer->SetOpaqueContentsRect(gfx::Rect(0, 0, 100, 100));
1791 this->ResetLayerIterator();
1792 this->VisitLayer(layer, &occlusion);
1793 this->EnterLayer(parent, &occlusion);
1795 EXPECT_EQ(gfx::Rect(100, 100, 100, 100).ToString(),
1796 occlusion.occlusion_from_inside_target().ToString());
1799 occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100)));
1801 occlusion.OccludedLayer(parent, gfx::Rect(100, 100, 100, 100)));
1803 occlusion.OccludedLayer(parent, gfx::Rect(200, 200, 100, 100)));
1806 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1807 gfx::Rect(0, 0, 1000, 1000));
1808 layer->SetOpaqueContentsRect(gfx::Rect(20, 20, 180, 180));
1810 this->ResetLayerIterator();
1811 this->VisitLayer(layer, &occlusion);
1812 this->EnterLayer(parent, &occlusion);
1814 EXPECT_EQ(gfx::Rect(120, 120, 180, 180).ToString(),
1815 occlusion.occlusion_from_inside_target().ToString());
1818 occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100)));
1820 occlusion.OccludedLayer(parent, gfx::Rect(100, 100, 100, 100)));
1822 occlusion.OccludedLayer(parent, gfx::Rect(200, 200, 100, 100)));
1825 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1826 gfx::Rect(0, 0, 1000, 1000));
1827 layer->SetOpaqueContentsRect(gfx::Rect(150, 150, 100, 100));
1829 this->ResetLayerIterator();
1830 this->VisitLayer(layer, &occlusion);
1831 this->EnterLayer(parent, &occlusion);
1833 EXPECT_EQ(gfx::Rect(250, 250, 50, 50).ToString(),
1834 occlusion.occlusion_from_inside_target().ToString());
1837 occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100)));
1839 occlusion.OccludedLayer(parent, gfx::Rect(100, 100, 100, 100)));
1841 occlusion.OccludedLayer(parent, gfx::Rect(200, 200, 100, 100)));
1846 MAIN_AND_IMPL_THREAD_TEST(OcclusionTrackerTestOpaqueContentsRegionNonEmpty);
1848 template <class Types>
1849 class OcclusionTrackerTest3dTransform : public OcclusionTrackerTest<Types> {
1851 explicit OcclusionTrackerTest3dTransform(bool opaque_layers)
1852 : OcclusionTrackerTest<Types>(opaque_layers) {}
1854 gfx::Transform transform;
1855 transform.RotateAboutYAxis(30.0);
1857 typename Types::ContentLayerType* parent = this->CreateRoot(
1858 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1859 typename Types::LayerType* container = this->CreateLayer(
1860 parent, this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1861 typename Types::ContentLayerType* layer =
1862 this->CreateDrawingLayer(container,
1864 gfx::PointF(100.f, 100.f),
1865 gfx::Size(200, 200),
1867 this->CalcDrawEtc(parent);
1869 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1870 gfx::Rect(0, 0, 1000, 1000));
1871 this->EnterLayer(layer, &occlusion);
1873 // The layer is rotated in 3d but without preserving 3d, so it only gets
1876 gfx::Rect(0, 0, 200, 200),
1877 occlusion.UnoccludedLayerContentRect(layer, gfx::Rect(0, 0, 200, 200)));
1881 MAIN_AND_IMPL_THREAD_TEST(OcclusionTrackerTest3dTransform);
1883 template <class Types>
1884 class OcclusionTrackerTestUnsorted3dLayers
1885 : public OcclusionTrackerTest<Types> {
1887 explicit OcclusionTrackerTestUnsorted3dLayers(bool opaque_layers)
1888 : OcclusionTrackerTest<Types>(opaque_layers) {}
1890 // Currently, The main thread layer iterator does not iterate over 3d items
1891 // in sorted order, because layer sorting is not performed on the main
1892 // thread. Because of this, the occlusion tracker cannot assume that a 3d
1893 // layer occludes other layers that have not yet been iterated over. For
1894 // now, the expected behavior is that a 3d layer simply does not add any
1895 // occlusion to the occlusion tracker.
1897 gfx::Transform translation_to_front;
1898 translation_to_front.Translate3d(0.0, 0.0, -10.0);
1899 gfx::Transform translation_to_back;
1900 translation_to_front.Translate3d(0.0, 0.0, -100.0);
1902 typename Types::ContentLayerType* parent = this->CreateRoot(
1903 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1904 typename Types::ContentLayerType* child1 = this->CreateDrawingLayer(
1905 parent, translation_to_back, gfx::PointF(), gfx::Size(100, 100), true);
1906 typename Types::ContentLayerType* child2 =
1907 this->CreateDrawingLayer(parent,
1908 translation_to_front,
1909 gfx::PointF(50.f, 50.f),
1910 gfx::Size(100, 100),
1912 parent->SetShouldFlattenTransform(false);
1913 parent->Set3dSortingContextId(1);
1914 child1->Set3dSortingContextId(1);
1915 child2->Set3dSortingContextId(1);
1917 this->CalcDrawEtc(parent);
1919 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1920 gfx::Rect(0, 0, 1000, 1000));
1921 this->VisitLayer(child2, &occlusion);
1922 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1923 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1925 this->VisitLayer(child1, &occlusion);
1926 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1927 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1931 // This test will have different layer ordering on the impl thread; the test
1932 // will only work on the main thread.
1933 MAIN_THREAD_TEST(OcclusionTrackerTestUnsorted3dLayers);
1935 template <class Types>
1936 class OcclusionTrackerTestPerspectiveTransform
1937 : public OcclusionTrackerTest<Types> {
1939 explicit OcclusionTrackerTestPerspectiveTransform(bool opaque_layers)
1940 : OcclusionTrackerTest<Types>(opaque_layers) {}
1942 gfx::Transform transform;
1943 transform.Translate(150.0, 150.0);
1944 transform.ApplyPerspectiveDepth(400.0);
1945 transform.RotateAboutXAxis(-30.0);
1946 transform.Translate(-150.0, -150.0);
1948 typename Types::ContentLayerType* parent = this->CreateRoot(
1949 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1950 typename Types::LayerType* container = this->CreateLayer(
1951 parent, this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1952 typename Types::ContentLayerType* layer =
1953 this->CreateDrawingLayer(container,
1955 gfx::PointF(100.f, 100.f),
1956 gfx::Size(200, 200),
1958 container->SetShouldFlattenTransform(false);
1959 container->Set3dSortingContextId(1);
1960 layer->Set3dSortingContextId(1);
1961 layer->SetShouldFlattenTransform(false);
1963 this->CalcDrawEtc(parent);
1965 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1966 gfx::Rect(0, 0, 1000, 1000));
1967 this->EnterLayer(layer, &occlusion);
1970 gfx::Rect(0, 0, 200, 200),
1971 occlusion.UnoccludedLayerContentRect(layer, gfx::Rect(0, 0, 200, 200)));
1975 // This test requires accumulating occlusion of 3d layers, which are skipped by
1976 // the occlusion tracker on the main thread. So this test should run on the impl
1978 IMPL_THREAD_TEST(OcclusionTrackerTestPerspectiveTransform);
1979 template <class Types>
1980 class OcclusionTrackerTestPerspectiveTransformBehindCamera
1981 : public OcclusionTrackerTest<Types> {
1983 explicit OcclusionTrackerTestPerspectiveTransformBehindCamera(
1985 : OcclusionTrackerTest<Types>(opaque_layers) {}
1987 // This test is based on the platform/chromium/compositing/3d-corners.html
1989 gfx::Transform transform;
1990 transform.Translate(250.0, 50.0);
1991 transform.ApplyPerspectiveDepth(10.0);
1992 transform.Translate(-250.0, -50.0);
1993 transform.Translate(250.0, 50.0);
1994 transform.RotateAboutXAxis(-167.0);
1995 transform.Translate(-250.0, -50.0);
1997 typename Types::ContentLayerType* parent = this->CreateRoot(
1998 this->identity_matrix, gfx::PointF(), gfx::Size(500, 100));
1999 typename Types::LayerType* container = this->CreateLayer(
2000 parent, this->identity_matrix, gfx::PointF(), gfx::Size(500, 500));
2001 typename Types::ContentLayerType* layer = this->CreateDrawingLayer(
2002 container, transform, gfx::PointF(), gfx::Size(500, 500), true);
2003 container->SetShouldFlattenTransform(false);
2004 container->Set3dSortingContextId(1);
2005 layer->SetShouldFlattenTransform(false);
2006 layer->Set3dSortingContextId(1);
2007 this->CalcDrawEtc(parent);
2009 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2010 gfx::Rect(0, 0, 1000, 1000));
2011 this->EnterLayer(layer, &occlusion);
2013 // The bottom 11 pixel rows of this layer remain visible inside the
2014 // container, after translation to the target surface. When translated back,
2015 // this will include many more pixels but must include at least the bottom
2017 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
2018 layer, gfx::Rect(0, 26, 500, 474)).
2019 Contains(gfx::Rect(0, 489, 500, 11)));
2023 // This test requires accumulating occlusion of 3d layers, which are skipped by
2024 // the occlusion tracker on the main thread. So this test should run on the impl
2026 IMPL_THREAD_TEST(OcclusionTrackerTestPerspectiveTransformBehindCamera);
2028 template <class Types>
2029 class OcclusionTrackerTestLayerBehindCameraDoesNotOcclude
2030 : public OcclusionTrackerTest<Types> {
2032 explicit OcclusionTrackerTestLayerBehindCameraDoesNotOcclude(
2034 : OcclusionTrackerTest<Types>(opaque_layers) {}
2036 gfx::Transform transform;
2037 transform.Translate(50.0, 50.0);
2038 transform.ApplyPerspectiveDepth(100.0);
2039 transform.Translate3d(0.0, 0.0, 110.0);
2040 transform.Translate(-50.0, -50.0);
2042 typename Types::ContentLayerType* parent = this->CreateRoot(
2043 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
2044 typename Types::ContentLayerType* layer = this->CreateDrawingLayer(
2045 parent, transform, gfx::PointF(), gfx::Size(100, 100), true);
2046 parent->SetShouldFlattenTransform(false);
2047 parent->Set3dSortingContextId(1);
2048 layer->SetShouldFlattenTransform(false);
2049 layer->Set3dSortingContextId(1);
2050 this->CalcDrawEtc(parent);
2052 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2053 gfx::Rect(0, 0, 1000, 1000));
2055 // The |layer| is entirely behind the camera and should not occlude.
2056 this->VisitLayer(layer, &occlusion);
2057 this->EnterLayer(parent, &occlusion);
2058 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
2059 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
2063 // This test requires accumulating occlusion of 3d layers, which are skipped by
2064 // the occlusion tracker on the main thread. So this test should run on the impl
2066 IMPL_THREAD_TEST(OcclusionTrackerTestLayerBehindCameraDoesNotOcclude);
2068 template <class Types>
2069 class OcclusionTrackerTestLargePixelsOccludeInsideClipRect
2070 : public OcclusionTrackerTest<Types> {
2072 explicit OcclusionTrackerTestLargePixelsOccludeInsideClipRect(
2074 : OcclusionTrackerTest<Types>(opaque_layers) {}
2076 gfx::Transform transform;
2077 transform.Translate(50.0, 50.0);
2078 transform.ApplyPerspectiveDepth(100.0);
2079 transform.Translate3d(0.0, 0.0, 99.0);
2080 transform.Translate(-50.0, -50.0);
2082 typename Types::ContentLayerType* parent = this->CreateRoot(
2083 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
2084 parent->SetMasksToBounds(true);
2085 typename Types::ContentLayerType* layer = this->CreateDrawingLayer(
2086 parent, transform, gfx::PointF(), gfx::Size(100, 100), true);
2087 parent->SetShouldFlattenTransform(false);
2088 parent->Set3dSortingContextId(1);
2089 layer->SetShouldFlattenTransform(false);
2090 layer->Set3dSortingContextId(1);
2091 this->CalcDrawEtc(parent);
2093 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2094 gfx::Rect(0, 0, 1000, 1000));
2096 // This is very close to the camera, so pixels in its visible_content_rect()
2097 // will actually go outside of the layer's clip rect. Ensure that those
2098 // pixels don't occlude things outside the clip rect.
2099 this->VisitLayer(layer, &occlusion);
2100 this->EnterLayer(parent, &occlusion);
2101 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
2102 occlusion.occlusion_from_inside_target().ToString());
2103 EXPECT_EQ(gfx::Rect().ToString(),
2104 occlusion.occlusion_from_outside_target().ToString());
2108 // This test requires accumulating occlusion of 3d layers, which are skipped by
2109 // the occlusion tracker on the main thread. So this test should run on the impl
2111 IMPL_THREAD_TEST(OcclusionTrackerTestLargePixelsOccludeInsideClipRect);
2113 template <class Types>
2114 class OcclusionTrackerTestAnimationOpacity1OnMainThread
2115 : public OcclusionTrackerTest<Types> {
2117 explicit OcclusionTrackerTestAnimationOpacity1OnMainThread(bool opaque_layers)
2118 : OcclusionTrackerTest<Types>(opaque_layers) {}
2123 // | +--surface_child
2124 // | +--surface_child2
2128 typename Types::ContentLayerType* parent = this->CreateRoot(
2129 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
2130 typename Types::ContentLayerType* layer =
2131 this->CreateDrawingLayer(parent,
2132 this->identity_matrix,
2134 gfx::Size(300, 300),
2136 typename Types::ContentLayerType* surface =
2137 this->CreateDrawingSurface(parent,
2138 this->identity_matrix,
2140 gfx::Size(300, 300),
2142 typename Types::ContentLayerType* surface_child =
2143 this->CreateDrawingLayer(surface,
2144 this->identity_matrix,
2146 gfx::Size(200, 300),
2148 typename Types::ContentLayerType* surface_child2 =
2149 this->CreateDrawingLayer(surface,
2150 this->identity_matrix,
2152 gfx::Size(100, 300),
2154 typename Types::ContentLayerType* parent2 =
2155 this->CreateDrawingLayer(parent,
2156 this->identity_matrix,
2158 gfx::Size(300, 300),
2160 typename Types::ContentLayerType* topmost =
2161 this->CreateDrawingLayer(parent,
2162 this->identity_matrix,
2163 gfx::PointF(250.f, 0.f),
2167 AddOpacityTransitionToController(
2168 layer->layer_animation_controller(), 10.0, 0.f, 1.f, false);
2169 AddOpacityTransitionToController(
2170 surface->layer_animation_controller(), 10.0, 0.f, 1.f, false);
2171 this->CalcDrawEtc(parent);
2173 EXPECT_TRUE(layer->draw_opacity_is_animating());
2174 EXPECT_FALSE(surface->draw_opacity_is_animating());
2175 EXPECT_TRUE(surface->render_surface()->draw_opacity_is_animating());
2177 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2178 gfx::Rect(0, 0, 1000, 1000));
2180 this->VisitLayer(topmost, &occlusion);
2181 this->EnterLayer(parent2, &occlusion);
2182 // This occlusion will affect all surfaces.
2183 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2184 occlusion.occlusion_from_inside_target().ToString());
2185 EXPECT_EQ(gfx::Rect().ToString(),
2186 occlusion.occlusion_from_outside_target().ToString());
2187 EXPECT_EQ(gfx::Rect(0, 0, 250, 300).ToString(),
2188 occlusion.UnoccludedLayerContentRect(
2189 parent2, gfx::Rect(0, 0, 300, 300)).ToString());
2190 this->LeaveLayer(parent2, &occlusion);
2192 this->VisitLayer(surface_child2, &occlusion);
2193 this->EnterLayer(surface_child, &occlusion);
2194 EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(),
2195 occlusion.occlusion_from_inside_target().ToString());
2196 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2197 occlusion.occlusion_from_outside_target().ToString());
2198 EXPECT_RECT_EQ(gfx::Rect(100, 0, 100, 300),
2199 occlusion.UnoccludedLayerContentRect(
2200 surface_child, gfx::Rect(0, 0, 200, 300)));
2201 this->LeaveLayer(surface_child, &occlusion);
2202 this->EnterLayer(surface, &occlusion);
2203 EXPECT_EQ(gfx::Rect(0, 0, 200, 300).ToString(),
2204 occlusion.occlusion_from_inside_target().ToString());
2205 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2206 occlusion.occlusion_from_outside_target().ToString());
2207 EXPECT_RECT_EQ(gfx::Rect(200, 0, 50, 300),
2208 occlusion.UnoccludedLayerContentRect(
2209 surface, gfx::Rect(0, 0, 300, 300)));
2210 this->LeaveLayer(surface, &occlusion);
2212 this->EnterContributingSurface(surface, &occlusion);
2213 // Occlusion within the surface is lost when leaving the animating surface.
2214 EXPECT_EQ(gfx::Rect().ToString(),
2215 occlusion.occlusion_from_inside_target().ToString());
2216 EXPECT_EQ(gfx::Rect().ToString(),
2217 occlusion.occlusion_from_outside_target().ToString());
2218 EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
2219 occlusion.UnoccludedSurfaceContentRect(
2220 surface, false, gfx::Rect(0, 0, 300, 300)));
2221 this->LeaveContributingSurface(surface, &occlusion);
2223 // Occlusion from outside the animating surface still exists.
2224 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2225 occlusion.occlusion_from_inside_target().ToString());
2226 EXPECT_EQ(gfx::Rect().ToString(),
2227 occlusion.occlusion_from_outside_target().ToString());
2229 this->VisitLayer(layer, &occlusion);
2230 this->EnterLayer(parent, &occlusion);
2232 // Occlusion is not added for the animating |layer|.
2233 EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
2234 occlusion.UnoccludedLayerContentRect(
2235 parent, gfx::Rect(0, 0, 300, 300)));
2239 MAIN_THREAD_TEST(OcclusionTrackerTestAnimationOpacity1OnMainThread);
2241 template <class Types>
2242 class OcclusionTrackerTestAnimationOpacity0OnMainThread
2243 : public OcclusionTrackerTest<Types> {
2245 explicit OcclusionTrackerTestAnimationOpacity0OnMainThread(bool opaque_layers)
2246 : OcclusionTrackerTest<Types>(opaque_layers) {}
2248 typename Types::ContentLayerType* parent = this->CreateRoot(
2249 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
2250 typename Types::ContentLayerType* layer =
2251 this->CreateDrawingLayer(parent,
2252 this->identity_matrix,
2254 gfx::Size(300, 300),
2256 typename Types::ContentLayerType* surface =
2257 this->CreateDrawingSurface(parent,
2258 this->identity_matrix,
2260 gfx::Size(300, 300),
2262 typename Types::ContentLayerType* surface_child =
2263 this->CreateDrawingLayer(surface,
2264 this->identity_matrix,
2266 gfx::Size(200, 300),
2268 typename Types::ContentLayerType* surface_child2 =
2269 this->CreateDrawingLayer(surface,
2270 this->identity_matrix,
2272 gfx::Size(100, 300),
2274 typename Types::ContentLayerType* parent2 =
2275 this->CreateDrawingLayer(parent,
2276 this->identity_matrix,
2278 gfx::Size(300, 300),
2280 typename Types::ContentLayerType* topmost =
2281 this->CreateDrawingLayer(parent,
2282 this->identity_matrix,
2283 gfx::PointF(250.f, 0.f),
2287 AddOpacityTransitionToController(
2288 layer->layer_animation_controller(), 10.0, 1.f, 0.f, false);
2289 AddOpacityTransitionToController(
2290 surface->layer_animation_controller(), 10.0, 1.f, 0.f, false);
2291 this->CalcDrawEtc(parent);
2293 EXPECT_TRUE(layer->draw_opacity_is_animating());
2294 EXPECT_FALSE(surface->draw_opacity_is_animating());
2295 EXPECT_TRUE(surface->render_surface()->draw_opacity_is_animating());
2297 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2298 gfx::Rect(0, 0, 1000, 1000));
2300 this->VisitLayer(topmost, &occlusion);
2301 this->EnterLayer(parent2, &occlusion);
2302 // This occlusion will affect all surfaces.
2303 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2304 occlusion.occlusion_from_inside_target().ToString());
2305 EXPECT_EQ(gfx::Rect().ToString(),
2306 occlusion.occlusion_from_outside_target().ToString());
2307 EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
2308 occlusion.UnoccludedLayerContentRect(
2309 parent, gfx::Rect(0, 0, 300, 300)));
2310 this->LeaveLayer(parent2, &occlusion);
2312 this->VisitLayer(surface_child2, &occlusion);
2313 this->EnterLayer(surface_child, &occlusion);
2314 EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(),
2315 occlusion.occlusion_from_inside_target().ToString());
2316 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2317 occlusion.occlusion_from_outside_target().ToString());
2318 EXPECT_RECT_EQ(gfx::Rect(100, 0, 100, 300),
2319 occlusion.UnoccludedLayerContentRect(
2320 surface_child, gfx::Rect(0, 0, 200, 300)));
2321 this->LeaveLayer(surface_child, &occlusion);
2322 this->EnterLayer(surface, &occlusion);
2323 EXPECT_EQ(gfx::Rect(0, 0, 200, 300).ToString(),
2324 occlusion.occlusion_from_inside_target().ToString());
2325 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2326 occlusion.occlusion_from_outside_target().ToString());
2327 EXPECT_RECT_EQ(gfx::Rect(200, 0, 50, 300),
2328 occlusion.UnoccludedLayerContentRect(
2329 surface, gfx::Rect(0, 0, 300, 300)));
2330 this->LeaveLayer(surface, &occlusion);
2332 this->EnterContributingSurface(surface, &occlusion);
2333 // Occlusion within the surface is lost when leaving the animating surface.
2334 EXPECT_EQ(gfx::Rect().ToString(),
2335 occlusion.occlusion_from_inside_target().ToString());
2336 EXPECT_EQ(gfx::Rect().ToString(),
2337 occlusion.occlusion_from_outside_target().ToString());
2338 EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
2339 occlusion.UnoccludedSurfaceContentRect(
2340 surface, false, gfx::Rect(0, 0, 300, 300)));
2341 this->LeaveContributingSurface(surface, &occlusion);
2343 // Occlusion from outside the animating surface still exists.
2344 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2345 occlusion.occlusion_from_inside_target().ToString());
2346 EXPECT_EQ(gfx::Rect().ToString(),
2347 occlusion.occlusion_from_outside_target().ToString());
2349 this->VisitLayer(layer, &occlusion);
2350 this->EnterLayer(parent, &occlusion);
2352 // Occlusion is not added for the animating |layer|.
2353 EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
2354 occlusion.UnoccludedLayerContentRect(
2355 parent, gfx::Rect(0, 0, 300, 300)));
2359 MAIN_THREAD_TEST(OcclusionTrackerTestAnimationOpacity0OnMainThread);
2361 template <class Types>
2362 class OcclusionTrackerTestAnimationTranslateOnMainThread
2363 : public OcclusionTrackerTest<Types> {
2365 explicit OcclusionTrackerTestAnimationTranslateOnMainThread(
2367 : OcclusionTrackerTest<Types>(opaque_layers) {}
2369 typename Types::ContentLayerType* parent = this->CreateRoot(
2370 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
2371 typename Types::ContentLayerType* layer =
2372 this->CreateDrawingLayer(parent,
2373 this->identity_matrix,
2375 gfx::Size(300, 300),
2377 typename Types::ContentLayerType* surface =
2378 this->CreateDrawingSurface(parent,
2379 this->identity_matrix,
2381 gfx::Size(300, 300),
2383 typename Types::ContentLayerType* surface_child =
2384 this->CreateDrawingLayer(surface,
2385 this->identity_matrix,
2387 gfx::Size(200, 300),
2389 typename Types::ContentLayerType* surface_child2 =
2390 this->CreateDrawingLayer(surface,
2391 this->identity_matrix,
2393 gfx::Size(100, 300),
2395 typename Types::ContentLayerType* surface2 = this->CreateDrawingSurface(
2396 parent, this->identity_matrix, gfx::PointF(), gfx::Size(50, 300), true);
2398 AddAnimatedTransformToController(
2399 layer->layer_animation_controller(), 10.0, 30, 0);
2400 AddAnimatedTransformToController(
2401 surface->layer_animation_controller(), 10.0, 30, 0);
2402 AddAnimatedTransformToController(
2403 surface_child->layer_animation_controller(), 10.0, 30, 0);
2404 this->CalcDrawEtc(parent);
2406 EXPECT_TRUE(layer->draw_transform_is_animating());
2407 EXPECT_TRUE(layer->screen_space_transform_is_animating());
2409 surface->render_surface()->target_surface_transforms_are_animating());
2411 surface->render_surface()->screen_space_transforms_are_animating());
2412 // The surface owning layer doesn't animate against its own surface.
2413 EXPECT_FALSE(surface->draw_transform_is_animating());
2414 EXPECT_TRUE(surface->screen_space_transform_is_animating());
2415 EXPECT_TRUE(surface_child->draw_transform_is_animating());
2416 EXPECT_TRUE(surface_child->screen_space_transform_is_animating());
2418 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2419 gfx::Rect(0, 0, 1000, 1000));
2421 this->VisitLayer(surface2, &occlusion);
2422 this->EnterContributingSurface(surface2, &occlusion);
2424 EXPECT_EQ(gfx::Rect(0, 0, 50, 300).ToString(),
2425 occlusion.occlusion_from_inside_target().ToString());
2427 this->LeaveContributingSurface(surface2, &occlusion);
2428 this->EnterLayer(surface_child2, &occlusion);
2429 // surface_child2 is moving in screen space but not relative to its target,
2430 // so occlusion should happen in its target space only. It also means that
2431 // things occluding from outside the target (e.g. surface2) cannot occlude
2433 EXPECT_EQ(gfx::Rect().ToString(),
2434 occlusion.occlusion_from_outside_target().ToString());
2435 EXPECT_EQ(gfx::Rect().ToString(),
2436 occlusion.occlusion_from_inside_target().ToString());
2438 this->LeaveLayer(surface_child2, &occlusion);
2439 this->EnterLayer(surface_child, &occlusion);
2440 // surface_child2 added to the occlusion since it is not moving relative
2442 EXPECT_EQ(gfx::Rect().ToString(),
2443 occlusion.occlusion_from_outside_target().ToString());
2444 EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(),
2445 occlusion.occlusion_from_inside_target().ToString());
2447 this->LeaveLayer(surface_child, &occlusion);
2448 // surface_child is moving relative to its target, so it does not add
2450 EXPECT_EQ(gfx::Rect().ToString(),
2451 occlusion.occlusion_from_outside_target().ToString());
2452 EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(),
2453 occlusion.occlusion_from_inside_target().ToString());
2455 this->EnterLayer(surface, &occlusion);
2456 EXPECT_EQ(gfx::Rect().ToString(),
2457 occlusion.occlusion_from_outside_target().ToString());
2458 EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(),
2459 occlusion.occlusion_from_inside_target().ToString());
2461 this->LeaveLayer(surface, &occlusion);
2462 // The surface's owning layer is moving in screen space but not relative to
2463 // its target, so it adds to the occlusion.
2464 EXPECT_EQ(gfx::Rect().ToString(),
2465 occlusion.occlusion_from_outside_target().ToString());
2466 EXPECT_EQ(gfx::Rect(0, 0, 300, 300).ToString(),
2467 occlusion.occlusion_from_inside_target().ToString());
2469 this->EnterContributingSurface(surface, &occlusion);
2470 this->LeaveContributingSurface(surface, &occlusion);
2471 // The |surface| is moving in the screen and in its target, so all occlusion
2472 // within the surface is lost when leaving it. Only the |surface2| occlusion
2474 EXPECT_EQ(gfx::Rect().ToString(),
2475 occlusion.occlusion_from_outside_target().ToString());
2476 EXPECT_EQ(gfx::Rect(0, 0, 50, 300).ToString(),
2477 occlusion.occlusion_from_inside_target().ToString());
2479 this->VisitLayer(layer, &occlusion);
2480 // The |layer| is animating in the screen and in its target, so no occlusion
2482 EXPECT_EQ(gfx::Rect().ToString(),
2483 occlusion.occlusion_from_outside_target().ToString());
2484 EXPECT_EQ(gfx::Rect(0, 0, 50, 300).ToString(),
2485 occlusion.occlusion_from_inside_target().ToString());
2489 MAIN_THREAD_TEST(OcclusionTrackerTestAnimationTranslateOnMainThread);
2491 template <class Types>
2492 class OcclusionTrackerTestSurfaceOcclusionTranslatesToParent
2493 : public OcclusionTrackerTest<Types> {
2495 explicit OcclusionTrackerTestSurfaceOcclusionTranslatesToParent(
2497 : OcclusionTrackerTest<Types>(opaque_layers) {}
2499 gfx::Transform surface_transform;
2500 surface_transform.Translate(300.0, 300.0);
2501 surface_transform.Scale(2.0, 2.0);
2502 surface_transform.Translate(-150.0, -150.0);
2504 typename Types::ContentLayerType* parent = this->CreateRoot(
2505 this->identity_matrix, gfx::PointF(), gfx::Size(500, 500));
2506 typename Types::ContentLayerType* surface = this->CreateDrawingSurface(
2507 parent, surface_transform, gfx::PointF(), gfx::Size(300, 300), false);
2508 typename Types::ContentLayerType* surface2 =
2509 this->CreateDrawingSurface(parent,
2510 this->identity_matrix,
2511 gfx::PointF(50.f, 50.f),
2512 gfx::Size(300, 300),
2514 surface->SetOpaqueContentsRect(gfx::Rect(0, 0, 200, 200));
2515 surface2->SetOpaqueContentsRect(gfx::Rect(0, 0, 200, 200));
2516 this->CalcDrawEtc(parent);
2518 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2519 gfx::Rect(0, 0, 1000, 1000));
2521 this->VisitLayer(surface2, &occlusion);
2522 this->VisitContributingSurface(surface2, &occlusion);
2524 EXPECT_EQ(gfx::Rect().ToString(),
2525 occlusion.occlusion_from_outside_target().ToString());
2526 EXPECT_EQ(gfx::Rect(50, 50, 200, 200).ToString(),
2527 occlusion.occlusion_from_inside_target().ToString());
2529 // Clear any stored occlusion.
2530 occlusion.set_occlusion_from_outside_target(Region());
2531 occlusion.set_occlusion_from_inside_target(Region());
2533 this->VisitLayer(surface, &occlusion);
2534 this->VisitContributingSurface(surface, &occlusion);
2536 EXPECT_EQ(gfx::Rect().ToString(),
2537 occlusion.occlusion_from_outside_target().ToString());
2538 EXPECT_EQ(gfx::Rect(0, 0, 400, 400).ToString(),
2539 occlusion.occlusion_from_inside_target().ToString());
2543 MAIN_AND_IMPL_THREAD_TEST(
2544 OcclusionTrackerTestSurfaceOcclusionTranslatesToParent);
2546 template <class Types>
2547 class OcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping
2548 : public OcclusionTrackerTest<Types> {
2550 explicit OcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping(
2552 : OcclusionTrackerTest<Types>(opaque_layers) {}
2554 typename Types::ContentLayerType* parent = this->CreateRoot(
2555 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
2556 parent->SetMasksToBounds(true);
2557 typename Types::ContentLayerType* surface =
2558 this->CreateDrawingSurface(parent,
2559 this->identity_matrix,
2561 gfx::Size(500, 300),
2563 surface->SetOpaqueContentsRect(gfx::Rect(0, 0, 400, 200));
2564 this->CalcDrawEtc(parent);
2566 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2567 gfx::Rect(0, 0, 1000, 1000));
2569 this->VisitLayer(surface, &occlusion);
2570 this->VisitContributingSurface(surface, &occlusion);
2572 EXPECT_EQ(gfx::Rect().ToString(),
2573 occlusion.occlusion_from_outside_target().ToString());
2574 EXPECT_EQ(gfx::Rect(0, 0, 300, 200).ToString(),
2575 occlusion.occlusion_from_inside_target().ToString());
2579 MAIN_AND_IMPL_THREAD_TEST(
2580 OcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping);
2582 template <class Types>
2583 class OcclusionTrackerTestReplicaOccluded : public OcclusionTrackerTest<Types> {
2585 explicit OcclusionTrackerTestReplicaOccluded(bool opaque_layers)
2586 : OcclusionTrackerTest<Types>(opaque_layers) {}
2588 typename Types::ContentLayerType* parent = this->CreateRoot(
2589 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
2590 typename Types::LayerType* surface =
2591 this->CreateDrawingSurface(parent,
2592 this->identity_matrix,
2594 gfx::Size(100, 100),
2596 this->CreateReplicaLayer(surface,
2597 this->identity_matrix,
2598 gfx::PointF(0.f, 100.f),
2599 gfx::Size(100, 100));
2600 typename Types::LayerType* topmost =
2601 this->CreateDrawingLayer(parent,
2602 this->identity_matrix,
2603 gfx::PointF(0.f, 100.f),
2604 gfx::Size(100, 100),
2606 this->CalcDrawEtc(parent);
2608 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2609 gfx::Rect(0, 0, 1000, 1000));
2611 // |topmost| occludes the replica, but not the surface itself.
2612 this->VisitLayer(topmost, &occlusion);
2614 EXPECT_EQ(gfx::Rect().ToString(),
2615 occlusion.occlusion_from_outside_target().ToString());
2616 EXPECT_EQ(gfx::Rect(0, 100, 100, 100).ToString(),
2617 occlusion.occlusion_from_inside_target().ToString());
2619 this->VisitLayer(surface, &occlusion);
2621 // Render target with replica ignores occlusion from outside.
2622 EXPECT_EQ(gfx::Rect().ToString(),
2623 occlusion.occlusion_from_outside_target().ToString());
2624 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
2625 occlusion.occlusion_from_inside_target().ToString());
2627 this->EnterContributingSurface(surface, &occlusion);
2629 // Surface is not occluded so it shouldn't think it is.
2630 EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 100),
2631 occlusion.UnoccludedSurfaceContentRect(
2632 surface, false, gfx::Rect(0, 0, 100, 100)));
2636 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaOccluded);
2638 template <class Types>
2639 class OcclusionTrackerTestSurfaceWithReplicaUnoccluded
2640 : public OcclusionTrackerTest<Types> {
2642 explicit OcclusionTrackerTestSurfaceWithReplicaUnoccluded(bool opaque_layers)
2643 : OcclusionTrackerTest<Types>(opaque_layers) {}
2645 typename Types::ContentLayerType* parent = this->CreateRoot(
2646 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
2647 typename Types::LayerType* surface =
2648 this->CreateDrawingSurface(parent,
2649 this->identity_matrix,
2651 gfx::Size(100, 100),
2653 this->CreateReplicaLayer(surface,
2654 this->identity_matrix,
2655 gfx::PointF(0.f, 100.f),
2656 gfx::Size(100, 100));
2657 typename Types::LayerType* topmost =
2658 this->CreateDrawingLayer(parent,
2659 this->identity_matrix,
2661 gfx::Size(100, 110),
2663 this->CalcDrawEtc(parent);
2665 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2666 gfx::Rect(0, 0, 1000, 1000));
2668 // |topmost| occludes the surface, but not the entire surface's replica.
2669 this->VisitLayer(topmost, &occlusion);
2671 EXPECT_EQ(gfx::Rect().ToString(),
2672 occlusion.occlusion_from_outside_target().ToString());
2673 EXPECT_EQ(gfx::Rect(0, 0, 100, 110).ToString(),
2674 occlusion.occlusion_from_inside_target().ToString());
2676 this->VisitLayer(surface, &occlusion);
2678 // Render target with replica ignores occlusion from outside.
2679 EXPECT_EQ(gfx::Rect().ToString(),
2680 occlusion.occlusion_from_outside_target().ToString());
2681 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
2682 occlusion.occlusion_from_inside_target().ToString());
2684 this->EnterContributingSurface(surface, &occlusion);
2686 // Surface is occluded, but only the top 10px of the replica.
2687 EXPECT_RECT_EQ(gfx::Rect(0, 0, 0, 0),
2688 occlusion.UnoccludedSurfaceContentRect(
2689 surface, false, gfx::Rect(0, 0, 100, 100)));
2690 EXPECT_RECT_EQ(gfx::Rect(0, 10, 100, 90),
2691 occlusion.UnoccludedSurfaceContentRect(
2692 surface, true, gfx::Rect(0, 0, 100, 100)));
2696 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceWithReplicaUnoccluded);
2698 template <class Types>
2699 class OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently
2700 : public OcclusionTrackerTest<Types> {
2702 explicit OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently(
2704 : OcclusionTrackerTest<Types>(opaque_layers) {}
2706 typename Types::ContentLayerType* parent = this->CreateRoot(
2707 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
2708 typename Types::LayerType* surface =
2709 this->CreateDrawingSurface(parent,
2710 this->identity_matrix,
2712 gfx::Size(100, 100),
2714 this->CreateReplicaLayer(surface,
2715 this->identity_matrix,
2716 gfx::PointF(0.f, 100.f),
2717 gfx::Size(100, 100));
2718 typename Types::LayerType* over_surface = this->CreateDrawingLayer(
2719 parent, this->identity_matrix, gfx::PointF(), gfx::Size(40, 100), true);
2720 typename Types::LayerType* over_replica =
2721 this->CreateDrawingLayer(parent,
2722 this->identity_matrix,
2723 gfx::PointF(0.f, 100.f),
2726 this->CalcDrawEtc(parent);
2728 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2729 gfx::Rect(0, 0, 1000, 1000));
2731 // These occlude the surface and replica differently, so we can test each
2733 this->VisitLayer(over_replica, &occlusion);
2734 this->VisitLayer(over_surface, &occlusion);
2736 EXPECT_EQ(gfx::Rect().ToString(),
2737 occlusion.occlusion_from_outside_target().ToString());
2738 EXPECT_EQ(UnionRegions(gfx::Rect(0, 0, 40, 100), gfx::Rect(0, 100, 50, 100))
2740 occlusion.occlusion_from_inside_target().ToString());
2742 this->VisitLayer(surface, &occlusion);
2744 // Render target with replica ignores occlusion from outside.
2745 EXPECT_EQ(gfx::Rect().ToString(),
2746 occlusion.occlusion_from_outside_target().ToString());
2747 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
2748 occlusion.occlusion_from_inside_target().ToString());
2750 this->EnterContributingSurface(surface, &occlusion);
2752 // Surface and replica are occluded different amounts.
2753 EXPECT_RECT_EQ(gfx::Rect(40, 0, 60, 100),
2754 occlusion.UnoccludedSurfaceContentRect(
2755 surface, false, gfx::Rect(0, 0, 100, 100)));
2756 EXPECT_RECT_EQ(gfx::Rect(50, 0, 50, 100),
2757 occlusion.UnoccludedSurfaceContentRect(
2758 surface, true, gfx::Rect(0, 0, 100, 100)));
2762 ALL_OCCLUSIONTRACKER_TEST(
2763 OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently);
2765 template <class Types>
2766 class OcclusionTrackerTestSurfaceChildOfSurface
2767 : public OcclusionTrackerTest<Types> {
2769 explicit OcclusionTrackerTestSurfaceChildOfSurface(bool opaque_layers)
2770 : OcclusionTrackerTest<Types>(opaque_layers) {}
2772 // This test verifies that the surface cliprect does not end up empty and
2773 // clip away the entire unoccluded rect.
2775 typename Types::ContentLayerType* parent = this->CreateRoot(
2776 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
2777 typename Types::LayerType* surface =
2778 this->CreateDrawingSurface(parent,
2779 this->identity_matrix,
2781 gfx::Size(100, 100),
2783 typename Types::LayerType* surface_child =
2784 this->CreateDrawingSurface(surface,
2785 this->identity_matrix,
2786 gfx::PointF(0.f, 10.f),
2789 typename Types::LayerType* topmost = this->CreateDrawingLayer(
2790 parent, this->identity_matrix, gfx::PointF(), gfx::Size(100, 50), true);
2791 this->CalcDrawEtc(parent);
2793 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2794 gfx::Rect(-100, -100, 1000, 1000));
2796 // |topmost| occludes everything partially so we know occlusion is happening
2798 this->VisitLayer(topmost, &occlusion);
2800 EXPECT_EQ(gfx::Rect().ToString(),
2801 occlusion.occlusion_from_outside_target().ToString());
2802 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
2803 occlusion.occlusion_from_inside_target().ToString());
2805 this->VisitLayer(surface_child, &occlusion);
2807 // surface_child increases the occlusion in the screen by a narrow sliver.
2808 EXPECT_EQ(gfx::Rect(0, -10, 100, 50).ToString(),
2809 occlusion.occlusion_from_outside_target().ToString());
2810 // In its own surface, surface_child is at 0,0 as is its occlusion.
2811 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
2812 occlusion.occlusion_from_inside_target().ToString());
2814 // The root layer always has a clip rect. So the parent of |surface| has a
2815 // clip rect. However, the owning layer for |surface| does not mask to
2816 // bounds, so it doesn't have a clip rect of its own. Thus the parent of
2817 // |surface_child| exercises different code paths as its parent does not
2818 // have a clip rect.
2820 this->EnterContributingSurface(surface_child, &occlusion);
2821 // The surface_child's parent does not have a clip rect as it owns a render
2822 // surface. Make sure the unoccluded rect does not get clipped away
2824 EXPECT_RECT_EQ(gfx::Rect(0, 40, 100, 10),
2825 occlusion.UnoccludedSurfaceContentRect(
2826 surface_child, false, gfx::Rect(0, 0, 100, 50)));
2827 this->LeaveContributingSurface(surface_child, &occlusion);
2829 // When the surface_child's occlusion is transformed up to its parent, make
2830 // sure it is not clipped away inappropriately also.
2831 this->EnterLayer(surface, &occlusion);
2832 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
2833 occlusion.occlusion_from_outside_target().ToString());
2834 EXPECT_EQ(gfx::Rect(0, 10, 100, 50).ToString(),
2835 occlusion.occlusion_from_inside_target().ToString());
2836 this->LeaveLayer(surface, &occlusion);
2838 this->EnterContributingSurface(surface, &occlusion);
2839 // The surface's parent does have a clip rect as it is the root layer.
2840 EXPECT_RECT_EQ(gfx::Rect(0, 50, 100, 50),
2841 occlusion.UnoccludedSurfaceContentRect(
2842 surface, false, gfx::Rect(0, 0, 100, 100)));
2846 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceChildOfSurface);
2848 template <class Types>
2849 class OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter
2850 : public OcclusionTrackerTest<Types> {
2852 explicit OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter(
2854 : OcclusionTrackerTest<Types>(opaque_layers) {}
2856 gfx::Transform scale_by_half;
2857 scale_by_half.Scale(0.5, 0.5);
2859 // Make a 50x50 filtered surface that is completely surrounded by opaque
2860 // layers which are above it in the z-order. The surface is scaled to test
2861 // that the pixel moving is done in the target space, where the background
2862 // filter is applied.
2863 typename Types::ContentLayerType* parent = this->CreateRoot(
2864 this->identity_matrix, gfx::PointF(), gfx::Size(200, 150));
2865 typename Types::LayerType* filtered_surface =
2866 this->CreateDrawingLayer(parent,
2868 gfx::PointF(50.f, 50.f),
2869 gfx::Size(100, 100),
2871 typename Types::LayerType* occluding_layer1 = this->CreateDrawingLayer(
2872 parent, this->identity_matrix, gfx::PointF(), gfx::Size(200, 50), true);
2873 typename Types::LayerType* occluding_layer2 =
2874 this->CreateDrawingLayer(parent,
2875 this->identity_matrix,
2876 gfx::PointF(0.f, 100.f),
2879 typename Types::LayerType* occluding_layer3 =
2880 this->CreateDrawingLayer(parent,
2881 this->identity_matrix,
2882 gfx::PointF(0.f, 50.f),
2885 typename Types::LayerType* occluding_layer4 =
2886 this->CreateDrawingLayer(parent,
2887 this->identity_matrix,
2888 gfx::PointF(100.f, 50.f),
2892 // Filters make the layer own a surface.
2893 FilterOperations filters;
2894 filters.Append(FilterOperation::CreateBlurFilter(10.f));
2895 filtered_surface->SetBackgroundFilters(filters);
2897 // Save the distance of influence for the blur effect.
2898 int outset_top, outset_right, outset_bottom, outset_left;
2900 &outset_top, &outset_right, &outset_bottom, &outset_left);
2902 this->CalcDrawEtc(parent);
2904 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2905 gfx::Rect(0, 0, 1000, 1000));
2907 // These layers occlude pixels directly beside the filtered_surface. Because
2908 // filtered surface blends pixels in a radius, it will need to see some of
2909 // the pixels (up to radius far) underneath the occluding layers.
2910 this->VisitLayer(occluding_layer4, &occlusion);
2911 this->VisitLayer(occluding_layer3, &occlusion);
2912 this->VisitLayer(occluding_layer2, &occlusion);
2913 this->VisitLayer(occluding_layer1, &occlusion);
2915 Region expected_occlusion;
2916 expected_occlusion.Union(gfx::Rect(0, 0, 200, 50));
2917 expected_occlusion.Union(gfx::Rect(0, 50, 50, 50));
2918 expected_occlusion.Union(gfx::Rect(100, 50, 100, 50));
2919 expected_occlusion.Union(gfx::Rect(0, 100, 200, 50));
2921 EXPECT_EQ(expected_occlusion.ToString(),
2922 occlusion.occlusion_from_inside_target().ToString());
2923 EXPECT_EQ(gfx::Rect().ToString(),
2924 occlusion.occlusion_from_outside_target().ToString());
2926 this->VisitLayer(filtered_surface, &occlusion);
2928 // The filtered layer does not occlude.
2929 Region expected_occlusion_outside_surface;
2930 expected_occlusion_outside_surface.Union(gfx::Rect(-50, -50, 200, 50));
2931 expected_occlusion_outside_surface.Union(gfx::Rect(-50, 0, 50, 50));
2932 expected_occlusion_outside_surface.Union(gfx::Rect(50, 0, 100, 50));
2933 expected_occlusion_outside_surface.Union(gfx::Rect(-50, 50, 200, 50));
2935 EXPECT_EQ(expected_occlusion_outside_surface.ToString(),
2936 occlusion.occlusion_from_outside_target().ToString());
2937 EXPECT_EQ(gfx::Rect().ToString(),
2938 occlusion.occlusion_from_inside_target().ToString());
2940 // The surface has a background blur, so it needs pixels that are currently
2941 // considered occluded in order to be drawn. So the pixels it needs should
2942 // be removed some the occluded area so that when we get to the parent they
2944 this->VisitContributingSurface(filtered_surface, &occlusion);
2946 this->EnterLayer(parent, &occlusion);
2948 Region expected_blurred_occlusion;
2949 expected_blurred_occlusion.Union(gfx::Rect(0, 0, 200, 50 - outset_top));
2950 expected_blurred_occlusion.Union(gfx::Rect(
2951 0, 50 - outset_top, 50 - outset_left, 50 + outset_top + outset_bottom));
2952 expected_blurred_occlusion.Union(
2953 gfx::Rect(100 + outset_right,
2956 50 + outset_top + outset_bottom));
2957 expected_blurred_occlusion.Union(
2958 gfx::Rect(0, 100 + outset_bottom, 200, 50 - outset_bottom));
2960 EXPECT_EQ(expected_blurred_occlusion.ToString(),
2961 occlusion.occlusion_from_inside_target().ToString());
2962 EXPECT_EQ(gfx::Rect().ToString(),
2963 occlusion.occlusion_from_outside_target().ToString());
2965 gfx::Rect outset_rect;
2966 gfx::Rect test_rect;
2968 // Nothing in the blur outsets for the filtered_surface is occluded.
2969 outset_rect = gfx::Rect(50 - outset_left,
2971 50 + outset_left + outset_right,
2972 50 + outset_top + outset_bottom);
2973 test_rect = outset_rect;
2975 outset_rect.ToString(),
2976 occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
2978 // Stuff outside the blur outsets is still occluded though.
2979 test_rect = outset_rect;
2980 test_rect.Inset(0, 0, -1, 0);
2982 outset_rect.ToString(),
2983 occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
2984 test_rect = outset_rect;
2985 test_rect.Inset(0, 0, 0, -1);
2987 outset_rect.ToString(),
2988 occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
2989 test_rect = outset_rect;
2990 test_rect.Inset(-1, 0, 0, 0);
2992 outset_rect.ToString(),
2993 occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
2994 test_rect = outset_rect;
2995 test_rect.Inset(0, -1, 0, 0);
2997 outset_rect.ToString(),
2998 occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
3002 ALL_OCCLUSIONTRACKER_TEST(
3003 OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter);
3005 template <class Types>
3006 class OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice
3007 : public OcclusionTrackerTest<Types> {
3009 explicit OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice(
3011 : OcclusionTrackerTest<Types>(opaque_layers) {}
3013 gfx::Transform scale_by_half;
3014 scale_by_half.Scale(0.5, 0.5);
3016 // Makes two surfaces that completely cover |parent|. The occlusion both
3017 // above and below the filters will be reduced by each of them.
3018 typename Types::ContentLayerType* root = this->CreateRoot(
3019 this->identity_matrix, gfx::PointF(), gfx::Size(75, 75));
3020 typename Types::LayerType* parent = this->CreateSurface(
3021 root, scale_by_half, gfx::PointF(), gfx::Size(150, 150));
3022 parent->SetMasksToBounds(true);
3023 typename Types::LayerType* filtered_surface1 = this->CreateDrawingLayer(
3024 parent, scale_by_half, gfx::PointF(), gfx::Size(300, 300), false);
3025 typename Types::LayerType* filtered_surface2 = this->CreateDrawingLayer(
3026 parent, scale_by_half, gfx::PointF(), gfx::Size(300, 300), false);
3027 typename Types::LayerType* occluding_layer_above =
3028 this->CreateDrawingLayer(parent,
3029 this->identity_matrix,
3030 gfx::PointF(100.f, 100.f),
3034 // Filters make the layers own surfaces.
3035 FilterOperations filters;
3036 filters.Append(FilterOperation::CreateBlurFilter(1.f));
3037 filtered_surface1->SetBackgroundFilters(filters);
3038 filtered_surface2->SetBackgroundFilters(filters);
3040 // Save the distance of influence for the blur effect.
3041 int outset_top, outset_right, outset_bottom, outset_left;
3043 &outset_top, &outset_right, &outset_bottom, &outset_left);
3045 this->CalcDrawEtc(root);
3047 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3048 gfx::Rect(0, 0, 1000, 1000));
3050 this->VisitLayer(occluding_layer_above, &occlusion);
3051 EXPECT_EQ(gfx::Rect().ToString(),
3052 occlusion.occlusion_from_outside_target().ToString());
3053 EXPECT_EQ(gfx::Rect(100 / 2, 100 / 2, 50 / 2, 50 / 2).ToString(),
3054 occlusion.occlusion_from_inside_target().ToString());
3056 this->VisitLayer(filtered_surface2, &occlusion);
3057 this->VisitContributingSurface(filtered_surface2, &occlusion);
3058 this->VisitLayer(filtered_surface1, &occlusion);
3059 this->VisitContributingSurface(filtered_surface1, &occlusion);
3061 // Test expectations in the target.
3062 gfx::Rect expected_occlusion =
3063 gfx::Rect(100 / 2 + outset_right * 2,
3064 100 / 2 + outset_bottom * 2,
3065 50 / 2 - (outset_left + outset_right) * 2,
3066 50 / 2 - (outset_top + outset_bottom) * 2);
3067 EXPECT_EQ(expected_occlusion.ToString(),
3068 occlusion.occlusion_from_inside_target().ToString());
3070 // Test expectations in the screen are the same as in the target, as the
3071 // render surface is 1:1 with the screen.
3072 EXPECT_EQ(expected_occlusion.ToString(),
3073 occlusion.occlusion_from_outside_target().ToString());
3077 ALL_OCCLUSIONTRACKER_TEST(
3078 OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice);
3080 template <class Types>
3081 class OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter
3082 : public OcclusionTrackerTest<Types> {
3084 explicit OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter(
3086 : OcclusionTrackerTest<Types>(opaque_layers) {}
3088 gfx::Transform scale_by_half;
3089 scale_by_half.Scale(0.5, 0.5);
3091 // Make a surface and its replica, each 50x50, with a smaller 30x30 layer
3092 // centered below each. The surface is scaled to test that the pixel moving
3093 // is done in the target space, where the background filter is applied, but
3094 // the surface appears at 50, 50 and the replica at 200, 50.
3095 typename Types::ContentLayerType* parent = this->CreateRoot(
3096 this->identity_matrix, gfx::PointF(), gfx::Size(300, 150));
3097 typename Types::LayerType* behind_surface_layer =
3098 this->CreateDrawingLayer(parent,
3099 this->identity_matrix,
3100 gfx::PointF(60.f, 60.f),
3103 typename Types::LayerType* behind_replica_layer =
3104 this->CreateDrawingLayer(parent,
3105 this->identity_matrix,
3106 gfx::PointF(210.f, 60.f),
3109 typename Types::LayerType* filtered_surface =
3110 this->CreateDrawingLayer(parent,
3112 gfx::PointF(50.f, 50.f),
3113 gfx::Size(100, 100),
3115 this->CreateReplicaLayer(filtered_surface,
3116 this->identity_matrix,
3117 gfx::PointF(300.f, 0.f),
3120 // Filters make the layer own a surface.
3121 FilterOperations filters;
3122 filters.Append(FilterOperation::CreateBlurFilter(3.f));
3123 filtered_surface->SetBackgroundFilters(filters);
3125 this->CalcDrawEtc(parent);
3127 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3128 gfx::Rect(0, 0, 1000, 1000));
3130 // The surface has a background blur, so it blurs non-opaque pixels below
3132 this->VisitLayer(filtered_surface, &occlusion);
3133 this->VisitContributingSurface(filtered_surface, &occlusion);
3135 this->VisitLayer(behind_replica_layer, &occlusion);
3136 this->VisitLayer(behind_surface_layer, &occlusion);
3138 // The layers behind the surface are not blurred, and their occlusion does
3139 // not change, until we leave the surface. So it should not be modified by
3141 gfx::Rect occlusion_behind_surface = gfx::Rect(60, 60, 30, 30);
3142 gfx::Rect occlusion_behind_replica = gfx::Rect(210, 60, 30, 30);
3144 Region expected_opaque_bounds =
3145 UnionRegions(occlusion_behind_surface, occlusion_behind_replica);
3146 EXPECT_EQ(expected_opaque_bounds.ToString(),
3147 occlusion.occlusion_from_inside_target().ToString());
3149 EXPECT_EQ(gfx::Rect().ToString(),
3150 occlusion.occlusion_from_outside_target().ToString());
3154 ALL_OCCLUSIONTRACKER_TEST(
3155 OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter);
3157 template <class Types>
3158 class OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded
3159 : public OcclusionTrackerTest<Types> {
3161 explicit OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded(
3163 : OcclusionTrackerTest<Types>(opaque_layers) {}
3165 gfx::Transform scale_by_half;
3166 scale_by_half.Scale(0.5, 0.5);
3168 // Make a 50x50 filtered surface that is completely occluded by an opaque
3169 // layer which is above it in the z-order. The surface is
3170 // scaled to test that the pixel moving is done in the target space, where
3171 // the background filter is applied, but the surface appears at 50, 50.
3172 typename Types::ContentLayerType* parent = this->CreateRoot(
3173 this->identity_matrix, gfx::PointF(), gfx::Size(200, 150));
3174 typename Types::LayerType* filtered_surface =
3175 this->CreateDrawingLayer(parent,
3177 gfx::PointF(50.f, 50.f),
3178 gfx::Size(100, 100),
3180 typename Types::LayerType* occluding_layer =
3181 this->CreateDrawingLayer(parent,
3182 this->identity_matrix,
3183 gfx::PointF(50.f, 50.f),
3187 // Filters make the layer own a surface.
3188 FilterOperations filters;
3189 filters.Append(FilterOperation::CreateBlurFilter(3.f));
3190 filtered_surface->SetBackgroundFilters(filters);
3192 this->CalcDrawEtc(parent);
3194 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3195 gfx::Rect(0, 0, 1000, 1000));
3197 this->VisitLayer(occluding_layer, &occlusion);
3199 this->VisitLayer(filtered_surface, &occlusion);
3201 // The layers above the filtered surface occlude from outside.
3202 gfx::Rect occlusion_above_surface = gfx::Rect(0, 0, 50, 50);
3204 EXPECT_EQ(gfx::Rect().ToString(),
3205 occlusion.occlusion_from_inside_target().ToString());
3206 EXPECT_EQ(occlusion_above_surface.ToString(),
3207 occlusion.occlusion_from_outside_target().ToString());
3210 // The surface has a background blur, so it blurs non-opaque pixels below
3212 this->VisitContributingSurface(filtered_surface, &occlusion);
3214 // The filter is completely occluded, so it should not blur anything and
3215 // reduce any occlusion.
3216 gfx::Rect occlusion_above_surface = gfx::Rect(50, 50, 50, 50);
3218 EXPECT_EQ(occlusion_above_surface.ToString(),
3219 occlusion.occlusion_from_inside_target().ToString());
3220 EXPECT_EQ(gfx::Rect().ToString(),
3221 occlusion.occlusion_from_outside_target().ToString());
3226 ALL_OCCLUSIONTRACKER_TEST(
3227 OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded);
3229 template <class Types>
3230 class OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded
3231 : public OcclusionTrackerTest<Types> {
3234 OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded(
3236 : OcclusionTrackerTest<Types>(opaque_layers) {}
3238 gfx::Transform scale_by_half;
3239 scale_by_half.Scale(0.5, 0.5);
3241 // Make a surface and its replica, each 50x50, that are partially occluded
3242 // by opaque layers which are above them in the z-order. The surface is
3243 // scaled to test that the pixel moving is done in the target space, where
3244 // the background filter is applied, but the surface appears at 50, 50 and
3245 // the replica at 200, 50.
3246 typename Types::ContentLayerType* parent = this->CreateRoot(
3247 this->identity_matrix, gfx::PointF(), gfx::Size(300, 150));
3248 typename Types::LayerType* filtered_surface =
3249 this->CreateDrawingLayer(parent,
3251 gfx::PointF(50.f, 50.f),
3252 gfx::Size(100, 100),
3254 this->CreateReplicaLayer(filtered_surface,
3255 this->identity_matrix,
3256 gfx::PointF(300.f, 0.f),
3258 typename Types::LayerType* above_surface_layer =
3259 this->CreateDrawingLayer(parent,
3260 this->identity_matrix,
3261 gfx::PointF(70.f, 50.f),
3264 typename Types::LayerType* above_replica_layer =
3265 this->CreateDrawingLayer(parent,
3266 this->identity_matrix,
3267 gfx::PointF(200.f, 50.f),
3270 typename Types::LayerType* beside_surface_layer =
3271 this->CreateDrawingLayer(parent,
3272 this->identity_matrix,
3273 gfx::PointF(90.f, 40.f),
3276 typename Types::LayerType* beside_replica_layer =
3277 this->CreateDrawingLayer(parent,
3278 this->identity_matrix,
3279 gfx::PointF(200.f, 40.f),
3283 // Filters make the layer own a surface.
3284 FilterOperations filters;
3285 filters.Append(FilterOperation::CreateBlurFilter(3.f));
3286 filtered_surface->SetBackgroundFilters(filters);
3288 // Save the distance of influence for the blur effect.
3289 int outset_top, outset_right, outset_bottom, outset_left;
3291 &outset_top, &outset_right, &outset_bottom, &outset_left);
3293 this->CalcDrawEtc(parent);
3295 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3296 gfx::Rect(0, 0, 1000, 1000));
3298 this->VisitLayer(beside_replica_layer, &occlusion);
3299 this->VisitLayer(beside_surface_layer, &occlusion);
3300 this->VisitLayer(above_replica_layer, &occlusion);
3301 this->VisitLayer(above_surface_layer, &occlusion);
3303 // The surface has a background blur, so it blurs non-opaque pixels below
3305 this->VisitLayer(filtered_surface, &occlusion);
3306 this->VisitContributingSurface(filtered_surface, &occlusion);
3308 // The filter in the surface and replica are partially unoccluded. Only the
3309 // unoccluded parts should reduce occlusion. This means it will push back
3310 // the occlusion that touches the unoccluded part (occlusion_above___), but
3311 // it will not touch occlusion_beside____ since that is not beside the
3312 // unoccluded part of the surface, even though it is beside the occluded
3313 // part of the surface.
3314 gfx::Rect occlusion_above_surface =
3315 gfx::Rect(70 + outset_right, 50, 30 - outset_right, 50);
3316 gfx::Rect occlusion_above_replica =
3317 gfx::Rect(200, 50, 30 - outset_left, 50);
3318 gfx::Rect occlusion_beside_surface = gfx::Rect(90, 40, 10, 10);
3319 gfx::Rect occlusion_beside_replica = gfx::Rect(200, 40, 10, 10);
3321 Region expected_occlusion;
3322 expected_occlusion.Union(occlusion_above_surface);
3323 expected_occlusion.Union(occlusion_above_replica);
3324 expected_occlusion.Union(occlusion_beside_surface);
3325 expected_occlusion.Union(occlusion_beside_replica);
3327 ASSERT_EQ(expected_occlusion.ToString(),
3328 occlusion.occlusion_from_inside_target().ToString());
3329 EXPECT_EQ(gfx::Rect().ToString(),
3330 occlusion.occlusion_from_outside_target().ToString());
3332 Region::Iterator expected_rects(expected_occlusion);
3333 Region::Iterator target_surface_rects(
3334 occlusion.occlusion_from_inside_target());
3335 for (; expected_rects.has_rect();
3336 expected_rects.next(), target_surface_rects.next()) {
3337 ASSERT_TRUE(target_surface_rects.has_rect());
3338 EXPECT_EQ(expected_rects.rect(), target_surface_rects.rect());
3343 ALL_OCCLUSIONTRACKER_TEST(
3344 OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded);
3346 template <class Types>
3347 class OcclusionTrackerTestMinimumTrackingSize
3348 : public OcclusionTrackerTest<Types> {
3350 explicit OcclusionTrackerTestMinimumTrackingSize(bool opaque_layers)
3351 : OcclusionTrackerTest<Types>(opaque_layers) {}
3353 gfx::Size tracking_size(100, 100);
3354 gfx::Size below_tracking_size(99, 99);
3356 typename Types::ContentLayerType* parent = this->CreateRoot(
3357 this->identity_matrix, gfx::PointF(), gfx::Size(400, 400));
3358 typename Types::LayerType* large = this->CreateDrawingLayer(
3359 parent, this->identity_matrix, gfx::PointF(), tracking_size, true);
3360 typename Types::LayerType* small =
3361 this->CreateDrawingLayer(parent,
3362 this->identity_matrix,
3364 below_tracking_size,
3366 this->CalcDrawEtc(parent);
3368 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3369 gfx::Rect(0, 0, 1000, 1000));
3370 occlusion.set_minimum_tracking_size(tracking_size);
3372 // The small layer is not tracked because it is too small.
3373 this->VisitLayer(small, &occlusion);
3375 EXPECT_EQ(gfx::Rect().ToString(),
3376 occlusion.occlusion_from_outside_target().ToString());
3377 EXPECT_EQ(gfx::Rect().ToString(),
3378 occlusion.occlusion_from_inside_target().ToString());
3380 // The large layer is tracked as it is large enough.
3381 this->VisitLayer(large, &occlusion);
3383 EXPECT_EQ(gfx::Rect().ToString(),
3384 occlusion.occlusion_from_outside_target().ToString());
3385 EXPECT_EQ(gfx::Rect(tracking_size).ToString(),
3386 occlusion.occlusion_from_inside_target().ToString());
3390 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestMinimumTrackingSize);
3392 template <class Types>
3393 class OcclusionTrackerTestScaledLayerIsClipped
3394 : public OcclusionTrackerTest<Types> {
3396 explicit OcclusionTrackerTestScaledLayerIsClipped(bool opaque_layers)
3397 : OcclusionTrackerTest<Types>(opaque_layers) {}
3399 gfx::Transform scale_transform;
3400 scale_transform.Scale(512.0, 512.0);
3402 typename Types::ContentLayerType* parent = this->CreateRoot(
3403 this->identity_matrix, gfx::PointF(), gfx::Size(400, 400));
3404 typename Types::LayerType* clip = this->CreateLayer(parent,
3405 this->identity_matrix,
3406 gfx::PointF(10.f, 10.f),
3408 clip->SetMasksToBounds(true);
3409 typename Types::LayerType* scale = this->CreateLayer(
3410 clip, scale_transform, gfx::PointF(), gfx::Size(1, 1));
3411 typename Types::LayerType* scaled = this->CreateDrawingLayer(
3412 scale, this->identity_matrix, gfx::PointF(), gfx::Size(500, 500), true);
3413 this->CalcDrawEtc(parent);
3415 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3416 gfx::Rect(0, 0, 1000, 1000));
3418 this->VisitLayer(scaled, &occlusion);
3420 EXPECT_EQ(gfx::Rect().ToString(),
3421 occlusion.occlusion_from_outside_target().ToString());
3422 EXPECT_EQ(gfx::Rect(10, 10, 50, 50).ToString(),
3423 occlusion.occlusion_from_inside_target().ToString());
3427 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestScaledLayerIsClipped)
3429 template <class Types>
3430 class OcclusionTrackerTestScaledLayerInSurfaceIsClipped
3431 : public OcclusionTrackerTest<Types> {
3433 explicit OcclusionTrackerTestScaledLayerInSurfaceIsClipped(bool opaque_layers)
3434 : OcclusionTrackerTest<Types>(opaque_layers) {}
3436 gfx::Transform scale_transform;
3437 scale_transform.Scale(512.0, 512.0);
3439 typename Types::ContentLayerType* parent = this->CreateRoot(
3440 this->identity_matrix, gfx::PointF(), gfx::Size(400, 400));
3441 typename Types::LayerType* clip = this->CreateLayer(parent,
3442 this->identity_matrix,
3443 gfx::PointF(10.f, 10.f),
3445 clip->SetMasksToBounds(true);
3446 typename Types::LayerType* surface = this->CreateDrawingSurface(
3447 clip, this->identity_matrix, gfx::PointF(), gfx::Size(400, 30), false);
3448 typename Types::LayerType* scale = this->CreateLayer(
3449 surface, scale_transform, gfx::PointF(), gfx::Size(1, 1));
3450 typename Types::LayerType* scaled = this->CreateDrawingLayer(
3451 scale, this->identity_matrix, gfx::PointF(), gfx::Size(500, 500), true);
3452 this->CalcDrawEtc(parent);
3454 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3455 gfx::Rect(0, 0, 1000, 1000));
3457 this->VisitLayer(scaled, &occlusion);
3458 this->VisitLayer(surface, &occlusion);
3459 this->VisitContributingSurface(surface, &occlusion);
3461 EXPECT_EQ(gfx::Rect().ToString(),
3462 occlusion.occlusion_from_outside_target().ToString());
3463 EXPECT_EQ(gfx::Rect(10, 10, 50, 50).ToString(),
3464 occlusion.occlusion_from_inside_target().ToString());
3468 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestScaledLayerInSurfaceIsClipped)
3470 template <class Types>
3471 class OcclusionTrackerTestCopyRequestDoesOcclude
3472 : public OcclusionTrackerTest<Types> {
3474 explicit OcclusionTrackerTestCopyRequestDoesOcclude(bool opaque_layers)
3475 : OcclusionTrackerTest<Types>(opaque_layers) {}
3477 typename Types::ContentLayerType* root = this->CreateRoot(
3478 this->identity_matrix, gfx::Point(), gfx::Size(400, 400));
3479 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
3480 root, this->identity_matrix, gfx::Point(), gfx::Size(400, 400), true);
3481 typename Types::LayerType* copy = this->CreateLayer(parent,
3482 this->identity_matrix,
3484 gfx::Size(200, 400));
3485 this->AddCopyRequest(copy);
3486 typename Types::LayerType* copy_child = this->CreateDrawingLayer(
3488 this->identity_matrix,
3490 gfx::Size(200, 400),
3492 this->CalcDrawEtc(root);
3494 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3495 gfx::Rect(0, 0, 1000, 1000));
3497 this->VisitLayer(copy_child, &occlusion);
3498 EXPECT_EQ(gfx::Rect().ToString(),
3499 occlusion.occlusion_from_outside_target().ToString());
3500 EXPECT_EQ(gfx::Rect(200, 400).ToString(),
3501 occlusion.occlusion_from_inside_target().ToString());
3503 // CopyRequests cause the layer to own a surface.
3504 this->VisitContributingSurface(copy, &occlusion);
3506 // The occlusion from the copy should be kept.
3507 EXPECT_EQ(gfx::Rect().ToString(),
3508 occlusion.occlusion_from_outside_target().ToString());
3509 EXPECT_EQ(gfx::Rect(100, 0, 200, 400).ToString(),
3510 occlusion.occlusion_from_inside_target().ToString());
3514 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestCopyRequestDoesOcclude)
3516 template <class Types>
3517 class OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude
3518 : public OcclusionTrackerTest<Types> {
3520 explicit OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude(
3522 : OcclusionTrackerTest<Types>(opaque_layers) {}
3524 typename Types::ContentLayerType* root = this->CreateRoot(
3525 this->identity_matrix, gfx::Point(), gfx::Size(400, 400));
3526 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
3527 root, this->identity_matrix, gfx::Point(), gfx::Size(400, 400), true);
3528 typename Types::LayerType* hide = this->CreateLayer(
3529 parent, this->identity_matrix, gfx::Point(), gfx::Size());
3530 typename Types::LayerType* copy = this->CreateLayer(
3531 hide, this->identity_matrix, gfx::Point(100, 0), gfx::Size(200, 400));
3532 this->AddCopyRequest(copy);
3533 typename Types::LayerType* copy_child = this->CreateDrawingLayer(
3534 copy, this->identity_matrix, gfx::PointF(), gfx::Size(200, 400), true);
3536 // The |copy| layer is hidden but since it is being copied, it will be
3538 hide->SetHideLayerAndSubtree(true);
3540 this->CalcDrawEtc(root);
3542 TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3543 gfx::Rect(0, 0, 1000, 1000));
3545 this->VisitLayer(copy_child, &occlusion);
3546 EXPECT_EQ(gfx::Rect().ToString(),
3547 occlusion.occlusion_from_outside_target().ToString());
3548 EXPECT_EQ(gfx::Rect(200, 400).ToString(),
3549 occlusion.occlusion_from_inside_target().ToString());
3551 // CopyRequests cause the layer to own a surface.
3552 this->VisitContributingSurface(copy, &occlusion);
3554 // The occlusion from the copy should be dropped since it is hidden.
3555 EXPECT_EQ(gfx::Rect().ToString(),
3556 occlusion.occlusion_from_outside_target().ToString());
3557 EXPECT_EQ(gfx::Rect().ToString(),
3558 occlusion.occlusion_from_inside_target().ToString());
3562 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude)