Changeset 188530 in webkit


Ignore:
Timestamp:
Aug 17, 2015 11:32:49 AM (9 years ago)
Author:
Simon Fraser
Message:

will-change should sometimes trigger compositing
https://bugs.webkit.org/show_bug.cgi?id=148072

Reviewed by Tim Horton.
Source/JavaScriptCore:

Include will-change as a reason for compositing.

  • inspector/protocol/LayerTree.json:

Source/WebCore:

Implement the compositing side-effects of will-change, if any of the
following properties are specified:

opacity
filter (as -webkit-filter)
backdrop-filter (as -webkit-backdrop-filter)
transform (on transformable elements only)

Tests: compositing/layer-creation/will-change-change.html

compositing/layer-creation/will-change-layer-creation.html

  • inspector/InspectorLayerTreeAgent.cpp:

(WebCore::InspectorLayerTreeAgent::reasonsForCompositingLayer): Tell the inspector
about will-change.

  • rendering/RenderElement.cpp:

(WebCore::RenderElement::adjustStyleDifference): Need to trigger a recomposite if
will-change includes a compositing trigger property. This gets called before and
after setting the style, so this checks both states.
(WebCore::RenderElement::shouldWillChangeCreateStackingContext):

  • rendering/RenderElement.h:

(WebCore::RenderElement::willChangeCreatesStackingContext): Helper function that
RenderInline uses to determine if it needs to create a RenderLayer, since RenderInline
doesn't get automatic layer RenderLayers as a side effect of having non-auto z-index
in the style.

  • rendering/RenderInline.h: Need to trigger a RenderLayer if will-change includes

a property that applies to inlines.

  • rendering/RenderLayerCompositor.cpp:

(WebCore::RenderLayerCompositor::requiresCompositingLayer): Call requiresCompositingForWillChange().
(WebCore::RenderLayerCompositor::requiresOwnBackingStore): Call requiresCompositingForWillChange().
(WebCore::RenderLayerCompositor::reasonsForCompositing): Include requiresCompositingForWillChange().
(WebCore::RenderLayerCompositor::requiresCompositingForWillChange): If will-change contains a
property that would trigger compositing on this element, return true.

  • rendering/RenderLayerCompositor.h:
  • rendering/style/RenderStyle.cpp:

(WebCore::RenderStyle::changeRequiresLayout): Set ContextSensitivePropertyWillChange in
changedContextSensitiveProperties if will-change changes.

  • rendering/style/RenderStyle.h: Rename for clarity.
  • rendering/style/RenderStyleConstants.h: Add ContextSensitivePropertyWillChange.
  • rendering/style/WillChangeData.cpp:

(WebCore::propertyCreatesStackingContext): Subset of properties that create stacking
context on any element.
(WebCore::propertyCreatesStackingContextOnBoxesOnly): Additional properties that
create stacking context on boxes.
(WebCore::propertyTriggersCompositing): Properties that trigger compositing on
any element.
(WebCore::propertyTriggersCompositingOnBoxesOnly): Additional properties that
trigger compositing on boxes.
(WebCore::WillChangeData::addFeature): As features are added, manage a set of
flags to know if they trigger stacking context or compositing, on inlines and boxes.
(WebCore::WillChangeData::createsStackingContext): Deleted.

  • rendering/style/WillChangeData.h:

(WebCore::WillChangeData::canCreateStackingContext):
(WebCore::WillChangeData::canCreateStackingContextOnInline):
(WebCore::WillChangeData::canTriggerCompositing):
(WebCore::WillChangeData::canTriggerCompositingOnInline):

Source/WebInspectorUI:

Have the web inspector show a correct compositing reason for will-change.
This could be improved to indicate which specific value in will-change triggered
the compositing.

  • Localizations/en.lproj/localizedStrings.js:
  • UserInterface/Views/LayerTreeDetailsSidebarPanel.js:

