[chromium] Clean up culling tests and templatize to test impl constructs
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 11 Mar 2012 02:37:37 +0000 (02:37 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 11 Mar 2012 02:37:37 +0000 (02:37 +0000)
https://bugs.webkit.org/show_bug.cgi?id=80613

Patch by Dana Jansens <danakj@chromium.org> on 2012-03-10
Reviewed by Adrienne Walker.

* tests/CCOcclusionTrackerTest.cpp:
(WebCore::TestContentLayerChromium::TestContentLayerChromium):
(WebCore::TestContentLayerChromium::opaqueContentsRegion):
(WebCore::TestContentLayerChromium::setOpaqueContentsRect):
(TestContentLayerChromium):
(TestContentLayerImpl):
(WebCore::TestContentLayerImpl::TestContentLayerImpl):
(WebCore::TestContentLayerImpl::opaqueContentsRegion):
(WebCore::TestContentLayerImpl::setOpaqueContentsRect):
(WebCore):
(WebCore::TestCCOcclusionTrackerBase::TestCCOcclusionTrackerBase):
(WebCore::TestCCOcclusionTrackerBase::occlusionInScreenSpace):
(WebCore::TestCCOcclusionTrackerBase::occlusionInTargetSurface):
(WebCore::TestCCOcclusionTrackerBase::setOcclusionInScreenSpace):
(WebCore::TestCCOcclusionTrackerBase::setOcclusionInTargetSurface):
(WebCore::TestCCOcclusionTrackerBase::layerScissorRectInTargetSurface):
(WebCore::TestDamageClient::damageRect):
(CCOcclusionTrackerTestMainThreadTypes):
(WebCore::CCOcclusionTrackerTestMainThreadTypes::createLayer):
(WebCore::CCOcclusionTrackerTestMainThreadTypes::createContentLayer):
(CCOcclusionTrackerTestImplThreadTypes):
(WebCore::CCOcclusionTrackerTestImplThreadTypes::createLayer):
(WebCore::CCOcclusionTrackerTestImplThreadTypes::createContentLayer):
(CCOcclusionTrackerTest):
(WebCore::CCOcclusionTrackerTest::TearDown):
(WebCore::CCOcclusionTrackerTest::createRoot):
(WebCore::CCOcclusionTrackerTest::createLayer):
(WebCore::CCOcclusionTrackerTest::createSurface):
(WebCore::CCOcclusionTrackerTest::createDrawingLayer):
(WebCore::CCOcclusionTrackerTest::createDrawingSurface):
(WebCore::CCOcclusionTrackerTest::calcDrawEtc):
(WebCore::CCOcclusionTrackerTest::setBaseProperties):
(WebCore::CCOcclusionTrackerTest::setProperties):
(CCOcclusionTrackerTestIdentityTransforms):
(WebCore::CCOcclusionTrackerTestIdentityTransforms::runMyTest):
(CCOcclusionTrackerTestRotatedChild):
(WebCore::CCOcclusionTrackerTestRotatedChild::runMyTest):
(CCOcclusionTrackerTestTranslatedChild):
(WebCore::CCOcclusionTrackerTestTranslatedChild::runMyTest):
(CCOcclusionTrackerTestChildInRotatedChild):
(WebCore::CCOcclusionTrackerTestChildInRotatedChild::runMyTest):
(CCOcclusionTrackerTestVisitTargetTwoTimes):
(WebCore::CCOcclusionTrackerTestVisitTargetTwoTimes::runMyTest):
(CCOcclusionTrackerTestSurfaceRotatedOffAxis):
(WebCore::CCOcclusionTrackerTestSurfaceRotatedOffAxis::runMyTest):
(CCOcclusionTrackerTestSurfaceWithTwoOpaqueChildren):
(WebCore::CCOcclusionTrackerTestSurfaceWithTwoOpaqueChildren::runMyTest):
(CCOcclusionTrackerTestOverlappingSurfaceSiblings):
(WebCore::CCOcclusionTrackerTestOverlappingSurfaceSiblings::runMyTest):
(CCOcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms):
(WebCore::CCOcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms::runMyTest):
(CCOcclusionTrackerTestFilters):
(WebCore::CCOcclusionTrackerTestFilters::runMyTest):
(CCOcclusionTrackerTestLayerScissorRectOutsideChild):
(WebCore::CCOcclusionTrackerTestLayerScissorRectOutsideChild::runMyTest):
(CCOcclusionTrackerTestScreenScissorRectOutsideChild):
(WebCore::CCOcclusionTrackerTestScreenScissorRectOutsideChild::runMyTest):
(CCOcclusionTrackerTestDamageRectOutsideChild):
(WebCore::CCOcclusionTrackerTestDamageRectOutsideChild::runMyTest):
(CCOcclusionTrackerTestLayerScissorRectOverChild):
(WebCore::CCOcclusionTrackerTestLayerScissorRectOverChild::runMyTest):
(CCOcclusionTrackerTestScreenScissorRectOverChild):
(WebCore::CCOcclusionTrackerTestScreenScissorRectOverChild::runMyTest):
(CCOcclusionTrackerTestDamageRectOverChild):
(WebCore::CCOcclusionTrackerTestDamageRectOverChild::runMyTest):
(CCOcclusionTrackerTestLayerScissorRectPartlyOverChild):
(WebCore::CCOcclusionTrackerTestLayerScissorRectPartlyOverChild::runMyTest):
(CCOcclusionTrackerTestScreenScissorRectPartlyOverChild):
(WebCore::CCOcclusionTrackerTestScreenScissorRectPartlyOverChild::runMyTest):
(CCOcclusionTrackerTestDamageRectPartlyOverChild):
(WebCore::CCOcclusionTrackerTestDamageRectPartlyOverChild::runMyTest):
(CCOcclusionTrackerTestLayerScissorRectOverNothing):
(WebCore::CCOcclusionTrackerTestLayerScissorRectOverNothing::runMyTest):
(CCOcclusionTrackerTestScreenScissorRectOverNothing):
(WebCore::CCOcclusionTrackerTestScreenScissorRectOverNothing::runMyTest):
(CCOcclusionTrackerTestDamageRectOverNothing):
(WebCore::CCOcclusionTrackerTestDamageRectOverNothing::runMyTest):
(CCOcclusionTrackerTestLayerScissorRectForLayerOffOrigin):
(WebCore::CCOcclusionTrackerTestLayerScissorRectForLayerOffOrigin::runMyTest):
(CCOcclusionTrackerTestOpaqueContentsRegionEmpty):
(WebCore::CCOcclusionTrackerTestOpaqueContentsRegionEmpty::runMyTest):
(CCOcclusionTrackerTestOpaqueContentsRegionNonEmpty):
(WebCore::CCOcclusionTrackerTestOpaqueContentsRegionNonEmpty::runMyTest):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@110384 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/tests/CCOcclusionTrackerTest.cpp

index 275f1e1..d108026 100644 (file)
@@ -1,3 +1,94 @@
+2012-03-10  Dana Jansens  <danakj@chromium.org>
+
+        [chromium] Clean up culling tests and templatize to test impl constructs
+        https://bugs.webkit.org/show_bug.cgi?id=80613
+
+        Reviewed by Adrienne Walker.
+
+        * tests/CCOcclusionTrackerTest.cpp:
+        (WebCore::TestContentLayerChromium::TestContentLayerChromium):
+        (WebCore::TestContentLayerChromium::opaqueContentsRegion):
+        (WebCore::TestContentLayerChromium::setOpaqueContentsRect):
+        (TestContentLayerChromium):
+        (TestContentLayerImpl):
+        (WebCore::TestContentLayerImpl::TestContentLayerImpl):
+        (WebCore::TestContentLayerImpl::opaqueContentsRegion):
+        (WebCore::TestContentLayerImpl::setOpaqueContentsRect):
+        (WebCore):
+        (WebCore::TestCCOcclusionTrackerBase::TestCCOcclusionTrackerBase):
+        (WebCore::TestCCOcclusionTrackerBase::occlusionInScreenSpace):
+        (WebCore::TestCCOcclusionTrackerBase::occlusionInTargetSurface):
+        (WebCore::TestCCOcclusionTrackerBase::setOcclusionInScreenSpace):
+        (WebCore::TestCCOcclusionTrackerBase::setOcclusionInTargetSurface):
+        (WebCore::TestCCOcclusionTrackerBase::layerScissorRectInTargetSurface):
+        (WebCore::TestDamageClient::damageRect):
+        (CCOcclusionTrackerTestMainThreadTypes):
+        (WebCore::CCOcclusionTrackerTestMainThreadTypes::createLayer):
+        (WebCore::CCOcclusionTrackerTestMainThreadTypes::createContentLayer):
+        (CCOcclusionTrackerTestImplThreadTypes):
+        (WebCore::CCOcclusionTrackerTestImplThreadTypes::createLayer):
+        (WebCore::CCOcclusionTrackerTestImplThreadTypes::createContentLayer):
+        (CCOcclusionTrackerTest):
+        (WebCore::CCOcclusionTrackerTest::TearDown):
+        (WebCore::CCOcclusionTrackerTest::createRoot):
+        (WebCore::CCOcclusionTrackerTest::createLayer):
+        (WebCore::CCOcclusionTrackerTest::createSurface):
+        (WebCore::CCOcclusionTrackerTest::createDrawingLayer):
+        (WebCore::CCOcclusionTrackerTest::createDrawingSurface):
+        (WebCore::CCOcclusionTrackerTest::calcDrawEtc):
+        (WebCore::CCOcclusionTrackerTest::setBaseProperties):
+        (WebCore::CCOcclusionTrackerTest::setProperties):
+        (CCOcclusionTrackerTestIdentityTransforms):
+        (WebCore::CCOcclusionTrackerTestIdentityTransforms::runMyTest):
+        (CCOcclusionTrackerTestRotatedChild):
+        (WebCore::CCOcclusionTrackerTestRotatedChild::runMyTest):
+        (CCOcclusionTrackerTestTranslatedChild):
+        (WebCore::CCOcclusionTrackerTestTranslatedChild::runMyTest):
+        (CCOcclusionTrackerTestChildInRotatedChild):
+        (WebCore::CCOcclusionTrackerTestChildInRotatedChild::runMyTest):
+        (CCOcclusionTrackerTestVisitTargetTwoTimes):
+        (WebCore::CCOcclusionTrackerTestVisitTargetTwoTimes::runMyTest):
+        (CCOcclusionTrackerTestSurfaceRotatedOffAxis):
+        (WebCore::CCOcclusionTrackerTestSurfaceRotatedOffAxis::runMyTest):
+        (CCOcclusionTrackerTestSurfaceWithTwoOpaqueChildren):
+        (WebCore::CCOcclusionTrackerTestSurfaceWithTwoOpaqueChildren::runMyTest):
+        (CCOcclusionTrackerTestOverlappingSurfaceSiblings):
+        (WebCore::CCOcclusionTrackerTestOverlappingSurfaceSiblings::runMyTest):
+        (CCOcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms):
+        (WebCore::CCOcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms::runMyTest):
+        (CCOcclusionTrackerTestFilters):
+        (WebCore::CCOcclusionTrackerTestFilters::runMyTest):
+        (CCOcclusionTrackerTestLayerScissorRectOutsideChild):
+        (WebCore::CCOcclusionTrackerTestLayerScissorRectOutsideChild::runMyTest):
+        (CCOcclusionTrackerTestScreenScissorRectOutsideChild):
+        (WebCore::CCOcclusionTrackerTestScreenScissorRectOutsideChild::runMyTest):
+        (CCOcclusionTrackerTestDamageRectOutsideChild):
+        (WebCore::CCOcclusionTrackerTestDamageRectOutsideChild::runMyTest):
+        (CCOcclusionTrackerTestLayerScissorRectOverChild):
+        (WebCore::CCOcclusionTrackerTestLayerScissorRectOverChild::runMyTest):
+        (CCOcclusionTrackerTestScreenScissorRectOverChild):
+        (WebCore::CCOcclusionTrackerTestScreenScissorRectOverChild::runMyTest):
+        (CCOcclusionTrackerTestDamageRectOverChild):
+        (WebCore::CCOcclusionTrackerTestDamageRectOverChild::runMyTest):
+        (CCOcclusionTrackerTestLayerScissorRectPartlyOverChild):
+        (WebCore::CCOcclusionTrackerTestLayerScissorRectPartlyOverChild::runMyTest):
+        (CCOcclusionTrackerTestScreenScissorRectPartlyOverChild):
+        (WebCore::CCOcclusionTrackerTestScreenScissorRectPartlyOverChild::runMyTest):
+        (CCOcclusionTrackerTestDamageRectPartlyOverChild):
+        (WebCore::CCOcclusionTrackerTestDamageRectPartlyOverChild::runMyTest):
+        (CCOcclusionTrackerTestLayerScissorRectOverNothing):
+        (WebCore::CCOcclusionTrackerTestLayerScissorRectOverNothing::runMyTest):
+        (CCOcclusionTrackerTestScreenScissorRectOverNothing):
+        (WebCore::CCOcclusionTrackerTestScreenScissorRectOverNothing::runMyTest):
+        (CCOcclusionTrackerTestDamageRectOverNothing):
+        (WebCore::CCOcclusionTrackerTestDamageRectOverNothing::runMyTest):
+        (CCOcclusionTrackerTestLayerScissorRectForLayerOffOrigin):
+        (WebCore::CCOcclusionTrackerTestLayerScissorRectForLayerOffOrigin::runMyTest):
+        (CCOcclusionTrackerTestOpaqueContentsRegionEmpty):
+        (WebCore::CCOcclusionTrackerTestOpaqueContentsRegionEmpty::runMyTest):
+        (CCOcclusionTrackerTestOpaqueContentsRegionNonEmpty):
+        (WebCore::CCOcclusionTrackerTestOpaqueContentsRegionNonEmpty::runMyTest):
+
 2012-03-09  Jon Lee  <jonlee@apple.com>
 
         Rename NotificationPresenter to NotificationClient
index 26d5252..bd84c8d 100644 (file)
@@ -30,7 +30,9 @@
 #include "LayerChromium.h"
 #include "Region.h"
 #include "TransformationMatrix.h"
+#include "cc/CCLayerImpl.h"
 #include "cc/CCLayerTreeHostCommon.h"
+#include "cc/CCSingleThreadProxy.h"
 
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
@@ -45,84 +47,66 @@ using namespace WebCore;
 
 namespace {
 
-class LayerChromiumWithForcedDrawsContent : public LayerChromium {
+class TestContentLayerChromium : public LayerChromium {
 public:
-    LayerChromiumWithForcedDrawsContent()
-        : LayerChromium()
-    {
-    }
+    TestContentLayerChromium() : LayerChromium() { }
 
     virtual bool drawsContent() const { return true; }
-    virtual Region opaqueContentsRegion() const
-    {
-        return intersection(m_opaquePaintRect, visibleLayerRect());
-    }
-
-    void setOpaquePaintRect(const IntRect& opaquePaintRect) { m_opaquePaintRect = opaquePaintRect; }
+    virtual Region opaqueContentsRegion() const { return intersection(m_opaqueContentsRect, visibleLayerRect()); }
+    void setOpaqueContentsRect(const IntRect& opaqueContentsRect) { m_opaqueContentsRect = opaqueContentsRect; }
 
 private:
-    IntRect m_opaquePaintRect;
+    IntRect m_opaqueContentsRect;
 };
 
-void setLayerPropertiesForTesting(LayerChromium* layer, const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
-{
-    layer->setTransform(transform);
-    layer->setSublayerTransform(TransformationMatrix());
-    layer->setAnchorPoint(FloatPoint(0, 0));
-    layer->setPosition(position);
-    layer->setBounds(bounds);
-}
-
-void setLayerPropertiesForTesting(LayerChromiumWithForcedDrawsContent* layer, const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds, bool opaque, bool opaqueLayers)
-{
-    setLayerPropertiesForTesting(layer, transform, position, bounds);
-    if (opaqueLayers)
-        layer->setOpaque(opaque);
-    else {
-        layer->setOpaque(false);
-        if (opaque)
-            layer->setOpaquePaintRect(IntRect(IntPoint(), bounds));
-        else
-            layer->setOpaquePaintRect(IntRect());
-    }
-}
+class TestContentLayerImpl : public CCLayerImpl {
+public:
+    TestContentLayerImpl(int id) : CCLayerImpl(id) { setDrawsContent(true); }
+
+    virtual Region opaqueContentsRegion() const { return intersection(m_opaqueContentsRect, visibleLayerRect()); }
+    void setOpaqueContentsRect(const IntRect& opaqueContentsRect) { m_opaqueContentsRect = opaqueContentsRect; }
+private:
+    IntRect m_opaqueContentsRect;
+};
 
 // A subclass to expose the total current occlusion.
-class TestCCOcclusionTracker : public CCOcclusionTracker {
+template<typename LayerType, typename RenderSurfaceType>
+class TestCCOcclusionTrackerBase : public CCOcclusionTrackerBase<LayerType, RenderSurfaceType> {
 public:
-    TestCCOcclusionTracker(IntRect screenScissorRect)
-        : CCOcclusionTracker(screenScissorRect)
+    TestCCOcclusionTrackerBase(IntRect screenScissorRect)
+        : CCOcclusionTrackerBase<LayerType, RenderSurfaceType>(screenScissorRect)
         , m_overrideLayerScissorRect(false)
     {
     }
 
-    TestCCOcclusionTracker(IntRect screenScissorRect, const CCOcclusionTrackerDamageClient* damageClient)
-        : CCOcclusionTracker(screenScissorRect, damageClient)
+    TestCCOcclusionTrackerBase(IntRect screenScissorRect, const CCOcclusionTrackerDamageClientBase<RenderSurfaceType>* damageClient)
+        : CCOcclusionTrackerBase<LayerType, RenderSurfaceType>(screenScissorRect, damageClient)
         , m_overrideLayerScissorRect(false)
     {
     }
 
-    Region occlusionInScreenSpace() const { return CCOcclusionTracker::m_stack.last().occlusionInScreen; }
-    Region occlusionInTargetSurface() const { return CCOcclusionTracker::m_stack.last().occlusionInTarget; }
+    Region occlusionInScreenSpace() const { return CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::m_stack.last().occlusionInScreen; }
+    Region occlusionInTargetSurface() const { return CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::m_stack.last().occlusionInTarget; }
 
-    void setOcclusionInScreenSpace(const Region& region) { CCOcclusionTracker::m_stack.last().occlusionInScreen = region; }
-    void setOcclusionInTargetSurface(const Region& region) { CCOcclusionTracker::m_stack.last().occlusionInTarget = region; }
+    void setOcclusionInScreenSpace(const Region& region) { CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::m_stack.last().occlusionInScreen = region; }
+    void setOcclusionInTargetSurface(const Region& region) { CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::m_stack.last().occlusionInTarget = region; }
 
     void setLayerScissorRect(const IntRect& rect) { m_overrideLayerScissorRect = true; m_layerScissorRect = rect;}
     void useDefaultLayerScissorRect() { m_overrideLayerScissorRect = false; }
 
 protected:
-    virtual IntRect layerScissorRectInTargetSurface(const LayerChromium* layer) const { return m_overrideLayerScissorRect ? m_layerScissorRect : CCOcclusionTracker::layerScissorRectInTargetSurface(layer); }
+    virtual IntRect layerScissorRectInTargetSurface(const LayerType* layer) const { return m_overrideLayerScissorRect ? m_layerScissorRect : CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::layerScissorRectInTargetSurface(layer); }
 
 private:
     bool m_overrideLayerScissorRect;
     IntRect m_layerScissorRect;
 };
 
-class TestDamageClient : public CCOcclusionTrackerDamageClient {
+template<typename RenderSurfaceType>
+class TestDamageClient : public CCOcclusionTrackerDamageClientBase<RenderSurfaceType> {
 public:
     // The interface
-    virtual FloatRect damageRect(const RenderSurfaceChromium*) const { return m_damageRect; }
+    virtual FloatRect damageRect(const RenderSurfaceType*) const { return m_damageRect; }
 
     // Testing stuff
     TestDamageClient(const FloatRect& damageRect) : m_damageRect(damageRect) { }
@@ -132,2081 +116,1588 @@ private:
     FloatRect m_damageRect;
 };
 
-#define TEST_OPAQUE_AND_PAINTED_OPAQUE(FULLTESTNAME, SHORTTESTNAME) \
-    TEST(FULLTESTNAME, opaqueLayer)                                 \
-    {                                                               \
-        SHORTTESTNAME(true);                                        \
-    }                                                               \
-    TEST(FULLTESTNAME, opaquePaintRect)                             \
-    {                                                               \
-        SHORTTESTNAME(false);                                       \
+struct CCOcclusionTrackerTestMainThreadTypes {
+    typedef LayerChromium LayerType;
+    typedef RenderSurfaceChromium RenderSurfaceType;
+    typedef TestContentLayerChromium ContentLayerType;
+    typedef RefPtr<LayerChromium> LayerPtrType;
+    typedef PassRefPtr<LayerChromium> PassLayerPtrType;
+    typedef RefPtr<ContentLayerType> ContentLayerPtrType;
+    typedef PassRefPtr<ContentLayerType> PassContentLayerPtrType;
+
+    static PassLayerPtrType createLayer() { return LayerChromium::create(); }
+    static PassContentLayerPtrType createContentLayer() { return adoptRef(new ContentLayerType()); }
+};
+
+struct CCOcclusionTrackerTestImplThreadTypes {
+    typedef CCLayerImpl LayerType;
+    typedef CCRenderSurface RenderSurfaceType;
+    typedef TestContentLayerImpl ContentLayerType;
+    typedef OwnPtr<CCLayerImpl> LayerPtrType;
+    typedef PassOwnPtr<CCLayerImpl> PassLayerPtrType;
+    typedef OwnPtr<ContentLayerType> ContentLayerPtrType;
+    typedef PassOwnPtr<ContentLayerType> PassContentLayerPtrType;
+
+    static PassLayerPtrType createLayer() { return CCLayerImpl::create(nextCCLayerImplId++); }
+    static PassContentLayerPtrType createContentLayer() { return adoptPtr(new ContentLayerType(nextCCLayerImplId++)); }
+    static int nextCCLayerImplId;
+};
+
+int CCOcclusionTrackerTestImplThreadTypes::nextCCLayerImplId = 0;
+
+template<typename Types, bool opaqueLayers>
+class CCOcclusionTrackerTest : public testing::Test {
+protected:
+    virtual void runMyTest() = 0;
+
+    virtual void TearDown()
+    {
+        m_root.clear();
+        m_renderSurfaceLayerListChromium.clear();
+        m_renderSurfaceLayerListImpl.clear();
     }
 
-void layerAddedToOccludedRegion(bool opaqueLayers)
-{
-    // This tests that the right transforms are being used.
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(layer);
-
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
-    setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(30, 30), IntSize(500, 500), true, opaqueLayers);
-
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
-
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
-
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
-    TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
-    occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
-    occlusion.enterTargetRenderSurface(parent->renderSurface());
-    occlusion.markOccludedBehindLayer(layer.get());
-    EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 30, 70, 70)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 30, 70, 70)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 29, 70, 70)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(31, 30, 70, 70)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 31, 70, 70)));
-
-    occlusion.useDefaultLayerScissorRect();
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 30, 70, 70)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 30, 70, 70)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 29, 70, 70)));
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(31, 30, 70, 70)));
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 31, 70, 70)));
-    occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 30, 70, 70)).isEmpty());
-    EXPECT_EQ_RECT(IntRect(29, 30, 1, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 30, 70, 70)));
-    EXPECT_EQ_RECT(IntRect(29, 29, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 29, 70, 70)));
-    EXPECT_EQ_RECT(IntRect(30, 29, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 29, 70, 70)));
-    EXPECT_EQ_RECT(IntRect(31, 29, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 29, 70, 70)));
-    EXPECT_EQ_RECT(IntRect(100, 30, 1, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 30, 70, 70)));
-    EXPECT_EQ_RECT(IntRect(31, 31, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 31, 70, 70)));
-    EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 31, 70, 70)));
-    EXPECT_EQ_RECT(IntRect(29, 31, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 31, 70, 70)));
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerAddedToOccludedRegion, layerAddedToOccludedRegion);
-
-void layerAddedToOccludedRegionWithRotation(bool opaqueLayers)
-{
-    // This tests that the right transforms are being used.
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(layer);
-
-    TransformationMatrix layerTransform;
-    layerTransform.translate(250, 250);
-    layerTransform.rotate(90);
-    layerTransform.translate(-250, -250);
-
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
-    setLayerPropertiesForTesting(layer.get(), layerTransform, FloatPoint(30, 30), IntSize(500, 500), true, opaqueLayers);
-
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
-
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
-
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
-    TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
-    occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
-    occlusion.enterTargetRenderSurface(parent->renderSurface());
-    occlusion.markOccludedBehindLayer(layer.get());
-    EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 30, 70, 70)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 30, 70, 70)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 29, 70, 70)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(31, 30, 70, 70)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 31, 70, 70)));
-
-    occlusion.useDefaultLayerScissorRect();
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 30, 70, 70)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 30, 70, 70)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 29, 70, 70)));
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(31, 30, 70, 70)));
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 31, 70, 70)));
-    occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 30, 70, 70)).isEmpty());
-    EXPECT_EQ_RECT(IntRect(29, 30, 1, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 30, 70, 70)));
-    EXPECT_EQ_RECT(IntRect(29, 29, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 29, 70, 70)));
-    EXPECT_EQ_RECT(IntRect(30, 29, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 29, 70, 70)));
-    EXPECT_EQ_RECT(IntRect(31, 29, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 29, 70, 70)));
-    EXPECT_EQ_RECT(IntRect(100, 30, 1, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 30, 70, 70)));
-    EXPECT_EQ_RECT(IntRect(31, 31, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 31, 70, 70)));
-    EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 31, 70, 70)));
-    EXPECT_EQ_RECT(IntRect(29, 31, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 31, 70, 70)));
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerAddedToOccludedRegionWithRotation, layerAddedToOccludedRegionWithRotation);
-
-void layerAddedToOccludedRegionWithTranslation(bool opaqueLayers)
-{
-    // This tests that the right transforms are being used.
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(layer);
-
-    TransformationMatrix layerTransform;
-    layerTransform.translate(20, 20);
-
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
-    setLayerPropertiesForTesting(layer.get(), layerTransform, FloatPoint(30, 30), IntSize(500, 500), true, opaqueLayers);
-
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
-
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
-
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
-    TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
-    occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
-    occlusion.enterTargetRenderSurface(parent->renderSurface());
-    occlusion.markOccludedBehindLayer(layer.get());
-    EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(50, 50, 50, 50)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(49, 50, 50, 50)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(50, 49, 50, 50)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(51, 50, 50, 50)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(50, 51, 50, 50)));
-
-    occlusion.useDefaultLayerScissorRect();
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(50, 50, 50, 50)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(49, 50, 50, 50)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(50, 49, 50, 50)));
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(51, 50, 50, 50)));
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(50, 51, 50, 50)));
-    occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(50, 50, 50, 50)).isEmpty());
-    EXPECT_EQ_RECT(IntRect(49, 50, 1, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(49, 50, 50, 50)));
-    EXPECT_EQ_RECT(IntRect(49, 49, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(49, 49, 50, 50)));
-    EXPECT_EQ_RECT(IntRect(50, 49, 50, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(50, 49, 50, 50)));
-    EXPECT_EQ_RECT(IntRect(51, 49, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(51, 49, 50, 50)));
-    EXPECT_EQ_RECT(IntRect(100, 50, 1, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(51, 50, 50, 50)));
-    EXPECT_EQ_RECT(IntRect(51, 51, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(51, 51, 50, 50)));
-    EXPECT_EQ_RECT(IntRect(50, 100, 50, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(50, 51, 50, 50)));
-    EXPECT_EQ_RECT(IntRect(49, 51, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(49, 51, 50, 50)));
-
-    occlusion.useDefaultLayerScissorRect();
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(50, 50, 50, 50)).isEmpty());
-    EXPECT_EQ_RECT(IntRect(49, 50, 1, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(49, 50, 50, 50)));
-    EXPECT_EQ_RECT(IntRect(49, 49, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(49, 49, 50, 50)));
-    EXPECT_EQ_RECT(IntRect(50, 49, 50, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(50, 49, 50, 50)));
-    EXPECT_EQ_RECT(IntRect(51, 49, 49, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(51, 49, 50, 50)));
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(51, 50, 50, 50)).isEmpty());
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(51, 51, 50, 50)).isEmpty());
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(50, 51, 50, 50)).isEmpty());
-    EXPECT_EQ_RECT(IntRect(49, 51, 1, 49), occlusion.unoccludedContentRect(parent.get(), IntRect(49, 51, 50, 50)));
-    occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerAddedToOccludedRegionWithTranslation, layerAddedToOccludedRegionWithTranslation);
-
-void layerAddedToOccludedRegionWithRotatedSurface(bool opaqueLayers)
-{
-    // This tests that the right transforms are being used.
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromium> child = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(child);
-    child->addChild(layer);
-
-    TransformationMatrix childTransform;
-    childTransform.translate(250, 250);
-    childTransform.rotate(90);
-    childTransform.translate(-250, -250);
-
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
-    setLayerPropertiesForTesting(child.get(), childTransform, FloatPoint(30, 30), IntSize(500, 500));
-    setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(10, 10), IntSize(500, 500), true, opaqueLayers);
-
-    child->setMasksToBounds(true);
-
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
-
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
-
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
-    TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
-    occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
-    occlusion.enterTargetRenderSurface(child->renderSurface());
-    occlusion.markOccludedBehindLayer(layer.get());
-
-    EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
-    EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 430, 60, 70)));
-    EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(9, 430, 60, 70)));
-    EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 429, 60, 70)));
-    EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 430, 61, 70)));
-    EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 430, 60, 71)));
-
-    occlusion.useDefaultLayerScissorRect();
-    EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 430, 60, 70)));
-    EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(9, 430, 60, 70)));
-    EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 429, 60, 70)));
-    EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 430, 61, 70)));
-    EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 430, 60, 71)));
-    occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
-    occlusion.markOccludedBehindLayer(child.get());
-    occlusion.finishedTargetRenderSurface(child.get(), child->renderSurface());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
-    EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 40, 70, 60)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 40, 70, 60)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 39, 70, 60)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(31, 40, 70, 60)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 41, 70, 60)));
-
-    occlusion.useDefaultLayerScissorRect();
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 40, 70, 60)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 40, 70, 60)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 39, 70, 60)));
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(31, 40, 70, 60)));
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 41, 70, 60)));
-    occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
-
-    /* Justification for the above occlusion from |layer|:
-               100
-      +---------------------+                                      +---------------------+
-      |                     |                                      |                     |30  Visible region of |layer|: /////
-      |    30               |           rotate(90)                 |                     |
-      | 30 + ---------------------------------+                    |     +---------------------------------+
-  100 |    |  10            |                 |            ==>     |     |               |10               |
-      |    |10+---------------------------------+                  |  +---------------------------------+  |
-      |    |  |             |                 | |                  |  |  |///////////////|     420      |  |
-      |    |  |             |                 | |                  |  |  |///////////////|60            |  |
-      |    |  |             |                 | |                  |  |  |///////////////|              |  |
-      +----|--|-------------+                 | |                  +--|--|---------------+              |  |
-           |  |                               | |                   20|10|     70                       |  |
-           |  |                               | |                     |  |                              |  |
-           |  |                               | |500                  |  |                              |  |
-           |  |                               | |                     |  |                              |  |
-           |  |                               | |                     |  |                              |  |
-           |  |                               | |                     |  |                              |  |
-           |  |                               | |                     |  |                              |10|
-           +--|-------------------------------+ |                     |  +------------------------------|--+
-              |                                 |                     |                 490             |
-              +---------------------------------+                     +---------------------------------+
-                             500                                                     500
-     */
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerAddedToOccludedRegionWithRotatedSurface, layerAddedToOccludedRegionWithRotatedSurface);
-
-void layerAddedToOccludedRegionWithSurfaceAlreadyOnStack(bool opaqueLayers)
-{
-    // This tests that the right transforms are being used.
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromium> child = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> child2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(child);
-    child->addChild(layer);
-    parent->addChild(child2);
-
-    TransformationMatrix childTransform;
-    childTransform.translate(250, 250);
-    childTransform.rotate(90);
-    childTransform.translate(-250, -250);
-
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
-    setLayerPropertiesForTesting(child.get(), childTransform, FloatPoint(30, 30), IntSize(500, 500));
-    setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(10, 10), IntSize(500, 500), true, opaqueLayers);
-
-    // |child2| makes |parent|'s surface get considered by CCOcclusionTracker first, instead of |child|'s. This exercises different code in
-    // leaveToTargetRenderSurface, as the target surface has already been seen.
-    setLayerPropertiesForTesting(child2.get(), identityMatrix, FloatPoint(30, 30), IntSize(60, 20), true, opaqueLayers);
-
-    child->setMasksToBounds(true);
-
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
-
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
-
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
-    TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
-    occlusion.setLayerScissorRect(IntRect(-10, -10, 1000, 1000));
-
-    occlusion.enterTargetRenderSurface(parent->renderSurface());
-    occlusion.markOccludedBehindLayer(child2.get());
-
-    EXPECT_EQ_RECT(IntRect(30, 30, 60, 20), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(30, 30, 60, 20), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
-    occlusion.enterTargetRenderSurface(child->renderSurface());
-    occlusion.markOccludedBehindLayer(layer.get());
-
-    EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
-    EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 430, 60, 70)));
-    EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(9, 430, 60, 70)));
-    EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 429, 60, 70)));
-    EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(11, 430, 60, 70)));
-    EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 431, 60, 70)));
-
-    occlusion.useDefaultLayerScissorRect();
-    EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 430, 60, 70)));
-    EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(9, 430, 60, 70)));
-    EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 429, 60, 70)));
-    EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(11, 430, 60, 70)));
-    EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 431, 60, 70)));
-    occlusion.setLayerScissorRect(IntRect(-10, -10, 1000, 1000));
-
-    EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(10, 430, 60, 70)).isEmpty());
-    // This is the little piece not occluded by child2
-    EXPECT_EQ_RECT(IntRect(9, 430, 1, 10), occlusion.unoccludedContentRect(child.get(), IntRect(9, 430, 60, 70)));
-    // This extends past both sides of child2, so it will be the original rect.
-    EXPECT_EQ_RECT(IntRect(9, 430, 60, 80), occlusion.unoccludedContentRect(child.get(), IntRect(9, 430, 60, 80)));
-    // This extends past two adjacent sides of child2, and should included the unoccluded parts of each side.
-    // This also demonstrates that the rect can be arbitrary and does not get clipped to the layer's visibleLayerRect().
-    EXPECT_EQ_RECT(IntRect(-10, 430, 20, 70), occlusion.unoccludedContentRect(child.get(), IntRect(-10, 430, 60, 70)));
-    // This extends past three adjacent sides of child2, so it should contain the unoccluded parts of each side. The left
-    // and bottom edges are completely unoccluded for some row/column so we get back the original query rect.
-    EXPECT_EQ_RECT(IntRect(-10, 430, 60, 80), occlusion.unoccludedContentRect(child.get(), IntRect(-10, 430, 60, 80)));
-    EXPECT_EQ_RECT(IntRect(10, 429, 60, 1), occlusion.unoccludedContentRect(child.get(), IntRect(10, 429, 60, 70)));
-    EXPECT_EQ_RECT(IntRect(70, 430, 1, 70), occlusion.unoccludedContentRect(child.get(), IntRect(11, 430, 60, 70)));
-    EXPECT_EQ_RECT(IntRect(10, 500, 60, 1), occlusion.unoccludedContentRect(child.get(), IntRect(10, 431, 60, 70)));
-
-    occlusion.useDefaultLayerScissorRect();
-    EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(10, 430, 60, 70)).isEmpty());
-    EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(9, 430, 60, 70)).isEmpty());
-    EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(9, 430, 60, 80)).isEmpty());
-    EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(-10, 430, 60, 70)).isEmpty());
-    EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(-10, 430, 60, 80)).isEmpty());
-    EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(10, 429, 60, 70)).isEmpty());
-    EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(11, 430, 60, 70)).isEmpty());
-    EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(10, 431, 60, 70)).isEmpty());
-    occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
-    occlusion.markOccludedBehindLayer(child.get());
-    // |child2| should get merged with the surface we are leaving now
-    occlusion.finishedTargetRenderSurface(child.get(), child->renderSurface());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
-    EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
-
-    Vector<IntRect> screen = occlusion.occlusionInScreenSpace().rects();
-    Vector<IntRect> target = occlusion.occlusionInTargetSurface().rects();
-
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 30, 70, 70)));
-    EXPECT_EQ_RECT(IntRect(90, 30, 10, 10), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 30, 70, 70)));
-
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 30, 60, 10)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 30, 60, 10)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 29, 60, 10)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(31, 30, 60, 10)));
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 31, 60, 10)));
-
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 40, 70, 60)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 40, 70, 60)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 39, 70, 60)));
-
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 30, 60, 10)).isEmpty());
-    EXPECT_EQ_RECT(IntRect(29, 30, 1, 10), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 30, 60, 10)));
-    EXPECT_EQ_RECT(IntRect(30, 29, 60, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 29, 60, 10)));
-    EXPECT_EQ_RECT(IntRect(90, 30, 1, 10), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 30, 60, 10)));
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 31, 60, 10)).isEmpty());
-
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 40, 70, 60)).isEmpty());
-    EXPECT_EQ_RECT(IntRect(29, 40, 1, 60), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 40, 70, 60)));
-    // This rect is mostly occluded by |child2|.
-    EXPECT_EQ_RECT(IntRect(90, 39, 10, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 39, 70, 60)));
-    // This rect extends past top/right ends of |child2|.
-    EXPECT_EQ_RECT(IntRect(30, 29, 70, 11), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 29, 70, 70)));
-    // This rect extends past left/right ends of |child2|.
-    EXPECT_EQ_RECT(IntRect(20, 39, 80, 60), occlusion.unoccludedContentRect(parent.get(), IntRect(20, 39, 80, 60)));
-    EXPECT_EQ_RECT(IntRect(100, 40, 1, 60), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 40, 70, 60)));
-    EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 41, 70, 60)));
-
-    /* Justification for the above occlusion from |layer|:
-               100
-      +---------------------+                                      +---------------------+
-      |                     |                                      |                     |30  Visible region of |layer|: /////
-      |    30               |           rotate(90)                 |     30   60         |    |child2|: \\\\\
-      | 30 + ------------+--------------------+                    |  30 +------------+--------------------+
-  100 |    |  10         |  |                 |            ==>     |     |\\\\\\\\\\\\|  |10               |
-      |    |10+----------|----------------------+                  |  +--|\\\\\\\\\\\\|-----------------+  |
-      |    + ------------+  |                 | |                  |  |  +------------+//|     420      |  |
-      |    |  |             |                 | |                  |  |  |///////////////|60            |  |
-      |    |  |             |                 | |                  |  |  |///////////////|              |  |
-      +----|--|-------------+                 | |                  +--|--|---------------+              |  |
-           |  |                               | |                   20|10|     70                       |  |
-           |  |                               | |                     |  |                              |  |
-           |  |                               | |500                  |  |                              |  |
-           |  |                               | |                     |  |                              |  |
-           |  |                               | |                     |  |                              |  |
-           |  |                               | |                     |  |                              |  |
-           |  |                               | |                     |  |                              |10|
-           +--|-------------------------------+ |                     |  +------------------------------|--+
-              |                                 |                     |                 490             |
-              +---------------------------------+                     +---------------------------------+
-                             500                                                     500
-     */
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerAddedToOccludedRegionWithSurfaceAlreadyOnStack, layerAddedToOccludedRegionWithSurfaceAlreadyOnStack);
-
-void layerAddedToOccludedRegionWithRotatedOffAxisSurface(bool opaqueLayers)
-{
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromium> child = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(child);
-    child->addChild(layer);
-
-    // Now rotate the child a little more so it is not axis-aligned. The parent will no longer be occluded by |layer|, but
-    // the child's occlusion should be unchanged.
-
-    TransformationMatrix childTransform;
-    childTransform.translate(250, 250);
-    childTransform.rotate(95);
-    childTransform.translate(-250, -250);
-
-    TransformationMatrix layerTransform;
-    layerTransform.translate(10, 10);
-
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
-    setLayerPropertiesForTesting(child.get(), childTransform, FloatPoint(30, 30), IntSize(500, 500));
-    setLayerPropertiesForTesting(layer.get(), layerTransform, FloatPoint(0, 0), IntSize(500, 500), true, opaqueLayers);
-
-    child->setMasksToBounds(true);
-
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
-
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
-
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
-    TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
-    occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
-    IntRect clippedLayerInChild = layerTransform.mapRect(layer->visibleLayerRect());
-
-    occlusion.enterTargetRenderSurface(child->renderSurface());
-    occlusion.markOccludedBehindLayer(layer.get());
-
-    EXPECT_EQ_RECT(IntRect(), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(clippedLayerInChild, occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
-    EXPECT_TRUE(occlusion.occluded(child.get(), clippedLayerInChild));
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), clippedLayerInChild).isEmpty());
-    clippedLayerInChild.move(-1, 0);
-    EXPECT_FALSE(occlusion.occluded(child.get(), clippedLayerInChild));
-    EXPECT_FALSE(occlusion.unoccludedContentRect(parent.get(), clippedLayerInChild).isEmpty());
-    clippedLayerInChild.move(1, 0);
-    clippedLayerInChild.move(1, 0);
-    EXPECT_FALSE(occlusion.occluded(child.get(), clippedLayerInChild));
-    EXPECT_FALSE(occlusion.unoccludedContentRect(parent.get(), clippedLayerInChild).isEmpty());
-    clippedLayerInChild.move(-1, 0);
-    clippedLayerInChild.move(0, -1);
-    EXPECT_FALSE(occlusion.occluded(child.get(), clippedLayerInChild));
-    EXPECT_FALSE(occlusion.unoccludedContentRect(parent.get(), clippedLayerInChild).isEmpty());
-    clippedLayerInChild.move(0, 1);
-    clippedLayerInChild.move(0, 1);
-    EXPECT_FALSE(occlusion.occluded(child.get(), clippedLayerInChild));
-    EXPECT_FALSE(occlusion.unoccludedContentRect(parent.get(), clippedLayerInChild).isEmpty());
-    clippedLayerInChild.move(0, -1);
-
-    occlusion.markOccludedBehindLayer(child.get());
-    occlusion.finishedTargetRenderSurface(child.get(), child->renderSurface());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
-    EXPECT_EQ_RECT(IntRect(), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(0u, occlusion.occlusionInTargetSurface().rects().size());
-
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(75, 55, 1, 1)));
-    EXPECT_EQ_RECT(IntRect(75, 55, 1, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(75, 55, 1, 1)));
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerAddedToOccludedRegionWithRotatedOffAxisSurface, layerAddedToOccludedRegionWithRotatedOffAxisSurface);
-
-void layerAddedToOccludedRegionWithMultipleOpaqueLayers(bool opaqueLayers)
-{
-    // This is similar to the previous test but now we make a few opaque layers inside of |child| so that the occluded parts of child are not a simple rect.
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromium> child = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(child);
-    child->addChild(layer1);
-    child->addChild(layer2);
-
-    TransformationMatrix childTransform;
-    childTransform.translate(250, 250);
-    childTransform.rotate(90);
-    childTransform.translate(-250, -250);
-
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
-    setLayerPropertiesForTesting(child.get(), childTransform, FloatPoint(30, 30), IntSize(500, 500));
-    setLayerPropertiesForTesting(layer1.get(), identityMatrix, FloatPoint(10, 10), IntSize(500, 440), true, opaqueLayers);
-    setLayerPropertiesForTesting(layer2.get(), identityMatrix, FloatPoint(10, 450), IntSize(500, 60), true, opaqueLayers);
-
-    child->setMasksToBounds(true);
-
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
-
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
-
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
-    TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
-    occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
-    occlusion.enterTargetRenderSurface(child->renderSurface());
-    occlusion.markOccludedBehindLayer(layer2.get());
-    occlusion.markOccludedBehindLayer(layer1.get());
-
-    EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
-    EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 430, 60, 70)));
-    EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(9, 430, 60, 70)));
-    EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 429, 60, 70)));
-    EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(11, 430, 60, 70)));
-    EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 431, 60, 70)));
-
-    EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(10, 430, 60, 70)).isEmpty());
-    EXPECT_EQ_RECT(IntRect(9, 430, 1, 70), occlusion.unoccludedContentRect(child.get(), IntRect(9, 430, 60, 70)));
-    EXPECT_EQ_RECT(IntRect(10, 429, 60, 1), occlusion.unoccludedContentRect(child.get(), IntRect(10, 429, 60, 70)));
-    EXPECT_EQ_RECT(IntRect(70, 430, 1, 70), occlusion.unoccludedContentRect(child.get(), IntRect(11, 430, 60, 70)));
-    EXPECT_EQ_RECT(IntRect(10, 500, 60, 1), occlusion.unoccludedContentRect(child.get(), IntRect(10, 431, 60, 70)));
-
-    occlusion.markOccludedBehindLayer(child.get());
-    occlusion.finishedTargetRenderSurface(child.get(), child->renderSurface());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
-    EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 40, 70, 60)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 40, 70, 60)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 39, 70, 60)));
-
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 40, 70, 60)).isEmpty());
-    EXPECT_EQ_RECT(IntRect(29, 40, 1, 60), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 40, 70, 60)));
-    EXPECT_EQ_RECT(IntRect(30, 39, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 39, 70, 60)));
-    EXPECT_EQ_RECT(IntRect(100, 40, 1, 60), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 40, 70, 60)));
-    EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 41, 70, 60)));
-
-    /* Justification for the above occlusion from |layer1| and |layer2|:
-
-       +---------------------+
-       |                     |30  Visible region of |layer1|: /////
-       |                     |    Visible region of |layer2|: \\\\\
-       |     +---------------------------------+
-       |     |               |10               |
-       |  +---------------+-----------------+  |
-       |  |  |\\\\\\\\\\\\|//|     420      |  |
-       |  |  |\\\\\\\\\\\\|//|60            |  |
-       |  |  |\\\\\\\\\\\\|//|              |  |
-       +--|--|------------|--+              |  |
-        20|10|     70     |                 |  |
-          |  |            |                 |  |
-          |  |            |                 |  |
-          |  |            |                 |  |
-          |  |            |                 |  |
-          |  |            |                 |  |
-          |  |            |                 |10|
-          |  +------------|-----------------|--+
-          |               | 490             |
-          +---------------+-----------------+
-                60               440
-     */
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerAddedToOccludedRegionWithMultipleOpaqueLayers, layerAddedToOccludedRegionWithMultipleOpaqueLayers);
-
-void surfaceOcclusionWithOverlappingSiblingSurfaces(bool opaqueLayers)
-{
-    // This tests that the right transforms are being used.
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromium> child1 = LayerChromium::create();
-    RefPtr<LayerChromium> child2 = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(child1);
-    parent->addChild(child2);
-    child1->addChild(layer1);
-    child2->addChild(layer2);
-
-    TransformationMatrix childTransform;
-    childTransform.translate(250, 250);
-    childTransform.rotate(90);
-    childTransform.translate(-250, -250);
-
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
-    setLayerPropertiesForTesting(child1.get(), childTransform, FloatPoint(30, 30), IntSize(500, 500));
-    setLayerPropertiesForTesting(layer1.get(), identityMatrix, FloatPoint(0, 0), IntSize(500, 500), true, opaqueLayers);
-    setLayerPropertiesForTesting(child2.get(), childTransform, FloatPoint(20, 40), IntSize(500, 500));
-    setLayerPropertiesForTesting(layer2.get(), identityMatrix, FloatPoint(0, 0), IntSize(500, 500), true, opaqueLayers);
-
-    child1->setMasksToBounds(true);
-    child2->setMasksToBounds(true);
-
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
-
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
-
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
-    TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
-    occlusion.setLayerScissorRect(IntRect(-10, -10, 1000, 1000));
-
-    occlusion.enterTargetRenderSurface(child2->renderSurface());
-    occlusion.markOccludedBehindLayer(layer2.get());
-
-    EXPECT_EQ_RECT(IntRect(20, 40, 80, 60), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(0, 420, 60, 80), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
-    EXPECT_TRUE(occlusion.occluded(child2.get(), IntRect(0, 420, 60, 80)));
-    EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-1, 420, 60, 80)));
-    EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(0, 419, 60, 80)));
-    EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(0, 420, 61, 80)));
-    EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(0, 420, 60, 81)));
-
-    occlusion.markOccludedBehindLayer(child2.get());
-    occlusion.finishedTargetRenderSurface(child2.get(), child2->renderSurface());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-    occlusion.enterTargetRenderSurface(child1->renderSurface());
-    occlusion.markOccludedBehindLayer(layer1.get());
-
-    EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(0, 430, 70, 70), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
-    EXPECT_TRUE(occlusion.occluded(child1.get(), IntRect(0, 430, 70, 70)));
-    EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(-1, 430, 70, 70)));
-    EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(0, 429, 70, 70)));
-    EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(0, 430, 71, 70)));
-    EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(0, 430, 70, 71)));
-
-    occlusion.markOccludedBehindLayer(child1.get());
-    occlusion.finishedTargetRenderSurface(child1.get(), child1->renderSurface());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
-    EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
-
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(20, 30, 80, 70)));
-
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 30, 70, 70)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 30, 70, 70)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 29, 70, 70)));
-
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(20, 40, 80, 60)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(19, 40, 80, 60)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(20, 39, 80, 60)));
-
-    /* Justification for the above occlusion:
-               100
-      +---------------------+
-      |                     |
-      |    30               |       child1
-      |  30+ ---------------------------------+
-  100 |  40|                |     child2      |
-      |20+----------------------------------+ |
-      |  | |                |               | |
-      |  | |                |               | |
-      |  | |                |               | |
-      +--|-|----------------+               | |
-         | |                                | | 500
-         | |                                | |
-         | |                                | |
-         | |                                | |
-         | |                                | |
-         | |                                | |
-         | |                                | |
-         | +--------------------------------|-+
-         |                                  |
-         +----------------------------------+
-                         500
-     */
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_surfaceOcclusionWithOverlappingSiblingSurfaces, surfaceOcclusionWithOverlappingSiblingSurfaces);
-
-void surfaceOcclusionInScreenSpace(bool opaqueLayers)
-{
-    // This tests that the right transforms are being used.
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromium> child1 = LayerChromium::create();
-    RefPtr<LayerChromium> child2 = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(child1);
-    parent->addChild(child2);
-    child1->addChild(layer1);
-    child2->addChild(layer2);
-
-    TransformationMatrix childTransform;
-    childTransform.translate(250, 250);
-    childTransform.rotate(90);
-    childTransform.translate(-250, -250);
-
-    // The owning layers have very different bounds from the surfaces that they own.
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
-    setLayerPropertiesForTesting(child1.get(), childTransform, FloatPoint(30, 30), IntSize(10, 10));
-    setLayerPropertiesForTesting(layer1.get(), identityMatrix, FloatPoint(-10, -10), IntSize(510, 510), true, opaqueLayers);
-    setLayerPropertiesForTesting(child2.get(), childTransform, FloatPoint(20, 40), IntSize(10, 10));
-    setLayerPropertiesForTesting(layer2.get(), identityMatrix, FloatPoint(-10, -10), IntSize(510, 510), true, opaqueLayers);
-
-    // Make them both render surfaces
-    FilterOperations filters;
-    filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
-    child1->setFilters(filters);
-    child2->setFilters(filters);
-
-    child1->setMasksToBounds(false);
-    child2->setMasksToBounds(false);
-
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
-
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
-
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
-    TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
-    occlusion.setLayerScissorRect(IntRect(-20, -20, 1000, 1000));
-
-    occlusion.enterTargetRenderSurface(child2->renderSurface());
-    occlusion.markOccludedBehindLayer(layer2.get());
-
-    EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(-10, 420, 70, 80), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
-    EXPECT_TRUE(occlusion.occluded(child2.get(), IntRect(-10, 420, 70, 80)));
-    EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-11, 420, 70, 80)));
-    EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 419, 70, 80)));
-    EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 420, 71, 80)));
-    EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 420, 70, 81)));
-
-    occlusion.useDefaultLayerScissorRect();
-    EXPECT_TRUE(occlusion.occluded(child2.get(), IntRect(-10, 420, 70, 80)));
-    EXPECT_TRUE(occlusion.occluded(child2.get(), IntRect(-11, 420, 70, 80)));
-    EXPECT_TRUE(occlusion.occluded(child2.get(), IntRect(-10, 419, 70, 80)));
-    EXPECT_TRUE(occlusion.occluded(child2.get(), IntRect(-10, 420, 71, 80)));
-    EXPECT_TRUE(occlusion.occluded(child2.get(), IntRect(-10, 420, 70, 81)));
-    occlusion.setLayerScissorRect(IntRect(-20, -20, 1000, 1000));
-
-    occlusion.markOccludedBehindLayer(child2.get());
-    occlusion.finishedTargetRenderSurface(child2.get(), child2->renderSurface());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-    occlusion.enterTargetRenderSurface(child1->renderSurface());
-    occlusion.markOccludedBehindLayer(layer1.get());
-
-    EXPECT_EQ_RECT(IntRect(20, 20, 80, 80), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(-10, 430, 80, 70), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
-    EXPECT_TRUE(occlusion.occluded(child1.get(), IntRect(-10, 430, 80, 70)));
-    EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(-11, 430, 80, 70)));
-    EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(-10, 429, 80, 70)));
-    EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(-10, 430, 81, 70)));
-    EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(-10, 430, 80, 71)));
-
-    occlusion.markOccludedBehindLayer(child1.get());
-    occlusion.finishedTargetRenderSurface(child1.get(), child1->renderSurface());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
-    EXPECT_EQ_RECT(IntRect(20, 20, 80, 80), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(20, 20, 80, 80), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
-
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(20, 20, 80, 80)));
-
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 20, 70, 80)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 20, 70, 80)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 19, 70, 80)));
-
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(20, 30, 80, 70)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(19, 30, 80, 70)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(20, 29, 80, 70)));
-
-    /* Justification for the above occlusion:
-               100
-      +---------------------+
-      |    20               |       layer1
-      |  30+ ---------------------------------+
-  100 |  30|                |     layer2      |
-      |20+----------------------------------+ |
-      |  | |                |               | |
-      |  | |                |               | |
-      |  | |                |               | |
-      +--|-|----------------+               | |
-         | |                                | | 510
-         | |                                | |
-         | |                                | |
-         | |                                | |
-         | |                                | |
-         | |                                | |
-         | |                                | |
-         | +--------------------------------|-+
-         |                                  |
-         +----------------------------------+
-                         510
-     */
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_surfaceOcclusionInScreenSpace, surfaceOcclusionInScreenSpace);
-
-void surfaceOcclusionInScreenSpaceDifferentTransforms(bool opaqueLayers)
-{
-    // This tests that the right transforms are being used.
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromium> child1 = LayerChromium::create();
-    RefPtr<LayerChromium> child2 = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(child1);
-    parent->addChild(child2);
-    child1->addChild(layer1);
-    child2->addChild(layer2);
-
-    TransformationMatrix child1Transform;
-    child1Transform.translate(250, 250);
-    child1Transform.rotate(-90);
-    child1Transform.translate(-250, -250);
-
-    TransformationMatrix child2Transform;
-    child2Transform.translate(250, 250);
-    child2Transform.rotate(90);
-    child2Transform.translate(-250, -250);
-
-    // The owning layers have very different bounds from the surfaces that they own.
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
-    setLayerPropertiesForTesting(child1.get(), child1Transform, FloatPoint(30, 20), IntSize(10, 10));
-    setLayerPropertiesForTesting(layer1.get(), identityMatrix, FloatPoint(-10, -20), IntSize(510, 520), true, opaqueLayers);
-    setLayerPropertiesForTesting(child2.get(), child2Transform, FloatPoint(20, 40), IntSize(10, 10));
-    setLayerPropertiesForTesting(layer2.get(), identityMatrix, FloatPoint(-10, -10), IntSize(510, 510), true, opaqueLayers);
-
-    // Make them both render surfaces
-    FilterOperations filters;
-    filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
-    child1->setFilters(filters);
-    child2->setFilters(filters);
-
-    child1->setMasksToBounds(false);
-    child2->setMasksToBounds(false);
-
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
-
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
-
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
-    TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
-    occlusion.setLayerScissorRect(IntRect(-30, -30, 1000, 1000));
-
-    occlusion.enterTargetRenderSurface(child2->renderSurface());
-    occlusion.markOccludedBehindLayer(layer2.get());
-
-    EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(-10, 420, 70, 80), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
-    EXPECT_TRUE(occlusion.occluded(child2.get(), IntRect(-10, 420, 70, 80)));
-    EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-11, 420, 70, 80)));
-    EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 419, 70, 80)));
-    EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 420, 71, 80)));
-    EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 420, 70, 81)));
-
-    occlusion.markOccludedBehindLayer(child2.get());
-    occlusion.finishedTargetRenderSurface(child2.get(), child2->renderSurface());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-    occlusion.enterTargetRenderSurface(child1->renderSurface());
-    occlusion.markOccludedBehindLayer(layer1.get());
-
-    EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(420, -20, 80, 90), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
-    EXPECT_TRUE(occlusion.occluded(child1.get(), IntRect(420, -20, 80, 90)));
-    EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(419, -20, 80, 90)));
-    EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(420, -21, 80, 90)));
-    EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(420, -19, 80, 90)));
-    EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(421, -20, 80, 90)));
-
-    occlusion.markOccludedBehindLayer(child1.get());
-    occlusion.finishedTargetRenderSurface(child1.get(), child1->renderSurface());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
-    EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
-    EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(10, 20, 90, 80)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(9, 20, 90, 80)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(10, 19, 90, 80)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(11, 20, 90, 80)));
-    EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(10, 21, 90, 80)));
-
-    /* Justification for the above occlusion:
-               100
-      +---------------------+
-      |20                   |       layer1
-     10+----------------------------------+
-  100 || 30                 |     layer2  |
-      |20+----------------------------------+
-      || |                  |             | |
-      || |                  |             | |
-      || |                  |             | |
-      +|-|------------------+             | |
-       | |                                | | 510
-       | |                            510 | |
-       | |                                | |
-       | |                                | |
-       | |                                | |
-       | |                                | |
-       | |                520             | |
-       +----------------------------------+ |
-         |                                  |
-         +----------------------------------+
-                         510
-     */
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_surfaceOcclusionInScreenSpaceDifferentTransforms, surfaceOcclusionInScreenSpaceDifferentTransforms);
-
-void occlusionInteractionWithFilters(bool opaqueLayers)
-{
-    // This tests that the right transforms are being used.
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> blurLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    RefPtr<LayerChromiumWithForcedDrawsContent> opacityLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    RefPtr<LayerChromiumWithForcedDrawsContent> opaqueLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(blurLayer);
-    parent->addChild(opacityLayer);
-    parent->addChild(opaqueLayer);
-
-    TransformationMatrix layerTransform;
-    layerTransform.translate(250, 250);
-    layerTransform.rotate(90);
-    layerTransform.translate(-250, -250);
-
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
-    setLayerPropertiesForTesting(blurLayer.get(), layerTransform, FloatPoint(30, 30), IntSize(500, 500), true, opaqueLayers);
-    setLayerPropertiesForTesting(opaqueLayer.get(), layerTransform, FloatPoint(30, 30), IntSize(500, 500), true, opaqueLayers);
-    setLayerPropertiesForTesting(opacityLayer.get(), layerTransform, FloatPoint(30, 30), IntSize(500, 500), true, opaqueLayers);
+    typename Types::ContentLayerType* createRoot(const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
+    {
+        typename Types::ContentLayerPtrType layer = Types::createContentLayer();
+        typename Types::ContentLayerType* layerPtr = layer.get();
+        setProperties(layerPtr, transform, position, bounds);
 
+        ASSERT(!m_root);
+        m_root = layer.release();
+        return layerPtr;
+    }
+
+    typename Types::LayerType* createLayer(typename Types::LayerType* parent, const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
     {
-        FilterOperations filters;
-        filters.operations().append(BlurFilterOperation::create(Length(10, WebCore::Percent), FilterOperation::BLUR));
-        blurLayer->setFilters(filters);
+        typename Types::LayerPtrType layer = Types::createLayer();
+        typename Types::LayerType* layerPtr = layer.get();
+        setProperties(layerPtr, transform, position, bounds);
+        parent->addChild(layer.release());
+        return layerPtr;
     }
 
+    typename Types::LayerType* createSurface(typename Types::LayerType* parent, const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
     {
+        typename Types::LayerType* layer = createLayer(parent, transform, position, bounds);
         FilterOperations filters;
         filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
-        opaqueLayer->setFilters(filters);
+        layer->setFilters(filters);
+        return layer;
     }
 
+    typename Types::ContentLayerType* createDrawingLayer(typename Types::LayerType* parent, const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds, bool opaque)
     {
+        typename Types::ContentLayerPtrType layer = Types::createContentLayer();
+        typename Types::ContentLayerType* layerPtr = layer.get();
+        setProperties(layerPtr, transform, position, bounds);
+
+        if (opaqueLayers)
+            layerPtr->setOpaque(opaque);
+        else {
+            layerPtr->setOpaque(false);
+            if (opaque)
+                layerPtr->setOpaqueContentsRect(IntRect(IntPoint(), bounds));
+            else
+                layerPtr->setOpaqueContentsRect(IntRect());
+        }
+
+        parent->addChild(layer.release());
+        return layerPtr;
+    }
+
+    typename Types::ContentLayerType* createDrawingSurface(typename Types::LayerType* parent, const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds, bool opaque)
+    {
+        typename Types::ContentLayerType* layer = createDrawingLayer(parent, transform, position, bounds, opaque);
         FilterOperations filters;
-        filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::OPACITY));
-        opacityLayer->setFilters(filters);
+        filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
+        layer->setFilters(filters);
+        return layer;
     }
 
 
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
-
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
-
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
-    TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
-    occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
-    // Opacity layer won't contribute to occlusion.
-    occlusion.enterTargetRenderSurface(opacityLayer->renderSurface());
-    occlusion.markOccludedBehindLayer(opacityLayer.get());
-    occlusion.finishedTargetRenderSurface(opacityLayer.get(), opacityLayer->renderSurface());
-
-    EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
-    EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
-
-    // And has nothing to contribute to its parent surface.
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-    EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
-    EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
-
-    // Opaque layer will contribute to occlusion.
-    occlusion.enterTargetRenderSurface(opaqueLayer->renderSurface());
-    occlusion.markOccludedBehindLayer(opaqueLayer.get());
-    occlusion.finishedTargetRenderSurface(opaqueLayer.get(), opaqueLayer->renderSurface());
-
-    EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(0, 430, 70, 70), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
-    // And it gets translated to the parent surface.
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-    EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
-    // The blur layer needs to throw away any occlusion from outside its subtree.
-    occlusion.enterTargetRenderSurface(blurLayer->renderSurface());
-    EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
-    EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
-
-    // And it won't contribute to occlusion.
-    occlusion.markOccludedBehindLayer(blurLayer.get());
-    occlusion.finishedTargetRenderSurface(blurLayer.get(), blurLayer->renderSurface());
-    EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
-    EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
-
-    // But the opaque layer's occlusion is preserved on the parent.
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-    EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
-    EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
-    EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_occlusionInteractionWithFilters, occlusionInteractionWithFilters);
-
-void layerScissorRectOverTile(bool opaqueLayers)
-{
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(parentLayer);
-    parent->addChild(layer);
-
-    FilterOperations filters;
-    filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
-    parentLayer->setFilters(filters);
-    layer->setFilters(filters);
-
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
-    setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
-    setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
-
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
-
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
-
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
-    TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
-    occlusion.setLayerScissorRect(IntRect(200, 100, 100, 100));
-
-    occlusion.enterTargetRenderSurface(layer->renderSurface());
-
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(200, 100, 100, 100)));
-
-    occlusion.useDefaultLayerScissorRect();
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(200, 100, 100, 100)));
-    occlusion.setLayerScissorRect(IntRect(200, 100, 100, 100));
-
-    occlusion.markOccludedBehindLayer(layer.get());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-    occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
-
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
-
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
-    EXPECT_EQ_RECT(IntRect(200, 100, 100, 100), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)));
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerScissorRectOverTile, layerScissorRectOverTile);
-
-void screenScissorRectOverTile(bool opaqueLayers)
-{
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(parentLayer);
-    parent->addChild(layer);
+    TestContentLayerImpl* calcDrawEtc(TestContentLayerImpl* root)
+    {
+        ASSERT(root == m_root.get());
+        Vector<CCLayerImpl*> dummyLayerList;
+        int dummyMaxTextureSize = 512;
+
+        ASSERT(!root->renderSurface());
+        root->createRenderSurface();
+        root->renderSurface()->setContentRect(IntRect(IntPoint::zero(), root->bounds()));
+        root->setClipRect(IntRect(IntPoint::zero(), root->bounds()));
+        m_renderSurfaceLayerListImpl.append(m_root.get());
+
+        CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(root, root, identityMatrix, identityMatrix, m_renderSurfaceLayerListImpl, dummyLayerList, 0, dummyMaxTextureSize);
+        return root;
+    }
 
-    FilterOperations filters;
-    filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
-    parentLayer->setFilters(filters);
-    layer->setFilters(filters);
+    TestContentLayerChromium* calcDrawEtc(TestContentLayerChromium* root)
+    {
+        ASSERT(root == m_root.get());
+        Vector<RefPtr<LayerChromium> > dummyLayerList;
+        int dummyMaxTextureSize = 512;
+
+        ASSERT(!root->renderSurface());
+        root->createRenderSurface();
+        root->renderSurface()->setContentRect(IntRect(IntPoint::zero(), root->bounds()));
+        root->setClipRect(IntRect(IntPoint::zero(), root->bounds()));
+        m_renderSurfaceLayerListChromium.append(m_root);
+
+        CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(root, root, identityMatrix, identityMatrix, m_renderSurfaceLayerListChromium, dummyLayerList, dummyMaxTextureSize);
+        return root;
+    }
 
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
-    setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
-    setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
+    const TransformationMatrix identityMatrix;
 
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
+private:
+    void setBaseProperties(typename Types::LayerType* layer, const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
+    {
+        layer->setTransform(transform);
+        layer->setSublayerTransform(TransformationMatrix());
+        layer->setAnchorPoint(FloatPoint(0, 0));
+        layer->setPosition(position);
+        layer->setBounds(bounds);
+    }
 
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
+    void setProperties(LayerChromium* layer, const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
+    {
+        setBaseProperties(layer, transform, position, bounds);
+    }
 
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+    void setProperties(CCLayerImpl* layer, const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
+    {
+        setBaseProperties(layer, transform, position, bounds);
 
-    TestCCOcclusionTracker occlusion(IntRect(200, 100, 100, 100));
+        layer->setContentBounds(layer->bounds());
+    }
 
-    occlusion.enterTargetRenderSurface(layer->renderSurface());
+    // These hold ownership of the layers for the duration of the test.
+    typename Types::LayerPtrType m_root;
+    Vector<RefPtr<LayerChromium> > m_renderSurfaceLayerListChromium;
+    Vector<CCLayerImpl*> m_renderSurfaceLayerListImpl;
+};
 
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
+#define RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \
+    class ClassName##MainThreadOpaqueLayers : public ClassName<CCOcclusionTrackerTestMainThreadTypes, true> { }; \
+    TEST_F(ClassName##MainThreadOpaqueLayers, runTest) { runMyTest(); }
+#define RUN_TEST_MAIN_THREAD_OPAQUE_PAINTS(ClassName) \
+    class ClassName##MainThreadOpaquePaints : public ClassName<CCOcclusionTrackerTestMainThreadTypes, false> { }; \
+    TEST_F(ClassName##MainThreadOpaquePaints, runTest) { runMyTest(); }
+
+#define RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) \
+    class ClassName##ImplThreadOpaqueLayers : public ClassName<CCOcclusionTrackerTestImplThreadTypes, true> { \
+        DebugScopedSetImplThread impl; \
+    }; \
+    TEST_F(ClassName##ImplThreadOpaqueLayers, runTest) { runMyTest(); }
+#define RUN_TEST_IMPL_THREAD_OPAQUE_PAINTS(ClassName) \
+    class ClassName##ImplThreadOpaquePaints : public ClassName<CCOcclusionTrackerTestImplThreadTypes, false> { \
+        DebugScopedSetImplThread impl; \
+    }; \
+    TEST_F(ClassName##ImplThreadOpaquePaints, runTest) { runMyTest(); }
+
+#define ALL_CCOCCLUSIONTRACKER_TEST(ClassName) \
+    RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \
+    RUN_TEST_MAIN_THREAD_OPAQUE_PAINTS(ClassName) \
+    RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) \
+    RUN_TEST_IMPL_THREAD_OPAQUE_PAINTS(ClassName)
+
+#define MAIN_AND_IMPL_THREAD_TEST(ClassName) \
+    RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \
+    RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName)
+
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestIdentityTransforms : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+        typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(30, 30), IntSize(500, 500), true);
+        this->calcDrawEtc(parent);
 
-    // Occluded since its outside the surface bounds.
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(200, 100, 100, 100)));
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
 
