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