(WebInspector.LayerTreeDetailsSidebarPanel.prototype._populateListOfCompositingReasons):
(WebInspector.LayerTreeDetailsSidebarPanel):

LayoutTests:

  • compositing/layer-creation/will-change-change-expected.txt: Added.
  • compositing/layer-creation/will-change-change.html: Added.
  • compositing/layer-creation/will-change-layer-creation-expected.txt: Added.
  • compositing/layer-creation/will-change-layer-creation.html: Added.
Location:
trunk
Files:
4 added
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r188527 r188530  
     12015-08-17  Simon Fraser  <simon.fraser@apple.com>
     2
     3        will-change should sometimes trigger compositing
     4        https://bugs.webkit.org/show_bug.cgi?id=148072
     5
     6        Reviewed by Tim Horton.
     7
     8        * compositing/layer-creation/will-change-change-expected.txt: Added.
     9        * compositing/layer-creation/will-change-change.html: Added.
     10        * compositing/layer-creation/will-change-layer-creation-expected.txt: Added.
     11        * compositing/layer-creation/will-change-layer-creation.html: Added.
     12
    1132015-08-17  Timothy Horton  <timothy_horton@apple.com>
    214
  • trunk/Source/JavaScriptCore/ChangeLog

    r188529 r188530  
     12015-08-17  Simon Fraser  <simon.fraser@apple.com>
     2
     3        will-change should sometimes trigger compositing
     4        https://bugs.webkit.org/show_bug.cgi?id=148072
     5
     6        Reviewed by Tim Horton.
     7       
     8        Include will-change as a reason for compositing.
     9
     10        * inspector/protocol/LayerTree.json:
     11
    1122015-08-17  Yusuke Suzuki  <utatane.tea@gmail.com>
    213
  • trunk/Source/JavaScriptCore/inspector/protocol/LayerTree.json

    r174906 r188530  
    7272                { "name": "perspective", "type": "boolean", "optional": true, "description": "Composition due to association with an element with perspective applied." },
    7373                { "name": "preserve3D", "type": "boolean", "optional": true, "description": "Composition due to association with an element with a \"transform-style: preserve-3d\" style." },
     74                { "name": "willChange", "type": "boolean", "optional": true, "description": "Composition due to association with an element with a \"will-change\" style." },
    7475                { "name": "root", "type": "boolean", "optional": true, "description": "Composition due to association with the root element." },
    7576                { "name": "blending", "type": "boolean", "optional": true, "description": "Composition due to association with an element with a \"blend-mode\" style." }
  • trunk/Source/WebCore/ChangeLog

    r188527 r188530  
     12015-08-17  Simon Fraser  <simon.fraser@apple.com>
     2
     3        will-change should sometimes trigger compositing
     4        https://bugs.webkit.org/show_bug.cgi?id=148072
     5
     6        Reviewed by Tim Horton.
     7       
     8        Implement the compositing side-effects of will-change, if any of the
     9        following properties are specified:
     10            opacity
     11            filter (as -webkit-filter)
     12            backdrop-filter (as -webkit-backdrop-filter)
     13            transform (on transformable elements only)
     14
     15        Tests: compositing/layer-creation/will-change-change.html
     16               compositing/layer-creation/will-change-layer-creation.html
     17
     18        * inspector/InspectorLayerTreeAgent.cpp:
     19        (WebCore::InspectorLayerTreeAgent::reasonsForCompositingLayer): Tell the inspector
     20        about will-change.
     21        * rendering/RenderElement.cpp:
     22        (WebCore::RenderElement::adjustStyleDifference): Need to trigger a recomposite if
     23        will-change includes a compositing trigger property. This gets called before and
     24        after setting the style, so this checks both states.
     25        (WebCore::RenderElement::shouldWillChangeCreateStackingContext):
     26        * rendering/RenderElement.h:
     27        (WebCore::RenderElement::willChangeCreatesStackingContext): Helper function that
     28        RenderInline uses to determine if it needs to create a RenderLayer, since RenderInline
     29        doesn't get automatic layer RenderLayers as a side effect of having non-auto z-index
     30        in the style.
     31        * rendering/RenderInline.h: Need to trigger a RenderLayer if will-change includes
     32        a property that applies to inlines.
     33        * rendering/RenderLayerCompositor.cpp:
     34        (WebCore::RenderLayerCompositor::requiresCompositingLayer): Call requiresCompositingForWillChange().
     35        (WebCore::RenderLayerCompositor::requiresOwnBackingStore): Call requiresCompositingForWillChange().
     36        (WebCore::RenderLayerCompositor::reasonsForCompositing): Include requiresCompositingForWillChange().
     37        (WebCore::RenderLayerCompositor::requiresCompositingForWillChange): If will-change contains a
     38        property that would trigger compositing on this element, return true.
     39        * rendering/RenderLayerCompositor.h:
     40        * rendering/style/RenderStyle.cpp:
     41        (WebCore::RenderStyle::changeRequiresLayout): Set ContextSensitivePropertyWillChange in
     42        changedContextSensitiveProperties if will-change changes.
     43        * rendering/style/RenderStyle.h: Rename for clarity.
     44        * rendering/style/RenderStyleConstants.h: Add ContextSensitivePropertyWillChange.
     45        * rendering/style/WillChangeData.cpp:
     46        (WebCore::propertyCreatesStackingContext): Subset of properties that create stacking
     47        context on any element.
     48        (WebCore::propertyCreatesStackingContextOnBoxesOnly): Additional properties that
     49        create stacking context on boxes.
     50        (WebCore::propertyTriggersCompositing): Properties that trigger compositing on
     51        any element.
     52        (WebCore::propertyTriggersCompositingOnBoxesOnly): Additional properties that
     53        trigger compositing on boxes.
     54        (WebCore::WillChangeData::addFeature): As features are added, manage a set of
     55        flags to know if they trigger stacking context or compositing, on inlines and boxes.
     56        (WebCore::WillChangeData::createsStackingContext): Deleted.
     57        * rendering/style/WillChangeData.h:
     58        (WebCore::WillChangeData::canCreateStackingContext):
     59        (WebCore::WillChangeData::canCreateStackingContextOnInline):
     60        (WebCore::WillChangeData::canTriggerCompositing):
     61        (WebCore::WillChangeData::canTriggerCompositingOnInline):
     62
    1632015-08-17  Timothy Horton  <timothy_horton@apple.com>
    264
  • trunk/Source/WebCore/inspector/InspectorLayerTreeAgent.cpp

    r186279 r188530  
    308308        compositingReasons->setPreserve3D(true);
    309309
     310    if (reasonsBitmask & CompositingReasonWillChange)
     311        compositingReasons->setWillChange(true);
     312
    310313    if (reasonsBitmask & CompositingReasonRoot)
    311314        compositingReasons->setRoot(true);
  • trunk/Source/WebCore/rendering/RenderElement.cpp

    r188370 r188530  
    285285    }
    286286   
     287    if (contextSensitiveProperties & ContextSensitivePropertyWillChange) {
     288        if (style().willChange() && style().willChange()->canTriggerCompositing())
     289            diff = std::max(diff, StyleDifferenceRecompositeLayer);
     290    }
     291   
    287292    if ((contextSensitiveProperties & ContextSensitivePropertyFilter) && hasLayer()) {
    288293        RenderLayer* layer = downcast<RenderLayerModelObject>(*this).layer();
     
    14601465    repaint();
    14611466    return true;
     1467}
     1468
     1469bool RenderElement::shouldWillChangeCreateStackingContext() const
     1470{
     1471    ASSERT(style().willChange());
     1472    ASSERT(style().willChange()->canCreateStackingContext());
     1473
     1474    // On inlines, we only want to trigger RenderLayer creation
     1475    // if will-change contains a property that applies to inlines.
     1476    return is<RenderBox>(this) || (is<RenderInline>(this) && style().willChange()->canCreateStackingContextOnInline());
    14621477}
    14631478
  • trunk/Source/WebCore/rendering/RenderElement.h

    r188482 r188530  
    166166    bool hasClipPath() const { return style().clipPath(); }
    167167    bool hasHiddenBackface() const { return style().backfaceVisibility() == BackfaceVisibilityHidden; }
     168    bool willChangeCreatesStackingContext() const
     169    {
     170        return style().willChange() && style().willChange()->canCreateStackingContext() && shouldWillChangeCreateStackingContext();
     171    }
    168172
    169173    // anchorRect() is conceptually similar to absoluteBoundingBoxRect(), but is intended for scrolling to an anchor.
     
    305309
    306310    void clearLayoutRootIfNeeded() const;
     311   
     312    bool shouldWillChangeCreateStackingContext() const;
    307313
    308314    unsigned m_baseTypeFlags : 6;
  • trunk/Source/WebCore/rendering/RenderInline.h

    r181505 r188530  
    137137    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override final;
    138138
    139     virtual bool requiresLayer() const override { return isInFlowPositioned() || createsGroup() || hasClipPath(); }
     139    virtual bool requiresLayer() const override { return isInFlowPositioned() || createsGroup() || hasClipPath() || willChangeCreatesStackingContext(); }
    140140
    141141    virtual LayoutUnit offsetLeft() const override final;
  • trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp

    r187659 r188530  
    21912191        || requiresCompositingForAnimation(renderer)
    21922192        || requiresCompositingForFilters(renderer)
     2193        || requiresCompositingForWillChange(renderer)
    21932194        || requiresCompositingForPosition(renderer, *renderer.layer(), viewportConstrainedNotCompositedReason)
    21942195#if PLATFORM(IOS)
     
    22332234        || requiresCompositingForAnimation(renderer)
    22342235        || requiresCompositingForFilters(renderer)
     2236        || requiresCompositingForWillChange(renderer)
    22352237        || requiresCompositingForPosition(renderer, layer)
    22362238        || requiresCompositingForOverflowScrolling(layer)
     
    22932295    if (requiresCompositingForFilters(renderer))
    22942296        reasons |= CompositingReasonFilters;
     2297
     2298    if (requiresCompositingForWillChange(renderer))
     2299        reasons |= CompositingReasonWillChange;
    22952300
    22962301    if (requiresCompositingForPosition(renderer, *renderer.layer()))
     
    26592664}
    26602665
     2666bool RenderLayerCompositor::requiresCompositingForWillChange(RenderLayerModelObject& renderer) const
     2667{
     2668    if (!renderer.style().willChange() || !renderer.style().willChange()->canTriggerCompositing())
     2669        return false;
     2670
     2671    if (is<RenderBox>(renderer))
     2672        return true;
     2673
     2674    return renderer.style().willChange()->canTriggerCompositingOnInline();
     2675}
     2676
    26612677bool RenderLayerCompositor::isAsyncScrollableStickyLayer(const RenderLayer& layer, const RenderLayer** enclosingAcceleratedOverflowLayer) const
    26622678{
  • trunk/Source/WebCore/rendering/RenderLayerCompositor.h

    r187659 r188530  
    8181    CompositingReasonPerspective                            = 1 << 21,
    8282    CompositingReasonPreserve3D                             = 1 << 22,
    83     CompositingReasonRoot                                   = 1 << 23,
    84     CompositingReasonIsolatesCompositedBlendingDescendants  = 1 << 24,
     83    CompositingReasonWillChange                             = 1 << 23,
     84    CompositingReasonRoot                                   = 1 << 24,
     85    CompositingReasonIsolatesCompositedBlendingDescendants  = 1 << 25,
    8586};
    8687typedef unsigned CompositingReasons;
     
    423424    bool requiresCompositingForFrame(RenderLayerModelObject&) const;
    424425    bool requiresCompositingForFilters(RenderLayerModelObject&) const;
     426    bool requiresCompositingForWillChange(RenderLayerModelObject&) const;
    425427    bool requiresCompositingForScrollableFrame() const;
    426428    bool requiresCompositingForPosition(RenderLayerModelObject&, const RenderLayer&, RenderLayer::ViewportConstrainedNotCompositedReason* = nullptr) const;
  • trunk/Source/WebCore/rendering/style/RenderStyle.cpp

    r188512 r188530  
    555555            return true;
    556556#endif
     557
     558        if (!rareNonInheritedData->willChangeDataEquivalent(*other.rareNonInheritedData.get())) {
     559            changedContextSensitiveProperties |= ContextSensitivePropertyWillChange;
     560            // Don't return; keep looking for another change
     561        }
    557562    }
    558563
  • trunk/Source/WebCore/rendering/style/RenderStyle.h

    r188514 r188530  
    18071807            return false;
    18081808       
    1809         return willChange()->createsStackingContext();
     1809        return willChange()->canCreateStackingContext();
    18101810    }
    18111811
  • trunk/Source/WebCore/rendering/style/RenderStyleConstants.h

    r187110 r188530  
    7070    ContextSensitivePropertyFilter      = 1 << 2,
    7171    ContextSensitivePropertyClipRect    = 1 << 3,
    72     ContextSensitivePropertyClipPath    = 1 << 4
     72    ContextSensitivePropertyClipPath    = 1 << 4,
     73    ContextSensitivePropertyWillChange  = 1 << 5,
    7374};
    7475
  • trunk/Source/WebCore/rendering/style/WillChangeData.cpp

    r188514 r188530  
    8585    case CSSPropertyWebkitMaskImage:
    8686    case CSSPropertyWebkitMaskBoxImage:
     87#if ENABLE(CSS_REGIONS)
     88    case CSSPropertyWebkitFlowFrom:
     89#endif
     90        return true;
     91    default:
     92        return false;
     93    }
     94}
     95
     96static bool propertyCreatesStackingContextOnBoxesOnly(CSSPropertyID property)
     97{
     98    switch (property) {
    8799    case CSSPropertyPerspective:
    88100    case CSSPropertyTransform:
    89101    case CSSPropertyTransformStyle:
    90102    case CSSPropertyWebkitTransformStyle:
    91 #if ENABLE(CSS_REGIONS)
    92     case CSSPropertyWebkitFlowFrom:
    93 #endif
    94103#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
    95104    case CSSPropertyWebkitOverflowScrolling:
     
    101110}
    102111
    103 bool WillChangeData::createsStackingContext() const
     112static bool propertyTriggersCompositing(CSSPropertyID property)
    104113{
    105     for (const auto& feature : m_animatableFeatures) {
    106         if (feature.feature() == Property && propertyCreatesStackingContext(feature.property()))
    107             return true;
     114    switch (property) {
     115    case CSSPropertyOpacity:
     116    case CSSPropertyWebkitFilter:
     117#if ENABLE(FILTERS_LEVEL_2)
     118    case CSSPropertyWebkitBackdropFilter:
     119#endif
     120        return true;
     121    default:
     122        return false;
    108123    }
    109     return false;
     124}
     125
     126static bool propertyTriggersCompositingOnBoxesOnly(CSSPropertyID property)
     127{
     128    // Don't trigger for perspective and transform-style, because those
     129    // only do compositing if they have a 3d-transformed descendant and
     130    // we don't want to do compositing all the time.
     131    // Similarly, we don't want -webkit-overflow-scrolling-touch to
     132    // always composite if there's no scrollable overflow.
     133    switch (property) {
     134    case CSSPropertyTransform:
     135        return true;
     136    default:
     137        return false;
     138    }
    110139}
    111140
     
    114143    ASSERT(feature == Property || propertyID == CSSPropertyInvalid);
    115144    m_animatableFeatures.append(AnimatableFeature(feature, propertyID));
     145
     146    m_canCreateStackingContextOnInline |= propertyCreatesStackingContext(propertyID);
     147    m_canCreateStackingContext |= m_canCreateStackingContextOnInline | propertyCreatesStackingContextOnBoxesOnly(propertyID);
     148
     149    m_canTriggerCompositingOnInline |= propertyTriggersCompositing(propertyID);
     150    m_canTriggerCompositing |= m_canTriggerCompositingOnInline | propertyTriggersCompositingOnBoxesOnly(propertyID);
    116151}
    117152
  • trunk/Source/WebCore/rendering/style/WillChangeData.h

    r188514 r188530  
    5454    bool containsContents() const;
    5555    bool containsProperty(CSSPropertyID) const;
    56     bool createsStackingContext() const;
     56
     57    bool canCreateStackingContext() const { return m_canCreateStackingContext; }
     58    bool canCreateStackingContextOnInline() const { return m_canCreateStackingContextOnInline; }
     59
     60    bool canTriggerCompositing() const { return m_canTriggerCompositing; }
     61    bool canTriggerCompositingOnInline() const { return m_canTriggerCompositingOnInline; }
    5762
    5863    enum Feature {
     
    119124
    120125    Vector<AnimatableFeature, 1> m_animatableFeatures;
     126    bool m_canCreateStackingContext { false };
     127    bool m_canCreateStackingContextOnInline { false };
     128    bool m_canTriggerCompositing { false };
     129    bool m_canTriggerCompositingOnInline { false };
    121130};
    122131
  • trunk/Source/WebInspectorUI/ChangeLog

    r188506 r188530  
     12015-08-17  Simon Fraser  <simon.fraser@apple.com>
     2
     3        will-change should sometimes trigger compositing
     4        https://bugs.webkit.org/show_bug.cgi?id=148072
     5
     6        Reviewed by Tim Horton.
     7       
     8        Have the web inspector show a correct compositing reason for will-change.
     9        This could be improved to indicate which specific value in will-change triggered
     10        the compositing.
     11
     12        * Localizations/en.lproj/localizedStrings.js:
     13        * UserInterface/Views/LayerTreeDetailsSidebarPanel.js:
     14        (WebInspector.LayerTreeDetailsSidebarPanel.prototype._populateListOfCompositingReasons):
     15        (WebInspector.LayerTreeDetailsSidebarPanel):
     16
    1172015-08-14  Matt Baker  <mattbaker@apple.com>
    218
  • trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js

    r188503 r188530  
    229229localizedStrings["Element has “position: sticky” style"] = "Element has “position: sticky” style";
    230230localizedStrings["Element has “transform-style: preserve-3d” style"] = "Element has “transform-style: preserve-3d” style";
     231localizedStrings["Element has “will-change” style with includes opacity, transform, transform-style, perspective, filter or backdrop-filter"] = "Element has “will-change” style with includes opacity, transform, transform-style, perspective, filter or backdrop-filter";
    231232localizedStrings["Element is <canvas>"] = "Element is <canvas>";
    232233localizedStrings["Element is <iframe>"] = "Element is <iframe>";
  • trunk/Source/WebInspectorUI/UserInterface/Views/LayerTreeDetailsSidebarPanel.js

    r185141 r188530  
    430430        if (compositingReasons.preserve3D)
    431431            addReason(WebInspector.UIString("Element has “transform-style: preserve-3d” style"));
     432        if (compositingReasons.willChange)
     433            addReason(WebInspector.UIString("Element has “will-change” style with includes opacity, transform, transform-style, perspective, filter or backdrop-filter"));
    432434        if (compositingReasons.root)
    433435            addReason(WebInspector.UIString("Element is the root element"));
Note: See TracChangeset for help on using the changeset viewer.