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