-    // Test without any scissors.
-    occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(200, 100, 100, 100)));
-    occlusion.useDefaultLayerScissorRect();
+        occlusion.enterTargetRenderSurface(parent->renderSurface());
+        occlusion.markOccludedBehindLayer(layer);
+        EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 30, 70, 70)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 30, 70, 70)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 29, 70, 70)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(31, 30, 70, 70)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 31, 70, 70)));
+
+        occlusion.useDefaultLayerScissorRect();
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 30, 70, 70)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 30, 70, 70)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 29, 70, 70)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(31, 30, 70, 70)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 31, 70, 70)));
+        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(30, 30, 70, 70)).isEmpty());
+        EXPECT_EQ_RECT(IntRect(29, 30, 1, 70), occlusion.unoccludedContentRect(parent, IntRect(29, 30, 70, 70)));
+        EXPECT_EQ_RECT(IntRect(29, 29, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(29, 29, 70, 70)));
+        EXPECT_EQ_RECT(IntRect(30, 29, 70, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 29, 70, 70)));
+        EXPECT_EQ_RECT(IntRect(31, 29, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(31, 29, 70, 70)));
+        EXPECT_EQ_RECT(IntRect(100, 30, 1, 70), occlusion.unoccludedContentRect(parent, IntRect(31, 30, 70, 70)));
+        EXPECT_EQ_RECT(IntRect(31, 31, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(31, 31, 70, 70)));
+        EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 31, 70, 70)));
+        EXPECT_EQ_RECT(IntRect(29, 31, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(29, 31, 70, 70)));
+    }
+};
 
