e6464a254dcd8b82f20b42161df255ac94458d42
[platform/framework/web/crosswalk.git] / src / cc / trees / occlusion_tracker_unittest.cc
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.
4
5 #include "cc/trees/occlusion_tracker.h"
6
7 #include "cc/animation/layer_animation_controller.h"
8 #include "cc/base/math_util.h"
9 #include "cc/layers/layer.h"
10 #include "cc/layers/layer_impl.h"
11 #include "cc/output/copy_output_request.h"
12 #include "cc/output/copy_output_result.h"
13 #include "cc/output/filter_operation.h"
14 #include "cc/output/filter_operations.h"
15 #include "cc/test/animation_test_common.h"
16 #include "cc/test/fake_impl_proxy.h"
17 #include "cc/test/fake_layer_tree_host.h"
18 #include "cc/test/fake_layer_tree_host_impl.h"
19 #include "cc/test/geometry_test_utils.h"
20 #include "cc/test/test_occlusion_tracker.h"
21 #include "cc/trees/layer_tree_host_common.h"
22 #include "cc/trees/single_thread_proxy.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "ui/gfx/transform.h"
26
27 namespace cc {
28 namespace {
29
30 class TestContentLayer : public Layer {
31  public:
32   TestContentLayer() : Layer(), override_opaque_contents_rect_(false) {
33     SetIsDrawable(true);
34   }
35
36   virtual Region VisibleContentOpaqueRegion() const OVERRIDE {
37     if (override_opaque_contents_rect_)
38       return gfx::IntersectRects(opaque_contents_rect_, visible_content_rect());
39     return Layer::VisibleContentOpaqueRegion();
40   }
41   void SetOpaqueContentsRect(const gfx::Rect& opaque_contents_rect) {
42     override_opaque_contents_rect_ = true;
43     opaque_contents_rect_ = opaque_contents_rect;
44   }
45
46  private:
47   virtual ~TestContentLayer() {}
48
49   bool override_opaque_contents_rect_;
50   gfx::Rect opaque_contents_rect_;
51 };
52
53 class TestContentLayerImpl : public LayerImpl {
54  public:
55   TestContentLayerImpl(LayerTreeImpl* tree_impl, int id)
56       : LayerImpl(tree_impl, id), override_opaque_contents_rect_(false) {
57     SetDrawsContent(true);
58   }
59
60   virtual Region VisibleContentOpaqueRegion() const OVERRIDE {
61     if (override_opaque_contents_rect_)
62       return gfx::IntersectRects(opaque_contents_rect_, visible_content_rect());
63     return LayerImpl::VisibleContentOpaqueRegion();
64   }
65   void SetOpaqueContentsRect(const gfx::Rect& opaque_contents_rect) {
66     override_opaque_contents_rect_ = true;
67     opaque_contents_rect_ = opaque_contents_rect;
68   }
69
70  private:
71   bool override_opaque_contents_rect_;
72   gfx::Rect opaque_contents_rect_;
73 };
74
75 template <typename LayerType>
76 class TestOcclusionTrackerWithClip : public TestOcclusionTracker<LayerType> {
77  public:
78   explicit TestOcclusionTrackerWithClip(const gfx::Rect& viewport_rect)
79       : TestOcclusionTracker<LayerType>(viewport_rect) {}
80
81   bool OccludedLayer(const LayerType* layer,
82                      const gfx::Rect& content_rect) const {
83     DCHECK(layer->visible_content_rect().Contains(content_rect));
84     return this->Occluded(
85         layer->render_target(), content_rect, layer->draw_transform());
86   }
87
88   // Gives an unoccluded sub-rect of |content_rect| in the content space of the
89   // layer. Simple wrapper around UnoccludedContentRect.
90   gfx::Rect UnoccludedLayerContentRect(const LayerType* layer,
91                                        const gfx::Rect& content_rect) const {
92     DCHECK(layer->visible_content_rect().Contains(content_rect));
93     return this->UnoccludedContentRect(content_rect, layer->draw_transform());
94   }
95
96   gfx::Rect UnoccludedSurfaceContentRect(const LayerType* layer,
97                                          bool for_replica,
98                                          const gfx::Rect& content_rect) const {
99     typename LayerType::RenderSurfaceType* surface = layer->render_surface();
100     gfx::Transform draw_transform = for_replica
101                                         ? surface->replica_draw_transform()
102                                         : surface->draw_transform();
103     return this->UnoccludedContributingSurfaceContentRect(content_rect,
104                                                           draw_transform);
105   }
106 };
107
108 struct OcclusionTrackerTestMainThreadTypes {
109   typedef Layer LayerType;
110   typedef FakeLayerTreeHost HostType;
111   typedef RenderSurface RenderSurfaceType;
112   typedef TestContentLayer ContentLayerType;
113   typedef scoped_refptr<Layer> LayerPtrType;
114   typedef scoped_refptr<ContentLayerType> ContentLayerPtrType;
115   typedef LayerIterator<Layer> TestLayerIterator;
116   typedef OcclusionTracker<Layer> OcclusionTrackerType;
117
118   static LayerPtrType CreateLayer(HostType*  host) { return Layer::Create(); }
119   static ContentLayerPtrType CreateContentLayer(HostType* host) {
120     return make_scoped_refptr(new ContentLayerType());
121   }
122
123   static LayerPtrType PassLayerPtr(ContentLayerPtrType* layer) {
124     LayerPtrType ref(*layer);
125     *layer = NULL;
126     return ref;
127   }
128
129   static LayerPtrType PassLayerPtr(LayerPtrType* layer) {
130     LayerPtrType ref(*layer);
131     *layer = NULL;
132     return ref;
133   }
134
135   static void DestroyLayer(LayerPtrType* layer) { *layer = NULL; }
136
137   static void RecursiveUpdateNumChildren(LayerType* layerType) {}
138 };
139
140 struct OcclusionTrackerTestImplThreadTypes {
141   typedef LayerImpl LayerType;
142   typedef LayerTreeImpl HostType;
143   typedef RenderSurfaceImpl RenderSurfaceType;
144   typedef TestContentLayerImpl ContentLayerType;
145   typedef scoped_ptr<LayerImpl> LayerPtrType;
146   typedef scoped_ptr<ContentLayerType> ContentLayerPtrType;
147   typedef LayerIterator<LayerImpl> TestLayerIterator;
148   typedef OcclusionTracker<LayerImpl> OcclusionTrackerType;
149
150   static LayerPtrType CreateLayer(HostType* host) {
151     return LayerImpl::Create(host, next_layer_impl_id++);
152   }
153   static ContentLayerPtrType CreateContentLayer(HostType* host) {
154     return make_scoped_ptr(new ContentLayerType(host, next_layer_impl_id++));
155   }
156   static int next_layer_impl_id;
157
158   static LayerPtrType PassLayerPtr(LayerPtrType* layer) {
159     return layer->Pass();
160   }
161
162   static LayerPtrType PassLayerPtr(ContentLayerPtrType* layer) {
163     return layer->PassAs<LayerType>();
164   }
165
166   static void DestroyLayer(LayerPtrType* layer) { layer->reset(); }
167
168   static void RecursiveUpdateNumChildren(LayerType* layer) {
169     FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(layer);
170   }
171 };
172
173 int OcclusionTrackerTestImplThreadTypes::next_layer_impl_id = 1;
174
175 template <typename Types> class OcclusionTrackerTest : public testing::Test {
176  protected:
177   explicit OcclusionTrackerTest(bool opaque_layers)
178       : opaque_layers_(opaque_layers), host_(FakeLayerTreeHost::Create()) {}
179
180   virtual void RunMyTest() = 0;
181
182   virtual void TearDown() {
183     Types::DestroyLayer(&root_);
184     render_surface_layer_list_.reset();
185     render_surface_layer_list_impl_.clear();
186     replica_layers_.clear();
187     mask_layers_.clear();
188   }
189
190   typename Types::HostType* GetHost();
191
192   typename Types::ContentLayerType* CreateRoot(const gfx::Transform& transform,
193                                                const gfx::PointF& position,
194                                                const gfx::Size& bounds) {
195     typename Types::ContentLayerPtrType layer(
196         Types::CreateContentLayer(GetHost()));
197     typename Types::ContentLayerType* layer_ptr = layer.get();
198     SetProperties(layer_ptr, transform, position, bounds);
199
200     DCHECK(!root_.get());
201     root_ = Types::PassLayerPtr(&layer);
202
203     SetRootLayerOnMainThread(layer_ptr);
204
205     return layer_ptr;
206   }
207
208   typename Types::LayerType* CreateLayer(typename Types::LayerType* parent,
209                                          const gfx::Transform& transform,
210                                          const gfx::PointF& position,
211                                          const gfx::Size& bounds) {
212     typename Types::LayerPtrType layer(Types::CreateLayer(GetHost()));
213     typename Types::LayerType* layer_ptr = layer.get();
214     SetProperties(layer_ptr, transform, position, bounds);
215     parent->AddChild(Types::PassLayerPtr(&layer));
216     return layer_ptr;
217   }
218
219   typename Types::LayerType* CreateSurface(typename Types::LayerType* parent,
220                                            const gfx::Transform& transform,
221                                            const gfx::PointF& position,
222                                            const gfx::Size& bounds) {
223     typename Types::LayerType* layer =
224         CreateLayer(parent, transform, position, bounds);
225     layer->SetForceRenderSurface(true);
226     return layer;
227   }
228
229   typename Types::ContentLayerType* CreateDrawingLayer(
230       typename Types::LayerType* parent,
231       const gfx::Transform& transform,
232       const gfx::PointF& position,
233       const gfx::Size& bounds,
234       bool opaque) {
235     typename Types::ContentLayerPtrType layer(
236         Types::CreateContentLayer(GetHost()));
237     typename Types::ContentLayerType* layer_ptr = layer.get();
238     SetProperties(layer_ptr, transform, position, bounds);
239
240     if (opaque_layers_) {
241       layer_ptr->SetContentsOpaque(opaque);
242     } else {
243       layer_ptr->SetContentsOpaque(false);
244       if (opaque)
245         layer_ptr->SetOpaqueContentsRect(gfx::Rect(bounds));
246       else
247         layer_ptr->SetOpaqueContentsRect(gfx::Rect());
248     }
249
250     parent->AddChild(Types::PassLayerPtr(&layer));
251     return layer_ptr;
252   }
253
254   typename Types::LayerType* CreateReplicaLayer(
255       typename Types::LayerType* owning_layer,
256       const gfx::Transform& transform,
257       const gfx::PointF& position,
258       const gfx::Size& bounds) {
259     typename Types::ContentLayerPtrType layer(
260         Types::CreateContentLayer(GetHost()));
261     typename Types::ContentLayerType* layer_ptr = layer.get();
262     SetProperties(layer_ptr, transform, position, bounds);
263     SetReplica(owning_layer, Types::PassLayerPtr(&layer));
264     return layer_ptr;
265   }
266
267   typename Types::LayerType* CreateMaskLayer(
268       typename Types::LayerType* owning_layer,
269       const gfx::Size& bounds) {
270     typename Types::ContentLayerPtrType layer(
271         Types::CreateContentLayer(GetHost()));
272     typename Types::ContentLayerType* layer_ptr = layer.get();
273     SetProperties(layer_ptr, identity_matrix, gfx::PointF(), bounds);
274     SetMask(owning_layer, Types::PassLayerPtr(&layer));
275     return layer_ptr;
276   }
277
278   typename Types::ContentLayerType* CreateDrawingSurface(
279       typename Types::LayerType* parent,
280       const gfx::Transform& transform,
281       const gfx::PointF& position,
282       const gfx::Size& bounds,
283       bool opaque) {
284     typename Types::ContentLayerType* layer =
285         CreateDrawingLayer(parent, transform, position, bounds, opaque);
286     layer->SetForceRenderSurface(true);
287     return layer;
288   }
289
290
291   void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {}
292
293   void AddCopyRequest(Layer* layer) {
294     layer->RequestCopyOfOutput(
295         CopyOutputRequest::CreateBitmapRequest(base::Bind(
296             &OcclusionTrackerTest<Types>::CopyOutputCallback,
297             base::Unretained(this))));
298   }
299
300   void AddCopyRequest(LayerImpl* layer) {
301     ScopedPtrVector<CopyOutputRequest> requests;
302     requests.push_back(
303         CopyOutputRequest::CreateBitmapRequest(base::Bind(
304             &OcclusionTrackerTest<Types>::CopyOutputCallback,
305             base::Unretained(this))));
306     layer->PassCopyRequests(&requests);
307   }
308
309   void CalcDrawEtc(TestContentLayerImpl* root) {
310     DCHECK(root == root_.get());
311     DCHECK(!root->render_surface());
312
313     Types::RecursiveUpdateNumChildren(root);
314     LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
315         root, root->bounds(), &render_surface_layer_list_impl_);
316     inputs.can_adjust_raster_scales = true;
317     LayerTreeHostCommon::CalculateDrawProperties(&inputs);
318
319     layer_iterator_ = layer_iterator_begin_ =
320         Types::TestLayerIterator::Begin(&render_surface_layer_list_impl_);
321   }
322
323   void CalcDrawEtc(TestContentLayer* root) {
324     DCHECK(root == root_.get());
325     DCHECK(!root->render_surface());
326
327     render_surface_layer_list_.reset(new RenderSurfaceLayerList);
328     LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
329         root, root->bounds(), render_surface_layer_list_.get());
330     inputs.can_adjust_raster_scales = true;
331     LayerTreeHostCommon::CalculateDrawProperties(&inputs);
332
333     layer_iterator_ = layer_iterator_begin_ =
334         Types::TestLayerIterator::Begin(render_surface_layer_list_.get());
335   }
336
337   void EnterLayer(typename Types::LayerType* layer,
338                   typename Types::OcclusionTrackerType* occlusion) {
339     ASSERT_EQ(layer, *layer_iterator_);
340     ASSERT_TRUE(layer_iterator_.represents_itself());
341     occlusion->EnterLayer(layer_iterator_);
342   }
343
344   void LeaveLayer(typename Types::LayerType* layer,
345                   typename Types::OcclusionTrackerType* occlusion) {
346     ASSERT_EQ(layer, *layer_iterator_);
347     ASSERT_TRUE(layer_iterator_.represents_itself());
348     occlusion->LeaveLayer(layer_iterator_);
349     ++layer_iterator_;
350   }
351
352   void VisitLayer(typename Types::LayerType* layer,
353                   typename Types::OcclusionTrackerType* occlusion) {
354     EnterLayer(layer, occlusion);
355     LeaveLayer(layer, occlusion);
356   }
357
358   void EnterContributingSurface(
359       typename Types::LayerType* layer,
360       typename Types::OcclusionTrackerType* occlusion) {
361     ASSERT_EQ(layer, *layer_iterator_);
362     ASSERT_TRUE(layer_iterator_.represents_target_render_surface());
363     occlusion->EnterLayer(layer_iterator_);
364     occlusion->LeaveLayer(layer_iterator_);
365     ++layer_iterator_;
366     ASSERT_TRUE(layer_iterator_.represents_contributing_render_surface());
367     occlusion->EnterLayer(layer_iterator_);
368   }
369
370   void LeaveContributingSurface(
371       typename Types::LayerType* layer,
372       typename Types::OcclusionTrackerType* occlusion) {
373     ASSERT_EQ(layer, *layer_iterator_);
374     ASSERT_TRUE(layer_iterator_.represents_contributing_render_surface());
375     occlusion->LeaveLayer(layer_iterator_);
376     ++layer_iterator_;
377   }
378
379   void VisitContributingSurface(
380       typename Types::LayerType* layer,
381       typename Types::OcclusionTrackerType* occlusion) {
382     EnterContributingSurface(layer, occlusion);
383     LeaveContributingSurface(layer, occlusion);
384   }
385
386   void ResetLayerIterator() { layer_iterator_ = layer_iterator_begin_; }
387
388   const gfx::Transform identity_matrix;
389
390  private:
391   void SetRootLayerOnMainThread(Layer* root) {
392     host_->SetRootLayer(scoped_refptr<Layer>(root));
393   }
394
395   void SetRootLayerOnMainThread(LayerImpl* root) {}
396
397   void SetBaseProperties(typename Types::LayerType* layer,
398                          const gfx::Transform& transform,
399                          const gfx::PointF& position,
400                          const gfx::Size& bounds) {
401     layer->SetTransform(transform);
402     layer->SetPosition(position);
403     layer->SetBounds(bounds);
404   }
405
406   void SetProperties(Layer* layer,
407                      const gfx::Transform& transform,
408                      const gfx::PointF& position,
409                      const gfx::Size& bounds) {
410     SetBaseProperties(layer, transform, position, bounds);
411   }
412
413   void SetProperties(LayerImpl* layer,
414                      const gfx::Transform& transform,
415                      const gfx::PointF& position,
416                      const gfx::Size& bounds) {
417     SetBaseProperties(layer, transform, position, bounds);
418
419     layer->SetContentBounds(layer->bounds());
420   }
421
422   void SetReplica(Layer* owning_layer, scoped_refptr<Layer> layer) {
423     owning_layer->SetReplicaLayer(layer.get());
424     replica_layers_.push_back(layer);
425   }
426
427   void SetReplica(LayerImpl* owning_layer, scoped_ptr<LayerImpl> layer) {
428     owning_layer->SetReplicaLayer(layer.Pass());
429   }
430
431   void SetMask(Layer* owning_layer, scoped_refptr<Layer> layer) {
432     owning_layer->SetMaskLayer(layer.get());
433     mask_layers_.push_back(layer);
434   }
435
436   void SetMask(LayerImpl* owning_layer, scoped_ptr<LayerImpl> layer) {
437     owning_layer->SetMaskLayer(layer.Pass());
438   }
439
440   bool opaque_layers_;
441   scoped_ptr<FakeLayerTreeHost> host_;
442   // These hold ownership of the layers for the duration of the test.
443   typename Types::LayerPtrType root_;
444   scoped_ptr<RenderSurfaceLayerList> render_surface_layer_list_;
445   LayerImplList render_surface_layer_list_impl_;
446   typename Types::TestLayerIterator layer_iterator_begin_;
447   typename Types::TestLayerIterator layer_iterator_;
448   typename Types::LayerType* last_layer_visited_;
449   LayerList replica_layers_;
450   LayerList mask_layers_;
451 };
452
453 template <>
454 FakeLayerTreeHost*
455 OcclusionTrackerTest<OcclusionTrackerTestMainThreadTypes>::GetHost() {
456   return host_.get();
457 }
458
459 template <>
460 LayerTreeImpl*
461 OcclusionTrackerTest<OcclusionTrackerTestImplThreadTypes>::GetHost() {
462   return host_->host_impl()->active_tree();
463 }
464
465 #define RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName)                          \
466   class ClassName##MainThreadOpaqueLayers                                      \
467       : public ClassName<OcclusionTrackerTestMainThreadTypes> {                \
468    public: /* NOLINT(whitespace/indent) */                                     \
469     ClassName##MainThreadOpaqueLayers()                                        \
470         : ClassName<OcclusionTrackerTestMainThreadTypes>(true) {}              \
471   };                                                                           \
472   TEST_F(ClassName##MainThreadOpaqueLayers, RunTest) { RunMyTest(); }
473 #define RUN_TEST_MAIN_THREAD_OPAQUE_PAINTS(ClassName)                          \
474   class ClassName##MainThreadOpaquePaints                                      \
475       : public ClassName<OcclusionTrackerTestMainThreadTypes> {                \
476    public: /* NOLINT(whitespace/indent) */                                     \
477     ClassName##MainThreadOpaquePaints()                                        \
478         : ClassName<OcclusionTrackerTestMainThreadTypes>(false) {}             \
479   };                                                                           \
480   TEST_F(ClassName##MainThreadOpaquePaints, RunTest) { RunMyTest(); }
481
482 #define RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName)                          \
483   class ClassName##ImplThreadOpaqueLayers                                      \
484       : public ClassName<OcclusionTrackerTestImplThreadTypes> {                \
485    public: /* NOLINT(whitespace/indent) */                                     \
486     ClassName##ImplThreadOpaqueLayers()                                        \
487         : ClassName<OcclusionTrackerTestImplThreadTypes>(true) {}              \
488   };                                                                           \
489   TEST_F(ClassName##ImplThreadOpaqueLayers, RunTest) { RunMyTest(); }
490 #define RUN_TEST_IMPL_THREAD_OPAQUE_PAINTS(ClassName)                          \
491   class ClassName##ImplThreadOpaquePaints                                      \
492       : public ClassName<OcclusionTrackerTestImplThreadTypes> {                \
493    public: /* NOLINT(whitespace/indent) */                                     \
494     ClassName##ImplThreadOpaquePaints()                                        \
495         : ClassName<OcclusionTrackerTestImplThreadTypes>(false) {}             \
496   };                                                                           \
497   TEST_F(ClassName##ImplThreadOpaquePaints, RunTest) { RunMyTest(); }
498
499 #define ALL_OCCLUSIONTRACKER_TEST(ClassName)                                   \
500   RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName)                                \
501       RUN_TEST_MAIN_THREAD_OPAQUE_PAINTS(ClassName)                            \
502       RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName)                            \
503       RUN_TEST_IMPL_THREAD_OPAQUE_PAINTS(ClassName)
504
505 #define MAIN_THREAD_TEST(ClassName)                                            \
506   RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName)
507
508 #define IMPL_THREAD_TEST(ClassName)                                            \
509   RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName)
510
511 #define MAIN_AND_IMPL_THREAD_TEST(ClassName)                                   \
512   RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName)                                \
513       RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName)
514
515 template <class Types>
516 class OcclusionTrackerTestIdentityTransforms
517     : public OcclusionTrackerTest<Types> {
518  protected:
519   explicit OcclusionTrackerTestIdentityTransforms(bool opaque_layers)
520       : OcclusionTrackerTest<Types>(opaque_layers) {}
521
522   void RunMyTest() {
523     typename Types::ContentLayerType* root = this->CreateRoot(
524         this->identity_matrix, gfx::PointF(), gfx::Size(200, 200));
525     typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
526         root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
527     typename Types::ContentLayerType* layer =
528         this->CreateDrawingLayer(parent,
529                                  this->identity_matrix,
530                                  gfx::PointF(30.f, 30.f),
531                                  gfx::Size(500, 500),
532                                  true);
533     parent->SetMasksToBounds(true);
534     this->CalcDrawEtc(root);
535
536     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
537         gfx::Rect(0, 0, 1000, 1000));
538
539     this->VisitLayer(layer, &occlusion);
540     this->EnterLayer(parent, &occlusion);
541
542     EXPECT_EQ(gfx::Rect().ToString(),
543               occlusion.occlusion_from_outside_target().ToString());
544     EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(),
545               occlusion.occlusion_from_inside_target().ToString());
546
547     EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 70, 70)));
548     EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 30, 70, 70)));
549     EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 29, 70, 70)));
550     EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 30, 69, 70)));
551     EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 31, 70, 69)));
552
553     EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
554         parent, gfx::Rect(30, 30, 70, 70)).IsEmpty());
555     EXPECT_RECT_EQ(gfx::Rect(29, 30, 1, 70),
556                    occlusion.UnoccludedLayerContentRect(
557                        parent, gfx::Rect(29, 30, 70, 70)));
558     EXPECT_RECT_EQ(gfx::Rect(29, 29, 70, 70),
559                    occlusion.UnoccludedLayerContentRect(
560                        parent, gfx::Rect(29, 29, 70, 70)));
561     EXPECT_RECT_EQ(gfx::Rect(30, 29, 70, 1),
562                    occlusion.UnoccludedLayerContentRect(
563                        parent, gfx::Rect(30, 29, 70, 70)));
564     EXPECT_RECT_EQ(gfx::Rect(31, 29, 69, 1),
565                    occlusion.UnoccludedLayerContentRect(
566                        parent, gfx::Rect(31, 29, 69, 70)));
567     EXPECT_RECT_EQ(gfx::Rect(),
568                    occlusion.UnoccludedLayerContentRect(
569                        parent, gfx::Rect(31, 30, 69, 70)));
570     EXPECT_RECT_EQ(gfx::Rect(),
571                    occlusion.UnoccludedLayerContentRect(
572                        parent, gfx::Rect(31, 31, 69, 69)));
573     EXPECT_RECT_EQ(gfx::Rect(),
574                    occlusion.UnoccludedLayerContentRect(
575                        parent, gfx::Rect(30, 31, 70, 69)));
576     EXPECT_RECT_EQ(gfx::Rect(29, 31, 1, 69),
577                    occlusion.UnoccludedLayerContentRect(
578                        parent, gfx::Rect(29, 31, 70, 69)));
579   }
580 };
581
582 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestIdentityTransforms);
583
584 template <class Types>
585 class OcclusionTrackerTestQuadsMismatchLayer
586     : public OcclusionTrackerTest<Types> {
587  protected:
588   explicit OcclusionTrackerTestQuadsMismatchLayer(bool opaque_layers)
589       : OcclusionTrackerTest<Types>(opaque_layers) {}
590   void RunMyTest() {
591     gfx::Transform layer_transform;
592     layer_transform.Translate(10.0, 10.0);
593
594     typename Types::ContentLayerType* parent = this->CreateRoot(
595         this->identity_matrix, gfx::Point(0, 0), gfx::Size(100, 100));
596     typename Types::ContentLayerType* layer1 = this->CreateDrawingLayer(
597         parent, layer_transform, gfx::PointF(), gfx::Size(90, 90), true);
598     typename Types::ContentLayerType* layer2 = this->CreateDrawingLayer(
599         layer1, layer_transform, gfx::PointF(), gfx::Size(50, 50), true);
600     this->CalcDrawEtc(parent);
601
602     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
603         gfx::Rect(0, 0, 1000, 1000));
604
605     this->VisitLayer(layer2, &occlusion);
606     this->EnterLayer(layer1, &occlusion);
607
608     EXPECT_EQ(gfx::Rect().ToString(),
609               occlusion.occlusion_from_outside_target().ToString());
610     EXPECT_EQ(gfx::Rect(20, 20, 50, 50).ToString(),
611               occlusion.occlusion_from_inside_target().ToString());
612
613     // This checks cases where the quads don't match their "containing"
614     // layers, e.g. in terms of transforms or clip rect. This is typical for
615     // DelegatedRendererLayer.
616
617     gfx::Transform quad_transform;
618     quad_transform.Translate(30.0, 30.0);
619
620     EXPECT_TRUE(occlusion.UnoccludedContentRect(gfx::Rect(0, 0, 10, 10),
621                                                 quad_transform).IsEmpty());
622     EXPECT_RECT_EQ(gfx::Rect(40, 40, 10, 10),
623                    occlusion.UnoccludedContentRect(gfx::Rect(40, 40, 10, 10),
624                                                    quad_transform));
625     EXPECT_RECT_EQ(gfx::Rect(40, 30, 5, 10),
626                    occlusion.UnoccludedContentRect(gfx::Rect(35, 30, 10, 10),
627                                                    quad_transform));
628   }
629 };
630
631 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestQuadsMismatchLayer);
632
633 template <class Types>
634 class OcclusionTrackerTestRotatedChild : public OcclusionTrackerTest<Types> {
635  protected:
636   explicit OcclusionTrackerTestRotatedChild(bool opaque_layers)
637       : OcclusionTrackerTest<Types>(opaque_layers) {}
638   void RunMyTest() {
639     gfx::Transform layer_transform;
640     layer_transform.Translate(250.0, 250.0);
641     layer_transform.Rotate(90.0);
642     layer_transform.Translate(-250.0, -250.0);
643
644     typename Types::ContentLayerType* root = this->CreateRoot(
645         this->identity_matrix, gfx::Point(0, 0), gfx::Size(200, 200));
646     typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
647         root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
648     typename Types::ContentLayerType* layer =
649         this->CreateDrawingLayer(parent,
650                                  layer_transform,
651                                  gfx::PointF(30.f, 30.f),
652                                  gfx::Size(500, 500),
653                                  true);
654     parent->SetMasksToBounds(true);
655     this->CalcDrawEtc(root);
656
657     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
658         gfx::Rect(0, 0, 1000, 1000));
659
660     this->VisitLayer(layer, &occlusion);
661     this->EnterLayer(parent, &occlusion);
662
663     EXPECT_EQ(gfx::Rect().ToString(),
664               occlusion.occlusion_from_outside_target().ToString());
665     EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(),
666               occlusion.occlusion_from_inside_target().ToString());
667
668     EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 70, 70)));
669     EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 30, 70, 70)));
670     EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 29, 70, 70)));
671     EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 30, 69, 70)));
672     EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 31, 70, 69)));
673
674     EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
675         parent, gfx::Rect(30, 30, 70, 70)).IsEmpty());
676     EXPECT_RECT_EQ(gfx::Rect(29, 30, 1, 70),
677                    occlusion.UnoccludedLayerContentRect(
678                        parent, gfx::Rect(29, 30, 69, 70)));
679     EXPECT_RECT_EQ(gfx::Rect(29, 29, 70, 70),
680                    occlusion.UnoccludedLayerContentRect(
681                        parent, gfx::Rect(29, 29, 70, 70)));
682     EXPECT_RECT_EQ(gfx::Rect(30, 29, 70, 1),
683                    occlusion.UnoccludedLayerContentRect(
684                        parent, gfx::Rect(30, 29, 70, 70)));
685     EXPECT_RECT_EQ(gfx::Rect(31, 29, 69, 1),
686                    occlusion.UnoccludedLayerContentRect(
687                        parent, gfx::Rect(31, 29, 69, 70)));
688     EXPECT_RECT_EQ(gfx::Rect(),
689                    occlusion.UnoccludedLayerContentRect(
690                        parent, gfx::Rect(31, 30, 69, 70)));
691     EXPECT_RECT_EQ(gfx::Rect(),
692                    occlusion.UnoccludedLayerContentRect(
693                        parent, gfx::Rect(31, 31, 69, 69)));
694     EXPECT_RECT_EQ(gfx::Rect(),
695                    occlusion.UnoccludedLayerContentRect(
696                        parent, gfx::Rect(30, 31, 70, 69)));
697     EXPECT_RECT_EQ(gfx::Rect(29, 31, 1, 69),
698                    occlusion.UnoccludedLayerContentRect(
699                        parent, gfx::Rect(29, 31, 70, 69)));
700   }
701 };
702
703 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestRotatedChild);
704
705 template <class Types>
706 class OcclusionTrackerTestTranslatedChild : public OcclusionTrackerTest<Types> {
707  protected:
708   explicit OcclusionTrackerTestTranslatedChild(bool opaque_layers)
709       : OcclusionTrackerTest<Types>(opaque_layers) {}
710   void RunMyTest() {
711     gfx::Transform layer_transform;
712     layer_transform.Translate(20.0, 20.0);
713
714     typename Types::ContentLayerType* root = this->CreateRoot(
715         this->identity_matrix, gfx::PointF(), gfx::Size(200, 200));
716     typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
717         root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
718     typename Types::ContentLayerType* layer =
719         this->CreateDrawingLayer(parent,
720                                  layer_transform,
721                                  gfx::PointF(30.f, 30.f),
722                                  gfx::Size(500, 500),
723                                  true);
724     parent->SetMasksToBounds(true);
725     this->CalcDrawEtc(root);
726
727     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
728         gfx::Rect(0, 0, 1000, 1000));
729
730     this->VisitLayer(layer, &occlusion);
731     this->EnterLayer(parent, &occlusion);
732
733     EXPECT_EQ(gfx::Rect().ToString(),
734               occlusion.occlusion_from_outside_target().ToString());
735     EXPECT_EQ(gfx::Rect(50, 50, 50, 50).ToString(),
736               occlusion.occlusion_from_inside_target().ToString());
737
738     EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(50, 50, 50, 50)));
739     EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(49, 50, 50, 50)));
740     EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(50, 49, 50, 50)));
741     EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(51, 50, 49, 50)));
742     EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(50, 51, 50, 49)));
743
744     EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
745         parent, gfx::Rect(50, 50, 50, 50)).IsEmpty());
746     EXPECT_RECT_EQ(gfx::Rect(49, 50, 1, 50),
747                    occlusion.UnoccludedLayerContentRect(
748                        parent, gfx::Rect(49, 50, 50, 50)));
749     EXPECT_RECT_EQ(gfx::Rect(49, 49, 50, 50),
750                    occlusion.UnoccludedLayerContentRect(
751                        parent, gfx::Rect(49, 49, 50, 50)));
752     EXPECT_RECT_EQ(gfx::Rect(50, 49, 50, 1),
753                    occlusion.UnoccludedLayerContentRect(
754                        parent, gfx::Rect(50, 49, 50, 50)));
755     EXPECT_RECT_EQ(gfx::Rect(51, 49, 49, 1),
756                    occlusion.UnoccludedLayerContentRect(
757                        parent, gfx::Rect(51, 49, 49, 50)));
758     EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
759         parent, gfx::Rect(51, 50, 49, 50)).IsEmpty());
760     EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
761         parent, gfx::Rect(51, 51, 49, 49)).IsEmpty());
762     EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
763         parent, gfx::Rect(50, 51, 50, 49)).IsEmpty());
764     EXPECT_RECT_EQ(gfx::Rect(49, 51, 1, 49),
765                    occlusion.UnoccludedLayerContentRect(
766                        parent, gfx::Rect(49, 51, 50, 49)));
767   }
768 };
769
770 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestTranslatedChild);
771
772 template <class Types>
773 class OcclusionTrackerTestChildInRotatedChild
774     : public OcclusionTrackerTest<Types> {
775  protected:
776   explicit OcclusionTrackerTestChildInRotatedChild(bool opaque_layers)
777       : OcclusionTrackerTest<Types>(opaque_layers) {}
778   void RunMyTest() {
779     gfx::Transform child_transform;
780     child_transform.Translate(250.0, 250.0);
781     child_transform.Rotate(90.0);
782     child_transform.Translate(-250.0, -250.0);
783
784     typename Types::ContentLayerType* parent = this->CreateRoot(
785         this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
786     parent->SetMasksToBounds(true);
787     typename Types::LayerType* child = this->CreateSurface(
788         parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500));
789     child->SetMasksToBounds(true);
790     typename Types::ContentLayerType* layer =
791         this->CreateDrawingLayer(child,
792                                  this->identity_matrix,
793                                  gfx::PointF(10.f, 10.f),
794                                  gfx::Size(500, 500),
795                                  true);
796     this->CalcDrawEtc(parent);
797
798     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
799         gfx::Rect(0, 0, 1000, 1000));
800
801     this->VisitLayer(layer, &occlusion);
802     this->EnterContributingSurface(child, &occlusion);
803
804     EXPECT_EQ(gfx::Rect().ToString(),
805               occlusion.occlusion_from_outside_target().ToString());
806     EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(),
807               occlusion.occlusion_from_inside_target().ToString());
808
809     this->LeaveContributingSurface(child, &occlusion);
810     this->EnterLayer(parent, &occlusion);
811
812     EXPECT_EQ(gfx::Rect().ToString(),
813               occlusion.occlusion_from_outside_target().ToString());
814     EXPECT_EQ(gfx::Rect(30, 40, 70, 60).ToString(),
815               occlusion.occlusion_from_inside_target().ToString());
816
817     EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 40, 70, 60)));
818     EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 40, 70, 60)));
819     EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 39, 70, 60)));
820     EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 40, 69, 60)));
821     EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 41, 70, 59)));
822
823     /* Justification for the above occlusion from |layer|:
824                   100
825          +---------------------+
826          |                     |
827          |    30               |           rotate(90)
828          | 30 + ---------------------------------+
829      100 |    |  10            |                 |            ==>
830          |    |10+---------------------------------+
831          |    |  |             |                 | |
832          |    |  |             |                 | |
833          |    |  |             |                 | |
834          +----|--|-------------+                 | |
835               |  |                               | |
836               |  |                               | |
837               |  |                               | |500
838               |  |                               | |
839               |  |                               | |
840               |  |                               | |
841               |  |                               | |
842               +--|-------------------------------+ |
843                  |                                 |
844                  +---------------------------------+
845                                 500
846
847         +---------------------+
848         |                     |30  Visible region of |layer|: /////
849         |                     |
850         |     +---------------------------------+
851      100|     |               |10               |
852         |  +---------------------------------+  |
853         |  |  |///////////////|     420      |  |
854         |  |  |///////////////|60            |  |
855         |  |  |///////////////|              |  |
856         +--|--|---------------+              |  |
857          20|10|     70                       |  |
858            |  |                              |  |
859            |  |                              |  |
860            |  |                              |  |
861            |  |                              |  |
862            |  |                              |  |
863            |  |                              |10|
864            |  +------------------------------|--+
865            |                 490             |
866            +---------------------------------+
867                           500
868
869      */
870   }
871 };
872
873 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestChildInRotatedChild);
874
875 template <class Types>
876 class OcclusionTrackerTestScaledRenderSurface
877     : public OcclusionTrackerTest<Types> {
878  protected:
879   explicit OcclusionTrackerTestScaledRenderSurface(bool opaque_layers)
880       : OcclusionTrackerTest<Types>(opaque_layers) {}
881
882   void RunMyTest() {
883     typename Types::ContentLayerType* parent = this->CreateRoot(
884         this->identity_matrix, gfx::PointF(), gfx::Size(200, 200));
885
886     gfx::Transform layer1_matrix;
887     layer1_matrix.Scale(2.0, 2.0);
888     typename Types::ContentLayerType* layer1 = this->CreateDrawingLayer(
889         parent, layer1_matrix, gfx::PointF(), gfx::Size(100, 100), true);
890     layer1->SetForceRenderSurface(true);
891
892     gfx::Transform layer2_matrix;
893     layer2_matrix.Translate(25.0, 25.0);
894     typename Types::ContentLayerType* layer2 = this->CreateDrawingLayer(
895         layer1, layer2_matrix, gfx::PointF(), gfx::Size(50, 50), true);
896     typename Types::ContentLayerType* occluder =
897         this->CreateDrawingLayer(parent,
898                                  this->identity_matrix,
899                                  gfx::PointF(100.f, 100.f),
900                                  gfx::Size(500, 500),
901                                  true);
902     this->CalcDrawEtc(parent);
903
904     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
905         gfx::Rect(0, 0, 1000, 1000));
906
907     this->VisitLayer(occluder, &occlusion);
908     this->EnterLayer(layer2, &occlusion);
909
910     EXPECT_EQ(gfx::Rect(100, 100, 100, 100).ToString(),
911               occlusion.occlusion_from_outside_target().ToString());
912     EXPECT_EQ(gfx::Rect().ToString(),
913               occlusion.occlusion_from_inside_target().ToString());
914
915     EXPECT_RECT_EQ(
916         gfx::Rect(0, 0, 25, 25),
917         occlusion.UnoccludedLayerContentRect(layer2, gfx::Rect(0, 0, 25, 25)));
918     EXPECT_RECT_EQ(gfx::Rect(10, 25, 15, 25),
919                    occlusion.UnoccludedLayerContentRect(
920                        layer2, gfx::Rect(10, 25, 25, 25)));
921     EXPECT_RECT_EQ(gfx::Rect(25, 10, 25, 15),
922                    occlusion.UnoccludedLayerContentRect(
923                        layer2, gfx::Rect(25, 10, 25, 25)));
924     EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
925         layer2, gfx::Rect(25, 25, 25, 25)).IsEmpty());
926   }
927 };
928
929 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestScaledRenderSurface);
930
931 template <class Types>
932 class OcclusionTrackerTestVisitTargetTwoTimes
933     : public OcclusionTrackerTest<Types> {
934  protected:
935   explicit OcclusionTrackerTestVisitTargetTwoTimes(bool opaque_layers)
936       : OcclusionTrackerTest<Types>(opaque_layers) {}
937   void RunMyTest() {
938     gfx::Transform child_transform;
939     child_transform.Translate(250.0, 250.0);
940     child_transform.Rotate(90.0);
941     child_transform.Translate(-250.0, -250.0);
942
943     typename Types::ContentLayerType* root = this->CreateRoot(
944         this->identity_matrix, gfx::PointF(), gfx::Size(200, 200));
945     typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
946         root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
947     parent->SetMasksToBounds(true);
948     typename Types::LayerType* child = this->CreateSurface(
949         parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500));
950     child->SetMasksToBounds(true);
951     typename Types::ContentLayerType* layer =
952         this->CreateDrawingLayer(child,
953                                  this->identity_matrix,
954                                  gfx::PointF(10.f, 10.f),
955                                  gfx::Size(500, 500),
956                                  true);
957     // |child2| makes |parent|'s surface get considered by OcclusionTracker
958     // first, instead of |child|'s. This exercises different code in
959     // LeaveToRenderTarget, as the target surface has already been seen.
960     typename Types::ContentLayerType* child2 =
961         this->CreateDrawingLayer(parent,
962                                  this->identity_matrix,
963                                  gfx::PointF(30.f, 30.f),
964                                  gfx::Size(60, 20),
965                                  true);
966     this->CalcDrawEtc(root);
967
968     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
969         gfx::Rect(0, 0, 1000, 1000));
970
971     this->VisitLayer(child2, &occlusion);
972
973     EXPECT_EQ(gfx::Rect().ToString(),
974               occlusion.occlusion_from_outside_target().ToString());
975     EXPECT_EQ(gfx::Rect(30, 30, 60, 20).ToString(),
976               occlusion.occlusion_from_inside_target().ToString());
977
978     this->VisitLayer(layer, &occlusion);
979
980     EXPECT_EQ(gfx::Rect(0, 440, 20, 60).ToString(),
981               occlusion.occlusion_from_outside_target().ToString());
982     EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(),
983               occlusion.occlusion_from_inside_target().ToString());
984
985     this->EnterContributingSurface(child, &occlusion);
986
987     EXPECT_EQ(gfx::Rect(0, 440, 20, 60).ToString(),
988               occlusion.occlusion_from_outside_target().ToString());
989     EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(),
990               occlusion.occlusion_from_inside_target().ToString());
991
992     // Occlusion in |child2| should get merged with the |child| surface we are
993     // leaving now.
994     this->LeaveContributingSurface(child, &occlusion);
995     this->EnterLayer(parent, &occlusion);
996
997     EXPECT_EQ(gfx::Rect().ToString(),
998               occlusion.occlusion_from_outside_target().ToString());
999     EXPECT_EQ(UnionRegions(gfx::Rect(30, 30, 60, 10), gfx::Rect(30, 40, 70, 60))
1000                   .ToString(),
1001               occlusion.occlusion_from_inside_target().ToString());
1002
1003     EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 70, 70)));
1004     EXPECT_RECT_EQ(gfx::Rect(90, 30, 10, 10),
1005                    occlusion.UnoccludedLayerContentRect(
1006                        parent, gfx::Rect(30, 30, 70, 70)));
1007
1008     EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 60, 10)));
1009     EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 30, 60, 10)));
1010     EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 29, 60, 10)));
1011     EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(31, 30, 60, 10)));
1012     EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 31, 60, 10)));
1013
1014     EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 40, 70, 60)));
1015     EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 40, 70, 60)));
1016     EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 39, 70, 60)));
1017
1018     EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
1019         parent, gfx::Rect(30, 30, 60, 10)).IsEmpty());
1020     EXPECT_RECT_EQ(gfx::Rect(29, 30, 1, 10),
1021                    occlusion.UnoccludedLayerContentRect(
1022                        parent, gfx::Rect(29, 30, 60, 10)));
1023     EXPECT_RECT_EQ(gfx::Rect(30, 29, 60, 1),
1024                    occlusion.UnoccludedLayerContentRect(
1025                        parent, gfx::Rect(30, 29, 60, 10)));
1026     EXPECT_RECT_EQ(gfx::Rect(90, 30, 1, 10),
1027                    occlusion.UnoccludedLayerContentRect(
1028                        parent, gfx::Rect(31, 30, 60, 10)));
1029     EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
1030         parent, gfx::Rect(30, 31, 60, 10)).IsEmpty());
1031
1032     EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
1033         parent, gfx::Rect(30, 40, 70, 60)).IsEmpty());
1034     EXPECT_RECT_EQ(gfx::Rect(29, 40, 1, 60),
1035                    occlusion.UnoccludedLayerContentRect(
1036                        parent, gfx::Rect(29, 40, 70, 60)));
1037     // This rect is mostly occluded by |child2|.
1038     EXPECT_RECT_EQ(gfx::Rect(90, 39, 10, 1),
1039                    occlusion.UnoccludedLayerContentRect(
1040                        parent, gfx::Rect(30, 39, 70, 60)));
1041     // This rect extends past top/right ends of |child2|.
1042     EXPECT_RECT_EQ(gfx::Rect(30, 29, 70, 11),
1043                    occlusion.UnoccludedLayerContentRect(
1044                        parent, gfx::Rect(30, 29, 70, 70)));
1045     // This rect extends past left/right ends of |child2|.
1046     EXPECT_RECT_EQ(gfx::Rect(20, 39, 80, 60),
1047                    occlusion.UnoccludedLayerContentRect(
1048                        parent, gfx::Rect(20, 39, 80, 60)));
1049     EXPECT_RECT_EQ(gfx::Rect(),
1050                    occlusion.UnoccludedLayerContentRect(
1051                        parent, gfx::Rect(31, 40, 69, 60)));
1052     EXPECT_RECT_EQ(gfx::Rect(),
1053                    occlusion.UnoccludedLayerContentRect(
1054                        parent, gfx::Rect(30, 41, 70, 59)));
1055
1056     /* Justification for the above occlusion from |layer|:
1057                100
1058       +---------------------+
1059       |                     |
1060       |    30               |           rotate(90)
1061       | 30 + ------------+--------------------+
1062   100 |    |  10         |  |                 |            ==>
1063       |    |10+----------|----------------------+
1064       |    + ------------+  |                 | |
1065       |    |  |             |                 | |
1066       |    |  |             |                 | |
1067       +----|--|-------------+                 | |
1068            |  |                               | |
1069            |  |                               | |
1070            |  |                               | |500
1071            |  |                               | |
1072            |  |                               | |
1073            |  |                               | |
1074            |  |                               | |
1075            +--|-------------------------------+ |
1076               |                                 |
1077               +---------------------------------+
1078                              500
1079
1080
1081        +---------------------+
1082        |                     |30  Visible region of |layer|: /////
1083        |     30   60         |    |child2|: \\\\\
1084        |  30 +------------+--------------------+
1085        |     |\\\\\\\\\\\\|  |10               |
1086        |  +--|\\\\\\\\\\\\|-----------------+  |
1087        |  |  +------------+//|     420      |  |
1088        |  |  |///////////////|60            |  |
1089        |  |  |///////////////|              |  |
1090        +--|--|---------------+              |  |
1091         20|10|     70                       |  |
1092           |  |                              |  |
1093           |  |                              |  |
1094           |  |                              |  |
1095           |  |                              |  |
1096           |  |                              |  |
1097           |  |                              |10|
1098           |  +------------------------------|--+
1099           |                 490             |
1100           +---------------------------------+
1101                          500
1102      */
1103   }
1104 };
1105
1106 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestVisitTargetTwoTimes);
1107
1108 template <class Types>
1109 class OcclusionTrackerTestSurfaceRotatedOffAxis
1110     : public OcclusionTrackerTest<Types> {
1111  protected:
1112   explicit OcclusionTrackerTestSurfaceRotatedOffAxis(bool opaque_layers)
1113       : OcclusionTrackerTest<Types>(opaque_layers) {}
1114   void RunMyTest() {
1115     gfx::Transform child_transform;
1116     child_transform.Translate(250.0, 250.0);
1117     child_transform.Rotate(95.0);
1118     child_transform.Translate(-250.0, -250.0);
1119
1120     gfx::Transform layer_transform;
1121     layer_transform.Translate(10.0, 10.0);
1122
1123     typename Types::ContentLayerType* root = this->CreateRoot(
1124         this->identity_matrix, gfx::PointF(), gfx::Size(1000, 1000));
1125     typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
1126         root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
1127     typename Types::LayerType* child = this->CreateLayer(
1128         parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500));
1129     child->SetMasksToBounds(true);
1130     typename Types::ContentLayerType* layer = this->CreateDrawingLayer(
1131         child, layer_transform, gfx::PointF(), gfx::Size(500, 500), true);
1132     this->CalcDrawEtc(root);
1133
1134     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1135         gfx::Rect(0, 0, 1000, 1000));
1136
1137     gfx::Rect clipped_layer_in_child = MathUtil::MapEnclosingClippedRect(
1138         layer_transform, layer->visible_content_rect());
1139
1140     this->VisitLayer(layer, &occlusion);
1141     this->EnterContributingSurface(child, &occlusion);
1142
1143     EXPECT_EQ(gfx::Rect().ToString(),
1144               occlusion.occlusion_from_outside_target().ToString());
1145     EXPECT_EQ(clipped_layer_in_child.ToString(),
1146               occlusion.occlusion_from_inside_target().ToString());
1147
1148     this->LeaveContributingSurface(child, &occlusion);
1149     this->EnterLayer(parent, &occlusion);
1150
1151     EXPECT_EQ(gfx::Rect().ToString(),
1152               occlusion.occlusion_from_outside_target().ToString());
1153     EXPECT_EQ(gfx::Rect().ToString(),
1154               occlusion.occlusion_from_inside_target().ToString());
1155
1156     EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(75, 55, 1, 1)));
1157     EXPECT_RECT_EQ(
1158         gfx::Rect(75, 55, 1, 1),
1159         occlusion.UnoccludedLayerContentRect(parent, gfx::Rect(75, 55, 1, 1)));
1160   }
1161 };
1162
1163 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceRotatedOffAxis);
1164
1165 template <class Types>
1166 class OcclusionTrackerTestSurfaceWithTwoOpaqueChildren
1167     : public OcclusionTrackerTest<Types> {
1168  protected:
1169   explicit OcclusionTrackerTestSurfaceWithTwoOpaqueChildren(bool opaque_layers)
1170       : OcclusionTrackerTest<Types>(opaque_layers) {}
1171   void RunMyTest() {
1172     gfx::Transform child_transform;
1173     child_transform.Translate(250.0, 250.0);
1174     child_transform.Rotate(90.0);
1175     child_transform.Translate(-250.0, -250.0);
1176
1177     typename Types::ContentLayerType* root = this->CreateRoot(
1178         this->identity_matrix, gfx::PointF(), gfx::Size(1000, 1000));
1179     typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
1180         root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true);
1181     parent->SetMasksToBounds(true);
1182     typename Types::ContentLayerType* child =
1183         this->CreateDrawingSurface(parent,
1184                                  child_transform,
1185                                  gfx::PointF(30.f, 30.f),
1186                                  gfx::Size(500, 500),
1187                                  false);
1188     child->SetMasksToBounds(true);
1189     typename Types::ContentLayerType* layer1 =
1190         this->CreateDrawingLayer(child,
1191                                  this->identity_matrix,
1192                                  gfx::PointF(10.f, 10.f),
1193                                  gfx::Size(500, 500),
1194                                  true);
1195     typename Types::ContentLayerType* layer2 =
1196         this->CreateDrawingLayer(child,
1197                                  this->identity_matrix,
1198                                  gfx::PointF(10.f, 450.f),
1199                                  gfx::Size(500, 60),
1200                                  true);
1201     this->CalcDrawEtc(root);
1202
1203     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1204         gfx::Rect(0, 0, 1000, 1000));
1205
1206     this->VisitLayer(layer2, &occlusion);
1207     this->VisitLayer(layer1, &occlusion);
1208     this->VisitLayer(child, &occlusion);
1209     this->EnterContributingSurface(child, &occlusion);
1210
1211     EXPECT_EQ(gfx::Rect().ToString(),
1212               occlusion.occlusion_from_outside_target().ToString());
1213     EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(),
1214               occlusion.occlusion_from_inside_target().ToString());
1215
1216     EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(10, 430, 60, 70)));
1217     EXPECT_FALSE(occlusion.OccludedLayer(child, gfx::Rect(9, 430, 60, 70)));
1218     EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(11, 430, 59, 70)));
1219     EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(10, 431, 60, 69)));
1220
1221     EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
1222         child, gfx::Rect(10, 430, 60, 70)).IsEmpty());
1223     EXPECT_RECT_EQ(
1224         gfx::Rect(9, 430, 1, 70),
1225         occlusion.UnoccludedLayerContentRect(child, gfx::Rect(9, 430, 60, 70)));
1226     EXPECT_RECT_EQ(gfx::Rect(),
1227                    occlusion.UnoccludedLayerContentRect(
1228                        child, gfx::Rect(11, 430, 59, 70)));
1229     EXPECT_RECT_EQ(gfx::Rect(),
1230                    occlusion.UnoccludedLayerContentRect(
1231                        child, gfx::Rect(10, 431, 60, 69)));
1232
1233     this->LeaveContributingSurface(child, &occlusion);
1234     this->EnterLayer(parent, &occlusion);
1235
1236     EXPECT_EQ(gfx::Rect().ToString(),
1237               occlusion.occlusion_from_outside_target().ToString());
1238     EXPECT_EQ(gfx::Rect(30, 40, 70, 60).ToString(),
1239               occlusion.occlusion_from_inside_target().ToString());
1240
1241     EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 40, 70, 60)));
1242     EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 40, 70, 60)));
1243     EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 39, 70, 60)));
1244
1245     EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
1246         parent, gfx::Rect(30, 40, 70, 60)).IsEmpty());
1247     EXPECT_RECT_EQ(gfx::Rect(29, 40, 1, 60),
1248                    occlusion.UnoccludedLayerContentRect(
1249                        parent, gfx::Rect(29, 40, 70, 60)));
1250     EXPECT_RECT_EQ(gfx::Rect(30, 39, 70, 1),
1251                    occlusion.UnoccludedLayerContentRect(
1252                        parent, gfx::Rect(30, 39, 70, 60)));
1253     EXPECT_RECT_EQ(gfx::Rect(),
1254                    occlusion.UnoccludedLayerContentRect(
1255                        parent, gfx::Rect(31, 40, 69, 60)));
1256     EXPECT_RECT_EQ(gfx::Rect(),
1257                    occlusion.UnoccludedLayerContentRect(
1258                        parent, gfx::Rect(30, 41, 70, 59)));
1259
1260     /* Justification for the above occlusion from |layer1| and |layer2|:
1261
1262            +---------------------+
1263            |                     |30  Visible region of |layer1|: /////
1264            |                     |    Visible region of |layer2|: \\\\\
1265            |     +---------------------------------+
1266            |     |               |10               |
1267            |  +---------------+-----------------+  |
1268            |  |  |\\\\\\\\\\\\|//|     420      |  |
1269            |  |  |\\\\\\\\\\\\|//|60            |  |
1270            |  |  |\\\\\\\\\\\\|//|              |  |
1271            +--|--|------------|--+              |  |
1272             20|10|     70     |                 |  |
1273               |  |            |                 |  |
1274               |  |            |                 |  |
1275               |  |            |                 |  |
1276               |  |            |                 |  |
1277               |  |            |                 |  |
1278               |  |            |                 |10|
1279               |  +------------|-----------------|--+
1280               |               | 490             |
1281               +---------------+-----------------+
1282                      60               440
1283          */
1284   }
1285 };
1286
1287 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceWithTwoOpaqueChildren);
1288
1289 template <class Types>
1290 class OcclusionTrackerTestOverlappingSurfaceSiblings
1291     : public OcclusionTrackerTest<Types> {
1292  protected:
1293   explicit OcclusionTrackerTestOverlappingSurfaceSiblings(bool opaque_layers)
1294       : OcclusionTrackerTest<Types>(opaque_layers) {}
1295   void RunMyTest() {
1296     gfx::Transform child_transform;
1297     child_transform.Translate(250.0, 250.0);
1298     child_transform.Rotate(90.0);
1299     child_transform.Translate(-250.0, -250.0);
1300
1301     typename Types::ContentLayerType* parent = this->CreateRoot(
1302         this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
1303     parent->SetMasksToBounds(true);
1304     typename Types::LayerType* child1 = this->CreateSurface(
1305         parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(10, 10));
1306     typename Types::LayerType* child2 = this->CreateSurface(
1307         parent, child_transform, gfx::PointF(20.f, 40.f), gfx::Size(10, 10));
1308     typename Types::ContentLayerType* layer1 =
1309         this->CreateDrawingLayer(child1,
1310                                  this->identity_matrix,
1311                                  gfx::PointF(-10.f, -10.f),
1312                                  gfx::Size(510, 510),
1313                                  true);
1314     typename Types::ContentLayerType* layer2 =
1315         this->CreateDrawingLayer(child2,
1316                                  this->identity_matrix,
1317                                  gfx::PointF(-10.f, -10.f),
1318                                  gfx::Size(510, 510),
1319                                  true);
1320     this->CalcDrawEtc(parent);
1321
1322     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1323         gfx::Rect(0, 0, 1000, 1000));
1324
1325     this->VisitLayer(layer2, &occlusion);
1326     this->EnterContributingSurface(child2, &occlusion);
1327
1328     EXPECT_EQ(gfx::Rect().ToString(),
1329               occlusion.occlusion_from_outside_target().ToString());
1330     EXPECT_EQ(gfx::Rect(-10, 420, 70, 80).ToString(),
1331               occlusion.occlusion_from_inside_target().ToString());
1332
1333     // There is nothing above child2's surface in the z-order.
1334     EXPECT_RECT_EQ(gfx::Rect(-10, 420, 70, 80),
1335                    occlusion.UnoccludedSurfaceContentRect(
1336                        child2, false, gfx::Rect(-10, 420, 70, 80)));
1337
1338     this->LeaveContributingSurface(child2, &occlusion);
1339     this->VisitLayer(layer1, &occlusion);
1340     this->EnterContributingSurface(child1, &occlusion);
1341
1342     EXPECT_EQ(gfx::Rect(0, 430, 70, 80).ToString(),
1343               occlusion.occlusion_from_outside_target().ToString());
1344     EXPECT_EQ(gfx::Rect(-10, 430, 80, 70).ToString(),
1345               occlusion.occlusion_from_inside_target().ToString());
1346
1347     // child2's contents will occlude child1 below it.
1348     EXPECT_RECT_EQ(gfx::Rect(-10, 430, 10, 70),
1349                    occlusion.UnoccludedSurfaceContentRect(
1350                        child1, false, gfx::Rect(-10, 430, 80, 70)));
1351
1352     this->LeaveContributingSurface(child1, &occlusion);
1353     this->EnterLayer(parent, &occlusion);
1354
1355     EXPECT_EQ(gfx::Rect().ToString(),
1356               occlusion.occlusion_from_outside_target().ToString());
1357     EXPECT_EQ(UnionRegions(gfx::Rect(30, 20, 70, 10), gfx::Rect(20, 30, 80, 70))
1358                   .ToString(),
1359               occlusion.occlusion_from_inside_target().ToString());
1360
1361     EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(20, 20, 80, 80)));
1362
1363     EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 20, 70, 80)));
1364     EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 20, 70, 80)));
1365     EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 19, 70, 80)));
1366
1367     EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(20, 30, 80, 70)));
1368     EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(19, 30, 80, 70)));
1369     EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(20, 29, 80, 70)));
1370
1371     /* Justification for the above occlusion:
1372                100
1373       +---------------------+
1374       |    20               |       layer1
1375       |  30+ ---------------------------------+
1376   100 |  30|                |     layer2      |
1377       |20+----------------------------------+ |
1378       |  | |                |               | |
1379       |  | |                |               | |
1380       |  | |                |               | |
1381       +--|-|----------------+               | |
1382          | |                                | | 510
1383          | |                                | |
1384          | |                                | |
1385          | |                                | |
1386          | |                                | |
1387          | |                                | |
1388          | |                                | |
1389          | +--------------------------------|-+
1390          |                                  |
1391          +----------------------------------+
1392                          510
1393      */
1394   }
1395 };
1396
1397 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestOverlappingSurfaceSiblings);
1398
1399 template <class Types>
1400 class OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms
1401     : public OcclusionTrackerTest<Types> {
1402  protected:
1403   explicit OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms(
1404       bool opaque_layers)
1405       : OcclusionTrackerTest<Types>(opaque_layers) {}
1406   void RunMyTest() {
1407     gfx::Transform child1_transform;
1408     child1_transform.Translate(250.0, 250.0);
1409     child1_transform.Rotate(-90.0);
1410     child1_transform.Translate(-250.0, -250.0);
1411
1412     gfx::Transform child2_transform;
1413     child2_transform.Translate(250.0, 250.0);
1414     child2_transform.Rotate(90.0);
1415     child2_transform.Translate(-250.0, -250.0);
1416
1417     typename Types::ContentLayerType* parent = this->CreateRoot(
1418         this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
1419     parent->SetMasksToBounds(true);
1420     typename Types::LayerType* child1 = this->CreateSurface(
1421         parent, child1_transform, gfx::PointF(30.f, 20.f), gfx::Size(10, 10));
1422     typename Types::LayerType* child2 =
1423         this->CreateDrawingSurface(parent,
1424                                    child2_transform,
1425                                    gfx::PointF(20.f, 40.f),
1426                                    gfx::Size(10, 10),
1427                                    false);
1428     typename Types::ContentLayerType* layer1 =
1429         this->CreateDrawingLayer(child1,
1430                                  this->identity_matrix,
1431                                  gfx::PointF(-10.f, -20.f),
1432                                  gfx::Size(510, 510),
1433                                  true);
1434     typename Types::ContentLayerType* layer2 =
1435         this->CreateDrawingLayer(child2,
1436                                  this->identity_matrix,
1437                                  gfx::PointF(-10.f, -10.f),
1438                                  gfx::Size(510, 510),
1439                                  true);
1440     this->CalcDrawEtc(parent);
1441
1442     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1443         gfx::Rect(0, 0, 1000, 1000));
1444
1445     this->VisitLayer(layer2, &occlusion);
1446     this->EnterLayer(child2, &occlusion);
1447
1448     EXPECT_EQ(gfx::Rect().ToString(),
1449               occlusion.occlusion_from_outside_target().ToString());
1450     EXPECT_EQ(gfx::Rect(-10, 420, 70, 80).ToString(),
1451               occlusion.occlusion_from_inside_target().ToString());
1452
1453     this->LeaveLayer(child2, &occlusion);
1454     this->EnterContributingSurface(child2, &occlusion);
1455
1456     // There is nothing above child2's surface in the z-order.
1457     EXPECT_RECT_EQ(gfx::Rect(-10, 420, 70, 80),
1458                    occlusion.UnoccludedSurfaceContentRect(
1459                        child2, false, gfx::Rect(-10, 420, 70, 80)));
1460
1461     this->LeaveContributingSurface(child2, &occlusion);
1462     this->VisitLayer(layer1, &occlusion);
1463     this->EnterContributingSurface(child1, &occlusion);
1464
1465     EXPECT_EQ(gfx::Rect(420, -10, 70, 80).ToString(),
1466               occlusion.occlusion_from_outside_target().ToString());
1467     EXPECT_EQ(gfx::Rect(420, -20, 80, 90).ToString(),
1468               occlusion.occlusion_from_inside_target().ToString());
1469
1470     // child2's contents will occlude child1 below it.
1471     EXPECT_EQ(gfx::Rect(20, 30, 80, 70).ToString(),
1472               occlusion.occlusion_on_contributing_surface_from_inside_target()
1473                   .ToString());
1474     EXPECT_EQ(gfx::Rect().ToString(),
1475               occlusion.occlusion_on_contributing_surface_from_outside_target()
1476                   .ToString());
1477
1478     this->LeaveContributingSurface(child1, &occlusion);
1479     this->EnterLayer(parent, &occlusion);
1480
1481     EXPECT_EQ(gfx::Rect().ToString(),
1482               occlusion.occlusion_from_outside_target().ToString());
1483     EXPECT_EQ(gfx::Rect(10, 20, 90, 80).ToString(),
1484               occlusion.occlusion_from_inside_target().ToString());
1485
1486     /* Justification for the above occlusion:
1487                   100
1488         +---------------------+
1489         |20                   |       layer1
1490        10+----------------------------------+
1491     100 || 30                 |     layer2  |
1492         |20+----------------------------------+
1493         || |                  |             | |
1494         || |                  |             | |
1495         || |                  |             | |
1496         +|-|------------------+             | |
1497          | |                                | | 510
1498          | |                            510 | |
1499          | |                                | |
1500          | |                                | |
1501          | |                                | |
1502          | |                                | |
1503          | |                520             | |
1504          +----------------------------------+ |
1505            |                                  |
1506            +----------------------------------+
1507                            510
1508      */
1509   }
1510 };
1511
1512 ALL_OCCLUSIONTRACKER_TEST(
1513     OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms);
1514
1515 template <class Types>
1516 class OcclusionTrackerTestFilters : public OcclusionTrackerTest<Types> {
1517  protected:
1518   explicit OcclusionTrackerTestFilters(bool opaque_layers)
1519       : OcclusionTrackerTest<Types>(opaque_layers) {}
1520   void RunMyTest() {
1521     gfx::Transform layer_transform;
1522     layer_transform.Translate(250.0, 250.0);
1523     layer_transform.Rotate(90.0);
1524     layer_transform.Translate(-250.0, -250.0);
1525
1526     typename Types::ContentLayerType* parent = this->CreateRoot(
1527         this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
1528     parent->SetMasksToBounds(true);
1529     typename Types::ContentLayerType* blur_layer =
1530         this->CreateDrawingLayer(parent,
1531                                  layer_transform,
1532                                  gfx::PointF(30.f, 30.f),
1533                                  gfx::Size(500, 500),
1534                                  true);
1535     typename Types::ContentLayerType* opaque_layer =
1536         this->CreateDrawingLayer(parent,
1537                                  layer_transform,
1538                                  gfx::PointF(30.f, 30.f),
1539                                  gfx::Size(500, 500),
1540                                  true);
1541     typename Types::ContentLayerType* opacity_layer =
1542         this->CreateDrawingLayer(parent,
1543                                  layer_transform,
1544                                  gfx::PointF(30.f, 30.f),
1545                                  gfx::Size(500, 500),
1546                                  true);
1547
1548     FilterOperations filters;
1549     filters.Append(FilterOperation::CreateBlurFilter(10.f));
1550     blur_layer->SetFilters(filters);
1551
1552     filters.Clear();
1553     filters.Append(FilterOperation::CreateGrayscaleFilter(0.5f));
1554     opaque_layer->SetFilters(filters);
1555
1556     filters.Clear();
1557     filters.Append(FilterOperation::CreateOpacityFilter(0.5f));
1558     opacity_layer->SetFilters(filters);
1559
1560     this->CalcDrawEtc(parent);
1561
1562     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1563         gfx::Rect(0, 0, 1000, 1000));
1564
1565     // Opacity layer won't contribute to occlusion.
1566     this->VisitLayer(opacity_layer, &occlusion);
1567     this->EnterContributingSurface(opacity_layer, &occlusion);
1568
1569     EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1570     EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1571
1572     // And has nothing to contribute to its parent surface.
1573     this->LeaveContributingSurface(opacity_layer, &occlusion);
1574     EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1575     EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1576
1577     // Opaque layer will contribute to occlusion.
1578     this->VisitLayer(opaque_layer, &occlusion);
1579     this->EnterContributingSurface(opaque_layer, &occlusion);
1580
1581     EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1582     EXPECT_EQ(gfx::Rect(0, 430, 70, 70).ToString(),
1583               occlusion.occlusion_from_inside_target().ToString());
1584
1585     // And it gets translated to the parent surface.
1586     this->LeaveContributingSurface(opaque_layer, &occlusion);
1587     EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1588     EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(),
1589               occlusion.occlusion_from_inside_target().ToString());
1590
1591     // The blur layer needs to throw away any occlusion from outside its
1592     // subtree.
1593     this->EnterLayer(blur_layer, &occlusion);
1594     EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1595     EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1596
1597     // And it won't contribute to occlusion.
1598     this->LeaveLayer(blur_layer, &occlusion);
1599     this->EnterContributingSurface(blur_layer, &occlusion);
1600     EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1601     EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1602
1603     // But the opaque layer's occlusion is preserved on the parent.
1604     this->LeaveContributingSurface(blur_layer, &occlusion);
1605     this->EnterLayer(parent, &occlusion);
1606     EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1607     EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(),
1608               occlusion.occlusion_from_inside_target().ToString());
1609   }
1610 };
1611
1612 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestFilters);
1613
1614 template <class Types>
1615 class OcclusionTrackerTestReplicaDoesOcclude
1616     : public OcclusionTrackerTest<Types> {
1617  protected:
1618   explicit OcclusionTrackerTestReplicaDoesOcclude(bool opaque_layers)
1619       : OcclusionTrackerTest<Types>(opaque_layers) {}
1620   void RunMyTest() {
1621     typename Types::ContentLayerType* parent = this->CreateRoot(
1622         this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
1623     typename Types::LayerType* surface =
1624         this->CreateDrawingSurface(parent,
1625                                    this->identity_matrix,
1626                                    gfx::PointF(0.f, 100.f),
1627                                    gfx::Size(50, 50),
1628                                    true);
1629     this->CreateReplicaLayer(
1630         surface, this->identity_matrix, gfx::PointF(50.f, 50.f), gfx::Size());
1631     this->CalcDrawEtc(parent);
1632
1633     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1634         gfx::Rect(0, 0, 1000, 1000));
1635
1636     this->VisitLayer(surface, &occlusion);
1637
1638     EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
1639               occlusion.occlusion_from_inside_target().ToString());
1640
1641     this->VisitContributingSurface(surface, &occlusion);
1642     this->EnterLayer(parent, &occlusion);
1643
1644     // The surface and replica should both be occluding the parent.
1645     EXPECT_EQ(
1646         UnionRegions(gfx::Rect(0, 100, 50, 50),
1647                      gfx::Rect(50, 150, 50, 50)).ToString(),
1648         occlusion.occlusion_from_inside_target().ToString());
1649   }
1650 };
1651
1652 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaDoesOcclude);
1653
1654 template <class Types>
1655 class OcclusionTrackerTestReplicaWithClipping
1656     : public OcclusionTrackerTest<Types> {
1657  protected:
1658   explicit OcclusionTrackerTestReplicaWithClipping(bool opaque_layers)
1659       : OcclusionTrackerTest<Types>(opaque_layers) {}
1660   void RunMyTest() {
1661     typename Types::ContentLayerType* parent = this->CreateRoot(
1662         this->identity_matrix, gfx::PointF(), gfx::Size(100, 170));
1663     parent->SetMasksToBounds(true);
1664     typename Types::LayerType* surface =
1665         this->CreateDrawingSurface(parent,
1666                                    this->identity_matrix,
1667                                    gfx::PointF(0.f, 100.f),
1668                                    gfx::Size(50, 50),
1669                                    true);
1670     this->CreateReplicaLayer(
1671         surface, this->identity_matrix, gfx::PointF(50.f, 50.f), gfx::Size());
1672     this->CalcDrawEtc(parent);
1673
1674     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1675         gfx::Rect(0, 0, 1000, 1000));
1676
1677     this->VisitLayer(surface, &occlusion);
1678
1679     EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
1680               occlusion.occlusion_from_inside_target().ToString());
1681
1682     this->VisitContributingSurface(surface, &occlusion);
1683     this->EnterLayer(parent, &occlusion);
1684
1685     // The surface and replica should both be occluding the parent.
1686     EXPECT_EQ(
1687         UnionRegions(gfx::Rect(0, 100, 50, 50),
1688                      gfx::Rect(50, 150, 50, 20)).ToString(),
1689         occlusion.occlusion_from_inside_target().ToString());
1690   }
1691 };
1692
1693 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaWithClipping);
1694
1695 template <class Types>
1696 class OcclusionTrackerTestReplicaWithMask : public OcclusionTrackerTest<Types> {
1697  protected:
1698   explicit OcclusionTrackerTestReplicaWithMask(bool opaque_layers)
1699       : OcclusionTrackerTest<Types>(opaque_layers) {}
1700   void RunMyTest() {
1701     typename Types::ContentLayerType* parent = this->CreateRoot(
1702         this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
1703     typename Types::LayerType* surface =
1704         this->CreateDrawingSurface(parent,
1705                                    this->identity_matrix,
1706                                    gfx::PointF(0.f, 100.f),
1707                                    gfx::Size(50, 50),
1708                                    true);
1709     typename Types::LayerType* replica = this->CreateReplicaLayer(
1710         surface, this->identity_matrix, gfx::PointF(50.f, 50.f), gfx::Size());
1711     this->CreateMaskLayer(replica, gfx::Size(10, 10));
1712     this->CalcDrawEtc(parent);
1713
1714     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1715         gfx::Rect(0, 0, 1000, 1000));
1716
1717     this->VisitLayer(surface, &occlusion);
1718
1719     EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
1720               occlusion.occlusion_from_inside_target().ToString());
1721
1722     this->VisitContributingSurface(surface, &occlusion);
1723     this->EnterLayer(parent, &occlusion);
1724
1725     // The replica should not be occluding the parent, since it has a mask
1726     // applied to it.
1727     EXPECT_EQ(gfx::Rect(0, 100, 50, 50).ToString(),
1728               occlusion.occlusion_from_inside_target().ToString());
1729   }
1730 };
1731
1732 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaWithMask);
1733
1734 template <class Types>
1735 class OcclusionTrackerTestOpaqueContentsRegionEmpty
1736     : public OcclusionTrackerTest<Types> {
1737  protected:
1738   explicit OcclusionTrackerTestOpaqueContentsRegionEmpty(bool opaque_layers)
1739       : OcclusionTrackerTest<Types>(opaque_layers) {}
1740   void RunMyTest() {
1741     typename Types::ContentLayerType* parent = this->CreateRoot(
1742         this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1743     typename Types::ContentLayerType* layer =
1744         this->CreateDrawingSurface(parent,
1745                                    this->identity_matrix,
1746                                    gfx::PointF(),
1747                                    gfx::Size(200, 200),
1748                                    false);
1749     this->CalcDrawEtc(parent);
1750
1751     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1752         gfx::Rect(0, 0, 1000, 1000));
1753     this->EnterLayer(layer, &occlusion);
1754
1755     EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 100, 100)));
1756     EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 0, 100, 100)));
1757     EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 100, 100, 100)));
1758     EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 100, 100, 100)));
1759
1760     this->LeaveLayer(layer, &occlusion);
1761     this->VisitContributingSurface(layer, &occlusion);
1762     this->EnterLayer(parent, &occlusion);
1763
1764     EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1765   }
1766 };
1767
1768 MAIN_AND_IMPL_THREAD_TEST(OcclusionTrackerTestOpaqueContentsRegionEmpty);
1769
1770 template <class Types>
1771 class OcclusionTrackerTestOpaqueContentsRegionNonEmpty
1772     : public OcclusionTrackerTest<Types> {
1773  protected:
1774   explicit OcclusionTrackerTestOpaqueContentsRegionNonEmpty(bool opaque_layers)
1775       : OcclusionTrackerTest<Types>(opaque_layers) {}
1776   void RunMyTest() {
1777     typename Types::ContentLayerType* parent = this->CreateRoot(
1778         this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1779     typename Types::ContentLayerType* layer =
1780         this->CreateDrawingLayer(parent,
1781                                  this->identity_matrix,
1782                                  gfx::PointF(100.f, 100.f),
1783                                  gfx::Size(200, 200),
1784                                  false);
1785     this->CalcDrawEtc(parent);
1786     {
1787       TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1788           gfx::Rect(0, 0, 1000, 1000));
1789       layer->SetOpaqueContentsRect(gfx::Rect(0, 0, 100, 100));
1790
1791       this->ResetLayerIterator();
1792       this->VisitLayer(layer, &occlusion);
1793       this->EnterLayer(parent, &occlusion);
1794
1795       EXPECT_EQ(gfx::Rect(100, 100, 100, 100).ToString(),
1796                 occlusion.occlusion_from_inside_target().ToString());
1797
1798       EXPECT_FALSE(
1799           occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100)));
1800       EXPECT_TRUE(
1801           occlusion.OccludedLayer(parent, gfx::Rect(100, 100, 100, 100)));
1802       EXPECT_FALSE(
1803           occlusion.OccludedLayer(parent, gfx::Rect(200, 200, 100, 100)));
1804     }
1805     {
1806       TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1807           gfx::Rect(0, 0, 1000, 1000));
1808       layer->SetOpaqueContentsRect(gfx::Rect(20, 20, 180, 180));
1809
1810       this->ResetLayerIterator();
1811       this->VisitLayer(layer, &occlusion);
1812       this->EnterLayer(parent, &occlusion);
1813
1814       EXPECT_EQ(gfx::Rect(120, 120, 180, 180).ToString(),
1815                 occlusion.occlusion_from_inside_target().ToString());
1816
1817       EXPECT_FALSE(
1818           occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100)));
1819       EXPECT_FALSE(
1820           occlusion.OccludedLayer(parent, gfx::Rect(100, 100, 100, 100)));
1821       EXPECT_TRUE(
1822           occlusion.OccludedLayer(parent, gfx::Rect(200, 200, 100, 100)));
1823     }
1824     {
1825       TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1826           gfx::Rect(0, 0, 1000, 1000));
1827       layer->SetOpaqueContentsRect(gfx::Rect(150, 150, 100, 100));
1828
1829       this->ResetLayerIterator();
1830       this->VisitLayer(layer, &occlusion);
1831       this->EnterLayer(parent, &occlusion);
1832
1833       EXPECT_EQ(gfx::Rect(250, 250, 50, 50).ToString(),
1834                 occlusion.occlusion_from_inside_target().ToString());
1835
1836       EXPECT_FALSE(
1837           occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100)));
1838       EXPECT_FALSE(
1839           occlusion.OccludedLayer(parent, gfx::Rect(100, 100, 100, 100)));
1840       EXPECT_FALSE(
1841           occlusion.OccludedLayer(parent, gfx::Rect(200, 200, 100, 100)));
1842     }
1843   }
1844 };
1845
1846 MAIN_AND_IMPL_THREAD_TEST(OcclusionTrackerTestOpaqueContentsRegionNonEmpty);
1847
1848 template <class Types>
1849 class OcclusionTrackerTest3dTransform : public OcclusionTrackerTest<Types> {
1850  protected:
1851   explicit OcclusionTrackerTest3dTransform(bool opaque_layers)
1852       : OcclusionTrackerTest<Types>(opaque_layers) {}
1853   void RunMyTest() {
1854     gfx::Transform transform;
1855     transform.RotateAboutYAxis(30.0);
1856
1857     typename Types::ContentLayerType* parent = this->CreateRoot(
1858         this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1859     typename Types::LayerType* container = this->CreateLayer(
1860         parent, this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1861     typename Types::ContentLayerType* layer =
1862         this->CreateDrawingLayer(container,
1863                                  transform,
1864                                  gfx::PointF(100.f, 100.f),
1865                                  gfx::Size(200, 200),
1866                                  true);
1867     this->CalcDrawEtc(parent);
1868
1869     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1870         gfx::Rect(0, 0, 1000, 1000));
1871     this->EnterLayer(layer, &occlusion);
1872
1873     // The layer is rotated in 3d but without preserving 3d, so it only gets
1874     // resized.
1875     EXPECT_RECT_EQ(
1876         gfx::Rect(0, 0, 200, 200),
1877         occlusion.UnoccludedLayerContentRect(layer, gfx::Rect(0, 0, 200, 200)));
1878   }
1879 };
1880
1881 MAIN_AND_IMPL_THREAD_TEST(OcclusionTrackerTest3dTransform);
1882
1883 template <class Types>
1884 class OcclusionTrackerTestUnsorted3dLayers
1885     : public OcclusionTrackerTest<Types> {
1886  protected:
1887   explicit OcclusionTrackerTestUnsorted3dLayers(bool opaque_layers)
1888       : OcclusionTrackerTest<Types>(opaque_layers) {}
1889   void RunMyTest() {
1890     // Currently, The main thread layer iterator does not iterate over 3d items
1891     // in sorted order, because layer sorting is not performed on the main
1892     // thread.  Because of this, the occlusion tracker cannot assume that a 3d
1893     // layer occludes other layers that have not yet been iterated over. For
1894     // now, the expected behavior is that a 3d layer simply does not add any
1895     // occlusion to the occlusion tracker.
1896
1897     gfx::Transform translation_to_front;
1898     translation_to_front.Translate3d(0.0, 0.0, -10.0);
1899     gfx::Transform translation_to_back;
1900     translation_to_front.Translate3d(0.0, 0.0, -100.0);
1901
1902     typename Types::ContentLayerType* parent = this->CreateRoot(
1903         this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1904     typename Types::ContentLayerType* child1 = this->CreateDrawingLayer(
1905         parent, translation_to_back, gfx::PointF(), gfx::Size(100, 100), true);
1906     typename Types::ContentLayerType* child2 =
1907         this->CreateDrawingLayer(parent,
1908                                  translation_to_front,
1909                                  gfx::PointF(50.f, 50.f),
1910                                  gfx::Size(100, 100),
1911                                  true);
1912     parent->SetShouldFlattenTransform(false);
1913     parent->Set3dSortingContextId(1);
1914     child1->Set3dSortingContextId(1);
1915     child2->Set3dSortingContextId(1);
1916
1917     this->CalcDrawEtc(parent);
1918
1919     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1920         gfx::Rect(0, 0, 1000, 1000));
1921     this->VisitLayer(child2, &occlusion);
1922     EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1923     EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1924
1925     this->VisitLayer(child1, &occlusion);
1926     EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
1927     EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
1928   }
1929 };
1930
1931 // This test will have different layer ordering on the impl thread; the test
1932 // will only work on the main thread.
1933 MAIN_THREAD_TEST(OcclusionTrackerTestUnsorted3dLayers);
1934
1935 template <class Types>
1936 class OcclusionTrackerTestPerspectiveTransform
1937     : public OcclusionTrackerTest<Types> {
1938  protected:
1939   explicit OcclusionTrackerTestPerspectiveTransform(bool opaque_layers)
1940       : OcclusionTrackerTest<Types>(opaque_layers) {}
1941   void RunMyTest() {
1942     gfx::Transform transform;
1943     transform.Translate(150.0, 150.0);
1944     transform.ApplyPerspectiveDepth(400.0);
1945     transform.RotateAboutXAxis(-30.0);
1946     transform.Translate(-150.0, -150.0);
1947
1948     typename Types::ContentLayerType* parent = this->CreateRoot(
1949         this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1950     typename Types::LayerType* container = this->CreateLayer(
1951         parent, this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
1952     typename Types::ContentLayerType* layer =
1953         this->CreateDrawingLayer(container,
1954                                  transform,
1955                                  gfx::PointF(100.f, 100.f),
1956                                  gfx::Size(200, 200),
1957                                  true);
1958     container->SetShouldFlattenTransform(false);
1959     container->Set3dSortingContextId(1);
1960     layer->Set3dSortingContextId(1);
1961     layer->SetShouldFlattenTransform(false);
1962
1963     this->CalcDrawEtc(parent);
1964
1965     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
1966         gfx::Rect(0, 0, 1000, 1000));
1967     this->EnterLayer(layer, &occlusion);
1968
1969     EXPECT_RECT_EQ(
1970         gfx::Rect(0, 0, 200, 200),
1971         occlusion.UnoccludedLayerContentRect(layer, gfx::Rect(0, 0, 200, 200)));
1972   }
1973 };
1974
1975 // This test requires accumulating occlusion of 3d layers, which are skipped by
1976 // the occlusion tracker on the main thread. So this test should run on the impl
1977 // thread.
1978 IMPL_THREAD_TEST(OcclusionTrackerTestPerspectiveTransform);
1979 template <class Types>
1980 class OcclusionTrackerTestPerspectiveTransformBehindCamera
1981     : public OcclusionTrackerTest<Types> {
1982  protected:
1983   explicit OcclusionTrackerTestPerspectiveTransformBehindCamera(
1984       bool opaque_layers)
1985       : OcclusionTrackerTest<Types>(opaque_layers) {}
1986   void RunMyTest() {
1987     // This test is based on the platform/chromium/compositing/3d-corners.html
1988     // layout test.
1989     gfx::Transform transform;
1990     transform.Translate(250.0, 50.0);
1991     transform.ApplyPerspectiveDepth(10.0);
1992     transform.Translate(-250.0, -50.0);
1993     transform.Translate(250.0, 50.0);
1994     transform.RotateAboutXAxis(-167.0);
1995     transform.Translate(-250.0, -50.0);
1996
1997     typename Types::ContentLayerType* parent = this->CreateRoot(
1998         this->identity_matrix, gfx::PointF(), gfx::Size(500, 100));
1999     typename Types::LayerType* container = this->CreateLayer(
2000         parent, this->identity_matrix, gfx::PointF(), gfx::Size(500, 500));
2001     typename Types::ContentLayerType* layer = this->CreateDrawingLayer(
2002         container, transform, gfx::PointF(), gfx::Size(500, 500), true);
2003     container->SetShouldFlattenTransform(false);
2004     container->Set3dSortingContextId(1);
2005     layer->SetShouldFlattenTransform(false);
2006     layer->Set3dSortingContextId(1);
2007     this->CalcDrawEtc(parent);
2008
2009     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2010         gfx::Rect(0, 0, 1000, 1000));
2011     this->EnterLayer(layer, &occlusion);
2012
2013     // The bottom 11 pixel rows of this layer remain visible inside the
2014     // container, after translation to the target surface. When translated back,
2015     // this will include many more pixels but must include at least the bottom
2016     // 11 rows.
2017     EXPECT_TRUE(occlusion.UnoccludedLayerContentRect(
2018         layer, gfx::Rect(0, 26, 500, 474)).
2019             Contains(gfx::Rect(0, 489, 500, 11)));
2020   }
2021 };
2022
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
2025 // thread.
2026 IMPL_THREAD_TEST(OcclusionTrackerTestPerspectiveTransformBehindCamera);
2027
2028 template <class Types>
2029 class OcclusionTrackerTestLayerBehindCameraDoesNotOcclude
2030     : public OcclusionTrackerTest<Types> {
2031  protected:
2032   explicit OcclusionTrackerTestLayerBehindCameraDoesNotOcclude(
2033       bool opaque_layers)
2034       : OcclusionTrackerTest<Types>(opaque_layers) {}
2035   void RunMyTest() {
2036     gfx::Transform transform;
2037     transform.Translate(50.0, 50.0);
2038     transform.ApplyPerspectiveDepth(100.0);
2039     transform.Translate3d(0.0, 0.0, 110.0);
2040     transform.Translate(-50.0, -50.0);
2041
2042     typename Types::ContentLayerType* parent = this->CreateRoot(
2043         this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
2044     typename Types::ContentLayerType* layer = this->CreateDrawingLayer(
2045         parent, transform, gfx::PointF(), gfx::Size(100, 100), true);
2046     parent->SetShouldFlattenTransform(false);
2047     parent->Set3dSortingContextId(1);
2048     layer->SetShouldFlattenTransform(false);
2049     layer->Set3dSortingContextId(1);
2050     this->CalcDrawEtc(parent);
2051
2052     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2053         gfx::Rect(0, 0, 1000, 1000));
2054
2055     // The |layer| is entirely behind the camera and should not occlude.
2056     this->VisitLayer(layer, &occlusion);
2057     this->EnterLayer(parent, &occlusion);
2058     EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
2059     EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
2060   }
2061 };
2062
2063 // This test requires accumulating occlusion of 3d layers, which are skipped by
2064 // the occlusion tracker on the main thread. So this test should run on the impl
2065 // thread.
2066 IMPL_THREAD_TEST(OcclusionTrackerTestLayerBehindCameraDoesNotOcclude);
2067
2068 template <class Types>
2069 class OcclusionTrackerTestLargePixelsOccludeInsideClipRect
2070     : public OcclusionTrackerTest<Types> {
2071  protected:
2072   explicit OcclusionTrackerTestLargePixelsOccludeInsideClipRect(
2073       bool opaque_layers)
2074       : OcclusionTrackerTest<Types>(opaque_layers) {}
2075   void RunMyTest() {
2076     gfx::Transform transform;
2077     transform.Translate(50.0, 50.0);
2078     transform.ApplyPerspectiveDepth(100.0);
2079     transform.Translate3d(0.0, 0.0, 99.0);
2080     transform.Translate(-50.0, -50.0);
2081
2082     typename Types::ContentLayerType* parent = this->CreateRoot(
2083         this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
2084     parent->SetMasksToBounds(true);
2085     typename Types::ContentLayerType* layer = this->CreateDrawingLayer(
2086         parent, transform, gfx::PointF(), gfx::Size(100, 100), true);
2087     parent->SetShouldFlattenTransform(false);
2088     parent->Set3dSortingContextId(1);
2089     layer->SetShouldFlattenTransform(false);
2090     layer->Set3dSortingContextId(1);
2091     this->CalcDrawEtc(parent);
2092
2093     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2094         gfx::Rect(0, 0, 1000, 1000));
2095
2096     // This is very close to the camera, so pixels in its visible_content_rect()
2097     // will actually go outside of the layer's clip rect.  Ensure that those
2098     // pixels don't occlude things outside the clip rect.
2099     this->VisitLayer(layer, &occlusion);
2100     this->EnterLayer(parent, &occlusion);
2101     EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
2102               occlusion.occlusion_from_inside_target().ToString());
2103     EXPECT_EQ(gfx::Rect().ToString(),
2104               occlusion.occlusion_from_outside_target().ToString());
2105   }
2106 };
2107
2108 // This test requires accumulating occlusion of 3d layers, which are skipped by
2109 // the occlusion tracker on the main thread. So this test should run on the impl
2110 // thread.
2111 IMPL_THREAD_TEST(OcclusionTrackerTestLargePixelsOccludeInsideClipRect);
2112
2113 template <class Types>
2114 class OcclusionTrackerTestAnimationOpacity1OnMainThread
2115     : public OcclusionTrackerTest<Types> {
2116  protected:
2117   explicit OcclusionTrackerTestAnimationOpacity1OnMainThread(bool opaque_layers)
2118       : OcclusionTrackerTest<Types>(opaque_layers) {}
2119   void RunMyTest() {
2120     // parent
2121     // +--layer
2122     // +--surface
2123     // |  +--surface_child
2124     // |  +--surface_child2
2125     // +--parent2
2126     // +--topmost
2127
2128     typename Types::ContentLayerType* parent = this->CreateRoot(
2129         this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
2130     typename Types::ContentLayerType* layer =
2131         this->CreateDrawingLayer(parent,
2132                                  this->identity_matrix,
2133                                  gfx::PointF(),
2134                                  gfx::Size(300, 300),
2135                                  true);
2136     typename Types::ContentLayerType* surface =
2137         this->CreateDrawingSurface(parent,
2138                                    this->identity_matrix,
2139                                    gfx::PointF(),
2140                                    gfx::Size(300, 300),
2141                                    true);
2142     typename Types::ContentLayerType* surface_child =
2143         this->CreateDrawingLayer(surface,
2144                                  this->identity_matrix,
2145                                  gfx::PointF(),
2146                                  gfx::Size(200, 300),
2147                                  true);
2148     typename Types::ContentLayerType* surface_child2 =
2149         this->CreateDrawingLayer(surface,
2150                                  this->identity_matrix,
2151                                  gfx::PointF(),
2152                                  gfx::Size(100, 300),
2153                                  true);
2154     typename Types::ContentLayerType* parent2 =
2155         this->CreateDrawingLayer(parent,
2156                                  this->identity_matrix,
2157                                  gfx::PointF(),
2158                                  gfx::Size(300, 300),
2159                                  false);
2160     typename Types::ContentLayerType* topmost =
2161         this->CreateDrawingLayer(parent,
2162                                  this->identity_matrix,
2163                                  gfx::PointF(250.f, 0.f),
2164                                  gfx::Size(50, 300),
2165                                  true);
2166
2167     AddOpacityTransitionToController(
2168         layer->layer_animation_controller(), 10.0, 0.f, 1.f, false);
2169     AddOpacityTransitionToController(
2170         surface->layer_animation_controller(), 10.0, 0.f, 1.f, false);
2171     this->CalcDrawEtc(parent);
2172
2173     EXPECT_TRUE(layer->draw_opacity_is_animating());
2174     EXPECT_FALSE(surface->draw_opacity_is_animating());
2175     EXPECT_TRUE(surface->render_surface()->draw_opacity_is_animating());
2176
2177     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2178         gfx::Rect(0, 0, 1000, 1000));
2179
2180     this->VisitLayer(topmost, &occlusion);
2181     this->EnterLayer(parent2, &occlusion);
2182     // This occlusion will affect all surfaces.
2183     EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2184               occlusion.occlusion_from_inside_target().ToString());
2185     EXPECT_EQ(gfx::Rect().ToString(),
2186               occlusion.occlusion_from_outside_target().ToString());
2187     EXPECT_EQ(gfx::Rect(0, 0, 250, 300).ToString(),
2188               occlusion.UnoccludedLayerContentRect(
2189                   parent2, gfx::Rect(0, 0, 300, 300)).ToString());
2190     this->LeaveLayer(parent2, &occlusion);
2191
2192     this->VisitLayer(surface_child2, &occlusion);
2193     this->EnterLayer(surface_child, &occlusion);
2194     EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(),
2195               occlusion.occlusion_from_inside_target().ToString());
2196     EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2197               occlusion.occlusion_from_outside_target().ToString());
2198     EXPECT_RECT_EQ(gfx::Rect(100, 0, 100, 300),
2199                    occlusion.UnoccludedLayerContentRect(
2200                        surface_child, gfx::Rect(0, 0, 200, 300)));
2201     this->LeaveLayer(surface_child, &occlusion);
2202     this->EnterLayer(surface, &occlusion);
2203     EXPECT_EQ(gfx::Rect(0, 0, 200, 300).ToString(),
2204               occlusion.occlusion_from_inside_target().ToString());
2205     EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2206               occlusion.occlusion_from_outside_target().ToString());
2207     EXPECT_RECT_EQ(gfx::Rect(200, 0, 50, 300),
2208                    occlusion.UnoccludedLayerContentRect(
2209                        surface, gfx::Rect(0, 0, 300, 300)));
2210     this->LeaveLayer(surface, &occlusion);
2211
2212     this->EnterContributingSurface(surface, &occlusion);
2213     // Occlusion within the surface is lost when leaving the animating surface.
2214     EXPECT_EQ(gfx::Rect().ToString(),
2215               occlusion.occlusion_from_inside_target().ToString());
2216     EXPECT_EQ(gfx::Rect().ToString(),
2217               occlusion.occlusion_from_outside_target().ToString());
2218     EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
2219                    occlusion.UnoccludedSurfaceContentRect(
2220                        surface, false, gfx::Rect(0, 0, 300, 300)));
2221     this->LeaveContributingSurface(surface, &occlusion);
2222
2223     // Occlusion from outside the animating surface still exists.
2224     EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2225               occlusion.occlusion_from_inside_target().ToString());
2226     EXPECT_EQ(gfx::Rect().ToString(),
2227               occlusion.occlusion_from_outside_target().ToString());
2228
2229     this->VisitLayer(layer, &occlusion);
2230     this->EnterLayer(parent, &occlusion);
2231
2232     // Occlusion is not added for the animating |layer|.
2233     EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
2234                    occlusion.UnoccludedLayerContentRect(
2235                        parent, gfx::Rect(0, 0, 300, 300)));
2236   }
2237 };
2238
2239 MAIN_THREAD_TEST(OcclusionTrackerTestAnimationOpacity1OnMainThread);
2240
2241 template <class Types>
2242 class OcclusionTrackerTestAnimationOpacity0OnMainThread
2243     : public OcclusionTrackerTest<Types> {
2244  protected:
2245   explicit OcclusionTrackerTestAnimationOpacity0OnMainThread(bool opaque_layers)
2246       : OcclusionTrackerTest<Types>(opaque_layers) {}
2247   void RunMyTest() {
2248     typename Types::ContentLayerType* parent = this->CreateRoot(
2249         this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
2250     typename Types::ContentLayerType* layer =
2251         this->CreateDrawingLayer(parent,
2252                                  this->identity_matrix,
2253                                  gfx::PointF(),
2254                                  gfx::Size(300, 300),
2255                                  true);
2256     typename Types::ContentLayerType* surface =
2257         this->CreateDrawingSurface(parent,
2258                                    this->identity_matrix,
2259                                    gfx::PointF(),
2260                                    gfx::Size(300, 300),
2261                                    true);
2262     typename Types::ContentLayerType* surface_child =
2263         this->CreateDrawingLayer(surface,
2264                                  this->identity_matrix,
2265                                  gfx::PointF(),
2266                                  gfx::Size(200, 300),
2267                                  true);
2268     typename Types::ContentLayerType* surface_child2 =
2269         this->CreateDrawingLayer(surface,
2270                                  this->identity_matrix,
2271                                  gfx::PointF(),
2272                                  gfx::Size(100, 300),
2273                                  true);
2274     typename Types::ContentLayerType* parent2 =
2275         this->CreateDrawingLayer(parent,
2276                                  this->identity_matrix,
2277                                  gfx::PointF(),
2278                                  gfx::Size(300, 300),
2279                                  false);
2280     typename Types::ContentLayerType* topmost =
2281         this->CreateDrawingLayer(parent,
2282                                  this->identity_matrix,
2283                                  gfx::PointF(250.f, 0.f),
2284                                  gfx::Size(50, 300),
2285                                  true);
2286
2287     AddOpacityTransitionToController(
2288         layer->layer_animation_controller(), 10.0, 1.f, 0.f, false);
2289     AddOpacityTransitionToController(
2290         surface->layer_animation_controller(), 10.0, 1.f, 0.f, false);
2291     this->CalcDrawEtc(parent);
2292
2293     EXPECT_TRUE(layer->draw_opacity_is_animating());
2294     EXPECT_FALSE(surface->draw_opacity_is_animating());
2295     EXPECT_TRUE(surface->render_surface()->draw_opacity_is_animating());
2296
2297     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2298         gfx::Rect(0, 0, 1000, 1000));
2299
2300     this->VisitLayer(topmost, &occlusion);
2301     this->EnterLayer(parent2, &occlusion);
2302     // This occlusion will affect all surfaces.
2303     EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2304               occlusion.occlusion_from_inside_target().ToString());
2305     EXPECT_EQ(gfx::Rect().ToString(),
2306               occlusion.occlusion_from_outside_target().ToString());
2307     EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
2308                    occlusion.UnoccludedLayerContentRect(
2309                        parent, gfx::Rect(0, 0, 300, 300)));
2310     this->LeaveLayer(parent2, &occlusion);
2311
2312     this->VisitLayer(surface_child2, &occlusion);
2313     this->EnterLayer(surface_child, &occlusion);
2314     EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(),
2315               occlusion.occlusion_from_inside_target().ToString());
2316     EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2317               occlusion.occlusion_from_outside_target().ToString());
2318     EXPECT_RECT_EQ(gfx::Rect(100, 0, 100, 300),
2319                    occlusion.UnoccludedLayerContentRect(
2320                        surface_child, gfx::Rect(0, 0, 200, 300)));
2321     this->LeaveLayer(surface_child, &occlusion);
2322     this->EnterLayer(surface, &occlusion);
2323     EXPECT_EQ(gfx::Rect(0, 0, 200, 300).ToString(),
2324               occlusion.occlusion_from_inside_target().ToString());
2325     EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2326               occlusion.occlusion_from_outside_target().ToString());
2327     EXPECT_RECT_EQ(gfx::Rect(200, 0, 50, 300),
2328                    occlusion.UnoccludedLayerContentRect(
2329                        surface, gfx::Rect(0, 0, 300, 300)));
2330     this->LeaveLayer(surface, &occlusion);
2331
2332     this->EnterContributingSurface(surface, &occlusion);
2333     // Occlusion within the surface is lost when leaving the animating surface.
2334     EXPECT_EQ(gfx::Rect().ToString(),
2335               occlusion.occlusion_from_inside_target().ToString());
2336     EXPECT_EQ(gfx::Rect().ToString(),
2337               occlusion.occlusion_from_outside_target().ToString());
2338     EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
2339                    occlusion.UnoccludedSurfaceContentRect(
2340                        surface, false, gfx::Rect(0, 0, 300, 300)));
2341     this->LeaveContributingSurface(surface, &occlusion);
2342
2343     // Occlusion from outside the animating surface still exists.
2344     EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(),
2345               occlusion.occlusion_from_inside_target().ToString());
2346     EXPECT_EQ(gfx::Rect().ToString(),
2347               occlusion.occlusion_from_outside_target().ToString());
2348
2349     this->VisitLayer(layer, &occlusion);
2350     this->EnterLayer(parent, &occlusion);
2351
2352     // Occlusion is not added for the animating |layer|.
2353     EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300),
2354                    occlusion.UnoccludedLayerContentRect(
2355                        parent, gfx::Rect(0, 0, 300, 300)));
2356   }
2357 };
2358
2359 MAIN_THREAD_TEST(OcclusionTrackerTestAnimationOpacity0OnMainThread);
2360
2361 template <class Types>
2362 class OcclusionTrackerTestAnimationTranslateOnMainThread
2363     : public OcclusionTrackerTest<Types> {
2364  protected:
2365   explicit OcclusionTrackerTestAnimationTranslateOnMainThread(
2366       bool opaque_layers)
2367       : OcclusionTrackerTest<Types>(opaque_layers) {}
2368   void RunMyTest() {
2369     typename Types::ContentLayerType* parent = this->CreateRoot(
2370         this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
2371     typename Types::ContentLayerType* layer =
2372         this->CreateDrawingLayer(parent,
2373                                  this->identity_matrix,
2374                                  gfx::PointF(),
2375                                  gfx::Size(300, 300),
2376                                  true);
2377     typename Types::ContentLayerType* surface =
2378         this->CreateDrawingSurface(parent,
2379                                    this->identity_matrix,
2380                                    gfx::PointF(),
2381                                    gfx::Size(300, 300),
2382                                    true);
2383     typename Types::ContentLayerType* surface_child =
2384         this->CreateDrawingLayer(surface,
2385                                  this->identity_matrix,
2386                                  gfx::PointF(),
2387                                  gfx::Size(200, 300),
2388                                  true);
2389     typename Types::ContentLayerType* surface_child2 =
2390         this->CreateDrawingLayer(surface,
2391                                  this->identity_matrix,
2392                                  gfx::PointF(),
2393                                  gfx::Size(100, 300),
2394                                  true);
2395     typename Types::ContentLayerType* surface2 = this->CreateDrawingSurface(
2396         parent, this->identity_matrix, gfx::PointF(), gfx::Size(50, 300), true);
2397
2398     AddAnimatedTransformToController(
2399         layer->layer_animation_controller(), 10.0, 30, 0);
2400     AddAnimatedTransformToController(
2401         surface->layer_animation_controller(), 10.0, 30, 0);
2402     AddAnimatedTransformToController(
2403         surface_child->layer_animation_controller(), 10.0, 30, 0);
2404     this->CalcDrawEtc(parent);
2405
2406     EXPECT_TRUE(layer->draw_transform_is_animating());
2407     EXPECT_TRUE(layer->screen_space_transform_is_animating());
2408     EXPECT_TRUE(
2409         surface->render_surface()->target_surface_transforms_are_animating());
2410     EXPECT_TRUE(
2411         surface->render_surface()->screen_space_transforms_are_animating());
2412     // The surface owning layer doesn't animate against its own surface.
2413     EXPECT_FALSE(surface->draw_transform_is_animating());
2414     EXPECT_TRUE(surface->screen_space_transform_is_animating());
2415     EXPECT_TRUE(surface_child->draw_transform_is_animating());
2416     EXPECT_TRUE(surface_child->screen_space_transform_is_animating());
2417
2418     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2419         gfx::Rect(0, 0, 1000, 1000));
2420
2421     this->VisitLayer(surface2, &occlusion);
2422     this->EnterContributingSurface(surface2, &occlusion);
2423
2424     EXPECT_EQ(gfx::Rect(0, 0, 50, 300).ToString(),
2425               occlusion.occlusion_from_inside_target().ToString());
2426
2427     this->LeaveContributingSurface(surface2, &occlusion);
2428     this->EnterLayer(surface_child2, &occlusion);
2429     // surface_child2 is moving in screen space but not relative to its target,
2430     // so occlusion should happen in its target space only.  It also means that
2431     // things occluding from outside the target (e.g. surface2) cannot occlude
2432     // this layer.
2433     EXPECT_EQ(gfx::Rect().ToString(),
2434               occlusion.occlusion_from_outside_target().ToString());
2435     EXPECT_EQ(gfx::Rect().ToString(),
2436               occlusion.occlusion_from_inside_target().ToString());
2437
2438     this->LeaveLayer(surface_child2, &occlusion);
2439     this->EnterLayer(surface_child, &occlusion);
2440     // surface_child2 added to the occlusion since it is not moving relative
2441     // to its target.
2442     EXPECT_EQ(gfx::Rect().ToString(),
2443               occlusion.occlusion_from_outside_target().ToString());
2444     EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(),
2445               occlusion.occlusion_from_inside_target().ToString());
2446
2447     this->LeaveLayer(surface_child, &occlusion);
2448     // surface_child is moving relative to its target, so it does not add
2449     // occlusion.
2450     EXPECT_EQ(gfx::Rect().ToString(),
2451               occlusion.occlusion_from_outside_target().ToString());
2452     EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(),
2453               occlusion.occlusion_from_inside_target().ToString());
2454
2455     this->EnterLayer(surface, &occlusion);
2456     EXPECT_EQ(gfx::Rect().ToString(),
2457               occlusion.occlusion_from_outside_target().ToString());
2458     EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(),
2459               occlusion.occlusion_from_inside_target().ToString());
2460
2461     this->LeaveLayer(surface, &occlusion);
2462     // The surface's owning layer is moving in screen space but not relative to
2463     // its target, so it adds to the occlusion.
2464     EXPECT_EQ(gfx::Rect().ToString(),
2465               occlusion.occlusion_from_outside_target().ToString());
2466     EXPECT_EQ(gfx::Rect(0, 0, 300, 300).ToString(),
2467               occlusion.occlusion_from_inside_target().ToString());
2468
2469     this->EnterContributingSurface(surface, &occlusion);
2470     this->LeaveContributingSurface(surface, &occlusion);
2471     // The |surface| is moving in the screen and in its target, so all occlusion
2472     // within the surface is lost when leaving it. Only the |surface2| occlusion
2473     // is left.
2474     EXPECT_EQ(gfx::Rect().ToString(),
2475               occlusion.occlusion_from_outside_target().ToString());
2476     EXPECT_EQ(gfx::Rect(0, 0, 50, 300).ToString(),
2477               occlusion.occlusion_from_inside_target().ToString());
2478
2479     this->VisitLayer(layer, &occlusion);
2480     // The |layer| is animating in the screen and in its target, so no occlusion
2481     // is added.
2482     EXPECT_EQ(gfx::Rect().ToString(),
2483               occlusion.occlusion_from_outside_target().ToString());
2484     EXPECT_EQ(gfx::Rect(0, 0, 50, 300).ToString(),
2485               occlusion.occlusion_from_inside_target().ToString());
2486   }
2487 };
2488
2489 MAIN_THREAD_TEST(OcclusionTrackerTestAnimationTranslateOnMainThread);
2490
2491 template <class Types>
2492 class OcclusionTrackerTestSurfaceOcclusionTranslatesToParent
2493     : public OcclusionTrackerTest<Types> {
2494  protected:
2495   explicit OcclusionTrackerTestSurfaceOcclusionTranslatesToParent(
2496       bool opaque_layers)
2497       : OcclusionTrackerTest<Types>(opaque_layers) {}
2498   void RunMyTest() {
2499     gfx::Transform surface_transform;
2500     surface_transform.Translate(300.0, 300.0);
2501     surface_transform.Scale(2.0, 2.0);
2502     surface_transform.Translate(-150.0, -150.0);
2503
2504     typename Types::ContentLayerType* parent = this->CreateRoot(
2505         this->identity_matrix, gfx::PointF(), gfx::Size(500, 500));
2506     typename Types::ContentLayerType* surface = this->CreateDrawingSurface(
2507         parent, surface_transform, gfx::PointF(), gfx::Size(300, 300), false);
2508     typename Types::ContentLayerType* surface2 =
2509         this->CreateDrawingSurface(parent,
2510                                    this->identity_matrix,
2511                                    gfx::PointF(50.f, 50.f),
2512                                    gfx::Size(300, 300),
2513                                    false);
2514     surface->SetOpaqueContentsRect(gfx::Rect(0, 0, 200, 200));
2515     surface2->SetOpaqueContentsRect(gfx::Rect(0, 0, 200, 200));
2516     this->CalcDrawEtc(parent);
2517
2518     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2519         gfx::Rect(0, 0, 1000, 1000));
2520
2521     this->VisitLayer(surface2, &occlusion);
2522     this->VisitContributingSurface(surface2, &occlusion);
2523
2524     EXPECT_EQ(gfx::Rect().ToString(),
2525               occlusion.occlusion_from_outside_target().ToString());
2526     EXPECT_EQ(gfx::Rect(50, 50, 200, 200).ToString(),
2527               occlusion.occlusion_from_inside_target().ToString());
2528
2529     // Clear any stored occlusion.
2530     occlusion.set_occlusion_from_outside_target(Region());
2531     occlusion.set_occlusion_from_inside_target(Region());
2532
2533     this->VisitLayer(surface, &occlusion);
2534     this->VisitContributingSurface(surface, &occlusion);
2535
2536     EXPECT_EQ(gfx::Rect().ToString(),
2537               occlusion.occlusion_from_outside_target().ToString());
2538     EXPECT_EQ(gfx::Rect(0, 0, 400, 400).ToString(),
2539               occlusion.occlusion_from_inside_target().ToString());
2540   }
2541 };
2542
2543 MAIN_AND_IMPL_THREAD_TEST(
2544     OcclusionTrackerTestSurfaceOcclusionTranslatesToParent);
2545
2546 template <class Types>
2547 class OcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping
2548     : public OcclusionTrackerTest<Types> {
2549  protected:
2550   explicit OcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping(
2551       bool opaque_layers)
2552       : OcclusionTrackerTest<Types>(opaque_layers) {}
2553   void RunMyTest() {
2554     typename Types::ContentLayerType* parent = this->CreateRoot(
2555         this->identity_matrix, gfx::PointF(), gfx::Size(300, 300));
2556     parent->SetMasksToBounds(true);
2557     typename Types::ContentLayerType* surface =
2558         this->CreateDrawingSurface(parent,
2559                                    this->identity_matrix,
2560                                    gfx::PointF(),
2561                                    gfx::Size(500, 300),
2562                                    false);
2563     surface->SetOpaqueContentsRect(gfx::Rect(0, 0, 400, 200));
2564     this->CalcDrawEtc(parent);
2565
2566     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2567         gfx::Rect(0, 0, 1000, 1000));
2568
2569     this->VisitLayer(surface, &occlusion);
2570     this->VisitContributingSurface(surface, &occlusion);
2571
2572     EXPECT_EQ(gfx::Rect().ToString(),
2573               occlusion.occlusion_from_outside_target().ToString());
2574     EXPECT_EQ(gfx::Rect(0, 0, 300, 200).ToString(),
2575               occlusion.occlusion_from_inside_target().ToString());
2576   }
2577 };
2578
2579 MAIN_AND_IMPL_THREAD_TEST(
2580     OcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping);
2581
2582 template <class Types>
2583 class OcclusionTrackerTestReplicaOccluded : public OcclusionTrackerTest<Types> {
2584  protected:
2585   explicit OcclusionTrackerTestReplicaOccluded(bool opaque_layers)
2586       : OcclusionTrackerTest<Types>(opaque_layers) {}
2587   void RunMyTest() {
2588     typename Types::ContentLayerType* parent = this->CreateRoot(
2589         this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
2590     typename Types::LayerType* surface =
2591         this->CreateDrawingSurface(parent,
2592                                    this->identity_matrix,
2593                                    gfx::PointF(),
2594                                    gfx::Size(100, 100),
2595                                    true);
2596     this->CreateReplicaLayer(surface,
2597                              this->identity_matrix,
2598                              gfx::PointF(0.f, 100.f),
2599                              gfx::Size(100, 100));
2600     typename Types::LayerType* topmost =
2601         this->CreateDrawingLayer(parent,
2602                                  this->identity_matrix,
2603                                  gfx::PointF(0.f, 100.f),
2604                                  gfx::Size(100, 100),
2605                                  true);
2606     this->CalcDrawEtc(parent);
2607
2608     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2609         gfx::Rect(0, 0, 1000, 1000));
2610
2611     // |topmost| occludes the replica, but not the surface itself.
2612     this->VisitLayer(topmost, &occlusion);
2613
2614     EXPECT_EQ(gfx::Rect().ToString(),
2615               occlusion.occlusion_from_outside_target().ToString());
2616     EXPECT_EQ(gfx::Rect(0, 100, 100, 100).ToString(),
2617               occlusion.occlusion_from_inside_target().ToString());
2618
2619     this->VisitLayer(surface, &occlusion);
2620
2621     // Render target with replica ignores occlusion from outside.
2622     EXPECT_EQ(gfx::Rect().ToString(),
2623               occlusion.occlusion_from_outside_target().ToString());
2624     EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
2625               occlusion.occlusion_from_inside_target().ToString());
2626
2627     this->EnterContributingSurface(surface, &occlusion);
2628
2629     // Surface is not occluded so it shouldn't think it is.
2630     EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 100),
2631                    occlusion.UnoccludedSurfaceContentRect(
2632                        surface, false, gfx::Rect(0, 0, 100, 100)));
2633   }
2634 };
2635
2636 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaOccluded);
2637
2638 template <class Types>
2639 class OcclusionTrackerTestSurfaceWithReplicaUnoccluded
2640     : public OcclusionTrackerTest<Types> {
2641  protected:
2642   explicit OcclusionTrackerTestSurfaceWithReplicaUnoccluded(bool opaque_layers)
2643       : OcclusionTrackerTest<Types>(opaque_layers) {}
2644   void RunMyTest() {
2645     typename Types::ContentLayerType* parent = this->CreateRoot(
2646         this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
2647     typename Types::LayerType* surface =
2648         this->CreateDrawingSurface(parent,
2649                                    this->identity_matrix,
2650                                    gfx::PointF(),
2651                                    gfx::Size(100, 100),
2652                                    true);
2653     this->CreateReplicaLayer(surface,
2654                              this->identity_matrix,
2655                              gfx::PointF(0.f, 100.f),
2656                              gfx::Size(100, 100));
2657     typename Types::LayerType* topmost =
2658         this->CreateDrawingLayer(parent,
2659                                  this->identity_matrix,
2660                                  gfx::PointF(),
2661                                  gfx::Size(100, 110),
2662                                  true);
2663     this->CalcDrawEtc(parent);
2664
2665     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2666         gfx::Rect(0, 0, 1000, 1000));
2667
2668     // |topmost| occludes the surface, but not the entire surface's replica.
2669     this->VisitLayer(topmost, &occlusion);
2670
2671     EXPECT_EQ(gfx::Rect().ToString(),
2672               occlusion.occlusion_from_outside_target().ToString());
2673     EXPECT_EQ(gfx::Rect(0, 0, 100, 110).ToString(),
2674               occlusion.occlusion_from_inside_target().ToString());
2675
2676     this->VisitLayer(surface, &occlusion);
2677
2678     // Render target with replica ignores occlusion from outside.
2679     EXPECT_EQ(gfx::Rect().ToString(),
2680               occlusion.occlusion_from_outside_target().ToString());
2681     EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
2682               occlusion.occlusion_from_inside_target().ToString());
2683
2684     this->EnterContributingSurface(surface, &occlusion);
2685
2686     // Surface is occluded, but only the top 10px of the replica.
2687     EXPECT_RECT_EQ(gfx::Rect(0, 0, 0, 0),
2688                    occlusion.UnoccludedSurfaceContentRect(
2689                        surface, false, gfx::Rect(0, 0, 100, 100)));
2690     EXPECT_RECT_EQ(gfx::Rect(0, 10, 100, 90),
2691                    occlusion.UnoccludedSurfaceContentRect(
2692                        surface, true, gfx::Rect(0, 0, 100, 100)));
2693   }
2694 };
2695
2696 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceWithReplicaUnoccluded);
2697
2698 template <class Types>
2699 class OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently
2700     : public OcclusionTrackerTest<Types> {
2701  protected:
2702   explicit OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently(
2703       bool opaque_layers)
2704       : OcclusionTrackerTest<Types>(opaque_layers) {}
2705   void RunMyTest() {
2706     typename Types::ContentLayerType* parent = this->CreateRoot(
2707         this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
2708     typename Types::LayerType* surface =
2709         this->CreateDrawingSurface(parent,
2710                                    this->identity_matrix,
2711                                    gfx::PointF(),
2712                                    gfx::Size(100, 100),
2713                                    true);
2714     this->CreateReplicaLayer(surface,
2715                              this->identity_matrix,
2716                              gfx::PointF(0.f, 100.f),
2717                              gfx::Size(100, 100));
2718     typename Types::LayerType* over_surface = this->CreateDrawingLayer(
2719         parent, this->identity_matrix, gfx::PointF(), gfx::Size(40, 100), true);
2720     typename Types::LayerType* over_replica =
2721         this->CreateDrawingLayer(parent,
2722                                  this->identity_matrix,
2723                                  gfx::PointF(0.f, 100.f),
2724                                  gfx::Size(50, 100),
2725                                  true);
2726     this->CalcDrawEtc(parent);
2727
2728     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2729         gfx::Rect(0, 0, 1000, 1000));
2730
2731     // These occlude the surface and replica differently, so we can test each
2732     // one.
2733     this->VisitLayer(over_replica, &occlusion);
2734     this->VisitLayer(over_surface, &occlusion);
2735
2736     EXPECT_EQ(gfx::Rect().ToString(),
2737               occlusion.occlusion_from_outside_target().ToString());
2738     EXPECT_EQ(UnionRegions(gfx::Rect(0, 0, 40, 100), gfx::Rect(0, 100, 50, 100))
2739                   .ToString(),
2740               occlusion.occlusion_from_inside_target().ToString());
2741
2742     this->VisitLayer(surface, &occlusion);
2743
2744     // Render target with replica ignores occlusion from outside.
2745     EXPECT_EQ(gfx::Rect().ToString(),
2746               occlusion.occlusion_from_outside_target().ToString());
2747     EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
2748               occlusion.occlusion_from_inside_target().ToString());
2749
2750     this->EnterContributingSurface(surface, &occlusion);
2751
2752     // Surface and replica are occluded different amounts.
2753     EXPECT_RECT_EQ(gfx::Rect(40, 0, 60, 100),
2754                    occlusion.UnoccludedSurfaceContentRect(
2755                        surface, false, gfx::Rect(0, 0, 100, 100)));
2756     EXPECT_RECT_EQ(gfx::Rect(50, 0, 50, 100),
2757                    occlusion.UnoccludedSurfaceContentRect(
2758                        surface, true, gfx::Rect(0, 0, 100, 100)));
2759   }
2760 };
2761
2762 ALL_OCCLUSIONTRACKER_TEST(
2763     OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently);
2764
2765 template <class Types>
2766 class OcclusionTrackerTestSurfaceChildOfSurface
2767     : public OcclusionTrackerTest<Types> {
2768  protected:
2769   explicit OcclusionTrackerTestSurfaceChildOfSurface(bool opaque_layers)
2770       : OcclusionTrackerTest<Types>(opaque_layers) {}
2771   void RunMyTest() {
2772     // This test verifies that the surface cliprect does not end up empty and
2773     // clip away the entire unoccluded rect.
2774
2775     typename Types::ContentLayerType* parent = this->CreateRoot(
2776         this->identity_matrix, gfx::PointF(), gfx::Size(100, 200));
2777     typename Types::LayerType* surface =
2778         this->CreateDrawingSurface(parent,
2779                                    this->identity_matrix,
2780                                    gfx::PointF(),
2781                                    gfx::Size(100, 100),
2782                                    true);
2783     typename Types::LayerType* surface_child =
2784         this->CreateDrawingSurface(surface,
2785                                    this->identity_matrix,
2786                                    gfx::PointF(0.f, 10.f),
2787                                    gfx::Size(100, 50),
2788                                    true);
2789     typename Types::LayerType* topmost = this->CreateDrawingLayer(
2790         parent, this->identity_matrix, gfx::PointF(), gfx::Size(100, 50), true);
2791     this->CalcDrawEtc(parent);
2792
2793     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2794         gfx::Rect(-100, -100, 1000, 1000));
2795
2796     // |topmost| occludes everything partially so we know occlusion is happening
2797     // at all.
2798     this->VisitLayer(topmost, &occlusion);
2799
2800     EXPECT_EQ(gfx::Rect().ToString(),
2801               occlusion.occlusion_from_outside_target().ToString());
2802     EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
2803               occlusion.occlusion_from_inside_target().ToString());
2804
2805     this->VisitLayer(surface_child, &occlusion);
2806
2807     // surface_child increases the occlusion in the screen by a narrow sliver.
2808     EXPECT_EQ(gfx::Rect(0, -10, 100, 50).ToString(),
2809               occlusion.occlusion_from_outside_target().ToString());
2810     // In its own surface, surface_child is at 0,0 as is its occlusion.
2811     EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
2812               occlusion.occlusion_from_inside_target().ToString());
2813
2814     // The root layer always has a clip rect. So the parent of |surface| has a
2815     // clip rect. However, the owning layer for |surface| does not mask to
2816     // bounds, so it doesn't have a clip rect of its own. Thus the parent of
2817     // |surface_child| exercises different code paths as its parent does not
2818     // have a clip rect.
2819
2820     this->EnterContributingSurface(surface_child, &occlusion);
2821     // The surface_child's parent does not have a clip rect as it owns a render
2822     // surface. Make sure the unoccluded rect does not get clipped away
2823     // inappropriately.
2824     EXPECT_RECT_EQ(gfx::Rect(0, 40, 100, 10),
2825                    occlusion.UnoccludedSurfaceContentRect(
2826                        surface_child, false, gfx::Rect(0, 0, 100, 50)));
2827     this->LeaveContributingSurface(surface_child, &occlusion);
2828
2829     // When the surface_child's occlusion is transformed up to its parent, make
2830     // sure it is not clipped away inappropriately also.
2831     this->EnterLayer(surface, &occlusion);
2832     EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
2833               occlusion.occlusion_from_outside_target().ToString());
2834     EXPECT_EQ(gfx::Rect(0, 10, 100, 50).ToString(),
2835               occlusion.occlusion_from_inside_target().ToString());
2836     this->LeaveLayer(surface, &occlusion);
2837
2838     this->EnterContributingSurface(surface, &occlusion);
2839     // The surface's parent does have a clip rect as it is the root layer.
2840     EXPECT_RECT_EQ(gfx::Rect(0, 50, 100, 50),
2841                    occlusion.UnoccludedSurfaceContentRect(
2842                        surface, false, gfx::Rect(0, 0, 100, 100)));
2843   }
2844 };
2845
2846 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceChildOfSurface);
2847
2848 template <class Types>
2849 class OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter
2850     : public OcclusionTrackerTest<Types> {
2851  protected:
2852   explicit OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter(
2853       bool opaque_layers)
2854       : OcclusionTrackerTest<Types>(opaque_layers) {}
2855   void RunMyTest() {
2856     gfx::Transform scale_by_half;
2857     scale_by_half.Scale(0.5, 0.5);
2858
2859     // Make a 50x50 filtered surface that is completely surrounded by opaque
2860     // layers which are above it in the z-order.  The surface is scaled to test
2861     // that the pixel moving is done in the target space, where the background
2862     // filter is applied.
2863     typename Types::ContentLayerType* parent = this->CreateRoot(
2864         this->identity_matrix, gfx::PointF(), gfx::Size(200, 150));
2865     typename Types::LayerType* filtered_surface =
2866         this->CreateDrawingLayer(parent,
2867                                  scale_by_half,
2868                                  gfx::PointF(50.f, 50.f),
2869                                  gfx::Size(100, 100),
2870                                  false);
2871     typename Types::LayerType* occluding_layer1 = this->CreateDrawingLayer(
2872         parent, this->identity_matrix, gfx::PointF(), gfx::Size(200, 50), true);
2873     typename Types::LayerType* occluding_layer2 =
2874         this->CreateDrawingLayer(parent,
2875                                  this->identity_matrix,
2876                                  gfx::PointF(0.f, 100.f),
2877                                  gfx::Size(200, 50),
2878                                  true);
2879     typename Types::LayerType* occluding_layer3 =
2880         this->CreateDrawingLayer(parent,
2881                                  this->identity_matrix,
2882                                  gfx::PointF(0.f, 50.f),
2883                                  gfx::Size(50, 50),
2884                                  true);
2885     typename Types::LayerType* occluding_layer4 =
2886         this->CreateDrawingLayer(parent,
2887                                  this->identity_matrix,
2888                                  gfx::PointF(100.f, 50.f),
2889                                  gfx::Size(100, 50),
2890                                  true);
2891
2892     // Filters make the layer own a surface.
2893     FilterOperations filters;
2894     filters.Append(FilterOperation::CreateBlurFilter(10.f));
2895     filtered_surface->SetBackgroundFilters(filters);
2896
2897     // Save the distance of influence for the blur effect.
2898     int outset_top, outset_right, outset_bottom, outset_left;
2899     filters.GetOutsets(
2900         &outset_top, &outset_right, &outset_bottom, &outset_left);
2901
2902     this->CalcDrawEtc(parent);
2903
2904     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
2905         gfx::Rect(0, 0, 1000, 1000));
2906
2907     // These layers occlude pixels directly beside the filtered_surface. Because
2908     // filtered surface blends pixels in a radius, it will need to see some of
2909     // the pixels (up to radius far) underneath the occluding layers.
2910     this->VisitLayer(occluding_layer4, &occlusion);
2911     this->VisitLayer(occluding_layer3, &occlusion);
2912     this->VisitLayer(occluding_layer2, &occlusion);
2913     this->VisitLayer(occluding_layer1, &occlusion);
2914
2915     Region expected_occlusion;
2916     expected_occlusion.Union(gfx::Rect(0, 0, 200, 50));
2917     expected_occlusion.Union(gfx::Rect(0, 50, 50, 50));
2918     expected_occlusion.Union(gfx::Rect(100, 50, 100, 50));
2919     expected_occlusion.Union(gfx::Rect(0, 100, 200, 50));
2920
2921     EXPECT_EQ(expected_occlusion.ToString(),
2922               occlusion.occlusion_from_inside_target().ToString());
2923     EXPECT_EQ(gfx::Rect().ToString(),
2924               occlusion.occlusion_from_outside_target().ToString());
2925
2926     this->VisitLayer(filtered_surface, &occlusion);
2927
2928     // The filtered layer does not occlude.
2929     Region expected_occlusion_outside_surface;
2930     expected_occlusion_outside_surface.Union(gfx::Rect(-50, -50, 200, 50));
2931     expected_occlusion_outside_surface.Union(gfx::Rect(-50, 0, 50, 50));
2932     expected_occlusion_outside_surface.Union(gfx::Rect(50, 0, 100, 50));
2933     expected_occlusion_outside_surface.Union(gfx::Rect(-50, 50, 200, 50));
2934
2935     EXPECT_EQ(expected_occlusion_outside_surface.ToString(),
2936               occlusion.occlusion_from_outside_target().ToString());
2937     EXPECT_EQ(gfx::Rect().ToString(),
2938               occlusion.occlusion_from_inside_target().ToString());
2939
2940     // The surface has a background blur, so it needs pixels that are currently
2941     // considered occluded in order to be drawn. So the pixels it needs should
2942     // be removed some the occluded area so that when we get to the parent they
2943     // are drawn.
2944     this->VisitContributingSurface(filtered_surface, &occlusion);
2945
2946     this->EnterLayer(parent, &occlusion);
2947
2948     Region expected_blurred_occlusion;
2949     expected_blurred_occlusion.Union(gfx::Rect(0, 0, 200, 50 - outset_top));
2950     expected_blurred_occlusion.Union(gfx::Rect(
2951         0, 50 - outset_top, 50 - outset_left, 50 + outset_top + outset_bottom));
2952     expected_blurred_occlusion.Union(
2953         gfx::Rect(100 + outset_right,
2954                   50 - outset_top,
2955                   100 - outset_right,
2956                   50 + outset_top + outset_bottom));
2957     expected_blurred_occlusion.Union(
2958         gfx::Rect(0, 100 + outset_bottom, 200, 50 - outset_bottom));
2959
2960     EXPECT_EQ(expected_blurred_occlusion.ToString(),
2961               occlusion.occlusion_from_inside_target().ToString());
2962     EXPECT_EQ(gfx::Rect().ToString(),
2963               occlusion.occlusion_from_outside_target().ToString());
2964
2965     gfx::Rect outset_rect;
2966     gfx::Rect test_rect;
2967
2968     // Nothing in the blur outsets for the filtered_surface is occluded.
2969     outset_rect = gfx::Rect(50 - outset_left,
2970                             50 - outset_top,
2971                             50 + outset_left + outset_right,
2972                             50 + outset_top + outset_bottom);
2973     test_rect = outset_rect;
2974     EXPECT_EQ(
2975         outset_rect.ToString(),
2976         occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
2977
2978     // Stuff outside the blur outsets is still occluded though.
2979     test_rect = outset_rect;
2980     test_rect.Inset(0, 0, -1, 0);
2981     EXPECT_EQ(
2982         outset_rect.ToString(),
2983         occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
2984     test_rect = outset_rect;
2985     test_rect.Inset(0, 0, 0, -1);
2986     EXPECT_EQ(
2987         outset_rect.ToString(),
2988         occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
2989     test_rect = outset_rect;
2990     test_rect.Inset(-1, 0, 0, 0);
2991     EXPECT_EQ(
2992         outset_rect.ToString(),
2993         occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
2994     test_rect = outset_rect;
2995     test_rect.Inset(0, -1, 0, 0);
2996     EXPECT_EQ(
2997         outset_rect.ToString(),
2998         occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString());
2999   }
3000 };
3001
3002 ALL_OCCLUSIONTRACKER_TEST(
3003     OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter);
3004
3005 template <class Types>
3006 class OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice
3007     : public OcclusionTrackerTest<Types> {
3008  protected:
3009   explicit OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice(
3010       bool opaque_layers)
3011       : OcclusionTrackerTest<Types>(opaque_layers) {}
3012   void RunMyTest() {
3013     gfx::Transform scale_by_half;
3014     scale_by_half.Scale(0.5, 0.5);
3015
3016     // Makes two surfaces that completely cover |parent|. The occlusion both
3017     // above and below the filters will be reduced by each of them.
3018     typename Types::ContentLayerType* root = this->CreateRoot(
3019         this->identity_matrix, gfx::PointF(), gfx::Size(75, 75));
3020     typename Types::LayerType* parent = this->CreateSurface(
3021         root, scale_by_half, gfx::PointF(), gfx::Size(150, 150));
3022     parent->SetMasksToBounds(true);
3023     typename Types::LayerType* filtered_surface1 = this->CreateDrawingLayer(
3024         parent, scale_by_half, gfx::PointF(), gfx::Size(300, 300), false);
3025     typename Types::LayerType* filtered_surface2 = this->CreateDrawingLayer(
3026         parent, scale_by_half, gfx::PointF(), gfx::Size(300, 300), false);
3027     typename Types::LayerType* occluding_layer_above =
3028         this->CreateDrawingLayer(parent,
3029                                  this->identity_matrix,
3030                                  gfx::PointF(100.f, 100.f),
3031                                  gfx::Size(50, 50),
3032                                  true);
3033
3034     // Filters make the layers own surfaces.
3035     FilterOperations filters;
3036     filters.Append(FilterOperation::CreateBlurFilter(1.f));
3037     filtered_surface1->SetBackgroundFilters(filters);
3038     filtered_surface2->SetBackgroundFilters(filters);
3039
3040     // Save the distance of influence for the blur effect.
3041     int outset_top, outset_right, outset_bottom, outset_left;
3042     filters.GetOutsets(
3043         &outset_top, &outset_right, &outset_bottom, &outset_left);
3044
3045     this->CalcDrawEtc(root);
3046
3047     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3048         gfx::Rect(0, 0, 1000, 1000));
3049
3050     this->VisitLayer(occluding_layer_above, &occlusion);
3051     EXPECT_EQ(gfx::Rect().ToString(),
3052               occlusion.occlusion_from_outside_target().ToString());
3053     EXPECT_EQ(gfx::Rect(100 / 2, 100 / 2, 50 / 2, 50 / 2).ToString(),
3054               occlusion.occlusion_from_inside_target().ToString());
3055
3056     this->VisitLayer(filtered_surface2, &occlusion);
3057     this->VisitContributingSurface(filtered_surface2, &occlusion);
3058     this->VisitLayer(filtered_surface1, &occlusion);
3059     this->VisitContributingSurface(filtered_surface1, &occlusion);
3060
3061     // Test expectations in the target.
3062     gfx::Rect expected_occlusion =
3063         gfx::Rect(100 / 2 + outset_right * 2,
3064                   100 / 2 + outset_bottom * 2,
3065                   50 / 2 - (outset_left + outset_right) * 2,
3066                   50 / 2 - (outset_top + outset_bottom) * 2);
3067     EXPECT_EQ(expected_occlusion.ToString(),
3068               occlusion.occlusion_from_inside_target().ToString());
3069
3070     // Test expectations in the screen are the same as in the target, as the
3071     // render surface is 1:1 with the screen.
3072     EXPECT_EQ(expected_occlusion.ToString(),
3073               occlusion.occlusion_from_outside_target().ToString());
3074   }
3075 };
3076
3077 ALL_OCCLUSIONTRACKER_TEST(
3078     OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice);
3079
3080 template <class Types>
3081 class OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter
3082     : public OcclusionTrackerTest<Types> {
3083  protected:
3084   explicit OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter(
3085       bool opaque_layers)
3086       : OcclusionTrackerTest<Types>(opaque_layers) {}
3087   void RunMyTest() {
3088     gfx::Transform scale_by_half;
3089     scale_by_half.Scale(0.5, 0.5);
3090
3091     // Make a surface and its replica, each 50x50, with a smaller 30x30 layer
3092     // centered below each.  The surface is scaled to test that the pixel moving
3093     // is done in the target space, where the background filter is applied, but
3094     // the surface appears at 50, 50 and the replica at 200, 50.
3095     typename Types::ContentLayerType* parent = this->CreateRoot(
3096         this->identity_matrix, gfx::PointF(), gfx::Size(300, 150));
3097     typename Types::LayerType* behind_surface_layer =
3098         this->CreateDrawingLayer(parent,
3099                                  this->identity_matrix,
3100                                  gfx::PointF(60.f, 60.f),
3101                                  gfx::Size(30, 30),
3102                                  true);
3103     typename Types::LayerType* behind_replica_layer =
3104         this->CreateDrawingLayer(parent,
3105                                  this->identity_matrix,
3106                                  gfx::PointF(210.f, 60.f),
3107                                  gfx::Size(30, 30),
3108                                  true);
3109     typename Types::LayerType* filtered_surface =
3110         this->CreateDrawingLayer(parent,
3111                                  scale_by_half,
3112                                  gfx::PointF(50.f, 50.f),
3113                                  gfx::Size(100, 100),
3114                                  false);
3115     this->CreateReplicaLayer(filtered_surface,
3116                              this->identity_matrix,
3117                              gfx::PointF(300.f, 0.f),
3118                              gfx::Size());
3119
3120     // Filters make the layer own a surface.
3121     FilterOperations filters;
3122     filters.Append(FilterOperation::CreateBlurFilter(3.f));
3123     filtered_surface->SetBackgroundFilters(filters);
3124
3125     this->CalcDrawEtc(parent);
3126
3127     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3128         gfx::Rect(0, 0, 1000, 1000));
3129
3130     // The surface has a background blur, so it blurs non-opaque pixels below
3131     // it.
3132     this->VisitLayer(filtered_surface, &occlusion);
3133     this->VisitContributingSurface(filtered_surface, &occlusion);
3134
3135     this->VisitLayer(behind_replica_layer, &occlusion);
3136     this->VisitLayer(behind_surface_layer, &occlusion);
3137
3138     // The layers behind the surface are not blurred, and their occlusion does
3139     // not change, until we leave the surface.  So it should not be modified by
3140     // the filter here.
3141     gfx::Rect occlusion_behind_surface = gfx::Rect(60, 60, 30, 30);
3142     gfx::Rect occlusion_behind_replica = gfx::Rect(210, 60, 30, 30);
3143
3144     Region expected_opaque_bounds =
3145         UnionRegions(occlusion_behind_surface, occlusion_behind_replica);
3146     EXPECT_EQ(expected_opaque_bounds.ToString(),
3147               occlusion.occlusion_from_inside_target().ToString());
3148
3149     EXPECT_EQ(gfx::Rect().ToString(),
3150               occlusion.occlusion_from_outside_target().ToString());
3151   }
3152 };
3153
3154 ALL_OCCLUSIONTRACKER_TEST(
3155     OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter);
3156
3157 template <class Types>
3158 class OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded
3159     : public OcclusionTrackerTest<Types> {
3160  protected:
3161   explicit OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded(
3162       bool opaque_layers)
3163       : OcclusionTrackerTest<Types>(opaque_layers) {}
3164   void RunMyTest() {
3165     gfx::Transform scale_by_half;
3166     scale_by_half.Scale(0.5, 0.5);
3167
3168     // Make a 50x50 filtered surface that is completely occluded by an opaque
3169     // layer which is above it in the z-order.  The surface is
3170     // scaled to test that the pixel moving is done in the target space, where
3171     // the background filter is applied, but the surface appears at 50, 50.
3172     typename Types::ContentLayerType* parent = this->CreateRoot(
3173         this->identity_matrix, gfx::PointF(), gfx::Size(200, 150));
3174     typename Types::LayerType* filtered_surface =
3175         this->CreateDrawingLayer(parent,
3176                                  scale_by_half,
3177                                  gfx::PointF(50.f, 50.f),
3178                                  gfx::Size(100, 100),
3179                                  false);
3180     typename Types::LayerType* occluding_layer =
3181         this->CreateDrawingLayer(parent,
3182                                  this->identity_matrix,
3183                                  gfx::PointF(50.f, 50.f),
3184                                  gfx::Size(50, 50),
3185                                  true);
3186
3187     // Filters make the layer own a surface.
3188     FilterOperations filters;
3189     filters.Append(FilterOperation::CreateBlurFilter(3.f));
3190     filtered_surface->SetBackgroundFilters(filters);
3191
3192     this->CalcDrawEtc(parent);
3193
3194     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3195         gfx::Rect(0, 0, 1000, 1000));
3196
3197     this->VisitLayer(occluding_layer, &occlusion);
3198
3199     this->VisitLayer(filtered_surface, &occlusion);
3200     {
3201       // The layers above the filtered surface occlude from outside.
3202       gfx::Rect occlusion_above_surface = gfx::Rect(0, 0, 50, 50);
3203
3204       EXPECT_EQ(gfx::Rect().ToString(),
3205                 occlusion.occlusion_from_inside_target().ToString());
3206       EXPECT_EQ(occlusion_above_surface.ToString(),
3207                 occlusion.occlusion_from_outside_target().ToString());
3208     }
3209
3210     // The surface has a background blur, so it blurs non-opaque pixels below
3211     // it.
3212     this->VisitContributingSurface(filtered_surface, &occlusion);
3213     {
3214       // The filter is completely occluded, so it should not blur anything and
3215       // reduce any occlusion.
3216       gfx::Rect occlusion_above_surface = gfx::Rect(50, 50, 50, 50);
3217
3218       EXPECT_EQ(occlusion_above_surface.ToString(),
3219                 occlusion.occlusion_from_inside_target().ToString());
3220       EXPECT_EQ(gfx::Rect().ToString(),
3221                 occlusion.occlusion_from_outside_target().ToString());
3222     }
3223   }
3224 };
3225
3226 ALL_OCCLUSIONTRACKER_TEST(
3227     OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded);
3228
3229 template <class Types>
3230 class OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded
3231     : public OcclusionTrackerTest<Types> {
3232  protected:
3233   explicit
3234   OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded(
3235       bool opaque_layers)
3236       : OcclusionTrackerTest<Types>(opaque_layers) {}
3237   void RunMyTest() {
3238     gfx::Transform scale_by_half;
3239     scale_by_half.Scale(0.5, 0.5);
3240
3241     // Make a surface and its replica, each 50x50, that are partially occluded
3242     // by opaque layers which are above them in the z-order.  The surface is
3243     // scaled to test that the pixel moving is done in the target space, where
3244     // the background filter is applied, but the surface appears at 50, 50 and
3245     // the replica at 200, 50.
3246     typename Types::ContentLayerType* parent = this->CreateRoot(
3247         this->identity_matrix, gfx::PointF(), gfx::Size(300, 150));
3248     typename Types::LayerType* filtered_surface =
3249         this->CreateDrawingLayer(parent,
3250                                  scale_by_half,
3251                                  gfx::PointF(50.f, 50.f),
3252                                  gfx::Size(100, 100),
3253                                  false);
3254     this->CreateReplicaLayer(filtered_surface,
3255                              this->identity_matrix,
3256                              gfx::PointF(300.f, 0.f),
3257                              gfx::Size());
3258     typename Types::LayerType* above_surface_layer =
3259         this->CreateDrawingLayer(parent,
3260                                  this->identity_matrix,
3261                                  gfx::PointF(70.f, 50.f),
3262                                  gfx::Size(30, 50),
3263                                  true);
3264     typename Types::LayerType* above_replica_layer =
3265         this->CreateDrawingLayer(parent,
3266                                  this->identity_matrix,
3267                                  gfx::PointF(200.f, 50.f),
3268                                  gfx::Size(30, 50),
3269                                  true);
3270     typename Types::LayerType* beside_surface_layer =
3271         this->CreateDrawingLayer(parent,
3272                                  this->identity_matrix,
3273                                  gfx::PointF(90.f, 40.f),
3274                                  gfx::Size(10, 10),
3275                                  true);
3276     typename Types::LayerType* beside_replica_layer =
3277         this->CreateDrawingLayer(parent,
3278                                  this->identity_matrix,
3279                                  gfx::PointF(200.f, 40.f),
3280                                  gfx::Size(10, 10),
3281                                  true);
3282
3283     // Filters make the layer own a surface.
3284     FilterOperations filters;
3285     filters.Append(FilterOperation::CreateBlurFilter(3.f));
3286     filtered_surface->SetBackgroundFilters(filters);
3287
3288     // Save the distance of influence for the blur effect.
3289     int outset_top, outset_right, outset_bottom, outset_left;
3290     filters.GetOutsets(
3291         &outset_top, &outset_right, &outset_bottom, &outset_left);
3292
3293     this->CalcDrawEtc(parent);
3294
3295     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3296         gfx::Rect(0, 0, 1000, 1000));
3297
3298     this->VisitLayer(beside_replica_layer, &occlusion);
3299     this->VisitLayer(beside_surface_layer, &occlusion);
3300     this->VisitLayer(above_replica_layer, &occlusion);
3301     this->VisitLayer(above_surface_layer, &occlusion);
3302
3303     // The surface has a background blur, so it blurs non-opaque pixels below
3304     // it.
3305     this->VisitLayer(filtered_surface, &occlusion);
3306     this->VisitContributingSurface(filtered_surface, &occlusion);
3307
3308     // The filter in the surface and replica are partially unoccluded. Only the
3309     // unoccluded parts should reduce occlusion.  This means it will push back
3310     // the occlusion that touches the unoccluded part (occlusion_above___), but
3311     // it will not touch occlusion_beside____ since that is not beside the
3312     // unoccluded part of the surface, even though it is beside the occluded
3313     // part of the surface.
3314     gfx::Rect occlusion_above_surface =
3315         gfx::Rect(70 + outset_right, 50, 30 - outset_right, 50);
3316     gfx::Rect occlusion_above_replica =
3317         gfx::Rect(200, 50, 30 - outset_left, 50);
3318     gfx::Rect occlusion_beside_surface = gfx::Rect(90, 40, 10, 10);
3319     gfx::Rect occlusion_beside_replica = gfx::Rect(200, 40, 10, 10);
3320
3321     Region expected_occlusion;
3322     expected_occlusion.Union(occlusion_above_surface);
3323     expected_occlusion.Union(occlusion_above_replica);
3324     expected_occlusion.Union(occlusion_beside_surface);
3325     expected_occlusion.Union(occlusion_beside_replica);
3326
3327     ASSERT_EQ(expected_occlusion.ToString(),
3328               occlusion.occlusion_from_inside_target().ToString());
3329     EXPECT_EQ(gfx::Rect().ToString(),
3330               occlusion.occlusion_from_outside_target().ToString());
3331
3332     Region::Iterator expected_rects(expected_occlusion);
3333     Region::Iterator target_surface_rects(
3334         occlusion.occlusion_from_inside_target());
3335     for (; expected_rects.has_rect();
3336          expected_rects.next(), target_surface_rects.next()) {
3337       ASSERT_TRUE(target_surface_rects.has_rect());
3338       EXPECT_EQ(expected_rects.rect(), target_surface_rects.rect());
3339     }
3340   }
3341 };
3342
3343 ALL_OCCLUSIONTRACKER_TEST(
3344     OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded);
3345
3346 template <class Types>
3347 class OcclusionTrackerTestMinimumTrackingSize
3348     : public OcclusionTrackerTest<Types> {
3349  protected:
3350   explicit OcclusionTrackerTestMinimumTrackingSize(bool opaque_layers)
3351       : OcclusionTrackerTest<Types>(opaque_layers) {}
3352   void RunMyTest() {
3353     gfx::Size tracking_size(100, 100);
3354     gfx::Size below_tracking_size(99, 99);
3355
3356     typename Types::ContentLayerType* parent = this->CreateRoot(
3357         this->identity_matrix, gfx::PointF(), gfx::Size(400, 400));
3358     typename Types::LayerType* large = this->CreateDrawingLayer(
3359         parent, this->identity_matrix, gfx::PointF(), tracking_size, true);
3360     typename Types::LayerType* small =
3361         this->CreateDrawingLayer(parent,
3362                                  this->identity_matrix,
3363                                  gfx::PointF(),
3364                                  below_tracking_size,
3365                                  true);
3366     this->CalcDrawEtc(parent);
3367
3368     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3369         gfx::Rect(0, 0, 1000, 1000));
3370     occlusion.set_minimum_tracking_size(tracking_size);
3371
3372     // The small layer is not tracked because it is too small.
3373     this->VisitLayer(small, &occlusion);
3374
3375     EXPECT_EQ(gfx::Rect().ToString(),
3376               occlusion.occlusion_from_outside_target().ToString());
3377     EXPECT_EQ(gfx::Rect().ToString(),
3378               occlusion.occlusion_from_inside_target().ToString());
3379
3380     // The large layer is tracked as it is large enough.
3381     this->VisitLayer(large, &occlusion);
3382
3383     EXPECT_EQ(gfx::Rect().ToString(),
3384               occlusion.occlusion_from_outside_target().ToString());
3385     EXPECT_EQ(gfx::Rect(tracking_size).ToString(),
3386               occlusion.occlusion_from_inside_target().ToString());
3387   }
3388 };
3389
3390 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestMinimumTrackingSize);
3391
3392 template <class Types>
3393 class OcclusionTrackerTestScaledLayerIsClipped
3394     : public OcclusionTrackerTest<Types> {
3395  protected:
3396   explicit OcclusionTrackerTestScaledLayerIsClipped(bool opaque_layers)
3397       : OcclusionTrackerTest<Types>(opaque_layers) {}
3398   void RunMyTest() {
3399     gfx::Transform scale_transform;
3400     scale_transform.Scale(512.0, 512.0);
3401
3402     typename Types::ContentLayerType* parent = this->CreateRoot(
3403         this->identity_matrix, gfx::PointF(), gfx::Size(400, 400));
3404     typename Types::LayerType* clip = this->CreateLayer(parent,
3405                                                         this->identity_matrix,
3406                                                         gfx::PointF(10.f, 10.f),
3407                                                         gfx::Size(50, 50));
3408     clip->SetMasksToBounds(true);
3409     typename Types::LayerType* scale = this->CreateLayer(
3410         clip, scale_transform, gfx::PointF(), gfx::Size(1, 1));
3411     typename Types::LayerType* scaled = this->CreateDrawingLayer(
3412         scale, this->identity_matrix, gfx::PointF(), gfx::Size(500, 500), true);
3413     this->CalcDrawEtc(parent);
3414
3415     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3416         gfx::Rect(0, 0, 1000, 1000));
3417
3418     this->VisitLayer(scaled, &occlusion);
3419
3420     EXPECT_EQ(gfx::Rect().ToString(),
3421               occlusion.occlusion_from_outside_target().ToString());
3422     EXPECT_EQ(gfx::Rect(10, 10, 50, 50).ToString(),
3423               occlusion.occlusion_from_inside_target().ToString());
3424   }
3425 };
3426
3427 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestScaledLayerIsClipped)
3428
3429 template <class Types>
3430 class OcclusionTrackerTestScaledLayerInSurfaceIsClipped
3431     : public OcclusionTrackerTest<Types> {
3432  protected:
3433   explicit OcclusionTrackerTestScaledLayerInSurfaceIsClipped(bool opaque_layers)
3434       : OcclusionTrackerTest<Types>(opaque_layers) {}
3435   void RunMyTest() {
3436     gfx::Transform scale_transform;
3437     scale_transform.Scale(512.0, 512.0);
3438
3439     typename Types::ContentLayerType* parent = this->CreateRoot(
3440         this->identity_matrix, gfx::PointF(), gfx::Size(400, 400));
3441     typename Types::LayerType* clip = this->CreateLayer(parent,
3442                                                         this->identity_matrix,
3443                                                         gfx::PointF(10.f, 10.f),
3444                                                         gfx::Size(50, 50));
3445     clip->SetMasksToBounds(true);
3446     typename Types::LayerType* surface = this->CreateDrawingSurface(
3447         clip, this->identity_matrix, gfx::PointF(), gfx::Size(400, 30), false);
3448     typename Types::LayerType* scale = this->CreateLayer(
3449         surface, scale_transform, gfx::PointF(), gfx::Size(1, 1));
3450     typename Types::LayerType* scaled = this->CreateDrawingLayer(
3451         scale, this->identity_matrix, gfx::PointF(), gfx::Size(500, 500), true);
3452     this->CalcDrawEtc(parent);
3453
3454     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3455         gfx::Rect(0, 0, 1000, 1000));
3456
3457     this->VisitLayer(scaled, &occlusion);
3458     this->VisitLayer(surface, &occlusion);
3459     this->VisitContributingSurface(surface, &occlusion);
3460
3461     EXPECT_EQ(gfx::Rect().ToString(),
3462               occlusion.occlusion_from_outside_target().ToString());
3463     EXPECT_EQ(gfx::Rect(10, 10, 50, 50).ToString(),
3464               occlusion.occlusion_from_inside_target().ToString());
3465   }
3466 };
3467
3468 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestScaledLayerInSurfaceIsClipped)
3469
3470 template <class Types>
3471 class OcclusionTrackerTestCopyRequestDoesOcclude
3472     : public OcclusionTrackerTest<Types> {
3473  protected:
3474   explicit OcclusionTrackerTestCopyRequestDoesOcclude(bool opaque_layers)
3475       : OcclusionTrackerTest<Types>(opaque_layers) {}
3476   void RunMyTest() {
3477     typename Types::ContentLayerType* root = this->CreateRoot(
3478         this->identity_matrix, gfx::Point(), gfx::Size(400, 400));
3479     typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
3480         root, this->identity_matrix, gfx::Point(), gfx::Size(400, 400), true);
3481     typename Types::LayerType* copy = this->CreateLayer(parent,
3482                                                         this->identity_matrix,
3483                                                         gfx::Point(100, 0),
3484                                                         gfx::Size(200, 400));
3485     this->AddCopyRequest(copy);
3486     typename Types::LayerType* copy_child = this->CreateDrawingLayer(
3487         copy,
3488         this->identity_matrix,
3489         gfx::PointF(),
3490         gfx::Size(200, 400),
3491         true);
3492     this->CalcDrawEtc(root);
3493
3494     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3495         gfx::Rect(0, 0, 1000, 1000));
3496
3497     this->VisitLayer(copy_child, &occlusion);
3498     EXPECT_EQ(gfx::Rect().ToString(),
3499               occlusion.occlusion_from_outside_target().ToString());
3500     EXPECT_EQ(gfx::Rect(200, 400).ToString(),
3501               occlusion.occlusion_from_inside_target().ToString());
3502
3503     // CopyRequests cause the layer to own a surface.
3504     this->VisitContributingSurface(copy, &occlusion);
3505
3506     // The occlusion from the copy should be kept.
3507     EXPECT_EQ(gfx::Rect().ToString(),
3508               occlusion.occlusion_from_outside_target().ToString());
3509     EXPECT_EQ(gfx::Rect(100, 0, 200, 400).ToString(),
3510               occlusion.occlusion_from_inside_target().ToString());
3511   }
3512 };
3513
3514 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestCopyRequestDoesOcclude)
3515
3516 template <class Types>
3517 class OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude
3518     : public OcclusionTrackerTest<Types> {
3519  protected:
3520   explicit OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude(
3521       bool opaque_layers)
3522       : OcclusionTrackerTest<Types>(opaque_layers) {}
3523   void RunMyTest() {
3524     typename Types::ContentLayerType* root = this->CreateRoot(
3525         this->identity_matrix, gfx::Point(), gfx::Size(400, 400));
3526     typename Types::ContentLayerType* parent = this->CreateDrawingLayer(
3527         root, this->identity_matrix, gfx::Point(), gfx::Size(400, 400), true);
3528     typename Types::LayerType* hide = this->CreateLayer(
3529         parent, this->identity_matrix, gfx::Point(), gfx::Size());
3530     typename Types::LayerType* copy = this->CreateLayer(
3531         hide, this->identity_matrix, gfx::Point(100, 0), gfx::Size(200, 400));
3532     this->AddCopyRequest(copy);
3533     typename Types::LayerType* copy_child = this->CreateDrawingLayer(
3534         copy, this->identity_matrix, gfx::PointF(), gfx::Size(200, 400), true);
3535
3536     // The |copy| layer is hidden but since it is being copied, it will be
3537     // drawn.
3538     hide->SetHideLayerAndSubtree(true);
3539
3540     this->CalcDrawEtc(root);
3541
3542     TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
3543         gfx::Rect(0, 0, 1000, 1000));
3544
3545     this->VisitLayer(copy_child, &occlusion);
3546     EXPECT_EQ(gfx::Rect().ToString(),
3547               occlusion.occlusion_from_outside_target().ToString());
3548     EXPECT_EQ(gfx::Rect(200, 400).ToString(),
3549               occlusion.occlusion_from_inside_target().ToString());
3550
3551     // CopyRequests cause the layer to own a surface.
3552     this->VisitContributingSurface(copy, &occlusion);
3553
3554     // The occlusion from the copy should be dropped since it is hidden.
3555     EXPECT_EQ(gfx::Rect().ToString(),
3556               occlusion.occlusion_from_outside_target().ToString());
3557     EXPECT_EQ(gfx::Rect().ToString(),
3558               occlusion.occlusion_from_inside_target().ToString());
3559   }
3560 };
3561
3562 ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude)
3563
3564 }  // namespace
3565 }  // namespace cc