Changeset 106324 in webkit


Ignore:
Timestamp:
Jan 30, 2012 8:03:00 PM (12 years ago)
Author:
commit-queue@webkit.org
Message:

[chromium] Compute occlusion during paint loop
https://bugs.webkit.org/show_bug.cgi?id=76858

Patch by Dana Jansens <danakj@chromium.org> on 2012-01-30
Reviewed by James Robinson.

Source/WebCore:

New unit tests in TiledLayerChromiumTest.cpp, CCLayerTreeHostCommonTest.cpp, CCLayerTreeHostTest.cpp

  • platform/graphics/FloatRect.cpp:

(WebCore::enclosedIntRect):
(WebCore):

  • platform/graphics/FloatRect.h:

(WebCore):

  • platform/graphics/chromium/Canvas2DLayerChromium.cpp:

(WebCore::Canvas2DLayerChromium::paintContentsIfDirty):

  • platform/graphics/chromium/Canvas2DLayerChromium.h:

(Canvas2DLayerChromium):

  • platform/graphics/chromium/ContentLayerChromium.cpp:

(WebCore::ContentLayerChromium::paintContentsIfDirty):

  • platform/graphics/chromium/ContentLayerChromium.h:

(ContentLayerChromium):

  • platform/graphics/chromium/ImageLayerChromium.cpp:

(WebCore::ImageLayerChromium::paintContentsIfDirty):

  • platform/graphics/chromium/ImageLayerChromium.h:

(ImageLayerChromium):

  • platform/graphics/chromium/LayerChromium.cpp:

(WebCore::LayerChromium::contentToScreenSpaceTransform):
(WebCore):
(WebCore::LayerChromium::addSelfToOccludedScreenSpace):
(WebCore::LayerChromium::isPaintedAxisAlignedInScreen):

  • platform/graphics/chromium/LayerChromium.h:

(WebCore):
(WebCore::LayerChromium::paintContentsIfDirty):
(LayerChromium):

  • platform/graphics/chromium/RenderSurfaceChromium.h:

(RenderSurfaceChromium):

  • platform/graphics/chromium/TiledLayerChromium.cpp:

(WebCore::TiledLayerChromium::addSelfToOccludedScreenSpace):

  • platform/graphics/chromium/TiledLayerChromium.h:

(WebCore):
():

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

(WebCore::CCLayerTreeHost::paintContentsIfDirty):
(WebCore::CCLayerTreeHost::paintMaskAndReplicaForRenderSurface):
(RenderSurfaceRegion):
(WebCore):
(WebCore::pushTargetRenderSurfaceRegion):
(WebCore::popAndPushTargetRenderSurfaceRegion):
(WebCore::CCLayerTreeHost::paintLayerContents):

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

(WebCore):
():

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

Source/WebKit/chromium:

  • tests/CCLayerTreeHostCommonTest.cpp:

(WebCore::TEST):
(WebCore):

  • tests/CCLayerTreeHostTest.cpp:

(WTF::ContentLayerChromiumWithUpdateTracking::paintContentsIfDirty):
(WTF):
(TestLayerChromium):
(WTF::TestLayerChromium::create):
(WTF::TestLayerChromium::paintContentsIfDirty):
(WTF::TestLayerChromium::drawsContent):
(WTF::TestLayerChromium::occludedScreenSpace):
(WTF::TestLayerChromium::clearOccludedScreenSpace):
(WTF::TestLayerChromium::TestLayerChromium):
(WTF::setLayerPropertiesForTesting):
(CCLayerTreeHostTestLayerOcclusion):
(WTF::CCLayerTreeHostTestLayerOcclusion::CCLayerTreeHostTestLayerOcclusion):
(WTF::CCLayerTreeHostTestLayerOcclusion::beginTest):
(WTF::CCLayerTreeHostTestLayerOcclusion::afterTest):

  • tests/Canvas2DLayerChromiumTest.cpp:

(WebCore::Canvas2DLayerChromiumTest::fullLifecycleTest):

  • tests/TiledLayerChromiumTest.cpp:

(WTF::FakeLayerTextureUpdater::setOpaquePaintRect):
(FakeLayerTextureUpdater):
(WTF::FakeTiledLayerChromium::paintContentsIfDirty):
(WTF::FakeLayerTextureUpdater::prepareToUpdate):
(WTF::TEST):
(WTF):

