Changeset 113652 in webkit


Ignore:
Timestamp:
Apr 9, 2012 6:23:21 PM (12 years ago)
Author:
danakj@chromium.org
Message:

[chromium] Cull occluded surface quads
https://bugs.webkit.org/show_bug.cgi?id=81227

Reviewed by Adrienne Walker.

Source/WebCore:

Cull render surface and replica quads during draw based on occlusion.

In order to compute occlusion for the surface or replica, it must not
consider occlusion found in the surface's own subtree. To do this, we
reorder the calls to the occlusion tracker, and add the surface and
replica quads before we "leaveToTargetRenderSurface" which merges
occlusion from the surface's subtree up into its parent.

Unit test: CCOcclusionTrackerTestReplicaOccluded

CCOcclusionTrackerTestSurfaceWithReplicaUnoccluded
CCOcclusionTrackerTestSurfaceAndReplicaOccludedDifferently
CCOcclusionTrackerTestSurfaceChildOfSurface
CCOcclusionTrackerTestSurfaceChildOfClippingSurface

And added some sanity checks to other CCOcclusionTracker tests that have
render surfaces.

  • platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp:

(WebCore::CCLayerTreeHostImpl::calculateRenderPasses):

  • platform/graphics/chromium/cc/CCOcclusionTracker.cpp:

(WebCore::::leaveToTargetRenderSurface):
(WebCore::::unoccludedContributingSurfaceContentRect):
(WebCore):

  • platform/graphics/chromium/cc/CCOcclusionTracker.h:

(CCOcclusionTrackerBase):

  • platform/graphics/chromium/cc/CCQuadCuller.cpp:

(WebCore::CCQuadCuller::CCQuadCuller):
(WebCore::appendQuadInternal):
(WebCore::CCQuadCuller::append):
(WebCore):
(WebCore::CCQuadCuller::appendSurface):
(WebCore::CCQuadCuller::appendReplica):

  • platform/graphics/chromium/cc/CCQuadCuller.h:

(CCQuadCuller):

  • platform/graphics/chromium/cc/CCRenderPass.cpp:

(WebCore::CCRenderPass::appendQuadsForRenderSurfaceLayer):

  • platform/graphics/chromium/cc/CCRenderPass.h:

(CCRenderPass):

Source/WebKit/chromium:

  • tests/CCOcclusionTrackerTest.cpp:

(WebKitTests::CCOcclusionTrackerTest::TearDown):
(WebKitTests::CCOcclusionTrackerTest::createReplicaLayer):
(CCOcclusionTrackerTest):
(WebKitTests::CCOcclusionTrackerTest::setReplica):
(WebKitTests::CCOcclusionTrackerTestOverlappingSurfaceSiblings::runMyTest):
(WebKitTests::CCOcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms::runMyTest):
(WebKitTests::CCOcclusionTrackerTestAnimationOpacity1OnMainThread::runMyTest):
(WebKitTests::CCOcclusionTrackerTestAnimationOpacity0OnMainThread::runMyTest):
(WebKitTests::CCOcclusionTrackerTestAnimationTranslateOnMainThread::runMyTest):
(WebKitTests::CCOcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping::runMyTest):
(WebKitTests):
(CCOcclusionTrackerTestReplicaOccluded):
(WebKitTests::CCOcclusionTrackerTestReplicaOccluded::runMyTest):
(CCOcclusionTrackerTestSurfaceWithReplicaUnoccluded):
(WebKitTests::CCOcclusionTrackerTestSurfaceWithReplicaUnoccluded::runMyTest):
(CCOcclusionTrackerTestSurfaceAndReplicaOccludedDifferently):
(WebKitTests::CCOcclusionTrackerTestSurfaceAndReplicaOccludedDifferently::runMyTest):
(CCOcclusionTrackerTestSurfaceChildOfSurface):
(WebKitTests::CCOcclusionTrackerTestSurfaceChildOfSurface::runMyTest):