-    occlusion.markOccludedBehindLayer(layer.get());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-    occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestIdentityTransforms);
 
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestRotatedChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        TransformationMatrix layerTransform;
+        layerTransform.translate(250, 250);
+        layerTransform.rotate(90);
+        layerTransform.translate(-250, -250);
 
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+        typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, layerTransform, FloatPoint(30, 30), IntSize(500, 500), true);
+        this->calcDrawEtc(parent);
 
-    EXPECT_EQ_RECT(IntRect(200, 100, 100, 100), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)));
-}
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
 
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_screenScissorRectOverTile, screenScissorRectOverTile);
+        occlusion.enterTargetRenderSurface(parent->renderSurface());
+        occlusion.markOccludedBehindLayer(layer);
+        EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 30, 70, 70)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 30, 70, 70)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 29, 70, 70)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(31, 30, 70, 70)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 31, 70, 70)));
+
+        occlusion.useDefaultLayerScissorRect();
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 30, 70, 70)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 30, 70, 70)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 29, 70, 70)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(31, 30, 70, 70)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 31, 70, 70)));
+        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(30, 30, 70, 70)).isEmpty());
+        EXPECT_EQ_RECT(IntRect(29, 30, 1, 70), occlusion.unoccludedContentRect(parent, IntRect(29, 30, 70, 70)));
+        EXPECT_EQ_RECT(IntRect(29, 29, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(29, 29, 70, 70)));
+        EXPECT_EQ_RECT(IntRect(30, 29, 70, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 29, 70, 70)));
+        EXPECT_EQ_RECT(IntRect(31, 29, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(31, 29, 70, 70)));
+        EXPECT_EQ_RECT(IntRect(100, 30, 1, 70), occlusion.unoccludedContentRect(parent, IntRect(31, 30, 70, 70)));
+        EXPECT_EQ_RECT(IntRect(31, 31, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(31, 31, 70, 70)));
+        EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 31, 70, 70)));
+        EXPECT_EQ_RECT(IntRect(29, 31, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(29, 31, 70, 70)));
+    }
+};
 
