Changeset 169972 in webkit


Ignore:
Timestamp:
Jun 14, 2014, 10:40:49 AM (12 years ago)
Author:
Simon Fraser
Message:

Masks disappear when layers become tiled
https://bugs.webkit.org/show_bug.cgi?id=133892
<rdar://problem/17309793>

Reviewed by Tim Horton.

Source/WebCore:
There were several problems with tiled mask layers.

First, when a layer became tiled it failed to re-apply the platform layer
for its mask; fixed by adding MaskLayerChanged to the set of flags in
swapFromOrToTiledLayer().

Secondly, in CA, a mask layer's superlayer is the layer which is it masking,
so the if (oldLayer->superlayer())... code in swapFromOrToTiledLayer() would
erroneously try to swap out a sublayer on the superlayer with the mask.

Thirdly, the mask layer is updated after its host layer, but when the mask layer
become tiled, there was no code that updated the mask platform layer on its
host layer. Fix by:

  1. setting a bit on a layer to note that it's being used as a mask.
  2. setting the parent of such a layer to its host layer (mimicking CA)
  3. when the mask becomes tiled, dirtying the MaskLayerChanged bit on its parent and adding a clause to commitLayerChangesAfterSublayers() to update the mask layer.

Finally, ASSERTION FAILED: owningGraphicsLayer()->isCommittingChanges() would
fire because we failed to set the m_isCommittingChanges flag while committing
the mask layer. Fix by moving the TemporaryChange<bool> that sets this flag
into commitLayerChangesBeforeSublayers() and commitLayerChangesAfterSublayers().

Also used safe casts in more places in GraphicsLayerCA.

Tests: compositing/masks/become-tiled-mask.html

compositing/masks/cease-tiled-mask.html
compositing/masks/tiled-mask.html

  • platform/graphics/GraphicsLayer.cpp:

(WebCore::GraphicsLayer::GraphicsLayer):
(WebCore::GraphicsLayer::removeFromParent):
(WebCore::GraphicsLayer::setMaskLayer):

  • platform/graphics/GraphicsLayer.h:

(WebCore::GraphicsLayer::setIsMaskLayer):
(WebCore::GraphicsLayer::isMaskLayer):
(WebCore::GraphicsLayer::setMaskLayer): Deleted.

  • platform/graphics/ca/GraphicsLayerCA.cpp:

(WebCore::GraphicsLayerCA::removeFromParent):
(WebCore::GraphicsLayerCA::setMaskLayer):
(WebCore::GraphicsLayerCA::recursiveVisibleRectChangeRequiresFlush):
(WebCore::GraphicsLayerCA::recursiveCommitChanges):
(WebCore::GraphicsLayerCA::commitLayerChangesBeforeSublayers):
(WebCore::GraphicsLayerCA::commitLayerChangesAfterSublayers):
(WebCore::GraphicsLayerCA::updateSublayerList):
(WebCore::GraphicsLayerCA::ensureStructuralLayer):
(WebCore::GraphicsLayerCA::updateMaskLayer):
(WebCore::GraphicsLayerCA::replicatedLayerRoot):
(WebCore::GraphicsLayerCA::createFilterAnimationsFromKeyframes):
(WebCore::GraphicsLayerCA::swapFromOrToTiledLayer):
(WebCore::GraphicsLayerCA::propagateLayerChangeToReplicas):
(WebCore::GraphicsLayerCA::fetchCloneLayers):

LayoutTests:
Tests for masking as they go into and out of tiled mode.

  • compositing/masks/become-tiled-mask-expected.html: Added.
  • compositing/masks/become-tiled-mask.html: Added.
  • compositing/masks/cease-tiled-mask-expected.html: Added.
  • compositing/masks/cease-tiled-mask.html: Added.
  • compositing/masks/tiled-mask-expected.html: Added.
  • compositing/masks/tiled-mask.html: Added.