Location:
trunk/Source
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r113647 r113652  
     12012-04-09  Dana Jansens  <danakj@chromium.org>
     2
     3        [chromium] Cull occluded surface quads
     4        https://bugs.webkit.org/show_bug.cgi?id=81227
     5
     6        Reviewed by Adrienne Walker.
     7
     8        Cull render surface and replica quads during draw based on occlusion.
     9
     10        In order to compute occlusion for the surface or replica, it must not
     11        consider occlusion found in the surface's own subtree. To do this, we
     12        reorder the calls to the occlusion tracker, and add the surface and
     13        replica quads before we "leaveToTargetRenderSurface" which merges
     14        occlusion from the surface's subtree up into its parent.
     15
     16        Unit test: CCOcclusionTrackerTestReplicaOccluded
     17                   CCOcclusionTrackerTestSurfaceWithReplicaUnoccluded
     18                   CCOcclusionTrackerTestSurfaceAndReplicaOccludedDifferently
     19                   CCOcclusionTrackerTestSurfaceChildOfSurface
     20                   CCOcclusionTrackerTestSurfaceChildOfClippingSurface
     21
     22        And added some sanity checks to other CCOcclusionTracker tests that have
     23        render surfaces.
     24
     25        * platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp:
     26        (WebCore::CCLayerTreeHostImpl::calculateRenderPasses):
     27        * platform/graphics/chromium/cc/CCOcclusionTracker.cpp:
     28        (WebCore::::leaveToTargetRenderSurface):
     29        (WebCore::::unoccludedContributingSurfaceContentRect):
     30        (WebCore):
     31        * platform/graphics/chromium/cc/CCOcclusionTracker.h:
     32        (CCOcclusionTrackerBase):
     33        * platform/graphics/chromium/cc/CCQuadCuller.cpp:
     34        (WebCore::CCQuadCuller::CCQuadCuller):
     35        (WebCore::appendQuadInternal):
     36        (WebCore::CCQuadCuller::append):
     37        (WebCore):
     38        (WebCore::CCQuadCuller::appendSurface):
     39        (WebCore::CCQuadCuller::appendReplica):
     40        * platform/graphics/chromium/cc/CCQuadCuller.h:
     41        (CCQuadCuller):
     42        * platform/graphics/chromium/cc/CCRenderPass.cpp:
     43        (WebCore::CCRenderPass::appendQuadsForRenderSurfaceLayer):
     44        * platform/graphics/chromium/cc/CCRenderPass.h:
     45        (CCRenderPass):
     46
    1472012-04-09  Andreas Kling  <kling@webkit.org>
    248
  • trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp

    r113350 r113652  
    297297    for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) {
    298298        CCRenderSurface* renderSurface = it.targetRenderSurfaceLayer()->renderSurface();
     299        CCRenderPass* pass = surfacePassMap.get(renderSurface);
    299300
    300301        if (it.representsItself())
    301302            occlusionTracker.enterTargetRenderSurface(renderSurface);
    302         else if (it.representsTargetRenderSurface())
     303        else if (it.representsTargetRenderSurface()) {
    303304            occlusionTracker.finishedTargetRenderSurface(*it, renderSurface);
    304         else
     305            continue;
     306        } else {
     307            pass->appendQuadsForRenderSurfaceLayer(*it, &occlusionTracker);
    305308            occlusionTracker.leaveToTargetRenderSurface(renderSurface);
    306 
    307         if (it.representsTargetRenderSurface())
    308309            continue;
     310        }
     311
    309312        if (it->visibleLayerRect().isEmpty())
    310313            continue;
    311 
    312         CCRenderPass* pass = surfacePassMap.get(renderSurface);
    313         if (it.representsContributingRenderSurface()) {
    314             pass->appendQuadsForRenderSurfaceLayer(*it);
    315             continue;
    316         }
    317314
    318315        it->willDraw(m_layerRenderer.get());
  • trunk/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp

    r113637 r113652  
    142142    const RenderSurfaceType* oldTarget = m_stack[lastIndex].surface;
    143143    Region oldTargetOcclusionInNewTarget = transformSurfaceOpaqueRegion<RenderSurfaceType>(oldTarget, m_stack[lastIndex].occlusionInTarget, oldTarget->originTransform());
     144    // FIXME: The replica can occlude things too.
    144145
    145146    if (surfaceWillBeAtTopAfterPop) {
     
    336337
    337338template<typename LayerType, typename RenderSurfaceType>
     339IntRect CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::unoccludedContributingSurfaceContentRect(const LayerType* layer, bool forReplica, const IntRect& contentRect) const
     340{
     341    ASSERT(!m_stack.isEmpty());
     342    // This should be called while the contributing render surface is still considered the current target in the occlusion tracker.
     343    ASSERT(layer->targetRenderSurface() == m_stack.last().surface);
     344
     345    // A contributing surface doesn't get occluded by things inside its own surface, so only things outside the surface can occlude it. That occlusion is
     346    // found just below the top of the stack (if it exists).
     347    if (m_stack.size() < 2)
     348        return contentRect;
     349    if (contentRect.isEmpty())
     350        return contentRect;
     351
     352    RenderSurfaceType* surface = layer->renderSurface();
     353    const StackObject& secondLast = m_stack[m_stack.size() - 2];
     354
     355    IntRect surfaceClipRect = surface->clipRect();
     356    if (surfaceClipRect.isEmpty()) {
     357        const RenderSurfaceType* targetSurface = secondLast.surface;
     358        surfaceClipRect = intersection(targetSurface->contentRect(), enclosingIntRect(surface->drawableContentRect()));
     359    }
     360
     361    const TransformationMatrix& transformToScreen = forReplica ? surface->replicaScreenSpaceTransform() : surface->screenSpaceTransform();
     362    const TransformationMatrix& transformToTarget = forReplica ? surface->replicaOriginTransform() : surface->originTransform();
     363
     364    IntRect unoccludedInScreen = contentRect;
     365    if (surfaceTransformsToScreenKnown(surface))
     366        unoccludedInScreen = computeUnoccludedContentRect(contentRect, transformToScreen, m_scissorRectInScreenSpace, secondLast.occlusionInScreen);
     367
     368    if (unoccludedInScreen.isEmpty())
     369        return unoccludedInScreen;
     370
     371    IntRect unoccludedInTarget = contentRect;
     372    if (surfaceTransformsToTargetKnown(surface))
     373        unoccludedInTarget = computeUnoccludedContentRect(contentRect, transformToTarget, surfaceClipRect, secondLast.occlusionInTarget);
     374
     375    return intersection(unoccludedInScreen, unoccludedInTarget);
     376}
     377
     378template<typename LayerType, typename RenderSurfaceType>
    338379IntRect CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::layerScissorRectInTargetSurface(const LayerType* layer) const
    339380{
     
    353394template bool CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::occluded(const LayerChromium*, const IntRect& contentRect) const;
    354395template IntRect CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::unoccludedContentRect(const LayerChromium*, const IntRect& contentRect) const;
     396template IntRect CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::unoccludedContributingSurfaceContentRect(const LayerChromium*, bool forReplica, const IntRect& contentRect) const;
    355397template IntRect CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::layerScissorRectInTargetSurface(const LayerChromium*) const;
    356398
     
    362404template bool CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::occluded(const CCLayerImpl*, const IntRect& contentRect) const;
    363405template IntRect CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::unoccludedContentRect(const CCLayerImpl*, const IntRect& contentRect) const;
     406template IntRect CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::unoccludedContributingSurfaceContentRect(const CCLayerImpl*, bool forReplica, const IntRect& contentRect) const;
    364407template IntRect CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::layerScissorRectInTargetSurface(const CCLayerImpl*) const;
    365408
  • trunk/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.h

    r112548 r113652  
    6868    IntRect unoccludedContentRect(const LayerType*, const IntRect& contentRect) const;
    6969
     70    // Gives an unoccluded sub-rect of |contentRect| in the content space of the surface owned by |layer|. Used when considering occlusion for a surface
     71    // that is rendering into another target surface.
     72    IntRect unoccludedContributingSurfaceContentRect(const LayerType*, bool forReplica, const IntRect& contentRect) const;
     73
    7074    // Report operations for recording overdraw metrics.
    7175    CCOverdrawMetrics& overdrawMetrics() const { return *m_overdrawMetrics.get(); }
  • trunk/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp

    r113372 r113652  
    4141namespace WebCore {
    4242
    43 CCQuadCuller::CCQuadCuller(CCQuadList& quadList, CCLayerImpl* layer, CCOcclusionTrackerImpl* occlusionTracker)
     43CCQuadCuller::CCQuadCuller(CCQuadList& quadList, CCLayerImpl* layer, const CCOcclusionTrackerImpl* occlusionTracker)
    4444    : m_quadList(quadList)
    4545    , m_layer(layer)
     
    4848}
    4949
    50 bool CCQuadCuller::append(PassOwnPtr<CCDrawQuad> passDrawQuad)
     50static inline bool appendQuadInternal(PassOwnPtr<CCDrawQuad> passDrawQuad, const IntRect& culledRect, CCQuadList& quadList, const CCOcclusionTrackerImpl& occlusionTracker)
    5151{
    5252    OwnPtr<CCDrawQuad> drawQuad(passDrawQuad);
    53     IntRect culledRect = m_occlusionTracker->unoccludedContentRect(m_layer, drawQuad->quadRect());
    5453    bool keepQuad = !culledRect.isEmpty();
    5554    if (keepQuad)
    5655        drawQuad->setQuadVisibleRect(culledRect);
    5756
    58     m_occlusionTracker->overdrawMetrics().didCullForDrawing(drawQuad->quadTransform(), drawQuad->quadRect(), culledRect);
    59     m_occlusionTracker->overdrawMetrics().didDraw(drawQuad->quadTransform(), culledRect, drawQuad->opaqueRect());
     57    occlusionTracker.overdrawMetrics().didCullForDrawing(drawQuad->quadTransform(), drawQuad->quadRect(), culledRect);
     58    occlusionTracker.overdrawMetrics().didDraw(drawQuad->quadTransform(), culledRect, drawQuad->opaqueRect());
    6059
    6160    // Release the quad after we're done using it.
    6261    if (keepQuad)
    63         m_quadList.append(drawQuad.release());
     62        quadList.append(drawQuad.release());
    6463    return keepQuad;
     64}
     65
     66bool CCQuadCuller::append(PassOwnPtr<CCDrawQuad> passDrawQuad)
     67{
     68    IntRect culledRect = m_occlusionTracker->unoccludedContentRect(m_layer, passDrawQuad->quadRect());
     69    return appendQuadInternal(passDrawQuad, culledRect, m_quadList, *m_occlusionTracker);
     70}
     71
     72bool CCQuadCuller::appendSurface(PassOwnPtr<CCDrawQuad> passDrawQuad)
     73{
     74    IntRect culledRect = m_occlusionTracker->unoccludedContributingSurfaceContentRect(m_layer, false, passDrawQuad->quadRect());
     75    return appendQuadInternal(passDrawQuad, culledRect, m_quadList, *m_occlusionTracker);
     76}
     77
     78bool CCQuadCuller::appendReplica(PassOwnPtr<CCDrawQuad> passDrawQuad)
     79{
     80    IntRect culledRect = m_occlusionTracker->unoccludedContributingSurfaceContentRect(m_layer, true, passDrawQuad->quadRect());
     81    return appendQuadInternal(passDrawQuad, culledRect, m_quadList, *m_occlusionTracker);
    6582}
    6683
  • trunk/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.h

    r111700 r113652  
    3737    // Passing 0 for CCOverdrawCounts* is valid, and disable the extra computation
    3838    // done to estimate over draw statistics.
    39     CCQuadCuller(CCQuadList&, CCLayerImpl*, CCOcclusionTrackerImpl*);
     39    CCQuadCuller(CCQuadList&, CCLayerImpl*, const CCOcclusionTrackerImpl*);
    4040
    4141    // Returns true if the quad is added to the list, and false if the quad is entirely culled.
    4242    virtual bool append(PassOwnPtr<CCDrawQuad> passDrawQuad);
     43    virtual bool appendSurface(PassOwnPtr<CCDrawQuad> passDrawQuad);
     44    virtual bool appendReplica(PassOwnPtr<CCDrawQuad> passDrawQuad);
    4345
    4446private:
    4547    CCQuadList& m_quadList;
    4648    CCLayerImpl* m_layer;
    47     CCOcclusionTrackerImpl* m_occlusionTracker;
     49    const CCOcclusionTrackerImpl* m_occlusionTracker;
    4850};
    4951
  • trunk/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.cpp

    r113453 r113652  
    6767}
    6868
    69 void CCRenderPass::appendQuadsForRenderSurfaceLayer(CCLayerImpl* layer)
     69void CCRenderPass::appendQuadsForRenderSurfaceLayer(CCLayerImpl* layer, CCOcclusionTrackerImpl* occlusionTracker)
    7070{
    7171    // FIXME: render surface layers should be a CCLayerImpl-derived class and
    7272    // not be handled specially here.
     73    CCQuadCuller quadCuller(m_quadList, layer, occlusionTracker);
     74
    7375    CCRenderSurface* surface = layer->renderSurface();
    7476    OwnPtr<CCSharedQuadState> sharedQuadState = surface->createSharedQuadState();
    7577    if (layer->hasDebugBorders()) {
    7678        Color color(debugSurfaceBorderColorRed, debugSurfaceBorderColorGreen, debugSurfaceBorderColorBlue, debugSurfaceBorderAlpha);
    77         m_quadList.append(CCDebugBorderDrawQuad::create(sharedQuadState.get(), surface->contentRect(), color, debugSurfaceBorderWidth));
     79        quadCuller.appendSurface(CCDebugBorderDrawQuad::create(sharedQuadState.get(), surface->contentRect(), color, debugSurfaceBorderWidth));
    7880    }
    7981    bool isReplica = false;
    80     m_quadList.append(CCRenderSurfaceDrawQuad::create(sharedQuadState.get(), surface->contentRect(), layer, surfaceDamageRect(), isReplica));
     82    quadCuller.appendSurface(CCRenderSurfaceDrawQuad::create(sharedQuadState.get(), surface->contentRect(), layer, surfaceDamageRect(), isReplica));
    8183    m_sharedQuadStateList.append(sharedQuadState.release());
    8284
     
    8688        if (layer->hasDebugBorders()) {
    8789            Color color(debugReplicaBorderColorRed, debugReplicaBorderColorGreen, debugReplicaBorderColorBlue, debugSurfaceBorderAlpha);
    88             m_quadList.append(CCDebugBorderDrawQuad::create(sharedQuadState.get(), surface->contentRect(), color, debugSurfaceBorderWidth));
     90            quadCuller.appendReplica(CCDebugBorderDrawQuad::create(sharedQuadState.get(), surface->contentRect(), color, debugSurfaceBorderWidth));
    8991        }
    9092        bool isReplica = true;
    91         m_quadList.append(CCRenderSurfaceDrawQuad::create(sharedQuadState.get(), surface->contentRect(), layer, surfaceDamageRect(), isReplica));
     93        quadCuller.appendReplica(CCRenderSurfaceDrawQuad::create(sharedQuadState.get(), surface->contentRect(), layer, surfaceDamageRect(), isReplica));
    9294        m_sharedQuadStateList.append(sharedQuadState.release());
    9395    }
  • trunk/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.h

    r111700 r113652  
    5656
    5757    void appendQuadsForLayer(CCLayerImpl*, CCOcclusionTrackerImpl*, bool& usedCheckerboard);
    58     void appendQuadsForRenderSurfaceLayer(CCLayerImpl*);
     58    void appendQuadsForRenderSurfaceLayer(CCLayerImpl*, CCOcclusionTrackerImpl*);
    5959
    6060    const CCQuadList& quadList() const { return m_quadList; }
  • trunk/Source/WebKit/chromium/ChangeLog

    r113650 r113652  
     12012-04-09  Dana Jansens  <danakj@chromium.org>
     2
     3        [chromium] Cull occluded surface quads
     4        https://bugs.webkit.org/show_bug.cgi?id=81227
     5
     6        Reviewed by Adrienne Walker.
     7
     8        * tests/CCOcclusionTrackerTest.cpp:
     9        (WebKitTests::CCOcclusionTrackerTest::TearDown):
     10        (WebKitTests::CCOcclusionTrackerTest::createReplicaLayer):
     11        (CCOcclusionTrackerTest):
     12        (WebKitTests::CCOcclusionTrackerTest::setReplica):
     13        (WebKitTests::CCOcclusionTrackerTestOverlappingSurfaceSiblings::runMyTest):
     14        (WebKitTests::CCOcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms::runMyTest):
     15        (WebKitTests::CCOcclusionTrackerTestAnimationOpacity1OnMainThread::runMyTest):
     16        (WebKitTests::CCOcclusionTrackerTestAnimationOpacity0OnMainThread::runMyTest):
     17        (WebKitTests::CCOcclusionTrackerTestAnimationTranslateOnMainThread::runMyTest):
     18        (WebKitTests::CCOcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping::runMyTest):
     19        (WebKitTests):
     20        (CCOcclusionTrackerTestReplicaOccluded):
     21        (WebKitTests::CCOcclusionTrackerTestReplicaOccluded::runMyTest):
     22        (CCOcclusionTrackerTestSurfaceWithReplicaUnoccluded):
     23        (WebKitTests::CCOcclusionTrackerTestSurfaceWithReplicaUnoccluded::runMyTest):
     24        (CCOcclusionTrackerTestSurfaceAndReplicaOccludedDifferently):
     25        (WebKitTests::CCOcclusionTrackerTestSurfaceAndReplicaOccludedDifferently::runMyTest):
     26        (CCOcclusionTrackerTestSurfaceChildOfSurface):
     27        (WebKitTests::CCOcclusionTrackerTestSurfaceChildOfSurface::runMyTest):
     28
    1292012-04-09  James Robinson  <jamesr@chromium.org>
    230
  • trunk/Source/WebKit/chromium/tests/CCOcclusionTrackerTest.cpp

    r113637 r113652  
    136136        m_renderSurfaceLayerListChromium.clear();
    137137        m_renderSurfaceLayerListImpl.clear();
     138        m_replicaLayers.clear();
    138139        CCLayerTreeHost::setNeedsFilterContext(false);
    139140    }
     
    188189    }
    189190
     191    typename Types::LayerType* createReplicaLayer(typename Types::LayerType* owningLayer, const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
     192    {
     193        typename Types::ContentLayerPtrType layer(Types::createContentLayer());
     194        typename Types::ContentLayerType* layerPtr = layer.get();
     195        setProperties(layerPtr, transform, position, bounds);
     196        setReplica(owningLayer, layer.release());
     197        return layerPtr;
     198    }
     199
    190200    typename Types::ContentLayerType* createDrawingSurface(typename Types::LayerType* parent, const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds, bool opaque)
    191201    {
     
    254264    }
    255265
     266    void setReplica(LayerChromium* owningLayer, PassRefPtr<LayerChromium> layer)
     267    {
     268        owningLayer->setReplicaLayer(layer.get());
     269        m_replicaLayers.append(layer);
     270    }
     271
     272    void setReplica(CCLayerImpl* owningLayer, PassOwnPtr<CCLayerImpl> layer)
     273    {
     274        owningLayer->setReplicaLayer(layer);
     275    }
     276
    256277    // These hold ownership of the layers for the duration of the test.
    257278    typename Types::LayerPtrType m_root;
    258279    Vector<RefPtr<LayerChromium> > m_renderSurfaceLayerListChromium;
    259280    Vector<CCLayerImpl*> m_renderSurfaceLayerListImpl;
     281    Vector<RefPtr<LayerChromium> > m_replicaLayers;
    260282};
    261283
     
    903925        occlusion.markOccludedBehindLayer(child2);
    904926        occlusion.finishedTargetRenderSurface(child2, child2->renderSurface());
     927
     928        // There is nothing above child2's surface in the z-order.
     929        EXPECT_EQ_RECT(IntRect(-10, 420, 70, 80), occlusion.unoccludedContributingSurfaceContentRect(child2, false, IntRect(-10, 420, 70, 80)));
     930
    905931        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
    906932        occlusion.enterTargetRenderSurface(child1->renderSurface());
     
    920946        occlusion.markOccludedBehindLayer(child1);
    921947        occlusion.finishedTargetRenderSurface(child1, child1->renderSurface());
     948
     949        // child2's contents will occlude child1 below it.
     950        EXPECT_EQ_RECT(IntRect(-10, 430, 10, 70), occlusion.unoccludedContributingSurfaceContentRect(child1, false, IntRect(-10, 430, 80, 70)));
     951
    922952        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
    923953
     
    9821012        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
    9831013        typename Types::LayerType* child1 = this->createSurface(parent, child1Transform, FloatPoint(30, 20), IntSize(10, 10));
    984         typename Types::LayerType* child2 = this->createSurface(parent, child2Transform, FloatPoint(20, 40), IntSize(10, 10));
     1014        typename Types::LayerType* child2 = this->createDrawingSurface(parent, child2Transform, FloatPoint(20, 40), IntSize(10, 10), false);
    9851015        typename Types::ContentLayerType* layer1 = this->createDrawingLayer(child1, this->identityMatrix, FloatPoint(-10, -20), IntSize(510, 510), true);
    9861016        typename Types::ContentLayerType* layer2 = this->createDrawingLayer(child2, this->identityMatrix, FloatPoint(-10, -10), IntSize(510, 510), true);
     
    10061036        occlusion.markOccludedBehindLayer(child2);
    10071037        occlusion.finishedTargetRenderSurface(child2, child2->renderSurface());
    1008         occlusion.leaveToTargetRenderSurface(parent->renderSurface());
     1038
     1039        // There is nothing above child2's surface in the z-order.
     1040        EXPECT_EQ_RECT(IntRect(-10, 420, 70, 80), occlusion.unoccludedContributingSurfaceContentRect(child2, false, IntRect(-10, 420, 70, 80)));
     1041
     1042        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
     1043
    10091044        occlusion.enterTargetRenderSurface(child1->renderSurface());
    10101045        occlusion.markOccludedBehindLayer(layer1);
     
    10231058        occlusion.markOccludedBehindLayer(child1);
    10241059        occlusion.finishedTargetRenderSurface(child1, child1->renderSurface());
     1060
     1061        // child2's contents will occlude child1 below it.
     1062        EXPECT_EQ_RECT(IntRect(420, -20, 80, 90), occlusion.unoccludedContributingSurfaceContentRect(child1, false, IntRect(420, -20, 80, 90)));
     1063        EXPECT_EQ_RECT(IntRect(490, -10, 10, 80), occlusion.unoccludedContributingSurfaceContentRect(child1, false, IntRect(420, -10, 80, 90)));
     1064        EXPECT_EQ_RECT(IntRect(420, -20, 70, 10), occlusion.unoccludedContributingSurfaceContentRect(child1, false, IntRect(420, -20, 70, 90)));
     1065
    10251066        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
    10261067
     
    17431784        typename Types::ContentLayerType* surfaceChild = this->createDrawingLayer(surface, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 300), true);
    17441785        typename Types::ContentLayerType* surfaceChild2 = this->createDrawingLayer(surface, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 300), true);
     1786        typename Types::ContentLayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(250, 0), IntSize(50, 300), true);
    17451787
    17461788        addOpacityTransitionToController(*layer->layerAnimationController(), 10, 0, 1, false);
     
    17541796        TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
    17551797
     1798        occlusion.enterTargetRenderSurface(parent->renderSurface());
     1799        occlusion.markOccludedBehindLayer(topmost);
     1800        // This occlusion will affect all surfaces.
     1801        EXPECT_EQ_RECT(IntRect(0, 0, 250, 300), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
     1802
    17561803        occlusion.enterTargetRenderSurface(surface->renderSurface());
    17571804        occlusion.markOccludedBehindLayer(surfaceChild2);
    1758         EXPECT_EQ_RECT(IntRect(100, 0, 200, 300), occlusion.unoccludedContentRect(surface, IntRect(0, 0, 300, 300)));
     1805        EXPECT_EQ_RECT(IntRect(100, 0, 150, 300), occlusion.unoccludedContentRect(surface, IntRect(0, 0, 300, 300)));
    17591806        occlusion.markOccludedBehindLayer(surfaceChild);
    1760         EXPECT_EQ_RECT(IntRect(200, 0, 100, 300), occlusion.unoccludedContentRect(surface, IntRect(0, 0, 300, 300)));
     1807        EXPECT_EQ_RECT(IntRect(200, 0, 50, 300), occlusion.unoccludedContentRect(surface, IntRect(0, 0, 300, 300)));
    17611808        occlusion.markOccludedBehindLayer(surface);
    17621809        EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), occlusion.unoccludedContentRect(surface, IntRect(0, 0, 300, 300)));
    17631810        occlusion.finishedTargetRenderSurface(surface, surface->renderSurface());
    1764         occlusion.leaveToTargetRenderSurface(parent->renderSurface());
    1765         // Occlusion is lost when leaving the animating surface.
    1766         EXPECT_EQ_RECT(IntRect(0, 0, 300, 300), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
    1767 
     1811
     1812        // Occlusion within the surface is lost when leaving the animating surface.
     1813        EXPECT_EQ_RECT(IntRect(0, 0, 250, 300), occlusion.unoccludedContributingSurfaceContentRect(surface, false, IntRect(0, 0, 300, 300)));
     1814
     1815        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
    17681816        occlusion.markOccludedBehindLayer(layer);
    17691817        // Occlusion is not added for the animating layer.
    1770         EXPECT_EQ_RECT(IntRect(0, 0, 300, 300), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
     1818        EXPECT_EQ_RECT(IntRect(0, 0, 250, 300), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
    17711819    }
    17721820};
     
    17841832        typename Types::ContentLayerType* surfaceChild = this->createDrawingLayer(surface, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 300), true);
    17851833        typename Types::ContentLayerType* surfaceChild2 = this->createDrawingLayer(surface, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 300), true);
     1834        typename Types::ContentLayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(250, 0), IntSize(50, 300), true);
    17861835
    17871836        addOpacityTransitionToController(*layer->layerAnimationController(), 10, 1, 0, false);
     
    17951844        TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
    17961845
     1846        occlusion.enterTargetRenderSurface(parent->renderSurface());
     1847        occlusion.markOccludedBehindLayer(topmost);
     1848        // This occlusion will affect all surfaces.
     1849        EXPECT_EQ_RECT(IntRect(0, 0, 250, 300), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
     1850
    17971851        occlusion.enterTargetRenderSurface(surface->renderSurface());
    17981852        occlusion.markOccludedBehindLayer(surfaceChild2);
    1799         EXPECT_EQ_RECT(IntRect(100, 0, 200, 300), occlusion.unoccludedContentRect(surface, IntRect(0, 0, 300, 300)));
     1853        EXPECT_EQ_RECT(IntRect(100, 0, 150, 300), occlusion.unoccludedContentRect(surface, IntRect(0, 0, 300, 300)));
    18001854        occlusion.markOccludedBehindLayer(surfaceChild);
    1801         EXPECT_EQ_RECT(IntRect(200, 0, 100, 300), occlusion.unoccludedContentRect(surface, IntRect(0, 0, 300, 300)));
     1855        EXPECT_EQ_RECT(IntRect(200, 0, 50, 300), occlusion.unoccludedContentRect(surface, IntRect(0, 0, 300, 300)));
    18021856        occlusion.markOccludedBehindLayer(surface);
    18031857        EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), occlusion.unoccludedContentRect(surface, IntRect(0, 0, 300, 300)));
    18041858        occlusion.finishedTargetRenderSurface(surface, surface->renderSurface());
    1805         occlusion.leaveToTargetRenderSurface(parent->renderSurface());
    1806         // Occlusion is lost when leaving the animating surface.
    1807         EXPECT_EQ_RECT(IntRect(0, 0, 300, 300), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
    1808 
     1859
     1860        // Occlusion within the surface is lost when leaving the animating surface.
     1861        EXPECT_EQ_RECT(IntRect(0, 0, 250, 300), occlusion.unoccludedContributingSurfaceContentRect(surface, false, IntRect(0, 0, 300, 300)));
     1862
     1863        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
    18091864        occlusion.markOccludedBehindLayer(layer);
    18101865        // Occlusion is not added for the animating layer.
    1811         EXPECT_EQ_RECT(IntRect(0, 0, 300, 300), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
     1866        EXPECT_EQ_RECT(IntRect(0, 0, 250, 300), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
    18121867    }
    18131868};
     
    18891944
    18901945        occlusion.finishedTargetRenderSurface(surface, surface->renderSurface());
    1891         occlusion.leaveToTargetRenderSurface(parent->renderSurface());
    1892         // The surface is moving in the screen and in its target, so all occlusion is lost when leaving it.
     1946
     1947        // The contributing |surface| is animating so it can't be occluded.
     1948        EXPECT_EQ_RECT(IntRect(0, 0, 300, 300), occlusion.unoccludedContributingSurfaceContentRect(surface, false, IntRect(0, 0, 300, 300)));
     1949
     1950        occlusion.leaveToTargetRenderSurface(parent->renderSurface());
     1951        // The surface is moving in the screen and in its target, so all occlusion within the surface is lost when leaving it.
    18931952        EXPECT_EQ_RECT(IntRect(50, 0, 250, 300), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
    18941953
     
    19582017        this->calcDrawEtc(parent);
    19592018
    1960         TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
     2019        TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
    19612020
    19622021        occlusion.enterTargetRenderSurface(surface->renderSurface());
     
    19742033MAIN_AND_IMPL_THREAD_TEST(CCOcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping);
    19752034
     2035template<class Types, bool opaqueLayers>
     2036class CCOcclusionTrackerTestReplicaOccluded : public CCOcclusionTrackerTest<Types, opaqueLayers> {
     2037protected:
     2038    void runMyTest()
     2039    {
     2040        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 200));
     2041        typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100), true);
     2042        this->createReplicaLayer(surface, this->identityMatrix, FloatPoint(0, 100), IntSize(100, 100));
     2043        typename Types::LayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 100), IntSize(100, 100), true);
     2044        this->calcDrawEtc(parent);
     2045
     2046        TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
     2047        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
     2048
     2049        // This occludes the replica, but not the surface itself.
     2050        occlusion.enterTargetRenderSurface(parent->renderSurface());
     2051        occlusion.markOccludedBehindLayer(topmost);
     2052
     2053        EXPECT_EQ_RECT(IntRect(0, 100, 100, 100), occlusion.occlusionInScreenSpace().bounds());
     2054        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
     2055        EXPECT_EQ_RECT(IntRect(0, 100, 100, 100), occlusion.occlusionInTargetSurface().bounds());
     2056        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
     2057
     2058        occlusion.enterTargetRenderSurface(surface->renderSurface());
     2059        occlusion.markOccludedBehindLayer(surface);
     2060
     2061        EXPECT_EQ_RECT(IntRect(0, 0, 100, 200), occlusion.occlusionInScreenSpace().bounds());
     2062        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
     2063        EXPECT_EQ_RECT(IntRect(0, 0, 100, 100), occlusion.occlusionInTargetSurface().bounds());
     2064        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
     2065
     2066        occlusion.finishedTargetRenderSurface(surface, surface->renderSurface());
     2067
     2068        // Surface is not occluded so it shouldn't think it is.
     2069        EXPECT_EQ_RECT(IntRect(0, 0, 100, 100), occlusion.unoccludedContributingSurfaceContentRect(surface, false, IntRect(0, 0, 100, 100)));
     2070    }
     2071};
     2072
     2073ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestReplicaOccluded);
     2074
     2075template<class Types, bool opaqueLayers>
     2076class CCOcclusionTrackerTestSurfaceWithReplicaUnoccluded : public CCOcclusionTrackerTest<Types, opaqueLayers> {
     2077protected:
     2078    void runMyTest()
     2079    {
     2080        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 200));
     2081        typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100), true);
     2082        this->createReplicaLayer(surface, this->identityMatrix, FloatPoint(0, 100), IntSize(100, 100));
     2083        typename Types::LayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 110), true);
     2084        this->calcDrawEtc(parent);
     2085
     2086        TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
     2087        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
     2088
     2089        // This occludes the surface, but not the entire surface's replica.
     2090        occlusion.enterTargetRenderSurface(parent->renderSurface());
     2091        occlusion.markOccludedBehindLayer(topmost);
     2092
     2093        EXPECT_EQ_RECT(IntRect(0, 0, 100, 110), occlusion.occlusionInScreenSpace().bounds());
     2094        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
     2095        EXPECT_EQ_RECT(IntRect(0, 0, 100, 110), occlusion.occlusionInTargetSurface().bounds());
     2096        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
     2097
     2098        occlusion.enterTargetRenderSurface(surface->renderSurface());
     2099        occlusion.markOccludedBehindLayer(surface);
     2100
     2101        EXPECT_EQ_RECT(IntRect(0, 0, 100, 110), occlusion.occlusionInScreenSpace().bounds());
     2102        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
     2103        EXPECT_EQ_RECT(IntRect(0, 0, 100, 100), occlusion.occlusionInTargetSurface().bounds());
     2104        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
     2105
     2106        occlusion.finishedTargetRenderSurface(surface, surface->renderSurface());
     2107
     2108        // Surface is occluded, but only the top 10px of the replica.
     2109        EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), occlusion.unoccludedContributingSurfaceContentRect(surface, false, IntRect(0, 0, 100, 100)));
     2110        EXPECT_EQ_RECT(IntRect(0, 10, 100, 90), occlusion.unoccludedContributingSurfaceContentRect(surface, true, IntRect(0, 0, 100, 100)));
     2111    }
     2112};
     2113
     2114ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestSurfaceWithReplicaUnoccluded);
     2115
     2116template<class Types, bool opaqueLayers>
     2117class CCOcclusionTrackerTestSurfaceAndReplicaOccludedDifferently : public CCOcclusionTrackerTest<Types, opaqueLayers> {
     2118protected:
     2119    void runMyTest()
     2120    {
     2121        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 200));
     2122        typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100), true);
     2123        this->createReplicaLayer(surface, this->identityMatrix, FloatPoint(0, 100), IntSize(100, 100));
     2124        typename Types::LayerType* overSurface = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(40, 100), true);
     2125        typename Types::LayerType* overReplica = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 100), IntSize(50, 100), true);
     2126        this->calcDrawEtc(parent);
     2127
     2128        TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
     2129        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
     2130
     2131        // These occlude the surface and replica differently, so we can test each one.
     2132        occlusion.enterTargetRenderSurface(parent->renderSurface());
     2133        occlusion.markOccludedBehindLayer(overReplica);
     2134        occlusion.markOccludedBehindLayer(overSurface);
     2135
     2136        EXPECT_EQ_RECT(IntRect(0, 0, 50, 200), occlusion.occlusionInScreenSpace().bounds());
     2137        EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
     2138        EXPECT_EQ_RECT(IntRect(0, 0, 50, 200), occlusion.occlusionInTargetSurface().bounds());
     2139        EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
     2140
     2141        occlusion.enterTargetRenderSurface(surface->renderSurface());
     2142        occlusion.markOccludedBehindLayer(surface);
     2143
     2144        EXPECT_EQ_RECT(IntRect(0, 0, 100, 200), occlusion.occlusionInScreenSpace().bounds());
     2145        EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
     2146        EXPECT_EQ_RECT(IntRect(0, 0, 100, 100), occlusion.occlusionInTargetSurface().bounds());
     2147        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
     2148
     2149        occlusion.finishedTargetRenderSurface(surface, surface->renderSurface());
     2150
     2151        // Surface and replica are occluded different amounts.
     2152        EXPECT_EQ_RECT(IntRect(40, 0, 60, 100), occlusion.unoccludedContributingSurfaceContentRect(surface, false, IntRect(0, 0, 100, 100)));
     2153        EXPECT_EQ_RECT(IntRect(50, 0, 50, 100), occlusion.unoccludedContributingSurfaceContentRect(surface, true, IntRect(0, 0, 100, 100)));
     2154    }
     2155};
     2156
     2157ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestSurfaceAndReplicaOccludedDifferently);
     2158
     2159template<class Types, bool opaqueLayers>
     2160class CCOcclusionTrackerTestSurfaceChildOfSurface : public CCOcclusionTrackerTest<Types, opaqueLayers> {
     2161protected:
     2162    void runMyTest()
     2163    {
     2164        // This test verifies that the surface cliprect does not end up empty and clip away the entire unoccluded rect.
     2165
     2166        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 200));
     2167        typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100), true);
     2168        typename Types::LayerType* surfaceChild = this->createDrawingSurface(surface, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100), false);
     2169        typename Types::LayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 50), true);
     2170        this->calcDrawEtc(parent);
     2171
     2172        TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
     2173        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
     2174
     2175        // This occludes everything partially so we know occlusion is happening at all.
     2176        occlusion.enterTargetRenderSurface(parent->renderSurface());
     2177        occlusion.markOccludedBehindLayer(topmost);
     2178
     2179        EXPECT_EQ_RECT(IntRect(0, 0, 100, 50), occlusion.occlusionInScreenSpace().bounds());
     2180        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
     2181        EXPECT_EQ_RECT(IntRect(0, 0, 100, 50), occlusion.occlusionInTargetSurface().bounds());
     2182        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
     2183
     2184        occlusion.enterTargetRenderSurface(surfaceChild->renderSurface());
     2185        // surfaceChild is not opaque and does not occlude, so we have a non-empty unoccluded area on surface.
     2186        occlusion.markOccludedBehindLayer(surfaceChild);
     2187
     2188        EXPECT_EQ_RECT(IntRect(0, 0, 100, 50), occlusion.occlusionInScreenSpace().bounds());
     2189        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
     2190        EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), occlusion.occlusionInTargetSurface().bounds());
     2191        EXPECT_EQ(0u, occlusion.occlusionInTargetSurface().rects().size());
     2192
     2193        // The root layer always has a clipRect. So the parent of |surface| has a clipRect. However, the owning layer for |surface| does not
     2194        // mask to bounds, so it doesn't have a clipRect of its own. Thus the parent of |surfaceChild| exercises different code paths
     2195        // as its parent does not have a clipRect.
     2196
     2197        occlusion.finishedTargetRenderSurface(surfaceChild, surfaceChild->renderSurface());
     2198        // The surfaceChild's parent does not have a clipRect as it owns a render surface.
     2199        EXPECT_EQ_RECT(IntRect(0, 50, 100, 50), occlusion.unoccludedContributingSurfaceContentRect(surfaceChild, false, IntRect(0, 0, 100, 100)));
     2200
     2201        occlusion.leaveToTargetRenderSurface(surface->renderSurface());
     2202        occlusion.markOccludedBehindLayer(surface);
     2203
     2204        occlusion.finishedTargetRenderSurface(surface, surface->renderSurface());
     2205        // The surface's parent does have a clipRect as it is the root layer.
     2206        EXPECT_EQ_RECT(IntRect(0, 50, 100, 50), occlusion.unoccludedContributingSurfaceContentRect(surface, false, IntRect(0, 0, 100, 100)));
     2207    }
     2208};
     2209
     2210ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestSurfaceChildOfSurface);
     2211
     2212template<class Types, bool opaqueLayers>
     2213class CCOcclusionTrackerTestSurfaceChildOfClippingSurface : public CCOcclusionTrackerTest<Types, opaqueLayers> {
     2214protected:
     2215    void runMyTest()
     2216    {
     2217        // This test verifies that the surface cliprect does not end up empty and clip away the entire unoccluded rect.
     2218
     2219        typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(80, 200));
     2220        typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100), true);
     2221        typename Types::LayerType* surfaceChild = this->createDrawingSurface(surface, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100), false);
     2222        typename Types::LayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 50), true);
     2223        this->calcDrawEtc(parent);
     2224
     2225        TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
     2226        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
     2227
     2228        // This occludes everything partially so we know occlusion is happening at all.
     2229        occlusion.enterTargetRenderSurface(parent->renderSurface());
     2230        occlusion.markOccludedBehindLayer(topmost);
     2231
     2232        EXPECT_EQ_RECT(IntRect(0, 0, 80, 50), occlusion.occlusionInScreenSpace().bounds());
     2233        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
     2234        EXPECT_EQ_RECT(IntRect(0, 0, 80, 50), occlusion.occlusionInTargetSurface().bounds());
     2235        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
     2236
     2237        occlusion.enterTargetRenderSurface(surfaceChild->renderSurface());
     2238        // surfaceChild is not opaque and does not occlude, so we have a non-empty unoccluded area on surface.
     2239        occlusion.markOccludedBehindLayer(surfaceChild);
     2240
     2241        EXPECT_EQ_RECT(IntRect(0, 0, 80, 50), occlusion.occlusionInScreenSpace().bounds());
     2242        EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
     2243        EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), occlusion.occlusionInTargetSurface().bounds());
     2244        EXPECT_EQ(0u, occlusion.occlusionInTargetSurface().rects().size());
     2245
     2246        // The root layer always has a clipRect. So the parent of |surface| has a clipRect. However, the owning layer for |surface| does not
     2247        // mask to bounds, so it doesn't have a clipRect of its own. Thus the parent of |surfaceChild| exercises different code paths
     2248        // as its parent does not have a clipRect.
     2249
     2250        occlusion.finishedTargetRenderSurface(surfaceChild, surfaceChild->renderSurface());
     2251        // The surfaceChild's parent does not have a clipRect as it owns a render surface.
     2252        EXPECT_EQ_RECT(IntRect(0, 50, 80, 50), occlusion.unoccludedContributingSurfaceContentRect(surfaceChild, false, IntRect(0, 0, 100, 100)));
     2253
     2254        occlusion.leaveToTargetRenderSurface(surface->renderSurface());
     2255        occlusion.markOccludedBehindLayer(surface);
     2256
     2257        occlusion.finishedTargetRenderSurface(surface, surface->renderSurface());
     2258        // The surface's parent does have a clipRect as it is the root layer.
     2259        EXPECT_EQ_RECT(IntRect(0, 50, 80, 50), occlusion.unoccludedContributingSurfaceContentRect(surface, false, IntRect(0, 0, 100, 100)));
     2260    }
     2261};
     2262
     2263ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestSurfaceChildOfClippingSurface);
     2264
    19762265} // namespace
Note: See TracChangeset for help on using the changeset viewer.