-void layerScissorRectOverCulledTile(bool opaqueLayers)
-{
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(parentLayer);
-    parent->addChild(layer);
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestRotatedChild);
 
-    FilterOperations filters;
-    filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
-    parentLayer->setFilters(filters);
-    layer->setFilters(filters);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestTranslatedChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        TransformationMatrix layerTransform;
+        layerTransform.translate(20, 20);
 
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
-    setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
-    setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+        typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, layerTransform, FloatPoint(30, 30), IntSize(500, 500), true);
+        this->calcDrawEtc(parent);
 
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
 
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
+        occlusion.enterTargetRenderSurface(parent->renderSurface());
+        occlusion.markOccludedBehindLayer(layer);
+        EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), occlusion.occlusionInScreenSpace().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), occlusion.occlusionInTargetSurface().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(50, 50, 50, 50)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(49, 50, 50, 50)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(50, 49, 50, 50)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(51, 50, 50, 50)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(50, 51, 50, 50)));
+
+        occlusion.useDefaultLayerScissorRect();
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(50, 50, 50, 50)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(49, 50, 50, 50)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(50, 49, 50, 50)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(51, 50, 50, 50)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(50, 51, 50, 50)));
+        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(50, 50, 50, 50)).isEmpty());
+        EXPECT_EQ_RECT(IntRect(49, 50, 1, 50), occlusion.unoccludedContentRect(parent, IntRect(49, 50, 50, 50)));
+        EXPECT_EQ_RECT(IntRect(49, 49, 50, 50), occlusion.unoccludedContentRect(parent, IntRect(49, 49, 50, 50)));
+        EXPECT_EQ_RECT(IntRect(50, 49, 50, 1), occlusion.unoccludedContentRect(parent, IntRect(50, 49, 50, 50)));
+        EXPECT_EQ_RECT(IntRect(51, 49, 50, 50), occlusion.unoccludedContentRect(parent, IntRect(51, 49, 50, 50)));
+        EXPECT_EQ_RECT(IntRect(100, 50, 1, 50), occlusion.unoccludedContentRect(parent, IntRect(51, 50, 50, 50)));
+        EXPECT_EQ_RECT(IntRect(51, 51, 50, 50), occlusion.unoccludedContentRect(parent, IntRect(51, 51, 50, 50)));
+        EXPECT_EQ_RECT(IntRect(50, 100, 50, 1), occlusion.unoccludedContentRect(parent, IntRect(50, 51, 50, 50)));
+        EXPECT_EQ_RECT(IntRect(49, 51, 50, 50), occlusion.unoccludedContentRect(parent, IntRect(49, 51, 50, 50)));
+
+        occlusion.useDefaultLayerScissorRect();
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(50, 50, 50, 50)).isEmpty());
+        EXPECT_EQ_RECT(IntRect(49, 50, 1, 50), occlusion.unoccludedContentRect(parent, IntRect(49, 50, 50, 50)));
+        EXPECT_EQ_RECT(IntRect(49, 49, 50, 50), occlusion.unoccludedContentRect(parent, IntRect(49, 49, 50, 50)));
+        EXPECT_EQ_RECT(IntRect(50, 49, 50, 1), occlusion.unoccludedContentRect(parent, IntRect(50, 49, 50, 50)));
+        EXPECT_EQ_RECT(IntRect(51, 49, 49, 1), occlusion.unoccludedContentRect(parent, IntRect(51, 49, 50, 50)));
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(51, 50, 50, 50)).isEmpty());
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(51, 51, 50, 50)).isEmpty());
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(50, 51, 50, 50)).isEmpty());
+        EXPECT_EQ_RECT(IntRect(49, 51, 1, 49), occlusion.unoccludedContentRect(parent, IntRect(49, 51, 50, 50)));
+        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+    }
+};
 
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestTranslatedChild);
 