Location:
trunk
Files:
6 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r169965 r169972  
     12014-06-14  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Masks disappear when layers become tiled
     4        https://bugs.webkit.org/show_bug.cgi?id=133892
     5        <rdar://problem/17309793>
     6
     7        Reviewed by Tim Horton.
     8       
     9        Tests for masking as they go into and out of tiled mode.
     10
     11        * compositing/masks/become-tiled-mask-expected.html: Added.
     12        * compositing/masks/become-tiled-mask.html: Added.
     13        * compositing/masks/cease-tiled-mask-expected.html: Added.
     14        * compositing/masks/cease-tiled-mask.html: Added.
     15        * compositing/masks/tiled-mask-expected.html: Added.
     16        * compositing/masks/tiled-mask.html: Added.
     17
    1182014-06-14  Commit Queue  <commit-queue@webkit.org>
    219
  • trunk/Source/WebCore/ChangeLog

    r169970 r169972  
     12014-06-14  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Masks disappear when layers become tiled
     4        https://bugs.webkit.org/show_bug.cgi?id=133892
     5        <rdar://problem/17309793>
     6
     7        Reviewed by Tim Horton.
     8       
     9        There were several problems with tiled mask layers.
     10       
     11        First, when a layer became tiled it failed to re-apply the platform layer
     12        for its mask; fixed by adding MaskLayerChanged to the set of flags in
     13        swapFromOrToTiledLayer().
     14       
     15        Secondly, in CA, a mask layer's superlayer is the layer which is it masking,
     16        so the if (oldLayer->superlayer())... code in swapFromOrToTiledLayer() would
     17        erroneously try to swap out a sublayer on the superlayer with the mask.
     18       
     19        Thirdly, the mask layer is updated after its host layer, but when the mask layer
     20        become tiled, there was no code that updated the mask platform layer on its
     21        host layer. Fix by:
     22            1. setting a bit on a layer to note that it's being used as a mask.
     23            2. setting the parent of such a layer to its host layer (mimicking CA)
     24            3. when the mask becomes tiled, dirtying the MaskLayerChanged bit on
     25               its parent and adding a clause to commitLayerChangesAfterSublayers()
     26               to update the mask layer.
     27       
     28        Finally, ASSERTION FAILED: owningGraphicsLayer()->isCommittingChanges() would
     29        fire because we failed to set the m_isCommittingChanges flag while committing
     30        the mask layer. Fix by moving the TemporaryChange<bool> that sets this flag
     31        into commitLayerChangesBeforeSublayers() and commitLayerChangesAfterSublayers().
     32       
     33        Also used safe casts in more places in GraphicsLayerCA.
     34
     35        Tests: compositing/masks/become-tiled-mask.html
     36               compositing/masks/cease-tiled-mask.html
     37               compositing/masks/tiled-mask.html
     38
     39        * platform/graphics/GraphicsLayer.cpp:
     40        (WebCore::GraphicsLayer::GraphicsLayer):
     41        (WebCore::GraphicsLayer::removeFromParent):
     42        (WebCore::GraphicsLayer::setMaskLayer):
     43        * platform/graphics/GraphicsLayer.h:
     44        (WebCore::GraphicsLayer::setIsMaskLayer):
     45        (WebCore::GraphicsLayer::isMaskLayer):
     46        (WebCore::GraphicsLayer::setMaskLayer): Deleted.
     47        * platform/graphics/ca/GraphicsLayerCA.cpp:
     48        (WebCore::GraphicsLayerCA::removeFromParent):
     49        (WebCore::GraphicsLayerCA::setMaskLayer):
     50        (WebCore::GraphicsLayerCA::recursiveVisibleRectChangeRequiresFlush):
     51        (WebCore::GraphicsLayerCA::recursiveCommitChanges):
     52        (WebCore::GraphicsLayerCA::commitLayerChangesBeforeSublayers):
     53        (WebCore::GraphicsLayerCA::commitLayerChangesAfterSublayers):
     54        (WebCore::GraphicsLayerCA::updateSublayerList):
     55        (WebCore::GraphicsLayerCA::ensureStructuralLayer):
     56        (WebCore::GraphicsLayerCA::updateMaskLayer):
     57        (WebCore::GraphicsLayerCA::replicatedLayerRoot):
     58        (WebCore::GraphicsLayerCA::createFilterAnimationsFromKeyframes):
     59        (WebCore::GraphicsLayerCA::swapFromOrToTiledLayer):
     60        (WebCore::GraphicsLayerCA::propagateLayerChangeToReplicas):
     61        (WebCore::GraphicsLayerCA::fetchCloneLayers):
     62
    1632014-06-14  peavo@outlook.com  <peavo@outlook.com>
    264
  • trunk/Source/WebCore/platform/graphics/GraphicsLayer.cpp

    r169320 r169972  
    9191    , m_showDebugBorder(false)
    9292    , m_showRepaintCounter(false)
     93    , m_isMaskLayer(false)
    9394    , m_paintingPhase(GraphicsLayerPaintAllWithOverflowClip)
    9495    , m_contentsOrientation(CompositingCoordinatesTopDown)
     
    261262        }
    262263
    263         setParent(0);
    264     }
     264        setParent(nullptr);
     265    }
     266}
     267
     268void GraphicsLayer::setMaskLayer(GraphicsLayer* layer)
     269{
     270    if (layer == m_maskLayer)
     271        return;
     272
     273    if (layer) {
     274        layer->removeFromParent();
     275        layer->setParent(this);
     276        layer->setIsMaskLayer(true);
     277    } else if (m_maskLayer) {
     278        m_maskLayer->setParent(nullptr);
     279        m_maskLayer->setIsMaskLayer(false);
     280    }
     281   
     282    m_maskLayer = layer;
    265283}
    266284
  • trunk/Source/WebCore/platform/graphics/GraphicsLayer.h

    r168440 r169972  
    262262    virtual void removeFromParent();
    263263
     264    // The parent() of a maskLayer is set to the layer being masked.
    264265    GraphicsLayer* maskLayer() const { return m_maskLayer; }
    265     virtual void setMaskLayer(GraphicsLayer* layer) { m_maskLayer = layer; }
     266    virtual void setMaskLayer(GraphicsLayer*);
     267
     268    void setIsMaskLayer(bool isMask) { m_isMaskLayer = isMask; }
     269    bool isMaskLayer() const { return m_isMaskLayer; }
    266270   
    267271    // The given layer will replicate this layer and its children; the replica renders behind this layer.
     
    594598    bool m_showDebugBorder : 1;
    595599    bool m_showRepaintCounter : 1;
     600    bool m_isMaskLayer : 1;
    596601   
    597602    GraphicsLayerPaintingPhase m_paintingPhase;
  • trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp

    r169690 r169972  
    457457{
    458458    if (m_parent)
    459         static_cast<GraphicsLayerCA*>(m_parent)->noteSublayersChanged();
     459        toGraphicsLayerCA(m_parent)->noteSublayersChanged();
    460460    GraphicsLayer::removeFromParent();
    461461}
     
    472472   
    473473    if (m_replicatedLayer)
    474         static_cast<GraphicsLayerCA*>(m_replicatedLayer)->propagateLayerChangeToReplicas();
     474        toGraphicsLayerCA(m_replicatedLayer)->propagateLayerChangeToReplicas();
    475475}
    476476
     
    10361036
    10371037    if (m_maskLayer) {
    1038         GraphicsLayerCA* maskLayerCA = static_cast<GraphicsLayerCA*>(m_maskLayer);
     1038        GraphicsLayerCA* maskLayerCA = toGraphicsLayerCA(m_maskLayer);
    10391039        if (maskLayerCA->recursiveVisibleRectChangeRequiresFlush(localState))
    10401040            return true;
     
    10451045   
    10461046    for (size_t i = 0; i < numChildren; ++i) {
    1047         GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]);
     1047        GraphicsLayerCA* curChild = toGraphicsLayerCA(childLayers[i]);
    10481048        if (curChild->recursiveVisibleRectChangeRequiresFlush(localState))
    10491049            return true;
     
    10511051
    10521052    if (m_replicaLayer)
    1053         if (static_cast<GraphicsLayerCA*>(m_replicaLayer)->recursiveVisibleRectChangeRequiresFlush(localState))
     1053        if (toGraphicsLayerCA(m_replicaLayer)->recursiveVisibleRectChangeRequiresFlush(localState))
    10541054            return true;
    10551055   
     
    11511151        m_uncommittedChanges |= VisibleRectChanged;
    11521152        m_visibleRect = visibleRect;
     1153       
     1154        if (GraphicsLayerCA* maskLayer = toGraphicsLayerCA(m_maskLayer)) {
     1155            // FIXME: this assumes that the mask layer has the same geometry as this layer (which is currently always true).
     1156            maskLayer->m_uncommittedChanges |= VisibleRectChanged;
     1157            maskLayer->m_visibleRect = visibleRect;
     1158        }
    11531159    }
    11541160
     
    11881194        baseRelativePosition += m_position;
    11891195   
    1190     {
    1191         TemporaryChange<bool> committingChangesChange(m_isCommittingChanges, true);
    1192         commitLayerChangesBeforeSublayers(childCommitState, pageScaleFactor, baseRelativePosition, oldVisibleRect);
    1193     }
     1196    commitLayerChangesBeforeSublayers(childCommitState, pageScaleFactor, baseRelativePosition, oldVisibleRect);
    11941197
    11951198    if (isRunningTransformAnimation()) {
     
    11981201    }
    11991202
    1200     if (m_maskLayer) {
    1201         GraphicsLayerCA* maskLayerCA = static_cast<GraphicsLayerCA*>(m_maskLayer);
    1202         maskLayerCA->commitLayerChangesBeforeSublayers(childCommitState, pageScaleFactor, baseRelativePosition, maskLayerCA->visibleRect());
    1203     }
     1203    if (GraphicsLayerCA* maskLayer = toGraphicsLayerCA(m_maskLayer))
     1204        maskLayer->commitLayerChangesBeforeSublayers(childCommitState, pageScaleFactor, baseRelativePosition, oldVisibleRect);
    12041205
    12051206    const Vector<GraphicsLayer*>& childLayers = children();
     
    12071208   
    12081209    for (size_t i = 0; i < numChildren; ++i) {
    1209         GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]);
     1210        GraphicsLayerCA* curChild = toGraphicsLayerCA(childLayers[i]);
    12101211        curChild->recursiveCommitChanges(childCommitState, localState, pageScaleFactor, baseRelativePosition, affectedByPageScale);
    12111212    }
    12121213
    1213     if (m_replicaLayer)
    1214         static_cast<GraphicsLayerCA*>(m_replicaLayer)->recursiveCommitChanges(childCommitState, localState, pageScaleFactor, baseRelativePosition, affectedByPageScale);
    1215 
    1216     if (m_maskLayer)
    1217         static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChangesAfterSublayers(childCommitState);
    1218 
    1219     {
    1220         TemporaryChange<bool> committingChangesChange(m_isCommittingChanges, true);
    1221         commitLayerChangesAfterSublayers(childCommitState);
    1222     }
     1214    if (GraphicsLayerCA* replicaLayer = toGraphicsLayerCA(m_replicaLayer))
     1215        replicaLayer->recursiveCommitChanges(childCommitState, localState, pageScaleFactor, baseRelativePosition, affectedByPageScale);
     1216
     1217    if (GraphicsLayerCA* maskLayer = toGraphicsLayerCA(m_maskLayer))
     1218        maskLayer->commitLayerChangesAfterSublayers(childCommitState);
     1219
     1220    commitLayerChangesAfterSublayers(childCommitState);
    12231221
    12241222    if (affectedByTransformAnimation && m_layer->layerType() == PlatformCALayer::LayerTypeTiledBackingLayer)
     
    12711269void GraphicsLayerCA::commitLayerChangesBeforeSublayers(CommitState& commitState, float pageScaleFactor, const FloatPoint& positionRelativeToBase, const FloatRect& oldVisibleRect)
    12721270{
     1271    TemporaryChange<bool> committingChangesChange(m_isCommittingChanges, true);
     1272
    12731273    ++commitState.treeDepth;
    12741274    if (m_structuralLayer)
     
    13651365        updateContentsRects();
    13661366
    1367     if (m_uncommittedChanges & MaskLayerChanged)
     1367    if (m_uncommittedChanges & MaskLayerChanged) {
    13681368        updateMaskLayer();
     1369        // If the mask layer becomes tiled it can set this flag again. Clear the flag so that
     1370        // commitLayerChangesAfterSublayers doesn't update the mask again in the normal case.
     1371        m_uncommittedChanges &= ~MaskLayerChanged;
     1372    }
    13691373
    13701374    if (m_uncommittedChanges & ContentsNeedsDisplay)
     
    13981402    if (!m_uncommittedChanges)
    13991403        return;
     1404
     1405    TemporaryChange<bool> committingChangesChange(m_isCommittingChanges, true);
     1406
     1407    if (m_uncommittedChanges & MaskLayerChanged)
     1408        updateMaskLayer();
    14001409
    14011410    if (m_uncommittedChanges & ChildrenChanged)
     
    14421451    if (m_structuralLayer) {
    14431452        if (m_replicaLayer)
    1444             structuralLayerChildren.append(static_cast<GraphicsLayerCA*>(m_replicaLayer)->primaryLayer());
     1453            structuralLayerChildren.append(toGraphicsLayerCA(m_replicaLayer)->primaryLayer());
    14451454   
    14461455        structuralLayerChildren.append(m_layer);
     
    14571466    size_t numChildren = childLayers.size();
    14581467    for (size_t i = 0; i < numChildren; ++i) {
    1459         GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]);
     1468        GraphicsLayerCA* curChild = toGraphicsLayerCA(childLayers[i]);
    14601469        PlatformCALayer* childLayer = curChild->layerForSuperlayer();
    14611470        childListForSublayers.append(childLayer);
     
    17421751    // We've changed the layer that our parent added to its sublayer list, so tell it to update
    17431752    // sublayers again in its commitLayerChangesAfterSublayers().
    1744     static_cast<GraphicsLayerCA*>(parent())->noteSublayersChanged(DontScheduleFlush);
     1753    toGraphicsLayerCA(parent())->noteSublayersChanged(DontScheduleFlush);
    17451754
    17461755    // Set properties of m_layer to their default values, since these are expressed on on the structural layer.
     
    20362045void GraphicsLayerCA::updateMaskLayer()
    20372046{
    2038     PlatformCALayer* maskCALayer = m_maskLayer ? static_cast<GraphicsLayerCA*>(m_maskLayer)->primaryLayer() : 0;
     2047    PlatformCALayer* maskCALayer = m_maskLayer ? toGraphicsLayerCA(m_maskLayer)->primaryLayer() : 0;
    20392048    m_layer->setMask(maskCALayer);
    20402049
    2041     LayerMap* maskLayerCloneMap = m_maskLayer ? static_cast<GraphicsLayerCA*>(m_maskLayer)->primaryLayerClones() : 0;
     2050    LayerMap* maskLayerCloneMap = m_maskLayer ? toGraphicsLayerCA(m_maskLayer)->primaryLayerClones() : 0;
    20422051   
    20432052    if (LayerMap* layerCloneMap = m_layerClones.get()) {
     
    20922101        return 0;
    20932102
    2094     GraphicsLayerCA* replicatedLayer = static_cast<GraphicsLayerCA*>(m_replicatedLayer);
     2103    GraphicsLayerCA* replicatedLayer = toGraphicsLayerCA(m_replicatedLayer);
    20952104   
    20962105    RefPtr<PlatformCALayer> clonedLayerRoot = replicatedLayer->fetchCloneLayers(this, replicaState, RootCloneLevel);
     
    24242433    if (listIndex < 0)
    24252434        return false;
    2426        
     2435
    24272436    const FilterOperations& operations = static_cast<const FilterAnimationValue&>(valueList.at(listIndex)).value();
    24282437    // Make sure the platform layer didn't fallback to using software filter compositing instead.
     
    30073016#endif
    30083017
    3009     // Skip this step if we don't have a superlayer. This is probably a benign
    3010     // case that happens while restructuring the layer tree, and also occurs with
    3011     // WebKit2 page overlays, which can become tiled but are out-of-tree.
    3012     if (oldLayer->superlayer())
     3018    if (isMaskLayer()) {
     3019        // A mask layer's superlayer is the layer that it masks. Set the MaskLayerChanged dirty bit
     3020        // so that the parent will fix up the platform layers in commitLayerChangesAfterSublayers().
     3021        if (GraphicsLayer* parentLayer = parent())
     3022            toGraphicsLayerCA(parentLayer)->noteLayerPropertyChanged(MaskLayerChanged);
     3023    } else if (oldLayer->superlayer()) {
     3024        // Skip this step if we don't have a superlayer. This is probably a benign
     3025        // case that happens while restructuring the layer tree, and also occurs with
     3026        // WebKit2 page overlays, which can become tiled but are out-of-tree.
    30133027        oldLayer->superlayer()->replaceSublayer(oldLayer.get(), m_layer.get());
     3028    }
    30143029
    30153030    m_uncommittedChanges |= ChildrenChanged
     
    30243039        | AcceleratesDrawingChanged
    30253040        | FiltersChanged
     3041        | MaskLayerChanged
    30263042        | OpacityChanged
    30273043        | DebugIndicatorsChanged;
     
    31443160{
    31453161    for (GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent()) {
    3146         GraphicsLayerCA* currLayerCA = static_cast<GraphicsLayerCA*>(currLayer);
     3162        GraphicsLayerCA* currLayerCA = toGraphicsLayerCA(currLayer);
    31473163        if (!currLayerCA->hasCloneLayers())
    31483164            break;
    31493165
    31503166        if (currLayerCA->replicaLayer())
    3151             static_cast<GraphicsLayerCA*>(currLayerCA->replicaLayer())->noteLayerPropertyChanged(ReplicatedLayerChanged);
     3167            toGraphicsLayerCA(currLayerCA->replicaLayer())->noteLayerPropertyChanged(ReplicatedLayerChanged);
    31523168    }
    31533169}
     
    31623178
    31633179    if (m_maskLayer) {
    3164         RefPtr<PlatformCALayer> maskClone = static_cast<GraphicsLayerCA*>(m_maskLayer)->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel);
     3180        RefPtr<PlatformCALayer> maskClone = toGraphicsLayerCA(m_maskLayer)->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel);
    31653181        primaryLayer->setMask(maskClone.get());
    31663182    }
     
    31893205        // We have nested replicas. Ask the replica layer for a clone of its contents.
    31903206        replicaState.setBranchType(ReplicaState::ReplicaBranch);
    3191         replicaLayer = static_cast<GraphicsLayerCA*>(m_replicaLayer)->fetchCloneLayers(replicaRoot, replicaState, RootCloneLevel);
     3207        replicaLayer = toGraphicsLayerCA(m_replicaLayer)->fetchCloneLayers(replicaRoot, replicaState, RootCloneLevel);
    31923208        replicaState.setBranchType(ReplicaState::ChildBranch);
    31933209    }
     
    32223238        size_t numChildren = childLayers.size();
    32233239        for (size_t i = 0; i < numChildren; ++i) {
    3224             GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]);
     3240            GraphicsLayerCA* curChild = toGraphicsLayerCA(childLayers[i]);
    32253241
    32263242            RefPtr<PlatformCALayer> childLayer = curChild->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel);
Note: See TracChangeset for help on using the changeset viewer.