Changeset 122152 in webkit


Ignore:
Timestamp:
Jul 9, 2012 1:36:21 PM (12 years ago)
Author:
dino@apple.com
Message:

Tiled drawing means some elements can disappear behind the page
https://bugs.webkit.org/show_bug.cgi?id=88906

Reviewed by Simon Fraser.

Source/WebCore:

The compositing layers in the tile cache could become siblings
of the compositing layers for page elements. This meant that in
some 3d transforms, the elements could disappear behind the
page background (which is rendered into the tile cache) or intersect
with the tile cache tiles.

Fix this by inserting a flattening layer between the tile cache
and the page, ensuring that the cache will always be rendered
first. I was able to reuse the clipping layer for this, because
the tile cache is attached to the RenderView, so there should never
be a case where we have both a clipping layer and tiles.

The unfortunate part of this code is the temporary state variable
that wraps the call to GraphicsLayer::create. Because that method
calls back into the object, we need to make sure we don't create
another tile cache.

Also added some obvious names to the tile cache layers to
help with debugging.

Test: compositing/tile-cache-must-flatten.html

  • platform/graphics/ca/mac/TileCache.mm:

(WebCore::TileCache::TileCache): give the tile host layer a name.
(WebCore::TileCache::createTileLayer):

  • platform/graphics/ca/mac/WebTileCacheLayer.mm:

(WebCore): give each tile layer a name.

  • rendering/RenderLayerBacking.cpp:

(WebCore):
(WebCore::RenderLayerBacking::shouldUseTileCache): check if we're in the middle
of creating the primary graphics layer before answering.
(WebCore::RenderLayerBacking::createPrimaryGraphicsLayer): wrap our call to
createGraphicsLayer with a message to indicate we are making the layer that should
get a tile cache.
(WebCore::RenderLayerBacking::destroyGraphicsLayers):
(WebCore::RenderLayerBacking::updateGraphicsLayerConfiguration): needs to make
sure the flattening layer is in the tree.
(WebCore::RenderLayerBacking::updateGraphicsLayerGeometry):
(WebCore::RenderLayerBacking::updateInternalHierarchy):
(WebCore::RenderLayerBacking::updateClippingLayers):
(WebCore::RenderLayerBacking::backingStoreMemoryEstimate):

  • rendering/RenderLayerBacking.h: rename m_clippingLayer to m_containmentLayer

because it can now either be the clip or the tile cache flattener. Also
a new state property used when creating the main graphics layer.
(WebCore::RenderLayerBacking::hasClippingLayer):
(WebCore::RenderLayerBacking::clippingLayer):
(WebCore::RenderLayerBacking::parentForSublayers):
(WebCore::RenderLayerBacking::hasTileCacheFlatteningLayer):
(WebCore::RenderLayerBacking::tileCacheFlatteningLayer):
(RenderLayerBacking):

LayoutTests:

Reftest to make sure elements can't disappear behind the tile cache.

  • compositing/tile-cache-must-flatten-expected.html: Added.
  • compositing/tile-cache-must-flatten.html: Added.
Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r122147 r122152  
     12012-07-09  Dean Jackson  <dino@apple.com>
     2
     3        Tiled drawing means some elements can disappear behind the page
     4        https://bugs.webkit.org/show_bug.cgi?id=88906
     5
     6        Reviewed by Simon Fraser.
     7
     8        Reftest to make sure elements can't disappear behind the tile cache.
     9
     10        * compositing/tile-cache-must-flatten-expected.html: Added.
     11        * compositing/tile-cache-must-flatten.html: Added.
     12
    1132012-07-09  Zan Dobersek  <zandobersek@gmail.com>
    214
  • trunk/Source/WebCore/ChangeLog

    r122150 r122152  
     12012-07-09  Dean Jackson  <dino@apple.com>
     2
     3        Tiled drawing means some elements can disappear behind the page
     4        https://bugs.webkit.org/show_bug.cgi?id=88906
     5
     6        Reviewed by Simon Fraser.
     7
     8        The compositing layers in the tile cache could become siblings
     9        of the compositing layers for page elements. This meant that in
     10        some 3d transforms, the elements could disappear behind the
     11        page background (which is rendered into the tile cache) or intersect
     12        with the tile cache tiles.
     13
     14        Fix this by inserting a flattening layer between the tile cache
     15        and the page, ensuring that the cache will always be rendered
     16        first. I was able to reuse the clipping layer for this, because
     17        the tile cache is attached to the RenderView, so there should never
     18        be a case where we have both a clipping layer and tiles.
     19
     20        The unfortunate part of this code is the temporary state variable
     21        that wraps the call to GraphicsLayer::create. Because that method
     22        calls back into the object, we need to make sure we don't create
     23        another tile cache.
     24
     25        Also added some obvious names to the tile cache layers to
     26        help with debugging.
     27
     28        Test: compositing/tile-cache-must-flatten.html
     29
     30        * platform/graphics/ca/mac/TileCache.mm:
     31        (WebCore::TileCache::TileCache): give the tile host layer a name.
     32        (WebCore::TileCache::createTileLayer):
     33        * platform/graphics/ca/mac/WebTileCacheLayer.mm:
     34        (WebCore): give each tile layer a name.
     35        * rendering/RenderLayerBacking.cpp:
     36        (WebCore):
     37        (WebCore::RenderLayerBacking::shouldUseTileCache): check if we're in the middle
     38        of creating the primary graphics layer before answering.
     39        (WebCore::RenderLayerBacking::createPrimaryGraphicsLayer): wrap our call to
     40        createGraphicsLayer with a message to indicate we are making the layer that should
     41        get a tile cache.
     42        (WebCore::RenderLayerBacking::destroyGraphicsLayers):
     43        (WebCore::RenderLayerBacking::updateGraphicsLayerConfiguration): needs to make
     44        sure the flattening layer is in the tree.
     45        (WebCore::RenderLayerBacking::updateGraphicsLayerGeometry):
     46        (WebCore::RenderLayerBacking::updateInternalHierarchy):
     47        (WebCore::RenderLayerBacking::updateClippingLayers):
     48        (WebCore::RenderLayerBacking::backingStoreMemoryEstimate):
     49        * rendering/RenderLayerBacking.h: rename m_clippingLayer to m_containmentLayer
     50        because it can now either be the clip or the tile cache flattener. Also
     51        a new state property used when creating the main graphics layer.
     52        (WebCore::RenderLayerBacking::hasClippingLayer):
     53        (WebCore::RenderLayerBacking::clippingLayer):
     54        (WebCore::RenderLayerBacking::parentForSublayers):
     55        (WebCore::RenderLayerBacking::hasTileCacheFlatteningLayer):
     56        (WebCore::RenderLayerBacking::tileCacheFlatteningLayer):
     57        (RenderLayerBacking):
     58
    1592012-07-09  Christophe Dumez  <christophe.dumez@intel.com>
    260
  • trunk/Source/WebCore/platform/graphics/ca/mac/TileCache.mm

    r121524 r122152  
    6565    [CATransaction setDisableActions:YES];
    6666    [m_tileCacheLayer addSublayer:m_tileContainerLayer.get()];
     67#ifndef NDEBUG
     68    [m_tileContainerLayer.get() setName:@"TileCache Container Layer"];
     69#endif
    6770    [CATransaction commit];
    6871}
     
    395398    [layer.get() setEdgeAntialiasingMask:0];
    396399    [layer.get() setOpaque:YES];
     400#ifndef NDEBUG
     401    [layer.get() setName:@"Tile"];
     402#endif
    397403
    398404#if !defined(BUILDING_ON_SNOW_LEOPARD)
  • trunk/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm

    r115376 r122152  
    4343    // FIXME: The tile size should be configurable.
    4444    _tileCache = TileCache::create(self, IntSize(512, 512));
    45 
     45#ifndef NDEBUG
     46    [self setName:@"WebTileCacheLayer"];
     47#endif
    4648    return self;
    4749}
  • trunk/Source/WebCore/rendering/RenderLayerBacking.cpp

    r121987 r122152  
    9191}
    9292
     93bool RenderLayerBacking::m_creatingPrimaryGraphicsLayer = false;
     94
    9395RenderLayerBacking::RenderLayerBacking(RenderLayer* layer)
    9496    : m_owningLayer(layer)
     
    155157bool RenderLayerBacking::shouldUseTileCache(const GraphicsLayer*) const
    156158{
    157     return m_usingTiledCacheLayer;
     159    return m_usingTiledCacheLayer && m_creatingPrimaryGraphicsLayer;
    158160}
    159161
     
    164166    layerName = nameForLayer();
    165167#endif
     168   
     169    // The call to createGraphicsLayer ends calling back into here as
     170    // a GraphicsLayerClient to ask if it shouldUseTileCache(). We only want
     171    // the tile cache on our main layer. This is pretty ugly, but saves us from
     172    // exposing the API to all clients.
     173
     174    m_creatingPrimaryGraphicsLayer = true;
    166175    m_graphicsLayer = createGraphicsLayer(layerName);
     176    m_creatingPrimaryGraphicsLayer = false;
     177
     178    if (m_usingTiledCacheLayer)
     179        m_containmentLayer = createGraphicsLayer("TileCache Flattening Layer");
    167180
    168181    if (m_isMainFrameRenderViewLayer) {
     
    197210    m_graphicsLayer = nullptr;
    198211    m_foregroundLayer = nullptr;
    199     m_clippingLayer = nullptr;
     212    m_containmentLayer = nullptr;
    200213    m_maskLayer = nullptr;
    201214}
     
    350363        updateInternalHierarchy();
    351364
     365    if (GraphicsLayer* flatteningLayer = tileCacheFlatteningLayer()) {
     366        flatteningLayer->removeFromParent();
     367        m_graphicsLayer->addChild(flatteningLayer);
     368    }
     369
    352370    if (updateMaskLayer(renderer->hasMask()))
    353371        m_graphicsLayer->setMaskLayer(m_maskLayer.get());
     
    516534    // If we have a layer that clips children, position it.
    517535    IntRect clippingBox;
    518     if (m_clippingLayer) {
     536    if (GraphicsLayer* clipLayer = clippingLayer()) {
    519537        clippingBox = clipBox(toRenderBox(renderer()));
    520         m_clippingLayer->setPosition(FloatPoint() + (clippingBox.location() - localCompositingBounds.location()));
    521         m_clippingLayer->setSize(clippingBox.size());
    522         m_clippingLayer->setOffsetFromRenderer(clippingBox.location() - IntPoint());
     538        clipLayer->setPosition(FloatPoint() + (clippingBox.location() - localCompositingBounds.location()));
     539        clipLayer->setSize(clippingBox.size());
     540        clipLayer->setOffsetFromRenderer(clippingBox.location() - IntPoint());
    523541    }
    524542   
     
    547565
    548566        RenderStyle* style = renderer()->style();
     567        GraphicsLayer* clipLayer = clippingLayer();
    549568        if (style->hasPerspective()) {
    550569            TransformationMatrix t = owningLayer()->perspectiveTransform();
    551570           
    552             if (m_clippingLayer) {
    553                 m_clippingLayer->setChildrenTransform(t);
     571            if (clipLayer) {
     572                clipLayer->setChildrenTransform(t);
    554573                m_graphicsLayer->setChildrenTransform(TransformationMatrix());
    555574            }
     
    557576                m_graphicsLayer->setChildrenTransform(t);
    558577        } else {
    559             if (m_clippingLayer)
    560                 m_clippingLayer->setChildrenTransform(TransformationMatrix());
     578            if (clipLayer)
     579                clipLayer->setChildrenTransform(TransformationMatrix());
    561580            else
    562581                m_graphicsLayer->setChildrenTransform(TransformationMatrix());
     
    570589        FloatSize foregroundSize = newSize;
    571590        IntSize foregroundOffset = m_graphicsLayer->offsetFromRenderer();
    572         if (m_clippingLayer) {
     591        if (hasClippingLayer()) {
    573592            // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it,
    574593            // so that it gets correctly sorted with children. In that case, position relative to the clipping layer.
     
    612631    }
    613632
    614     if (m_clippingLayer) {
    615         m_clippingLayer->removeFromParent();
    616         m_graphicsLayer->addChild(m_clippingLayer.get());
     633    if (m_containmentLayer) {
     634        m_containmentLayer->removeFromParent();
     635        m_graphicsLayer->addChild(m_containmentLayer.get());
    617636    }
    618637
     
    662681   
    663682    if (needsDescendantClip) {
    664         if (!m_clippingLayer) {
    665             m_clippingLayer = createGraphicsLayer("Child clipping Layer");
    666             m_clippingLayer->setMasksToBounds(true);
     683        if (!m_containmentLayer && !m_usingTiledCacheLayer) {
     684            m_containmentLayer = createGraphicsLayer("Child clipping Layer");
     685            m_containmentLayer->setMasksToBounds(true);
    667686            layersChanged = true;
    668687        }
    669     } else if (m_clippingLayer) {
    670         m_clippingLayer->removeFromParent();
    671         m_clippingLayer = nullptr;
     688    } else if (hasClippingLayer()) {
     689        m_containmentLayer->removeFromParent();
     690        m_containmentLayer = nullptr;
    672691        layersChanged = true;
    673692    }
     
    15771596    double backingMemory;
    15781597   
    1579     // m_ancestorClippingLayer and m_clippingLayer are just used for masking, so have no backing.
     1598    // m_ancestorClippingLayer and m_containmentLayer are just used for masking or containment, so have no backing.
    15801599    backingMemory = m_graphicsLayer->backingStoreMemoryEstimate();
    15811600    if (m_foregroundLayer)
  • trunk/Source/WebCore/rendering/RenderLayerBacking.h

    r121461 r122152  
    7575
    7676    // Layer to clip children
    77     bool hasClippingLayer() const { return m_clippingLayer != 0; }
    78     GraphicsLayer* clippingLayer() const { return m_clippingLayer.get(); }
     77    bool hasClippingLayer() const { return (m_containmentLayer && !m_usingTiledCacheLayer); }
     78    GraphicsLayer* clippingLayer() const { return !m_usingTiledCacheLayer ? m_containmentLayer.get() : 0; }
    7979
    8080    // Layer to get clipped by ancestor
     
    8787    bool hasMaskLayer() const { return m_maskLayer != 0; }
    8888
    89     GraphicsLayer* parentForSublayers() const { return m_clippingLayer ? m_clippingLayer.get() : m_graphicsLayer.get(); }
     89    GraphicsLayer* parentForSublayers() const { return m_containmentLayer ? m_containmentLayer.get() : m_graphicsLayer.get(); }
    9090    GraphicsLayer* childForSuperlayers() const { return m_ancestorClippingLayer ? m_ancestorClippingLayer.get() : m_graphicsLayer.get(); }
    9191
     
    221221    bool shouldClipCompositedBounds() const;
    222222
     223    bool hasTileCacheFlatteningLayer() const { return (m_containmentLayer && m_usingTiledCacheLayer); }
     224    GraphicsLayer* tileCacheFlatteningLayer() const { return m_usingTiledCacheLayer ? m_containmentLayer.get() : 0; }
     225
    223226    void paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*, const IntRect& paintDirtyRect, PaintBehavior, GraphicsLayerPaintingPhase, RenderObject* paintingRoot);
    224227
     
    231234    OwnPtr<GraphicsLayer> m_graphicsLayer;
    232235    OwnPtr<GraphicsLayer> m_foregroundLayer;       // only used in cases where we need to draw the foreground separately
    233     OwnPtr<GraphicsLayer> m_clippingLayer;         // only used if we have clipping on a stacking context, with compositing children
     236    OwnPtr<GraphicsLayer> m_containmentLayer; // Only used if we have clipping on a stacking context with compositing children, or if the layer has a tile cache.
    234237    OwnPtr<GraphicsLayer> m_maskLayer;             // only used if we have a mask
    235238
     
    247250    bool m_canCompositeFilters;
    248251#endif
     252
     253    static bool m_creatingPrimaryGraphicsLayer;
    249254};
    250255
Note: See TracChangeset for help on using the changeset viewer.