-    TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
-    occlusion.setLayerScissorRect(IntRect(100, 100, 100, 100));
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestChildInRotatedChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        TransformationMatrix childTransform;
+        childTransform.translate(250, 250);
+        childTransform.rotate(90);
+        childTransform.translate(-250, -250);
 
-    occlusion.enterTargetRenderSurface(layer->renderSurface());
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+        typename Types::LayerType* child = this->createLayer(parent, childTransform, FloatPoint(30, 30), IntSize(500, 500));
+        child->setMasksToBounds(true);
+        typename Types::ContentLayerType* layer = this->createDrawingLayer(child, this->identityMatrix, FloatPoint(10, 10), IntSize(500, 500), true);
+        this->calcDrawEtc(parent);
 
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
 
-    occlusion.markOccludedBehindLayer(layer.get());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-    occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
+        occlusion.enterTargetRenderSurface(child->renderSurface());
+        occlusion.markOccludedBehindLayer(layer);
 
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
+        EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_EQ_RECT(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+        EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 430, 60, 70)));
+        EXPECT_FALSE(occlusion.occluded(child, IntRect(9, 430, 60, 70)));
+        EXPECT_FALSE(occlusion.occluded(child, IntRect(10, 429, 60, 70)));
+        EXPECT_FALSE(occlusion.occluded(child, IntRect(10, 430, 61, 70)));
+        EXPECT_FALSE(occlusion.occluded(child, IntRect(10, 430, 60, 71)));
+
+        occlusion.useDefaultLayerScissorRect();
+        EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 430, 60, 70)));
+        EXPECT_TRUE(occlusion.occluded(child, IntRect(9, 430, 60, 70)));
+        EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 429, 60, 70)));
+        EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 430, 61, 70)));
+        EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 430, 60, 71)));
+        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+        occlusion.markOccludedBehindLayer(child);
+        occlusion.finishedTargetRenderSurface(child, child->renderSurface());
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+
+        EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInTargetSurface().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 40, 70, 60)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 40, 70, 60)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 39, 70, 60)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(31, 40, 70, 60)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 41, 70, 60)));
+
+        occlusion.useDefaultLayerScissorRect();
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 40, 70, 60)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 40, 70, 60)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 39, 70, 60)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(31, 40, 70, 60)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 41, 70, 60)));
+        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+
+        /* Justification for the above occlusion from |layer|:
+                   100
+          +---------------------+                                      +---------------------+
+          |                     |                                      |                     |30  Visible region of |layer|: /////
+          |    30               |           rotate(90)                 |                     |
+          | 30 + ---------------------------------+                    |     +---------------------------------+
+      100 |    |  10            |                 |            ==>     |     |               |10               |
+          |    |10+---------------------------------+                  |  +---------------------------------+  |
+          |    |  |             |                 | |                  |  |  |///////////////|     420      |  |
+          |    |  |             |                 | |                  |  |  |///////////////|60            |  |
+          |    |  |             |                 | |                  |  |  |///////////////|              |  |
+          +----|--|-------------+                 | |                  +--|--|---------------+              |  |
+               |  |                               | |                   20|10|     70                       |  |
+               |  |                               | |                     |  |                              |  |
+               |  |                               | |500                  |  |                              |  |
+               |  |                               | |                     |  |                              |  |
+               |  |                               | |                     |  |                              |  |
+               |  |                               | |                     |  |                              |  |
+               |  |                               | |                     |  |                              |10|
+               +--|-------------------------------+ |                     |  +------------------------------|--+
+                  |                                 |                     |                 490             |
+                  +---------------------------------+                     +---------------------------------+
+                                 500                                                     500
+         */
+    }
+};
 
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestChildInRotatedChild);
 
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)).isEmpty());
-}
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestVisitTargetTwoTimes : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        TransformationMatrix childTransform;
+        childTransform.translate(250, 250);
+        childTransform.rotate(90);
+        childTransform.translate(-250, -250);
+
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+        typename Types::LayerType* child = this->createLayer(parent, childTransform, FloatPoint(30, 30), IntSize(500, 500));
+        child->setMasksToBounds(true);
+        typename Types::ContentLayerType* layer = this->createDrawingLayer(child, this->identityMatrix, FloatPoint(10, 10), IntSize(500, 500), true);
+        // |child2| makes |parent|'s surface get considered by CCOcclusionTracker first, instead of |child|'s. This exercises different code in
+        // leaveToTargetRenderSurface, as the target surface has already been seen.
+        typename Types::ContentLayerType* child2 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(30, 30), IntSize(60, 20), true);
+        this->calcDrawEtc(parent);
+
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+        occlusion.setLayerScissorRect(IntRect(-10, -10, 1000, 1000));
 
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerScissorRectOverCulledTile, layerScissorRectOverCulledTile);
+        occlusion.enterTargetRenderSurface(parent->renderSurface());
+        occlusion.markOccludedBehindLayer(child2);
 
