4e5f9dc88f3f8149905d68fa473d2674844dbc19
[WebKit-https.git] / Source / WebKit / chromium / tests / CCOcclusionTrackerTest.cpp
1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "config.h"
26
27 #include "CCOcclusionTracker.h"
28
29 #include "CCAnimationTestCommon.h"
30 #include "CCLayerAnimationController.h"
31 #include "CCLayerImpl.h"
32 #include "CCLayerTreeHostCommon.h"
33 #include "CCLayerTreeTestCommon.h"
34 #include "CCMathUtil.h"
35 #include "CCOcclusionTrackerTestCommon.h"
36 #include "CCOverdrawMetrics.h"
37 #include "CCSingleThreadProxy.h"
38 #include "LayerChromium.h"
39 #include "Region.h"
40 #include <gmock/gmock.h>
41 #include <gtest/gtest.h>
42 #include <public/WebFilterOperation.h>
43 #include <public/WebFilterOperations.h>
44 #include <public/WebTransformationMatrix.h>
45
46 using namespace WebCore;
47 using namespace WebKit;
48 using namespace WebKitTests;
49
50 namespace {
51
52 class TestContentLayerChromium : public LayerChromium {
53 public:
54     TestContentLayerChromium()
55         : LayerChromium()
56         , m_overrideOpaqueContentsRect(false)
57     {
58     }
59
60     virtual bool drawsContent() const OVERRIDE { return true; }
61     virtual Region visibleContentOpaqueRegion() const OVERRIDE
62     {
63         if (m_overrideOpaqueContentsRect)
64             return intersection(m_opaqueContentsRect, visibleContentRect());
65         return LayerChromium::visibleContentOpaqueRegion();
66     }
67     void setOpaqueContentsRect(const IntRect& opaqueContentsRect)
68     {
69         m_overrideOpaqueContentsRect = true;
70         m_opaqueContentsRect = opaqueContentsRect;
71     }
72
73 private:
74     bool m_overrideOpaqueContentsRect;
75     IntRect m_opaqueContentsRect;
76 };
77
78 class TestContentLayerImpl : public CCLayerImpl {
79 public:
80     TestContentLayerImpl(int id)
81         : CCLayerImpl(id)
82         , m_overrideOpaqueContentsRect(false)
83     {
84         setDrawsContent(true);
85     }
86
87     virtual Region visibleContentOpaqueRegion() const OVERRIDE
88     {
89         if (m_overrideOpaqueContentsRect)
90             return intersection(m_opaqueContentsRect, visibleContentRect());
91         return CCLayerImpl::visibleContentOpaqueRegion();
92     }
93     void setOpaqueContentsRect(const IntRect& opaqueContentsRect)
94     {
95         m_overrideOpaqueContentsRect = true;
96         m_opaqueContentsRect = opaqueContentsRect;
97     }
98
99 private:
100     bool m_overrideOpaqueContentsRect;
101     IntRect m_opaqueContentsRect;
102 };
103
104 template<typename LayerType, typename RenderSurfaceType>
105 class TestCCOcclusionTrackerWithClip : public TestCCOcclusionTrackerBase<LayerType, RenderSurfaceType> {
106 public:
107     TestCCOcclusionTrackerWithClip(IntRect viewportRect, bool recordMetricsForFrame = false)
108         : TestCCOcclusionTrackerBase<LayerType, RenderSurfaceType>(viewportRect, recordMetricsForFrame)
109         , m_overrideLayerClipRect(false)
110     {
111     }
112
113     void setLayerClipRect(const IntRect& rect) { m_overrideLayerClipRect = true; m_layerClipRect = rect;}
114     void useDefaultLayerClipRect() { m_overrideLayerClipRect = false; }
115
116 protected:
117     virtual IntRect layerClipRectInTarget(const LayerType* layer) const { return m_overrideLayerClipRect ? m_layerClipRect : CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::layerClipRectInTarget(layer); }
118
119 private:
120     bool m_overrideLayerClipRect;
121     IntRect m_layerClipRect;
122 };
123
124 struct CCOcclusionTrackerTestMainThreadTypes {
125     typedef LayerChromium LayerType;
126     typedef RenderSurfaceChromium RenderSurfaceType;
127     typedef TestContentLayerChromium ContentLayerType;
128     typedef RefPtr<LayerChromium> LayerPtrType;
129     typedef PassRefPtr<LayerChromium> PassLayerPtrType;
130     typedef RefPtr<ContentLayerType> ContentLayerPtrType;
131     typedef PassRefPtr<ContentLayerType> PassContentLayerPtrType;
132     typedef CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, CCLayerIteratorActions::FrontToBack> LayerIterator;
133     typedef CCOcclusionTracker OcclusionTrackerType;
134
135     static PassLayerPtrType createLayer()
136     {
137         return LayerChromium::create();
138     }
139     static PassContentLayerPtrType createContentLayer() { return adoptRef(new ContentLayerType()); }
140 };
141
142 struct CCOcclusionTrackerTestImplThreadTypes {
143     typedef CCLayerImpl LayerType;
144     typedef CCRenderSurface RenderSurfaceType;
145     typedef TestContentLayerImpl ContentLayerType;
146     typedef OwnPtr<CCLayerImpl> LayerPtrType;
147     typedef PassOwnPtr<CCLayerImpl> PassLayerPtrType;
148     typedef OwnPtr<ContentLayerType> ContentLayerPtrType;
149     typedef PassOwnPtr<ContentLayerType> PassContentLayerPtrType;
150     typedef CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, CCLayerIteratorActions::FrontToBack> LayerIterator;
151     typedef CCOcclusionTrackerImpl OcclusionTrackerType;
152
153     static PassLayerPtrType createLayer() { return CCLayerImpl::create(nextCCLayerImplId++); }
154     static PassContentLayerPtrType createContentLayer() { return adoptPtr(new ContentLayerType(nextCCLayerImplId++)); }
155     static int nextCCLayerImplId;
156 };
157
158 int CCOcclusionTrackerTestImplThreadTypes::nextCCLayerImplId = 1;
159
160 template<typename Types, bool opaqueLayers>
161 class CCOcclusionTrackerTest : public testing::Test {
162 protected:
163     CCOcclusionTrackerTest()
164         : testing::Test()
165     { }
166
167     virtual void runMyTest() = 0;
168
169     virtual void TearDown()
170     {
171         m_root.clear();
172         m_renderSurfaceLayerListChromium.clear();
173         m_renderSurfaceLayerListImpl.clear();
174         m_replicaLayers.clear();
175         m_maskLayers.clear();
176         CCLayerTreeHost::setNeedsFilterContext(false);
177     }
178
179     typename Types::ContentLayerType* createRoot(const WebTransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
180     {
181         typename Types::ContentLayerPtrType layer(Types::createContentLayer());
182         typename Types::ContentLayerType* layerPtr = layer.get();
183         setProperties(layerPtr, transform, position, bounds);
184
185         ASSERT(!m_root);
186         m_root = layer.release();
187         return layerPtr;
188     }
189
190     typename Types::LayerType* createLayer(typename Types::LayerType* parent, const WebTransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
191     {
192         typename Types::LayerPtrType layer(Types::createLayer());
193         typename Types::LayerType* layerPtr = layer.get();
194         setProperties(layerPtr, transform, position, bounds);
195         parent->addChild(layer.release());
196         return layerPtr;
197     }
198
199     typename Types::LayerType* createSurface(typename Types::LayerType* parent, const WebTransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
200     {
201         typename Types::LayerType* layer = createLayer(parent, transform, position, bounds);
202         WebFilterOperations filters;
203         filters.append(WebFilterOperation::createGrayscaleFilter(0.5));
204         layer->setFilters(filters);
205         return layer;
206     }
207
208     typename Types::ContentLayerType* createDrawingLayer(typename Types::LayerType* parent, const WebTransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds, bool opaque)
209     {
210         typename Types::ContentLayerPtrType layer(Types::createContentLayer());
211         typename Types::ContentLayerType* layerPtr = layer.get();
212         setProperties(layerPtr, transform, position, bounds);
213
214         if (opaqueLayers)
215             layerPtr->setOpaque(opaque);
216         else {
217             layerPtr->setOpaque(false);
218             if (opaque)
219                 layerPtr->setOpaqueContentsRect(IntRect(IntPoint(), bounds));
220             else
221                 layerPtr->setOpaqueContentsRect(IntRect());
222         }
223
224         parent->addChild(layer.release());
225         return layerPtr;
226     }
227
228     typename Types::LayerType* createReplicaLayer(typename Types::LayerType* owningLayer, const WebTransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
229     {
230         typename Types::ContentLayerPtrType layer(Types::createContentLayer());
231         typename Types::ContentLayerType* layerPtr = layer.get();
232         setProperties(layerPtr, transform, position, bounds);
233         setReplica(owningLayer, layer.release());
234         return layerPtr;
235     }
236
237     typename Types::LayerType* createMaskLayer(typename Types::LayerType* owningLayer, const IntSize& bounds)
238     {
239         typename Types::ContentLayerPtrType layer(Types::createContentLayer());
240         typename Types::ContentLayerType* layerPtr = layer.get();
241         setProperties(layerPtr, identityMatrix, FloatPoint(), bounds);
242         setMask(owningLayer, layer.release());
243         return layerPtr;
244     }
245
246     typename Types::ContentLayerType* createDrawingSurface(typename Types::LayerType* parent, const WebTransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds, bool opaque)
247     {
248         typename Types::ContentLayerType* layer = createDrawingLayer(parent, transform, position, bounds, opaque);
249         WebFilterOperations filters;
250         filters.append(WebFilterOperation::createGrayscaleFilter(0.5));
251         layer->setFilters(filters);
252         return layer;
253     }
254
255     void calcDrawEtc(TestContentLayerImpl* root)
256     {
257         ASSERT(root == m_root.get());
258         int dummyMaxTextureSize = 512;
259         CCLayerSorter layerSorter;
260
261         ASSERT(!root->renderSurface());
262
263         CCLayerTreeHostCommon::calculateDrawTransforms(root, root->bounds(), 1, &layerSorter, dummyMaxTextureSize, m_renderSurfaceLayerListImpl);
264         CCLayerTreeHostCommon::calculateVisibleRects(m_renderSurfaceLayerListImpl);
265
266         m_layerIterator = m_layerIteratorBegin = Types::LayerIterator::begin(&m_renderSurfaceLayerListImpl);
267     }
268
269     void calcDrawEtc(TestContentLayerChromium* root)
270     {
271         ASSERT(root == m_root.get());
272         int dummyMaxTextureSize = 512;
273
274         ASSERT(!root->renderSurface());
275
276         CCLayerTreeHostCommon::calculateDrawTransforms(root, root->bounds(), 1, dummyMaxTextureSize, m_renderSurfaceLayerListChromium);
277         CCLayerTreeHostCommon::calculateVisibleRects(m_renderSurfaceLayerListChromium);
278
279         m_layerIterator = m_layerIteratorBegin = Types::LayerIterator::begin(&m_renderSurfaceLayerListChromium);
280     }
281
282     void enterLayer(typename Types::LayerType* layer, typename Types::OcclusionTrackerType& occlusion)
283     {
284         ASSERT_EQ(layer, *m_layerIterator);
285         ASSERT_TRUE(m_layerIterator.representsItself());
286         occlusion.enterLayer(m_layerIterator);
287     }
288
289     void leaveLayer(typename Types::LayerType* layer, typename Types::OcclusionTrackerType& occlusion)
290     {
291         ASSERT_EQ(layer, *m_layerIterator);
292         ASSERT_TRUE(m_layerIterator.representsItself());
293         occlusion.leaveLayer(m_layerIterator);
294         ++m_layerIterator;
295     }
296
297     void visitLayer(typename Types::LayerType* layer, typename Types::OcclusionTrackerType& occlusion)
298     {
299         enterLayer(layer, occlusion);
300         leaveLayer(layer, occlusion);
301     }
302
303     void enterContributingSurface(typename Types::LayerType* layer, typename Types::OcclusionTrackerType& occlusion)
304     {
305         ASSERT_EQ(layer, *m_layerIterator);
306         ASSERT_TRUE(m_layerIterator.representsTargetRenderSurface());
307         occlusion.enterLayer(m_layerIterator);
308         occlusion.leaveLayer(m_layerIterator);
309         ++m_layerIterator;
310         ASSERT_TRUE(m_layerIterator.representsContributingRenderSurface());
311         occlusion.enterLayer(m_layerIterator);
312     }
313
314     void leaveContributingSurface(typename Types::LayerType* layer, typename Types::OcclusionTrackerType& occlusion)
315     {
316         ASSERT_EQ(layer, *m_layerIterator);
317         ASSERT_TRUE(m_layerIterator.representsContributingRenderSurface());
318         occlusion.leaveLayer(m_layerIterator);
319         ++m_layerIterator;
320     }
321
322     void visitContributingSurface(typename Types::LayerType* layer, typename Types::OcclusionTrackerType& occlusion)
323     {
324         enterContributingSurface(layer, occlusion);
325         leaveContributingSurface(layer, occlusion);
326     }
327
328     void resetLayerIterator()
329     {
330         m_layerIterator = m_layerIteratorBegin;
331     }
332
333     const WebTransformationMatrix identityMatrix;
334
335 private:
336     void setBaseProperties(typename Types::LayerType* layer, const WebTransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
337     {
338         layer->setTransform(transform);
339         layer->setSublayerTransform(WebTransformationMatrix());
340         layer->setAnchorPoint(FloatPoint(0, 0));
341         layer->setPosition(position);
342         layer->setBounds(bounds);
343     }
344
345     void setProperties(LayerChromium* layer, const WebTransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
346     {
347         setBaseProperties(layer, transform, position, bounds);
348     }
349
350     void setProperties(CCLayerImpl* layer, const WebTransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
351     {
352         setBaseProperties(layer, transform, position, bounds);
353
354         layer->setContentBounds(layer->bounds());
355     }
356
357     void setReplica(LayerChromium* owningLayer, PassRefPtr<LayerChromium> layer)
358     {
359         owningLayer->setReplicaLayer(layer.get());
360         m_replicaLayers.append(layer);
361     }
362
363     void setReplica(CCLayerImpl* owningLayer, PassOwnPtr<CCLayerImpl> layer)
364     {
365         owningLayer->setReplicaLayer(layer);
366     }
367
368     void setMask(LayerChromium* owningLayer, PassRefPtr<LayerChromium> layer)
369     {
370         owningLayer->setMaskLayer(layer.get());
371         m_maskLayers.append(layer);
372     }
373
374     void setMask(CCLayerImpl* owningLayer, PassOwnPtr<CCLayerImpl> layer)
375     {
376         owningLayer->setMaskLayer(layer);
377     }
378
379     // These hold ownership of the layers for the duration of the test.
380     typename Types::LayerPtrType m_root;
381     Vector<RefPtr<LayerChromium> > m_renderSurfaceLayerListChromium;
382     Vector<CCLayerImpl*> m_renderSurfaceLayerListImpl;
383     typename Types::LayerIterator m_layerIteratorBegin;
384     typename Types::LayerIterator m_layerIterator;
385     typename Types::LayerType* m_lastLayerVisited;
386     Vector<RefPtr<LayerChromium> > m_replicaLayers;
387     Vector<RefPtr<LayerChromium> > m_maskLayers;
388 };
389
390 #define RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \
391     class ClassName##MainThreadOpaqueLayers : public ClassName<CCOcclusionTrackerTestMainThreadTypes, true> { \
392     public: \
393         ClassName##MainThreadOpaqueLayers() : ClassName<CCOcclusionTrackerTestMainThreadTypes, true>() { } \
394     }; \
395     TEST_F(ClassName##MainThreadOpaqueLayers, runTest) { runMyTest(); }
396 #define RUN_TEST_MAIN_THREAD_OPAQUE_PAINTS(ClassName) \
397     class ClassName##MainThreadOpaquePaints : public ClassName<CCOcclusionTrackerTestMainThreadTypes, false> { \
398     public: \
399         ClassName##MainThreadOpaquePaints() : ClassName<CCOcclusionTrackerTestMainThreadTypes, false>() { } \
400     }; \
401     TEST_F(ClassName##MainThreadOpaquePaints, runTest) { runMyTest(); }
402
403 #define RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) \
404     class ClassName##ImplThreadOpaqueLayers : public ClassName<CCOcclusionTrackerTestImplThreadTypes, true> { \
405         DebugScopedSetImplThread impl; \
406     public: \
407         ClassName##ImplThreadOpaqueLayers() : ClassName<CCOcclusionTrackerTestImplThreadTypes, true>() { } \
408     }; \
409     TEST_F(ClassName##ImplThreadOpaqueLayers, runTest) { runMyTest(); }
410 #define RUN_TEST_IMPL_THREAD_OPAQUE_PAINTS(ClassName) \
411     class ClassName##ImplThreadOpaquePaints : public ClassName<CCOcclusionTrackerTestImplThreadTypes, false> { \
412         DebugScopedSetImplThread impl; \
413     public: \
414         ClassName##ImplThreadOpaquePaints() : ClassName<CCOcclusionTrackerTestImplThreadTypes, false>() { } \
415     }; \
416     TEST_F(ClassName##ImplThreadOpaquePaints, runTest) { runMyTest(); }
417
418 #define ALL_CCOCCLUSIONTRACKER_TEST(ClassName) \
419     RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \
420     RUN_TEST_MAIN_THREAD_OPAQUE_PAINTS(ClassName) \
421     RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) \
422     RUN_TEST_IMPL_THREAD_OPAQUE_PAINTS(ClassName)
423
424 #define MAIN_THREAD_TEST(ClassName) \
425     RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName)
426
427 #define IMPL_THREAD_TEST(ClassName) \
428     RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName)
429
430 #define MAIN_AND_IMPL_THREAD_TEST(ClassName) \
431     RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \
432     RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName)
433
434 template<class Types, bool opaqueLayers>
435 class CCOcclusionTrackerTestIdentityTransforms : public CCOcclusionTrackerTest<Types, opaqueLayers> {
436 protected:
437     void runMyTest()
438     {
439         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
440         typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(30, 30), IntSize(500, 500), true);
441         this->calcDrawEtc(parent);
442
443         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
444         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
445
446         this->visitLayer(layer, occlusion);
447         this->enterLayer(parent, occlusion);
448
449         EXPECT_INT_RECT_EQ(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
450         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
451         EXPECT_INT_RECT_EQ(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
452         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
453
454         EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 30, 70, 70)));
455         EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 30, 70, 70)));
456         EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 29, 70, 70)));
457         EXPECT_FALSE(occlusion.occluded(parent, IntRect(31, 30, 70, 70)));
458         EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 31, 70, 70)));
459
460         occlusion.useDefaultLayerClipRect();
461         EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 30, 70, 70)));
462         EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 30, 70, 70)));
463         EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 29, 70, 70)));
464         EXPECT_TRUE(occlusion.occluded(parent, IntRect(31, 30, 70, 70)));
465         EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 31, 70, 70)));
466         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
467
468         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(30, 30, 70, 70)).isEmpty());
469         EXPECT_INT_RECT_EQ(IntRect(29, 30, 1, 70), occlusion.unoccludedContentRect(parent, IntRect(29, 30, 70, 70)));
470         EXPECT_INT_RECT_EQ(IntRect(29, 29, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(29, 29, 70, 70)));
471         EXPECT_INT_RECT_EQ(IntRect(30, 29, 70, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 29, 70, 70)));
472         EXPECT_INT_RECT_EQ(IntRect(31, 29, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(31, 29, 70, 70)));
473         EXPECT_INT_RECT_EQ(IntRect(100, 30, 1, 70), occlusion.unoccludedContentRect(parent, IntRect(31, 30, 70, 70)));
474         EXPECT_INT_RECT_EQ(IntRect(31, 31, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(31, 31, 70, 70)));
475         EXPECT_INT_RECT_EQ(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 31, 70, 70)));
476         EXPECT_INT_RECT_EQ(IntRect(29, 31, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(29, 31, 70, 70)));
477     }
478 };
479
480 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestIdentityTransforms);
481
482 template<class Types, bool opaqueLayers>
483 class CCOcclusionTrackerTestRotatedChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
484 protected:
485     void runMyTest()
486     {
487         WebTransformationMatrix layerTransform;
488         layerTransform.translate(250, 250);
489         layerTransform.rotate(90);
490         layerTransform.translate(-250, -250);
491
492         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
493         typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, layerTransform, FloatPoint(30, 30), IntSize(500, 500), true);
494         this->calcDrawEtc(parent);
495
496         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
497         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
498
499         this->visitLayer(layer, occlusion);
500         this->enterLayer(parent, occlusion);
501
502         EXPECT_INT_RECT_EQ(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
503         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
504         EXPECT_INT_RECT_EQ(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
505         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
506
507         EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 30, 70, 70)));
508         EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 30, 70, 70)));
509         EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 29, 70, 70)));
510         EXPECT_FALSE(occlusion.occluded(parent, IntRect(31, 30, 70, 70)));
511         EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 31, 70, 70)));
512
513         occlusion.useDefaultLayerClipRect();
514         EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 30, 70, 70)));
515         EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 30, 70, 70)));
516         EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 29, 70, 70)));
517         EXPECT_TRUE(occlusion.occluded(parent, IntRect(31, 30, 70, 70)));
518         EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 31, 70, 70)));
519         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
520
521         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(30, 30, 70, 70)).isEmpty());
522         EXPECT_INT_RECT_EQ(IntRect(29, 30, 1, 70), occlusion.unoccludedContentRect(parent, IntRect(29, 30, 70, 70)));
523         EXPECT_INT_RECT_EQ(IntRect(29, 29, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(29, 29, 70, 70)));
524         EXPECT_INT_RECT_EQ(IntRect(30, 29, 70, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 29, 70, 70)));
525         EXPECT_INT_RECT_EQ(IntRect(31, 29, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(31, 29, 70, 70)));
526         EXPECT_INT_RECT_EQ(IntRect(100, 30, 1, 70), occlusion.unoccludedContentRect(parent, IntRect(31, 30, 70, 70)));
527         EXPECT_INT_RECT_EQ(IntRect(31, 31, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(31, 31, 70, 70)));
528         EXPECT_INT_RECT_EQ(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 31, 70, 70)));
529         EXPECT_INT_RECT_EQ(IntRect(29, 31, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(29, 31, 70, 70)));
530     }
531 };
532
533 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestRotatedChild);
534
535 template<class Types, bool opaqueLayers>
536 class CCOcclusionTrackerTestTranslatedChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
537 protected:
538     void runMyTest()
539     {
540         WebTransformationMatrix layerTransform;
541         layerTransform.translate(20, 20);
542
543         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
544         typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, layerTransform, FloatPoint(30, 30), IntSize(500, 500), true);
545         this->calcDrawEtc(parent);
546
547         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
548         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
549
550         this->visitLayer(layer, occlusion);
551         this->enterLayer(parent, occlusion);
552
553         EXPECT_INT_RECT_EQ(IntRect(50, 50, 50, 50), occlusion.occlusionInScreenSpace().bounds());
554         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
555         EXPECT_INT_RECT_EQ(IntRect(50, 50, 50, 50), occlusion.occlusionInTargetSurface().bounds());
556         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
557
558         EXPECT_TRUE(occlusion.occluded(parent, IntRect(50, 50, 50, 50)));
559         EXPECT_FALSE(occlusion.occluded(parent, IntRect(49, 50, 50, 50)));
560         EXPECT_FALSE(occlusion.occluded(parent, IntRect(50, 49, 50, 50)));
561         EXPECT_FALSE(occlusion.occluded(parent, IntRect(51, 50, 50, 50)));
562         EXPECT_FALSE(occlusion.occluded(parent, IntRect(50, 51, 50, 50)));
563
564         occlusion.useDefaultLayerClipRect();
565         EXPECT_TRUE(occlusion.occluded(parent, IntRect(50, 50, 50, 50)));
566         EXPECT_FALSE(occlusion.occluded(parent, IntRect(49, 50, 50, 50)));
567         EXPECT_FALSE(occlusion.occluded(parent, IntRect(50, 49, 50, 50)));
568         EXPECT_TRUE(occlusion.occluded(parent, IntRect(51, 50, 50, 50)));
569         EXPECT_TRUE(occlusion.occluded(parent, IntRect(50, 51, 50, 50)));
570         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
571
572         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(50, 50, 50, 50)).isEmpty());
573         EXPECT_INT_RECT_EQ(IntRect(49, 50, 1, 50), occlusion.unoccludedContentRect(parent, IntRect(49, 50, 50, 50)));
574         EXPECT_INT_RECT_EQ(IntRect(49, 49, 50, 50), occlusion.unoccludedContentRect(parent, IntRect(49, 49, 50, 50)));
575         EXPECT_INT_RECT_EQ(IntRect(50, 49, 50, 1), occlusion.unoccludedContentRect(parent, IntRect(50, 49, 50, 50)));
576         EXPECT_INT_RECT_EQ(IntRect(51, 49, 50, 50), occlusion.unoccludedContentRect(parent, IntRect(51, 49, 50, 50)));
577         EXPECT_INT_RECT_EQ(IntRect(100, 50, 1, 50), occlusion.unoccludedContentRect(parent, IntRect(51, 50, 50, 50)));
578         EXPECT_INT_RECT_EQ(IntRect(51, 51, 50, 50), occlusion.unoccludedContentRect(parent, IntRect(51, 51, 50, 50)));
579         EXPECT_INT_RECT_EQ(IntRect(50, 100, 50, 1), occlusion.unoccludedContentRect(parent, IntRect(50, 51, 50, 50)));
580         EXPECT_INT_RECT_EQ(IntRect(49, 51, 50, 50), occlusion.unoccludedContentRect(parent, IntRect(49, 51, 50, 50)));
581
582         occlusion.useDefaultLayerClipRect();
583         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(50, 50, 50, 50)).isEmpty());
584         EXPECT_INT_RECT_EQ(IntRect(49, 50, 1, 50), occlusion.unoccludedContentRect(parent, IntRect(49, 50, 50, 50)));
585         EXPECT_INT_RECT_EQ(IntRect(49, 49, 50, 50), occlusion.unoccludedContentRect(parent, IntRect(49, 49, 50, 50)));
586         EXPECT_INT_RECT_EQ(IntRect(50, 49, 50, 1), occlusion.unoccludedContentRect(parent, IntRect(50, 49, 50, 50)));
587         EXPECT_INT_RECT_EQ(IntRect(51, 49, 49, 1), occlusion.unoccludedContentRect(parent, IntRect(51, 49, 50, 50)));
588         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(51, 50, 50, 50)).isEmpty());
589         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(51, 51, 50, 50)).isEmpty());
590         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(50, 51, 50, 50)).isEmpty());
591         EXPECT_INT_RECT_EQ(IntRect(49, 51, 1, 49), occlusion.unoccludedContentRect(parent, IntRect(49, 51, 50, 50)));
592         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
593     }
594 };
595
596 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestTranslatedChild);
597
598 template<class Types, bool opaqueLayers>
599 class CCOcclusionTrackerTestChildInRotatedChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
600 protected:
601     void runMyTest()
602     {
603         WebTransformationMatrix childTransform;
604         childTransform.translate(250, 250);
605         childTransform.rotate(90);
606         childTransform.translate(-250, -250);
607
608         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
609         typename Types::LayerType* child = this->createLayer(parent, childTransform, FloatPoint(30, 30), IntSize(500, 500));
610         child->setMasksToBounds(true);
611         typename Types::ContentLayerType* layer = this->createDrawingLayer(child, this->identityMatrix, FloatPoint(10, 10), IntSize(500, 500), true);
612         this->calcDrawEtc(parent);
613
614         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
615         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
616
617         this->visitLayer(layer, occlusion);
618         this->enterContributingSurface(child, occlusion);
619
620         EXPECT_INT_RECT_EQ(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
621         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
622         EXPECT_INT_RECT_EQ(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds());
623         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
624
625         this->leaveContributingSurface(child, occlusion);
626         this->enterLayer(parent, occlusion);
627
628         EXPECT_INT_RECT_EQ(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
629         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
630         EXPECT_INT_RECT_EQ(IntRect(30, 40, 70, 60), occlusion.occlusionInTargetSurface().bounds());
631         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
632
633         EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 40, 70, 60)));
634         EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 40, 70, 60)));
635         EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 39, 70, 60)));
636         EXPECT_FALSE(occlusion.occluded(parent, IntRect(31, 40, 70, 60)));
637         EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 41, 70, 60)));
638
639         occlusion.useDefaultLayerClipRect();
640         EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 40, 70, 60)));
641         EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 40, 70, 60)));
642         EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 39, 70, 60)));
643         EXPECT_TRUE(occlusion.occluded(parent, IntRect(31, 40, 70, 60)));
644         EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 41, 70, 60)));
645         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
646
647
648         /* Justification for the above occlusion from |layer|:
649                    100
650           +---------------------+                                      +---------------------+
651           |                     |                                      |                     |30  Visible region of |layer|: /////
652           |    30               |           rotate(90)                 |                     |
653           | 30 + ---------------------------------+                    |     +---------------------------------+
654       100 |    |  10            |                 |            ==>     |     |               |10               |
655           |    |10+---------------------------------+                  |  +---------------------------------+  |
656           |    |  |             |                 | |                  |  |  |///////////////|     420      |  |
657           |    |  |             |                 | |                  |  |  |///////////////|60            |  |
658           |    |  |             |                 | |                  |  |  |///////////////|              |  |
659           +----|--|-------------+                 | |                  +--|--|---------------+              |  |
660                |  |                               | |                   20|10|     70                       |  |
661                |  |                               | |                     |  |                              |  |
662                |  |                               | |500                  |  |                              |  |
663                |  |                               | |                     |  |                              |  |
664                |  |                               | |                     |  |                              |  |
665                |  |                               | |                     |  |                              |  |
666                |  |                               | |                     |  |                              |10|
667                +--|-------------------------------+ |                     |  +------------------------------|--+
668                   |                                 |                     |                 490             |
669                   +---------------------------------+                     +---------------------------------+
670                                  500                                                     500
671          */
672     }
673 };
674
675 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestChildInRotatedChild);
676
677 template<class Types, bool opaqueLayers>
678 class CCOcclusionTrackerTestVisitTargetTwoTimes : public CCOcclusionTrackerTest<Types, opaqueLayers> {
679 protected:
680     void runMyTest()
681     {
682         WebTransformationMatrix childTransform;
683         childTransform.translate(250, 250);
684         childTransform.rotate(90);
685         childTransform.translate(-250, -250);
686
687         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
688         typename Types::LayerType* child = this->createLayer(parent, childTransform, FloatPoint(30, 30), IntSize(500, 500));
689         child->setMasksToBounds(true);
690         typename Types::ContentLayerType* layer = this->createDrawingLayer(child, this->identityMatrix, FloatPoint(10, 10), IntSize(500, 500), true);
691         // |child2| makes |parent|'s surface get considered by CCOcclusionTracker first, instead of |child|'s. This exercises different code in
692         // leaveToTargetRenderSurface, as the target surface has already been seen.
693         typename Types::ContentLayerType* child2 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(30, 30), IntSize(60, 20), true);
694         this->calcDrawEtc(parent);
695
696         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
697         occlusion.setLayerClipRect(IntRect(-10, -10, 1000, 1000));
698
699         this->visitLayer(child2, occlusion);
700
701         EXPECT_INT_RECT_EQ(IntRect(30, 30, 60, 20), occlusion.occlusionInScreenSpace().bounds());
702         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
703         EXPECT_INT_RECT_EQ(IntRect(30, 30, 60, 20), occlusion.occlusionInTargetSurface().bounds());
704         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
705
706         this->visitLayer(layer, occlusion);
707
708         EXPECT_INT_RECT_EQ(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
709         EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
710         EXPECT_INT_RECT_EQ(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds());
711         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
712
713         this->enterContributingSurface(child, occlusion);
714
715         EXPECT_INT_RECT_EQ(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
716         EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
717         EXPECT_INT_RECT_EQ(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds());
718         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
719
720         // Occlusion in |child2| should get merged with the |child| surface we are leaving now.
721         this->leaveContributingSurface(child, occlusion);
722         this->enterLayer(parent, occlusion);
723
724         EXPECT_INT_RECT_EQ(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
725         EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
726         EXPECT_INT_RECT_EQ(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
727         EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
728
729         EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 30, 70, 70)));
730         EXPECT_INT_RECT_EQ(IntRect(90, 30, 10, 10), occlusion.unoccludedContentRect(parent, IntRect(30, 30, 70, 70)));
731
732         EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 30, 60, 10)));
733         EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 30, 60, 10)));
734         EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 29, 60, 10)));
735         EXPECT_FALSE(occlusion.occluded(parent, IntRect(31, 30, 60, 10)));
736         EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 31, 60, 10)));
737
738         EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 40, 70, 60)));
739         EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 40, 70, 60)));
740         EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 39, 70, 60)));
741
742         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(30, 30, 60, 10)).isEmpty());
743         EXPECT_INT_RECT_EQ(IntRect(29, 30, 1, 10), occlusion.unoccludedContentRect(parent, IntRect(29, 30, 60, 10)));
744         EXPECT_INT_RECT_EQ(IntRect(30, 29, 60, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 29, 60, 10)));
745         EXPECT_INT_RECT_EQ(IntRect(90, 30, 1, 10), occlusion.unoccludedContentRect(parent, IntRect(31, 30, 60, 10)));
746         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(30, 31, 60, 10)).isEmpty());
747
748         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(30, 40, 70, 60)).isEmpty());
749         EXPECT_INT_RECT_EQ(IntRect(29, 40, 1, 60), occlusion.unoccludedContentRect(parent, IntRect(29, 40, 70, 60)));
750         // This rect is mostly occluded by |child2|.
751         EXPECT_INT_RECT_EQ(IntRect(90, 39, 10, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 39, 70, 60)));
752         // This rect extends past top/right ends of |child2|.
753         EXPECT_INT_RECT_EQ(IntRect(30, 29, 70, 11), occlusion.unoccludedContentRect(parent, IntRect(30, 29, 70, 70)));
754         // This rect extends past left/right ends of |child2|.
755         EXPECT_INT_RECT_EQ(IntRect(20, 39, 80, 60), occlusion.unoccludedContentRect(parent, IntRect(20, 39, 80, 60)));
756         EXPECT_INT_RECT_EQ(IntRect(100, 40, 1, 60), occlusion.unoccludedContentRect(parent, IntRect(31, 40, 70, 60)));
757         EXPECT_INT_RECT_EQ(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 41, 70, 60)));
758
759         /* Justification for the above occlusion from |layer|:
760                    100
761           +---------------------+                                      +---------------------+
762           |                     |                                      |                     |30  Visible region of |layer|: /////
763           |    30               |           rotate(90)                 |     30   60         |    |child2|: \\\\\
764           | 30 + ------------+--------------------+                    |  30 +------------+--------------------+
765       100 |    |  10         |  |                 |            ==>     |     |\\\\\\\\\\\\|  |10               |
766           |    |10+----------|----------------------+                  |  +--|\\\\\\\\\\\\|-----------------+  |
767           |    + ------------+  |                 | |                  |  |  +------------+//|     420      |  |
768           |    |  |             |                 | |                  |  |  |///////////////|60            |  |
769           |    |  |             |                 | |                  |  |  |///////////////|              |  |
770           +----|--|-------------+                 | |                  +--|--|---------------+              |  |
771                |  |                               | |                   20|10|     70                       |  |
772                |  |                               | |                     |  |                              |  |
773                |  |                               | |500                  |  |                              |  |
774                |  |                               | |                     |  |                              |  |
775                |  |                               | |                     |  |                              |  |
776                |  |                               | |                     |  |                              |  |
777                |  |                               | |                     |  |                              |10|
778                +--|-------------------------------+ |                     |  +------------------------------|--+
779                   |                                 |                     |                 490             |
780                   +---------------------------------+                     +---------------------------------+
781                                  500                                                     500
782          */
783     }
784 };
785
786 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestVisitTargetTwoTimes);
787
788 template<class Types, bool opaqueLayers>
789 class CCOcclusionTrackerTestSurfaceRotatedOffAxis : public CCOcclusionTrackerTest<Types, opaqueLayers> {
790 protected:
791     void runMyTest()
792     {
793         WebTransformationMatrix childTransform;
794         childTransform.translate(250, 250);
795         childTransform.rotate(95);
796         childTransform.translate(-250, -250);
797
798         WebTransformationMatrix layerTransform;
799         layerTransform.translate(10, 10);
800
801         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
802         typename Types::LayerType* child = this->createLayer(parent, childTransform, FloatPoint(30, 30), IntSize(500, 500));
803         child->setMasksToBounds(true);
804         typename Types::ContentLayerType* layer = this->createDrawingLayer(child, layerTransform, FloatPoint(0, 0), IntSize(500, 500), true);
805         this->calcDrawEtc(parent);
806
807         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
808         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
809
810         IntRect clippedLayerInChild = CCMathUtil::mapClippedRect(layerTransform, layer->visibleContentRect());
811
812         this->visitLayer(layer, occlusion);
813         this->enterContributingSurface(child, occlusion);
814
815         EXPECT_INT_RECT_EQ(IntRect(), occlusion.occlusionInScreenSpace().bounds());
816         EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size());
817         EXPECT_INT_RECT_EQ(clippedLayerInChild, occlusion.occlusionInTargetSurface().bounds());
818         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
819
820         EXPECT_TRUE(occlusion.occluded(child, clippedLayerInChild));
821         EXPECT_TRUE(occlusion.unoccludedContentRect(child, clippedLayerInChild).isEmpty());
822         clippedLayerInChild.move(-1, 0);
823         EXPECT_FALSE(occlusion.occluded(child, clippedLayerInChild));
824         EXPECT_FALSE(occlusion.unoccludedContentRect(child, clippedLayerInChild).isEmpty());
825         clippedLayerInChild.move(1, 0);
826         clippedLayerInChild.move(1, 0);
827         EXPECT_FALSE(occlusion.occluded(child, clippedLayerInChild));
828         EXPECT_FALSE(occlusion.unoccludedContentRect(child, clippedLayerInChild).isEmpty());
829         clippedLayerInChild.move(-1, 0);
830         clippedLayerInChild.move(0, -1);
831         EXPECT_FALSE(occlusion.occluded(child, clippedLayerInChild));
832         EXPECT_FALSE(occlusion.unoccludedContentRect(child, clippedLayerInChild).isEmpty());
833         clippedLayerInChild.move(0, 1);
834         clippedLayerInChild.move(0, 1);
835         EXPECT_FALSE(occlusion.occluded(child, clippedLayerInChild));
836         EXPECT_FALSE(occlusion.unoccludedContentRect(child, clippedLayerInChild).isEmpty());
837         clippedLayerInChild.move(0, -1);
838
839         this->leaveContributingSurface(child, occlusion);
840         this->enterLayer(parent, occlusion);
841
842         EXPECT_INT_RECT_EQ(IntRect(), occlusion.occlusionInScreenSpace().bounds());
843         EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size());
844         EXPECT_INT_RECT_EQ(IntRect(), occlusion.occlusionInTargetSurface().bounds());
845         EXPECT_EQ(0u, occlusion.occlusionInTargetSurface().rects().size());
846
847         EXPECT_FALSE(occlusion.occluded(parent, IntRect(75, 55, 1, 1)));
848         EXPECT_INT_RECT_EQ(IntRect(75, 55, 1, 1), occlusion.unoccludedContentRect(parent, IntRect(75, 55, 1, 1)));
849     }
850 };
851
852 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestSurfaceRotatedOffAxis);
853
854 template<class Types, bool opaqueLayers>
855 class CCOcclusionTrackerTestSurfaceWithTwoOpaqueChildren : public CCOcclusionTrackerTest<Types, opaqueLayers> {
856 protected:
857     void runMyTest()
858     {
859         WebTransformationMatrix childTransform;
860         childTransform.translate(250, 250);
861         childTransform.rotate(90);
862         childTransform.translate(-250, -250);
863
864         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
865         typename Types::LayerType* child = this->createLayer(parent, childTransform, FloatPoint(30, 30), IntSize(500, 500));
866         child->setMasksToBounds(true);
867         typename Types::ContentLayerType* layer1 = this->createDrawingLayer(child, this->identityMatrix, FloatPoint(10, 10), IntSize(500, 500), true);
868         typename Types::ContentLayerType* layer2 = this->createDrawingLayer(child, this->identityMatrix, FloatPoint(10, 450), IntSize(500, 60), true);
869         this->calcDrawEtc(parent);
870
871         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
872         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
873
874         this->visitLayer(layer2, occlusion);
875         this->visitLayer(layer1, occlusion);
876         this->enterContributingSurface(child, occlusion);
877
878         EXPECT_INT_RECT_EQ(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
879         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
880         EXPECT_INT_RECT_EQ(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds());
881         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
882
883         EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 430, 60, 70)));
884         EXPECT_FALSE(occlusion.occluded(child, IntRect(9, 430, 60, 70)));
885         EXPECT_FALSE(occlusion.occluded(child, IntRect(10, 429, 60, 70)));
886         EXPECT_FALSE(occlusion.occluded(child, IntRect(11, 430, 60, 70)));
887         EXPECT_FALSE(occlusion.occluded(child, IntRect(10, 431, 60, 70)));
888
889         EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(10, 430, 60, 70)).isEmpty());
890         EXPECT_INT_RECT_EQ(IntRect(9, 430, 1, 70), occlusion.unoccludedContentRect(child, IntRect(9, 430, 60, 70)));
891         EXPECT_INT_RECT_EQ(IntRect(10, 429, 60, 1), occlusion.unoccludedContentRect(child, IntRect(10, 429, 60, 70)));
892         EXPECT_INT_RECT_EQ(IntRect(70, 430, 1, 70), occlusion.unoccludedContentRect(child, IntRect(11, 430, 60, 70)));
893         EXPECT_INT_RECT_EQ(IntRect(10, 500, 60, 1), occlusion.unoccludedContentRect(child, IntRect(10, 431, 60, 70)));
894
895         this->leaveContributingSurface(child, occlusion);
896         this->enterLayer(parent, occlusion);
897
898         EXPECT_INT_RECT_EQ(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
899         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
900         EXPECT_INT_RECT_EQ(IntRect(30, 40, 70, 60), occlusion.occlusionInTargetSurface().bounds());
901         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
902
903         EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 40, 70, 60)));
904         EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 40, 70, 60)));
905         EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 39, 70, 60)));
906
907         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(30, 40, 70, 60)).isEmpty());
908         EXPECT_INT_RECT_EQ(IntRect(29, 40, 1, 60), occlusion.unoccludedContentRect(parent, IntRect(29, 40, 70, 60)));
909         EXPECT_INT_RECT_EQ(IntRect(30, 39, 70, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 39, 70, 60)));
910         EXPECT_INT_RECT_EQ(IntRect(100, 40, 1, 60), occlusion.unoccludedContentRect(parent, IntRect(31, 40, 70, 60)));
911         EXPECT_INT_RECT_EQ(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 41, 70, 60)));
912
913         /* Justification for the above occlusion from |layer1| and |layer2|:
914
915            +---------------------+
916            |                     |30  Visible region of |layer1|: /////
917            |                     |    Visible region of |layer2|: \\\\\
918            |     +---------------------------------+
919            |     |               |10               |
920            |  +---------------+-----------------+  |
921            |  |  |\\\\\\\\\\\\|//|     420      |  |
922            |  |  |\\\\\\\\\\\\|//|60            |  |
923            |  |  |\\\\\\\\\\\\|//|              |  |
924            +--|--|------------|--+              |  |
925             20|10|     70     |                 |  |
926               |  |            |                 |  |
927               |  |            |                 |  |
928               |  |            |                 |  |
929               |  |            |                 |  |
930               |  |            |                 |  |
931               |  |            |                 |10|
932               |  +------------|-----------------|--+
933               |               | 490             |
934               +---------------+-----------------+
935                      60               440
936          */
937     }
938 };
939
940 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestSurfaceWithTwoOpaqueChildren);
941
942 template<class Types, bool opaqueLayers>
943 class CCOcclusionTrackerTestOverlappingSurfaceSiblings : public CCOcclusionTrackerTest<Types, opaqueLayers> {
944 protected:
945     void runMyTest()
946     {
947         WebTransformationMatrix childTransform;
948         childTransform.translate(250, 250);
949         childTransform.rotate(90);
950         childTransform.translate(-250, -250);
951
952         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
953         typename Types::LayerType* child1 = this->createSurface(parent, childTransform, FloatPoint(30, 30), IntSize(10, 10));
954         typename Types::LayerType* child2 = this->createSurface(parent, childTransform, FloatPoint(20, 40), IntSize(10, 10));
955         typename Types::ContentLayerType* layer1 = this->createDrawingLayer(child1, this->identityMatrix, FloatPoint(-10, -10), IntSize(510, 510), true);
956         typename Types::ContentLayerType* layer2 = this->createDrawingLayer(child2, this->identityMatrix, FloatPoint(-10, -10), IntSize(510, 510), true);
957         this->calcDrawEtc(parent);
958
959         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
960         occlusion.setLayerClipRect(IntRect(-20, -20, 1000, 1000));
961
962         this->visitLayer(layer2, occlusion);
963         this->enterContributingSurface(child2, occlusion);
964
965         EXPECT_INT_RECT_EQ(IntRect(20, 30, 80, 70), occlusion.occlusionInScreenSpace().bounds());
966         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
967         EXPECT_INT_RECT_EQ(IntRect(-10, 420, 70, 80), occlusion.occlusionInTargetSurface().bounds());
968         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
969
970         EXPECT_TRUE(occlusion.occluded(child2, IntRect(-10, 420, 70, 80)));
971         EXPECT_FALSE(occlusion.occluded(child2, IntRect(-11, 420, 70, 80)));
972         EXPECT_FALSE(occlusion.occluded(child2, IntRect(-10, 419, 70, 80)));
973         EXPECT_FALSE(occlusion.occluded(child2, IntRect(-10, 420, 71, 80)));
974         EXPECT_FALSE(occlusion.occluded(child2, IntRect(-10, 420, 70, 81)));
975
976         occlusion.useDefaultLayerClipRect();
977         EXPECT_TRUE(occlusion.occluded(child2, IntRect(-10, 420, 70, 80)));
978         EXPECT_TRUE(occlusion.occluded(child2, IntRect(-11, 420, 70, 80)));
979         EXPECT_TRUE(occlusion.occluded(child2, IntRect(-10, 419, 70, 80)));
980         EXPECT_TRUE(occlusion.occluded(child2, IntRect(-10, 420, 71, 80)));
981         EXPECT_TRUE(occlusion.occluded(child2, IntRect(-10, 420, 70, 81)));
982         occlusion.setLayerClipRect(IntRect(-20, -20, 1000, 1000));
983
984         // There is nothing above child2's surface in the z-order.
985         EXPECT_INT_RECT_EQ(IntRect(-10, 420, 70, 80), occlusion.unoccludedContributingSurfaceContentRect(child2, false, IntRect(-10, 420, 70, 80)));
986
987         this->leaveContributingSurface(child2, occlusion);
988         this->visitLayer(layer1, occlusion);
989         this->enterContributingSurface(child1, occlusion);
990
991         EXPECT_INT_RECT_EQ(IntRect(20, 20, 80, 80), occlusion.occlusionInScreenSpace().bounds());
992         EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
993         EXPECT_INT_RECT_EQ(IntRect(-10, 430, 80, 70), occlusion.occlusionInTargetSurface().bounds());
994         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
995
996         EXPECT_TRUE(occlusion.occluded(child1, IntRect(-10, 430, 80, 70)));
997         EXPECT_FALSE(occlusion.occluded(child1, IntRect(-11, 430, 80, 70)));
998         EXPECT_FALSE(occlusion.occluded(child1, IntRect(-10, 429, 80, 70)));
999         EXPECT_FALSE(occlusion.occluded(child1, IntRect(-10, 430, 81, 70)));
1000         EXPECT_FALSE(occlusion.occluded(child1, IntRect(-10, 430, 80, 71)));
1001
1002         // child2's contents will occlude child1 below it.
1003         EXPECT_INT_RECT_EQ(IntRect(-10, 430, 10, 70), occlusion.unoccludedContributingSurfaceContentRect(child1, false, IntRect(-10, 430, 80, 70)));
1004
1005         this->leaveContributingSurface(child1, occlusion);
1006         this->enterLayer(parent, occlusion);
1007
1008         EXPECT_INT_RECT_EQ(IntRect(20, 20, 80, 80), occlusion.occlusionInScreenSpace().bounds());
1009         EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
1010         EXPECT_INT_RECT_EQ(IntRect(20, 20, 80, 80), occlusion.occlusionInTargetSurface().bounds());
1011         EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
1012
1013         EXPECT_FALSE(occlusion.occluded(parent, IntRect(20, 20, 80, 80)));
1014
1015         EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 20, 70, 80)));
1016         EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 20, 70, 80)));
1017         EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 19, 70, 80)));
1018
1019         EXPECT_TRUE(occlusion.occluded(parent, IntRect(20, 30, 80, 70)));
1020         EXPECT_FALSE(occlusion.occluded(parent, IntRect(19, 30, 80, 70)));
1021         EXPECT_FALSE(occlusion.occluded(parent, IntRect(20, 29, 80, 70)));
1022
1023         /* Justification for the above occlusion:
1024                    100
1025           +---------------------+
1026           |    20               |       layer1
1027           |  30+ ---------------------------------+
1028       100 |  30|                |     layer2      |
1029           |20+----------------------------------+ |
1030           |  | |                |               | |
1031           |  | |                |               | |
1032           |  | |                |               | |
1033           +--|-|----------------+               | |
1034              | |                                | | 510
1035              | |                                | |
1036              | |                                | |
1037              | |                                | |
1038              | |                                | |
1039              | |                                | |
1040              | |                                | |
1041              | +--------------------------------|-+
1042              |                                  |
1043              +----------------------------------+
1044                              510
1045          */
1046     }
1047 };
1048
1049 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestOverlappingSurfaceSiblings);
1050
1051 template<class Types, bool opaqueLayers>
1052 class CCOcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1053 protected:
1054     void runMyTest()
1055     {
1056         WebTransformationMatrix child1Transform;
1057         child1Transform.translate(250, 250);
1058         child1Transform.rotate(-90);
1059         child1Transform.translate(-250, -250);
1060
1061         WebTransformationMatrix child2Transform;
1062         child2Transform.translate(250, 250);
1063         child2Transform.rotate(90);
1064         child2Transform.translate(-250, -250);
1065
1066         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
1067         typename Types::LayerType* child1 = this->createSurface(parent, child1Transform, FloatPoint(30, 20), IntSize(10, 10));
1068         typename Types::LayerType* child2 = this->createDrawingSurface(parent, child2Transform, FloatPoint(20, 40), IntSize(10, 10), false);
1069         typename Types::ContentLayerType* layer1 = this->createDrawingLayer(child1, this->identityMatrix, FloatPoint(-10, -20), IntSize(510, 510), true);
1070         typename Types::ContentLayerType* layer2 = this->createDrawingLayer(child2, this->identityMatrix, FloatPoint(-10, -10), IntSize(510, 510), true);
1071         this->calcDrawEtc(parent);
1072
1073         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
1074         occlusion.setLayerClipRect(IntRect(-30, -30, 1000, 1000));
1075
1076         this->visitLayer(layer2, occlusion);
1077         this->enterLayer(child2, occlusion);
1078
1079         EXPECT_INT_RECT_EQ(IntRect(20, 30, 80, 70), occlusion.occlusionInScreenSpace().bounds());
1080         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
1081         EXPECT_INT_RECT_EQ(IntRect(-10, 420, 70, 80), occlusion.occlusionInTargetSurface().bounds());
1082         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
1083
1084         EXPECT_TRUE(occlusion.occluded(child2, IntRect(-10, 420, 70, 80)));
1085         EXPECT_FALSE(occlusion.occluded(child2, IntRect(-11, 420, 70, 80)));
1086         EXPECT_FALSE(occlusion.occluded(child2, IntRect(-10, 419, 70, 80)));
1087         EXPECT_FALSE(occlusion.occluded(child2, IntRect(-10, 420, 71, 80)));
1088         EXPECT_FALSE(occlusion.occluded(child2, IntRect(-10, 420, 70, 81)));
1089
1090         this->leaveLayer(child2, occlusion);
1091         this->enterContributingSurface(child2, occlusion);
1092
1093         // There is nothing above child2's surface in the z-order.
1094         EXPECT_INT_RECT_EQ(IntRect(-10, 420, 70, 80), occlusion.unoccludedContributingSurfaceContentRect(child2, false, IntRect(-10, 420, 70, 80)));
1095
1096         this->leaveContributingSurface(child2, occlusion);
1097         this->visitLayer(layer1, occlusion);
1098         this->enterContributingSurface(child1, occlusion);
1099
1100         EXPECT_INT_RECT_EQ(IntRect(10, 20, 90, 80), occlusion.occlusionInScreenSpace().bounds());
1101         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
1102         EXPECT_INT_RECT_EQ(IntRect(420, -20, 80, 90), occlusion.occlusionInTargetSurface().bounds());
1103         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
1104
1105         EXPECT_TRUE(occlusion.occluded(child1, IntRect(420, -20, 80, 90)));
1106         EXPECT_FALSE(occlusion.occluded(child1, IntRect(419, -20, 80, 90)));
1107         EXPECT_FALSE(occlusion.occluded(child1, IntRect(420, -21, 80, 90)));
1108         EXPECT_FALSE(occlusion.occluded(child1, IntRect(420, -19, 80, 90)));
1109         EXPECT_FALSE(occlusion.occluded(child1, IntRect(421, -20, 80, 90)));
1110
1111         // child2's contents will occlude child1 below it.
1112         EXPECT_INT_RECT_EQ(IntRect(420, -20, 80, 90), occlusion.unoccludedContributingSurfaceContentRect(child1, false, IntRect(420, -20, 80, 90)));
1113         EXPECT_INT_RECT_EQ(IntRect(490, -10, 10, 80), occlusion.unoccludedContributingSurfaceContentRect(child1, false, IntRect(420, -10, 80, 90)));
1114         EXPECT_INT_RECT_EQ(IntRect(420, -20, 70, 10), occlusion.unoccludedContributingSurfaceContentRect(child1, false, IntRect(420, -20, 70, 90)));
1115
1116         this->leaveContributingSurface(child1, occlusion);
1117         this->enterLayer(parent, occlusion);
1118
1119         EXPECT_INT_RECT_EQ(IntRect(10, 20, 90, 80), occlusion.occlusionInScreenSpace().bounds());
1120         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
1121         EXPECT_INT_RECT_EQ(IntRect(10, 20, 90, 80), occlusion.occlusionInTargetSurface().bounds());
1122         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
1123
1124         EXPECT_TRUE(occlusion.occluded(parent, IntRect(10, 20, 90, 80)));
1125         EXPECT_FALSE(occlusion.occluded(parent, IntRect(9, 20, 90, 80)));
1126         EXPECT_FALSE(occlusion.occluded(parent, IntRect(10, 19, 90, 80)));
1127         EXPECT_FALSE(occlusion.occluded(parent, IntRect(11, 20, 90, 80)));
1128         EXPECT_FALSE(occlusion.occluded(parent, IntRect(10, 21, 90, 80)));
1129
1130         /* Justification for the above occlusion:
1131                       100
1132             +---------------------+
1133             |20                   |       layer1
1134            10+----------------------------------+
1135         100 || 30                 |     layer2  |
1136             |20+----------------------------------+
1137             || |                  |             | |
1138             || |                  |             | |
1139             || |                  |             | |
1140             +|-|------------------+             | |
1141              | |                                | | 510
1142              | |                            510 | |
1143              | |                                | |
1144              | |                                | |
1145              | |                                | |
1146              | |                                | |
1147              | |                520             | |
1148              +----------------------------------+ |
1149                |                                  |
1150                +----------------------------------+
1151                                510
1152          */
1153     }
1154 };
1155
1156 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms);
1157
1158 template<class Types, bool opaqueLayers>
1159 class CCOcclusionTrackerTestFilters : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1160 protected:
1161     void runMyTest()
1162     {
1163         WebTransformationMatrix layerTransform;
1164         layerTransform.translate(250, 250);
1165         layerTransform.rotate(90);
1166         layerTransform.translate(-250, -250);
1167
1168         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
1169         typename Types::ContentLayerType* blurLayer = this->createDrawingLayer(parent, layerTransform, FloatPoint(30, 30), IntSize(500, 500), true);
1170         typename Types::ContentLayerType* opaqueLayer = this->createDrawingLayer(parent, layerTransform, FloatPoint(30, 30), IntSize(500, 500), true);
1171         typename Types::ContentLayerType* opacityLayer = this->createDrawingLayer(parent, layerTransform, FloatPoint(30, 30), IntSize(500, 500), true);
1172
1173         WebFilterOperations filters;
1174         filters.append(WebFilterOperation::createBlurFilter(10));
1175         blurLayer->setFilters(filters);
1176
1177         filters.clear();
1178         filters.append(WebFilterOperation::createGrayscaleFilter(0.5));
1179         opaqueLayer->setFilters(filters);
1180
1181         filters.clear();
1182         filters.append(WebFilterOperation::createOpacityFilter(0.5));
1183         opacityLayer->setFilters(filters);
1184
1185         this->calcDrawEtc(parent);
1186
1187         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
1188         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
1189
1190         // Opacity layer won't contribute to occlusion.
1191         this->visitLayer(opacityLayer, occlusion);
1192         this->enterContributingSurface(opacityLayer, occlusion);
1193
1194         EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
1195         EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
1196
1197         // And has nothing to contribute to its parent surface.
1198         this->leaveContributingSurface(opacityLayer, occlusion);
1199         EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
1200         EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
1201
1202         // Opaque layer will contribute to occlusion.
1203         this->visitLayer(opaqueLayer, occlusion);
1204         this->enterContributingSurface(opaqueLayer, occlusion);
1205
1206         EXPECT_INT_RECT_EQ(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
1207         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
1208         EXPECT_INT_RECT_EQ(IntRect(0, 430, 70, 70), occlusion.occlusionInTargetSurface().bounds());
1209         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
1210
1211         // And it gets translated to the parent surface.
1212         this->leaveContributingSurface(opaqueLayer, occlusion);
1213         EXPECT_INT_RECT_EQ(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
1214         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
1215         EXPECT_INT_RECT_EQ(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
1216         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
1217
1218         // The blur layer needs to throw away any occlusion from outside its subtree.
1219         this->enterLayer(blurLayer, occlusion);
1220         EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
1221         EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
1222
1223         // And it won't contribute to occlusion.
1224         this->leaveLayer(blurLayer, occlusion);
1225         this->enterContributingSurface(blurLayer, occlusion);
1226         EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
1227         EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
1228
1229         // But the opaque layer's occlusion is preserved on the parent. 
1230         this->leaveContributingSurface(blurLayer, occlusion);
1231         this->enterLayer(parent, occlusion);
1232         EXPECT_INT_RECT_EQ(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
1233         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
1234         EXPECT_INT_RECT_EQ(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
1235         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
1236     }
1237 };
1238
1239 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestFilters);
1240
1241 template<class Types, bool opaqueLayers>
1242 class CCOcclusionTrackerTestReplicaDoesOcclude : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1243 protected:
1244     void runMyTest()
1245     {
1246         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 200));
1247         typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 100), IntSize(50, 50), true);
1248         this->createReplicaLayer(surface, this->identityMatrix, FloatPoint(50, 50), IntSize());
1249         this->calcDrawEtc(parent);
1250
1251         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
1252         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
1253
1254         this->visitLayer(surface, occlusion);
1255
1256         EXPECT_INT_RECT_EQ(IntRect(0, 100, 50, 50), occlusion.occlusionInScreenSpace().bounds());
1257         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
1258         EXPECT_INT_RECT_EQ(IntRect(0, 0, 50, 50), occlusion.occlusionInTargetSurface().bounds());
1259         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
1260
1261         this->visitContributingSurface(surface, occlusion);
1262         this->enterLayer(parent, occlusion);
1263
1264         // The surface and replica should both be occluding the parent.
1265         EXPECT_INT_RECT_EQ(IntRect(0, 100, 100, 100), occlusion.occlusionInTargetSurface().bounds());
1266         EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
1267     }
1268 };
1269
1270 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestReplicaDoesOcclude);
1271
1272 template<class Types, bool opaqueLayers>
1273 class CCOcclusionTrackerTestReplicaWithClipping : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1274 protected:
1275     void runMyTest()
1276     {
1277         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 170));
1278         typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 100), IntSize(50, 50), true);
1279         this->createReplicaLayer(surface, this->identityMatrix, FloatPoint(50, 50), IntSize());
1280         this->calcDrawEtc(parent);
1281
1282         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
1283         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
1284
1285         this->visitLayer(surface, occlusion);
1286
1287         EXPECT_INT_RECT_EQ(IntRect(0, 100, 50, 50), occlusion.occlusionInScreenSpace().bounds());
1288         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
1289         EXPECT_INT_RECT_EQ(IntRect(0, 0, 50, 50), occlusion.occlusionInTargetSurface().bounds());
1290         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
1291
1292         this->visitContributingSurface(surface, occlusion);
1293         this->enterLayer(parent, occlusion);
1294
1295         // The surface and replica should both be occluding the parent.
1296         EXPECT_INT_RECT_EQ(IntRect(0, 100, 100, 70), occlusion.occlusionInTargetSurface().bounds());
1297         EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
1298     }
1299 };
1300
1301 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestReplicaWithClipping);
1302
1303 template<class Types, bool opaqueLayers>
1304 class CCOcclusionTrackerTestReplicaWithMask : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1305 protected:
1306     void runMyTest()
1307     {
1308         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 200));
1309         typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 100), IntSize(50, 50), true);
1310         typename Types::LayerType* replica = this->createReplicaLayer(surface, this->identityMatrix, FloatPoint(50, 50), IntSize());
1311         this->createMaskLayer(replica, IntSize(10, 10));
1312         this->calcDrawEtc(parent);
1313
1314         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
1315         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
1316
1317         this->visitLayer(surface, occlusion);
1318
1319         EXPECT_INT_RECT_EQ(IntRect(0, 100, 50, 50), occlusion.occlusionInScreenSpace().bounds());
1320         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
1321         EXPECT_INT_RECT_EQ(IntRect(0, 0, 50, 50), occlusion.occlusionInTargetSurface().bounds());
1322         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
1323
1324         this->visitContributingSurface(surface, occlusion);
1325         this->enterLayer(parent, occlusion);
1326
1327         // The replica should not be occluding the parent, since it has a mask applied to it.
1328         EXPECT_INT_RECT_EQ(IntRect(0, 100, 50, 50), occlusion.occlusionInTargetSurface().bounds());
1329         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
1330     }
1331 };
1332
1333 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestReplicaWithMask);
1334
1335 template<class Types, bool opaqueLayers>
1336 class CCOcclusionTrackerTestLayerClipRectOutsideChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1337 protected:
1338     void runMyTest()
1339     {
1340         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
1341         typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
1342         this->calcDrawEtc(parent);
1343
1344         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
1345         occlusion.setLayerClipRect(IntRect(200, 100, 100, 100));
1346
1347         this->enterLayer(layer, occlusion);
1348
1349         EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
1350         EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
1351         EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
1352         EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
1353         EXPECT_FALSE(occlusion.occluded(layer, IntRect(200, 100, 100, 100)));
1354
1355         occlusion.useDefaultLayerClipRect();
1356         EXPECT_TRUE(occlusion.occluded(layer, IntRect(200, 100, 100, 100)));
1357         occlusion.setLayerClipRect(IntRect(200, 100, 100, 100));
1358
1359         this->leaveLayer(layer, occlusion);
1360         this->visitContributingSurface(layer, occlusion);
1361         this->enterLayer(parent, occlusion);
1362
1363         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
1364         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
1365         EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
1366         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
1367         EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
1368         EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
1369         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
1370         EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
1371         EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
1372
1373         EXPECT_INT_RECT_EQ(IntRect(200, 100, 100, 100), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
1374     }
1375 };
1376
1377 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestLayerClipRectOutsideChild);
1378
1379 template<class Types, bool opaqueLayers>
1380 class CCOcclusionTrackerTestViewportRectOutsideChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1381 protected:
1382     void runMyTest()
1383     {
1384         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
1385         typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
1386         this->calcDrawEtc(parent);
1387
1388         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(200, 100, 100, 100));
1389         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
1390
1391         this->enterLayer(layer, occlusion);
1392
1393         EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
1394         EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
1395         EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
1396         EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
1397         EXPECT_FALSE(occlusion.occluded(layer, IntRect(200, 100, 100, 100)));
1398
1399         occlusion.useDefaultLayerClipRect();
1400         EXPECT_TRUE(occlusion.occluded(layer, IntRect(200, 100, 100, 100)));
1401         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
1402
1403         this->leaveLayer(layer, occlusion);
1404         this->visitContributingSurface(layer, occlusion);
1405         this->enterLayer(parent, occlusion);
1406
1407         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
1408         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
1409         EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
1410         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
1411         EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
1412         EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
1413         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
1414         EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
1415         EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
1416
1417         EXPECT_INT_RECT_EQ(IntRect(200, 100, 100, 100), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
1418     }
1419 };
1420
1421 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestViewportRectOutsideChild);
1422
1423 template<class Types, bool opaqueLayers>
1424 class CCOcclusionTrackerTestLayerClipRectOverChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1425 protected:
1426     void runMyTest()
1427     {
1428         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
1429         typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
1430         this->calcDrawEtc(parent);
1431
1432         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
1433         occlusion.setLayerClipRect(IntRect(100, 100, 100, 100));
1434
1435         this->enterLayer(layer, occlusion);
1436
1437         EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
1438         EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
1439         EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
1440         EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
1441
1442         this->leaveLayer(layer, occlusion);
1443         this->visitContributingSurface(layer, occlusion);
1444         this->enterLayer(parent, occlusion);
1445
1446         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
1447         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
1448         EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
1449         EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
1450         EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
1451         EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
1452         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
1453         EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
1454         EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
1455
1456         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)).isEmpty());
1457     }
1458 };
1459
1460 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestLayerClipRectOverChild);
1461
1462 template<class Types, bool opaqueLayers>
1463 class CCOcclusionTrackerTestViewportRectOverChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1464 protected:
1465     void runMyTest()
1466     {
1467         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
1468         typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
1469         this->calcDrawEtc(parent);
1470
1471         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(100, 100, 100, 100));
1472         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
1473
1474         this->enterLayer(layer, occlusion);
1475
1476         EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
1477         EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
1478         EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
1479         EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
1480
1481         this->leaveLayer(layer, occlusion);
1482         this->visitContributingSurface(layer, occlusion);
1483         this->enterLayer(parent, occlusion);
1484
1485         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
1486         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
1487         EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
1488         EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
1489         EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
1490         EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
1491         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
1492         EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
1493         EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
1494
1495         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)).isEmpty());
1496     }
1497 };
1498
1499 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestViewportRectOverChild);
1500
1501 template<class Types, bool opaqueLayers>
1502 class CCOcclusionTrackerTestLayerClipRectPartlyOverChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1503 protected:
1504     void runMyTest()
1505     {
1506         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
1507         typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
1508         this->calcDrawEtc(parent);
1509
1510         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
1511         occlusion.setLayerClipRect(IntRect(50, 50, 200, 200));
1512
1513         this->enterLayer(layer, occlusion);
1514
1515         EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
1516         EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
1517         EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
1518         EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
1519
1520         this->leaveLayer(layer, occlusion);
1521         this->visitContributingSurface(layer, occlusion);
1522         this->enterLayer(parent, occlusion);
1523
1524         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
1525         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
1526         EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
1527         EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
1528         EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
1529         EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
1530         EXPECT_FALSE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
1531         EXPECT_FALSE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
1532         EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
1533
1534         EXPECT_INT_RECT_EQ(IntRect(50, 50, 200, 200), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
1535         EXPECT_INT_RECT_EQ(IntRect(200, 50, 50, 50), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 100)));
1536         EXPECT_INT_RECT_EQ(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent, IntRect(0, 100, 300, 100)));
1537         EXPECT_INT_RECT_EQ(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent, IntRect(200, 100, 100, 100)));
1538         EXPECT_INT_RECT_EQ(IntRect(100, 200, 100, 50), occlusion.unoccludedContentRect(parent, IntRect(100, 200, 100, 100)));
1539     }
1540 };
1541
1542 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestLayerClipRectPartlyOverChild);
1543
1544 template<class Types, bool opaqueLayers>
1545 class CCOcclusionTrackerTestViewportRectPartlyOverChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1546 protected:
1547     void runMyTest()
1548     {
1549         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
1550         typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
1551         this->calcDrawEtc(parent);
1552
1553         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(50, 50, 200, 200));
1554         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
1555
1556         this->enterLayer(layer, occlusion);
1557
1558         EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
1559         EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
1560         EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
1561         EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
1562
1563         this->leaveLayer(layer, occlusion);
1564         this->visitContributingSurface(layer, occlusion);
1565         this->enterLayer(parent, occlusion);
1566
1567         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
1568         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
1569         EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
1570         EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
1571         EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
1572         EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
1573         EXPECT_FALSE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
1574         EXPECT_FALSE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
1575         EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
1576
1577         EXPECT_INT_RECT_EQ(IntRect(50, 50, 200, 200), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
1578         EXPECT_INT_RECT_EQ(IntRect(200, 50, 50, 50), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 100)));
1579         EXPECT_INT_RECT_EQ(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent, IntRect(0, 100, 300, 100)));
1580         EXPECT_INT_RECT_EQ(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent, IntRect(200, 100, 100, 100)));
1581         EXPECT_INT_RECT_EQ(IntRect(100, 200, 100, 50), occlusion.unoccludedContentRect(parent, IntRect(100, 200, 100, 100)));
1582     }
1583 };
1584
1585 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestViewportRectPartlyOverChild);
1586
1587 template<class Types, bool opaqueLayers>
1588 class CCOcclusionTrackerTestLayerClipRectOverNothing : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1589 protected:
1590     void runMyTest()
1591     {
1592         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
1593         typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
1594         this->calcDrawEtc(parent);
1595
1596         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
1597         occlusion.setLayerClipRect(IntRect(500, 500, 100, 100));
1598
1599         this->enterLayer(layer, occlusion);
1600
1601         EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
1602         EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
1603         EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
1604         EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
1605
1606         this->leaveLayer(layer, occlusion);
1607         this->visitContributingSurface(layer, occlusion);
1608         this->enterLayer(parent, occlusion);
1609
1610         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
1611         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
1612         EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
1613         EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
1614         EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
1615         EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
1616         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
1617         EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
1618         EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
1619
1620         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)).isEmpty());
1621         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 100)).isEmpty());
1622         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 100, 300, 100)).isEmpty());
1623         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(200, 100, 100, 100)).isEmpty());
1624         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(100, 200, 100, 100)).isEmpty());
1625     }
1626 };
1627
1628 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestLayerClipRectOverNothing);
1629
1630 template<class Types, bool opaqueLayers>
1631 class CCOcclusionTrackerTestViewportRectOverNothing : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1632 protected:
1633     void runMyTest()
1634     {
1635         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
1636         typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
1637         this->calcDrawEtc(parent);
1638
1639         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(500, 500, 100, 100));
1640         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
1641
1642         this->enterLayer(layer, occlusion);
1643
1644         EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
1645         EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
1646         EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
1647         EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
1648
1649         this->leaveLayer(layer, occlusion);
1650         this->visitContributingSurface(layer, occlusion);
1651         this->enterLayer(parent, occlusion);
1652
1653         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
1654         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
1655         EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
1656         EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
1657         EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
1658         EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
1659         EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
1660         EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
1661         EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
1662
1663         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)).isEmpty());
1664         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 100)).isEmpty());
1665         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 100, 300, 100)).isEmpty());
1666         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(200, 100, 100, 100)).isEmpty());
1667         EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(100, 200, 100, 100)).isEmpty());
1668     }
1669 };
1670
1671 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestViewportRectOverNothing);
1672
1673 template<class Types, bool opaqueLayers>
1674 class CCOcclusionTrackerTestLayerClipRectForLayerOffOrigin : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1675 protected:
1676     void runMyTest()
1677     {
1678         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
1679         typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
1680         this->calcDrawEtc(parent);
1681
1682         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
1683         this->enterLayer(layer, occlusion);
1684
1685         // This layer is translated when drawn into its target. So if the clip rect given from the target surface
1686         // is not in that target space, then after translating these query rects into the target, they will fall outside
1687         // the clip and be considered occluded.
1688         EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
1689         EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
1690         EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
1691         EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
1692     }
1693 };
1694
1695 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestLayerClipRectForLayerOffOrigin);
1696
1697 template<class Types, bool opaqueLayers>
1698 class CCOcclusionTrackerTestOpaqueContentsRegionEmpty : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1699 protected:
1700     void runMyTest()
1701     {
1702         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
1703         typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), false);
1704         this->calcDrawEtc(parent);
1705
1706         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
1707         this->enterLayer(layer, occlusion);
1708
1709         EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
1710         EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
1711         EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
1712         EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
1713
1714         // Occluded since its outside the surface bounds.
1715         EXPECT_TRUE(occlusion.occluded(layer, IntRect(200, 100, 100, 100)));
1716
1717         // Test without any clip rect.
1718         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
1719         EXPECT_FALSE(occlusion.occluded(layer, IntRect(200, 100, 100, 100)));
1720         occlusion.useDefaultLayerClipRect();
1721
1722         this->leaveLayer(layer, occlusion);
1723         this->visitContributingSurface(layer, occlusion);
1724         this->enterLayer(parent, occlusion);
1725
1726         EXPECT_TRUE(occlusion.occlusionInScreenSpace().bounds().isEmpty());
1727         EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size());
1728     }
1729 };
1730
1731 MAIN_AND_IMPL_THREAD_TEST(CCOcclusionTrackerTestOpaqueContentsRegionEmpty);
1732
1733 template<class Types, bool opaqueLayers>
1734 class CCOcclusionTrackerTestOpaqueContentsRegionNonEmpty : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1735 protected:
1736     void runMyTest()
1737     {
1738         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
1739         typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(100, 100), IntSize(200, 200), false);
1740         this->calcDrawEtc(parent);
1741
1742         {
1743             TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
1744             layer->setOpaqueContentsRect(IntRect(0, 0, 100, 100));
1745
1746             this->resetLayerIterator();
1747             this->visitLayer(layer, occlusion);
1748             this->enterLayer(parent, occlusion);
1749
1750             EXPECT_INT_RECT_EQ(IntRect(100, 100, 100, 100), occlusion.occlusionInScreenSpace().bounds());
1751             EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
1752
1753             EXPECT_FALSE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
1754             EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
1755             EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
1756         }
1757
1758         {
1759             TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
1760             layer->setOpaqueContentsRect(IntRect(20, 20, 180, 180));
1761
1762             this->resetLayerIterator();
1763             this->visitLayer(layer, occlusion);
1764             this->enterLayer(parent, occlusion);
1765
1766             EXPECT_INT_RECT_EQ(IntRect(120, 120, 180, 180), occlusion.occlusionInScreenSpace().bounds());
1767             EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
1768
1769             EXPECT_FALSE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
1770             EXPECT_FALSE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
1771             EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
1772         }
1773
1774         {
1775             TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
1776             layer->setOpaqueContentsRect(IntRect(150, 150, 100, 100));
1777
1778             this->resetLayerIterator();
1779             this->visitLayer(layer, occlusion);
1780             this->enterLayer(parent, occlusion);
1781
1782             EXPECT_INT_RECT_EQ(IntRect(250, 250, 50, 50), occlusion.occlusionInScreenSpace().bounds());
1783             EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
1784
1785             EXPECT_FALSE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
1786             EXPECT_FALSE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
1787             EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
1788         }
1789     }
1790 };
1791
1792 MAIN_AND_IMPL_THREAD_TEST(CCOcclusionTrackerTestOpaqueContentsRegionNonEmpty);
1793
1794 template<class Types, bool opaqueLayers>
1795 class CCOcclusionTrackerTest3dTransform : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1796 protected:
1797     void runMyTest()
1798     {
1799         WebTransformationMatrix transform;
1800         transform.rotate3d(0, 30, 0);
1801
1802         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
1803         typename Types::LayerType* container = this->createLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
1804         typename Types::ContentLayerType* layer = this->createDrawingLayer(container, transform, FloatPoint(100, 100), IntSize(200, 200), true);
1805         this->calcDrawEtc(parent);
1806
1807         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
1808         this->enterLayer(layer, occlusion);
1809
1810         // The layer is rotated in 3d but without preserving 3d, so it only gets resized.
1811         EXPECT_INT_RECT_EQ(IntRect(0, 0, 200, 200), occlusion.unoccludedContentRect(layer, IntRect(0, 0, 200, 200)));
1812     }
1813 };
1814
1815 MAIN_AND_IMPL_THREAD_TEST(CCOcclusionTrackerTest3dTransform);
1816
1817 template<class Types, bool opaqueLayers>
1818 class CCOcclusionTrackerTestUnsorted3dLayers : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1819 protected:
1820     void runMyTest()
1821     {
1822         // Currently, the main thread layer iterator does not iterate over 3d items in
1823         // sorted order, because layer sorting is not performed on the main thread.
1824         // Because of this, the occlusion tracker cannot assume that a 3d layer occludes
1825         // other layers that have not yet been iterated over. For now, the expected
1826         // behavior is that a 3d layer simply does not add any occlusion to the occlusion
1827         // tracker.
1828
1829         WebTransformationMatrix translationToFront;
1830         translationToFront.translate3d(0, 0, -10);
1831         WebTransformationMatrix translationToBack;
1832         translationToFront.translate3d(0, 0, -100);
1833
1834         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
1835         typename Types::ContentLayerType* child1 = this->createDrawingLayer(parent, translationToBack, FloatPoint(0, 0), IntSize(100, 100), true);
1836         typename Types::ContentLayerType* child2 = this->createDrawingLayer(parent, translationToFront, FloatPoint(50, 50), IntSize(100, 100), true);
1837         parent->setPreserves3D(true);
1838
1839         this->calcDrawEtc(parent);
1840
1841         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
1842         this->visitLayer(child2, occlusion);
1843         EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
1844         EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
1845
1846         this->visitLayer(child1, occlusion);
1847         EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
1848         EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
1849     }
1850 };
1851
1852 // This test will have different layer ordering on the impl thread; the test will only work on the main thread.
1853 MAIN_THREAD_TEST(CCOcclusionTrackerTestUnsorted3dLayers);
1854
1855 template<class Types, bool opaqueLayers>
1856 class CCOcclusionTrackerTestPerspectiveTransform : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1857 protected:
1858     void runMyTest()
1859     {
1860         WebTransformationMatrix transform;
1861         transform.translate(150, 150);
1862         transform.applyPerspective(400);
1863         transform.rotate3d(1, 0, 0, -30);
1864         transform.translate(-150, -150);
1865
1866         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
1867         typename Types::LayerType* container = this->createLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
1868         typename Types::ContentLayerType* layer = this->createDrawingLayer(container, transform, FloatPoint(100, 100), IntSize(200, 200), true);
1869         container->setPreserves3D(true);
1870         layer->setPreserves3D(true);
1871         this->calcDrawEtc(parent);
1872
1873         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
1874         this->enterLayer(layer, occlusion);
1875
1876         EXPECT_INT_RECT_EQ(IntRect(0, 0, 200, 200), occlusion.unoccludedContentRect(layer, IntRect(0, 0, 200, 200)));
1877     }
1878 };
1879
1880 // This test requires accumulating occlusion of 3d layers, which are skipped by the occlusion tracker on the main thread. So this test should run on the impl thread.
1881 IMPL_THREAD_TEST(CCOcclusionTrackerTestPerspectiveTransform);
1882
1883 template<class Types, bool opaqueLayers>
1884 class CCOcclusionTrackerTestPerspectiveTransformBehindCamera : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1885 protected:
1886     void runMyTest()
1887     {
1888         // This test is based on the platform/chromium/compositing/3d-corners.html layout test.
1889         WebTransformationMatrix transform;
1890         transform.translate(250, 50);
1891         transform.applyPerspective(10);
1892         transform.translate(-250, -50);
1893         transform.translate(250, 50);
1894         transform.rotate3d(1, 0, 0, -167);
1895         transform.translate(-250, -50);
1896
1897         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(500, 100));
1898         typename Types::LayerType* container = this->createLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(500, 500));
1899         typename Types::ContentLayerType* layer = this->createDrawingLayer(container, transform, FloatPoint(0, 0), IntSize(500, 500), true);
1900         container->setPreserves3D(true);
1901         layer->setPreserves3D(true);
1902         this->calcDrawEtc(parent);
1903
1904         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
1905         this->enterLayer(layer, occlusion);
1906
1907         // The bottom 11 pixel rows of this layer remain visible inside the container, after translation to the target surface. When translated back,
1908         // this will include many more pixels but must include at least the bottom 11 rows.
1909         EXPECT_TRUE(occlusion.unoccludedContentRect(layer, IntRect(0, 0, 500, 500)).contains(IntRect(0, 489, 500, 11)));
1910     }
1911 };
1912
1913 // This test requires accumulating occlusion of 3d layers, which are skipped by the occlusion tracker on the main thread. So this test should run on the impl thread.
1914 IMPL_THREAD_TEST(CCOcclusionTrackerTestPerspectiveTransformBehindCamera);
1915
1916 template<class Types, bool opaqueLayers>
1917 class CCOcclusionTrackerTestLayerBehindCameraDoesNotOcclude : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1918 protected:
1919     void runMyTest()
1920     {
1921         WebTransformationMatrix transform;
1922         transform.translate(50, 50);
1923         transform.applyPerspective(100);
1924         transform.translate3d(0, 0, 110);
1925         transform.translate(-50, -50);
1926
1927         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
1928         typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, transform, FloatPoint(0, 0), IntSize(100, 100), true);
1929         parent->setPreserves3D(true);
1930         layer->setPreserves3D(true);
1931         this->calcDrawEtc(parent);
1932
1933         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
1934
1935         // The |layer| is entirely behind the camera and should not occlude.
1936         this->visitLayer(layer, occlusion);
1937         this->enterLayer(parent, occlusion);
1938         EXPECT_EQ(0u, occlusion.occlusionInTargetSurface().rects().size());
1939         EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size());
1940     }
1941 };
1942
1943 // This test requires accumulating occlusion of 3d layers, which are skipped by the occlusion tracker on the main thread. So this test should run on the impl thread.
1944 IMPL_THREAD_TEST(CCOcclusionTrackerTestLayerBehindCameraDoesNotOcclude);
1945
1946 template<class Types, bool opaqueLayers>
1947 class CCOcclusionTrackerTestLargePixelsOccludeInsideClipRect : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1948 protected:
1949     void runMyTest()
1950     {
1951         WebTransformationMatrix transform;
1952         transform.translate(50, 50);
1953         transform.applyPerspective(100);
1954         transform.translate3d(0, 0, 99);
1955         transform.translate(-50, -50);
1956
1957         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
1958         typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, transform, FloatPoint(0, 0), IntSize(100, 100), true);
1959         parent->setPreserves3D(true);
1960         layer->setPreserves3D(true);
1961         this->calcDrawEtc(parent);
1962
1963         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
1964
1965         // This is very close to the camera, so pixels in its visibleContentRect will actually go outside of the layer's clipRect.
1966         // Ensure that those pixels don't occlude things outside the clipRect.
1967         this->visitLayer(layer, occlusion);
1968         this->enterLayer(parent, occlusion);
1969         EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 100), occlusion.occlusionInTargetSurface().bounds());
1970         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
1971         EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 100), occlusion.occlusionInScreenSpace().bounds());
1972         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
1973     }
1974 };
1975
1976 // This test requires accumulating occlusion of 3d layers, which are skipped by the occlusion tracker on the main thread. So this test should run on the impl thread.
1977 IMPL_THREAD_TEST(CCOcclusionTrackerTestLargePixelsOccludeInsideClipRect);
1978
1979 template<class Types, bool opaqueLayers>
1980 class CCOcclusionTrackerTestAnimationOpacity1OnMainThread : public CCOcclusionTrackerTest<Types, opaqueLayers> {
1981 protected:
1982     void runMyTest()
1983     {
1984         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
1985         typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300), true);
1986         typename Types::ContentLayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300), true);
1987         typename Types::ContentLayerType* surfaceChild = this->createDrawingLayer(surface, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 300), true);
1988         typename Types::ContentLayerType* surfaceChild2 = this->createDrawingLayer(surface, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 300), true);
1989         typename Types::ContentLayerType* parent2 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false);
1990         typename Types::ContentLayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(250, 0), IntSize(50, 300), true);
1991
1992         addOpacityTransitionToController(*layer->layerAnimationController(), 10, 0, 1, false);
1993         addOpacityTransitionToController(*surface->layerAnimationController(), 10, 0, 1, false);
1994         this->calcDrawEtc(parent);
1995
1996         EXPECT_TRUE(layer->drawOpacityIsAnimating());
1997         EXPECT_FALSE(surface->drawOpacityIsAnimating());
1998         EXPECT_TRUE(surface->renderSurface()->drawOpacityIsAnimating());
1999
2000         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
2001
2002         this->visitLayer(topmost, occlusion);
2003         this->enterLayer(parent2, occlusion);
2004         // This occlusion will affect all surfaces.
2005         EXPECT_INT_RECT_EQ(IntRect(0, 0, 250, 300), occlusion.unoccludedContentRect(parent2, IntRect(0, 0, 300, 300)));
2006         this->leaveLayer(parent2, occlusion);
2007
2008         this->visitLayer(surfaceChild2, occlusion);
2009         this->enterLayer(surfaceChild, occlusion);
2010         EXPECT_INT_RECT_EQ(IntRect(100, 0, 100, 300), occlusion.unoccludedContentRect(surfaceChild, IntRect(0, 0, 300, 300)));
2011         this->leaveLayer(surfaceChild, occlusion);
2012         this->enterLayer(surface, occlusion);
2013         EXPECT_INT_RECT_EQ(IntRect(200, 0, 50, 300), occlusion.unoccludedContentRect(surface, IntRect(0, 0, 300, 300)));
2014         this->leaveLayer(surface, occlusion);
2015
2016         this->enterContributingSurface(surface, occlusion);
2017         // Occlusion within the surface is lost when leaving the animating surface.
2018         EXPECT_INT_RECT_EQ(IntRect(0, 0, 250, 300), occlusion.unoccludedContributingSurfaceContentRect(surface, false, IntRect(0, 0, 300, 300)));
2019         this->leaveContributingSurface(surface, occlusion);
2020
2021         this->visitLayer(layer, occlusion);
2022         this->enterLayer(parent, occlusion);
2023
2024         // Occlusion is not added for the animating |layer|.
2025         EXPECT_INT_RECT_EQ(IntRect(0, 0, 250, 300), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
2026     }
2027 };
2028
2029 MAIN_THREAD_TEST(CCOcclusionTrackerTestAnimationOpacity1OnMainThread);
2030
2031 template<class Types, bool opaqueLayers>
2032 class CCOcclusionTrackerTestAnimationOpacity0OnMainThread : public CCOcclusionTrackerTest<Types, opaqueLayers> {
2033 protected:
2034     void runMyTest()
2035     {
2036         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
2037         typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300), true);
2038         typename Types::ContentLayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300), true);
2039         typename Types::ContentLayerType* surfaceChild = this->createDrawingLayer(surface, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 300), true);
2040         typename Types::ContentLayerType* surfaceChild2 = this->createDrawingLayer(surface, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 300), true);
2041         typename Types::ContentLayerType* parent2 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false);
2042         typename Types::ContentLayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(250, 0), IntSize(50, 300), true);
2043
2044         addOpacityTransitionToController(*layer->layerAnimationController(), 10, 1, 0, false);
2045         addOpacityTransitionToController(*surface->layerAnimationController(), 10, 1, 0, false);
2046         this->calcDrawEtc(parent);
2047
2048         EXPECT_TRUE(layer->drawOpacityIsAnimating());
2049         EXPECT_FALSE(surface->drawOpacityIsAnimating());
2050         EXPECT_TRUE(surface->renderSurface()->drawOpacityIsAnimating());
2051
2052         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
2053
2054         this->visitLayer(topmost, occlusion);
2055         this->enterLayer(parent2, occlusion);
2056         // This occlusion will affect all surfaces.
2057         EXPECT_INT_RECT_EQ(IntRect(0, 0, 250, 300), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
2058         this->leaveLayer(parent2, occlusion);
2059
2060         this->visitLayer(surfaceChild2, occlusion);
2061         this->enterLayer(surfaceChild, occlusion);
2062         EXPECT_INT_RECT_EQ(IntRect(100, 0, 100, 300), occlusion.unoccludedContentRect(surfaceChild, IntRect(0, 0, 300, 300)));
2063         this->leaveLayer(surfaceChild, occlusion);
2064         this->enterLayer(surface, occlusion);
2065         EXPECT_INT_RECT_EQ(IntRect(200, 0, 50, 300), occlusion.unoccludedContentRect(surface, IntRect(0, 0, 300, 300)));
2066         this->leaveLayer(surface, occlusion);
2067
2068         this->enterContributingSurface(surface, occlusion);
2069         // Occlusion within the surface is lost when leaving the animating surface.
2070         EXPECT_INT_RECT_EQ(IntRect(0, 0, 250, 300), occlusion.unoccludedContributingSurfaceContentRect(surface, false, IntRect(0, 0, 300, 300)));
2071         this->leaveContributingSurface(surface, occlusion);
2072
2073         this->visitLayer(layer, occlusion);
2074         this->enterLayer(parent, occlusion);
2075
2076         // Occlusion is not added for the animating |layer|.
2077         EXPECT_INT_RECT_EQ(IntRect(0, 0, 250, 300), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
2078     }
2079 };
2080
2081 MAIN_THREAD_TEST(CCOcclusionTrackerTestAnimationOpacity0OnMainThread);
2082
2083 template<class Types, bool opaqueLayers>
2084 class CCOcclusionTrackerTestAnimationTranslateOnMainThread : public CCOcclusionTrackerTest<Types, opaqueLayers> {
2085 protected:
2086     void runMyTest()
2087     {
2088         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
2089         typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300), true);
2090         typename Types::ContentLayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300), true);
2091         typename Types::ContentLayerType* surfaceChild = this->createDrawingLayer(surface, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 300), true);
2092         typename Types::ContentLayerType* surfaceChild2 = this->createDrawingLayer(surface, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 300), true);
2093         typename Types::ContentLayerType* surface2 = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(50, 300), true);
2094
2095         addAnimatedTransformToController(*layer->layerAnimationController(), 10, 30, 0);
2096         addAnimatedTransformToController(*surface->layerAnimationController(), 10, 30, 0);
2097         addAnimatedTransformToController(*surfaceChild->layerAnimationController(), 10, 30, 0);
2098         this->calcDrawEtc(parent);
2099
2100         EXPECT_TRUE(layer->drawTransformIsAnimating());
2101         EXPECT_TRUE(layer->screenSpaceTransformIsAnimating());
2102         EXPECT_TRUE(surface->renderSurface()->targetSurfaceTransformsAreAnimating());
2103         EXPECT_TRUE(surface->renderSurface()->screenSpaceTransformsAreAnimating());
2104         // The surface owning layer doesn't animate against its own surface.
2105         EXPECT_FALSE(surface->drawTransformIsAnimating());
2106         EXPECT_TRUE(surface->screenSpaceTransformIsAnimating());
2107         EXPECT_TRUE(surfaceChild->drawTransformIsAnimating());
2108         EXPECT_TRUE(surfaceChild->screenSpaceTransformIsAnimating());
2109
2110         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
2111
2112         this->visitLayer(surface2, occlusion);
2113         this->enterContributingSurface(surface2, occlusion);
2114
2115         EXPECT_INT_RECT_EQ(IntRect(0, 0, 50, 300), occlusion.occlusionInScreenSpace().bounds());
2116         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
2117
2118         this->leaveContributingSurface(surface2, occlusion);
2119         this->enterLayer(surfaceChild2, occlusion);
2120
2121         // surfaceChild2 is moving in screen space but not relative to its target, so occlusion should happen in its target space only.
2122         // It also means that things occluding in screen space (e.g. surface2) cannot occlude this layer.
2123         EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 300), occlusion.unoccludedContentRect(surfaceChild2, IntRect(0, 0, 100, 300)));
2124         EXPECT_FALSE(occlusion.occluded(surfaceChild, IntRect(0, 0, 50, 300)));
2125
2126         this->leaveLayer(surfaceChild2, occlusion);
2127         this->enterLayer(surfaceChild, occlusion);
2128         EXPECT_FALSE(occlusion.occluded(surfaceChild, IntRect(0, 0, 100, 300)));
2129         EXPECT_INT_RECT_EQ(IntRect(0, 0, 50, 300), occlusion.occlusionInScreenSpace().bounds());
2130         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
2131         EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 300), occlusion.occlusionInTargetSurface().bounds());
2132         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
2133         EXPECT_INT_RECT_EQ(IntRect(100, 0, 200, 300), occlusion.unoccludedContentRect(surface, IntRect(0, 0, 300, 300)));
2134
2135         // The surfaceChild is occluded by the surfaceChild2, but is moving relative its target and the screen, so it
2136         // can't be occluded.
2137         EXPECT_INT_RECT_EQ(IntRect(0, 0, 200, 300), occlusion.unoccludedContentRect(surfaceChild, IntRect(0, 0, 200, 300)));
2138         EXPECT_FALSE(occlusion.occluded(surfaceChild, IntRect(0, 0, 50, 300)));
2139
2140         this->leaveLayer(surfaceChild, occlusion);
2141         this->enterLayer(surface, occlusion);
2142         // The surfaceChild is moving in screen space but not relative to its target, so occlusion should happen in its target space only.
2143         EXPECT_INT_RECT_EQ(IntRect(0, 0, 50, 300), occlusion.occlusionInScreenSpace().bounds());
2144         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
2145         EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 300), occlusion.occlusionInTargetSurface().bounds());
2146         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
2147         EXPECT_INT_RECT_EQ(IntRect(100, 0, 200, 300), occlusion.unoccludedContentRect(surface, IntRect(0, 0, 300, 300)));
2148
2149         this->leaveLayer(surface, occlusion);
2150         // The surface's owning layer is moving in screen space but not relative to its target, so occlusion should happen in its target space only.
2151         EXPECT_INT_RECT_EQ(IntRect(0, 0, 50, 300), occlusion.occlusionInScreenSpace().bounds());
2152         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
2153         EXPECT_INT_RECT_EQ(IntRect(0, 0, 300, 300), occlusion.occlusionInTargetSurface().bounds());
2154         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
2155         EXPECT_INT_RECT_EQ(IntRect(0, 0, 0, 0), occlusion.unoccludedContentRect(surface, IntRect(0, 0, 300, 300)));
2156
2157         this->enterContributingSurface(surface, occlusion);
2158         // The contributing |surface| is animating so it can't be occluded.
2159         EXPECT_INT_RECT_EQ(IntRect(0, 0, 300, 300), occlusion.unoccludedContributingSurfaceContentRect(surface, false, IntRect(0, 0, 300, 300)));
2160         this->leaveContributingSurface(surface, occlusion);
2161
2162         this->enterLayer(layer, occlusion);
2163         // The |surface| is moving in the screen and in its target, so all occlusion within the surface is lost when leaving it.
2164         EXPECT_INT_RECT_EQ(IntRect(50, 0, 250, 300), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
2165         this->leaveLayer(layer, occlusion);
2166
2167         this->enterLayer(parent, occlusion);
2168         // The |layer| is animating in the screen and in its target, so no occlusion is added.
2169         EXPECT_INT_RECT_EQ(IntRect(50, 0, 250, 300), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
2170     }
2171 };
2172
2173 MAIN_THREAD_TEST(CCOcclusionTrackerTestAnimationTranslateOnMainThread);
2174
2175 template<class Types, bool opaqueLayers>
2176 class CCOcclusionTrackerTestSurfaceOcclusionTranslatesToParent : public CCOcclusionTrackerTest<Types, opaqueLayers> {
2177 protected:
2178     void runMyTest()
2179     {
2180         WebTransformationMatrix surfaceTransform;
2181         surfaceTransform.translate(300, 300);
2182         surfaceTransform.scale(2);
2183         surfaceTransform.translate(-150, -150);
2184
2185         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(500, 500));
2186         typename Types::ContentLayerType* surface = this->createDrawingSurface(parent, surfaceTransform, FloatPoint(0, 0), IntSize(300, 300), false);
2187         typename Types::ContentLayerType* surface2 = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(50, 50), IntSize(300, 300), false);
2188         surface->setOpaqueContentsRect(IntRect(0, 0, 200, 200));
2189         surface2->setOpaqueContentsRect(IntRect(0, 0, 200, 200));
2190         this->calcDrawEtc(parent);
2191
2192         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
2193
2194         this->visitLayer(surface2, occlusion);
2195         this->visitContributingSurface(surface2, occlusion);
2196
2197         EXPECT_INT_RECT_EQ(IntRect(50, 50, 200, 200), occlusion.occlusionInScreenSpace().bounds());
2198         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
2199         EXPECT_INT_RECT_EQ(IntRect(50, 50, 200, 200), occlusion.occlusionInTargetSurface().bounds());
2200         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
2201
2202         // Clear any stored occlusion.
2203         occlusion.setOcclusionInScreenSpace(Region());
2204         occlusion.setOcclusionInTargetSurface(Region());
2205
2206         this->visitLayer(surface, occlusion);
2207         this->visitContributingSurface(surface, occlusion);
2208
2209         EXPECT_INT_RECT_EQ(IntRect(0, 0, 400, 400), occlusion.occlusionInScreenSpace().bounds());
2210         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
2211         EXPECT_INT_RECT_EQ(IntRect(0, 0, 400, 400), occlusion.occlusionInTargetSurface().bounds());
2212         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
2213     }
2214 };
2215
2216 MAIN_AND_IMPL_THREAD_TEST(CCOcclusionTrackerTestSurfaceOcclusionTranslatesToParent);
2217
2218 template<class Types, bool opaqueLayers>
2219 class CCOcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping : public CCOcclusionTrackerTest<Types, opaqueLayers> {
2220 protected:
2221     void runMyTest()
2222     {
2223         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
2224         typename Types::ContentLayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(500, 300), false);
2225         surface->setOpaqueContentsRect(IntRect(0, 0, 400, 200));
2226         this->calcDrawEtc(parent);
2227
2228         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
2229
2230         this->visitLayer(surface, occlusion);
2231         this->visitContributingSurface(surface, occlusion);
2232
2233         EXPECT_INT_RECT_EQ(IntRect(0, 0, 300, 200), occlusion.occlusionInScreenSpace().bounds());
2234         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
2235         EXPECT_INT_RECT_EQ(IntRect(0, 0, 300, 200), occlusion.occlusionInTargetSurface().bounds());
2236         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
2237     }
2238 };
2239
2240 MAIN_AND_IMPL_THREAD_TEST(CCOcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping);
2241
2242 template<class Types, bool opaqueLayers>
2243 class CCOcclusionTrackerTestReplicaOccluded : public CCOcclusionTrackerTest<Types, opaqueLayers> {
2244 protected:
2245     void runMyTest()
2246     {
2247         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 200));
2248         typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100), true);
2249         this->createReplicaLayer(surface, this->identityMatrix, FloatPoint(0, 100), IntSize(100, 100));
2250         typename Types::LayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 100), IntSize(100, 100), true);
2251         this->calcDrawEtc(parent);
2252
2253         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
2254         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
2255
2256         // |topmost| occludes the replica, but not the surface itself.
2257         this->visitLayer(topmost, occlusion);
2258
2259         EXPECT_INT_RECT_EQ(IntRect(0, 100, 100, 100), occlusion.occlusionInScreenSpace().bounds());
2260         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
2261         EXPECT_INT_RECT_EQ(IntRect(0, 100, 100, 100), occlusion.occlusionInTargetSurface().bounds());
2262         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
2263
2264         this->visitLayer(surface, occlusion);
2265
2266         EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 200), occlusion.occlusionInScreenSpace().bounds());
2267         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
2268         EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 100), occlusion.occlusionInTargetSurface().bounds());
2269         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
2270
2271         this->enterContributingSurface(surface, occlusion);
2272
2273         // Surface is not occluded so it shouldn't think it is.
2274         EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 100), occlusion.unoccludedContributingSurfaceContentRect(surface, false, IntRect(0, 0, 100, 100)));
2275     }
2276 };
2277
2278 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestReplicaOccluded);
2279
2280 template<class Types, bool opaqueLayers>
2281 class CCOcclusionTrackerTestSurfaceWithReplicaUnoccluded : public CCOcclusionTrackerTest<Types, opaqueLayers> {
2282 protected:
2283     void runMyTest()
2284     {
2285         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 200));
2286         typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100), true);
2287         this->createReplicaLayer(surface, this->identityMatrix, FloatPoint(0, 100), IntSize(100, 100));
2288         typename Types::LayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 110), true);
2289         this->calcDrawEtc(parent);
2290
2291         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
2292         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
2293
2294         // |topmost| occludes the surface, but not the entire surface's replica.
2295         this->visitLayer(topmost, occlusion);
2296
2297         EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 110), occlusion.occlusionInScreenSpace().bounds());
2298         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
2299         EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 110), occlusion.occlusionInTargetSurface().bounds());
2300         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
2301
2302         this->visitLayer(surface, occlusion);
2303
2304         EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 110), occlusion.occlusionInScreenSpace().bounds());
2305         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
2306         EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 100), occlusion.occlusionInTargetSurface().bounds());
2307         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
2308
2309         this->enterContributingSurface(surface, occlusion);
2310
2311         // Surface is occluded, but only the top 10px of the replica.
2312         EXPECT_INT_RECT_EQ(IntRect(0, 0, 0, 0), occlusion.unoccludedContributingSurfaceContentRect(surface, false, IntRect(0, 0, 100, 100)));
2313         EXPECT_INT_RECT_EQ(IntRect(0, 10, 100, 90), occlusion.unoccludedContributingSurfaceContentRect(surface, true, IntRect(0, 0, 100, 100)));
2314     }
2315 };
2316
2317 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestSurfaceWithReplicaUnoccluded);
2318
2319 template<class Types, bool opaqueLayers>
2320 class CCOcclusionTrackerTestSurfaceAndReplicaOccludedDifferently : public CCOcclusionTrackerTest<Types, opaqueLayers> {
2321 protected:
2322     void runMyTest()
2323     {
2324         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 200));
2325         typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100), true);
2326         this->createReplicaLayer(surface, this->identityMatrix, FloatPoint(0, 100), IntSize(100, 100));
2327         typename Types::LayerType* overSurface = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(40, 100), true);
2328         typename Types::LayerType* overReplica = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 100), IntSize(50, 100), true);
2329         this->calcDrawEtc(parent);
2330
2331         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
2332         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
2333
2334         // These occlude the surface and replica differently, so we can test each one.
2335         this->visitLayer(overReplica, occlusion);
2336         this->visitLayer(overSurface, occlusion);
2337
2338         EXPECT_INT_RECT_EQ(IntRect(0, 0, 50, 200), occlusion.occlusionInScreenSpace().bounds());
2339         EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
2340         EXPECT_INT_RECT_EQ(IntRect(0, 0, 50, 200), occlusion.occlusionInTargetSurface().bounds());
2341         EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
2342
2343         this->visitLayer(surface, occlusion);
2344
2345         EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 200), occlusion.occlusionInScreenSpace().bounds());
2346         EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
2347         EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 100), occlusion.occlusionInTargetSurface().bounds());
2348         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
2349
2350         this->enterContributingSurface(surface, occlusion);
2351
2352         // Surface and replica are occluded different amounts.
2353         EXPECT_INT_RECT_EQ(IntRect(40, 0, 60, 100), occlusion.unoccludedContributingSurfaceContentRect(surface, false, IntRect(0, 0, 100, 100)));
2354         EXPECT_INT_RECT_EQ(IntRect(50, 0, 50, 100), occlusion.unoccludedContributingSurfaceContentRect(surface, true, IntRect(0, 0, 100, 100)));
2355     }
2356 };
2357
2358 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestSurfaceAndReplicaOccludedDifferently);
2359
2360 template<class Types, bool opaqueLayers>
2361 class CCOcclusionTrackerTestSurfaceChildOfSurface : public CCOcclusionTrackerTest<Types, opaqueLayers> {
2362 protected:
2363     void runMyTest()
2364     {
2365         // This test verifies that the surface cliprect does not end up empty and clip away the entire unoccluded rect.
2366
2367         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 200));
2368         typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100), true);
2369         typename Types::LayerType* surfaceChild = this->createDrawingSurface(surface, this->identityMatrix, FloatPoint(0, 10), IntSize(100, 50), true);
2370         typename Types::LayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 50), true);
2371         this->calcDrawEtc(parent);
2372
2373         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(-100, -100, 1000, 1000));
2374
2375         // |topmost| occludes everything partially so we know occlusion is happening at all.
2376         this->visitLayer(topmost, occlusion);
2377
2378         EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 50), occlusion.occlusionInScreenSpace().bounds());
2379         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
2380         EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 50), occlusion.occlusionInTargetSurface().bounds());
2381         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
2382
2383         this->visitLayer(surfaceChild, occlusion);
2384
2385         // surfaceChild increases the occlusion in the screen by a narrow sliver.
2386         EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 60), occlusion.occlusionInScreenSpace().bounds());
2387         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
2388         // In its own surface, surfaceChild is at 0,0 as is its occlusion.
2389         EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 50), occlusion.occlusionInTargetSurface().bounds());
2390         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
2391
2392         // The root layer always has a clipRect. So the parent of |surface| has a clipRect. However, the owning layer for |surface| does not
2393         // mask to bounds, so it doesn't have a clipRect of its own. Thus the parent of |surfaceChild| exercises different code paths
2394         // as its parent does not have a clipRect.
2395
2396         this->enterContributingSurface(surfaceChild, occlusion);
2397         // The surfaceChild's parent does not have a clipRect as it owns a render surface. Make sure the unoccluded rect
2398         // does not get clipped away inappropriately.
2399         EXPECT_INT_RECT_EQ(IntRect(0, 40, 100, 10), occlusion.unoccludedContributingSurfaceContentRect(surfaceChild, false, IntRect(0, 0, 100, 50)));
2400         this->leaveContributingSurface(surfaceChild, occlusion);
2401
2402         // When the surfaceChild's occlusion is transformed up to its parent, make sure it is not clipped away inappropriately also.
2403         this->enterLayer(surface, occlusion);
2404         EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 60), occlusion.occlusionInScreenSpace().bounds());
2405         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
2406         EXPECT_INT_RECT_EQ(IntRect(0, 10, 100, 50), occlusion.occlusionInTargetSurface().bounds());
2407         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
2408         this->leaveLayer(surface, occlusion);
2409
2410         this->enterContributingSurface(surface, occlusion);
2411         // The surface's parent does have a clipRect as it is the root layer.
2412         EXPECT_INT_RECT_EQ(IntRect(0, 50, 100, 50), occlusion.unoccludedContributingSurfaceContentRect(surface, false, IntRect(0, 0, 100, 100)));
2413     }
2414 };
2415
2416 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestSurfaceChildOfSurface);
2417
2418 template<class Types, bool opaqueLayers>
2419 class CCOcclusionTrackerTestTopmostSurfaceIsClippedToViewport : public CCOcclusionTrackerTest<Types, opaqueLayers> {
2420 protected:
2421     void runMyTest()
2422     {
2423         // This test verifies that the top-most surface is considered occluded outside of its target's clipRect and outside the viewport rect.
2424
2425         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 200));
2426         typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 300), true);
2427         this->calcDrawEtc(parent);
2428
2429         {
2430             // Make a viewport rect that is larger than the root layer.
2431             TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
2432
2433             this->visitLayer(surface, occlusion);
2434
2435             // The root layer always has a clipRect. So the parent of |surface| has a clipRect giving the surface itself a clipRect.
2436             this->enterContributingSurface(surface, occlusion);
2437             // Make sure the parent's clipRect clips the unoccluded region of the child surface.
2438             EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 200), occlusion.unoccludedContributingSurfaceContentRect(surface, false, IntRect(0, 0, 100, 300)));
2439         }
2440         this->resetLayerIterator();
2441         {
2442             // Make a viewport rect that is smaller than the root layer.
2443             TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 100, 100));
2444
2445             this->visitLayer(surface, occlusion);
2446
2447             // The root layer always has a clipRect. So the parent of |surface| has a clipRect giving the surface itself a clipRect.
2448             this->enterContributingSurface(surface, occlusion);
2449             // Make sure the viewport rect clips the unoccluded region of the child surface.
2450             EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 100), occlusion.unoccludedContributingSurfaceContentRect(surface, false, IntRect(0, 0, 100, 300)));
2451         }
2452     }
2453 };
2454
2455 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestTopmostSurfaceIsClippedToViewport);
2456
2457 template<class Types, bool opaqueLayers>
2458 class CCOcclusionTrackerTestSurfaceChildOfClippingSurface : public CCOcclusionTrackerTest<Types, opaqueLayers> {
2459 protected:
2460     void runMyTest()
2461     {
2462         // This test verifies that the surface cliprect does not end up empty and clip away the entire unoccluded rect.
2463
2464         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(80, 200));
2465         typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100), true);
2466         typename Types::LayerType* surfaceChild = this->createDrawingSurface(surface, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100), false);
2467         typename Types::LayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 50), true);
2468         this->calcDrawEtc(parent);
2469
2470         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
2471         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
2472
2473         // |topmost| occludes everything partially so we know occlusion is happening at all.
2474         this->visitLayer(topmost, occlusion);
2475
2476         EXPECT_INT_RECT_EQ(IntRect(0, 0, 80, 50), occlusion.occlusionInScreenSpace().bounds());
2477         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
2478         EXPECT_INT_RECT_EQ(IntRect(0, 0, 80, 50), occlusion.occlusionInTargetSurface().bounds());
2479         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
2480
2481         // surfaceChild is not opaque and does not occlude, so we have a non-empty unoccluded area on surface.
2482         this->visitLayer(surfaceChild, occlusion);
2483
2484         EXPECT_INT_RECT_EQ(IntRect(0, 0, 80, 50), occlusion.occlusionInScreenSpace().bounds());
2485         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
2486         EXPECT_INT_RECT_EQ(IntRect(0, 0, 0, 0), occlusion.occlusionInTargetSurface().bounds());
2487         EXPECT_EQ(0u, occlusion.occlusionInTargetSurface().rects().size());
2488
2489         // The root layer always has a clipRect. So the parent of |surface| has a clipRect. However, the owning layer for |surface| does not
2490         // mask to bounds, so it doesn't have a clipRect of its own. Thus the parent of |surfaceChild| exercises different code paths
2491         // as its parent does not have a clipRect.
2492
2493         this->enterContributingSurface(surfaceChild, occlusion);
2494         // The surfaceChild's parent does not have a clipRect as it owns a render surface.
2495         EXPECT_INT_RECT_EQ(IntRect(0, 50, 80, 50), occlusion.unoccludedContributingSurfaceContentRect(surfaceChild, false, IntRect(0, 0, 100, 100)));
2496         this->leaveContributingSurface(surfaceChild, occlusion);
2497
2498         this->visitLayer(surface, occlusion);
2499         this->enterContributingSurface(surface, occlusion);
2500         // The surface's parent does have a clipRect as it is the root layer.
2501         EXPECT_INT_RECT_EQ(IntRect(0, 50, 80, 50), occlusion.unoccludedContributingSurfaceContentRect(surface, false, IntRect(0, 0, 100, 100)));
2502     }
2503 };
2504
2505 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestSurfaceChildOfClippingSurface);
2506
2507 template<class Types, bool opaqueLayers>
2508 class CCOcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter : public CCOcclusionTrackerTest<Types, opaqueLayers> {
2509 protected:
2510     void runMyTest()
2511     {
2512         WebTransformationMatrix scaleByHalf;
2513         scaleByHalf.scale(0.5);
2514
2515         // Make a surface and its replica, each 50x50, that are completely surrounded by opaque layers which are above them in the z-order.
2516         // The surface is scaled to test that the pixel moving is done in the target space, where the background filter is applied, but the surface
2517         // appears at 50, 50 and the replica at 200, 50.
2518         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 150));
2519         typename Types::LayerType* filteredSurface = this->createDrawingLayer(parent, scaleByHalf, FloatPoint(50, 50), IntSize(100, 100), false);
2520         this->createReplicaLayer(filteredSurface, this->identityMatrix, FloatPoint(300, 0), IntSize());
2521         typename Types::LayerType* occludingLayer1 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 50), true);
2522         typename Types::LayerType* occludingLayer2 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 100), IntSize(300, 50), true);
2523         typename Types::LayerType* occludingLayer3 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 50), IntSize(50, 50), true);
2524         typename Types::LayerType* occludingLayer4 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(100, 50), IntSize(100, 50), true);
2525         typename Types::LayerType* occludingLayer5 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(250, 50), IntSize(50, 50), true);
2526
2527         // Filters make the layer own a surface.
2528         WebFilterOperations filters;
2529         filters.append(WebFilterOperation::createBlurFilter(10));
2530         filteredSurface->setBackgroundFilters(filters);
2531
2532         // Save the distance of influence for the blur effect.
2533         int outsetTop, outsetRight, outsetBottom, outsetLeft;
2534         filters.getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft);
2535
2536         this->calcDrawEtc(parent);
2537
2538         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
2539         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
2540
2541         // These layers occlude pixels directly beside the filteredSurface. Because filtered surface blends pixels in a radius, it will
2542         // need to see some of the pixels (up to radius far) underneath the occludingLayers.
2543         this->visitLayer(occludingLayer5, occlusion);
2544         this->visitLayer(occludingLayer4, occlusion);
2545         this->visitLayer(occludingLayer3, occlusion);
2546         this->visitLayer(occludingLayer2, occlusion);
2547         this->visitLayer(occludingLayer1, occlusion);
2548
2549         EXPECT_INT_RECT_EQ(IntRect(0, 0, 300, 150), occlusion.occlusionInScreenSpace().bounds());
2550         EXPECT_EQ(5u, occlusion.occlusionInScreenSpace().rects().size());
2551         EXPECT_INT_RECT_EQ(IntRect(0, 0, 300, 150), occlusion.occlusionInTargetSurface().bounds());
2552         EXPECT_EQ(5u, occlusion.occlusionInTargetSurface().rects().size());
2553
2554         // Everything outside the surface/replica is occluded but the surface/replica itself is not.
2555         this->enterLayer(filteredSurface, occlusion);
2556         EXPECT_INT_RECT_EQ(IntRect(1, 0, 99, 100), occlusion.unoccludedContentRect(filteredSurface, IntRect(1, 0, 100, 100)));
2557         EXPECT_INT_RECT_EQ(IntRect(0, 1, 100, 99), occlusion.unoccludedContentRect(filteredSurface, IntRect(0, 1, 100, 100)));
2558         EXPECT_INT_RECT_EQ(IntRect(0, 0, 99, 100), occlusion.unoccludedContentRect(filteredSurface, IntRect(-1, 0, 100, 100)));
2559         EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 99), occlusion.unoccludedContentRect(filteredSurface, IntRect(0, -1, 100, 100)));
2560
2561         EXPECT_INT_RECT_EQ(IntRect(300 + 1, 0, 99, 100), occlusion.unoccludedContentRect(filteredSurface, IntRect(300 + 1, 0, 100, 100)));
2562         EXPECT_INT_RECT_EQ(IntRect(300 + 0, 1, 100, 99), occlusion.unoccludedContentRect(filteredSurface, IntRect(300 + 0, 1, 100, 100)));
2563         EXPECT_INT_RECT_EQ(IntRect(300 + 0, 0, 99, 100), occlusion.unoccludedContentRect(filteredSurface, IntRect(300 - 1, 0, 100, 100)));
2564         EXPECT_INT_RECT_EQ(IntRect(300 + 0, 0, 100, 99), occlusion.unoccludedContentRect(filteredSurface, IntRect(300 + 0, -1, 100, 100)));
2565         this->leaveLayer(filteredSurface, occlusion);
2566
2567         // The filtered layer/replica does not occlude.
2568         EXPECT_INT_RECT_EQ(IntRect(0, 0, 300, 150), occlusion.occlusionInScreenSpace().bounds());
2569         EXPECT_EQ(5u, occlusion.occlusionInScreenSpace().rects().size());
2570         EXPECT_INT_RECT_EQ(IntRect(0, 0, 0, 0), occlusion.occlusionInTargetSurface().bounds());
2571         EXPECT_EQ(0u, occlusion.occlusionInTargetSurface().rects().size());
2572
2573         // The surface has a background blur, so it needs pixels that are currently considered occluded in order to be drawn. So the pixels
2574         // it needs should be removed some the occluded area so that when we get to the parent they are drawn.
2575         this->visitContributingSurface(filteredSurface, occlusion);
2576
2577         this->enterLayer(parent, occlusion);
2578         EXPECT_INT_RECT_EQ(IntRect(0, 0, 300, 150), occlusion.occlusionInScreenSpace().bounds());
2579         EXPECT_EQ(5u, occlusion.occlusionInScreenSpace().rects().size());
2580         EXPECT_INT_RECT_EQ(IntRect(0, 0, 300, 150), occlusion.occlusionInTargetSurface().bounds());
2581         EXPECT_EQ(5u, occlusion.occlusionInTargetSurface().rects().size());
2582
2583         IntRect outsetRect;
2584         IntRect testRect;
2585
2586         // Nothing in the blur outsets for the filteredSurface is occluded.
2587         outsetRect = IntRect(50 - outsetLeft, 50 - outsetTop, 50 + outsetLeft + outsetRight, 50 + outsetTop + outsetBottom);
2588         testRect = outsetRect;
2589         EXPECT_INT_RECT_EQ(outsetRect, occlusion.unoccludedContentRect(parent, testRect));
2590
2591         // Stuff outside the blur outsets is still occluded though.
2592         testRect = outsetRect;
2593         testRect.expand(1, 0);
2594         EXPECT_INT_RECT_EQ(outsetRect, occlusion.unoccludedContentRect(parent, testRect));
2595         testRect = outsetRect;
2596         testRect.expand(0, 1);
2597         EXPECT_INT_RECT_EQ(outsetRect, occlusion.unoccludedContentRect(parent, testRect));
2598         testRect = outsetRect;
2599         testRect.move(-1, 0);
2600         testRect.expand(1, 0);
2601         EXPECT_INT_RECT_EQ(outsetRect, occlusion.unoccludedContentRect(parent, testRect));
2602         testRect = outsetRect;
2603         testRect.move(0, -1);
2604         testRect.expand(0, 1);
2605         EXPECT_INT_RECT_EQ(outsetRect, occlusion.unoccludedContentRect(parent, testRect));
2606
2607         // Nothing in the blur outsets for the filteredSurface's replica is occluded.
2608         outsetRect = IntRect(200 - outsetLeft, 50 - outsetTop, 50 + outsetLeft + outsetRight, 50 + outsetTop + outsetBottom);
2609         testRect = outsetRect;
2610         EXPECT_INT_RECT_EQ(outsetRect, occlusion.unoccludedContentRect(parent, testRect));
2611
2612         // Stuff outside the blur outsets is still occluded though.
2613         testRect = outsetRect;
2614         testRect.expand(1, 0);
2615         EXPECT_INT_RECT_EQ(outsetRect, occlusion.unoccludedContentRect(parent, testRect));
2616         testRect = outsetRect;
2617         testRect.expand(0, 1);
2618         EXPECT_INT_RECT_EQ(outsetRect, occlusion.unoccludedContentRect(parent, testRect));
2619         testRect = outsetRect;
2620         testRect.move(-1, 0);
2621         testRect.expand(1, 0);
2622         EXPECT_INT_RECT_EQ(outsetRect, occlusion.unoccludedContentRect(parent, testRect));
2623         testRect = outsetRect;
2624         testRect.move(0, -1);
2625         testRect.expand(0, 1);
2626         EXPECT_INT_RECT_EQ(outsetRect, occlusion.unoccludedContentRect(parent, testRect));
2627     }
2628 };
2629
2630 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter);
2631
2632 template<class Types, bool opaqueLayers>
2633 class CCOcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice : public CCOcclusionTrackerTest<Types, opaqueLayers> {
2634 protected:
2635     void runMyTest()
2636     {
2637         WebTransformationMatrix scaleByHalf;
2638         scaleByHalf.scale(0.5);
2639
2640         // Makes two surfaces that completely cover |parent|. The occlusion both above and below the filters will be reduced by each of them.
2641         typename Types::ContentLayerType* root = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(75, 75));
2642         typename Types::LayerType* parent = this->createSurface(root, scaleByHalf, FloatPoint(0, 0), IntSize(150, 150));
2643         parent->setMasksToBounds(true);
2644         typename Types::LayerType* filteredSurface1 = this->createDrawingLayer(parent, scaleByHalf, FloatPoint(0, 0), IntSize(300, 300), false);
2645         typename Types::LayerType* filteredSurface2 = this->createDrawingLayer(parent, scaleByHalf, FloatPoint(0, 0), IntSize(300, 300), false);
2646         typename Types::LayerType* occludingLayerAbove = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(100, 100), IntSize(50, 50), true);
2647
2648         // Filters make the layers own surfaces.
2649         WebFilterOperations filters;
2650         filters.append(WebFilterOperation::createBlurFilter(3));
2651         filteredSurface1->setBackgroundFilters(filters);
2652         filteredSurface2->setBackgroundFilters(filters);
2653
2654         // Save the distance of influence for the blur effect.
2655         int outsetTop, outsetRight, outsetBottom, outsetLeft;
2656         filters.getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft);
2657
2658         this->calcDrawEtc(root);
2659
2660         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
2661         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
2662
2663         this->visitLayer(occludingLayerAbove, occlusion);
2664         EXPECT_INT_RECT_EQ(IntRect(100 / 2, 100 / 2, 50 / 2, 50 / 2), occlusion.occlusionInScreenSpace().bounds());
2665         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
2666         EXPECT_INT_RECT_EQ(IntRect(100, 100, 50, 50), occlusion.occlusionInTargetSurface().bounds());
2667         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
2668
2669         this->visitLayer(filteredSurface2, occlusion);
2670         this->visitContributingSurface(filteredSurface2, occlusion);
2671         this->visitLayer(filteredSurface1, occlusion);
2672         this->visitContributingSurface(filteredSurface1, occlusion);
2673
2674         ASSERT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
2675         ASSERT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
2676
2677         // Test expectations in the target.
2678         IntRect expectedOcclusion = IntRect(100 + outsetRight * 2, 100 + outsetBottom * 2, 50 - (outsetLeft + outsetRight) * 2, 50 - (outsetTop + outsetBottom) * 2);
2679         EXPECT_INT_RECT_EQ(expectedOcclusion, occlusion.occlusionInTargetSurface().rects()[0]);
2680
2681         // Test expectations in the screen. Take the ceiling of half of the outsets.
2682         outsetTop = (outsetTop + 1) / 2;
2683         outsetRight = (outsetRight + 1) / 2;
2684         outsetBottom = (outsetBottom + 1) / 2;
2685         outsetLeft = (outsetLeft + 1) / 2;
2686         expectedOcclusion = IntRect(100 / 2 + outsetRight * 2, 100 / 2 + outsetBottom * 2, 50 / 2 - (outsetLeft + outsetRight) * 2, 50 /2 - (outsetTop + outsetBottom) * 2);
2687
2688         EXPECT_INT_RECT_EQ(expectedOcclusion, occlusion.occlusionInScreenSpace().rects()[0]);
2689     }
2690 };
2691
2692 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice);
2693
2694 template<class Types, bool opaqueLayers>
2695 class CCOcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilterWithClip : public CCOcclusionTrackerTest<Types, opaqueLayers> {
2696 protected:
2697     void runMyTest()
2698     {
2699         // Make a surface and its replica, each 50x50, that are completely surrounded by opaque layers which are above them in the z-order.
2700         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 150));
2701         // We stick the filtered surface inside a clipping surface so that we can make sure the clip is honored when exposing pixels for
2702         // the background filter.
2703         typename Types::LayerType* clippingSurface = this->createSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 70));
2704         clippingSurface->setMasksToBounds(true);
2705         typename Types::LayerType* filteredSurface = this->createDrawingLayer(clippingSurface, this->identityMatrix, FloatPoint(50, 50), IntSize(50, 50), false);
2706         this->createReplicaLayer(filteredSurface, this->identityMatrix, FloatPoint(150, 0), IntSize());
2707         typename Types::LayerType* occludingLayer1 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 50), true);
2708         typename Types::LayerType* occludingLayer2 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 100), IntSize(300, 50), true);
2709         typename Types::LayerType* occludingLayer3 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 50), IntSize(50, 50), true);
2710         typename Types::LayerType* occludingLayer4 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(100, 50), IntSize(100, 50), true);
2711         typename Types::LayerType* occludingLayer5 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(250, 50), IntSize(50, 50), true);
2712
2713         // Filters make the layer own a surface. This filter is large enough that it goes outside the bottom of the clippingSurface.
2714         WebFilterOperations filters;
2715         filters.append(WebFilterOperation::createBlurFilter(12));
2716         filteredSurface->setBackgroundFilters(filters);
2717
2718         // Save the distance of influence for the blur effect.
2719         int outsetTop, outsetRight, outsetBottom, outsetLeft;
2720         filters.getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft);
2721
2722         this->calcDrawEtc(parent);
2723
2724         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
2725         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
2726
2727         // These layers occlude pixels directly beside the filteredSurface. Because filtered surface blends pixels in a radius, it will
2728         // need to see some of the pixels (up to radius far) underneath the occludingLayers.
2729         this->visitLayer(occludingLayer5, occlusion);
2730         this->visitLayer(occludingLayer4, occlusion);
2731         this->visitLayer(occludingLayer3, occlusion);
2732         this->visitLayer(occludingLayer2, occlusion);
2733         this->visitLayer(occludingLayer1, occlusion);
2734
2735         EXPECT_INT_RECT_EQ(IntRect(0, 0, 300, 150), occlusion.occlusionInScreenSpace().bounds());
2736         EXPECT_EQ(5u, occlusion.occlusionInScreenSpace().rects().size());
2737         EXPECT_INT_RECT_EQ(IntRect(0, 0, 300, 150), occlusion.occlusionInTargetSurface().bounds());
2738         EXPECT_EQ(5u, occlusion.occlusionInTargetSurface().rects().size());
2739
2740         // Everything outside the surface/replica is occluded but the surface/replica itself is not.
2741         this->enterLayer(filteredSurface, occlusion);
2742         EXPECT_INT_RECT_EQ(IntRect(1, 0, 49, 50), occlusion.unoccludedContentRect(filteredSurface, IntRect(1, 0, 50, 50)));
2743         EXPECT_INT_RECT_EQ(IntRect(0, 1, 50, 49), occlusion.unoccludedContentRect(filteredSurface, IntRect(0, 1, 50, 50)));
2744         EXPECT_INT_RECT_EQ(IntRect(0, 0, 49, 50), occlusion.unoccludedContentRect(filteredSurface, IntRect(-1, 0, 50, 50)));
2745         EXPECT_INT_RECT_EQ(IntRect(0, 0, 50, 49), occlusion.unoccludedContentRect(filteredSurface, IntRect(0, -1, 50, 50)));
2746
2747         EXPECT_INT_RECT_EQ(IntRect(150 + 1, 0, 49, 50), occlusion.unoccludedContentRect(filteredSurface, IntRect(150 + 1, 0, 50, 50)));
2748         EXPECT_INT_RECT_EQ(IntRect(150 + 0, 1, 50, 49), occlusion.unoccludedContentRect(filteredSurface, IntRect(150 + 0, 1, 50, 50)));
2749         EXPECT_INT_RECT_EQ(IntRect(150 + 0, 0, 49, 50), occlusion.unoccludedContentRect(filteredSurface, IntRect(150 - 1, 0, 50, 50)));
2750         EXPECT_INT_RECT_EQ(IntRect(150 + 0, 0, 50, 49), occlusion.unoccludedContentRect(filteredSurface, IntRect(150 + 0, -1, 50, 50)));
2751         this->leaveLayer(filteredSurface, occlusion);
2752
2753         // The filtered layer/replica does not occlude.
2754         EXPECT_INT_RECT_EQ(IntRect(0, 0, 300, 150), occlusion.occlusionInScreenSpace().bounds());
2755         EXPECT_EQ(5u, occlusion.occlusionInScreenSpace().rects().size());
2756         EXPECT_INT_RECT_EQ(IntRect(0, 0, 0, 0), occlusion.occlusionInTargetSurface().bounds());
2757         EXPECT_EQ(0u, occlusion.occlusionInTargetSurface().rects().size());
2758
2759         // The surface has a background blur, so it needs pixels that are currently considered occluded in order to be drawn. So the pixels
2760         // it needs should be removed some the occluded area so that when we get to the parent they are drawn.
2761         this->visitContributingSurface(filteredSurface, occlusion);
2762
2763         this->enterContributingSurface(clippingSurface, occlusion);
2764         EXPECT_INT_RECT_EQ(IntRect(0, 0, 300, 150), occlusion.occlusionInScreenSpace().bounds());
2765         EXPECT_EQ(5u, occlusion.occlusionInScreenSpace().rects().size());
2766
2767         IntRect outsetRect;
2768         IntRect clippedOutsetRect;
2769         IntRect testRect;
2770
2771         // Nothing in the (clipped) blur outsets for the filteredSurface is occluded.
2772         outsetRect = IntRect(50 - outsetLeft, 50 - outsetTop, 50 + outsetLeft + outsetRight, 50 + outsetTop + outsetBottom);
2773         clippedOutsetRect = intersection(outsetRect, IntRect(0 - outsetLeft, 0 - outsetTop, 300 + outsetLeft + outsetRight, 70 + outsetTop + outsetBottom));
2774         testRect = outsetRect;
2775         EXPECT_INT_RECT_EQ(clippedOutsetRect, occlusion.unoccludedContentRect(clippingSurface, testRect));
2776
2777         // Stuff outside the (clipped) blur outsets is still occluded though.
2778         testRect = outsetRect;
2779         testRect.expand(1, 0);
2780         EXPECT_INT_RECT_EQ(clippedOutsetRect, occlusion.unoccludedContentRect(clippingSurface, testRect));
2781         testRect = outsetRect;
2782         testRect.expand(0, 1);
2783         EXPECT_INT_RECT_EQ(clippedOutsetRect, occlusion.unoccludedContentRect(clippingSurface, testRect));
2784         testRect = outsetRect;
2785         testRect.move(-1, 0);
2786         testRect.expand(1, 0);
2787         EXPECT_INT_RECT_EQ(clippedOutsetRect, occlusion.unoccludedContentRect(clippingSurface, testRect));
2788         testRect = outsetRect;
2789         testRect.move(0, -1);
2790         testRect.expand(0, 1);
2791         EXPECT_INT_RECT_EQ(clippedOutsetRect, occlusion.unoccludedContentRect(clippingSurface, testRect));
2792
2793         // Nothing in the (clipped) blur outsets for the filteredSurface's replica is occluded.
2794         outsetRect = IntRect(200 - outsetLeft, 50 - outsetTop, 50 + outsetLeft + outsetRight, 50 + outsetTop + outsetBottom);
2795         clippedOutsetRect = intersection(outsetRect, IntRect(0 - outsetLeft, 0 - outsetTop, 300 + outsetLeft + outsetRight, 70 + outsetTop + outsetBottom));
2796         testRect = outsetRect;
2797         EXPECT_INT_RECT_EQ(clippedOutsetRect, occlusion.unoccludedContentRect(clippingSurface, testRect));
2798
2799         // Stuff outside the (clipped) blur outsets is still occluded though.
2800         testRect = outsetRect;
2801         testRect.expand(1, 0);
2802         EXPECT_INT_RECT_EQ(clippedOutsetRect, occlusion.unoccludedContentRect(clippingSurface, testRect));
2803         testRect = outsetRect;
2804         testRect.expand(0, 1);
2805         EXPECT_INT_RECT_EQ(clippedOutsetRect, occlusion.unoccludedContentRect(clippingSurface, testRect));
2806         testRect = outsetRect;
2807         testRect.move(-1, 0);
2808         testRect.expand(1, 0);
2809         EXPECT_INT_RECT_EQ(clippedOutsetRect, occlusion.unoccludedContentRect(clippingSurface, testRect));
2810         testRect = outsetRect;
2811         testRect.move(0, -1);
2812         testRect.expand(0, 1);
2813         EXPECT_INT_RECT_EQ(clippedOutsetRect, occlusion.unoccludedContentRect(clippingSurface, testRect));
2814     }
2815 };
2816
2817 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilterWithClip);
2818
2819 template<class Types, bool opaqueLayers>
2820 class CCOcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter : public CCOcclusionTrackerTest<Types, opaqueLayers> {
2821 protected:
2822     void runMyTest()
2823     {
2824         WebTransformationMatrix scaleByHalf;
2825         scaleByHalf.scale(0.5);
2826
2827         // Make a surface and its replica, each 50x50, with a smaller 30x30 layer centered below each.
2828         // The surface is scaled to test that the pixel moving is done in the target space, where the background filter is applied, but the surface
2829         // appears at 50, 50 and the replica at 200, 50.
2830         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 150));
2831         typename Types::LayerType* behindSurfaceLayer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(60, 60), IntSize(30, 30), true);
2832         typename Types::LayerType* behindReplicaLayer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(210, 60), IntSize(30, 30), true);
2833         typename Types::LayerType* filteredSurface = this->createDrawingLayer(parent, scaleByHalf, FloatPoint(50, 50), IntSize(100, 100), false);
2834         this->createReplicaLayer(filteredSurface, this->identityMatrix, FloatPoint(300, 0), IntSize());
2835
2836         // Filters make the layer own a surface.
2837         WebFilterOperations filters;
2838         filters.append(WebFilterOperation::createBlurFilter(3));
2839         filteredSurface->setBackgroundFilters(filters);
2840
2841         this->calcDrawEtc(parent);
2842
2843         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
2844         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
2845
2846         // The surface has a background blur, so it blurs non-opaque pixels below it.
2847         this->visitLayer(filteredSurface, occlusion);
2848         this->visitContributingSurface(filteredSurface, occlusion);
2849
2850         this->visitLayer(behindReplicaLayer, occlusion);
2851         this->visitLayer(behindSurfaceLayer, occlusion);
2852
2853         // The layers behind the surface are not blurred, and their occlusion does not change, until we leave the surface.
2854         // So it should not be modified by the filter here.
2855         IntRect occlusionBehindSurface = IntRect(60, 60, 30, 30);
2856         IntRect occlusionBehindReplica = IntRect(210, 60, 30, 30);
2857
2858         IntRect expectedOpaqueBounds = unionRect(occlusionBehindSurface, occlusionBehindReplica);
2859         EXPECT_INT_RECT_EQ(expectedOpaqueBounds, occlusion.occlusionInScreenSpace().bounds());
2860         EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
2861         EXPECT_INT_RECT_EQ(expectedOpaqueBounds, occlusion.occlusionInTargetSurface().bounds());
2862         EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
2863     }
2864 };
2865
2866 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter);
2867
2868 template<class Types, bool opaqueLayers>
2869 class CCOcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded : public CCOcclusionTrackerTest<Types, opaqueLayers> {
2870 protected:
2871     void runMyTest()
2872     {
2873         WebTransformationMatrix scaleByHalf;
2874         scaleByHalf.scale(0.5);
2875
2876         // Make a surface and its replica, each 50x50, that are completely occluded by opaque layers which are above them in the z-order.
2877         // The surface is scaled to test that the pixel moving is done in the target space, where the background filter is applied, but the surface
2878         // appears at 50, 50 and the replica at 200, 50.
2879         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 150));
2880         typename Types::LayerType* filteredSurface = this->createDrawingLayer(parent, scaleByHalf, FloatPoint(50, 50), IntSize(100, 100), false);
2881         this->createReplicaLayer(filteredSurface, this->identityMatrix, FloatPoint(300, 0), IntSize());
2882         typename Types::LayerType* aboveSurfaceLayer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(50, 50), IntSize(50, 50), true);
2883         typename Types::LayerType* aboveReplicaLayer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(200, 50), IntSize(50, 50), true);
2884
2885         // Filters make the layer own a surface.
2886         WebFilterOperations filters;
2887         filters.append(WebFilterOperation::createBlurFilter(3));
2888         filteredSurface->setBackgroundFilters(filters);
2889
2890         this->calcDrawEtc(parent);
2891
2892         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
2893         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
2894
2895         this->visitLayer(aboveReplicaLayer, occlusion);
2896         this->visitLayer(aboveSurfaceLayer, occlusion);
2897
2898         // The surface has a background blur, so it blurs non-opaque pixels below it.
2899         this->visitLayer(filteredSurface, occlusion);
2900         this->visitContributingSurface(filteredSurface, occlusion);
2901
2902         // The filter is completely occluded, so it should not blur anything and reduce any occlusion.
2903         IntRect occlusionAboveSurface = IntRect(50, 50, 50, 50);
2904         IntRect occlusionAboveReplica = IntRect(200, 50, 50, 50);
2905
2906         IntRect expectedOpaqueBounds = unionRect(occlusionAboveSurface, occlusionAboveReplica);
2907         EXPECT_INT_RECT_EQ(expectedOpaqueBounds, occlusion.occlusionInScreenSpace().bounds());
2908         EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
2909         EXPECT_INT_RECT_EQ(expectedOpaqueBounds, occlusion.occlusionInTargetSurface().bounds());
2910         EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
2911     }
2912 };
2913
2914 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded);
2915
2916 template<class Types, bool opaqueLayers>
2917 class CCOcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded : public CCOcclusionTrackerTest<Types, opaqueLayers> {
2918 protected:
2919     void runMyTest()
2920     {
2921         WebTransformationMatrix scaleByHalf;
2922         scaleByHalf.scale(0.5);
2923
2924         // Make a surface and its replica, each 50x50, that are partially occluded by opaque layers which are above them in the z-order.
2925         // The surface is scaled to test that the pixel moving is done in the target space, where the background filter is applied, but the surface
2926         // appears at 50, 50 and the replica at 200, 50.
2927         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 150));
2928         typename Types::LayerType* filteredSurface = this->createDrawingLayer(parent, scaleByHalf, FloatPoint(50, 50), IntSize(100, 100), false);
2929         this->createReplicaLayer(filteredSurface, this->identityMatrix, FloatPoint(300, 0), IntSize());
2930         typename Types::LayerType* aboveSurfaceLayer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(70, 50), IntSize(30, 50), true);
2931         typename Types::LayerType* aboveReplicaLayer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(200, 50), IntSize(30, 50), true);
2932         typename Types::LayerType* besideSurfaceLayer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(90, 40), IntSize(10, 10), true);
2933         typename Types::LayerType* besideReplicaLayer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(200, 40), IntSize(10, 10), true);
2934
2935         // Filters make the layer own a surface.
2936         WebFilterOperations filters;
2937         filters.append(WebFilterOperation::createBlurFilter(3));
2938         filteredSurface->setBackgroundFilters(filters);
2939
2940         // Save the distance of influence for the blur effect.
2941         int outsetTop, outsetRight, outsetBottom, outsetLeft;
2942         filters.getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft);
2943
2944         this->calcDrawEtc(parent);
2945
2946         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
2947         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
2948
2949         this->visitLayer(besideReplicaLayer, occlusion);
2950         this->visitLayer(besideSurfaceLayer, occlusion);
2951         this->visitLayer(aboveReplicaLayer, occlusion);
2952         this->visitLayer(aboveSurfaceLayer, occlusion);
2953
2954         // The surface has a background blur, so it blurs non-opaque pixels below it.
2955         this->visitLayer(filteredSurface, occlusion);
2956         this->visitContributingSurface(filteredSurface, occlusion);
2957
2958         // The filter in the surface and replica are partially unoccluded. Only the unoccluded parts should reduce occlusion.
2959         // This means it will push back the occlusion that touches the unoccluded part (occlusionAbove___), but it will not
2960         // touch occlusionBeside____ since that is not beside the unoccluded part of the surface, even though it is beside
2961         // the occluded part of the surface.
2962         IntRect occlusionAboveSurface = IntRect(70 + outsetRight, 50, 30 - outsetRight, 50);
2963         IntRect occlusionAboveReplica = IntRect(200, 50, 30 - outsetLeft, 50);
2964         IntRect occlusionBesideSurface = IntRect(90, 40, 10, 10);
2965         IntRect occlusionBesideReplica = IntRect(200, 40, 10, 10);
2966
2967         Region expectedOcclusion;
2968         expectedOcclusion.unite(occlusionAboveSurface);
2969         expectedOcclusion.unite(occlusionAboveReplica);
2970         expectedOcclusion.unite(occlusionBesideSurface);
2971         expectedOcclusion.unite(occlusionBesideReplica);
2972
2973         ASSERT_EQ(expectedOcclusion.rects().size(), occlusion.occlusionInTargetSurface().rects().size());
2974         ASSERT_EQ(expectedOcclusion.rects().size(), occlusion.occlusionInScreenSpace().rects().size());
2975
2976         for (size_t i = 0; i < expectedOcclusion.rects().size(); ++i) {
2977             IntRect expectedRect = expectedOcclusion.rects()[i];
2978             IntRect screenRect = occlusion.occlusionInScreenSpace().rects()[i];
2979             IntRect targetRect = occlusion.occlusionInTargetSurface().rects()[i];
2980             EXPECT_EQ(expectedRect, screenRect);
2981             EXPECT_EQ(expectedRect, targetRect);
2982         }
2983     }
2984 };
2985
2986 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded);
2987
2988 template<class Types, bool opaqueLayers>
2989 class CCOcclusionTrackerTestMinimumTrackingSize : public CCOcclusionTrackerTest<Types, opaqueLayers> {
2990 protected:
2991     void runMyTest()
2992     {
2993         IntSize trackingSize(100, 100);
2994         IntSize belowTrackingSize(99, 99);
2995
2996         typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(400, 400));
2997         typename Types::LayerType* large = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), trackingSize, true);
2998         typename Types::LayerType* small = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), belowTrackingSize, true);
2999         this->calcDrawEtc(parent);
3000
3001         TestCCOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
3002         occlusion.setLayerClipRect(IntRect(0, 0, 1000, 1000));
3003         occlusion.setMinimumTrackingSize(trackingSize);
3004
3005         // The small layer is not tracked because it is too small.
3006         this->visitLayer(small, occlusion);
3007
3008         EXPECT_INT_RECT_EQ(IntRect(), occlusion.occlusionInScreenSpace().bounds());
3009         EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size());
3010         EXPECT_INT_RECT_EQ(IntRect(), occlusion.occlusionInTargetSurface().bounds());
3011         EXPECT_EQ(0u, occlusion.occlusionInTargetSurface().rects().size());
3012
3013         // The large layer is tracked as it is large enough.
3014         this->visitLayer(large, occlusion);
3015
3016         EXPECT_INT_RECT_EQ(IntRect(IntPoint(), trackingSize), occlusion.occlusionInScreenSpace().bounds());
3017         EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
3018         EXPECT_INT_RECT_EQ(IntRect(IntPoint(), trackingSize), occlusion.occlusionInTargetSurface().bounds());
3019         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
3020     }
3021 };
3022
3023 ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestMinimumTrackingSize);
3024
3025 } // namespace