Changeset 165970 in webkit


Ignore:
Timestamp:
Mar 20, 2014 10:37:16 AM (10 years ago)
Author:
commit-queue@webkit.org
Message:

[CSS Blending] Blending operation is not isolated when setting z-index on parent from javascript
https://bugs.webkit.org/show_bug.cgi?id=129307

Patch by Mihai Tica <mitica@adobe.com> on 2014-03-20
Reviewed by Dean Jackson.

Source/WebCore:

Reimplement the logic behind isolating blend modes. The blending operation should be limited to the
contents of the parent stacking context. The proposed solution implies adding logic in updateDescendantDependentFlags,
to track child elements that have blending and create a transparency layer that triggers isolation.

Tests: css3/compositing/blend-mode-background.html

fast/repaint/blend-mode-isolate-stacking-context.html

  • rendering/RenderLayer.cpp:

(WebCore::RenderLayer::RenderLayer): Remove old members, add new members to constructor.
(WebCore::RenderLayer::updateBlendMode): Update parent stacking context isolation on blend mode change.
(WebCore::RenderLayer::updateNonCompositedParentStackingContextHasBlendedChild):

  • Set m_hasBlendedElementInChildStackingContext for the non composited parent stacking context.

(WebCore::RenderLayer::dirtyAncestorParentStackingContextHasBlendedElement):

  • Set flag so isolation should be considered in updateDescendantDependentFlags.

(WebCore::RenderLayer::nonCompositedParentStackingContextHasBlendedChild):

  • Return whether the non composited parent stacking context isolates blending.

(WebCore::RenderLayer::updateDescendantDependentFlags): Add logic for isolating blending.
(WebCore::RenderLayer::addChild): Call to updateNonCompositedParentStackingContextHasBlendedChild if needed.
(WebCore::RenderLayer::removeChild): Call to dirtyAncestorParentStackingContextHasBlendedElement if needed.
(WebCore::RenderLayer::updateStackingContextsAfterStyleChange): Update isolation when a stacking context was set or unset.
(WebCore::RenderLayer::styleChanged): Removed oldStyle parameter from updateBlendMode call.

Update parent stacking context isolation on blend mode change.

  • rendering/RenderLayer.h:
  • Add members, getters and setters for tracking whether the element has a blended child:
    • m_hasBlendedElementInChildStackingContext
    • m_hasBlendedElementInChildStackingContextStatusDirty
  • Removed m_updateParentStackingContextShouldIsolateBlendingDirty (replaced with m_hasBlendedElementInChildStackingContextStatusDirty)
  • Removed m_isolatesBlending (replaced with m_hasBlendedElementInChildStackingContext)
  • Updated the isolatesBlending method to return true only when the element is a stacking context and has a blended child.
  • rendering/RenderLayerCompositor.cpp:

(WebCore::RenderLayerCompositor::computeCompositingRequirements): Removed layer.updateParentStackingContextShouldIsolateBlending call.

LayoutTests:

Test if setting or unsetting stacking context or blend mode from script correctly updates blending
isolation.

  • css3/compositing/blend-mode-background.html: Added.
  • fast/repaint/blend-mode-isolate-stacking-context-expected.txt: Added.
  • fast/repaint/blend-mode-isolate-stacking-context.html: Added.
  • platform/mac/css3/compositing/blend-mode-background-expected.png: Added.
  • platform/mac/css3/compositing/blend-mode-background-expected.txt: Added.