-void screenScissorRectOverCulledTile(bool opaqueLayers)
-{
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(parentLayer);
-    parent->addChild(layer);
+        EXPECT_EQ_RECT(IntRect(30, 30, 60, 20), occlusion.occlusionInScreenSpace().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_EQ_RECT(IntRect(30, 30, 60, 20), occlusion.occlusionInTargetSurface().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+        occlusion.enterTargetRenderSurface(child->renderSurface());
+        occlusion.markOccludedBehindLayer(layer);
+
+        EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
+        EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_EQ_RECT(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+        EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 430, 60, 70)));
+        EXPECT_FALSE(occlusion.occluded(child, IntRect(9, 430, 60, 70)));
+        EXPECT_FALSE(occlusion.occluded(child, IntRect(10, 429, 60, 70)));
+        EXPECT_FALSE(occlusion.occluded(child, IntRect(11, 430, 60, 70)));
+        EXPECT_FALSE(occlusion.occluded(child, IntRect(10, 431, 60, 70)));
+
+        occlusion.useDefaultLayerScissorRect();
+        EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 430, 60, 70)));
+        EXPECT_TRUE(occlusion.occluded(child, IntRect(9, 430, 60, 70)));
+        EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 429, 60, 70)));
+        EXPECT_TRUE(occlusion.occluded(child, IntRect(11, 430, 60, 70)));
+        EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 431, 60, 70)));
+        occlusion.setLayerScissorRect(IntRect(-10, -10, 1000, 1000));
+
+        EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(10, 430, 60, 70)).isEmpty());
+        // This is the little piece not occluded by child2
+        EXPECT_EQ_RECT(IntRect(9, 430, 1, 10), occlusion.unoccludedContentRect(child, IntRect(9, 430, 60, 70)));
+        // This extends past both sides of child2, so it will be the original rect.
+        EXPECT_EQ_RECT(IntRect(9, 430, 60, 80), occlusion.unoccludedContentRect(child, IntRect(9, 430, 60, 80)));
+        // This extends past two adjacent sides of child2, and should included the unoccluded parts of each side.
+        // This also demonstrates that the rect can be arbitrary and does not get clipped to the layer's visibleLayerRect().
+        EXPECT_EQ_RECT(IntRect(-10, 430, 20, 70), occlusion.unoccludedContentRect(child, IntRect(-10, 430, 60, 70)));
+        // This extends past three adjacent sides of child2, so it should contain the unoccluded parts of each side. The left
+        // and bottom edges are completely unoccluded for some row/column so we get back the original query rect.
+        EXPECT_EQ_RECT(IntRect(-10, 430, 60, 80), occlusion.unoccludedContentRect(child, IntRect(-10, 430, 60, 80)));
+        EXPECT_EQ_RECT(IntRect(10, 429, 60, 1), occlusion.unoccludedContentRect(child, IntRect(10, 429, 60, 70)));
+        EXPECT_EQ_RECT(IntRect(70, 430, 1, 70), occlusion.unoccludedContentRect(child, IntRect(11, 430, 60, 70)));
+        EXPECT_EQ_RECT(IntRect(10, 500, 60, 1), occlusion.unoccludedContentRect(child, IntRect(10, 431, 60, 70)));
+
+        occlusion.useDefaultLayerScissorRect();
+        EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(10, 430, 60, 70)).isEmpty());
+        EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(9, 430, 60, 70)).isEmpty());
+        EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(9, 430, 60, 80)).isEmpty());
+        EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(-10, 430, 60, 70)).isEmpty());
+        EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(-10, 430, 60, 80)).isEmpty());
+        EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(10, 429, 60, 70)).isEmpty());
+        EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(11, 430, 60, 70)).isEmpty());
+        EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(10, 431, 60, 70)).isEmpty());
+        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+        occlusion.markOccludedBehindLayer(child);
+        // |child2| should get merged with the surface we are leaving now
+        occlusion.finishedTargetRenderSurface(child, child->renderSurface());
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+
+        EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
+        EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
+        EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
+
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 30, 70, 70)));
+        EXPECT_EQ_RECT(IntRect(90, 30, 10, 10), occlusion.unoccludedContentRect(parent, IntRect(30, 30, 70, 70)));
+
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 30, 60, 10)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 30, 60, 10)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 29, 60, 10)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(31, 30, 60, 10)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 31, 60, 10)));
+
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 40, 70, 60)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 40, 70, 60)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 39, 70, 60)));
+
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(30, 30, 60, 10)).isEmpty());
+        EXPECT_EQ_RECT(IntRect(29, 30, 1, 10), occlusion.unoccludedContentRect(parent, IntRect(29, 30, 60, 10)));
+        EXPECT_EQ_RECT(IntRect(30, 29, 60, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 29, 60, 10)));
+        EXPECT_EQ_RECT(IntRect(90, 30, 1, 10), occlusion.unoccludedContentRect(parent, IntRect(31, 30, 60, 10)));
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(30, 31, 60, 10)).isEmpty());
+
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(30, 40, 70, 60)).isEmpty());
+        EXPECT_EQ_RECT(IntRect(29, 40, 1, 60), occlusion.unoccludedContentRect(parent, IntRect(29, 40, 70, 60)));
+        // This rect is mostly occluded by |child2|.
+        EXPECT_EQ_RECT(IntRect(90, 39, 10, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 39, 70, 60)));
+        // This rect extends past top/right ends of |child2|.
+        EXPECT_EQ_RECT(IntRect(30, 29, 70, 11), occlusion.unoccludedContentRect(parent, IntRect(30, 29, 70, 70)));
+        // This rect extends past left/right ends of |child2|.
+        EXPECT_EQ_RECT(IntRect(20, 39, 80, 60), occlusion.unoccludedContentRect(parent, IntRect(20, 39, 80, 60)));
+        EXPECT_EQ_RECT(IntRect(100, 40, 1, 60), occlusion.unoccludedContentRect(parent, IntRect(31, 40, 70, 60)));
+        EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 41, 70, 60)));
+
+        /* Justification for the above occlusion from |layer|:
+                   100
+          +---------------------+                                      +---------------------+
+          |                     |                                      |                     |30  Visible region of |layer|: /////
+          |    30               |           rotate(90)                 |     30   60         |    |child2|: \\\\\
+          | 30 + ------------+--------------------+                    |  30 +------------+--------------------+
+      100 |    |  10         |  |                 |            ==>     |     |\\\\\\\\\\\\|  |10               |
+          |    |10+----------|----------------------+                  |  +--|\\\\\\\\\\\\|-----------------+  |
+          |    + ------------+  |                 | |                  |  |  +------------+//|     420      |  |
+          |    |  |             |                 | |                  |  |  |///////////////|60            |  |
+          |    |  |             |                 | |                  |  |  |///////////////|              |  |
+          +----|--|-------------+                 | |                  +--|--|---------------+              |  |
+               |  |                               | |                   20|10|     70                       |  |
+               |  |                               | |                     |  |                              |  |
+               |  |                               | |500                  |  |                              |  |
+               |  |                               | |                     |  |                              |  |
+               |  |                               | |                     |  |                              |  |
+               |  |                               | |                     |  |                              |  |
+               |  |                               | |                     |  |                              |10|
+               +--|-------------------------------+ |                     |  +------------------------------|--+
+                  |                                 |                     |                 490             |
+                  +---------------------------------+                     +---------------------------------+
+                                 500                                                     500
+         */
+    }
+};
+
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestVisitTargetTwoTimes);
 
-    FilterOperations filters;
-    filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
-    parentLayer->setFilters(filters);
-    layer->setFilters(filters);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestSurfaceRotatedOffAxis : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        TransformationMatrix childTransform;
+        childTransform.translate(250, 250);
+        childTransform.rotate(95);
+        childTransform.translate(-250, -250);
+
+        TransformationMatrix layerTransform;
+        layerTransform.translate(10, 10);
+
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+        typename Types::LayerType* child = this->createLayer(parent, childTransform, FloatPoint(30, 30), IntSize(500, 500));
+        child->setMasksToBounds(true);
+        typename Types::ContentLayerType* layer = this->createDrawingLayer(child, layerTransform, FloatPoint(0, 0), IntSize(500, 500), true);
+        this->calcDrawEtc(parent);
+
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+        IntRect clippedLayerInChild = layerTransform.mapRect(layer->visibleLayerRect());
+
+        occlusion.enterTargetRenderSurface(child->renderSurface());
+        occlusion.markOccludedBehindLayer(layer);
+
+        EXPECT_EQ_RECT(IntRect(), occlusion.occlusionInScreenSpace().bounds());
+        EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_EQ_RECT(clippedLayerInChild, occlusion.occlusionInTargetSurface().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+        EXPECT_TRUE(occlusion.occluded(child, clippedLayerInChild));
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, clippedLayerInChild).isEmpty());
+        clippedLayerInChild.move(-1, 0);
+        EXPECT_FALSE(occlusion.occluded(child, clippedLayerInChild));
+        EXPECT_FALSE(occlusion.unoccludedContentRect(parent, clippedLayerInChild).isEmpty());
+        clippedLayerInChild.move(1, 0);
+        clippedLayerInChild.move(1, 0);
+        EXPECT_FALSE(occlusion.occluded(child, clippedLayerInChild));
+        EXPECT_FALSE(occlusion.unoccludedContentRect(parent, clippedLayerInChild).isEmpty());
+        clippedLayerInChild.move(-1, 0);
+        clippedLayerInChild.move(0, -1);
+        EXPECT_FALSE(occlusion.occluded(child, clippedLayerInChild));
+        EXPECT_FALSE(occlusion.unoccludedContentRect(parent, clippedLayerInChild).isEmpty());
+        clippedLayerInChild.move(0, 1);
+        clippedLayerInChild.move(0, 1);
+        EXPECT_FALSE(occlusion.occluded(child, clippedLayerInChild));
+        EXPECT_FALSE(occlusion.unoccludedContentRect(parent, clippedLayerInChild).isEmpty());
+        clippedLayerInChild.move(0, -1);
+
+        occlusion.markOccludedBehindLayer(child);
+        occlusion.finishedTargetRenderSurface(child, child->renderSurface());
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+
+        EXPECT_EQ_RECT(IntRect(), occlusion.occlusionInScreenSpace().bounds());
+        EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_EQ_RECT(IntRect(), occlusion.occlusionInTargetSurface().bounds());
+        EXPECT_EQ(0u, occlusion.occlusionInTargetSurface().rects().size());
+
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(75, 55, 1, 1)));
+        EXPECT_EQ_RECT(IntRect(75, 55, 1, 1), occlusion.unoccludedContentRect(parent, IntRect(75, 55, 1, 1)));
+    }
+};
 
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
-    setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
-    setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestSurfaceRotatedOffAxis);
 
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestSurfaceWithTwoOpaqueChildren : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        TransformationMatrix childTransform;
+        childTransform.translate(250, 250);
+        childTransform.rotate(90);
+        childTransform.translate(-250, -250);
+
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+        typename Types::LayerType* child = this->createLayer(parent, childTransform, FloatPoint(30, 30), IntSize(500, 500));
+        child->setMasksToBounds(true);
+        typename Types::ContentLayerType* layer1 = this->createDrawingLayer(child, this->identityMatrix, FloatPoint(10, 10), IntSize(500, 500), true);
+        typename Types::ContentLayerType* layer2 = this->createDrawingLayer(child, this->identityMatrix, FloatPoint(10, 450), IntSize(500, 60), true);
+        this->calcDrawEtc(parent);
+
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+        occlusion.enterTargetRenderSurface(child->renderSurface());
+        occlusion.markOccludedBehindLayer(layer2);
+        occlusion.markOccludedBehindLayer(layer1);
+
+        EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_EQ_RECT(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+        EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 430, 60, 70)));
+        EXPECT_FALSE(occlusion.occluded(child, IntRect(9, 430, 60, 70)));
+        EXPECT_FALSE(occlusion.occluded(child, IntRect(10, 429, 60, 70)));
+        EXPECT_FALSE(occlusion.occluded(child, IntRect(11, 430, 60, 70)));
+        EXPECT_FALSE(occlusion.occluded(child, IntRect(10, 431, 60, 70)));
+
+        EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(10, 430, 60, 70)).isEmpty());
+        EXPECT_EQ_RECT(IntRect(9, 430, 1, 70), occlusion.unoccludedContentRect(child, IntRect(9, 430, 60, 70)));
+        EXPECT_EQ_RECT(IntRect(10, 429, 60, 1), occlusion.unoccludedContentRect(child, IntRect(10, 429, 60, 70)));
+        EXPECT_EQ_RECT(IntRect(70, 430, 1, 70), occlusion.unoccludedContentRect(child, IntRect(11, 430, 60, 70)));
+        EXPECT_EQ_RECT(IntRect(10, 500, 60, 1), occlusion.unoccludedContentRect(child, IntRect(10, 431, 60, 70)));
+
+        occlusion.markOccludedBehindLayer(child);
+        occlusion.finishedTargetRenderSurface(child, child->renderSurface());
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+
+        EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInTargetSurface().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 40, 70, 60)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 40, 70, 60)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 39, 70, 60)));
+
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(30, 40, 70, 60)).isEmpty());
+        EXPECT_EQ_RECT(IntRect(29, 40, 1, 60), occlusion.unoccludedContentRect(parent, IntRect(29, 40, 70, 60)));
+        EXPECT_EQ_RECT(IntRect(30, 39, 70, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 39, 70, 60)));
+        EXPECT_EQ_RECT(IntRect(100, 40, 1, 60), occlusion.unoccludedContentRect(parent, IntRect(31, 40, 70, 60)));
+        EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 41, 70, 60)));
+
+        /* Justification for the above occlusion from |layer1| and |layer2|:
+
+           +---------------------+
+           |                     |30  Visible region of |layer1|: /////
+           |                     |    Visible region of |layer2|: \\\\\
+           |     +---------------------------------+
+           |     |               |10               |
+           |  +---------------+-----------------+  |
+           |  |  |\\\\\\\\\\\\|//|     420      |  |
+           |  |  |\\\\\\\\\\\\|//|60            |  |
+           |  |  |\\\\\\\\\\\\|//|              |  |
+           +--|--|------------|--+              |  |
+            20|10|     70     |                 |  |
+              |  |            |                 |  |
+              |  |            |                 |  |
+              |  |            |                 |  |
+              |  |            |                 |  |
+              |  |            |                 |  |
+              |  |            |                 |10|
+              |  +------------|-----------------|--+
+              |               | 490             |
+              +---------------+-----------------+
+                     60               440
+         */
+    }
+};
 
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestSurfaceWithTwoOpaqueChildren);
 
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestOverlappingSurfaceSiblings : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        TransformationMatrix childTransform;
+        childTransform.translate(250, 250);
+        childTransform.rotate(90);
+        childTransform.translate(-250, -250);
 
-    TestCCOcclusionTracker occlusion(IntRect(100, 100, 100, 100));
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+        typename Types::LayerType* child1 = this->createSurface(parent, childTransform, FloatPoint(30, 30), IntSize(10, 10));
+        typename Types::LayerType* child2 = this->createSurface(parent, childTransform, FloatPoint(20, 40), IntSize(10, 10));
+        typename Types::ContentLayerType* layer1 = this->createDrawingLayer(child1, this->identityMatrix, FloatPoint(-10, -10), IntSize(510, 510), true);
+        typename Types::ContentLayerType* layer2 = this->createDrawingLayer(child2, this->identityMatrix, FloatPoint(-10, -10), IntSize(510, 510), true);
+        this->calcDrawEtc(parent);
 