Location:
trunk/Source
Files:
22 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r106323 r106324  
     12012-01-30  Dana Jansens  <danakj@chromium.org>
     2
     3        [chromium] Compute occlusion during paint loop
     4        https://bugs.webkit.org/show_bug.cgi?id=76858
     5
     6        Reviewed by James Robinson.
     7
     8        New unit tests in TiledLayerChromiumTest.cpp, CCLayerTreeHostCommonTest.cpp, CCLayerTreeHostTest.cpp
     9
     10        * platform/graphics/FloatRect.cpp:
     11        (WebCore::enclosedIntRect):
     12        (WebCore):
     13        * platform/graphics/FloatRect.h:
     14        (WebCore):
     15        * platform/graphics/chromium/Canvas2DLayerChromium.cpp:
     16        (WebCore::Canvas2DLayerChromium::paintContentsIfDirty):
     17        * platform/graphics/chromium/Canvas2DLayerChromium.h:
     18        (Canvas2DLayerChromium):
     19        * platform/graphics/chromium/ContentLayerChromium.cpp:
     20        (WebCore::ContentLayerChromium::paintContentsIfDirty):
     21        * platform/graphics/chromium/ContentLayerChromium.h:
     22        (ContentLayerChromium):
     23        * platform/graphics/chromium/ImageLayerChromium.cpp:
     24        (WebCore::ImageLayerChromium::paintContentsIfDirty):
     25        * platform/graphics/chromium/ImageLayerChromium.h:
     26        (ImageLayerChromium):
     27        * platform/graphics/chromium/LayerChromium.cpp:
     28        (WebCore::LayerChromium::contentToScreenSpaceTransform):
     29        (WebCore):
     30        (WebCore::LayerChromium::addSelfToOccludedScreenSpace):
     31        (WebCore::LayerChromium::isPaintedAxisAlignedInScreen):
     32        * platform/graphics/chromium/LayerChromium.h:
     33        (WebCore):
     34        (WebCore::LayerChromium::paintContentsIfDirty):
     35        (LayerChromium):
     36        * platform/graphics/chromium/RenderSurfaceChromium.h:
     37        (RenderSurfaceChromium):
     38        * platform/graphics/chromium/TiledLayerChromium.cpp:
     39        (WebCore::TiledLayerChromium::addSelfToOccludedScreenSpace):
     40        * platform/graphics/chromium/TiledLayerChromium.h:
     41        (WebCore):
     42        ():
     43        * platform/graphics/chromium/cc/CCLayerTreeHost.cpp:
     44        (WebCore::CCLayerTreeHost::paintContentsIfDirty):
     45        (WebCore::CCLayerTreeHost::paintMaskAndReplicaForRenderSurface):
     46        (RenderSurfaceRegion):
     47        (WebCore):
     48        (WebCore::pushTargetRenderSurfaceRegion):
     49        (WebCore::popAndPushTargetRenderSurfaceRegion):
     50        (WebCore::CCLayerTreeHost::paintLayerContents):
     51        * platform/graphics/chromium/cc/CCLayerTreeHost.h:
     52        (WebCore):
     53        ():
     54        * platform/graphics/chromium/cc/CCQuadCuller.cpp:
     55
    1562012-01-30  Caio Marcelo de Oliveira Filho  <caio.oliveira@openbossa.org>
    257
  • trunk/Source/WebCore/platform/graphics/FloatRect.cpp

    r105643 r106324  
    219219}
    220220
     221IntRect enclosedIntRect(const FloatRect& rect)
     222{
     223    int x = clampToInteger(ceilf(rect.x()));
     224    int y = clampToInteger(ceilf(rect.y()));
     225    float maxX = clampToInteger(floorf(rect.maxX()));
     226    float maxY = clampToInteger(floorf(rect.maxY()));
     227    // A rect of width 0 should not become a rect of width -1 due to ceil/floor.
     228    int width = max(clampToInteger(maxX - x), 0);
     229    int height = max(clampToInteger(maxY - y), 0);
     230
     231    return IntRect(x, y, width, height);
     232}
     233
    221234FloatRect mapRect(const FloatRect& r, const FloatRect& srcRect, const FloatRect& destRect)
    222235{
  • trunk/Source/WebCore/platform/graphics/FloatRect.h

    r105231 r106324  
    271271IntRect enclosingIntRect(const FloatRect&);
    272272
     273// Returns a valid IntRect contained within the given FloatRect.
     274IntRect enclosedIntRect(const FloatRect&);
     275
    273276// Map rect r from srcRect to an equivalent rect in destRect.
    274277FloatRect mapRect(const FloatRect& r, const FloatRect& srcRect, const FloatRect& destRect);
  • trunk/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp

    r105544 r106324  
    9292}
    9393
    94 void Canvas2DLayerChromium::paintContentsIfDirty()
     94void Canvas2DLayerChromium::paintContentsIfDirty(const Region& /* occludedScreenSpace */)
    9595{
    9696    if (!drawsContent())
  • trunk/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h

    r104044 r106324  
    4141
    4242class GraphicsContext3D;
     43class Region;
    4344
    4445// A layer containing an accelerated 2d canvas
     
    5354
    5455    virtual bool drawsContent() const;
    55     virtual void paintContentsIfDirty();
     56    virtual void paintContentsIfDirty(const Region& occludedScreenSpace);
    5657
    5758    virtual void setLayerTreeHost(CCLayerTreeHost*);
  • trunk/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp

    r105783 r106324  
    9494}
    9595
    96 void ContentLayerChromium::paintContentsIfDirty()
     96void ContentLayerChromium::paintContentsIfDirty(const Region& /* occludedScreenSpace */)
    9797{
    9898    updateTileSizeAndTilingOption();
  • trunk/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h

    r105783 r106324  
    4242class LayerTilerChromium;
    4343class LayerTextureUpdater;
     44class Region;
    4445
    4546class ContentLayerDelegate {
     
    5960
    6061    virtual bool drawsContent() const;
    61     virtual void paintContentsIfDirty();
     62    virtual void paintContentsIfDirty(const Region& occludedScreenSpace);
    6263    virtual void idlePaintContentsIfDirty();
    6364
  • trunk/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp

    r105460 r106324  
    159159}
    160160
    161 void ImageLayerChromium::paintContentsIfDirty()
     161void ImageLayerChromium::paintContentsIfDirty(const Region& /* occludedScreenSpace */)
    162162{
    163163    if (m_needsDisplay) {
  • trunk/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h

    r105460 r106324  
    4646class Image;
    4747class ImageLayerTextureUpdater;
     48class Region;
    4849
    4950// A Layer that contains only an Image element.
     
    5455
    5556    virtual bool drawsContent() const;
    56     virtual void paintContentsIfDirty();
     57    virtual void paintContentsIfDirty(const Region& occludedScreenSpace);
    5758    virtual bool needsContentsScale() const;
    5859
  • trunk/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp

    r106300 r106324  
    4040#include "PlatformContextSkia.h"
    4141#endif
     42#include "Region.h"
    4243#include "RenderLayerBacking.h"
    4344#include "TextStream.h"
     
    470471}
    471472
     473TransformationMatrix LayerChromium::contentToScreenSpaceTransform() const
     474{
     475    IntSize boundsInLayerSpace = bounds();
     476    IntSize boundsInContentSpace = contentBounds();
     477
     478    TransformationMatrix transform = screenSpaceTransform();
     479
     480    // Scale from content space to layer space
     481    transform.scaleNonUniform(boundsInLayerSpace.width() / static_cast<double>(boundsInContentSpace.width()),
     482                              boundsInLayerSpace.height() / static_cast<double>(boundsInContentSpace.height()));
     483
     484    return transform;
     485}
     486
     487void LayerChromium::addSelfToOccludedScreenSpace(Region& occludedScreenSpace)
     488{
     489    if (!opaque() || drawOpacity() != 1 || !isPaintedAxisAlignedInScreen())
     490        return;
     491
     492    FloatRect targetRect = contentToScreenSpaceTransform().mapRect(FloatRect(visibleLayerRect()));
     493    occludedScreenSpace.unite(enclosedIntRect(targetRect));
     494}
     495
     496bool LayerChromium::isPaintedAxisAlignedInScreen() const
     497{
     498    FloatQuad quad = contentToScreenSpaceTransform().mapQuad(FloatQuad(visibleLayerRect()));
     499    return quad.isRectilinear();
     500}
     501
    472502void LayerChromium::createRenderSurface()
    473503{
  • trunk/Source/WebCore/platform/graphics/chromium/LayerChromium.h

    r106289 r106324  
    5656class CCTextureUpdater;
    5757class GraphicsContext3D;
     58class Region;
    5859
    5960// Base class for composited layers. Special layer types are derived from
     
    154155    // These methods typically need to be overwritten by derived classes.
    155156    virtual bool drawsContent() const { return m_isDrawable; }
    156     virtual void paintContentsIfDirty() { }
     157    virtual void paintContentsIfDirty(const Region& /* occludedScreenSpace */) { }
    157158    virtual void idlePaintContentsIfDirty() { }
    158159    virtual void updateCompositorResources(GraphicsContext3D*, CCTextureUpdater&) { }
     
    183184    RenderSurfaceChromium* targetRenderSurface() const { return m_targetRenderSurface; }
    184185    void setTargetRenderSurface(RenderSurfaceChromium* surface) { m_targetRenderSurface = surface; }
     186    // This moves from layer space, with origin in the center to target space with origin in the top left
    185187    const TransformationMatrix& drawTransform() const { return m_drawTransform; }
    186188    void setDrawTransform(const TransformationMatrix& matrix) { m_drawTransform = matrix; }
     189    // This moves from layer space, with origin the top left to screen space with origin in the top left
    187190    const TransformationMatrix& screenSpaceTransform() const { return m_screenSpaceTransform; }
    188191    void setScreenSpaceTransform(const TransformationMatrix& matrix) { m_screenSpaceTransform = matrix; }
     
    192195    void setContentsScale(float);
    193196
     197    TransformationMatrix contentToScreenSpaceTransform() const;
     198
     199    // Adds any opaque visible pixels to the occluded region.
     200    virtual void addSelfToOccludedScreenSpace(Region& occludedScreenSpace);
     201
    194202    // Returns true if any of the layer's descendants has content to draw.
    195203    bool descendantDrawsContent();
     
    211219    // hold context-dependent resources such as textures.
    212220    virtual void cleanupResources();
     221
     222    bool isPaintedAxisAlignedInScreen() const;
    213223
    214224    void setNeedsCommit();
  • trunk/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h

    r104626 r106324  
    6464    void setDrawOpacity(float drawOpacity) { m_drawOpacity = drawOpacity; }
    6565
     66    // This goes from content space with the origin in the center of the rect being transformed to the target space with the origin in the top left of the
     67    // rect being transformed. Position the rect so that the origin is in the center of it before applying this transform.
    6668    const TransformationMatrix& drawTransform() const { return m_drawTransform; }
    6769    void setDrawTransform(const TransformationMatrix& drawTransform) { m_drawTransform = drawTransform; }
  • trunk/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp

    r106300 r106324  
    489489}
    490490
     491void TiledLayerChromium::addSelfToOccludedScreenSpace(Region& occludedScreenSpace)
     492{
     493    if (m_skipsDraw || drawOpacity() != 1 || !isPaintedAxisAlignedInScreen())
     494        return;
     495
     496    if (opaque()) {
     497        LayerChromium::addSelfToOccludedScreenSpace(occludedScreenSpace);
     498        return;
     499    }
     500
     501    IntRect visibleRect = visibleLayerRect();
     502    TransformationMatrix contentTransform = contentToScreenSpaceTransform();
     503
     504    // FIXME: Create/Use a FloatRegion for the occludedScreenSpace, instead of a Region based on ints, to avoid this step and get better accuracy between layers in target space.
     505    Region tileRegion;
     506    int left, top, right, bottom;
     507    m_tiler->layerRectToTileIndices(visibleLayerRect(), left, top, right, bottom);
     508    for (int j = top; j <= bottom; ++j) {
     509        for (int i = left; i <= right; ++i) {
     510            UpdatableTile* tile = tileAt(i, j);
     511            if (tile) {
     512                IntRect visibleTileOpaqueRect = intersection(visibleRect, tile->m_opaqueRect);
     513                FloatRect screenRect = contentTransform.mapRect(FloatRect(visibleTileOpaqueRect));
     514                occludedScreenSpace.unite(enclosedIntRect(screenRect));
     515            }
     516        }
     517    }
     518}
     519
    491520void TiledLayerChromium::prepareToUpdate(const IntRect& layerRect)
    492521{
  • trunk/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.h

    r106289 r106324  
    3636
    3737class LayerTextureUpdater;
     38class Region;
    3839class UpdatableTile;
    3940
     
    6364
    6465    virtual void reserveTextures();
     66
     67    virtual void addSelfToOccludedScreenSpace(Region& occludedScreenSpace);
    6568
    6669protected:
  • trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp

    r106289 r106324  
    3030#include "LayerPainterChromium.h"
    3131#include "LayerRendererChromium.h"
     32#include "Region.h"
    3233#include "TraceEvent.h"
    3334#include "TreeSynchronizer.h"
     
    414415
    415416// static
    416 void CCLayerTreeHost::paintContentsIfDirty(LayerChromium* layer, PaintType paintType)
     417void CCLayerTreeHost::paintContentsIfDirty(LayerChromium* layer, PaintType paintType, const Region& occludedScreenSpace)
    417418{
    418419    ASSERT(layer);
    419420    ASSERT(PaintVisible == paintType || PaintIdle == paintType);
    420421    if (PaintVisible == paintType)
    421         layer->paintContentsIfDirty();
     422        layer->paintContentsIfDirty(occludedScreenSpace);
    422423    else
    423424        layer->idlePaintContentsIfDirty();
     
    430431    // mask and replica should be painted.
    431432
     433    // FIXME: If the surface has a replica, it should be painted with occlusion that excludes the current target surface subtree.
     434    Region noOcclusion;
     435
    432436    if (renderSurfaceLayer->maskLayer()) {
    433437        renderSurfaceLayer->maskLayer()->setVisibleLayerRect(IntRect(IntPoint(), renderSurfaceLayer->contentBounds()));
    434         paintContentsIfDirty(renderSurfaceLayer->maskLayer(), paintType);
     438        paintContentsIfDirty(renderSurfaceLayer->maskLayer(), paintType, noOcclusion);
    435439    }
    436440
    437441    LayerChromium* replicaLayer = renderSurfaceLayer->replicaLayer();
    438442    if (replicaLayer) {
    439         paintContentsIfDirty(replicaLayer, paintType);
     443        paintContentsIfDirty(replicaLayer, paintType, noOcclusion);
    440444
    441445        if (replicaLayer->maskLayer()) {
    442446            replicaLayer->maskLayer()->setVisibleLayerRect(IntRect(IntPoint(), replicaLayer->maskLayer()->contentBounds()));
    443             paintContentsIfDirty(replicaLayer->maskLayer(), paintType);
     447            paintContentsIfDirty(replicaLayer->maskLayer(), paintType, noOcclusion);
    444448        }
     449    }
     450}
     451
     452struct RenderSurfaceRegion {
     453    RenderSurfaceChromium* surface;
     454    Region occludedInScreen;
     455};
     456
     457// Add the surface to the top of the stack and copy the occlusion from the old top of the stack to the new.
     458static void enterTargetRenderSurface(Vector<RenderSurfaceRegion>& stack, RenderSurfaceChromium* newTarget)
     459{
     460    if (stack.isEmpty()) {
     461        stack.append(RenderSurfaceRegion());
     462        stack.last().surface = newTarget;
     463    } else if (stack.last().surface != newTarget) {
     464        const RenderSurfaceRegion& previous = stack.last();
     465        stack.append(RenderSurfaceRegion());
     466        stack.last().surface = newTarget;
     467        stack.last().occludedInScreen = previous.occludedInScreen;
     468    }
     469}
     470
     471// Pop the top of the stack off, push on the new surface, and merge the old top's occlusion into the new top surface.
     472static void leaveTargetRenderSurface(Vector<RenderSurfaceRegion>& stack, RenderSurfaceChromium* newTarget)
     473{
     474    int lastIndex = stack.size() - 1;
     475    bool surfaceWillBeAtTopAfterPop = stack.size() > 1 && stack[lastIndex - 1].surface == newTarget;
     476
     477    if (surfaceWillBeAtTopAfterPop) {
     478        // Merge the top of the stack down.
     479        stack[lastIndex - 1].occludedInScreen.unite(stack[lastIndex].occludedInScreen);
     480        stack.removeLast();
     481    } else {
     482        // Replace the top of the stack with the new pushed surface. Copy the occluded region to the top.
     483        stack.last().surface = newTarget;
    445484    }
    446485}
     
    450489    // Use FrontToBack to allow for testing occlusion and performing culling during the tree walk.
    451490    typedef CCLayerIterator<LayerChromium, RenderSurfaceChromium, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType;
     491
     492    // The stack holds occluded regions for subtrees in the RenderSurface-Layer tree, so that when we leave a subtree we may
     493    // apply a mask to it, but not to the parts outside the subtree.
     494    // - The first time we see a new subtree under a target, we add that target to the top of the stack. This can happen as a layer representing itself, or as a target surface.
     495    // - When we visit a target surface, we apply its mask to its subtree, which is at the top of the stack.
     496    // - When we visit a layer representing itself, we add its occlusion to the current subtree, which is at the top of the stack.
     497    // - When we visit a layer representing a contributing surface, the current target will never be the top of the stack since we just came from the contributing surface.
     498    // We merge the occlusion at the top of the stack with the new current subtree. This new target is pushed onto the stack if not already there.
     499    Vector<RenderSurfaceRegion> targetSurfaceStack;
    452500
    453501    CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList);
     
    455503        if (it.representsTargetRenderSurface()) {
    456504            ASSERT(it->renderSurface()->drawOpacity());
     505
     506            enterTargetRenderSurface(targetSurfaceStack, it->renderSurface());
    457507            paintMaskAndReplicaForRenderSurface(*it, paintType);
     508            // FIXME: add the replica layer to the current occlusion
     509
     510            if (it->maskLayer() || it->renderSurface()->drawOpacity() < 1)
     511                targetSurfaceStack.last().occludedInScreen = Region();
    458512        } else if (it.representsItself()) {
    459513            ASSERT(!it->bounds().isEmpty());
    460             paintContentsIfDirty(*it, paintType);
     514
     515            enterTargetRenderSurface(targetSurfaceStack, it->targetRenderSurface());
     516            paintContentsIfDirty(*it, paintType, targetSurfaceStack.last().occludedInScreen);
     517            it->addSelfToOccludedScreenSpace(targetSurfaceStack.last().occludedInScreen);
     518        } else {
     519            leaveTargetRenderSurface(targetSurfaceStack, it.targetRenderSurfaceLayer()->renderSurface());
    461520        }
    462521    }
  • trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h

    r106289 r106324  
    4949class GraphicsContext3D;
    5050class LayerPainterChromium;
     51class Region;
    5152class TextureAllocator;
    5253class TextureManager;
     
    206207
    207208    enum PaintType { PaintVisible, PaintIdle };
    208     static void paintContentsIfDirty(LayerChromium*, PaintType);
     209    static void paintContentsIfDirty(LayerChromium*, PaintType, const Region& occludedScreenSpace);
    209210    void paintLayerContents(const LayerList&, PaintType);
    210211    void paintMaskAndReplicaForRenderSurface(LayerChromium*, PaintType);
  • trunk/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp

    r106300 r106324  
    7676}
    7777
    78 static IntRect enclosedIntRect(const FloatRect& rect)
    79 {
    80     float x = ceilf(rect.x());
    81     float y = ceilf(rect.y());
    82     // A rect of width 0 should not become a rect of width -1.
    83     float width = max<float>(floorf(rect.maxX()) - x, 0);
    84     float height = max<float>(floorf(rect.maxY()) - y, 0);
    85 
    86     return IntRect(clampToInteger(x), clampToInteger(y),
    87                    clampToInteger(width), clampToInteger(height));
    88 }
    89 
    9078void CCQuadCuller::cullOccludedQuads(CCQuadList& quadList)
    9179{
  • trunk/Source/WebKit/chromium/ChangeLog

    r106320 r106324  
     12012-01-30  Dana Jansens  <danakj@chromium.org>
     2
     3        [chromium] Compute occlusion during paint loop
     4        https://bugs.webkit.org/show_bug.cgi?id=76858
     5
     6        Reviewed by James Robinson.
     7
     8        * tests/CCLayerTreeHostCommonTest.cpp:
     9        (WebCore::TEST):
     10        (WebCore):
     11        * tests/CCLayerTreeHostTest.cpp:
     12        (WTF::ContentLayerChromiumWithUpdateTracking::paintContentsIfDirty):
     13        (WTF):
     14        (TestLayerChromium):
     15        (WTF::TestLayerChromium::create):
     16        (WTF::TestLayerChromium::paintContentsIfDirty):
     17        (WTF::TestLayerChromium::drawsContent):
     18        (WTF::TestLayerChromium::occludedScreenSpace):
     19        (WTF::TestLayerChromium::clearOccludedScreenSpace):
     20        (WTF::TestLayerChromium::TestLayerChromium):
     21        (WTF::setLayerPropertiesForTesting):
     22        (CCLayerTreeHostTestLayerOcclusion):
     23        (WTF::CCLayerTreeHostTestLayerOcclusion::CCLayerTreeHostTestLayerOcclusion):
     24        (WTF::CCLayerTreeHostTestLayerOcclusion::beginTest):
     25        (WTF::CCLayerTreeHostTestLayerOcclusion::afterTest):
     26        * tests/Canvas2DLayerChromiumTest.cpp:
     27        (WebCore::Canvas2DLayerChromiumTest::fullLifecycleTest):
     28        * tests/TiledLayerChromiumTest.cpp:
     29        (WTF::FakeLayerTextureUpdater::setOpaquePaintRect):
     30        (FakeLayerTextureUpdater):
     31        (WTF::FakeTiledLayerChromium::paintContentsIfDirty):
     32        (WTF::FakeLayerTextureUpdater::prepareToUpdate):
     33        (WTF::TEST):
     34        (WTF):
     35
    1362012-01-30  Gregg Tavares  <gman@google.com>
    237
  • trunk/Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp

    r105460 r106324  
    2929#include "CCLayerTreeTestCommon.h"
    3030#include "LayerChromium.h"
     31#include "Region.h"
    3132#include "TransformationMatrix.h"
    3233
     
    3536
    3637using namespace WebCore;
     38
     39#define EXPECT_EQ_RECT(a, b) \
     40    EXPECT_EQ(a.x(), b.x()); \
     41    EXPECT_EQ(a.y(), b.y()); \
     42    EXPECT_EQ(a.width(), b.width()); \
     43    EXPECT_EQ(a.height(), b.height());
    3744
    3845namespace {
     
    596603//
    597604
     605TEST(CCLayerTreeHostCommonTest, layerAddsSelfToOccludedRegion)
     606{
     607    // This tests that the right transforms are being used.
     608    Region occluded;
     609    const TransformationMatrix identityMatrix;
     610    RefPtr<LayerChromium> parent = LayerChromium::create();
     611    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
     612    parent->createRenderSurface();
     613    parent->addChild(layer);
     614
     615    setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
     616    setLayerPropertiesForTesting(layer.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false);
     617
     618    layer->setOpaque(true);
     619
     620    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
     621    Vector<RefPtr<LayerChromium> > dummyLayerList;
     622    int dummyMaxTextureSize = 512;
     623
     624    // FIXME: when we fix this "root-layer special case" behavior in CCLayerTreeHost, we will have to fix it here, too.
     625    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
     626    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
     627    renderSurfaceLayerList.append(parent);
     628
     629    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
     630
     631    occluded = Region();
     632    layer->addSelfToOccludedScreenSpace(occluded);
     633    EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occluded.bounds());
     634    EXPECT_EQ(1u, occluded.rects().size());
     635}
     636
     637TEST(CCLayerTreeHostCommonTest, layerAddsSelfToOccludedRegionWithRotation)
     638{
     639    // This tests that the right transforms are being used.
     640    Region occluded;
     641    const TransformationMatrix identityMatrix;
     642    RefPtr<LayerChromium> parent = LayerChromium::create();
     643    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
     644    parent->createRenderSurface();
     645    parent->addChild(layer);
     646
     647    TransformationMatrix layerTransform;
     648    layerTransform.translate(250, 250);
     649    layerTransform.rotate(90);
     650    layerTransform.translate(-250, -250);
     651
     652    setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
     653    setLayerPropertiesForTesting(layer.get(), layerTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false);
     654
     655    layer->setOpaque(true);
     656
     657    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
     658    Vector<RefPtr<LayerChromium> > dummyLayerList;
     659    int dummyMaxTextureSize = 512;
     660
     661    // FIXME: when we fix this "root-layer special case" behavior in CCLayerTreeHost, we will have to fix it here, too.
     662    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
     663    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
     664    renderSurfaceLayerList.append(parent);
     665
     666    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
     667
     668    occluded = Region();
     669    layer->addSelfToOccludedScreenSpace(occluded);
     670    EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occluded.bounds());
     671    EXPECT_EQ(1u, occluded.rects().size());
     672}
     673
     674TEST(CCLayerTreeHostCommonTest, layerAddsSelfToOccludedRegionWithTranslation)
     675{
     676    // This tests that the right transforms are being used.
     677    Region occluded;
     678    const TransformationMatrix identityMatrix;
     679    RefPtr<LayerChromium> parent = LayerChromium::create();
     680    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
     681    parent->createRenderSurface();
     682    parent->addChild(layer);
     683
     684    TransformationMatrix layerTransform;
     685    layerTransform.translate(20, 20);
     686
     687    setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
     688    setLayerPropertiesForTesting(layer.get(), layerTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false);
     689
     690    layer->setOpaque(true);
     691
     692    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
     693    Vector<RefPtr<LayerChromium> > dummyLayerList;
     694    int dummyMaxTextureSize = 512;
     695
     696    // FIXME: when we fix this "root-layer special case" behavior in CCLayerTreeHost, we will have to fix it here, too.
     697    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
     698    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
     699    renderSurfaceLayerList.append(parent);
     700
     701    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
     702
     703    occluded = Region();
     704    layer->addSelfToOccludedScreenSpace(occluded);
     705    EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), occluded.bounds());
     706    EXPECT_EQ(1u, occluded.rects().size());
     707}
     708
     709TEST(CCLayerTreeHostCommonTest, layerAddsSelfToOccludedRegionWithRotatedSurface)
     710{
     711    // This tests that the right transforms are being used.
     712    Region occluded;
     713    const TransformationMatrix identityMatrix;
     714    RefPtr<LayerChromium> parent = LayerChromium::create();
     715    RefPtr<LayerChromium> child = LayerChromium::create();
     716    RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
     717    parent->createRenderSurface();
     718    parent->addChild(child);
     719    child->addChild(layer);
     720
     721    TransformationMatrix childTransform;
     722    childTransform.translate(250, 250);
     723    childTransform.rotate(90);
     724    childTransform.translate(-250, -250);
     725
     726    setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
     727    setLayerPropertiesForTesting(child.get(), childTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false);
     728    setLayerPropertiesForTesting(layer.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), false);
     729
     730    child->setMasksToBounds(true);
     731    layer->setOpaque(true);
     732
     733    Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
     734    Vector<RefPtr<LayerChromium> > dummyLayerList;
     735    int dummyMaxTextureSize = 512;
     736
     737    // FIXME: when we fix this "root-layer special case" behavior in CCLayerTreeHost, we will have to fix it here, too.
     738    parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
     739    parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
     740    renderSurfaceLayerList.append(parent);
     741
     742    CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
     743
     744    occluded = Region();
     745    layer->addSelfToOccludedScreenSpace(occluded);
     746    EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occluded.bounds());
     747    EXPECT_EQ(1u, occluded.rects().size());
     748
     749    /* Justification for the above opaque rect from |layer|:
     750               100
     751      +---------------------+                                      +---------------------+
     752      |                     |                                      |                     |30  Visible region of |layer|: /////
     753      |    30               |           rotate(90)                 |                     |
     754      | 30 + ---------------------------------+                    |     +---------------------------------+
     755  100 |    |  10            |                 |            ==>     |     |               |10               |
     756      |    |10+---------------------------------+                  |  +---------------------------------+  |
     757      |    |  |             |                 | |                  |  |  |///////////////|     420      |  |
     758      |    |  |             |                 | |                  |  |  |///////////////|60            |  |
     759      |    |  |             |                 | |                  |  |  |///////////////|              |  |
     760      +----|--|-------------+                 | |                  +--|--|---------------+              |  |
     761           |  |                               | |                   20|10|     70                       |  |
     762           |  |                               | |                     |  |                              |  |
     763           |  |                               | |500                  |  |                              |  |
     764           |  |                               | |                     |  |                              |  |
     765           |  |                               | |                     |  |                              |  |
     766           |  |                               | |                     |  |                              |  |
     767           |  |                               | |                     |  |                              |10|
     768           +--|-------------------------------+ |                     |  +------------------------------|--+
     769              |                                 |                     |                 490             |
     770              +---------------------------------+                     +---------------------------------+
     771                             500                                                     500
     772     */
     773}
     774
    598775} // namespace
  • trunk/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp

    r106044 r106324  
    3131#include "GraphicsContext3DPrivate.h"
    3232#include "LayerChromium.h"
     33#include "Region.h"
    3334#include "TextureManager.h"
    3435#include "WebCompositor.h"
     
    10061007    void resetUpdateCount() { m_updateCount = 0; }
    10071008
    1008     virtual void paintContentsIfDirty()
    1009     {
    1010         ContentLayerChromium::paintContentsIfDirty();
     1009    virtual void paintContentsIfDirty(const Region& occludedScreenSpace)
     1010    {
     1011        ContentLayerChromium::paintContentsIfDirty(occludedScreenSpace);
    10111012        m_paintContentsCount++;
    10121013    }
     
    12291230}
    12301231
     1232#define EXPECT_EQ_RECT(a, b) \
     1233    EXPECT_EQ(a.x(), b.x()); \
     1234    EXPECT_EQ(a.y(), b.y()); \
     1235    EXPECT_EQ(a.width(), b.width()); \
     1236    EXPECT_EQ(a.height(), b.height());
     1237
     1238class TestLayerChromium : public LayerChromium {
     1239public:
     1240    static PassRefPtr<TestLayerChromium> create() { return adoptRef(new TestLayerChromium()); }
     1241
     1242    virtual void paintContentsIfDirty(const Region& occludedScreenSpace)
     1243    {
     1244        m_occludedScreenSpace = occludedScreenSpace;
     1245    }
     1246
     1247    virtual bool drawsContent() const { return true; }
     1248
     1249    const Region& occludedScreenSpace() const { return m_occludedScreenSpace; }
     1250    void clearOccludedScreenSpace() { m_occludedScreenSpace = Region(); }
     1251
     1252private:
     1253    TestLayerChromium() : LayerChromium() { }
     1254
     1255    Region m_occludedScreenSpace;
     1256};
     1257
     1258static void setLayerPropertiesForTesting(TestLayerChromium* layer, LayerChromium* parent, const TransformationMatrix& transform, const FloatPoint& anchor, const FloatPoint& position, const IntSize& bounds, bool opaque)
     1259{
     1260    layer->removeAllChildren();
     1261    if (parent)
     1262        parent->addChild(layer);
     1263    layer->setTransform(transform);
     1264    layer->setAnchorPoint(anchor);
     1265    layer->setPosition(position);
     1266    layer->setBounds(bounds);
     1267    layer->setOpaque(opaque);
     1268    layer->clearOccludedScreenSpace();
     1269}
     1270
     1271class CCLayerTreeHostTestLayerOcclusion : public CCLayerTreeHostTest {
     1272public:
     1273    CCLayerTreeHostTestLayerOcclusion() { }
     1274
     1275    virtual void beginTest()
     1276    {
     1277        RefPtr<TestLayerChromium> rootLayer = TestLayerChromium::create();
     1278        RefPtr<TestLayerChromium> child = TestLayerChromium::create();
     1279        RefPtr<TestLayerChromium> child2 = TestLayerChromium::create();
     1280        RefPtr<TestLayerChromium> grandChild = TestLayerChromium::create();
     1281        RefPtr<TestLayerChromium> mask = TestLayerChromium::create();
     1282
     1283        TransformationMatrix identityMatrix;
     1284        TransformationMatrix childTransform;
     1285        childTransform.translate(250, 250);
     1286        childTransform.rotate(90);
     1287        childTransform.translate(-250, -250);
     1288
     1289        child->setMasksToBounds(true);
     1290
     1291        // See CCLayerTreeHostCommonTest.layerAddsSelfToOccludedRegionWithRotatedSurface for a nice visual of these layers and how they end up
     1292        // positioned on the screen.
     1293
     1294        // The child layer is rotated and the grandChild is opaque, but clipped to the child and rootLayer
     1295        setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
     1296        setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false);
     1297        setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
     1298
     1299        m_layerTreeHost->setRootLayer(rootLayer);
     1300        m_layerTreeHost->setViewportSize(rootLayer->bounds());
     1301        m_layerTreeHost->updateLayers();
     1302        m_layerTreeHost->commitComplete();
     1303
     1304        EXPECT_EQ_RECT(IntRect(), grandChild->occludedScreenSpace().bounds());
     1305        EXPECT_EQ(0u, grandChild->occludedScreenSpace().rects().size());
     1306        EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), child->occludedScreenSpace().bounds());
     1307        EXPECT_EQ(1u, child->occludedScreenSpace().rects().size());
     1308        EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), rootLayer->occludedScreenSpace().bounds());
     1309        EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
     1310
     1311        // If the child layer is opaque, then it adds to the occlusion seen by the rootLayer.
     1312        setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
     1313        setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
     1314        setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
     1315
     1316        m_layerTreeHost->setRootLayer(rootLayer);
     1317        m_layerTreeHost->setViewportSize(rootLayer->bounds());
     1318        m_layerTreeHost->updateLayers();
     1319        m_layerTreeHost->commitComplete();
     1320
     1321        EXPECT_EQ_RECT(IntRect(), grandChild->occludedScreenSpace().bounds());
     1322        EXPECT_EQ(0u, grandChild->occludedScreenSpace().rects().size());
     1323        EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), child->occludedScreenSpace().bounds());
     1324        EXPECT_EQ(1u, child->occludedScreenSpace().rects().size());
     1325        EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), rootLayer->occludedScreenSpace().bounds());
     1326        EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
     1327
     1328        // Add a second child to the root layer and the regions should merge
     1329        setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
     1330        setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(70, 20), IntSize(500, 500), true);
     1331        setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
     1332        setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
     1333
     1334        m_layerTreeHost->setRootLayer(rootLayer);
     1335        m_layerTreeHost->setViewportSize(rootLayer->bounds());
     1336        m_layerTreeHost->updateLayers();
     1337        m_layerTreeHost->commitComplete();
     1338
     1339        EXPECT_EQ_RECT(IntRect(), grandChild->occludedScreenSpace().bounds());
     1340        EXPECT_EQ(0u, grandChild->occludedScreenSpace().rects().size());
     1341        EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), child->occludedScreenSpace().bounds());
     1342        EXPECT_EQ(1u, child->occludedScreenSpace().rects().size());
     1343        EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), child2->occludedScreenSpace().bounds());
     1344        EXPECT_EQ(1u, child2->occludedScreenSpace().rects().size());
     1345        EXPECT_EQ_RECT(IntRect(30, 20, 70, 80), rootLayer->occludedScreenSpace().bounds());
     1346        EXPECT_EQ(2u, rootLayer->occludedScreenSpace().rects().size());
     1347
     1348        // Move the second child to be sure.
     1349        setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
     1350        setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true);
     1351        setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
     1352        setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
     1353
     1354        m_layerTreeHost->setRootLayer(rootLayer);
     1355        m_layerTreeHost->setViewportSize(rootLayer->bounds());
     1356        m_layerTreeHost->updateLayers();
     1357        m_layerTreeHost->commitComplete();
     1358
     1359        EXPECT_EQ_RECT(IntRect(), grandChild->occludedScreenSpace().bounds());
     1360        EXPECT_EQ(0u, grandChild->occludedScreenSpace().rects().size());
     1361        EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), child->occludedScreenSpace().bounds());
     1362        EXPECT_EQ(1u, child->occludedScreenSpace().rects().size());
     1363        EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), child2->occludedScreenSpace().bounds());
     1364        EXPECT_EQ(1u, child2->occludedScreenSpace().rects().size());
     1365        EXPECT_EQ_RECT(IntRect(10, 30, 90, 70), rootLayer->occludedScreenSpace().bounds());
     1366        EXPECT_EQ(2u, rootLayer->occludedScreenSpace().rects().size());
     1367
     1368        // If the child layer has a mask on it, then it shouldn't contribute to occlusion on stuff below it
     1369        setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
     1370        setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true);
     1371        setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
     1372        setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
     1373
     1374        child->setMaskLayer(mask.get());
     1375
     1376        m_layerTreeHost->setRootLayer(rootLayer);
     1377        m_layerTreeHost->setViewportSize(rootLayer->bounds());
     1378        m_layerTreeHost->updateLayers();
     1379        m_layerTreeHost->commitComplete();
     1380
     1381        EXPECT_EQ_RECT(IntRect(), grandChild->occludedScreenSpace().bounds());
     1382        EXPECT_EQ(0u, grandChild->occludedScreenSpace().rects().size());
     1383        EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), child->occludedScreenSpace().bounds());
     1384        EXPECT_EQ(1u, child->occludedScreenSpace().rects().size());
     1385        EXPECT_EQ_RECT(IntRect(), child2->occludedScreenSpace().bounds());
     1386        EXPECT_EQ(0u, child2->occludedScreenSpace().rects().size());
     1387        EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), rootLayer->occludedScreenSpace().bounds());
     1388        EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
     1389
     1390        // If the child layer with a mask is below child2, then child2 should contribute to occlusion on everything, and child shouldn't contribute to the rootLayer
     1391        setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
     1392        setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
     1393        setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
     1394        setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true);
     1395
     1396        child->setMaskLayer(mask.get());
     1397
     1398        m_layerTreeHost->setRootLayer(rootLayer);
     1399        m_layerTreeHost->setViewportSize(rootLayer->bounds());
     1400        m_layerTreeHost->updateLayers();
     1401        m_layerTreeHost->commitComplete();
     1402
     1403        EXPECT_EQ_RECT(IntRect(), child2->occludedScreenSpace().bounds());
     1404        EXPECT_EQ(0u, child2->occludedScreenSpace().rects().size());
     1405        EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), grandChild->occludedScreenSpace().bounds());
     1406        EXPECT_EQ(1u, grandChild->occludedScreenSpace().rects().size());
     1407        EXPECT_EQ_RECT(IntRect(10, 40, 90, 60), child->occludedScreenSpace().bounds());
     1408        EXPECT_EQ(2u, child->occludedScreenSpace().rects().size());
     1409        EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), rootLayer->occludedScreenSpace().bounds());
     1410        EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
     1411
     1412        // If the child layer has a non-opaque drawOpacity, then it shouldn't contribute to occlusion on stuff below it
     1413        setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
     1414        setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true);
     1415        setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
     1416        setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
     1417
     1418        child->setMaskLayer(0);
     1419        child->setDrawOpacity(0.5);
     1420
     1421        m_layerTreeHost->setRootLayer(rootLayer);
     1422        m_layerTreeHost->setViewportSize(rootLayer->bounds());
     1423        m_layerTreeHost->updateLayers();
     1424        m_layerTreeHost->commitComplete();
     1425
     1426        EXPECT_EQ_RECT(IntRect(), grandChild->occludedScreenSpace().bounds());
     1427        EXPECT_EQ(0u, grandChild->occludedScreenSpace().rects().size());
     1428        EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), child->occludedScreenSpace().bounds());
     1429        EXPECT_EQ(1u, child->occludedScreenSpace().rects().size());
     1430        EXPECT_EQ_RECT(IntRect(), child2->occludedScreenSpace().bounds());
     1431        EXPECT_EQ(0u, child2->occludedScreenSpace().rects().size());
     1432        EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), rootLayer->occludedScreenSpace().bounds());
     1433        EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
     1434
     1435        // If the child layer with non-opaque drawOpacity is below child2, then child2 should contribute to occlusion on everything, and child shouldn't contribute to the rootLayer
     1436        setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
     1437        setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
     1438        setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
     1439        setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true);
     1440
     1441        child->setMaskLayer(0);
     1442        child->setDrawOpacity(0.5);
     1443
     1444        m_layerTreeHost->setRootLayer(rootLayer);
     1445        m_layerTreeHost->setViewportSize(rootLayer->bounds());
     1446        m_layerTreeHost->updateLayers();
     1447        m_layerTreeHost->commitComplete();
     1448
     1449        EXPECT_EQ_RECT(IntRect(), child2->occludedScreenSpace().bounds());
     1450        EXPECT_EQ(0u, child2->occludedScreenSpace().rects().size());
     1451        EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), grandChild->occludedScreenSpace().bounds());
     1452        EXPECT_EQ(1u, grandChild->occludedScreenSpace().rects().size());
     1453        EXPECT_EQ_RECT(IntRect(10, 40, 90, 60), child->occludedScreenSpace().bounds());
     1454        EXPECT_EQ(2u, child->occludedScreenSpace().rects().size());
     1455        EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), rootLayer->occludedScreenSpace().bounds());
     1456        EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
     1457
     1458        // Kill the layerTreeHost immediately.
     1459        m_layerTreeHost->setRootLayer(0);
     1460        m_layerTreeHost.clear();
     1461
     1462        endTest();
     1463    }
     1464
     1465    virtual void afterTest()
     1466    {
     1467    }
     1468};
     1469
     1470SINGLE_AND_MULTI_THREAD_TEST_F(CCLayerTreeHostTestLayerOcclusion)
     1471
    12311472} // namespace
  • trunk/Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp

    r104044 r106324  
    3030#include "FakeWebGraphicsContext3D.h"
    3131#include "GraphicsContext3DPrivate.h"
     32#include "Region.h"
    3233#include "TextureManager.h"
    3334#include "cc/CCCanvasLayerImpl.h"
     
    139140        canvas->contentChanged();
    140141        EXPECT_TRUE(canvas->needsDisplay());
    141         canvas->paintContentsIfDirty();
     142        Region occludedScreenSpace;
     143        canvas->paintContentsIfDirty(occludedScreenSpace);
    142144        EXPECT_FALSE(canvas->needsDisplay());
    143145        {
  • trunk/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp

    r105845 r106324  
    3030#include "FakeCCLayerTreeHostClient.h"
    3131#include "LayerTextureUpdater.h"
     32#include "Region.h"
    3233#include "TextureManager.h"
    3334#include "WebCompositor.h"
     
    4041using namespace WTF;
    4142
     43#define EXPECT_EQ_RECT(a, b) \
     44    EXPECT_EQ(a.x(), b.x()); \
     45    EXPECT_EQ(a.y(), b.y()); \
     46    EXPECT_EQ(a.width(), b.width()); \
     47    EXPECT_EQ(a.height(), b.height());
     48
    4249namespace {
    4350
     
    7178    void clearPrepareCount() { m_prepareCount = 0; }
    7279
     80    void setOpaquePaintRect(const IntRect& opaquePaintRect) { m_opaquePaintRect = opaquePaintRect; }
     81
    7382    // Last rect passed to prepareToUpdate().
    7483    const IntRect& lastUpdateRect()  const { return m_lastUpdateRect; }
     
    7685    virtual PassOwnPtr<LayerTextureUpdater::Texture> createTexture(TextureManager* manager) { return adoptPtr(new Texture(ManagedTexture::create(manager))); }
    7786    virtual SampledTexelFormat sampledTexelFormat(GC3Denum) { return SampledTexelFormatRGBA; }
    78     virtual void prepareToUpdate(const IntRect& contentRect, const IntSize&, int, float, IntRect*);
     87    virtual void prepareToUpdate(const IntRect& contentRect, const IntSize&, int, float, IntRect* resultingOpaqueRect);
    7988
    8089private:
     
    8291    IntRect m_rectToInvalidate;
    8392    IntRect m_lastUpdateRect;
     93    IntRect m_opaquePaintRect;
    8494    RefPtr<FakeTiledLayerChromium> m_layer;
    8595};
     
    140150    virtual TextureManager* textureManager() const { return m_textureManager; }
    141151
    142     virtual void paintContentsIfDirty()
     152    virtual void paintContentsIfDirty(const Region& /* occludedScreenSpace */)
    143153    {
    144154        prepareToUpdate(visibleLayerRect());
     
    188198        m_layer = 0;
    189199    }
    190     *resultingOpaqueRect = IntRect();
     200    *resultingOpaqueRect = m_opaquePaintRect;
    191201}
    192202
     
    461471}
    462472
     473TEST(TiledLayerChromiumTest, layerAddsSelfToOccludedRegion)
     474{
     475    OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
     476    RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
     477
     478    // The tile size is 100x100, so this invalidates and then paints two tiles in various ways.
     479
     480    Region occluded;
     481    IntRect contentBounds = IntRect(0, 0, 100, 200);
     482    IntRect visibleBounds = IntRect(0, 0, 100, 150);
     483
     484    layer->setBounds(contentBounds.size());
     485    layer->setVisibleLayerRect(visibleBounds);
     486    layer->setDrawOpacity(1);
     487
     488    // The screenSpaceTransform is verified in CCLayerTreeHostCommonTests
     489    TransformationMatrix screenSpaceTransform;
     490    layer->setScreenSpaceTransform(screenSpaceTransform);
     491
     492    // If the layer is opaque then the occluded region should be the whole layer's visible region.
     493    layer->setOpaque(true);
     494    layer->invalidateRect(contentBounds);
     495    layer->prepareToUpdate(contentBounds);
     496
     497    occluded = Region();
     498    layer->addSelfToOccludedScreenSpace(occluded);
     499    EXPECT_EQ_RECT(visibleBounds, occluded.bounds());
     500    EXPECT_EQ(1u, occluded.rects().size());
     501
     502    // If the layer is not opaque then the occluded region should be empty.
     503    layer->setOpaque(false);
     504    layer->invalidateRect(contentBounds);
     505    layer->prepareToUpdate(contentBounds);
     506
     507    occluded = Region();
     508    layer->addSelfToOccludedScreenSpace(occluded);
     509    EXPECT_EQ_RECT(IntRect(), occluded.bounds());
     510    EXPECT_EQ(1u, occluded.rects().size());
     511
     512    // If the layer paints opaque content, then the occluded region should match the visible opaque content.
     513    IntRect opaquePaintRect = IntRect(10, 10, 90, 190);
     514    layer->fakeLayerTextureUpdater()->setOpaquePaintRect(opaquePaintRect);
     515    layer->invalidateRect(contentBounds);
     516    layer->prepareToUpdate(contentBounds);
     517
     518    occluded = Region();
     519    layer->addSelfToOccludedScreenSpace(occluded);
     520    EXPECT_EQ_RECT(intersection(opaquePaintRect, visibleBounds), occluded.bounds());
     521    EXPECT_EQ(1u, occluded.rects().size());
     522
     523    // If we paint again without invalidating, the same stuff should be occluded.
     524    layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
     525    layer->prepareToUpdate(contentBounds);
     526
     527    occluded = Region();
     528    layer->addSelfToOccludedScreenSpace(occluded);
     529    EXPECT_EQ_RECT(intersection(opaquePaintRect, visibleBounds), occluded.bounds());
     530    EXPECT_EQ(1u, occluded.rects().size());
     531
     532    // If the layer is transformed then the resulting occluded area needs to be transformed to its target space.
     533    TransformationMatrix transform;
     534    transform.translate(contentBounds.width() / 2.0, contentBounds.height() / 2.0);
     535    transform.rotate(90);
     536    transform.translate(-contentBounds.width() / 2.0, -contentBounds.height() / 2.0);
     537    transform.translate(10, 10);
     538    screenSpaceTransform.translate(contentBounds.width() / 2.0, contentBounds.height() / 2.0);
     539    screenSpaceTransform *= transform;
     540    screenSpaceTransform.translate(-contentBounds.width() / 2.0, -contentBounds.height() / 2.0);
     541    layer->setScreenSpaceTransform(screenSpaceTransform);
     542    layer->prepareToUpdate(contentBounds);
     543
     544    occluded = Region();
     545    layer->addSelfToOccludedScreenSpace(occluded);
     546    EXPECT_EQ_RECT(screenSpaceTransform.mapRect(intersection(opaquePaintRect, visibleBounds)), occluded.bounds());
     547    EXPECT_EQ(1u, occluded.rects().size());
     548
     549    // But a non-axis-aligned transform does not get considered for occlusion.
     550    transform.translate(contentBounds.width() / 2.0, contentBounds.height() / 2.0);
     551    transform.rotate(5);
     552    transform.translate(-contentBounds.width() / 2.0, -contentBounds.height() / 2.0);
     553    screenSpaceTransform.translate(contentBounds.width() / 2.0, contentBounds.height() / 2.0);
     554    screenSpaceTransform *= transform;
     555    screenSpaceTransform.translate(-contentBounds.width() / 2.0, -contentBounds.height() / 2.0);
     556    layer->setScreenSpaceTransform(screenSpaceTransform);
     557    layer->prepareToUpdate(contentBounds);
     558
     559    occluded = Region();
     560    layer->addSelfToOccludedScreenSpace(occluded);
     561    // FIXME: If we find an opaque rect contained in the rotated non-axis-aligned rect, then
     562    // this won't be an empty result.
     563    EXPECT_EQ_RECT(IntRect(), occluded.bounds());
     564    EXPECT_EQ(0u, occluded.rects().size());
     565}
     566
    463567} // namespace
Note: See TracChangeset for help on using the changeset viewer.