Location:
trunk
Files:
5 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r165969 r165970  
     12014-03-20  Mihai Tica  <mitica@adobe.com>
     2
     3        [CSS Blending] Blending operation is not isolated when setting z-index on parent from javascript
     4        https://bugs.webkit.org/show_bug.cgi?id=129307
     5
     6        Reviewed by Dean Jackson.
     7
     8        Test if setting or unsetting stacking context or blend mode from script correctly updates blending
     9        isolation.
     10
     11        * css3/compositing/blend-mode-background.html: Added.
     12        * fast/repaint/blend-mode-isolate-stacking-context-expected.txt: Added.
     13        * fast/repaint/blend-mode-isolate-stacking-context.html: Added.
     14        * platform/mac/css3/compositing/blend-mode-background-expected.png: Added.
     15        * platform/mac/css3/compositing/blend-mode-background-expected.txt: Added.
     16
    1172014-03-20  Radu Stavila  <stavila@adobe.com>
    218
  • trunk/Source/WebCore/ChangeLog

    r165967 r165970  
     12014-03-20  Mihai Tica  <mitica@adobe.com>
     2
     3        [CSS Blending] Blending operation is not isolated when setting z-index on parent from javascript
     4        https://bugs.webkit.org/show_bug.cgi?id=129307
     5
     6        Reviewed by Dean Jackson.
     7
     8        Reimplement the logic behind isolating blend modes. The blending operation should be limited to the
     9        contents of the parent stacking context. The proposed solution implies adding logic in updateDescendantDependentFlags,
     10        to track child elements that have blending and create a transparency layer that triggers isolation.
     11
     12        Tests: css3/compositing/blend-mode-background.html
     13               fast/repaint/blend-mode-isolate-stacking-context.html
     14
     15        * rendering/RenderLayer.cpp:
     16        (WebCore::RenderLayer::RenderLayer): Remove old members, add new members to constructor.
     17        (WebCore::RenderLayer::updateBlendMode): Update parent stacking context isolation on blend mode change.
     18        (WebCore::RenderLayer::updateNonCompositedParentStackingContextHasBlendedChild):
     19        - Set m_hasBlendedElementInChildStackingContext for the non composited parent stacking context.
     20        (WebCore::RenderLayer::dirtyAncestorParentStackingContextHasBlendedElement):
     21        - Set flag so isolation should be considered in updateDescendantDependentFlags.
     22        (WebCore::RenderLayer::nonCompositedParentStackingContextHasBlendedChild):
     23        - Return whether the non composited parent stacking context isolates blending.
     24        (WebCore::RenderLayer::updateDescendantDependentFlags): Add logic for isolating blending.
     25        (WebCore::RenderLayer::addChild): Call to updateNonCompositedParentStackingContextHasBlendedChild if needed.
     26        (WebCore::RenderLayer::removeChild): Call to dirtyAncestorParentStackingContextHasBlendedElement if needed.
     27        (WebCore::RenderLayer::updateStackingContextsAfterStyleChange): Update isolation when a stacking context was set or unset.
     28        (WebCore::RenderLayer::styleChanged): Removed oldStyle parameter from updateBlendMode call.
     29         Update parent stacking context isolation on blend mode change.
     30        * rendering/RenderLayer.h:
     31        - Add members, getters and setters for tracking whether the element has a blended child:
     32            - m_hasBlendedElementInChildStackingContext
     33            - m_hasBlendedElementInChildStackingContextStatusDirty
     34        - Removed m_updateParentStackingContextShouldIsolateBlendingDirty (replaced with m_hasBlendedElementInChildStackingContextStatusDirty)
     35        - Removed m_isolatesBlending (replaced with m_hasBlendedElementInChildStackingContext)
     36        - Updated the isolatesBlending method to return true only when the element is a stacking context and has a blended child.
     37        * rendering/RenderLayerCompositor.cpp:
     38        (WebCore::RenderLayerCompositor::computeCompositingRequirements): Removed layer.updateParentStackingContextShouldIsolateBlending call.
     39
    1402014-03-20  Martin Robinson  <mrobinson@igalia.com>
    241
  • trunk/Source/WebCore/rendering/RenderLayer.cpp

    r165963 r165970  
    186186#if ENABLE(CSS_COMPOSITING)
    187187    , m_blendMode(BlendModeNormal)
    188     , m_isolatesBlending(false)
    189     , m_updateParentStackingContextShouldIsolateBlendingDirty(false)
     188    , m_hasBlendedElementInChildStackingContext(false)
     189    , m_hasBlendedElementInChildStackingContextStatusDirty(false)
    190190#endif
    191191    , m_renderer(rendererLayerModelObject)
     
    804804#if ENABLE(CSS_COMPOSITING)
    805805
    806 void RenderLayer::updateBlendMode(const RenderStyle* oldStyle)
    807 {
    808     m_updateParentStackingContextShouldIsolateBlendingDirty = false;
    809 
    810     if ((!oldStyle && renderer().style().hasBlendMode()) || (oldStyle && oldStyle->hasBlendMode() != renderer().style().hasBlendMode()))
    811         m_updateParentStackingContextShouldIsolateBlendingDirty = true;
     806void RenderLayer::updateBlendMode()
     807{
     808    bool hadBlendMode = m_blendMode != BlendModeNormal;
     809    if (hadBlendMode != hasBlendMode()) {
     810        if (hasBlendMode())
     811            updateNonCompositedParentStackingContextHasBlendedChild(true);
     812        else
     813            dirtyAncestorParentStackingContextHasBlendedElement();
     814    }
    812815
    813816    BlendMode newBlendMode = renderer().style().blendMode();
     
    819822}
    820823
    821 void RenderLayer::updateParentStackingContextShouldIsolateBlending()
    822 {
    823     if (!m_updateParentStackingContextShouldIsolateBlendingDirty)
    824         return;
    825 
    826     if (isComposited()) {
    827         m_updateParentStackingContextShouldIsolateBlendingDirty = false;
    828         return;
    829     }
    830 
    831     for (auto ancestor = parent(); ancestor && !ancestor->isComposited() && !ancestor->isRootLayer(); ancestor = ancestor->parent()) {
    832         if (ancestor->isStackingContext()) {
    833             ancestor->m_isolatesBlending = renderer().style().hasBlendMode();
     824void RenderLayer::updateNonCompositedParentStackingContextHasBlendedChild(bool hasBlendedChild)
     825{
     826    if (isComposited())
     827        return;
     828
     829    for (auto ancestor = parent(); ancestor && !ancestor->isComposited() && !ancestor->renderer().isRoot(); ancestor = ancestor->parent()) {
     830        ancestor->m_hasBlendedElementInChildStackingContext = hasBlendedChild;
     831
     832        if (ancestor->isStackingContext())
    834833            break;
    835         }
    836     }
    837 
    838     m_updateParentStackingContextShouldIsolateBlendingDirty = false;
     834    }
     835}
     836
     837void RenderLayer::dirtyAncestorParentStackingContextHasBlendedElement()
     838{
     839    for (auto layer = this; layer && !layer->isComposited() && !layer->m_hasBlendedElementInChildStackingContextStatusDirty; layer = layer->parent()) {
     840        layer->m_hasBlendedElementInChildStackingContextStatusDirty = true;
     841
     842        if (layer->isStackingContext())
     843            break;
     844    }
     845}
     846
     847bool RenderLayer::nonCompositedParentStackingContextHasBlendedChild() const
     848{
     849    for (auto ancestor = parent(); ancestor && !ancestor->isComposited() && !ancestor->renderer().isRoot(); ancestor = ancestor->parent()) {
     850        if (ancestor->isStackingContext())
     851            return ancestor->hasBlendedElementInChildStackingContext();
     852    }
     853
     854    return false;
    839855}
    840856
     
    10811097void RenderLayer::updateDescendantDependentFlags(HashSet<const RenderObject*>* outOfFlowDescendantContainingBlocks)
    10821098{
    1083     if (m_visibleDescendantStatusDirty || m_hasSelfPaintingLayerDescendantDirty || m_hasOutOfFlowPositionedDescendantDirty) {
     1099    if (m_visibleDescendantStatusDirty || m_hasSelfPaintingLayerDescendantDirty || m_hasOutOfFlowPositionedDescendantDirty || hasBlendedElementInChildStackingContextStatusDirty()) {
    10841100        m_hasVisibleDescendant = false;
    10851101        m_hasSelfPaintingLayerDescendant = false;
    10861102        m_hasOutOfFlowPositionedDescendant = false;
     1103        setHasBlendedElementInChildStackingContext(false);
    10871104
    10881105        HashSet<const RenderObject*> childOutOfFlowDescendantContainingBlocks;
     
    11041121            bool hasSelfPaintingLayerDescendant = child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendant();
    11051122            bool hasOutOfFlowPositionedDescendant = !childOutOfFlowDescendantContainingBlocks.isEmpty();
     1123            bool hasBlendedElementInChildStackingContext = child->hasBlendMode() || child->hasBlendedElementInChildStackingContext();
    11061124
    11071125            m_hasVisibleDescendant |= hasVisibleDescendant;
    11081126            m_hasSelfPaintingLayerDescendant |= hasSelfPaintingLayerDescendant;
    11091127            m_hasOutOfFlowPositionedDescendant |= hasOutOfFlowPositionedDescendant;
    1110 
    1111             if (m_hasVisibleDescendant && m_hasSelfPaintingLayerDescendant && m_hasOutOfFlowPositionedDescendant)
     1128            setHasBlendedElementInChildStackingContext(this->hasBlendedElementInChildStackingContext() | hasBlendedElementInChildStackingContext);
     1129
     1130            if (m_hasVisibleDescendant && m_hasSelfPaintingLayerDescendant && m_hasOutOfFlowPositionedDescendant && this->hasBlendedElementInChildStackingContext())
    11121131                break;
    11131132        }
     
    11231142
    11241143        m_hasOutOfFlowPositionedDescendantDirty = false;
     1144
     1145        setHasBlendedElementInChildStackingContextStatusDirty(false);
    11251146    }
    11261147
     
    17781799        setAncestorChainHasOutOfFlowPositionedDescendant(child->renderer().containingBlock());
    17791800
     1801#if ENABLE(CSS_COMPOSITING)
     1802    if (child->hasBlendMode() || (!child->isStackingContext() && child->hasBlendedElementInChildStackingContext()))
     1803        child->updateNonCompositedParentStackingContextHasBlendedChild(true);
     1804#endif
     1805
    17801806    compositor().layerWasAdded(*this, *child);
    17811807}
     
    18191845    if (oldChild->isSelfPaintingLayer() || oldChild->hasSelfPaintingLayerDescendant())
    18201846        dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
     1847
     1848#if ENABLE(CSS_COMPOSITING)
     1849    if (oldChild->hasBlendMode() || oldChild->isolatesBlending())
     1850        dirtyAncestorParentStackingContextHasBlendedElement();
     1851#endif
    18211852
    18221853    return oldChild;
     
    64066437        else
    64076438            clearZOrderLists();
     6439
     6440#if ENABLE(CSS_COMPOSITING)
     6441            m_hasBlendedElementInChildStackingContext = isStackingContext ? nonCompositedParentStackingContextHasBlendedChild() : false;
     6442            dirtyAncestorParentStackingContextHasBlendedElement();
     6443#endif
     6444
    64086445        return;
    64096446    }
     
    65566593    updateTransform();
    65576594#if ENABLE(CSS_COMPOSITING)
    6558     updateBlendMode(oldStyle);
     6595    updateBlendMode();
    65596596#endif
    65606597#if ENABLE(CSS_FILTERS)
  • trunk/Source/WebCore/rendering/RenderLayer.h

    r165094 r165970  
    504504   
    505505#if ENABLE(CSS_COMPOSITING)
    506     void updateBlendMode(const RenderStyle*);
    507     void updateParentStackingContextShouldIsolateBlending();
     506    void updateBlendMode();
    508507#endif
    509508
     
    791790    {
    792791#if ENABLE(CSS_COMPOSITING)
    793         return m_isolatesBlending;
     792        return m_hasBlendedElementInChildStackingContext && isStackingContext();
    794793#else
    795794        return false;
     795#endif
     796    }
     797
     798    bool hasBlendedElementInChildStackingContext() const
     799    {
     800#if ENABLE(CSS_COMPOSITING)
     801        return m_hasBlendedElementInChildStackingContext;
     802#else
     803        return false;
     804#endif
     805    }
     806
     807    void setHasBlendedElementInChildStackingContext(bool hasBlendedElementInChildStackingContext)
     808    {
     809#if ENABLE(CSS_COMPOSITING)
     810        m_hasBlendedElementInChildStackingContext = hasBlendedElementInChildStackingContext;
     811#else
     812        UNUSED_PARAM(hasBlendedElementInChildStackingContext);
     813#endif
     814    }
     815
     816    bool hasBlendedElementInChildStackingContextStatusDirty() const
     817    {
     818#if ENABLE(CSS_COMPOSITING)
     819        return m_hasBlendedElementInChildStackingContextStatusDirty;
     820#else
     821        return false;
     822#endif
     823    }
     824
     825    void setHasBlendedElementInChildStackingContextStatusDirty(bool hasBlendedElementInChildStackingContextStatusDirty)
     826    {
     827#if ENABLE(CSS_COMPOSITING)
     828        m_hasBlendedElementInChildStackingContextStatusDirty = hasBlendedElementInChildStackingContextStatusDirty;
     829#else
     830        UNUSED_PARAM(hasBlendedElementInChildStackingContextStatusDirty);
    796831#endif
    797832    }
     
    11101145#endif
    11111146
     1147#if ENABLE(CSS_COMPOSITING)
     1148    void updateNonCompositedParentStackingContextHasBlendedChild(bool hasBlendedChild);
     1149    void dirtyAncestorParentStackingContextHasBlendedElement();
     1150    bool nonCompositedParentStackingContextHasBlendedChild() const;
     1151#endif
     1152
    11121153    void parentClipRects(const ClipRectsContext&, ClipRects&) const;
    11131154    ClipRect backgroundClipRect(const ClipRectsContext&) const;
     
    12471288#if ENABLE(CSS_COMPOSITING)
    12481289    BlendMode m_blendMode : 5;
    1249     bool m_isolatesBlending : 1;
    1250     bool m_updateParentStackingContextShouldIsolateBlendingDirty : 1;
     1290    bool m_hasBlendedElementInChildStackingContext : 1;
     1291    bool m_hasBlendedElementInChildStackingContextStatusDirty : 1;
    12511292#endif
    12521293
  • trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp

    r165676 r165970  
    10481048    layer.updateLayerListsIfNeeded();
    10491049
    1050 #if ENABLE(CSS_COMPOSITING)
    1051     layer.updateParentStackingContextShouldIsolateBlending();
    1052 #endif
    1053 
    10541050    if (layer.isFlowThreadCollectingGraphicsLayersUnderRegions()) {
    10551051        RenderFlowThread& flowThread = toRenderFlowThread(layer.renderer());
Note: See TracChangeset for help on using the changeset viewer.