-    occlusion.enterTargetRenderSurface(layer->renderSurface());
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+        occlusion.setLayerScissorRect(IntRect(-20, -20, 1000, 1000));
 
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
+        occlusion.enterTargetRenderSurface(child2->renderSurface());
+        occlusion.markOccludedBehindLayer(layer2);
 
-    occlusion.markOccludedBehindLayer(layer.get());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-    occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
+        EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInScreenSpace().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_EQ_RECT(IntRect(-10, 420, 70, 80), occlusion.occlusionInTargetSurface().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+        EXPECT_TRUE(occlusion.occluded(child2, IntRect(-10, 420, 70, 80)));
+        EXPECT_FALSE(occlusion.occluded(child2, IntRect(-11, 420, 70, 80)));
+        EXPECT_FALSE(occlusion.occluded(child2, IntRect(-10, 419, 70, 80)));
+        EXPECT_FALSE(occlusion.occluded(child2, IntRect(-10, 420, 71, 80)));
+        EXPECT_FALSE(occlusion.occluded(child2, IntRect(-10, 420, 70, 81)));
+
+        occlusion.useDefaultLayerScissorRect();
+        EXPECT_TRUE(occlusion.occluded(child2, IntRect(-10, 420, 70, 80)));
+        EXPECT_TRUE(occlusion.occluded(child2, IntRect(-11, 420, 70, 80)));
+        EXPECT_TRUE(occlusion.occluded(child2, IntRect(-10, 419, 70, 80)));
+        EXPECT_TRUE(occlusion.occluded(child2, IntRect(-10, 420, 71, 80)));
+        EXPECT_TRUE(occlusion.occluded(child2, IntRect(-10, 420, 70, 81)));
+        occlusion.setLayerScissorRect(IntRect(-20, -20, 1000, 1000));
+
+        occlusion.markOccludedBehindLayer(child2);
+        occlusion.finishedTargetRenderSurface(child2, child2->renderSurface());
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+        occlusion.enterTargetRenderSurface(child1->renderSurface());
+        occlusion.markOccludedBehindLayer(layer1);
+
+        EXPECT_EQ_RECT(IntRect(20, 20, 80, 80), occlusion.occlusionInScreenSpace().bounds());
+        EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_EQ_RECT(IntRect(-10, 430, 80, 70), occlusion.occlusionInTargetSurface().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+        EXPECT_TRUE(occlusion.occluded(child1, IntRect(-10, 430, 80, 70)));
+        EXPECT_FALSE(occlusion.occluded(child1, IntRect(-11, 430, 80, 70)));
+        EXPECT_FALSE(occlusion.occluded(child1, IntRect(-10, 429, 80, 70)));
+        EXPECT_FALSE(occlusion.occluded(child1, IntRect(-10, 430, 81, 70)));
+        EXPECT_FALSE(occlusion.occluded(child1, IntRect(-10, 430, 80, 71)));
+
+        occlusion.markOccludedBehindLayer(child1);
+        occlusion.finishedTargetRenderSurface(child1, child1->renderSurface());
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+
+        EXPECT_EQ_RECT(IntRect(20, 20, 80, 80), occlusion.occlusionInScreenSpace().bounds());
+        EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_EQ_RECT(IntRect(20, 20, 80, 80), occlusion.occlusionInTargetSurface().bounds());
+        EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
+
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(20, 20, 80, 80)));
+
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 20, 70, 80)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 20, 70, 80)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 19, 70, 80)));
+
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(20, 30, 80, 70)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(19, 30, 80, 70)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(20, 29, 80, 70)));
+
+        /* Justification for the above occlusion:
+                   100
+          +---------------------+
+          |    20               |       layer1
+          |  30+ ---------------------------------+
+      100 |  30|                |     layer2      |
+          |20+----------------------------------+ |
+          |  | |                |               | |
+          |  | |                |               | |
+          |  | |                |               | |
+          +--|-|----------------+               | |
+             | |                                | | 510
+             | |                                | |
+             | |                                | |
+             | |                                | |
+             | |                                | |
+             | |                                | |
+             | |                                | |
+             | +--------------------------------|-+
+             |                                  |
+             +----------------------------------+
+                             510
+         */
+    }
+};
 
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestOverlappingSurfaceSiblings);
 
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        TransformationMatrix child1Transform;
+        child1Transform.translate(250, 250);
+        child1Transform.rotate(-90);
+        child1Transform.translate(-250, -250);
+
+        TransformationMatrix child2Transform;
+        child2Transform.translate(250, 250);
+        child2Transform.rotate(90);
+        child2Transform.translate(-250, -250);
+
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+        typename Types::LayerType* child1 = this->createSurface(parent, child1Transform, FloatPoint(30, 20), IntSize(10, 10));
+        typename Types::LayerType* child2 = this->createSurface(parent, child2Transform, FloatPoint(20, 40), IntSize(10, 10));
+        typename Types::ContentLayerType* layer1 = this->createDrawingLayer(child1, this->identityMatrix, FloatPoint(-10, -20), IntSize(510, 510), true);
+        typename Types::ContentLayerType* layer2 = this->createDrawingLayer(child2, this->identityMatrix, FloatPoint(-10, -10), IntSize(510, 510), true);
+        this->calcDrawEtc(parent);
+
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+        occlusion.setLayerScissorRect(IntRect(-30, -30, 1000, 1000));
+
+        occlusion.enterTargetRenderSurface(child2->renderSurface());
+        occlusion.markOccludedBehindLayer(layer2);
+
+        EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInScreenSpace().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_EQ_RECT(IntRect(-10, 420, 70, 80), occlusion.occlusionInTargetSurface().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+        EXPECT_TRUE(occlusion.occluded(child2, IntRect(-10, 420, 70, 80)));
+        EXPECT_FALSE(occlusion.occluded(child2, IntRect(-11, 420, 70, 80)));
+        EXPECT_FALSE(occlusion.occluded(child2, IntRect(-10, 419, 70, 80)));
+        EXPECT_FALSE(occlusion.occluded(child2, IntRect(-10, 420, 71, 80)));
+        EXPECT_FALSE(occlusion.occluded(child2, IntRect(-10, 420, 70, 81)));
+
+        occlusion.markOccludedBehindLayer(child2);
+        occlusion.finishedTargetRenderSurface(child2, child2->renderSurface());
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+        occlusion.enterTargetRenderSurface(child1->renderSurface());
+        occlusion.markOccludedBehindLayer(layer1);
+
+        EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), occlusion.occlusionInScreenSpace().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_EQ_RECT(IntRect(420, -20, 80, 90), occlusion.occlusionInTargetSurface().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
 
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)).isEmpty());
-}
+        EXPECT_TRUE(occlusion.occluded(child1, IntRect(420, -20, 80, 90)));
+        EXPECT_FALSE(occlusion.occluded(child1, IntRect(419, -20, 80, 90)));
+        EXPECT_FALSE(occlusion.occluded(child1, IntRect(420, -21, 80, 90)));
+        EXPECT_FALSE(occlusion.occluded(child1, IntRect(420, -19, 80, 90)));
+        EXPECT_FALSE(occlusion.occluded(child1, IntRect(421, -20, 80, 90)));
 
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_screenScissorRectOverCulledTile, screenScissorRectOverCulledTile);
+        occlusion.markOccludedBehindLayer(child1);
+        occlusion.finishedTargetRenderSurface(child1, child1->renderSurface());
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
 
-void layerScissorRectOverPartialTiles(bool opaqueLayers)
-{
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(parentLayer);
-    parent->addChild(layer);
-
-    FilterOperations filters;
-    filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
-    parentLayer->setFilters(filters);
-    layer->setFilters(filters);
-
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
-    setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
-    setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
-
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
-
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
-
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
-    TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
-    occlusion.setLayerScissorRect(IntRect(50, 50, 200, 200));
-
-    occlusion.enterTargetRenderSurface(layer->renderSurface());
-
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
-
-    occlusion.markOccludedBehindLayer(layer.get());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-    occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
-
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 100, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
-
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
-    EXPECT_EQ_RECT(IntRect(50, 50, 200, 200), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)));
-    EXPECT_EQ_RECT(IntRect(200, 50, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 100)));
-    EXPECT_EQ_RECT(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 100, 300, 100)));
-    EXPECT_EQ_RECT(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent.get(), IntRect(200, 100, 100, 100)));
-    EXPECT_EQ_RECT(IntRect(100, 200, 100, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(100, 200, 100, 100)));
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerScissorRectOverPartialTiles, layerScissorRectOverPartialTiles);
-
-void screenScissorRectOverPartialTiles(bool opaqueLayers)
-{
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(parentLayer);
-    parent->addChild(layer);
-
-    FilterOperations filters;
-    filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
-    parentLayer->setFilters(filters);
-    layer->setFilters(filters);
-
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
-    setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
-    setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
-
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
-
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
-
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
-    TestCCOcclusionTracker occlusion(IntRect(50, 50, 200, 200));
-
-    occlusion.enterTargetRenderSurface(layer->renderSurface());
-
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
-
-    occlusion.markOccludedBehindLayer(layer.get());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-    occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
-
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 100, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
-
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
-    EXPECT_EQ_RECT(IntRect(50, 50, 200, 200), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)));
-    EXPECT_EQ_RECT(IntRect(200, 50, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 100)));
-    EXPECT_EQ_RECT(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 100, 300, 100)));
-    EXPECT_EQ_RECT(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent.get(), IntRect(200, 100, 100, 100)));
-    EXPECT_EQ_RECT(IntRect(100, 200, 100, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(100, 200, 100, 100)));
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_screenScissorRectOverPartialTiles, screenScissorRectOverPartialTiles);
-
-void layerScissorRectOverNoTiles(bool opaqueLayers)
-{
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(parentLayer);
-    parent->addChild(layer);
-
-    FilterOperations filters;
-    filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
-    parentLayer->setFilters(filters);
-    layer->setFilters(filters);
-
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
-    setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
-    setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
-
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
-
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
-
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
-    TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
-    occlusion.setLayerScissorRect(IntRect(500, 500, 100, 100));
-
-    occlusion.enterTargetRenderSurface(layer->renderSurface());
-
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
-
-    occlusion.markOccludedBehindLayer(layer.get());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-    occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
-
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
-
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)).isEmpty());
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 100)).isEmpty());
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 100, 300, 100)).isEmpty());
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(200, 100, 100, 100)).isEmpty());
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(100, 200, 100, 100)).isEmpty());
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerScissorRectOverNoTiles, layerScissorRectOverNoTiles);
-
-void screenScissorRectOverNoTiles(bool opaqueLayers)
-{
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(parentLayer);
-    parent->addChild(layer);
-
-    FilterOperations filters;
-    filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
-    parentLayer->setFilters(filters);
-    layer->setFilters(filters);
-
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
-    setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
-    setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
-
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
-
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
-
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
-    TestCCOcclusionTracker occlusion(IntRect(500, 500, 100, 100));
-
-    occlusion.enterTargetRenderSurface(layer->renderSurface());
-
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
-
-    occlusion.markOccludedBehindLayer(layer.get());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-    occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
-
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
-
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)).isEmpty());
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 100)).isEmpty());
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 100, 300, 100)).isEmpty());
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(200, 100, 100, 100)).isEmpty());
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(100, 200, 100, 100)).isEmpty());
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_screenScissorRectOverNoTiles, screenScissorRectOverNoTiles);
-
-void layerScissorRectForLayerOffOrigin(bool opaqueLayers)
-{
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(parentLayer);
-    parent->addChild(layer);
+        EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), occlusion.occlusionInScreenSpace().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), occlusion.occlusionInTargetSurface().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(10, 20, 90, 80)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(9, 20, 90, 80)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(10, 19, 90, 80)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(11, 20, 90, 80)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(10, 21, 90, 80)));
+
+        /* Justification for the above occlusion:
+                      100
+            +---------------------+
+            |20                   |       layer1
+           10+----------------------------------+
+        100 || 30                 |     layer2  |
+            |20+----------------------------------+
+            || |                  |             | |
+            || |                  |             | |
+            || |                  |             | |
+            +|-|------------------+             | |
+             | |                                | | 510
+             | |                            510 | |
+             | |                                | |
+             | |                                | |
+             | |                                | |
+             | |                                | |
+             | |                520             | |
+             +----------------------------------+ |
+               |                                  |
+               +----------------------------------+
+                               510
+         */
+    }
+};
 
-    FilterOperations filters;
-    filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
-    parentLayer->setFilters(filters);
-    layer->setFilters(filters);
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms);
 
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
-    setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
-    setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(100, 100), IntSize(200, 200), true, opaqueLayers);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestFilters : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        TransformationMatrix layerTransform;
+        layerTransform.translate(250, 250);
+        layerTransform.rotate(90);
+        layerTransform.translate(-250, -250);
 
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+        typename Types::ContentLayerType* blurLayer = this->createDrawingLayer(parent, layerTransform, FloatPoint(30, 30), IntSize(500, 500), true);
+        typename Types::ContentLayerType* opacityLayer = this->createDrawingLayer(parent, layerTransform, FloatPoint(30, 30), IntSize(500, 500), true);
+        typename Types::ContentLayerType* opaqueLayer = this->createDrawingLayer(parent, layerTransform, FloatPoint(30, 30), IntSize(500, 500), true);
 
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
+        FilterOperations filters;
+        filters.operations().append(BlurFilterOperation::create(Length(10, WebCore::Percent), FilterOperation::BLUR));
+        blurLayer->setFilters(filters);
 
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+        filters.operations().clear();
+        filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
+        opaqueLayer->setFilters(filters);
 
-    TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
+        filters.operations().clear();
+        filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::OPACITY));
+        opacityLayer->setFilters(filters);
 
-    occlusion.enterTargetRenderSurface(layer->renderSurface());
+        this->calcDrawEtc(parent);
 
-    // This layer is translated when drawn into its target. So if the scissor rect given from the target surface
-    // is not in that target space, then after translating these query rects into the target, they will fall outside
-    // the scissor and be considered occluded.
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
-}
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
 
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerScissorRectForLayerOffOrigin, layerScissorRectForLayerOffOrigin);
+        // Opacity layer won't contribute to occlusion.
+        occlusion.enterTargetRenderSurface(opacityLayer->renderSurface());
+        occlusion.markOccludedBehindLayer(opacityLayer);
+        occlusion.finishedTargetRenderSurface(opacityLayer, opacityLayer->renderSurface());
 
-void damageRectOverTile(bool opaqueLayers)
-{
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(parentLayer);
-    parent->addChild(layer);
+        EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
+        EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
 
-    FilterOperations filters;
-    filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
-    parentLayer->setFilters(filters);
-    layer->setFilters(filters);
+        // And has nothing to contribute to its parent surface.
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+        EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
+        EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
 
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
-    setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
-    setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
+        // Opaque layer will contribute to occlusion.
+        occlusion.enterTargetRenderSurface(opaqueLayer->renderSurface());
+        occlusion.markOccludedBehindLayer(opaqueLayer);
+        occlusion.finishedTargetRenderSurface(opaqueLayer, opaqueLayer->renderSurface());
 
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
+        EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_EQ_RECT(IntRect(0, 430, 70, 70), occlusion.occlusionInTargetSurface().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
 
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
+        // And it gets translated to the parent surface.
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+        EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+        // The blur layer needs to throw away any occlusion from outside its subtree.
+        occlusion.enterTargetRenderSurface(blurLayer->renderSurface());
+        EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
+        EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
+
+        // And it won't contribute to occlusion.
+        occlusion.markOccludedBehindLayer(blurLayer);
+        occlusion.finishedTargetRenderSurface(blurLayer, blurLayer->renderSurface());
+        EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
+        EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
+
+        // But the opaque layer's occlusion is preserved on the parent.
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+        EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+    }
+};
 
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestFilters);
 
-    TestDamageClient damage(FloatRect(200, 100, 100, 100));
-    TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000), &damage);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestLayerScissorRectOutsideChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+        typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
+        this->calcDrawEtc(parent);
+
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+        occlusion.setLayerScissorRect(IntRect(200, 100, 100, 100));
+
+        occlusion.enterTargetRenderSurface(layer->renderSurface());
+
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(layer, IntRect(200, 100, 100, 100)));
+
+        occlusion.useDefaultLayerScissorRect();
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(200, 100, 100, 100)));
+        occlusion.setLayerScissorRect(IntRect(200, 100, 100, 100));
+
+        occlusion.markOccludedBehindLayer(layer);
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
+
+        EXPECT_EQ_RECT(IntRect(200, 100, 100, 100), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
+    }
+};
 
-    occlusion.enterTargetRenderSurface(layer->renderSurface());
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestLayerScissorRectOutsideChild);
 
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestScreenScissorRectOutsideChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+        typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
+        this->calcDrawEtc(parent);
+
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(200, 100, 100, 100));
+        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+        occlusion.enterTargetRenderSurface(layer->renderSurface());
+
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(layer, IntRect(200, 100, 100, 100)));
+
+        occlusion.useDefaultLayerScissorRect();
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(200, 100, 100, 100)));
+        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+        occlusion.markOccludedBehindLayer(layer);
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
+
+        EXPECT_EQ_RECT(IntRect(200, 100, 100, 100), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
+    }
+};
 
-    // Outside the layer's clip rect.
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(200, 100, 100, 100)));
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestScreenScissorRectOutsideChild);
 
-    occlusion.markOccludedBehindLayer(layer.get());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-    occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestDamageRectOutsideChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+        typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
+        this->calcDrawEtc(parent);
 
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 100, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
+        TestDamageClient<typename Types::RenderSurfaceType> damage(FloatRect(200, 100, 100, 100));
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000), &damage);
 
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+        occlusion.enterTargetRenderSurface(layer->renderSurface());
 
-    EXPECT_EQ_RECT(IntRect(200, 100, 100, 100), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)));
-}
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 0, 200, 200)).isEmpty());
 
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_damageRectOverTile, damageRectOverTile);
+        occlusion.markOccludedBehindLayer(layer);
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
 
-void damageRectOverCulledTile(bool opaqueLayers)
-{
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(parentLayer);
-    parent->addChild(layer);
+        EXPECT_EQ_RECT(IntRect(200, 100, 100, 100), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
+    }
+};
 
-    FilterOperations filters;
-    filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
-    parentLayer->setFilters(filters);
-    layer->setFilters(filters);
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestDamageRectOutsideChild);
 
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
-    setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
-    setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestLayerScissorRectOverChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+        typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
+        this->calcDrawEtc(parent);
+
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+        occlusion.setLayerScissorRect(IntRect(100, 100, 100, 100));
+
+        occlusion.enterTargetRenderSurface(layer->renderSurface());
+
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
+
+        occlusion.markOccludedBehindLayer(layer);
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
+
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)).isEmpty());
+    }
+};
 
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestLayerScissorRectOverChild);
 
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestScreenScissorRectOverChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+        typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
+        this->calcDrawEtc(parent);
+
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(100, 100, 100, 100));
+        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+        occlusion.enterTargetRenderSurface(layer->renderSurface());
+
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
+
+        occlusion.markOccludedBehindLayer(layer);
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
+
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)).isEmpty());
+    }
+};
 
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestScreenScissorRectOverChild);
 
-    TestDamageClient damage(FloatRect(100, 100, 100, 100));
-    TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000), &damage);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestDamageRectOverChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+        typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
+        this->calcDrawEtc(parent);
 
-    occlusion.enterTargetRenderSurface(layer->renderSurface());
+        TestDamageClient<typename Types::RenderSurfaceType> damage(FloatRect(100, 100, 100, 100));
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000), &damage);
 
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
+        occlusion.enterTargetRenderSurface(layer->renderSurface());
 
-    occlusion.markOccludedBehindLayer(layer.get());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-    occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
+        EXPECT_EQ_RECT(IntRect(100, 100, 100, 100), occlusion.unoccludedContentRect(layer, IntRect(0, 0, 200, 200)));
 
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
+        occlusion.markOccludedBehindLayer(layer);
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
 
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)).isEmpty());
+    }
+};
 
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)).isEmpty());
-}
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestDamageRectOverChild);
 
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_damageRectOverCulledTile, damageRectOverCulledTile);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestLayerScissorRectPartlyOverChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+        typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
+        this->calcDrawEtc(parent);
+
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+        occlusion.setLayerScissorRect(IntRect(50, 50, 200, 200));
+
+        occlusion.enterTargetRenderSurface(layer->renderSurface());
+
+        EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
+
+        occlusion.markOccludedBehindLayer(layer);
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
+
+        EXPECT_EQ_RECT(IntRect(50, 50, 200, 200), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
+        EXPECT_EQ_RECT(IntRect(200, 50, 50, 50), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 100)));
+        EXPECT_EQ_RECT(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent, IntRect(0, 100, 300, 100)));
+        EXPECT_EQ_RECT(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent, IntRect(200, 100, 100, 100)));
+        EXPECT_EQ_RECT(IntRect(100, 200, 100, 50), occlusion.unoccludedContentRect(parent, IntRect(100, 200, 100, 100)));
+    }
+};
 
-void damageRectOverPartialTiles(bool opaqueLayers)
-{
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(parentLayer);
-    parent->addChild(layer);
-
-    FilterOperations filters;
-    filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
-    parentLayer->setFilters(filters);
-    layer->setFilters(filters);
-
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
-    setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
-    setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
-
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
-
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
-
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
-    TestDamageClient damage(FloatRect(50, 50, 200, 200));
-    TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000), &damage);
-
-    occlusion.enterTargetRenderSurface(layer->renderSurface());
-
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
-
-    occlusion.markOccludedBehindLayer(layer.get());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-    occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
-
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 100, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
-
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
-    EXPECT_EQ_RECT(IntRect(50, 50, 200, 200), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)));
-    EXPECT_EQ_RECT(IntRect(200, 50, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 100)));
-    EXPECT_EQ_RECT(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 100, 300, 100)));
-    EXPECT_EQ_RECT(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent.get(), IntRect(200, 100, 100, 100)));
-    EXPECT_EQ_RECT(IntRect(100, 200, 100, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(100, 200, 100, 100)));
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_damageRectOverPartialTiles, damageRectOverPartialTiles);
-
-void damageRectOverNoTiles(bool opaqueLayers)
-{
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(parentLayer);
-    parent->addChild(layer);
-
-    FilterOperations filters;
-    filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
-    parentLayer->setFilters(filters);
-    layer->setFilters(filters);
-
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
-    setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
-    setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
-
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
-
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
-
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
-    TestDamageClient damage(FloatRect(500, 500, 100, 100));
-    TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000), &damage);
-
-    occlusion.enterTargetRenderSurface(layer->renderSurface());
-
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
-
-    occlusion.markOccludedBehindLayer(layer.get());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-    occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
-
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
-    EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
-
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)).isEmpty());
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 100)).isEmpty());
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 100, 300, 100)).isEmpty());
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(200, 100, 100, 100)).isEmpty());
-    EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(100, 200, 100, 100)).isEmpty());
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_damageRectOverNoTiles, damageRectOverNoTiles);
-
-TEST(CCOcclusionTrackerTest, opaqueContentsRegionEmpty)
-{
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(layer);
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestLayerScissorRectPartlyOverChild);
 
-    FilterOperations filters;
-    filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
-    layer->setFilters(filters);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestScreenScissorRectPartlyOverChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+        typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
+        this->calcDrawEtc(parent);
+
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(50, 50, 200, 200));
+        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+        occlusion.enterTargetRenderSurface(layer->renderSurface());
+
+        EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
+
+        occlusion.markOccludedBehindLayer(layer);
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
+
+        EXPECT_EQ_RECT(IntRect(50, 50, 200, 200), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
+        EXPECT_EQ_RECT(IntRect(200, 50, 50, 50), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 100)));
+        EXPECT_EQ_RECT(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent, IntRect(0, 100, 300, 100)));
+        EXPECT_EQ_RECT(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent, IntRect(200, 100, 100, 100)));
+        EXPECT_EQ_RECT(IntRect(100, 200, 100, 50), occlusion.unoccludedContentRect(parent, IntRect(100, 200, 100, 100)));
+    }
+};
 
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
-    setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), false, false);
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestScreenScissorRectPartlyOverChild);
 
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestDamageRectPartlyOverChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+        typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
+        this->calcDrawEtc(parent);
 
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
+        TestDamageClient<typename Types::RenderSurfaceType> damage(FloatRect(50, 50, 200, 200));
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000), &damage);
 
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+        occlusion.enterTargetRenderSurface(layer->renderSurface());
 
-    TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
+        EXPECT_EQ_RECT(IntRect(50, 50, 150, 150), occlusion.unoccludedContentRect(layer, IntRect(0, 0, 200, 200)));
 
-    occlusion.enterTargetRenderSurface(layer->renderSurface());
+        occlusion.markOccludedBehindLayer(layer);
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
 
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
+        EXPECT_EQ_RECT(IntRect(50, 50, 200, 200), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
+    }
+};
 
-    // Occluded since its outside the surface bounds.
-    EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(200, 100, 100, 100)));
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestDamageRectPartlyOverChild);
 
-    // Test without any scissors.
-    occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-    EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(200, 100, 100, 100)));
-    occlusion.useDefaultLayerScissorRect();
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestLayerScissorRectOverNothing : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+        typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
+        this->calcDrawEtc(parent);
+
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+        occlusion.setLayerScissorRect(IntRect(500, 500, 100, 100));
+
+        occlusion.enterTargetRenderSurface(layer->renderSurface());
+
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
+
+        occlusion.markOccludedBehindLayer(layer);
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
+
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)).isEmpty());
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 100)).isEmpty());
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 100, 300, 100)).isEmpty());
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(200, 100, 100, 100)).isEmpty());
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(100, 200, 100, 100)).isEmpty());
+    }
+};
 
-    occlusion.markOccludedBehindLayer(layer.get());
-    occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestLayerScissorRectOverNothing);
 
-    EXPECT_TRUE(occlusion.occlusionInScreenSpace().bounds().isEmpty());
-    EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size());
-}
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestScreenScissorRectOverNothing : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+        typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
+        this->calcDrawEtc(parent);
+
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(500, 500, 100, 100));
+        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+        occlusion.enterTargetRenderSurface(layer->renderSurface());
+
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
+
+        occlusion.markOccludedBehindLayer(layer);
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
+        EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
+
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)).isEmpty());
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 100)).isEmpty());
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 100, 300, 100)).isEmpty());
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(200, 100, 100, 100)).isEmpty());
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(100, 200, 100, 100)).isEmpty());
+    }
+};
 
-TEST(CCOcclusionTrackerTest, opaqueContentsRegionNonEmpty)
-{
-    const TransformationMatrix identityMatrix;
-    RefPtr<LayerChromium> parent = LayerChromium::create();
-    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
-    parent->createRenderSurface();
-    parent->addChild(layer);
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestScreenScissorRectOverNothing);
 
-    setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
-    setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(100, 100), IntSize(200, 200), false, false);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestDamageRectOverNothing : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+        typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
+        this->calcDrawEtc(parent);
 
-    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
-    Vector<RefPtr<LayerChromium> > dummyLayerList;
-    int dummyMaxTextureSize = 512;
+        TestDamageClient<typename Types::RenderSurfaceType> damage(FloatRect(500, 500, 100, 100));
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000), &damage);
 
-    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
-    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
-    renderSurfaceLayerList.append(parent);
+        occlusion.enterTargetRenderSurface(layer->renderSurface());
 
-    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+        EXPECT_TRUE(occlusion.unoccludedContentRect(layer, IntRect(0, 0, 200, 200)).isEmpty());
 
-    {
-        TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
-        layer->setOpaquePaintRect(IntRect(0, 0, 100, 100));
+        occlusion.markOccludedBehindLayer(layer);
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
 
-        occlusion.enterTargetRenderSurface(parent->renderSurface());
-        occlusion.markOccludedBehindLayer(layer.get());
+        EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)).isEmpty());
+    }
+};
 
-        EXPECT_EQ_RECT(IntRect(100, 100, 100, 100), occlusion.occlusionInScreenSpace().bounds());
-        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestDamageRectOverNothing);
 
-        EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(0, 100, 100, 100)));
-        EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(100, 100, 100, 100)));
-        EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(200, 200, 100, 100)));
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestLayerScissorRectForLayerOffOrigin : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
+    {
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+        typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
+        this->calcDrawEtc(parent);
+
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+        occlusion.enterTargetRenderSurface(layer->renderSurface());
+
+        // This layer is translated when drawn into its target. So if the scissor rect given from the target surface
+        // is not in that target space, then after translating these query rects into the target, they will fall outside
+        // the scissor and be considered occluded.
+        EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
     }
+};
+
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestLayerScissorRectForLayerOffOrigin);
 
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestOpaqueContentsRegionEmpty : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
     {
-        TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
-        layer->setOpaquePaintRect(IntRect(20, 20, 180, 180));
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+        typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), false);
+        this->calcDrawEtc(parent);
 
-        occlusion.enterTargetRenderSurface(parent->renderSurface());
-        occlusion.markOccludedBehindLayer(layer.get());
+        TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+        occlusion.enterTargetRenderSurface(layer->renderSurface());
 
-        EXPECT_EQ_RECT(IntRect(120, 120, 180, 180), occlusion.occlusionInScreenSpace().bounds());
-        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
+        EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
 
-        EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(0, 100, 100, 100)));
-        EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(100, 100, 100, 100)));
-        EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(200, 200, 100, 100)));
+        // Occluded since its outside the surface bounds.
+        EXPECT_TRUE(occlusion.occluded(layer, IntRect(200, 100, 100, 100)));
+
+        // Test without any scissors.
+        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+        EXPECT_FALSE(occlusion.occluded(layer, IntRect(200, 100, 100, 100)));
+        occlusion.useDefaultLayerScissorRect();
+
+        occlusion.markOccludedBehindLayer(layer);
+        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+
+        EXPECT_TRUE(occlusion.occlusionInScreenSpace().bounds().isEmpty());
+        EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size());
     }
+};
+
+MAIN_AND_IMPL_THREAD_TEST(CCOcclusionTrackerTestOpaqueContentsRegionEmpty);
 
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestOpaqueContentsRegionNonEmpty : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+    void runMyTest()
     {
-        TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
-        layer->setOpaquePaintRect(IntRect(150, 150, 100, 100));
+        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+        typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(100, 100), IntSize(200, 200), false);
+        this->calcDrawEtc(parent);
 
-        occlusion.enterTargetRenderSurface(parent->renderSurface());
-        occlusion.markOccludedBehindLayer(layer.get());
+        {
+            TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+            layer->setOpaqueContentsRect(IntRect(0, 0, 100, 100));
 
-        EXPECT_EQ_RECT(IntRect(250, 250, 50, 50), occlusion.occlusionInScreenSpace().bounds());
-        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+            occlusion.enterTargetRenderSurface(parent->renderSurface());
+            occlusion.markOccludedBehindLayer(layer);
+
+            EXPECT_EQ_RECT(IntRect(100, 100, 100, 100), occlusion.occlusionInScreenSpace().bounds());
+            EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+
+            EXPECT_FALSE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+            EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
+            EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
+        }
+
+        {
+            TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+            layer->setOpaqueContentsRect(IntRect(20, 20, 180, 180));
+
+            occlusion.enterTargetRenderSurface(parent->renderSurface());
+            occlusion.markOccludedBehindLayer(layer);
+
+            EXPECT_EQ_RECT(IntRect(120, 120, 180, 180), occlusion.occlusionInScreenSpace().bounds());
+            EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
 
-        EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(0, 100, 100, 100)));
-        EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(100, 100, 100, 100)));
-        EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(200, 200, 100, 100)));
+            EXPECT_FALSE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+            EXPECT_FALSE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
+            EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
+        }
+
+        {
+            TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+            layer->setOpaqueContentsRect(IntRect(150, 150, 100, 100));
+
+            occlusion.enterTargetRenderSurface(parent->renderSurface());
+            occlusion.markOccludedBehindLayer(layer);
+
+            EXPECT_EQ_RECT(IntRect(250, 250, 50, 50), occlusion.occlusionInScreenSpace().bounds());
+            EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+
+            EXPECT_FALSE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+            EXPECT_FALSE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
+            EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
+        }
     }
-}
+};
+
+MAIN_AND_IMPL_THREAD_TEST(CCOcclusionTrackerTestOpaqueContentsRegionNonEmpty);
 
 } // namespace