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/debug/overdraw_metrics.h"
10 #include "cc/layers/layer.h"
11 #include "cc/layers/layer_impl.h"
12 #include "cc/output/copy_output_request.h"
13 #include "cc/output/copy_output_result.h"
14 #include "cc/output/filter_operation.h"
15 #include "cc/output/filter_operations.h"
16 #include "cc/test/animation_test_common.h"
17 #include "cc/test/fake_impl_proxy.h"
18 #include "cc/test/fake_layer_tree_host.h"
19 #include "cc/test/fake_layer_tree_host_impl.h"
20 #include "cc/test/geometry_test_utils.h"
21 #include "cc/test/occlusion_tracker_test_common.h"
22 #include "cc/trees/layer_tree_host_common.h"
23 #include "cc/trees/single_thread_proxy.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "ui/gfx/transform.h"
31 class TestContentLayer : public Layer {
33 TestContentLayer() : Layer(), override_opaque_contents_rect_(false) {
37 virtual Region VisibleContentOpaqueRegion() const OVERRIDE {
38 if (override_opaque_contents_rect_)
39 return gfx::IntersectRects(opaque_contents_rect_, visible_content_rect());
40 return Layer::VisibleContentOpaqueRegion();
42 void SetOpaqueContentsRect(const gfx::Rect& opaque_contents_rect) {
43 override_opaque_contents_rect_ = true;
44 opaque_contents_rect_ = opaque_contents_rect;
48 virtual ~TestContentLayer() {}
50 bool override_opaque_contents_rect_;
51 gfx::Rect opaque_contents_rect_;
54 class TestContentLayerImpl : public LayerImpl {
56 TestContentLayerImpl(LayerTreeImpl* tree_impl, int id)
57 : LayerImpl(tree_impl, id), override_opaque_contents_rect_(false) {
58 SetDrawsContent(true);
61 virtual Region VisibleContentOpaqueRegion() const OVERRIDE {
62 if (override_opaque_contents_rect_)
63 return gfx::IntersectRects(opaque_contents_rect_, visible_content_rect());
64 return LayerImpl::VisibleContentOpaqueRegion();
66 void SetOpaqueContentsRect(const gfx::Rect& opaque_contents_rect) {
67 override_opaque_contents_rect_ = true;
68 opaque_contents_rect_ = opaque_contents_rect;
72 bool override_opaque_contents_rect_;
73 gfx::Rect opaque_contents_rect_;
76 static inline bool LayerImplDrawTransformIsUnknown(const Layer* layer) {
77 return layer->draw_transform_is_animating();
79 static inline bool LayerImplDrawTransformIsUnknown(const LayerImpl* layer) {
83 template <typename LayerType, typename RenderSurfaceType>
84 class TestOcclusionTrackerWithClip
85 : public TestOcclusionTrackerBase<LayerType, RenderSurfaceType> {
87 TestOcclusionTrackerWithClip(const gfx::Rect& viewport_rect,
88 bool record_metrics_for_frame)
89 : TestOcclusionTrackerBase<LayerType, RenderSurfaceType>(
91 record_metrics_for_frame) {}
92 explicit TestOcclusionTrackerWithClip(const gfx::Rect& viewport_rect)
93 : TestOcclusionTrackerBase<LayerType, RenderSurfaceType>(viewport_rect,
96 bool OccludedLayer(const LayerType* layer,
97 const gfx::Rect& content_rect) const {
98 DCHECK(layer->visible_content_rect().Contains(content_rect));
99 return this->Occluded(layer->render_target(),
101 layer->draw_transform(),
102 LayerImplDrawTransformIsUnknown(layer));
105 // Gives an unoccluded sub-rect of |content_rect| in the content space of the
106 // layer. Simple wrapper around UnoccludedContentRect.
107 gfx::Rect UnoccludedLayerContentRect(const LayerType* layer,
108 const gfx::Rect& content_rect) const {
109 DCHECK(layer->visible_content_rect().Contains(content_rect));
110 return this->UnoccludedContentRect(
111 layer->render_target(),
113 layer->draw_transform(),
114 LayerImplDrawTransformIsUnknown(layer));
118 struct OcclusionTrackerTestMainThreadTypes {
119 typedef Layer LayerType;
120 typedef FakeLayerTreeHost HostType;
121 typedef RenderSurface RenderSurfaceType;
122 typedef TestContentLayer ContentLayerType;
123 typedef scoped_refptr<Layer> LayerPtrType;
124 typedef scoped_refptr<ContentLayerType> ContentLayerPtrType;
125 typedef LayerIterator<Layer> TestLayerIterator;
126 typedef OcclusionTracker OcclusionTrackerType;
128 static LayerPtrType CreateLayer(HostType* host) { return Layer::Create(); }
129 static ContentLayerPtrType CreateContentLayer(HostType* host) {
130 return make_scoped_refptr(new ContentLayerType());
133 static LayerPtrType PassLayerPtr(ContentLayerPtrType* layer) {
134 LayerPtrType ref(*layer);
139 static LayerPtrType PassLayerPtr(LayerPtrType* layer) {
140 LayerPtrType ref(*layer);
145 static void DestroyLayer(LayerPtrType* layer) { *layer = NULL; }
148 struct OcclusionTrackerTestImplThreadTypes {
149 typedef LayerImpl LayerType;
150 typedef LayerTreeImpl HostType;
151 typedef RenderSurfaceImpl RenderSurfaceType;
152 typedef TestContentLayerImpl ContentLayerType;
153 typedef scoped_ptr<LayerImpl> LayerPtrType;
154 typedef scoped_ptr<ContentLayerType> ContentLayerPtrType;
155 typedef LayerIterator<LayerImpl> TestLayerIterator;
156 typedef OcclusionTrackerImpl OcclusionTrackerType;
158 static LayerPtrType CreateLayer(HostType* host) {
159 return LayerImpl::Create(host, next_layer_impl_id++);
161 static ContentLayerPtrType CreateContentLayer(HostType* host) {
162 return make_scoped_ptr(new ContentLayerType(host, next_layer_impl_id++));
164 static int next_layer_impl_id;
166 static LayerPtrType PassLayerPtr(LayerPtrType* layer) {
167 return layer->Pass();
170 static LayerPtrType PassLayerPtr(ContentLayerPtrType* layer) {
171 return layer->PassAs<LayerType>();
174 static void DestroyLayer(LayerPtrType* layer) { layer->reset(); }
177 int OcclusionTrackerTestImplThreadTypes::next_layer_impl_id = 1;
179 template <typename Types> class OcclusionTrackerTest : public testing::Test {
181 explicit OcclusionTrackerTest(bool opaque_layers)
182 : opaque_layers_(opaque_layers), host_(FakeLayerTreeHost::Create()) {}
184 virtual void RunMyTest() = 0;
186 virtual void TearDown() {
187 Types::DestroyLayer(&root_);
188 render_surface_layer_list_.reset();
189 render_surface_layer_list_impl_.clear();
190 replica_layers_.clear();
191 mask_layers_.clear();
194 typename Types::HostType* GetHost();
196 typename Types::ContentLayerType* CreateRoot(const gfx::Transform& transform,
197 const gfx::PointF& position,
198 const gfx::Size& bounds) {
199 typename Types::ContentLayerPtrType layer(
200 Types::CreateContentLayer(GetHost()));
201 typename Types::ContentLayerType* layer_ptr = layer.get();
202 SetProperties(layer_ptr, transform, position, bounds);
204 DCHECK(!root_.get());
205 root_ = Types::PassLayerPtr(&layer);
207 SetRootLayerOnMainThread(layer_ptr);
212 typename Types::LayerType* CreateLayer(typename Types::LayerType* parent,
213 const gfx::Transform& transform,
214 const gfx::PointF& position,
215 const gfx::Size& bounds) {
216 typename Types::LayerPtrType layer(Types::CreateLayer(GetHost()));
217 typename Types::LayerType* layer_ptr = layer.get();
218 SetProperties(layer_ptr, transform, position, bounds);
219 parent->AddChild(Types::PassLayerPtr(&layer));
223 typename Types::LayerType* CreateSurface(typename Types::LayerType* parent,
224 const gfx::Transform& transform,
225 const gfx::PointF& position,
226 const gfx::Size& bounds) {
227 typename Types::LayerType* layer =
228 CreateLayer(parent, transform, position, bounds);
229 layer->SetForceRenderSurface(true);
233 typename Types::ContentLayerType* CreateDrawingLayer(
234 typename Types::LayerType* parent,
235 const gfx::Transform& transform,
236 const gfx::PointF& position,
237 const gfx::Size& bounds,
239 typename Types::ContentLayerPtrType layer(
240 Types::CreateContentLayer(GetHost()));
241 typename Types::ContentLayerType* layer_ptr = layer.get();
242 SetProperties(layer_ptr, transform, position, bounds);
244 if (opaque_layers_) {
245 layer_ptr->SetContentsOpaque(opaque);
247 layer_ptr->SetContentsOpaque(false);
249 layer_ptr->SetOpaqueContentsRect(gfx::Rect(bounds));
251 layer_ptr->SetOpaqueContentsRect(gfx::Rect());
254 parent->AddChild(Types::PassLayerPtr(&layer));
258 typename Types::LayerType* CreateReplicaLayer(
259 typename Types::LayerType* owning_layer,
260 const gfx::Transform& transform,
261 const gfx::PointF& position,
262 const gfx::Size& bounds) {
263 typename Types::ContentLayerPtrType layer(
264 Types::CreateContentLayer(GetHost()));
265 typename Types::ContentLayerType* layer_ptr = layer.get();
266 SetProperties(layer_ptr, transform, position, bounds);
267 SetReplica(owning_layer, Types::PassLayerPtr(&layer));
271 typename Types::LayerType* CreateMaskLayer(
272 typename Types::LayerType* owning_layer,
273 const gfx::Size& bounds) {
274 typename Types::ContentLayerPtrType layer(
275 Types::CreateContentLayer(GetHost()));
276 typename Types::ContentLayerType* layer_ptr = layer.get();
277 SetProperties(layer_ptr, identity_matrix, gfx::PointF(), bounds);
278 SetMask(owning_layer, Types::PassLayerPtr(&layer));
282 typename Types::ContentLayerType* CreateDrawingSurface(
283 typename Types::LayerType* parent,
284 const gfx::Transform& transform,
285 const gfx::PointF& position,
286 const gfx::Size& bounds,
288 typename Types::ContentLayerType* layer =
289 CreateDrawingLayer(parent, transform, position, bounds, opaque);
290 layer->SetForceRenderSurface(true);
295 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {}
297 void AddCopyRequest(Layer* layer) {
298 layer->RequestCopyOfOutput(
299 CopyOutputRequest::CreateBitmapRequest(base::Bind(
300 &OcclusionTrackerTest<Types>::CopyOutputCallback,
301 base::Unretained(this))));
304 void AddCopyRequest(LayerImpl* layer) {
305 ScopedPtrVector<CopyOutputRequest> requests;
307 CopyOutputRequest::CreateBitmapRequest(base::Bind(
308 &OcclusionTrackerTest<Types>::CopyOutputCallback,
309 base::Unretained(this))));
310 layer->PassCopyRequests(&requests);
313 void CalcDrawEtc(TestContentLayerImpl* root) {
314 DCHECK(root == root_.get());
315 DCHECK(!root->render_surface());
317 LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
318 root, root->bounds(), &render_surface_layer_list_impl_);
319 inputs.can_adjust_raster_scales = true;
320 LayerTreeHostCommon::CalculateDrawProperties(&inputs);
322 layer_iterator_ = layer_iterator_begin_ =
323 Types::TestLayerIterator::Begin(&render_surface_layer_list_impl_);
326 void CalcDrawEtc(TestContentLayer* root) {
327 DCHECK(root == root_.get());
328 DCHECK(!root->render_surface());
330 render_surface_layer_list_.reset(new RenderSurfaceLayerList);
331 LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
332 root, root->bounds(), render_surface_layer_list_.get());
333 inputs.can_adjust_raster_scales = true;
334 LayerTreeHostCommon::CalculateDrawProperties(&inputs);
336 layer_iterator_ = layer_iterator_begin_ =
337 Types::TestLayerIterator::Begin(render_surface_layer_list_.get());
340 void SetDrawsContent(LayerImpl* layer_impl, bool draws_content) {
341 layer_impl->SetDrawsContent(draws_content);
344 void SetDrawsContent(Layer* layer, bool draws_content) {
345 layer->SetIsDrawable(draws_content);
348 void EnterLayer(typename Types::LayerType* layer,
349 typename Types::OcclusionTrackerType* occlusion) {
350 ASSERT_EQ(layer, *layer_iterator_);
351 ASSERT_TRUE(layer_iterator_.represents_itself());
352 occlusion->EnterLayer(layer_iterator_);
355 void LeaveLayer(typename Types::LayerType* layer,
356 typename Types::OcclusionTrackerType* occlusion) {
357 ASSERT_EQ(layer, *layer_iterator_);
358 ASSERT_TRUE(layer_iterator_.represents_itself());
359 occlusion->LeaveLayer(layer_iterator_);
363 void VisitLayer(typename Types::LayerType* layer,
364 typename Types::OcclusionTrackerType* occlusion) {
365 EnterLayer(layer, occlusion);
366 LeaveLayer(layer, occlusion);
369 void EnterContributingSurface(
370 typename Types::LayerType* layer,
371 typename Types::OcclusionTrackerType* occlusion) {
372 ASSERT_EQ(layer, *layer_iterator_);
373 ASSERT_TRUE(layer_iterator_.represents_target_render_surface());
374 occlusion->EnterLayer(layer_iterator_);
375 occlusion->LeaveLayer(layer_iterator_);
377 ASSERT_TRUE(layer_iterator_.represents_contributing_render_surface());
378 occlusion->EnterLayer(layer_iterator_);
381 void LeaveContributingSurface(
382 typename Types::LayerType* layer,
383 typename Types::OcclusionTrackerType* occlusion) {
384 ASSERT_EQ(layer, *layer_iterator_);
385 ASSERT_TRUE(layer_iterator_.represents_contributing_render_surface());
386 occlusion->LeaveLayer(layer_iterator_);
390 void VisitContributingSurface(
391 typename Types::LayerType* layer,
392 typename Types::OcclusionTrackerType* occlusion) {
393 EnterContributingSurface(layer, occlusion);
394 LeaveContributingSurface(layer, occlusion);
397 void ResetLayerIterator() { layer_iterator_ = layer_iterator_begin_; }
399 const gfx::Transform identity_matrix;
402 void SetRootLayerOnMainThread(Layer* root) {
403 host_->SetRootLayer(scoped_refptr<Layer>(root));
406 void SetRootLayerOnMainThread(LayerImpl* root) {}
408 void SetBaseProperties(typename Types::LayerType* layer,
409 const gfx::Transform& transform,
410 const gfx::PointF& position,
411 const gfx::Size& bounds) {
412 layer->SetTransform(transform);
413 layer->SetAnchorPoint(gfx::PointF());
414 layer->SetPosition(position);
415 layer->SetBounds(bounds);
418 void SetProperties(Layer* layer,
419 const gfx::Transform& transform,
420 const gfx::PointF& position,
421 const gfx::Size& bounds) {
422 SetBaseProperties(layer, transform, position, bounds);
425 void SetProperties(LayerImpl* layer,
426 const gfx::Transform& transform,
427 const gfx::PointF& position,
428 const gfx::Size& bounds) {
429 SetBaseProperties(layer, transform, position, bounds);
431 layer->SetContentBounds(layer->bounds());
434 void SetReplica(Layer* owning_layer, scoped_refptr<Layer> layer) {
435 owning_layer->SetReplicaLayer(layer.get());
436 replica_layers_.push_back(layer);
439 void SetReplica(LayerImpl* owning_layer, scoped_ptr<LayerImpl> layer) {
440 owning_layer->SetReplicaLayer(layer.Pass());
443 void SetMask(Layer* owning_layer, scoped_refptr<Layer> layer) {
444 owning_layer->SetMaskLayer(layer.get());
445 mask_layers_.push_back(layer);
448 void SetMask(LayerImpl* owning_layer, scoped_ptr<LayerImpl> layer) {
449 owning_layer->SetMaskLayer(layer.Pass());
453 scoped_ptr<FakeLayerTreeHost> host_;
454 // These hold ownership of the layers for the duration of the test.
455 typename Types::LayerPtrType root_;
456 scoped_ptr<RenderSurfaceLayerList> render_surface_layer_list_;
457 LayerImplList render_surface_layer_list_impl_;
458 typename Types::TestLayerIterator layer_iterator_begin_;
459 typename Types::TestLayerIterator layer_iterator_;
460 typename Types::LayerType* last_layer_visited_;
461 LayerList replica_layers_;
462 LayerList mask_layers_;
467 OcclusionTrackerTest<OcclusionTrackerTestMainThreadTypes>::GetHost() {
473 OcclusionTrackerTest<OcclusionTrackerTestImplThreadTypes>::GetHost() {
474 return host_->host_impl()->active_tree();
477 #define RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \
478 class ClassName##MainThreadOpaqueLayers \
479 : public ClassName<OcclusionTrackerTestMainThreadTypes> { \
480 public: /* NOLINT(whitespace/indent) */ \
481 ClassName##MainThreadOpaqueLayers() \
482 : ClassName<OcclusionTrackerTestMainThreadTypes>(true) {} \
484 TEST_F(ClassName##MainThreadOpaqueLayers, RunTest) { RunMyTest(); }
485 #define RUN_TEST_MAIN_THREAD_OPAQUE_PAINTS(ClassName) \
486 class ClassName##MainThreadOpaquePaints \
487 : public ClassName<OcclusionTrackerTestMainThreadTypes> { \
488 public: /* NOLINT(whitespace/indent) */ \
489 ClassName##MainThreadOpaquePaints() \
490 : ClassName<OcclusionTrackerTestMainThreadTypes>(false) {} \
492 TEST_F(ClassName##MainThreadOpaquePaints, RunTest) { RunMyTest(); }
494 #define RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) \
495 class ClassName##ImplThreadOpaqueLayers \
496 : public ClassName<OcclusionTrackerTestImplThreadTypes> { \
497 public: /* NOLINT(whitespace/indent) */ \
498 ClassName##ImplThreadOpaqueLayers() \
499 : ClassName<OcclusionTrackerTestImplThreadTypes>(true) {} \
501 TEST_F(ClassName##ImplThreadOpaqueLayers, RunTest) { RunMyTest(); }
502 #define RUN_TEST_IMPL_THREAD_OPAQUE_PAINTS(ClassName) \
503 class ClassName##ImplThreadOpaquePaints \
504 : public ClassName<OcclusionTrackerTestImplThreadTypes> { \
505 public: /* NOLINT(whitespace/indent) */ \
506 ClassName##ImplThreadOpaquePaints() \
507 : ClassName<OcclusionTrackerTestImplThreadTypes>(false) {} \
509 TEST_F(ClassName##ImplThreadOpaquePaints, RunTest) { RunMyTest(); }
511 #define ALL_OCCLUSIONTRACKER_TEST(ClassName) \
512 RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \
513 RUN_TEST_MAIN_THREAD_OPAQUE_PAINTS(ClassName) \
514 RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) \
515 RUN_TEST_IMPL_THREAD_OPAQUE_PAINTS(ClassName)
517 #define MAIN_THREAD_TEST(ClassName) \
518 RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName)
520 #define IMPL_THREAD_TEST(ClassName) \
521 RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName)
523 #define MAIN_AND_IMPL_THREAD_TEST(ClassName) \
524 RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \
525 RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName)
527 template <class Types>
528 class OcclusionTrackerTestIdentityTransforms
529 : public OcclusionTrackerTest<Types> {
531 explicit OcclusionTrackerTestIdentityTransforms(bool opaque_layers)
532 : OcclusionTrackerTest<Types>(opaque_layers) {}
535 typename Types::ContentLayerType* root = this->CreateRoot(
536 this->identity_matrix, gfx::PointF(), gfx::Size(200, 200));
537 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
538 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
539 typename Types::ContentLayerType* layer =
540 this->CreateDrawingLayer(parent,
541 this->identity_matrix,
542 gfx::PointF(30.f, 30.f),
545 parent->SetMasksToBounds(true);
546 this->CalcDrawEtc(root);
548 TestOcclusionTrackerWithClip<typename Types::LayerType,
549 typename Types::RenderSurfaceType> occlusion(
550 gfx::Rect(0, 0, 1000, 1000), false);
552 this->VisitLayer(layer, &occlusion);
553 this->EnterLayer(parent, &occlusion);
555 EXPECT_EQ(gfx::Rect().ToString(),
556 occlusion.occlusion_from_outside_target().ToString());
557 EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(),
558 occlusion.occlusion_from_inside_target().ToString());
560 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 70, 70)));
561 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 30, 70, 70)));
562 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 29, 70, 70)));
563 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 30, 69, 70)));
564 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 31, 70, 69)));
566 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
567 parent, gfx::Rect(30, 30, 70, 70)).IsEmpty());
568 EXPECT_RECT_EQ(gfx::Rect(29, 30, 1, 70),
569 occlusion.UnoccludedLayerContentRect(
570 parent, gfx::Rect(29, 30, 70, 70)));
571 EXPECT_RECT_EQ(gfx::Rect(29, 29, 70, 70),
572 occlusion.UnoccludedLayerContentRect(
573 parent, gfx::Rect(29, 29, 70, 70)));
574 EXPECT_RECT_EQ(gfx::Rect(30, 29, 70, 1),
575 occlusion.UnoccludedLayerContentRect(
576 parent, gfx::Rect(30, 29, 70, 70)));
577 EXPECT_RECT_EQ(gfx::Rect(31, 29, 69, 1),
578 occlusion.UnoccludedLayerContentRect(
579 parent, gfx::Rect(31, 29, 69, 70)));
580 EXPECT_RECT_EQ(gfx::Rect(),
581 occlusion.UnoccludedLayerContentRect(
582 parent, gfx::Rect(31, 30, 69, 70)));
583 EXPECT_RECT_EQ(gfx::Rect(),
584 occlusion.UnoccludedLayerContentRect(
585 parent, gfx::Rect(31, 31, 69, 69)));
586 EXPECT_RECT_EQ(gfx::Rect(),
587 occlusion.UnoccludedLayerContentRect(
588 parent, gfx::Rect(30, 31, 70, 69)));
589 EXPECT_RECT_EQ(gfx::Rect(29, 31, 1, 69),
590 occlusion.UnoccludedLayerContentRect(
591 parent, gfx::Rect(29, 31, 70, 69)));
595 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestIdentityTransforms);
597 template <class Types>
598 class OcclusionTrackerTestQuadsMismatchLayer
599 : public OcclusionTrackerTest<Types> {
601 explicit OcclusionTrackerTestQuadsMismatchLayer(bool opaque_layers)
602 : OcclusionTrackerTest<Types>(opaque_layers) {}
604 gfx::Transform layer_transform;
605 layer_transform.Translate(10.0, 10.0);
607 typename Types::ContentLayerType* parent = this->CreateRoot(
608 this->identity_matrix, gfx::Point(0, 0), gfx::Size(100, 100));
609 typename Types::ContentLayerType* layer1 = this->CreateDrawingLayer(
610 parent, layer_transform, gfx::PointF(), gfx::Size(90, 90), true);
611 typename Types::ContentLayerType* layer2 = this->CreateDrawingLayer(
612 layer1, layer_transform, gfx::PointF(), gfx::Size(50, 50), true);
613 this->CalcDrawEtc(parent);
615 TestOcclusionTrackerWithClip<typename Types::LayerType,
616 typename Types::RenderSurfaceType> occlusion(
617 gfx::Rect(0, 0, 1000, 1000));
619 this->VisitLayer(layer2, &occlusion);
620 this->EnterLayer(layer1, &occlusion);
622 EXPECT_EQ(gfx::Rect().ToString(),
623 occlusion.occlusion_from_outside_target().ToString());
624 EXPECT_EQ(gfx::Rect(20, 20, 50, 50).ToString(),
625 occlusion.occlusion_from_inside_target().ToString());
627 // This checks cases where the quads don't match their "containing"
628 // layers, e.g. in terms of transforms or clip rect. This is typical for
629 // DelegatedRendererLayer.
631 gfx::Transform quad_transform;
632 quad_transform.Translate(30.0, 30.0);
634 EXPECT_TRUE(occlusion.UnoccludedContentRect(parent,
635 gfx::Rect(0, 0, 10, 10),
638 EXPECT_RECT_EQ(gfx::Rect(0, 0, 10, 10),
639 occlusion.UnoccludedContentRect(parent,
640 gfx::Rect(0, 0, 10, 10),
643 EXPECT_RECT_EQ(gfx::Rect(40, 40, 10, 10),
644 occlusion.UnoccludedContentRect(parent,
645 gfx::Rect(40, 40, 10, 10),
648 EXPECT_RECT_EQ(gfx::Rect(40, 30, 5, 10),
649 occlusion.UnoccludedContentRect(parent,
650 gfx::Rect(35, 30, 10, 10),
656 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestQuadsMismatchLayer);
658 template <class Types>
659 class OcclusionTrackerTestRotatedChild : public OcclusionTrackerTest<Types> {
661 explicit OcclusionTrackerTestRotatedChild(bool opaque_layers)
662 : OcclusionTrackerTest<Types>(opaque_layers) {}
664 gfx::Transform layer_transform;
665 layer_transform.Translate(250.0, 250.0);
666 layer_transform.Rotate(90.0);
667 layer_transform.Translate(-250.0, -250.0);
669 typename Types::ContentLayerType* root = this->CreateRoot(
670 this->identity_matrix, gfx::Point(0, 0), gfx::Size(200, 200));
671 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
672 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
673 typename Types::ContentLayerType* layer =
674 this->CreateDrawingLayer(parent,
676 gfx::PointF(30.f, 30.f),
679 parent->SetMasksToBounds(true);
680 this->CalcDrawEtc(root);
682 TestOcclusionTrackerWithClip<typename Types::LayerType,
683 typename Types::RenderSurfaceType> occlusion(
684 gfx::Rect(0, 0, 1000, 1000));
686 this->VisitLayer(layer, &occlusion);
687 this->EnterLayer(parent, &occlusion);
689 EXPECT_EQ(gfx::Rect().ToString(),
690 occlusion.occlusion_from_outside_target().ToString());
691 EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(),
692 occlusion.occlusion_from_inside_target().ToString());
694 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 70, 70)));
695 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 30, 70, 70)));
696 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 29, 70, 70)));
697 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 30, 69, 70)));
698 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 31, 70, 69)));
700 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
701 parent, gfx::Rect(30, 30, 70, 70)).IsEmpty());
702 EXPECT_RECT_EQ(gfx::Rect(29, 30, 1, 70),
703 occlusion.UnoccludedLayerContentRect(
704 parent, gfx::Rect(29, 30, 69, 70)));
705 EXPECT_RECT_EQ(gfx::Rect(29, 29, 70, 70),
706 occlusion.UnoccludedLayerContentRect(
707 parent, gfx::Rect(29, 29, 70, 70)));
708 EXPECT_RECT_EQ(gfx::Rect(30, 29, 70, 1),
709 occlusion.UnoccludedLayerContentRect(
710 parent, gfx::Rect(30, 29, 70, 70)));
711 EXPECT_RECT_EQ(gfx::Rect(31, 29, 69, 1),
712 occlusion.UnoccludedLayerContentRect(
713 parent, gfx::Rect(31, 29, 69, 70)));
714 EXPECT_RECT_EQ(gfx::Rect(),
715 occlusion.UnoccludedLayerContentRect(
716 parent, gfx::Rect(31, 30, 69, 70)));
717 EXPECT_RECT_EQ(gfx::Rect(),
718 occlusion.UnoccludedLayerContentRect(
719 parent, gfx::Rect(31, 31, 69, 69)));
720 EXPECT_RECT_EQ(gfx::Rect(),
721 occlusion.UnoccludedLayerContentRect(
722 parent, gfx::Rect(30, 31, 70, 69)));
723 EXPECT_RECT_EQ(gfx::Rect(29, 31, 1, 69),
724 occlusion.UnoccludedLayerContentRect(
725 parent, gfx::Rect(29, 31, 70, 69)));
729 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestRotatedChild);
731 template <class Types>
732 class OcclusionTrackerTestTranslatedChild : public OcclusionTrackerTest<Types> {
734 explicit OcclusionTrackerTestTranslatedChild(bool opaque_layers)
735 : OcclusionTrackerTest<Types>(opaque_layers) {}
737 gfx::Transform layer_transform;
738 layer_transform.Translate(20.0, 20.0);
740 typename Types::ContentLayerType* root = this->CreateRoot(
741 this->identity_matrix, gfx::PointF(), gfx::Size(200, 200));
742 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
743 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
744 typename Types::ContentLayerType* layer =
745 this->CreateDrawingLayer(parent,
747 gfx::PointF(30.f, 30.f),
750 parent->SetMasksToBounds(true);
751 this->CalcDrawEtc(root);
753 TestOcclusionTrackerWithClip<typename Types::LayerType,
754 typename Types::RenderSurfaceType> occlusion(
755 gfx::Rect(0, 0, 1000, 1000));
757 this->VisitLayer(layer, &occlusion);
758 this->EnterLayer(parent, &occlusion);
760 EXPECT_EQ(gfx::Rect().ToString(),
761 occlusion.occlusion_from_outside_target().ToString());
762 EXPECT_EQ(gfx::Rect(50, 50, 50, 50).ToString(),
763 occlusion.occlusion_from_inside_target().ToString());
765 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(50, 50, 50, 50)));
766 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(49, 50, 50, 50)));
767 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(50, 49, 50, 50)));
768 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(51, 50, 49, 50)));
769 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(50, 51, 50, 49)));
771 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
772 parent, gfx::Rect(50, 50, 50, 50)).IsEmpty());
773 EXPECT_RECT_EQ(gfx::Rect(49, 50, 1, 50),
774 occlusion.UnoccludedLayerContentRect(
775 parent, gfx::Rect(49, 50, 50, 50)));
776 EXPECT_RECT_EQ(gfx::Rect(49, 49, 50, 50),
777 occlusion.UnoccludedLayerContentRect(
778 parent, gfx::Rect(49, 49, 50, 50)));
779 EXPECT_RECT_EQ(gfx::Rect(50, 49, 50, 1),
780 occlusion.UnoccludedLayerContentRect(
781 parent, gfx::Rect(50, 49, 50, 50)));
782 EXPECT_RECT_EQ(gfx::Rect(51, 49, 49, 1),
783 occlusion.UnoccludedLayerContentRect(
784 parent, gfx::Rect(51, 49, 49, 50)));
785 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
786 parent, gfx::Rect(51, 50, 49, 50)).IsEmpty());
787 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
788 parent, gfx::Rect(51, 51, 49, 49)).IsEmpty());
789 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
790 parent, gfx::Rect(50, 51, 50, 49)).IsEmpty());
791 EXPECT_RECT_EQ(gfx::Rect(49, 51, 1, 49),
792 occlusion.UnoccludedLayerContentRect(
793 parent, gfx::Rect(49, 51, 50, 49)));
797 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestTranslatedChild);
799 template <class Types>
800 class OcclusionTrackerTestChildInRotatedChild
801 : public OcclusionTrackerTest<Types> {
803 explicit OcclusionTrackerTestChildInRotatedChild(bool opaque_layers)
804 : OcclusionTrackerTest<Types>(opaque_layers) {}
806 gfx::Transform child_transform;
807 child_transform.Translate(250.0, 250.0);
808 child_transform.Rotate(90.0);
809 child_transform.Translate(-250.0, -250.0);
811 typename Types::ContentLayerType* parent = this->CreateRoot(
812 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
813 parent->SetMasksToBounds(true);
814 typename Types::LayerType* child = this->CreateSurface(
815 parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500));
816 child->SetMasksToBounds(true);
817 typename Types::ContentLayerType* layer =
818 this->CreateDrawingLayer(child,
819 this->identity_matrix,
820 gfx::PointF(10.f, 10.f),
823 this->CalcDrawEtc(parent);
825 TestOcclusionTrackerWithClip<typename Types::LayerType,
826 typename Types::RenderSurfaceType> occlusion(
827 gfx::Rect(0, 0, 1000, 1000));
829 this->VisitLayer(layer, &occlusion);
830 this->EnterContributingSurface(child, &occlusion);
832 EXPECT_EQ(gfx::Rect().ToString(),
833 occlusion.occlusion_from_outside_target().ToString());
834 EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(),
835 occlusion.occlusion_from_inside_target().ToString());
837 this->LeaveContributingSurface(child, &occlusion);
838 this->EnterLayer(parent, &occlusion);
840 EXPECT_EQ(gfx::Rect().ToString(),
841 occlusion.occlusion_from_outside_target().ToString());
842 EXPECT_EQ(gfx::Rect(30, 40, 70, 60).ToString(),
843 occlusion.occlusion_from_inside_target().ToString());
845 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 40, 70, 60)));
846 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 40, 70, 60)));
847 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 39, 70, 60)));
848 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 40, 69, 60)));
849 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 41, 70, 59)));
851 /* Justification for the above occlusion from |layer|:
853 +---------------------+
856 | 30 + ---------------------------------+
858 | |10+---------------------------------+
862 +----|--|-------------+ | |
870 +--|-------------------------------+ |
872 +---------------------------------+
875 +---------------------+
876 | |30 Visible region of |layer|: /////
878 | +---------------------------------+
880 | +---------------------------------+ |
881 | | |///////////////| 420 | |
882 | | |///////////////|60 | |
883 | | |///////////////| | |
884 +--|--|---------------+ | |
892 | +------------------------------|--+
894 +---------------------------------+
901 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestChildInRotatedChild);
903 template <class Types>
904 class OcclusionTrackerTestScaledRenderSurface
905 : public OcclusionTrackerTest<Types> {
907 explicit OcclusionTrackerTestScaledRenderSurface(bool opaque_layers)
908 : OcclusionTrackerTest<Types>(opaque_layers) {}
911 typename Types::ContentLayerType* parent = this->CreateRoot(
912 this->identity_matrix, gfx::PointF(), gfx::Size(200, 200));
914 gfx::Transform layer1_matrix;
915 layer1_matrix.Scale(2.0, 2.0);
916 typename Types::ContentLayerType* layer1 = this->CreateDrawingLayer(
917 parent, layer1_matrix, gfx::PointF(), gfx::Size(100, 100), true);
918 layer1->SetForceRenderSurface(true);
920 gfx::Transform layer2_matrix;
921 layer2_matrix.Translate(25.0, 25.0);
922 typename Types::ContentLayerType* layer2 = this->CreateDrawingLayer(
923 layer1, layer2_matrix, gfx::PointF(), gfx::Size(50, 50), true);
924 typename Types::ContentLayerType* occluder =
925 this->CreateDrawingLayer(parent,
926 this->identity_matrix,
927 gfx::PointF(100.f, 100.f),
930 this->CalcDrawEtc(parent);
932 TestOcclusionTrackerWithClip<typename Types::LayerType,
933 typename Types::RenderSurfaceType> occlusion(
934 gfx::Rect(0, 0, 1000, 1000));
936 this->VisitLayer(occluder, &occlusion);
937 this->EnterLayer(layer2, &occlusion);
939 EXPECT_EQ(gfx::Rect(100, 100, 100, 100).ToString(),
940 occlusion.occlusion_from_outside_target().ToString());
941 EXPECT_EQ(gfx::Rect().ToString(),
942 occlusion.occlusion_from_inside_target().ToString());
945 gfx::Rect(0, 0, 25, 25),
946 occlusion.UnoccludedLayerContentRect(layer2, gfx::Rect(0, 0, 25, 25)));
947 EXPECT_RECT_EQ(gfx::Rect(10, 25, 15, 25),
948 occlusion.UnoccludedLayerContentRect(
949 layer2, gfx::Rect(10, 25, 25, 25)));
950 EXPECT_RECT_EQ(gfx::Rect(25, 10, 25, 15),
951 occlusion.UnoccludedLayerContentRect(
952 layer2, gfx::Rect(25, 10, 25, 25)));
953 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
954 layer2, gfx::Rect(25, 25, 25, 25)).IsEmpty());
958 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestScaledRenderSurface);
960 template <class Types>
961 class OcclusionTrackerTestVisitTargetTwoTimes
962 : public OcclusionTrackerTest<Types> {
964 explicit OcclusionTrackerTestVisitTargetTwoTimes(bool opaque_layers)
965 : OcclusionTrackerTest<Types>(opaque_layers) {}
967 gfx::Transform child_transform;
968 child_transform.Translate(250.0, 250.0);
969 child_transform.Rotate(90.0);
970 child_transform.Translate(-250.0, -250.0);
972 typename Types::ContentLayerType* root = this->CreateRoot(
973 this->identity_matrix, gfx::PointF(), gfx::Size(200, 200));
974 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
975 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
976 parent->SetMasksToBounds(true);
977 typename Types::LayerType* child = this->CreateSurface(
978 parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500));
979 child->SetMasksToBounds(true);
980 typename Types::ContentLayerType* layer =
981 this->CreateDrawingLayer(child,
982 this->identity_matrix,
983 gfx::PointF(10.f, 10.f),
986 // |child2| makes |parent|'s surface get considered by OcclusionTracker
987 // first, instead of |child|'s. This exercises different code in
988 // LeaveToRenderTarget, as the target surface has already been seen.
989 typename Types::ContentLayerType* child2 =
990 this->CreateDrawingLayer(parent,
991 this->identity_matrix,
992 gfx::PointF(30.f, 30.f),
995 this->CalcDrawEtc(root);
997 TestOcclusionTrackerWithClip<typename Types::LayerType,
998 typename Types::RenderSurfaceType> occlusion(
999 gfx::Rect(0, 0, 1000, 1000));
1001 this->VisitLayer(child2, &occlusion);
1003 EXPECT_EQ(gfx::Rect().ToString(),
1004 occlusion.occlusion_from_outside_target().ToString());
1005 EXPECT_EQ(gfx::Rect(30, 30, 60, 20).ToString(),
1006 occlusion.occlusion_from_inside_target().ToString());
1008 this->VisitLayer(layer, &occlusion);
1010 EXPECT_EQ(gfx::Rect(0, 440, 20, 60).ToString(),
1011 occlusion.occlusion_from_outside_target().ToString());
1012 EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(),
1013 occlusion.occlusion_from_inside_target().ToString());
1015 this->EnterContributingSurface(child, &occlusion);
1017 EXPECT_EQ(gfx::Rect(0, 440, 20, 60).ToString(),
1018 occlusion.occlusion_from_outside_target().ToString());
1019 EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(),
1020 occlusion.occlusion_from_inside_target().ToString());
1022 // Occlusion in |child2| should get merged with the |child| surface we are
1024 this->LeaveContributingSurface(child, &occlusion);
1025 this->EnterLayer(parent, &occlusion);
1027 EXPECT_EQ(gfx::Rect().ToString(),
1028 occlusion.occlusion_from_outside_target().ToString());
1029 EXPECT_EQ(UnionRegions(gfx::Rect(30, 30, 60, 10), gfx::Rect(30, 40, 70, 60))
1031 occlusion.occlusion_from_inside_target().ToString());
1033 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 70, 70)));
1034 EXPECT_RECT_EQ(gfx::Rect(90, 30, 10, 10),
1035 occlusion.UnoccludedLayerContentRect(
1036 parent, gfx::Rect(30, 30, 70, 70)));
1038 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 60, 10)));
1039 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 30, 60, 10)));
1040 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 29, 60, 10)));
1041 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(31, 30, 60, 10)));
1042 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 31, 60, 10)));
1044 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 40, 70, 60)));
1045 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 40, 70, 60)));
1046 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 39, 70, 60)));
1048 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
1049 parent, gfx::Rect(30, 30, 60, 10)).IsEmpty());
1050 EXPECT_RECT_EQ(gfx::Rect(29, 30, 1, 10),
1051 occlusion.UnoccludedLayerContentRect(
1052 parent, gfx::Rect(29, 30, 60, 10)));
1053 EXPECT_RECT_EQ(gfx::Rect(30, 29, 60, 1),
1054 occlusion.UnoccludedLayerContentRect(
1055 parent, gfx::Rect(30, 29, 60, 10)));
1056 EXPECT_RECT_EQ(gfx::Rect(90, 30, 1, 10),
1057 occlusion.UnoccludedLayerContentRect(
1058 parent, gfx::Rect(31, 30, 60, 10)));
1059 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
1060 parent, gfx::Rect(30, 31, 60, 10)).IsEmpty());
1062 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
1063 parent, gfx::Rect(30, 40, 70, 60)).IsEmpty());
1064 EXPECT_RECT_EQ(gfx::Rect(29, 40, 1, 60),
1065 occlusion.UnoccludedLayerContentRect(
1066 parent, gfx::Rect(29, 40, 70, 60)));
1067 // This rect is mostly occluded by |child2|.
1068 EXPECT_RECT_EQ(gfx::Rect(90, 39, 10, 1),
1069 occlusion.UnoccludedLayerContentRect(
1070 parent, gfx::Rect(30, 39, 70, 60)));
1071 // This rect extends past top/right ends of |child2|.
1072 EXPECT_RECT_EQ(gfx::Rect(30, 29, 70, 11),
1073 occlusion.UnoccludedLayerContentRect(
1074 parent, gfx::Rect(30, 29, 70, 70)));
1075 // This rect extends past left/right ends of |child2|.
1076 EXPECT_RECT_EQ(gfx::Rect(20, 39, 80, 60),
1077 occlusion.UnoccludedLayerContentRect(
1078 parent, gfx::Rect(20, 39, 80, 60)));
1079 EXPECT_RECT_EQ(gfx::Rect(),
1080 occlusion.UnoccludedLayerContentRect(
1081 parent, gfx::Rect(31, 40, 69, 60)));
1082 EXPECT_RECT_EQ(gfx::Rect(),
1083 occlusion.UnoccludedLayerContentRect(
1084 parent, gfx::Rect(30, 41, 70, 59)));
1086 /* Justification for the above occlusion from |layer|:
1088 +---------------------+
1091 | 30 + ------------+--------------------+
1092 100 | | 10 | | | ==>
1093 | |10+----------|----------------------+
1094 | + ------------+ | | |
1097 +----|--|-------------+ | |
1105 +--|-------------------------------+ |
1107 +---------------------------------+
1111 +---------------------+
1112 | |30 Visible region of |layer|: /////
1113 | 30 60 | |child2|: \\\\\
1114 | 30 +------------+--------------------+
1115 | |\\\\\\\\\\\\| |10 |
1116 | +--|\\\\\\\\\\\\|-----------------+ |
1117 | | +------------+//| 420 | |
1118 | | |///////////////|60 | |
1119 | | |///////////////| | |
1120 +--|--|---------------+ | |
1128 | +------------------------------|--+
1130 +---------------------------------+
1136 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestVisitTargetTwoTimes);
1138 template <class Types>
1139 class OcclusionTrackerTestSurfaceRotatedOffAxis
1140 : public OcclusionTrackerTest<Types> {
1142 explicit OcclusionTrackerTestSurfaceRotatedOffAxis(bool opaque_layers)
1143 : OcclusionTrackerTest<Types>(opaque_layers) {}
1145 gfx::Transform child_transform;
1146 child_transform.Translate(250.0, 250.0);
1147 child_transform.Rotate(95.0);
1148 child_transform.Translate(-250.0, -250.0);
1150 gfx::Transform layer_transform;
1151 layer_transform.Translate(10.0, 10.0);
1153 typename Types::ContentLayerType* root = this->CreateRoot(
1154 this->identity_matrix, gfx::PointF(), gfx::Size(1000, 1000));
1155 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
1156 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
1157 typename Types::LayerType* child = this->CreateLayer(
1158 parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500));
1159 child->SetMasksToBounds(true);
1160 typename Types::ContentLayerType* layer = this->CreateDrawingLayer(
1161 child, layer_transform, gfx::PointF(), gfx::Size(500, 500), true);
1162 this->CalcDrawEtc(root);
1164 TestOcclusionTrackerWithClip<typename Types::LayerType,
1165 typename Types::RenderSurfaceType> occlusion(
1166 gfx::Rect(0, 0, 1000, 1000));
1168 gfx::Rect clipped_layer_in_child = MathUtil::MapEnclosingClippedRect(
1169 layer_transform, layer->visible_content_rect());
1171 this->VisitLayer(layer, &occlusion);
1172 this->EnterContributingSurface(child, &occlusion);
1174 EXPECT_EQ(gfx::Rect().ToString(),
1175 occlusion.occlusion_from_outside_target().ToString());
1176 EXPECT_EQ(clipped_layer_in_child.ToString(),
1177 occlusion.occlusion_from_inside_target().ToString());
1179 this->LeaveContributingSurface(child, &occlusion);
1180 this->EnterLayer(parent, &occlusion);
1182 EXPECT_EQ(gfx::Rect().ToString(),
1183 occlusion.occlusion_from_outside_target().ToString());
1184 EXPECT_EQ(gfx::Rect().ToString(),
1185 occlusion.occlusion_from_inside_target().ToString());
1187 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(75, 55, 1, 1)));
1189 gfx::Rect(75, 55, 1, 1),
1190 occlusion.UnoccludedLayerContentRect(parent, gfx::Rect(75, 55, 1, 1)));
1194 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceRotatedOffAxis);
1196 template <class Types>
1197 class OcclusionTrackerTestSurfaceWithTwoOpaqueChildren
1198 : public OcclusionTrackerTest<Types> {
1200 explicit OcclusionTrackerTestSurfaceWithTwoOpaqueChildren(bool opaque_layers)
1201 : OcclusionTrackerTest<Types>(opaque_layers) {}
1203 gfx::Transform child_transform;
1204 child_transform.Translate(250.0, 250.0);
1205 child_transform.Rotate(90.0);
1206 child_transform.Translate(-250.0, -250.0);
1208 typename Types::ContentLayerType* root = this->CreateRoot(
1209 this->identity_matrix, gfx::PointF(), gfx::Size(1000, 1000));
1210 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
1211 root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
1212 parent->SetMasksToBounds(true);
1213 typename Types::ContentLayerType* child =
1214 this->CreateDrawingSurface(parent,
1216 gfx::PointF(30.f, 30.f),
1217 gfx::Size(500, 500),
1219 child->SetMasksToBounds(true);
1220 typename Types::ContentLayerType* layer1 =
1221 this->CreateDrawingLayer(child,
1222 this->identity_matrix,
1223 gfx::PointF(10.f, 10.f),
1224 gfx::Size(500, 500),
1226 typename Types::ContentLayerType* layer2 =
1227 this->CreateDrawingLayer(child,
1228 this->identity_matrix,
1229 gfx::PointF(10.f, 450.f),
1232 this->CalcDrawEtc(root);
1234 TestOcclusionTrackerWithClip<typename Types::LayerType,
1235 typename Types::RenderSurfaceType> occlusion(
1236 gfx::Rect(0, 0, 1000, 1000));
1238 this->VisitLayer(layer2, &occlusion);
1239 this->VisitLayer(layer1, &occlusion);
1240 this->VisitLayer(child, &occlusion);
1241 this->EnterContributingSurface(child, &occlusion);
1243 EXPECT_EQ(gfx::Rect().ToString(),
1244 occlusion.occlusion_from_outside_target().ToString());
1245 EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(),
1246 occlusion.occlusion_from_inside_target().ToString());
1248 EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(10, 430, 60, 70)));
1249 EXPECT_FALSE(occlusion.OccludedLayer(child, gfx::Rect(9, 430, 60, 70)));
1250 EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(11, 430, 59, 70)));
1251 EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(10, 431, 60, 69)));
1253 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
1254 child, gfx::Rect(10, 430, 60, 70)).IsEmpty());
1256 gfx::Rect(9, 430, 1, 70),
1257 occlusion.UnoccludedLayerContentRect(child, gfx::Rect(9, 430, 60, 70)));
1258 EXPECT_RECT_EQ(gfx::Rect(),
1259 occlusion.UnoccludedLayerContentRect(
1260 child, gfx::Rect(11, 430, 59, 70)));
1261 EXPECT_RECT_EQ(gfx::Rect(),
1262 occlusion.UnoccludedLayerContentRect(
1263 child, gfx::Rect(10, 431, 60, 69)));
1265 this->LeaveContributingSurface(child, &occlusion);
1266 this->EnterLayer(parent, &occlusion);
1268 EXPECT_EQ(gfx::Rect().ToString(),
1269 occlusion.occlusion_from_outside_target().ToString());
1270 EXPECT_EQ(gfx::Rect(30, 40, 70, 60).ToString(),
1271 occlusion.occlusion_from_inside_target().ToString());
1273 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 40, 70, 60)));
1274 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 40, 70, 60)));
1275 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 39, 70, 60)));
1277 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
1278 parent, gfx::Rect(30, 40, 70, 60)).IsEmpty());
1279 EXPECT_RECT_EQ(gfx::Rect(29, 40, 1, 60),
1280 occlusion.UnoccludedLayerContentRect(
1281 parent, gfx::Rect(29, 40, 70, 60)));
1282 EXPECT_RECT_EQ(gfx::Rect(30, 39, 70, 1),
1283 occlusion.UnoccludedLayerContentRect(
1284 parent, gfx::Rect(30, 39, 70, 60)));
1285 EXPECT_RECT_EQ(gfx::Rect(),
1286 occlusion.UnoccludedLayerContentRect(
1287 parent, gfx::Rect(31, 40, 69, 60)));
1288 EXPECT_RECT_EQ(gfx::Rect(),
1289 occlusion.UnoccludedLayerContentRect(
1290 parent, gfx::Rect(30, 41, 70, 59)));
1292 /* Justification for the above occlusion from |layer1| and |layer2|:
1294 +---------------------+
1295 | |30 Visible region of |layer1|: /////
1296 | | Visible region of |layer2|: \\\\\
1297 | +---------------------------------+
1299 | +---------------+-----------------+ |
1300 | | |\\\\\\\\\\\\|//| 420 | |
1301 | | |\\\\\\\\\\\\|//|60 | |
1302 | | |\\\\\\\\\\\\|//| | |
1303 +--|--|------------|--+ | |
1311 | +------------|-----------------|--+
1313 +---------------+-----------------+
1319 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceWithTwoOpaqueChildren);
1321 template <class Types>
1322 class OcclusionTrackerTestOverlappingSurfaceSiblings
1323 : public OcclusionTrackerTest<Types> {
1325 explicit OcclusionTrackerTestOverlappingSurfaceSiblings(bool opaque_layers)
1326 : OcclusionTrackerTest<Types>(opaque_layers) {}
1328 gfx::Transform child_transform;
1329 child_transform.Translate(250.0, 250.0);
1330 child_transform.Rotate(90.0);
1331 child_transform.Translate(-250.0, -250.0);
1333 typename Types::ContentLayerType* parent = this->CreateRoot(
1334 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
1335 parent->SetMasksToBounds(true);
1336 typename Types::LayerType* child1 = this->CreateSurface(
1337 parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(10, 10));
1338 typename Types::LayerType* child2 = this->CreateSurface(
1339 parent, child_transform, gfx::PointF(20.f, 40.f), gfx::Size(10, 10));
1340 typename Types::ContentLayerType* layer1 =
1341 this->CreateDrawingLayer(child1,
1342 this->identity_matrix,
1343 gfx::PointF(-10.f, -10.f),
1344 gfx::Size(510, 510),
1346 typename Types::ContentLayerType* layer2 =
1347 this->CreateDrawingLayer(child2,
1348 this->identity_matrix,
1349 gfx::PointF(-10.f, -10.f),
1350 gfx::Size(510, 510),
1352 this->CalcDrawEtc(parent);
1354 TestOcclusionTrackerWithClip<typename Types::LayerType,
1355 typename Types::RenderSurfaceType> occlusion(
1356 gfx::Rect(0, 0, 1000, 1000));
1358 this->VisitLayer(layer2, &occlusion);
1359 this->EnterContributingSurface(child2, &occlusion);
1361 EXPECT_EQ(gfx::Rect().ToString(),
1362 occlusion.occlusion_from_outside_target().ToString());
1363 EXPECT_EQ(gfx::Rect(-10, 420, 70, 80).ToString(),
1364 occlusion.occlusion_from_inside_target().ToString());
1366 // There is nothing above child2's surface in the z-order.
1367 EXPECT_RECT_EQ(gfx::Rect(-10, 420, 70, 80),
1368 occlusion.UnoccludedContributingSurfaceContentRect(
1369 child2, false, gfx::Rect(-10, 420, 70, 80)));
1371 this->LeaveContributingSurface(child2, &occlusion);
1372 this->VisitLayer(layer1, &occlusion);
1373 this->EnterContributingSurface(child1, &occlusion);
1375 EXPECT_EQ(gfx::Rect(0, 430, 70, 80).ToString(),
1376 occlusion.occlusion_from_outside_target().ToString());
1377 EXPECT_EQ(gfx::Rect(-10, 430, 80, 70).ToString(),
1378 occlusion.occlusion_from_inside_target().ToString());
1380 // child2's contents will occlude child1 below it.
1381 EXPECT_RECT_EQ(gfx::Rect(-10, 430, 10, 70),
1382 occlusion.UnoccludedContributingSurfaceContentRect(
1383 child1, false, gfx::Rect(-10, 430, 80, 70)));
1385 this->LeaveContributingSurface(child1, &occlusion);
1386 this->EnterLayer(parent, &occlusion);
1388 EXPECT_EQ(gfx::Rect().ToString(),
1389 occlusion.occlusion_from_outside_target().ToString());
1390 EXPECT_EQ(UnionRegions(gfx::Rect(30, 20, 70, 10), gfx::Rect(20, 30, 80, 70))
1392 occlusion.occlusion_from_inside_target().ToString());
1394 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(20, 20, 80, 80)));
1396 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 20, 70, 80)));
1397 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 20, 70, 80)));
1398 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 19, 70, 80)));
1400 EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(20, 30, 80, 70)));
1401 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(19, 30, 80, 70)));
1402 EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(20, 29, 80, 70)));
1404 /* Justification for the above occlusion:
1406 +---------------------+
1408 | 30+ ---------------------------------+
1409 100 | 30| | layer2 |
1410 |20+----------------------------------+ |
1414 +--|-|----------------+ | |
1422 | +--------------------------------|-+
1424 +----------------------------------+
1430 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestOverlappingSurfaceSiblings);
1432 template <class Types>
1433 class OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms
1434 : public OcclusionTrackerTest<Types> {
1436 explicit OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms(
1438 : OcclusionTrackerTest<Types>(opaque_layers) {}
1440 gfx::Transform child1_transform;
1441 child1_transform.Translate(250.0, 250.0);
1442 child1_transform.Rotate(-90.0);
1443 child1_transform.Translate(-250.0, -250.0);
1445 gfx::Transform child2_transform;
1446 child2_transform.Translate(250.0, 250.0);
1447 child2_transform.Rotate(90.0);
1448 child2_transform.Translate(-250.0, -250.0);
1450 typename Types::ContentLayerType* parent = this->CreateRoot(
1451 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
1452 parent->SetMasksToBounds(true);
1453 typename Types::LayerType* child1 = this->CreateSurface(
1454 parent, child1_transform, gfx::PointF(30.f, 20.f), gfx::Size(10, 10));
1455 typename Types::LayerType* child2 =
1456 this->CreateDrawingSurface(parent,
1458 gfx::PointF(20.f, 40.f),
1461 typename Types::ContentLayerType* layer1 =
1462 this->CreateDrawingLayer(child1,
1463 this->identity_matrix,
1464 gfx::PointF(-10.f, -20.f),
1465 gfx::Size(510, 510),
1467 typename Types::ContentLayerType* layer2 =
1468 this->CreateDrawingLayer(child2,
1469 this->identity_matrix,
1470 gfx::PointF(-10.f, -10.f),
1471 gfx::Size(510, 510),
1473 this->CalcDrawEtc(parent);
1475 TestOcclusionTrackerWithClip<typename Types::LayerType,
1476 typename Types::RenderSurfaceType> occlusion(
1477 gfx::Rect(0, 0, 1000, 1000));
1479 this->VisitLayer(layer2, &occlusion);
1480 this->EnterLayer(child2, &occlusion);
1482 EXPECT_EQ(gfx::Rect().ToString(),
1483 occlusion.occlusion_from_outside_target().ToString());
1484 EXPECT_EQ(gfx::Rect(-10, 420, 70, 80).ToString(),
1485 occlusion.occlusion_from_inside_target().ToString());
1487 this->LeaveLayer(child2, &occlusion);
1488 this->EnterContributingSurface(child2, &occlusion);
1490 // There is nothing above child2's surface in the z-order.
1491 EXPECT_RECT_EQ(gfx::Rect(-10, 420, 70, 80),
1492 occlusion.UnoccludedContributingSurfaceContentRect(
1493 child2, false, gfx::Rect(-10, 420, 70, 80)));
1495 this->LeaveContributingSurface(child2, &occlusion);
1496 this->VisitLayer(layer1, &occlusion);
1497 this->EnterContributingSurface(child1, &occlusion);
1499 EXPECT_EQ(gfx::Rect(420, -10, 70, 80).ToString(),
1500 occlusion.occlusion_from_outside_target().ToString());
1501 EXPECT_EQ(gfx::Rect(420, -20, 80, 90).ToString(),
1502 occlusion.occlusion_from_inside_target().ToString());
1504 // child2's contents will occlude child1 below it.
1505 EXPECT_RECT_EQ(gfx::Rect(420, -20, 80, 90),
1506 occlusion.UnoccludedContributingSurfaceContentRect(
1507 child1, false, gfx::Rect(420, -20, 80, 90)));
1508 EXPECT_RECT_EQ(gfx::Rect(490, -10, 10, 80),
1509 occlusion.UnoccludedContributingSurfaceContentRect(
1510 child1, false, gfx::Rect(420, -10, 80, 90)));
1511 EXPECT_RECT_EQ(gfx::Rect(420, -20, 70, 10),
1512 occlusion.UnoccludedContributingSurfaceContentRect(
1513 child1, false, gfx::Rect(420, -20, 70, 90)));
1515 this->LeaveContributingSurface(child1, &occlusion);
1516 this->EnterLayer(parent, &occlusion);
1518 EXPECT_EQ(gfx::Rect().ToString(),
1519 occlusion.occlusion_from_outside_target().ToString());
1520 EXPECT_EQ(gfx::Rect(10, 20, 90, 80).ToString(),
1521 occlusion.occlusion_from_inside_target().ToString());
1523 /* Justification for the above occlusion:
1525 +---------------------+
1527 10+----------------------------------+
1528 100 || 30 | layer2 |
1529 |20+----------------------------------+
1533 +|-|------------------+ | |
1541 +----------------------------------+ |
1543 +----------------------------------+
1549 ALL_OCCLUSIONTRACKER_TEST(
1550 OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms);
1552 template <class Types>
1553 class OcclusionTrackerTestFilters : public OcclusionTrackerTest<Types> {
1555 explicit OcclusionTrackerTestFilters(bool opaque_layers)
1556 : OcclusionTrackerTest<Types>(opaque_layers) {}
1558 gfx::Transform layer_transform;
1559 layer_transform.Translate(250.0, 250.0);
1560 layer_transform.Rotate(90.0);
1561 layer_transform.Translate(-250.0, -250.0);
1563 typename Types::ContentLayerType* parent = this->CreateRoot(
1564 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
1565 parent->SetMasksToBounds(true);
1566 typename Types::ContentLayerType* blur_layer =
1567 this->CreateDrawingLayer(parent,
1569 gfx::PointF(30.f, 30.f),
1570 gfx::Size(500, 500),
1572 typename Types::ContentLayerType* opaque_layer =
1573 this->CreateDrawingLayer(parent,
1575 gfx::PointF(30.f, 30.f),
1576 gfx::Size(500, 500),
1578 typename Types::ContentLayerType* opacity_layer =
1579 this->CreateDrawingLayer(parent,
1581 gfx::PointF(30.f, 30.f),
1582 gfx::Size(500, 500),
1585 FilterOperations filters;
1586 filters.Append(FilterOperation::CreateBlurFilter(10.f));
1587 blur_layer->SetFilters(filters);
1590 filters.Append(FilterOperation::CreateGrayscaleFilter(0.5f));
1591 opaque_layer->SetFilters(filters);
1594 filters.Append(FilterOperation::CreateOpacityFilter(0.5f));
1595 opacity_layer->SetFilters(filters);
1597 this->CalcDrawEtc(parent);
1599 TestOcclusionTrackerWithClip<typename Types::LayerType,
1600 typename Types::RenderSurfaceType> occlusion(
1601 gfx::Rect(0, 0, 1000, 1000));
1603 // Opacity layer won't contribute to occlusion.
1604 this->VisitLayer(opacity_layer, &occlusion);
1605 this->EnterContributingSurface(opacity_layer, &occlusion);
1607 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1608 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1610 // And has nothing to contribute to its parent surface.
1611 this->LeaveContributingSurface(opacity_layer, &occlusion);
1612 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1613 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1615 // Opaque layer will contribute to occlusion.
1616 this->VisitLayer(opaque_layer, &occlusion);
1617 this->EnterContributingSurface(opaque_layer, &occlusion);
1619 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1620 EXPECT_EQ(gfx::Rect(0, 430, 70, 70).ToString(),
1621 occlusion.occlusion_from_inside_target().ToString());
1623 // And it gets translated to the parent surface.
1624 this->LeaveContributingSurface(opaque_layer, &occlusion);
1625 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1626 EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(),
1627 occlusion.occlusion_from_inside_target().ToString());
1629 // The blur layer needs to throw away any occlusion from outside its
1631 this->EnterLayer(blur_layer, &occlusion);
1632 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1633 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1635 // And it won't contribute to occlusion.
1636 this->LeaveLayer(blur_layer, &occlusion);
1637 this->EnterContributingSurface(blur_layer, &occlusion);
1638 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1639 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1641 // But the opaque layer's occlusion is preserved on the parent.
1642 this->LeaveContributingSurface(blur_layer, &occlusion);
1643 this->EnterLayer(parent, &occlusion);
1644 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1645 EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(),
1646 occlusion.occlusion_from_inside_target().ToString());
1650 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestFilters);
1652 template <class Types>
1653 class OcclusionTrackerTestReplicaDoesOcclude
1654 : public OcclusionTrackerTest<Types> {
1656 explicit OcclusionTrackerTestReplicaDoesOcclude(bool opaque_layers)
1657 : OcclusionTrackerTest<Types>(opaque_layers) {}
1659 typename Types::ContentLayerType* parent = this->CreateRoot(
1660 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
1661 typename Types::LayerType* surface =
1662 this->CreateDrawingSurface(parent,
1663 this->identity_matrix,
1664 gfx::PointF(0.f, 100.f),
1667 this->CreateReplicaLayer(
1668 surface, this->identity_matrix, gfx::PointF(50.f, 50.f), gfx::Size());
1669 this->CalcDrawEtc(parent);
1671 TestOcclusionTrackerWithClip<typename Types::LayerType,
1672 typename Types::RenderSurfaceType> occlusion(
1673 gfx::Rect(0, 0, 1000, 1000));
1675 this->VisitLayer(surface, &occlusion);
1677 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
1678 occlusion.occlusion_from_inside_target().ToString());
1680 this->VisitContributingSurface(surface, &occlusion);
1681 this->EnterLayer(parent, &occlusion);
1683 // The surface and replica should both be occluding the parent.
1685 UnionRegions(gfx::Rect(0, 100, 50, 50),
1686 gfx::Rect(50, 150, 50, 50)).ToString(),
1687 occlusion.occlusion_from_inside_target().ToString());
1691 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaDoesOcclude);
1693 template <class Types>
1694 class OcclusionTrackerTestReplicaWithClipping
1695 : public OcclusionTrackerTest<Types> {
1697 explicit OcclusionTrackerTestReplicaWithClipping(bool opaque_layers)
1698 : OcclusionTrackerTest<Types>(opaque_layers) {}
1700 typename Types::ContentLayerType* parent = this->CreateRoot(
1701 this->identity_matrix, gfx::PointF(), gfx::Size(100, 170));
1702 parent->SetMasksToBounds(true);
1703 typename Types::LayerType* surface =
1704 this->CreateDrawingSurface(parent,
1705 this->identity_matrix,
1706 gfx::PointF(0.f, 100.f),
1709 this->CreateReplicaLayer(
1710 surface, this->identity_matrix, gfx::PointF(50.f, 50.f), gfx::Size());
1711 this->CalcDrawEtc(parent);
1713 TestOcclusionTrackerWithClip<typename Types::LayerType,
1714 typename Types::RenderSurfaceType> 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 surface and replica should both be occluding the parent.
1727 UnionRegions(gfx::Rect(0, 100, 50, 50),
1728 gfx::Rect(50, 150, 50, 20)).ToString(),
1729 occlusion.occlusion_from_inside_target().ToString());
1733 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaWithClipping);
1735 template <class Types>
1736 class OcclusionTrackerTestReplicaWithMask : public OcclusionTrackerTest<Types> {
1738 explicit OcclusionTrackerTestReplicaWithMask(bool opaque_layers)
1739 : OcclusionTrackerTest<Types>(opaque_layers) {}
1741 typename Types::ContentLayerType* parent = this->CreateRoot(
1742 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
1743 typename Types::LayerType* surface =
1744 this->CreateDrawingSurface(parent,
1745 this->identity_matrix,
1746 gfx::PointF(0.f, 100.f),
1749 typename Types::LayerType* replica = this->CreateReplicaLayer(
1750 surface, this->identity_matrix, gfx::PointF(50.f, 50.f), gfx::Size());
1751 this->CreateMaskLayer(replica, gfx::Size(10, 10));
1752 this->CalcDrawEtc(parent);
1754 TestOcclusionTrackerWithClip<typename Types::LayerType,
1755 typename Types::RenderSurfaceType> occlusion(
1756 gfx::Rect(0, 0, 1000, 1000));
1758 this->VisitLayer(surface, &occlusion);
1760 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
1761 occlusion.occlusion_from_inside_target().ToString());
1763 this->VisitContributingSurface(surface, &occlusion);
1764 this->EnterLayer(parent, &occlusion);
1766 // The replica should not be occluding the parent, since it has a mask
1768 EXPECT_EQ(gfx::Rect(0, 100, 50, 50).ToString(),
1769 occlusion.occlusion_from_inside_target().ToString());
1773 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaWithMask);
1775 template <class Types>
1776 class OcclusionTrackerTestOpaqueContentsRegionEmpty
1777 : public OcclusionTrackerTest<Types> {
1779 explicit OcclusionTrackerTestOpaqueContentsRegionEmpty(bool opaque_layers)
1780 : OcclusionTrackerTest<Types>(opaque_layers) {}
1782 typename Types::ContentLayerType* parent = this->CreateRoot(
1783 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1784 typename Types::ContentLayerType* layer =
1785 this->CreateDrawingSurface(parent,
1786 this->identity_matrix,
1788 gfx::Size(200, 200),
1790 this->CalcDrawEtc(parent);
1792 TestOcclusionTrackerWithClip<typename Types::LayerType,
1793 typename Types::RenderSurfaceType> occlusion(
1794 gfx::Rect(0, 0, 1000, 1000));
1795 this->EnterLayer(layer, &occlusion);
1797 EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 100, 100)));
1798 EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 0, 100, 100)));
1799 EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 100, 100, 100)));
1800 EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 100, 100, 100)));
1802 this->LeaveLayer(layer, &occlusion);
1803 this->VisitContributingSurface(layer, &occlusion);
1804 this->EnterLayer(parent, &occlusion);
1806 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1810 MAIN_AND_IMPL_THREAD_TEST(OcclusionTrackerTestOpaqueContentsRegionEmpty);
1812 template <class Types>
1813 class OcclusionTrackerTestOpaqueContentsRegionNonEmpty
1814 : public OcclusionTrackerTest<Types> {
1816 explicit OcclusionTrackerTestOpaqueContentsRegionNonEmpty(bool opaque_layers)
1817 : OcclusionTrackerTest<Types>(opaque_layers) {}
1819 typename Types::ContentLayerType* parent = this->CreateRoot(
1820 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1821 typename Types::ContentLayerType* layer =
1822 this->CreateDrawingLayer(parent,
1823 this->identity_matrix,
1824 gfx::PointF(100.f, 100.f),
1825 gfx::Size(200, 200),
1827 this->CalcDrawEtc(parent);
1829 TestOcclusionTrackerWithClip<typename Types::LayerType,
1830 typename Types::RenderSurfaceType> occlusion(
1831 gfx::Rect(0, 0, 1000, 1000));
1832 layer->SetOpaqueContentsRect(gfx::Rect(0, 0, 100, 100));
1834 this->ResetLayerIterator();
1835 this->VisitLayer(layer, &occlusion);
1836 this->EnterLayer(parent, &occlusion);
1838 EXPECT_EQ(gfx::Rect(100, 100, 100, 100).ToString(),
1839 occlusion.occlusion_from_inside_target().ToString());
1842 occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100)));
1844 occlusion.OccludedLayer(parent, gfx::Rect(100, 100, 100, 100)));
1846 occlusion.OccludedLayer(parent, gfx::Rect(200, 200, 100, 100)));
1849 TestOcclusionTrackerWithClip<typename Types::LayerType,
1850 typename Types::RenderSurfaceType> occlusion(
1851 gfx::Rect(0, 0, 1000, 1000));
1852 layer->SetOpaqueContentsRect(gfx::Rect(20, 20, 180, 180));
1854 this->ResetLayerIterator();
1855 this->VisitLayer(layer, &occlusion);
1856 this->EnterLayer(parent, &occlusion);
1858 EXPECT_EQ(gfx::Rect(120, 120, 180, 180).ToString(),
1859 occlusion.occlusion_from_inside_target().ToString());
1862 occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100)));
1864 occlusion.OccludedLayer(parent, gfx::Rect(100, 100, 100, 100)));
1866 occlusion.OccludedLayer(parent, gfx::Rect(200, 200, 100, 100)));
1869 TestOcclusionTrackerWithClip<typename Types::LayerType,
1870 typename Types::RenderSurfaceType> occlusion(
1871 gfx::Rect(0, 0, 1000, 1000));
1872 layer->SetOpaqueContentsRect(gfx::Rect(150, 150, 100, 100));
1874 this->ResetLayerIterator();
1875 this->VisitLayer(layer, &occlusion);
1876 this->EnterLayer(parent, &occlusion);
1878 EXPECT_EQ(gfx::Rect(250, 250, 50, 50).ToString(),
1879 occlusion.occlusion_from_inside_target().ToString());
1882 occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100)));
1884 occlusion.OccludedLayer(parent, gfx::Rect(100, 100, 100, 100)));
1886 occlusion.OccludedLayer(parent, gfx::Rect(200, 200, 100, 100)));
1891 MAIN_AND_IMPL_THREAD_TEST(OcclusionTrackerTestOpaqueContentsRegionNonEmpty);
1893 template <class Types>
1894 class OcclusionTrackerTest3dTransform : public OcclusionTrackerTest<Types> {
1896 explicit OcclusionTrackerTest3dTransform(bool opaque_layers)
1897 : OcclusionTrackerTest<Types>(opaque_layers) {}
1899 gfx::Transform transform;
1900 transform.RotateAboutYAxis(30.0);
1902 typename Types::ContentLayerType* parent = this->CreateRoot(
1903 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1904 typename Types::LayerType* container = this->CreateLayer(
1905 parent, this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1906 typename Types::ContentLayerType* layer =
1907 this->CreateDrawingLayer(container,
1909 gfx::PointF(100.f, 100.f),
1910 gfx::Size(200, 200),
1912 this->CalcDrawEtc(parent);
1914 TestOcclusionTrackerWithClip<typename Types::LayerType,
1915 typename Types::RenderSurfaceType> occlusion(
1916 gfx::Rect(0, 0, 1000, 1000));
1917 this->EnterLayer(layer, &occlusion);
1919 // The layer is rotated in 3d but without preserving 3d, so it only gets
1922 gfx::Rect(0, 0, 200, 200),
1923 occlusion.UnoccludedLayerContentRect(layer, gfx::Rect(0, 0, 200, 200)));
1927 MAIN_AND_IMPL_THREAD_TEST(OcclusionTrackerTest3dTransform);
1929 template <class Types>
1930 class OcclusionTrackerTestUnsorted3dLayers
1931 : public OcclusionTrackerTest<Types> {
1933 explicit OcclusionTrackerTestUnsorted3dLayers(bool opaque_layers)
1934 : OcclusionTrackerTest<Types>(opaque_layers) {}
1936 // Currently, The main thread layer iterator does not iterate over 3d items
1937 // in sorted order, because layer sorting is not performed on the main
1938 // thread. Because of this, the occlusion tracker cannot assume that a 3d
1939 // layer occludes other layers that have not yet been iterated over. For
1940 // now, the expected behavior is that a 3d layer simply does not add any
1941 // occlusion to the occlusion tracker.
1943 gfx::Transform translation_to_front;
1944 translation_to_front.Translate3d(0.0, 0.0, -10.0);
1945 gfx::Transform translation_to_back;
1946 translation_to_front.Translate3d(0.0, 0.0, -100.0);
1948 typename Types::ContentLayerType* parent = this->CreateRoot(
1949 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1950 typename Types::ContentLayerType* child1 = this->CreateDrawingLayer(
1951 parent, translation_to_back, gfx::PointF(), gfx::Size(100, 100), true);
1952 typename Types::ContentLayerType* child2 =
1953 this->CreateDrawingLayer(parent,
1954 translation_to_front,
1955 gfx::PointF(50.f, 50.f),
1956 gfx::Size(100, 100),
1958 parent->SetShouldFlattenTransform(false);
1959 parent->SetIs3dSorted(true);
1960 child1->SetIs3dSorted(true);
1961 child2->SetIs3dSorted(true);
1963 this->CalcDrawEtc(parent);
1965 TestOcclusionTrackerWithClip<typename Types::LayerType,
1966 typename Types::RenderSurfaceType> occlusion(
1967 gfx::Rect(0, 0, 1000, 1000));
1968 this->VisitLayer(child2, &occlusion);
1969 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1970 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1972 this->VisitLayer(child1, &occlusion);
1973 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1974 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1978 // This test will have different layer ordering on the impl thread; the test
1979 // will only work on the main thread.
1980 MAIN_THREAD_TEST(OcclusionTrackerTestUnsorted3dLayers);
1982 template <class Types>
1983 class OcclusionTrackerTestPerspectiveTransform
1984 : public OcclusionTrackerTest<Types> {
1986 explicit OcclusionTrackerTestPerspectiveTransform(bool opaque_layers)
1987 : OcclusionTrackerTest<Types>(opaque_layers) {}
1989 gfx::Transform transform;
1990 transform.Translate(150.0, 150.0);
1991 transform.ApplyPerspectiveDepth(400.0);
1992 transform.RotateAboutXAxis(-30.0);
1993 transform.Translate(-150.0, -150.0);
1995 typename Types::ContentLayerType* parent = this->CreateRoot(
1996 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1997 typename Types::LayerType* container = this->CreateLayer(
1998 parent, this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1999 typename Types::ContentLayerType* layer =
2000 this->CreateDrawingLayer(container,
2002 gfx::PointF(100.f, 100.f),
2003 gfx::Size(200, 200),
2005 container->SetShouldFlattenTransform(false);
2006 container->SetIs3dSorted(true);
2007 layer->SetIs3dSorted(true);
2008 layer->SetShouldFlattenTransform(false);
2010 this->CalcDrawEtc(parent);
2012 TestOcclusionTrackerWithClip<typename Types::LayerType,
2013 typename Types::RenderSurfaceType> occlusion(
2014 gfx::Rect(0, 0, 1000, 1000));
2015 this->EnterLayer(layer, &occlusion);
2018 gfx::Rect(0, 0, 200, 200),
2019 occlusion.UnoccludedLayerContentRect(layer, gfx::Rect(0, 0, 200, 200)));
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(OcclusionTrackerTestPerspectiveTransform);
2027 template <class Types>
2028 class OcclusionTrackerTestPerspectiveTransformBehindCamera
2029 : public OcclusionTrackerTest<Types> {
2031 explicit OcclusionTrackerTestPerspectiveTransformBehindCamera(
2033 : OcclusionTrackerTest<Types>(opaque_layers) {}
2035 // This test is based on the platform/chromium/compositing/3d-corners.html
2037 gfx::Transform transform;
2038 transform.Translate(250.0, 50.0);
2039 transform.ApplyPerspectiveDepth(10.0);
2040 transform.Translate(-250.0, -50.0);
2041 transform.Translate(250.0, 50.0);
2042 transform.RotateAboutXAxis(-167.0);
2043 transform.Translate(-250.0, -50.0);
2045 typename Types::ContentLayerType* parent = this->CreateRoot(
2046 this->identity_matrix, gfx::PointF(), gfx::Size(500, 100));
2047 typename Types::LayerType* container = this->CreateLayer(
2048 parent, this->identity_matrix, gfx::PointF(), gfx::Size(500, 500));
2049 typename Types::ContentLayerType* layer = this->CreateDrawingLayer(
2050 container, transform, gfx::PointF(), gfx::Size(500, 500), true);
2051 container->SetShouldFlattenTransform(false);
2052 container->SetIs3dSorted(true);
2053 layer->SetShouldFlattenTransform(false);
2054 layer->SetIs3dSorted(true);
2055 this->CalcDrawEtc(parent);
2057 TestOcclusionTrackerWithClip<typename Types::LayerType,
2058 typename Types::RenderSurfaceType> occlusion(
2059 gfx::Rect(0, 0, 1000, 1000));
2060 this->EnterLayer(layer, &occlusion);
2062 // The bottom 11 pixel rows of this layer remain visible inside the
2063 // container, after translation to the target surface. When translated back,
2064 // this will include many more pixels but must include at least the bottom
2066 EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
2067 layer, gfx::Rect(0, 26, 500, 474)).
2068 Contains(gfx::Rect(0, 489, 500, 11)));
2072 // This test requires accumulating occlusion of 3d layers, which are skipped by
2073 // the occlusion tracker on the main thread. So this test should run on the impl
2075 IMPL_THREAD_TEST(OcclusionTrackerTestPerspectiveTransformBehindCamera);
2077 template <class Types>
2078 class OcclusionTrackerTestLayerBehindCameraDoesNotOcclude
2079 : public OcclusionTrackerTest<Types> {
2081 explicit OcclusionTrackerTestLayerBehindCameraDoesNotOcclude(
2083 : OcclusionTrackerTest<Types>(opaque_layers) {}
2085 gfx::Transform transform;
2086 transform.Translate(50.0, 50.0);
2087 transform.ApplyPerspectiveDepth(100.0);
2088 transform.Translate3d(0.0, 0.0, 110.0);
2089 transform.Translate(-50.0, -50.0);
2091 typename Types::ContentLayerType* parent = this->CreateRoot(
2092 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
2093 typename Types::ContentLayerType* layer = this->CreateDrawingLayer(
2094 parent, transform, gfx::PointF(), gfx::Size(100, 100), true);
2095 parent->SetShouldFlattenTransform(false);
2096 parent->SetIs3dSorted(true);
2097 layer->SetShouldFlattenTransform(false);
2098 layer->SetIs3dSorted(true);
2099 this->CalcDrawEtc(parent);
2101 TestOcclusionTrackerWithClip<typename Types::LayerType,
2102 typename Types::RenderSurfaceType> occlusion(
2103 gfx::Rect(0, 0, 1000, 1000));
2105 // The |layer| is entirely behind the camera and should not occlude.
2106 this->VisitLayer(layer, &occlusion);
2107 this->EnterLayer(parent, &occlusion);
2108 EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
2109 EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
2113 // This test requires accumulating occlusion of 3d layers, which are skipped by
2114 // the occlusion tracker on the main thread. So this test should run on the impl
2116 IMPL_THREAD_TEST(OcclusionTrackerTestLayerBehindCameraDoesNotOcclude);
2118 template <class Types>
2119 class OcclusionTrackerTestLargePixelsOccludeInsideClipRect
2120 : public OcclusionTrackerTest<Types> {
2122 explicit OcclusionTrackerTestLargePixelsOccludeInsideClipRect(
2124 : OcclusionTrackerTest<Types>(opaque_layers) {}
2126 gfx::Transform transform;
2127 transform.Translate(50.0, 50.0);
2128 transform.ApplyPerspectiveDepth(100.0);
2129 transform.Translate3d(0.0, 0.0, 99.0);
2130 transform.Translate(-50.0, -50.0);
2132 typename Types::ContentLayerType* parent = this->CreateRoot(
2133 this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
2134 parent->SetMasksToBounds(true);
2135 typename Types::ContentLayerType* layer = this->CreateDrawingLayer(
2136 parent, transform, gfx::PointF(), gfx::Size(100, 100), true);
2137 parent->SetShouldFlattenTransform(false);
2138 parent->SetIs3dSorted(true);
2139 layer->SetShouldFlattenTransform(false);
2140 layer->SetIs3dSorted(true);
2141 this->CalcDrawEtc(parent);
2143 TestOcclusionTrackerWithClip<typename Types::LayerType,
2144 typename Types::RenderSurfaceType> occlusion(
2145 gfx::Rect(0, 0, 1000, 1000));
2147 // This is very close to the camera, so pixels in its visible_content_rect()
2148 // will actually go outside of the layer's clip rect. Ensure that those
2149 // pixels don't occlude things outside the clip rect.
2150 this->VisitLayer(layer, &occlusion);
2151 this->EnterLayer(parent, &occlusion);
2152 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
2153 occlusion.occlusion_from_inside_target().ToString());
2154 EXPECT_EQ(gfx::Rect().ToString(),
2155 occlusion.occlusion_from_outside_target().ToString());
2159 // This test requires accumulating occlusion of 3d layers, which are skipped by
2160 // the occlusion tracker on the main thread. So this test should run on the impl
2162 IMPL_THREAD_TEST(OcclusionTrackerTestLargePixelsOccludeInsideClipRect);
2164 template <class Types>
2165 class OcclusionTrackerTestAnimationOpacity1OnMainThread
2166 : public OcclusionTrackerTest<Types> {
2168 explicit OcclusionTrackerTestAnimationOpacity1OnMainThread(bool opaque_layers)
2169 : OcclusionTrackerTest<Types>(opaque_layers) {}
2174 // | +--surface_child
2175 // | +--surface_child2
2179 typename Types::ContentLayerType* parent = this->CreateRoot(
2180 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
2181 typename Types::ContentLayerType* layer =
2182 this->CreateDrawingLayer(parent,
2183 this->identity_matrix,
2185 gfx::Size(300, 300),
2187 typename Types::ContentLayerType* surface =
2188 this->CreateDrawingSurface(parent,
2189 this->identity_matrix,
2191 gfx::Size(300, 300),
2193 typename Types::ContentLayerType* surface_child =
2194 this->CreateDrawingLayer(surface,
2195 this->identity_matrix,
2197 gfx::Size(200, 300),
2199 typename Types::ContentLayerType* surface_child2 =
2200 this->CreateDrawingLayer(surface,
2201 this->identity_matrix,
2203 gfx::Size(100, 300),
2205 typename Types::ContentLayerType* parent2 =
2206 this->CreateDrawingLayer(parent,
2207 this->identity_matrix,
2209 gfx::Size(300, 300),
2211 typename Types::ContentLayerType* topmost =
2212 this->CreateDrawingLayer(parent,
2213 this->identity_matrix,
2214 gfx::PointF(250.f, 0.f),
2218 AddOpacityTransitionToController(
2219 layer->layer_animation_controller(), 10.0, 0.f, 1.f, false);
2220 AddOpacityTransitionToController(
2221 surface->layer_animation_controller(), 10.0, 0.f, 1.f, false);
2222 this->CalcDrawEtc(parent);
2224 EXPECT_TRUE(layer->draw_opacity_is_animating());
2225 EXPECT_FALSE(surface->draw_opacity_is_animating());
2226 EXPECT_TRUE(surface->render_surface()->draw_opacity_is_animating());
2228 TestOcclusionTrackerWithClip<typename Types::LayerType,
2229 typename Types::RenderSurfaceType> occlusion(
2230 gfx::Rect(0, 0, 1000, 1000));
2232 this->VisitLayer(topmost, &occlusion);
2233 this->EnterLayer(parent2, &occlusion);
2234 // This occlusion will affect all surfaces.
2235 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2236 occlusion.occlusion_from_inside_target().ToString());
2237 EXPECT_EQ(gfx::Rect().ToString(),
2238 occlusion.occlusion_from_outside_target().ToString());
2239 EXPECT_EQ(gfx::Rect(0, 0, 250, 300).ToString(),
2240 occlusion.UnoccludedLayerContentRect(
2241 parent2, gfx::Rect(0, 0, 300, 300)).ToString());
2242 this->LeaveLayer(parent2, &occlusion);
2244 this->VisitLayer(surface_child2, &occlusion);
2245 this->EnterLayer(surface_child, &occlusion);
2246 EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(),
2247 occlusion.occlusion_from_inside_target().ToString());
2248 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2249 occlusion.occlusion_from_outside_target().ToString());
2250 EXPECT_RECT_EQ(gfx::Rect(100, 0, 100, 300),
2251 occlusion.UnoccludedLayerContentRect(
2252 surface_child, gfx::Rect(0, 0, 200, 300)));
2253 this->LeaveLayer(surface_child, &occlusion);
2254 this->EnterLayer(surface, &occlusion);
2255 EXPECT_EQ(gfx::Rect(0, 0, 200, 300).ToString(),
2256 occlusion.occlusion_from_inside_target().ToString());
2257 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2258 occlusion.occlusion_from_outside_target().ToString());
2259 EXPECT_RECT_EQ(gfx::Rect(200, 0, 50, 300),
2260 occlusion.UnoccludedLayerContentRect(
2261 surface, gfx::Rect(0, 0, 300, 300)));
2262 this->LeaveLayer(surface, &occlusion);
2264 this->EnterContributingSurface(surface, &occlusion);
2265 // Occlusion within the surface is lost when leaving the animating surface.
2266 EXPECT_EQ(gfx::Rect().ToString(),
2267 occlusion.occlusion_from_inside_target().ToString());
2268 EXPECT_EQ(gfx::Rect().ToString(),
2269 occlusion.occlusion_from_outside_target().ToString());
2270 EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
2271 occlusion.UnoccludedContributingSurfaceContentRect(
2272 surface, false, gfx::Rect(0, 0, 300, 300)));
2273 this->LeaveContributingSurface(surface, &occlusion);
2275 // Occlusion from outside the animating surface still exists.
2276 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2277 occlusion.occlusion_from_inside_target().ToString());
2278 EXPECT_EQ(gfx::Rect().ToString(),
2279 occlusion.occlusion_from_outside_target().ToString());
2281 this->VisitLayer(layer, &occlusion);
2282 this->EnterLayer(parent, &occlusion);
2284 // Occlusion is not added for the animating |layer|.
2285 EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
2286 occlusion.UnoccludedLayerContentRect(
2287 parent, gfx::Rect(0, 0, 300, 300)));
2291 MAIN_THREAD_TEST(OcclusionTrackerTestAnimationOpacity1OnMainThread);
2293 template <class Types>
2294 class OcclusionTrackerTestAnimationOpacity0OnMainThread
2295 : public OcclusionTrackerTest<Types> {
2297 explicit OcclusionTrackerTestAnimationOpacity0OnMainThread(bool opaque_layers)
2298 : OcclusionTrackerTest<Types>(opaque_layers) {}
2300 typename Types::ContentLayerType* parent = this->CreateRoot(
2301 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
2302 typename Types::ContentLayerType* layer =
2303 this->CreateDrawingLayer(parent,
2304 this->identity_matrix,
2306 gfx::Size(300, 300),
2308 typename Types::ContentLayerType* surface =
2309 this->CreateDrawingSurface(parent,
2310 this->identity_matrix,
2312 gfx::Size(300, 300),
2314 typename Types::ContentLayerType* surface_child =
2315 this->CreateDrawingLayer(surface,
2316 this->identity_matrix,
2318 gfx::Size(200, 300),
2320 typename Types::ContentLayerType* surface_child2 =
2321 this->CreateDrawingLayer(surface,
2322 this->identity_matrix,
2324 gfx::Size(100, 300),
2326 typename Types::ContentLayerType* parent2 =
2327 this->CreateDrawingLayer(parent,
2328 this->identity_matrix,
2330 gfx::Size(300, 300),
2332 typename Types::ContentLayerType* topmost =
2333 this->CreateDrawingLayer(parent,
2334 this->identity_matrix,
2335 gfx::PointF(250.f, 0.f),
2339 AddOpacityTransitionToController(
2340 layer->layer_animation_controller(), 10.0, 1.f, 0.f, false);
2341 AddOpacityTransitionToController(
2342 surface->layer_animation_controller(), 10.0, 1.f, 0.f, false);
2343 this->CalcDrawEtc(parent);
2345 EXPECT_TRUE(layer->draw_opacity_is_animating());
2346 EXPECT_FALSE(surface->draw_opacity_is_animating());
2347 EXPECT_TRUE(surface->render_surface()->draw_opacity_is_animating());
2349 TestOcclusionTrackerWithClip<typename Types::LayerType,
2350 typename Types::RenderSurfaceType> occlusion(
2351 gfx::Rect(0, 0, 1000, 1000));
2353 this->VisitLayer(topmost, &occlusion);
2354 this->EnterLayer(parent2, &occlusion);
2355 // This occlusion will affect all surfaces.
2356 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2357 occlusion.occlusion_from_inside_target().ToString());
2358 EXPECT_EQ(gfx::Rect().ToString(),
2359 occlusion.occlusion_from_outside_target().ToString());
2360 EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
2361 occlusion.UnoccludedLayerContentRect(
2362 parent, gfx::Rect(0, 0, 300, 300)));
2363 this->LeaveLayer(parent2, &occlusion);
2365 this->VisitLayer(surface_child2, &occlusion);
2366 this->EnterLayer(surface_child, &occlusion);
2367 EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(),
2368 occlusion.occlusion_from_inside_target().ToString());
2369 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2370 occlusion.occlusion_from_outside_target().ToString());
2371 EXPECT_RECT_EQ(gfx::Rect(100, 0, 100, 300),
2372 occlusion.UnoccludedLayerContentRect(
2373 surface_child, gfx::Rect(0, 0, 200, 300)));
2374 this->LeaveLayer(surface_child, &occlusion);
2375 this->EnterLayer(surface, &occlusion);
2376 EXPECT_EQ(gfx::Rect(0, 0, 200, 300).ToString(),
2377 occlusion.occlusion_from_inside_target().ToString());
2378 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2379 occlusion.occlusion_from_outside_target().ToString());
2380 EXPECT_RECT_EQ(gfx::Rect(200, 0, 50, 300),
2381 occlusion.UnoccludedLayerContentRect(
2382 surface, gfx::Rect(0, 0, 300, 300)));
2383 this->LeaveLayer(surface, &occlusion);
2385 this->EnterContributingSurface(surface, &occlusion);
2386 // Occlusion within the surface is lost when leaving the animating surface.
2387 EXPECT_EQ(gfx::Rect().ToString(),
2388 occlusion.occlusion_from_inside_target().ToString());
2389 EXPECT_EQ(gfx::Rect().ToString(),
2390 occlusion.occlusion_from_outside_target().ToString());
2391 EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
2392 occlusion.UnoccludedContributingSurfaceContentRect(
2393 surface, false, gfx::Rect(0, 0, 300, 300)));
2394 this->LeaveContributingSurface(surface, &occlusion);
2396 // Occlusion from outside the animating surface still exists.
2397 EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2398 occlusion.occlusion_from_inside_target().ToString());
2399 EXPECT_EQ(gfx::Rect().ToString(),
2400 occlusion.occlusion_from_outside_target().ToString());
2402 this->VisitLayer(layer, &occlusion);
2403 this->EnterLayer(parent, &occlusion);
2405 // Occlusion is not added for the animating |layer|.
2406 EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
2407 occlusion.UnoccludedLayerContentRect(
2408 parent, gfx::Rect(0, 0, 300, 300)));
2412 MAIN_THREAD_TEST(OcclusionTrackerTestAnimationOpacity0OnMainThread);
2414 template <class Types>
2415 class OcclusionTrackerTestAnimationTranslateOnMainThread
2416 : public OcclusionTrackerTest<Types> {
2418 explicit OcclusionTrackerTestAnimationTranslateOnMainThread(
2420 : OcclusionTrackerTest<Types>(opaque_layers) {}
2422 typename Types::ContentLayerType* parent = this->CreateRoot(
2423 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
2424 typename Types::ContentLayerType* layer =
2425 this->CreateDrawingLayer(parent,
2426 this->identity_matrix,
2428 gfx::Size(300, 300),
2430 typename Types::ContentLayerType* surface =
2431 this->CreateDrawingSurface(parent,
2432 this->identity_matrix,
2434 gfx::Size(300, 300),
2436 typename Types::ContentLayerType* surface_child =
2437 this->CreateDrawingLayer(surface,
2438 this->identity_matrix,
2440 gfx::Size(200, 300),
2442 typename Types::ContentLayerType* surface_child2 =
2443 this->CreateDrawingLayer(surface,
2444 this->identity_matrix,
2446 gfx::Size(100, 300),
2448 typename Types::ContentLayerType* surface2 = this->CreateDrawingSurface(
2449 parent, this->identity_matrix, gfx::PointF(), gfx::Size(50, 300), true);
2451 AddAnimatedTransformToController(
2452 layer->layer_animation_controller(), 10.0, 30, 0);
2453 AddAnimatedTransformToController(
2454 surface->layer_animation_controller(), 10.0, 30, 0);
2455 AddAnimatedTransformToController(
2456 surface_child->layer_animation_controller(), 10.0, 30, 0);
2457 this->CalcDrawEtc(parent);
2459 EXPECT_TRUE(layer->draw_transform_is_animating());
2460 EXPECT_TRUE(layer->screen_space_transform_is_animating());
2462 surface->render_surface()->target_surface_transforms_are_animating());
2464 surface->render_surface()->screen_space_transforms_are_animating());
2465 // The surface owning layer doesn't animate against its own surface.
2466 EXPECT_FALSE(surface->draw_transform_is_animating());
2467 EXPECT_TRUE(surface->screen_space_transform_is_animating());
2468 EXPECT_TRUE(surface_child->draw_transform_is_animating());
2469 EXPECT_TRUE(surface_child->screen_space_transform_is_animating());
2471 TestOcclusionTrackerWithClip<typename Types::LayerType,
2472 typename Types::RenderSurfaceType> occlusion(
2473 gfx::Rect(0, 0, 1000, 1000));
2475 this->VisitLayer(surface2, &occlusion);
2476 this->EnterContributingSurface(surface2, &occlusion);
2478 EXPECT_EQ(gfx::Rect(0, 0, 50, 300).ToString(),
2479 occlusion.occlusion_from_inside_target().ToString());
2481 this->LeaveContributingSurface(surface2, &occlusion);
2482 this->EnterLayer(surface_child2, &occlusion);
2484 // surface_child2 is moving in screen space but not relative to its target,
2485 // so occlusion should happen in its target space only. It also means that
2486 // things occluding from outside the target (e.g. surface2) cannot occlude
2488 EXPECT_EQ(gfx::Rect().ToString(),
2489 occlusion.occlusion_from_outside_target().ToString());
2491 EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 300),
2492 occlusion.UnoccludedLayerContentRect(
2493 surface_child2, gfx::Rect(0, 0, 100, 300)));
2495 occlusion.OccludedLayer(surface_child, gfx::Rect(0, 0, 50, 300)));
2497 this->LeaveLayer(surface_child2, &occlusion);
2498 this->EnterLayer(surface_child, &occlusion);
2500 occlusion.OccludedLayer(surface_child, gfx::Rect(0, 0, 100, 300)));
2501 EXPECT_EQ(gfx::Rect().ToString(),
2502 occlusion.occlusion_from_outside_target().ToString());
2503 EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(),
2504 occlusion.occlusion_from_inside_target().ToString());
2505 EXPECT_RECT_EQ(gfx::Rect(100, 0, 200, 300),
2506 occlusion.UnoccludedLayerContentRect(
2507 surface, gfx::Rect(0, 0, 300, 300)));
2509 // The surface_child is occluded by the surface_child2, but is moving
2510 // relative its target, so it can't be occluded.
2511 EXPECT_RECT_EQ(gfx::Rect(0, 0, 200, 300),
2512 occlusion.UnoccludedLayerContentRect(
2513 surface_child, gfx::Rect(0, 0, 200, 300)));
2515 occlusion.OccludedLayer(surface_child, gfx::Rect(0, 0, 50, 300)));
2517 this->LeaveLayer(surface_child, &occlusion);
2518 this->EnterLayer(surface, &occlusion);
2519 // The surface_child is moving in screen space but not relative to its
2520 // target, so occlusion should happen from within the target only.
2521 EXPECT_EQ(gfx::Rect().ToString(),
2522 occlusion.occlusion_from_outside_target().ToString());
2523 EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(),
2524 occlusion.occlusion_from_inside_target().ToString());
2525 EXPECT_RECT_EQ(gfx::Rect(100, 0, 200, 300),
2526 occlusion.UnoccludedLayerContentRect(
2527 surface, gfx::Rect(0, 0, 300, 300)));
2529 this->LeaveLayer(surface, &occlusion);
2530 // The surface's owning layer is moving in screen space but not relative to
2531 // its target, so occlusion should happen within the target only.
2532 EXPECT_EQ(gfx::Rect().ToString(),
2533 occlusion.occlusion_from_outside_target().ToString());
2534 EXPECT_EQ(gfx::Rect(0, 0, 300, 300).ToString(),
2535 occlusion.occlusion_from_inside_target().ToString());
2536 EXPECT_RECT_EQ(gfx::Rect(0, 0, 0, 0),
2537 occlusion.UnoccludedLayerContentRect(
2538 surface, gfx::Rect(0, 0, 300, 300)));
2540 this->EnterContributingSurface(surface, &occlusion);
2541 // The contributing |surface| is animating so it can't be occluded.
2542 EXPECT_RECT_EQ(gfx::Rect(0, 0, 300, 300),
2543 occlusion.UnoccludedContributingSurfaceContentRect(
2544 surface, false, gfx::Rect(0, 0, 300, 300)));
2545 this->LeaveContributingSurface(surface, &occlusion);
2547 this->EnterLayer(layer, &occlusion);
2548 // The |surface| is moving in the screen and in its target, so all occlusion
2549 // within the surface is lost when leaving it.
2550 EXPECT_RECT_EQ(gfx::Rect(50, 0, 250, 300),
2551 occlusion.UnoccludedLayerContentRect(
2552 parent, gfx::Rect(0, 0, 300, 300)));
2553 this->LeaveLayer(layer, &occlusion);
2555 this->EnterLayer(parent, &occlusion);
2556 // The |layer| is animating in the screen and in its target, so no occlusion
2558 EXPECT_RECT_EQ(gfx::Rect(50, 0, 250, 300),
2559 occlusion.UnoccludedLayerContentRect(
2560 parent, gfx::Rect(0, 0, 300, 300)));
2564 MAIN_THREAD_TEST(OcclusionTrackerTestAnimationTranslateOnMainThread);
2566 template <class Types>
2567 class OcclusionTrackerTestSurfaceOcclusionTranslatesToParent
2568 : public OcclusionTrackerTest<Types> {
2570 explicit OcclusionTrackerTestSurfaceOcclusionTranslatesToParent(
2572 : OcclusionTrackerTest<Types>(opaque_layers) {}
2574 gfx::Transform surface_transform;
2575 surface_transform.Translate(300.0, 300.0);
2576 surface_transform.Scale(2.0, 2.0);
2577 surface_transform.Translate(-150.0, -150.0);
2579 typename Types::ContentLayerType* parent = this->CreateRoot(
2580 this->identity_matrix, gfx::PointF(), gfx::Size(500, 500));
2581 typename Types::ContentLayerType* surface = this->CreateDrawingSurface(
2582 parent, surface_transform, gfx::PointF(), gfx::Size(300, 300), false);
2583 typename Types::ContentLayerType* surface2 =
2584 this->CreateDrawingSurface(parent,
2585 this->identity_matrix,
2586 gfx::PointF(50.f, 50.f),
2587 gfx::Size(300, 300),
2589 surface->SetOpaqueContentsRect(gfx::Rect(0, 0, 200, 200));
2590 surface2->SetOpaqueContentsRect(gfx::Rect(0, 0, 200, 200));
2591 this->CalcDrawEtc(parent);
2593 TestOcclusionTrackerWithClip<typename Types::LayerType,
2594 typename Types::RenderSurfaceType> occlusion(
2595 gfx::Rect(0, 0, 1000, 1000));
2597 this->VisitLayer(surface2, &occlusion);
2598 this->VisitContributingSurface(surface2, &occlusion);
2600 EXPECT_EQ(gfx::Rect().ToString(),
2601 occlusion.occlusion_from_outside_target().ToString());
2602 EXPECT_EQ(gfx::Rect(50, 50, 200, 200).ToString(),
2603 occlusion.occlusion_from_inside_target().ToString());
2605 // Clear any stored occlusion.
2606 occlusion.set_occlusion_from_outside_target(Region());
2607 occlusion.set_occlusion_from_inside_target(Region());
2609 this->VisitLayer(surface, &occlusion);
2610 this->VisitContributingSurface(surface, &occlusion);
2612 EXPECT_EQ(gfx::Rect().ToString(),
2613 occlusion.occlusion_from_outside_target().ToString());
2614 EXPECT_EQ(gfx::Rect(0, 0, 400, 400).ToString(),
2615 occlusion.occlusion_from_inside_target().ToString());
2619 MAIN_AND_IMPL_THREAD_TEST(
2620 OcclusionTrackerTestSurfaceOcclusionTranslatesToParent);
2622 template <class Types>
2623 class OcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping
2624 : public OcclusionTrackerTest<Types> {
2626 explicit OcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping(
2628 : OcclusionTrackerTest<Types>(opaque_layers) {}
2630 typename Types::ContentLayerType* parent = this->CreateRoot(
2631 this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
2632 parent->SetMasksToBounds(true);
2633 typename Types::ContentLayerType* surface =
2634 this->CreateDrawingSurface(parent,
2635 this->identity_matrix,
2637 gfx::Size(500, 300),
2639 surface->SetOpaqueContentsRect(gfx::Rect(0, 0, 400, 200));
2640 this->CalcDrawEtc(parent);
2642 TestOcclusionTrackerWithClip<typename Types::LayerType,
2643 typename Types::RenderSurfaceType> occlusion(
2644 gfx::Rect(0, 0, 1000, 1000));
2646 this->VisitLayer(surface, &occlusion);
2647 this->VisitContributingSurface(surface, &occlusion);
2649 EXPECT_EQ(gfx::Rect().ToString(),
2650 occlusion.occlusion_from_outside_target().ToString());
2651 EXPECT_EQ(gfx::Rect(0, 0, 300, 200).ToString(),
2652 occlusion.occlusion_from_inside_target().ToString());
2656 MAIN_AND_IMPL_THREAD_TEST(
2657 OcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping);
2659 template <class Types>
2660 class OcclusionTrackerTestReplicaOccluded : public OcclusionTrackerTest<Types> {
2662 explicit OcclusionTrackerTestReplicaOccluded(bool opaque_layers)
2663 : OcclusionTrackerTest<Types>(opaque_layers) {}
2665 typename Types::ContentLayerType* parent = this->CreateRoot(
2666 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
2667 typename Types::LayerType* surface =
2668 this->CreateDrawingSurface(parent,
2669 this->identity_matrix,
2671 gfx::Size(100, 100),
2673 this->CreateReplicaLayer(surface,
2674 this->identity_matrix,
2675 gfx::PointF(0.f, 100.f),
2676 gfx::Size(100, 100));
2677 typename Types::LayerType* topmost =
2678 this->CreateDrawingLayer(parent,
2679 this->identity_matrix,
2680 gfx::PointF(0.f, 100.f),
2681 gfx::Size(100, 100),
2683 this->CalcDrawEtc(parent);
2685 TestOcclusionTrackerWithClip<typename Types::LayerType,
2686 typename Types::RenderSurfaceType> occlusion(
2687 gfx::Rect(0, 0, 1000, 1000));
2689 // |topmost| occludes the replica, but not the surface itself.
2690 this->VisitLayer(topmost, &occlusion);
2692 EXPECT_EQ(gfx::Rect().ToString(),
2693 occlusion.occlusion_from_outside_target().ToString());
2694 EXPECT_EQ(gfx::Rect(0, 100, 100, 100).ToString(),
2695 occlusion.occlusion_from_inside_target().ToString());
2697 this->VisitLayer(surface, &occlusion);
2699 // Render target with replica ignores occlusion from outside.
2700 EXPECT_EQ(gfx::Rect().ToString(),
2701 occlusion.occlusion_from_outside_target().ToString());
2702 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
2703 occlusion.occlusion_from_inside_target().ToString());
2705 this->EnterContributingSurface(surface, &occlusion);
2707 // Surface is not occluded so it shouldn't think it is.
2708 EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 100),
2709 occlusion.UnoccludedContributingSurfaceContentRect(
2710 surface, false, gfx::Rect(0, 0, 100, 100)));
2714 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaOccluded);
2716 template <class Types>
2717 class OcclusionTrackerTestSurfaceWithReplicaUnoccluded
2718 : public OcclusionTrackerTest<Types> {
2720 explicit OcclusionTrackerTestSurfaceWithReplicaUnoccluded(bool opaque_layers)
2721 : OcclusionTrackerTest<Types>(opaque_layers) {}
2723 typename Types::ContentLayerType* parent = this->CreateRoot(
2724 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
2725 typename Types::LayerType* surface =
2726 this->CreateDrawingSurface(parent,
2727 this->identity_matrix,
2729 gfx::Size(100, 100),
2731 this->CreateReplicaLayer(surface,
2732 this->identity_matrix,
2733 gfx::PointF(0.f, 100.f),
2734 gfx::Size(100, 100));
2735 typename Types::LayerType* topmost =
2736 this->CreateDrawingLayer(parent,
2737 this->identity_matrix,
2739 gfx::Size(100, 110),
2741 this->CalcDrawEtc(parent);
2743 TestOcclusionTrackerWithClip<typename Types::LayerType,
2744 typename Types::RenderSurfaceType> occlusion(
2745 gfx::Rect(0, 0, 1000, 1000));
2747 // |topmost| occludes the surface, but not the entire surface's replica.
2748 this->VisitLayer(topmost, &occlusion);
2750 EXPECT_EQ(gfx::Rect().ToString(),
2751 occlusion.occlusion_from_outside_target().ToString());
2752 EXPECT_EQ(gfx::Rect(0, 0, 100, 110).ToString(),
2753 occlusion.occlusion_from_inside_target().ToString());
2755 this->VisitLayer(surface, &occlusion);
2757 // Render target with replica ignores occlusion from outside.
2758 EXPECT_EQ(gfx::Rect().ToString(),
2759 occlusion.occlusion_from_outside_target().ToString());
2760 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
2761 occlusion.occlusion_from_inside_target().ToString());
2763 this->EnterContributingSurface(surface, &occlusion);
2765 // Surface is occluded, but only the top 10px of the replica.
2766 EXPECT_RECT_EQ(gfx::Rect(0, 0, 0, 0),
2767 occlusion.UnoccludedContributingSurfaceContentRect(
2768 surface, false, gfx::Rect(0, 0, 100, 100)));
2769 EXPECT_RECT_EQ(gfx::Rect(0, 10, 100, 90),
2770 occlusion.UnoccludedContributingSurfaceContentRect(
2771 surface, true, gfx::Rect(0, 0, 100, 100)));
2775 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceWithReplicaUnoccluded);
2777 template <class Types>
2778 class OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently
2779 : public OcclusionTrackerTest<Types> {
2781 explicit OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently(
2783 : OcclusionTrackerTest<Types>(opaque_layers) {}
2785 typename Types::ContentLayerType* parent = this->CreateRoot(
2786 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
2787 typename Types::LayerType* surface =
2788 this->CreateDrawingSurface(parent,
2789 this->identity_matrix,
2791 gfx::Size(100, 100),
2793 this->CreateReplicaLayer(surface,
2794 this->identity_matrix,
2795 gfx::PointF(0.f, 100.f),
2796 gfx::Size(100, 100));
2797 typename Types::LayerType* over_surface = this->CreateDrawingLayer(
2798 parent, this->identity_matrix, gfx::PointF(), gfx::Size(40, 100), true);
2799 typename Types::LayerType* over_replica =
2800 this->CreateDrawingLayer(parent,
2801 this->identity_matrix,
2802 gfx::PointF(0.f, 100.f),
2805 this->CalcDrawEtc(parent);
2807 TestOcclusionTrackerWithClip<typename Types::LayerType,
2808 typename Types::RenderSurfaceType> occlusion(
2809 gfx::Rect(0, 0, 1000, 1000));
2811 // These occlude the surface and replica differently, so we can test each
2813 this->VisitLayer(over_replica, &occlusion);
2814 this->VisitLayer(over_surface, &occlusion);
2816 EXPECT_EQ(gfx::Rect().ToString(),
2817 occlusion.occlusion_from_outside_target().ToString());
2818 EXPECT_EQ(UnionRegions(gfx::Rect(0, 0, 40, 100), gfx::Rect(0, 100, 50, 100))
2820 occlusion.occlusion_from_inside_target().ToString());
2822 this->VisitLayer(surface, &occlusion);
2824 // Render target with replica ignores occlusion from outside.
2825 EXPECT_EQ(gfx::Rect().ToString(),
2826 occlusion.occlusion_from_outside_target().ToString());
2827 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
2828 occlusion.occlusion_from_inside_target().ToString());
2830 this->EnterContributingSurface(surface, &occlusion);
2832 // Surface and replica are occluded different amounts.
2833 EXPECT_RECT_EQ(gfx::Rect(40, 0, 60, 100),
2834 occlusion.UnoccludedContributingSurfaceContentRect(
2835 surface, false, gfx::Rect(0, 0, 100, 100)));
2836 EXPECT_RECT_EQ(gfx::Rect(50, 0, 50, 100),
2837 occlusion.UnoccludedContributingSurfaceContentRect(
2838 surface, true, gfx::Rect(0, 0, 100, 100)));
2842 ALL_OCCLUSIONTRACKER_TEST(
2843 OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently);
2845 template <class Types>
2846 class OcclusionTrackerTestSurfaceChildOfSurface
2847 : public OcclusionTrackerTest<Types> {
2849 explicit OcclusionTrackerTestSurfaceChildOfSurface(bool opaque_layers)
2850 : OcclusionTrackerTest<Types>(opaque_layers) {}
2852 // This test verifies that the surface cliprect does not end up empty and
2853 // clip away the entire unoccluded rect.
2855 typename Types::ContentLayerType* parent = this->CreateRoot(
2856 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
2857 typename Types::LayerType* surface =
2858 this->CreateDrawingSurface(parent,
2859 this->identity_matrix,
2861 gfx::Size(100, 100),
2863 typename Types::LayerType* surface_child =
2864 this->CreateDrawingSurface(surface,
2865 this->identity_matrix,
2866 gfx::PointF(0.f, 10.f),
2869 typename Types::LayerType* topmost = this->CreateDrawingLayer(
2870 parent, this->identity_matrix, gfx::PointF(), gfx::Size(100, 50), true);
2871 this->CalcDrawEtc(parent);
2873 TestOcclusionTrackerWithClip<typename Types::LayerType,
2874 typename Types::RenderSurfaceType> occlusion(
2875 gfx::Rect(-100, -100, 1000, 1000));
2877 // |topmost| occludes everything partially so we know occlusion is happening
2879 this->VisitLayer(topmost, &occlusion);
2881 EXPECT_EQ(gfx::Rect().ToString(),
2882 occlusion.occlusion_from_outside_target().ToString());
2883 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
2884 occlusion.occlusion_from_inside_target().ToString());
2886 this->VisitLayer(surface_child, &occlusion);
2888 // surface_child increases the occlusion in the screen by a narrow sliver.
2889 EXPECT_EQ(gfx::Rect(0, -10, 100, 50).ToString(),
2890 occlusion.occlusion_from_outside_target().ToString());
2891 // In its own surface, surface_child is at 0,0 as is its occlusion.
2892 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
2893 occlusion.occlusion_from_inside_target().ToString());
2895 // The root layer always has a clip rect. So the parent of |surface| has a
2896 // clip rect. However, the owning layer for |surface| does not mask to
2897 // bounds, so it doesn't have a clip rect of its own. Thus the parent of
2898 // |surface_child| exercises different code paths as its parent does not
2899 // have a clip rect.
2901 this->EnterContributingSurface(surface_child, &occlusion);
2902 // The surface_child's parent does not have a clip rect as it owns a render
2903 // surface. Make sure the unoccluded rect does not get clipped away
2905 EXPECT_RECT_EQ(gfx::Rect(0, 40, 100, 10),
2906 occlusion.UnoccludedContributingSurfaceContentRect(
2907 surface_child, false, gfx::Rect(0, 0, 100, 50)));
2908 this->LeaveContributingSurface(surface_child, &occlusion);
2910 // When the surface_child's occlusion is transformed up to its parent, make
2911 // sure it is not clipped away inappropriately also.
2912 this->EnterLayer(surface, &occlusion);
2913 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
2914 occlusion.occlusion_from_outside_target().ToString());
2915 EXPECT_EQ(gfx::Rect(0, 10, 100, 50).ToString(),
2916 occlusion.occlusion_from_inside_target().ToString());
2917 this->LeaveLayer(surface, &occlusion);
2919 this->EnterContributingSurface(surface, &occlusion);
2920 // The surface's parent does have a clip rect as it is the root layer.
2921 EXPECT_RECT_EQ(gfx::Rect(0, 50, 100, 50),
2922 occlusion.UnoccludedContributingSurfaceContentRect(
2923 surface, false, gfx::Rect(0, 0, 100, 100)));
2927 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceChildOfSurface);
2929 template <class Types>
2930 class OcclusionTrackerTestTopmostSurfaceIsClippedToViewport
2931 : public OcclusionTrackerTest<Types> {
2933 explicit OcclusionTrackerTestTopmostSurfaceIsClippedToViewport(
2935 : OcclusionTrackerTest<Types>(opaque_layers) {}
2937 // This test verifies that the top-most surface is considered occluded
2938 // outside of its target's clip rect and outside the viewport rect.
2940 typename Types::ContentLayerType* parent = this->CreateRoot(
2941 this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
2942 typename Types::LayerType* surface =
2943 this->CreateDrawingSurface(parent,
2944 this->identity_matrix,
2946 gfx::Size(100, 300),
2948 this->CalcDrawEtc(parent);
2950 // Make a viewport rect that is larger than the root layer.
2951 TestOcclusionTrackerWithClip<typename Types::LayerType,
2952 typename Types::RenderSurfaceType> occlusion(
2953 gfx::Rect(0, 0, 1000, 1000));
2955 this->VisitLayer(surface, &occlusion);
2957 // The root layer always has a clip rect. So the parent of |surface| has a
2958 // clip rect giving the surface itself a clip rect.
2959 this->EnterContributingSurface(surface, &occlusion);
2960 // Make sure the parent's clip rect clips the unoccluded region of the
2962 EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 200),
2963 occlusion.UnoccludedContributingSurfaceContentRect(
2964 surface, false, gfx::Rect(0, 0, 100, 300)));
2966 this->ResetLayerIterator();
2968 // Make a viewport rect that is smaller than the root layer.
2969 TestOcclusionTrackerWithClip<typename Types::LayerType,
2970 typename Types::RenderSurfaceType> occlusion(
2971 gfx::Rect(0, 0, 100, 100));
2973 this->VisitLayer(surface, &occlusion);
2975 // The root layer always has a clip rect. So the parent of |surface| has a
2976 // clip rect giving the surface itself a clip rect.
2977 this->EnterContributingSurface(surface, &occlusion);
2978 // Make sure the viewport rect clips the unoccluded region of the child
2980 EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 100),
2981 occlusion.UnoccludedContributingSurfaceContentRect(
2982 surface, false, gfx::Rect(0, 0, 100, 300)));
2987 ALL_OCCLUSIONTRACKER_TEST(
2988 OcclusionTrackerTestTopmostSurfaceIsClippedToViewport);
2990 template <class Types>
2991 class OcclusionTrackerTestSurfaceChildOfClippingSurface
2992 : public OcclusionTrackerTest<Types> {
2994 explicit OcclusionTrackerTestSurfaceChildOfClippingSurface(bool opaque_layers)
2995 : OcclusionTrackerTest<Types>(opaque_layers) {}
2997 // This test verifies that the surface cliprect does not end up empty and
2998 // clip away the entire unoccluded rect.
3000 typename Types::ContentLayerType* parent = this->CreateRoot(
3001 this->identity_matrix, gfx::PointF(), gfx::Size(80, 200));
3002 parent->SetMasksToBounds(true);
3003 typename Types::LayerType* surface =
3004 this->CreateDrawingSurface(parent,
3005 this->identity_matrix,
3007 gfx::Size(100, 100),
3009 typename Types::LayerType* surface_child =
3010 this->CreateDrawingSurface(surface,
3011 this->identity_matrix,
3013 gfx::Size(100, 100),
3015 typename Types::LayerType* topmost = this->CreateDrawingLayer(
3016 parent, this->identity_matrix, gfx::PointF(), gfx::Size(100, 50), true);
3017 this->CalcDrawEtc(parent);
3019 TestOcclusionTrackerWithClip<typename Types::LayerType,
3020 typename Types::RenderSurfaceType> occlusion(
3021 gfx::Rect(0, 0, 1000, 1000));
3023 // |topmost| occludes everything partially so we know occlusion is happening
3025 this->VisitLayer(topmost, &occlusion);
3027 EXPECT_EQ(gfx::Rect().ToString(),
3028 occlusion.occlusion_from_outside_target().ToString());
3029 EXPECT_EQ(gfx::Rect(0, 0, 80, 50).ToString(),
3030 occlusion.occlusion_from_inside_target().ToString());
3032 // surface_child is not opaque and does not occlude, so we have a non-empty
3033 // unoccluded area on surface.
3034 this->VisitLayer(surface_child, &occlusion);
3036 EXPECT_EQ(gfx::Rect(0, 0, 80, 50).ToString(),
3037 occlusion.occlusion_from_outside_target().ToString());
3038 EXPECT_EQ(gfx::Rect(0, 0, 0, 0).ToString(),
3039 occlusion.occlusion_from_inside_target().ToString());
3041 // The root layer always has a clip rect. So the parent of |surface| has a
3042 // clip rect. However, the owning layer for |surface| does not mask to
3043 // bounds, so it doesn't have a clip rect of its own. Thus the parent of
3044 // |surface_child| exercises different code paths as its parent does not
3045 // have a clip rect.
3047 this->EnterContributingSurface(surface_child, &occlusion);
3048 // The surface_child's parent does not have a clip rect as it owns a render
3051 gfx::Rect(0, 50, 80, 50).ToString(),
3052 occlusion.UnoccludedContributingSurfaceContentRect(
3053 surface_child, false, gfx::Rect(0, 0, 100, 100)).ToString());
3054 this->LeaveContributingSurface(surface_child, &occlusion);
3056 this->VisitLayer(surface, &occlusion);
3057 this->EnterContributingSurface(surface, &occlusion);
3058 // The surface's parent does have a clip rect as it is the root layer.
3059 EXPECT_EQ(gfx::Rect(0, 50, 80, 50).ToString(),
3060 occlusion.UnoccludedContributingSurfaceContentRect(
3061 surface, false, gfx::Rect(0, 0, 100, 100)).ToString());
3065 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceChildOfClippingSurface);
3067 template <class Types>
3068 class OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter
3069 : public OcclusionTrackerTest<Types> {
3071 explicit OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter(
3073 : OcclusionTrackerTest<Types>(opaque_layers) {}
3075 gfx::Transform scale_by_half;
3076 scale_by_half.Scale(0.5, 0.5);
3078 // Make a 50x50 filtered surface that is completely surrounded by opaque
3079 // layers which are above it in the z-order. The surface is scaled to test
3080 // that the pixel moving is done in the target space, where the background
3081 // filter is applied.
3082 typename Types::ContentLayerType* parent = this->CreateRoot(
3083 this->identity_matrix, gfx::PointF(), gfx::Size(200, 150));
3084 typename Types::LayerType* filtered_surface =
3085 this->CreateDrawingLayer(parent,
3087 gfx::PointF(50.f, 50.f),
3088 gfx::Size(100, 100),
3090 typename Types::LayerType* occluding_layer1 = this->CreateDrawingLayer(
3091 parent, this->identity_matrix, gfx::PointF(), gfx::Size(200, 50), true);
3092 typename Types::LayerType* occluding_layer2 =
3093 this->CreateDrawingLayer(parent,
3094 this->identity_matrix,
3095 gfx::PointF(0.f, 100.f),
3098 typename Types::LayerType* occluding_layer3 =
3099 this->CreateDrawingLayer(parent,
3100 this->identity_matrix,
3101 gfx::PointF(0.f, 50.f),
3104 typename Types::LayerType* occluding_layer4 =
3105 this->CreateDrawingLayer(parent,
3106 this->identity_matrix,
3107 gfx::PointF(100.f, 50.f),
3111 // Filters make the layer own a surface.
3112 FilterOperations filters;
3113 filters.Append(FilterOperation::CreateBlurFilter(10.f));
3114 filtered_surface->SetBackgroundFilters(filters);
3116 // Save the distance of influence for the blur effect.
3117 int outset_top, outset_right, outset_bottom, outset_left;
3119 &outset_top, &outset_right, &outset_bottom, &outset_left);
3121 this->CalcDrawEtc(parent);
3123 TestOcclusionTrackerWithClip<typename Types::LayerType,
3124 typename Types::RenderSurfaceType> occlusion(
3125 gfx::Rect(0, 0, 1000, 1000));
3127 // These layers occlude pixels directly beside the filtered_surface. Because
3128 // filtered surface blends pixels in a radius, it will need to see some of
3129 // the pixels (up to radius far) underneath the occluding layers.
3130 this->VisitLayer(occluding_layer4, &occlusion);
3131 this->VisitLayer(occluding_layer3, &occlusion);
3132 this->VisitLayer(occluding_layer2, &occlusion);
3133 this->VisitLayer(occluding_layer1, &occlusion);
3135 Region expected_occlusion;
3136 expected_occlusion.Union(gfx::Rect(0, 0, 200, 50));
3137 expected_occlusion.Union(gfx::Rect(0, 50, 50, 50));
3138 expected_occlusion.Union(gfx::Rect(100, 50, 100, 50));
3139 expected_occlusion.Union(gfx::Rect(0, 100, 200, 50));
3141 EXPECT_EQ(expected_occlusion.ToString(),
3142 occlusion.occlusion_from_inside_target().ToString());
3143 EXPECT_EQ(gfx::Rect().ToString(),
3144 occlusion.occlusion_from_outside_target().ToString());
3146 this->VisitLayer(filtered_surface, &occlusion);
3148 // The filtered layer does not occlude.
3149 Region expected_occlusion_outside_surface;
3150 expected_occlusion_outside_surface.Union(gfx::Rect(-50, -50, 200, 50));
3151 expected_occlusion_outside_surface.Union(gfx::Rect(-50, 0, 50, 50));
3152 expected_occlusion_outside_surface.Union(gfx::Rect(50, 0, 100, 50));
3153 expected_occlusion_outside_surface.Union(gfx::Rect(-50, 50, 200, 50));
3155 EXPECT_EQ(expected_occlusion_outside_surface.ToString(),
3156 occlusion.occlusion_from_outside_target().ToString());
3157 EXPECT_EQ(gfx::Rect().ToString(),
3158 occlusion.occlusion_from_inside_target().ToString());
3160 // The surface has a background blur, so it needs pixels that are currently
3161 // considered occluded in order to be drawn. So the pixels it needs should
3162 // be removed some the occluded area so that when we get to the parent they
3164 this->VisitContributingSurface(filtered_surface, &occlusion);
3166 this->EnterLayer(parent, &occlusion);
3168 Region expected_blurred_occlusion;
3169 expected_blurred_occlusion.Union(gfx::Rect(0, 0, 200, 50 - outset_top));
3170 expected_blurred_occlusion.Union(gfx::Rect(
3171 0, 50 - outset_top, 50 - outset_left, 50 + outset_top + outset_bottom));
3172 expected_blurred_occlusion.Union(
3173 gfx::Rect(100 + outset_right,
3176 50 + outset_top + outset_bottom));
3177 expected_blurred_occlusion.Union(
3178 gfx::Rect(0, 100 + outset_bottom, 200, 50 - outset_bottom));
3180 EXPECT_EQ(expected_blurred_occlusion.ToString(),
3181 occlusion.occlusion_from_inside_target().ToString());
3182 EXPECT_EQ(gfx::Rect().ToString(),
3183 occlusion.occlusion_from_outside_target().ToString());
3185 gfx::Rect outset_rect;
3186 gfx::Rect test_rect;
3188 // Nothing in the blur outsets for the filtered_surface is occluded.
3189 outset_rect = gfx::Rect(50 - outset_left,
3191 50 + outset_left + outset_right,
3192 50 + outset_top + outset_bottom);
3193 test_rect = outset_rect;
3195 outset_rect.ToString(),
3196 occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
3198 // Stuff outside the blur outsets is still occluded though.
3199 test_rect = outset_rect;
3200 test_rect.Inset(0, 0, -1, 0);
3202 outset_rect.ToString(),
3203 occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
3204 test_rect = outset_rect;
3205 test_rect.Inset(0, 0, 0, -1);
3207 outset_rect.ToString(),
3208 occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
3209 test_rect = outset_rect;
3210 test_rect.Inset(-1, 0, 0, 0);
3212 outset_rect.ToString(),
3213 occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
3214 test_rect = outset_rect;
3215 test_rect.Inset(0, -1, 0, 0);
3217 outset_rect.ToString(),
3218 occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
3222 ALL_OCCLUSIONTRACKER_TEST(
3223 OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter);
3225 template <class Types>
3226 class OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice
3227 : public OcclusionTrackerTest<Types> {
3229 explicit OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice(
3231 : OcclusionTrackerTest<Types>(opaque_layers) {}
3233 gfx::Transform scale_by_half;
3234 scale_by_half.Scale(0.5, 0.5);
3236 // Makes two surfaces that completely cover |parent|. The occlusion both
3237 // above and below the filters will be reduced by each of them.
3238 typename Types::ContentLayerType* root = this->CreateRoot(
3239 this->identity_matrix, gfx::PointF(), gfx::Size(75, 75));
3240 typename Types::LayerType* parent = this->CreateSurface(
3241 root, scale_by_half, gfx::PointF(), gfx::Size(150, 150));
3242 parent->SetMasksToBounds(true);
3243 typename Types::LayerType* filtered_surface1 = this->CreateDrawingLayer(
3244 parent, scale_by_half, gfx::PointF(), gfx::Size(300, 300), false);
3245 typename Types::LayerType* filtered_surface2 = this->CreateDrawingLayer(
3246 parent, scale_by_half, gfx::PointF(), gfx::Size(300, 300), false);
3247 typename Types::LayerType* occluding_layer_above =
3248 this->CreateDrawingLayer(parent,
3249 this->identity_matrix,
3250 gfx::PointF(100.f, 100.f),
3254 // Filters make the layers own surfaces.
3255 FilterOperations filters;
3256 filters.Append(FilterOperation::CreateBlurFilter(1.f));
3257 filtered_surface1->SetBackgroundFilters(filters);
3258 filtered_surface2->SetBackgroundFilters(filters);
3260 // Save the distance of influence for the blur effect.
3261 int outset_top, outset_right, outset_bottom, outset_left;
3263 &outset_top, &outset_right, &outset_bottom, &outset_left);
3265 this->CalcDrawEtc(root);
3267 TestOcclusionTrackerWithClip<typename Types::LayerType,
3268 typename Types::RenderSurfaceType> occlusion(
3269 gfx::Rect(0, 0, 1000, 1000));
3271 this->VisitLayer(occluding_layer_above, &occlusion);
3272 EXPECT_EQ(gfx::Rect().ToString(),
3273 occlusion.occlusion_from_outside_target().ToString());
3274 EXPECT_EQ(gfx::Rect(100 / 2, 100 / 2, 50 / 2, 50 / 2).ToString(),
3275 occlusion.occlusion_from_inside_target().ToString());
3277 this->VisitLayer(filtered_surface2, &occlusion);
3278 this->VisitContributingSurface(filtered_surface2, &occlusion);
3279 this->VisitLayer(filtered_surface1, &occlusion);
3280 this->VisitContributingSurface(filtered_surface1, &occlusion);
3282 // Test expectations in the target.
3283 gfx::Rect expected_occlusion =
3284 gfx::Rect(100 / 2 + outset_right * 2,
3285 100 / 2 + outset_bottom * 2,
3286 50 / 2 - (outset_left + outset_right) * 2,
3287 50 / 2 - (outset_top + outset_bottom) * 2);
3288 EXPECT_EQ(expected_occlusion.ToString(),
3289 occlusion.occlusion_from_inside_target().ToString());
3291 // Test expectations in the screen are the same as in the target, as the
3292 // render surface is 1:1 with the screen.
3293 EXPECT_EQ(expected_occlusion.ToString(),
3294 occlusion.occlusion_from_outside_target().ToString());
3298 ALL_OCCLUSIONTRACKER_TEST(
3299 OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice);
3301 template <class Types>
3302 class OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter
3303 : public OcclusionTrackerTest<Types> {
3305 explicit OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter(
3307 : OcclusionTrackerTest<Types>(opaque_layers) {}
3309 gfx::Transform scale_by_half;
3310 scale_by_half.Scale(0.5, 0.5);
3312 // Make a surface and its replica, each 50x50, with a smaller 30x30 layer
3313 // centered below each. The surface is scaled to test that the pixel moving
3314 // is done in the target space, where the background filter is applied, but
3315 // the surface appears at 50, 50 and the replica at 200, 50.
3316 typename Types::ContentLayerType* parent = this->CreateRoot(
3317 this->identity_matrix, gfx::PointF(), gfx::Size(300, 150));
3318 typename Types::LayerType* behind_surface_layer =
3319 this->CreateDrawingLayer(parent,
3320 this->identity_matrix,
3321 gfx::PointF(60.f, 60.f),
3324 typename Types::LayerType* behind_replica_layer =
3325 this->CreateDrawingLayer(parent,
3326 this->identity_matrix,
3327 gfx::PointF(210.f, 60.f),
3330 typename Types::LayerType* filtered_surface =
3331 this->CreateDrawingLayer(parent,
3333 gfx::PointF(50.f, 50.f),
3334 gfx::Size(100, 100),
3336 this->CreateReplicaLayer(filtered_surface,
3337 this->identity_matrix,
3338 gfx::PointF(300.f, 0.f),
3341 // Filters make the layer own a surface.
3342 FilterOperations filters;
3343 filters.Append(FilterOperation::CreateBlurFilter(3.f));
3344 filtered_surface->SetBackgroundFilters(filters);
3346 this->CalcDrawEtc(parent);
3348 TestOcclusionTrackerWithClip<typename Types::LayerType,
3349 typename Types::RenderSurfaceType> occlusion(
3350 gfx::Rect(0, 0, 1000, 1000));
3352 // The surface has a background blur, so it blurs non-opaque pixels below
3354 this->VisitLayer(filtered_surface, &occlusion);
3355 this->VisitContributingSurface(filtered_surface, &occlusion);
3357 this->VisitLayer(behind_replica_layer, &occlusion);
3358 this->VisitLayer(behind_surface_layer, &occlusion);
3360 // The layers behind the surface are not blurred, and their occlusion does
3361 // not change, until we leave the surface. So it should not be modified by
3363 gfx::Rect occlusion_behind_surface = gfx::Rect(60, 60, 30, 30);
3364 gfx::Rect occlusion_behind_replica = gfx::Rect(210, 60, 30, 30);
3366 Region expected_opaque_bounds =
3367 UnionRegions(occlusion_behind_surface, occlusion_behind_replica);
3368 EXPECT_EQ(expected_opaque_bounds.ToString(),
3369 occlusion.occlusion_from_inside_target().ToString());
3371 EXPECT_EQ(gfx::Rect().ToString(),
3372 occlusion.occlusion_from_outside_target().ToString());
3376 ALL_OCCLUSIONTRACKER_TEST(
3377 OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter);
3379 template <class Types>
3380 class OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded
3381 : public OcclusionTrackerTest<Types> {
3383 explicit OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded(
3385 : OcclusionTrackerTest<Types>(opaque_layers) {}
3387 gfx::Transform scale_by_half;
3388 scale_by_half.Scale(0.5, 0.5);
3390 // Make a 50x50 filtered surface that is completely occluded by an opaque
3391 // layer which is above it in the z-order. The surface is
3392 // scaled to test that the pixel moving is done in the target space, where
3393 // the background filter is applied, but the surface appears at 50, 50.
3394 typename Types::ContentLayerType* parent = this->CreateRoot(
3395 this->identity_matrix, gfx::PointF(), gfx::Size(200, 150));
3396 typename Types::LayerType* filtered_surface =
3397 this->CreateDrawingLayer(parent,
3399 gfx::PointF(50.f, 50.f),
3400 gfx::Size(100, 100),
3402 typename Types::LayerType* occluding_layer =
3403 this->CreateDrawingLayer(parent,
3404 this->identity_matrix,
3405 gfx::PointF(50.f, 50.f),
3409 // Filters make the layer own a surface.
3410 FilterOperations filters;
3411 filters.Append(FilterOperation::CreateBlurFilter(3.f));
3412 filtered_surface->SetBackgroundFilters(filters);
3414 this->CalcDrawEtc(parent);
3416 TestOcclusionTrackerWithClip<typename Types::LayerType,
3417 typename Types::RenderSurfaceType> occlusion(
3418 gfx::Rect(0, 0, 1000, 1000));
3420 this->VisitLayer(occluding_layer, &occlusion);
3422 this->VisitLayer(filtered_surface, &occlusion);
3424 // The layers above the filtered surface occlude from outside.
3425 gfx::Rect occlusion_above_surface = gfx::Rect(0, 0, 50, 50);
3427 EXPECT_EQ(gfx::Rect().ToString(),
3428 occlusion.occlusion_from_inside_target().ToString());
3429 EXPECT_EQ(occlusion_above_surface.ToString(),
3430 occlusion.occlusion_from_outside_target().ToString());
3433 // The surface has a background blur, so it blurs non-opaque pixels below
3435 this->VisitContributingSurface(filtered_surface, &occlusion);
3437 // The filter is completely occluded, so it should not blur anything and
3438 // reduce any occlusion.
3439 gfx::Rect occlusion_above_surface = gfx::Rect(50, 50, 50, 50);
3441 EXPECT_EQ(occlusion_above_surface.ToString(),
3442 occlusion.occlusion_from_inside_target().ToString());
3443 EXPECT_EQ(gfx::Rect().ToString(),
3444 occlusion.occlusion_from_outside_target().ToString());
3449 ALL_OCCLUSIONTRACKER_TEST(
3450 OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded);
3452 template <class Types>
3453 class OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded
3454 : public OcclusionTrackerTest<Types> {
3457 OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded(
3459 : OcclusionTrackerTest<Types>(opaque_layers) {}
3461 gfx::Transform scale_by_half;
3462 scale_by_half.Scale(0.5, 0.5);
3464 // Make a surface and its replica, each 50x50, that are partially occluded
3465 // by opaque layers which are above them in the z-order. The surface is
3466 // scaled to test that the pixel moving is done in the target space, where
3467 // the background filter is applied, but the surface appears at 50, 50 and
3468 // the replica at 200, 50.
3469 typename Types::ContentLayerType* parent = this->CreateRoot(
3470 this->identity_matrix, gfx::PointF(), gfx::Size(300, 150));
3471 typename Types::LayerType* filtered_surface =
3472 this->CreateDrawingLayer(parent,
3474 gfx::PointF(50.f, 50.f),
3475 gfx::Size(100, 100),
3477 this->CreateReplicaLayer(filtered_surface,
3478 this->identity_matrix,
3479 gfx::PointF(300.f, 0.f),
3481 typename Types::LayerType* above_surface_layer =
3482 this->CreateDrawingLayer(parent,
3483 this->identity_matrix,
3484 gfx::PointF(70.f, 50.f),
3487 typename Types::LayerType* above_replica_layer =
3488 this->CreateDrawingLayer(parent,
3489 this->identity_matrix,
3490 gfx::PointF(200.f, 50.f),
3493 typename Types::LayerType* beside_surface_layer =
3494 this->CreateDrawingLayer(parent,
3495 this->identity_matrix,
3496 gfx::PointF(90.f, 40.f),
3499 typename Types::LayerType* beside_replica_layer =
3500 this->CreateDrawingLayer(parent,
3501 this->identity_matrix,
3502 gfx::PointF(200.f, 40.f),
3506 // Filters make the layer own a surface.
3507 FilterOperations filters;
3508 filters.Append(FilterOperation::CreateBlurFilter(3.f));
3509 filtered_surface->SetBackgroundFilters(filters);
3511 // Save the distance of influence for the blur effect.
3512 int outset_top, outset_right, outset_bottom, outset_left;
3514 &outset_top, &outset_right, &outset_bottom, &outset_left);
3516 this->CalcDrawEtc(parent);
3518 TestOcclusionTrackerWithClip<typename Types::LayerType,
3519 typename Types::RenderSurfaceType> occlusion(
3520 gfx::Rect(0, 0, 1000, 1000));
3522 this->VisitLayer(beside_replica_layer, &occlusion);
3523 this->VisitLayer(beside_surface_layer, &occlusion);
3524 this->VisitLayer(above_replica_layer, &occlusion);
3525 this->VisitLayer(above_surface_layer, &occlusion);
3527 // The surface has a background blur, so it blurs non-opaque pixels below
3529 this->VisitLayer(filtered_surface, &occlusion);
3530 this->VisitContributingSurface(filtered_surface, &occlusion);
3532 // The filter in the surface and replica are partially unoccluded. Only the
3533 // unoccluded parts should reduce occlusion. This means it will push back
3534 // the occlusion that touches the unoccluded part (occlusion_above___), but
3535 // it will not touch occlusion_beside____ since that is not beside the
3536 // unoccluded part of the surface, even though it is beside the occluded
3537 // part of the surface.
3538 gfx::Rect occlusion_above_surface =
3539 gfx::Rect(70 + outset_right, 50, 30 - outset_right, 50);
3540 gfx::Rect occlusion_above_replica =
3541 gfx::Rect(200, 50, 30 - outset_left, 50);
3542 gfx::Rect occlusion_beside_surface = gfx::Rect(90, 40, 10, 10);
3543 gfx::Rect occlusion_beside_replica = gfx::Rect(200, 40, 10, 10);
3545 Region expected_occlusion;
3546 expected_occlusion.Union(occlusion_above_surface);
3547 expected_occlusion.Union(occlusion_above_replica);
3548 expected_occlusion.Union(occlusion_beside_surface);
3549 expected_occlusion.Union(occlusion_beside_replica);
3551 ASSERT_EQ(expected_occlusion.ToString(),
3552 occlusion.occlusion_from_inside_target().ToString());
3553 EXPECT_EQ(gfx::Rect().ToString(),
3554 occlusion.occlusion_from_outside_target().ToString());
3556 Region::Iterator expected_rects(expected_occlusion);
3557 Region::Iterator target_surface_rects(
3558 occlusion.occlusion_from_inside_target());
3559 for (; expected_rects.has_rect();
3560 expected_rects.next(), target_surface_rects.next()) {
3561 ASSERT_TRUE(target_surface_rects.has_rect());
3562 EXPECT_EQ(expected_rects.rect(), target_surface_rects.rect());
3567 ALL_OCCLUSIONTRACKER_TEST(
3568 OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded);
3570 template <class Types>
3571 class OcclusionTrackerTestMinimumTrackingSize
3572 : public OcclusionTrackerTest<Types> {
3574 explicit OcclusionTrackerTestMinimumTrackingSize(bool opaque_layers)
3575 : OcclusionTrackerTest<Types>(opaque_layers) {}
3577 gfx::Size tracking_size(100, 100);
3578 gfx::Size below_tracking_size(99, 99);
3580 typename Types::ContentLayerType* parent = this->CreateRoot(
3581 this->identity_matrix, gfx::PointF(), gfx::Size(400, 400));
3582 typename Types::LayerType* large = this->CreateDrawingLayer(
3583 parent, this->identity_matrix, gfx::PointF(), tracking_size, true);
3584 typename Types::LayerType* small =
3585 this->CreateDrawingLayer(parent,
3586 this->identity_matrix,
3588 below_tracking_size,
3590 this->CalcDrawEtc(parent);
3592 TestOcclusionTrackerWithClip<typename Types::LayerType,
3593 typename Types::RenderSurfaceType> occlusion(
3594 gfx::Rect(0, 0, 1000, 1000));
3595 occlusion.set_minimum_tracking_size(tracking_size);
3597 // The small layer is not tracked because it is too small.
3598 this->VisitLayer(small, &occlusion);
3600 EXPECT_EQ(gfx::Rect().ToString(),
3601 occlusion.occlusion_from_outside_target().ToString());
3602 EXPECT_EQ(gfx::Rect().ToString(),
3603 occlusion.occlusion_from_inside_target().ToString());
3605 // The large layer is tracked as it is large enough.
3606 this->VisitLayer(large, &occlusion);
3608 EXPECT_EQ(gfx::Rect().ToString(),
3609 occlusion.occlusion_from_outside_target().ToString());
3610 EXPECT_EQ(gfx::Rect(tracking_size).ToString(),
3611 occlusion.occlusion_from_inside_target().ToString());
3615 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestMinimumTrackingSize);
3617 template <class Types>
3618 class OcclusionTrackerTestScaledLayerIsClipped
3619 : public OcclusionTrackerTest<Types> {
3621 explicit OcclusionTrackerTestScaledLayerIsClipped(bool opaque_layers)
3622 : OcclusionTrackerTest<Types>(opaque_layers) {}
3624 gfx::Transform scale_transform;
3625 scale_transform.Scale(512.0, 512.0);
3627 typename Types::ContentLayerType* parent = this->CreateRoot(
3628 this->identity_matrix, gfx::PointF(), gfx::Size(400, 400));
3629 typename Types::LayerType* clip = this->CreateLayer(parent,
3630 this->identity_matrix,
3631 gfx::PointF(10.f, 10.f),
3633 clip->SetMasksToBounds(true);
3634 typename Types::LayerType* scale = this->CreateLayer(
3635 clip, scale_transform, gfx::PointF(), gfx::Size(1, 1));
3636 typename Types::LayerType* scaled = this->CreateDrawingLayer(
3637 scale, this->identity_matrix, gfx::PointF(), gfx::Size(500, 500), true);
3638 this->CalcDrawEtc(parent);
3640 TestOcclusionTrackerWithClip<typename Types::LayerType,
3641 typename Types::RenderSurfaceType> occlusion(
3642 gfx::Rect(0, 0, 1000, 1000));
3644 this->VisitLayer(scaled, &occlusion);
3646 EXPECT_EQ(gfx::Rect().ToString(),
3647 occlusion.occlusion_from_outside_target().ToString());
3648 EXPECT_EQ(gfx::Rect(10, 10, 50, 50).ToString(),
3649 occlusion.occlusion_from_inside_target().ToString());
3653 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestScaledLayerIsClipped)
3655 template <class Types>
3656 class OcclusionTrackerTestScaledLayerInSurfaceIsClipped
3657 : public OcclusionTrackerTest<Types> {
3659 explicit OcclusionTrackerTestScaledLayerInSurfaceIsClipped(bool opaque_layers)
3660 : OcclusionTrackerTest<Types>(opaque_layers) {}
3662 gfx::Transform scale_transform;
3663 scale_transform.Scale(512.0, 512.0);
3665 typename Types::ContentLayerType* parent = this->CreateRoot(
3666 this->identity_matrix, gfx::PointF(), gfx::Size(400, 400));
3667 typename Types::LayerType* clip = this->CreateLayer(parent,
3668 this->identity_matrix,
3669 gfx::PointF(10.f, 10.f),
3671 clip->SetMasksToBounds(true);
3672 typename Types::LayerType* surface = this->CreateDrawingSurface(
3673 clip, this->identity_matrix, gfx::PointF(), gfx::Size(400, 30), false);
3674 typename Types::LayerType* scale = this->CreateLayer(
3675 surface, scale_transform, gfx::PointF(), gfx::Size(1, 1));
3676 typename Types::LayerType* scaled = this->CreateDrawingLayer(
3677 scale, this->identity_matrix, gfx::PointF(), gfx::Size(500, 500), true);
3678 this->CalcDrawEtc(parent);
3680 TestOcclusionTrackerWithClip<typename Types::LayerType,
3681 typename Types::RenderSurfaceType> occlusion(
3682 gfx::Rect(0, 0, 1000, 1000));
3684 this->VisitLayer(scaled, &occlusion);
3685 this->VisitLayer(surface, &occlusion);
3686 this->VisitContributingSurface(surface, &occlusion);
3688 EXPECT_EQ(gfx::Rect().ToString(),
3689 occlusion.occlusion_from_outside_target().ToString());
3690 EXPECT_EQ(gfx::Rect(10, 10, 50, 50).ToString(),
3691 occlusion.occlusion_from_inside_target().ToString());
3695 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestScaledLayerInSurfaceIsClipped)
3697 template <class Types>
3698 class OcclusionTrackerTestCopyRequestDoesOcclude
3699 : public OcclusionTrackerTest<Types> {
3701 explicit OcclusionTrackerTestCopyRequestDoesOcclude(bool opaque_layers)
3702 : OcclusionTrackerTest<Types>(opaque_layers) {}
3704 typename Types::ContentLayerType* root = this->CreateRoot(
3705 this->identity_matrix, gfx::Point(), gfx::Size(400, 400));
3706 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
3707 root, this->identity_matrix, gfx::Point(), gfx::Size(400, 400), true);
3708 typename Types::LayerType* copy = this->CreateLayer(parent,
3709 this->identity_matrix,
3711 gfx::Size(200, 400));
3712 this->AddCopyRequest(copy);
3713 typename Types::LayerType* copy_child = this->CreateDrawingLayer(
3715 this->identity_matrix,
3717 gfx::Size(200, 400),
3719 this->CalcDrawEtc(root);
3721 TestOcclusionTrackerWithClip<typename Types::LayerType,
3722 typename Types::RenderSurfaceType> occlusion(
3723 gfx::Rect(0, 0, 1000, 1000));
3725 this->VisitLayer(copy_child, &occlusion);
3726 EXPECT_EQ(gfx::Rect().ToString(),
3727 occlusion.occlusion_from_outside_target().ToString());
3728 EXPECT_EQ(gfx::Rect(200, 400).ToString(),
3729 occlusion.occlusion_from_inside_target().ToString());
3731 // CopyRequests cause the layer to own a surface.
3732 this->VisitContributingSurface(copy, &occlusion);
3734 // The occlusion from the copy should be kept.
3735 EXPECT_EQ(gfx::Rect().ToString(),
3736 occlusion.occlusion_from_outside_target().ToString());
3737 EXPECT_EQ(gfx::Rect(100, 0, 200, 400).ToString(),
3738 occlusion.occlusion_from_inside_target().ToString());
3742 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestCopyRequestDoesOcclude)
3744 template <class Types>
3745 class OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude
3746 : public OcclusionTrackerTest<Types> {
3748 explicit OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude(
3750 : OcclusionTrackerTest<Types>(opaque_layers) {}
3752 typename Types::ContentLayerType* root = this->CreateRoot(
3753 this->identity_matrix, gfx::Point(), gfx::Size(400, 400));
3754 typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
3755 root, this->identity_matrix, gfx::Point(), gfx::Size(400, 400), true);
3756 typename Types::LayerType* hide = this->CreateLayer(
3757 parent, this->identity_matrix, gfx::Point(), gfx::Size());
3758 typename Types::LayerType* copy = this->CreateLayer(
3759 hide, this->identity_matrix, gfx::Point(100, 0), gfx::Size(200, 400));
3760 this->AddCopyRequest(copy);
3761 typename Types::LayerType* copy_child = this->CreateDrawingLayer(
3762 copy, this->identity_matrix, gfx::PointF(), gfx::Size(200, 400), true);
3764 // The |copy| layer is hidden but since it is being copied, it will be
3766 hide->SetHideLayerAndSubtree(true);
3768 this->CalcDrawEtc(root);
3770 TestOcclusionTrackerWithClip<typename Types::LayerType,
3771 typename Types::RenderSurfaceType> occlusion(
3772 gfx::Rect(0, 0, 1000, 1000));
3774 this->VisitLayer(copy_child, &occlusion);
3775 EXPECT_EQ(gfx::Rect().ToString(),
3776 occlusion.occlusion_from_outside_target().ToString());
3777 EXPECT_EQ(gfx::Rect(200, 400).ToString(),
3778 occlusion.occlusion_from_inside_target().ToString());
3780 // CopyRequests cause the layer to own a surface.
3781 this->VisitContributingSurface(copy, &occlusion);
3783 // The occlusion from the copy should be dropped since it is hidden.
3784 EXPECT_EQ(gfx::Rect().ToString(),
3785 occlusion.occlusion_from_outside_target().ToString());
3786 EXPECT_EQ(gfx::Rect().ToString(),
3787 occlusion.occlusion_from_inside_target().ToString());
3791 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude)
3793 template <class Types>
3794 class OcclusionTrackerTestEmptyEventLayerDoesNotOcclude
3795 : public OcclusionTrackerTest<Types> {
3797 explicit OcclusionTrackerTestEmptyEventLayerDoesNotOcclude(
3799 : OcclusionTrackerTest<Types>(opaque_layers) {}
3801 typename Types::ContentLayerType* root = this->CreateRoot(
3802 this->identity_matrix, gfx::Point(), gfx::Size(400, 400));
3803 typename Types::ContentLayerType* empty_layer = this->CreateDrawingLayer(
3804 root, this->identity_matrix, gfx::Point(), gfx::Size(200, 200), true);
3805 this->SetDrawsContent(empty_layer, false);
3806 empty_layer->SetTouchEventHandlerRegion(gfx::Rect(10, 10, 10, 10));
3808 this->CalcDrawEtc(root);
3810 TestOcclusionTrackerWithClip<typename Types::LayerType,
3811 typename Types::RenderSurfaceType> occlusion(
3812 gfx::Rect(0, 0, 1000, 1000), false);
3814 this->VisitLayer(empty_layer, &occlusion);
3816 EXPECT_EQ(gfx::Rect().ToString(),
3817 occlusion.occlusion_from_outside_target().ToString());
3818 EXPECT_EQ(gfx::Rect().ToString(),
3819 occlusion.occlusion_from_inside_target().ToString());
3823 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestEmptyEventLayerDoesNotOcclude)