Commit 7f9ac13f authored by ajuma@chromium.org's avatar ajuma@chromium.org

Make 'will-change: contents' suppress compositing in subtree

The contents of 'will-change: contents' elements are expected
to change frequently (e.g. every frame). Consequently, the
creation of composited layers within a 'will-change: contents'
subtree should be avoided where possible. This CL suppresses
compositing for animations and for will-change in descendants
of elements with 'will-change: contents'.

BUG=365885

Review URL: https://codereview.chromium.org/298723011

git-svn-id: svn://svn.chromium.org/blink/trunk@175584 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 99db239f
(GraphicsLayer
(bounds 800.00 600.00)
(children 1
(GraphicsLayer
(bounds 800.00 600.00)
(contentsOpaque 1)
(drawsContent 1)
)
)
)
<!DOCTYPE html>
<style>
.shouldNotComposite {
width: 30px;
height: 30px;
margin: 4px;
background-color: blue;
}
.positioned {
position: relative;
left: 40px;
}
#willChangeContents {
will-change: contents;
}
#willChangeOpacity {
will-change: opacity;
}
#willChangeTransform {
will-change: -webkit-transform;
}
#willChangeTop {
will-change: top;
}
#willChangeLeft {
will-change: left;
}
#animateOpacity {
-webkit-animation: fade-in-out 0.1s linear infinite alternate;
}
@-webkit-keyframes fade-in-out { from { opacity: 0.3; } to { opacity: 0.9; } }
</style>
<script>
if (window.testRunner) {
testRunner.dumpAsText();
testRunner.waitUntilDone();
}
function animationEventListener() {
if (window.testRunner) {
document.getElementById('layertree').innerText = window.internals.layerTreeAsText(document);
testRunner.notifyDone();
}
}
onload = function() {
document.getElementById('animateOpacity').addEventListener('webkitAnimationIteration', animationEventListener);
};
</script>
<div id="willChangeContents">
<div id="willChangeOpacity" class="shouldNotComposite"></div>
<div>
<div id="willChangeLeft" class="positioned shouldNotComposite"></div>
</div>
<div>
<div>
<div id="willChangeTransform" class="shouldNotComposite">
<div id="willChangeTop" class="positioned shouldNotComposite"></div>
</div>
</div>
</div>
<div id="animateOpacity" class="shouldNotComposite"></div>
</div>
<pre id="layertree"></pre>
...@@ -1091,6 +1091,7 @@ void StyleBuilderFunctions::applyInitialCSSPropertyWillChange(StyleResolverState ...@@ -1091,6 +1091,7 @@ void StyleBuilderFunctions::applyInitialCSSPropertyWillChange(StyleResolverState
state.style()->setWillChangeContents(false); state.style()->setWillChangeContents(false);
state.style()->setWillChangeScrollPosition(false); state.style()->setWillChangeScrollPosition(false);
state.style()->setWillChangeProperties(Vector<CSSPropertyID>()); state.style()->setWillChangeProperties(Vector<CSSPropertyID>());
state.style()->setSubtreeWillChangeContents(state.parentStyle()->subtreeWillChangeContents());
} }
void StyleBuilderFunctions::applyInheritCSSPropertyWillChange(StyleResolverState& state) void StyleBuilderFunctions::applyInheritCSSPropertyWillChange(StyleResolverState& state)
...@@ -1098,6 +1099,7 @@ void StyleBuilderFunctions::applyInheritCSSPropertyWillChange(StyleResolverState ...@@ -1098,6 +1099,7 @@ void StyleBuilderFunctions::applyInheritCSSPropertyWillChange(StyleResolverState
state.style()->setWillChangeContents(state.parentStyle()->willChangeContents()); state.style()->setWillChangeContents(state.parentStyle()->willChangeContents());
state.style()->setWillChangeScrollPosition(state.parentStyle()->willChangeScrollPosition()); state.style()->setWillChangeScrollPosition(state.parentStyle()->willChangeScrollPosition());
state.style()->setWillChangeProperties(state.parentStyle()->willChangeProperties()); state.style()->setWillChangeProperties(state.parentStyle()->willChangeProperties());
state.style()->setSubtreeWillChangeContents(state.parentStyle()->subtreeWillChangeContents());
} }
void StyleBuilderFunctions::applyValueCSSPropertyWillChange(StyleResolverState& state, CSSValue* value) void StyleBuilderFunctions::applyValueCSSPropertyWillChange(StyleResolverState& state, CSSValue* value)
...@@ -1121,6 +1123,7 @@ void StyleBuilderFunctions::applyValueCSSPropertyWillChange(StyleResolverState& ...@@ -1121,6 +1123,7 @@ void StyleBuilderFunctions::applyValueCSSPropertyWillChange(StyleResolverState&
state.style()->setWillChangeContents(willChangeContents); state.style()->setWillChangeContents(willChangeContents);
state.style()->setWillChangeScrollPosition(willChangeScrollPosition); state.style()->setWillChangeScrollPosition(willChangeScrollPosition);
state.style()->setWillChangeProperties(willChangeProperties); state.style()->setWillChangeProperties(willChangeProperties);
state.style()->setSubtreeWillChangeContents(willChangeContents || state.parentStyle()->subtreeWillChangeContents());
} }
void StyleBuilderFunctions::applyInitialCSSPropertyContent(StyleResolverState& state) void StyleBuilderFunctions::applyInitialCSSPropertyContent(StyleResolverState& state)
......
...@@ -110,10 +110,10 @@ CompositingReasons CompositingReasonFinder::styleDeterminedReasons(RenderObject* ...@@ -110,10 +110,10 @@ CompositingReasons CompositingReasonFinder::styleDeterminedReasons(RenderObject*
if (style->backfaceVisibility() == BackfaceVisibilityHidden) if (style->backfaceVisibility() == BackfaceVisibilityHidden)
directReasons |= CompositingReasonBackfaceVisibilityHidden; directReasons |= CompositingReasonBackfaceVisibilityHidden;
if (style->shouldCompositeForCurrentAnimations()) if (requiresCompositingForAnimation(renderer))
directReasons |= CompositingReasonActiveAnimation; directReasons |= CompositingReasonActiveAnimation;
if (style->hasWillChangeCompositingHint()) if (style->hasWillChangeCompositingHint() && !style->subtreeWillChangeContents())
directReasons |= CompositingReasonWillChangeCompositingHint; directReasons |= CompositingReasonWillChangeCompositingHint;
ASSERT(!(directReasons & ~CompositingReasonComboAllStyleDeterminedReasons)); ASSERT(!(directReasons & ~CompositingReasonComboAllStyleDeterminedReasons));
...@@ -166,6 +166,14 @@ CompositingReasons CompositingReasonFinder::nonStyleDeterminedDirectReasons(cons ...@@ -166,6 +166,14 @@ CompositingReasons CompositingReasonFinder::nonStyleDeterminedDirectReasons(cons
return directReasons; return directReasons;
} }
bool CompositingReasonFinder::requiresCompositingForAnimation(RenderObject* renderer) const
{
if (renderer->style()->subtreeWillChangeContents())
return renderer->style()->isRunningAnimationOnCompositor();
return renderer->style()->shouldCompositeForCurrentAnimations();
}
bool CompositingReasonFinder::requiresCompositingForPosition(RenderObject* renderer, const RenderLayer* layer, RenderLayer::ViewportConstrainedNotCompositedReason* viewportConstrainedNotCompositedReason) const bool CompositingReasonFinder::requiresCompositingForPosition(RenderObject* renderer, const RenderLayer* layer, RenderLayer::ViewportConstrainedNotCompositedReason* viewportConstrainedNotCompositedReason) const
{ {
return requiresCompositingForPositionSticky(renderer, layer) || requiresCompositingForPositionFixed(renderer, layer, viewportConstrainedNotCompositedReason); return requiresCompositingForPositionSticky(renderer, layer) || requiresCompositingForPositionFixed(renderer, layer, viewportConstrainedNotCompositedReason);
......
...@@ -37,6 +37,7 @@ private: ...@@ -37,6 +37,7 @@ private:
bool requiresCompositingForTransform(RenderObject*) const; bool requiresCompositingForTransform(RenderObject*) const;
bool requiresCompositingForFilters(RenderObject*) const; bool requiresCompositingForFilters(RenderObject*) const;
bool requiresCompositingForAnimation(RenderObject*) const;
bool requiresCompositingForPositionSticky(RenderObject*, const RenderLayer*) const; bool requiresCompositingForPositionSticky(RenderObject*, const RenderLayer*) const;
bool requiresCompositingForPositionFixed(RenderObject*, const RenderLayer*, RenderLayer::ViewportConstrainedNotCompositedReason*) const; bool requiresCompositingForPositionFixed(RenderObject*, const RenderLayer*, RenderLayer::ViewportConstrainedNotCompositedReason*) const;
......
...@@ -967,6 +967,7 @@ public: ...@@ -967,6 +967,7 @@ public:
bool willChangeContents() const { return rareNonInheritedData->m_willChange->m_contents; } bool willChangeContents() const { return rareNonInheritedData->m_willChange->m_contents; }
bool willChangeScrollPosition() const { return rareNonInheritedData->m_willChange->m_scrollPosition; } bool willChangeScrollPosition() const { return rareNonInheritedData->m_willChange->m_scrollPosition; }
bool hasWillChangeCompositingHint() const; bool hasWillChangeCompositingHint() const;
bool subtreeWillChangeContents() const { return rareInheritedData->m_subtreeWillChangeContents; }
// attribute setter methods // attribute setter methods
...@@ -1390,6 +1391,7 @@ public: ...@@ -1390,6 +1391,7 @@ public:
void setWillChangeProperties(const Vector<CSSPropertyID>& properties) { SET_VAR(rareNonInheritedData.access()->m_willChange, m_properties, properties); } void setWillChangeProperties(const Vector<CSSPropertyID>& properties) { SET_VAR(rareNonInheritedData.access()->m_willChange, m_properties, properties); }
void setWillChangeContents(bool b) { SET_VAR(rareNonInheritedData.access()->m_willChange, m_contents, b); } void setWillChangeContents(bool b) { SET_VAR(rareNonInheritedData.access()->m_willChange, m_contents, b); }
void setWillChangeScrollPosition(bool b) { SET_VAR(rareNonInheritedData.access()->m_willChange, m_scrollPosition, b); } void setWillChangeScrollPosition(bool b) { SET_VAR(rareNonInheritedData.access()->m_willChange, m_scrollPosition, b); }
void setSubtreeWillChangeContents(bool b) { SET_VAR(rareInheritedData, m_subtreeWillChangeContents, b); }
const SVGRenderStyle* svgStyle() const { return m_svgStyle.get(); } const SVGRenderStyle* svgStyle() const { return m_svgStyle.get(); }
SVGRenderStyle* accessSVGStyle() { return m_svgStyle.access(); } SVGRenderStyle* accessSVGStyle() { return m_svgStyle.access(); }
......
...@@ -90,6 +90,7 @@ StyleRareInheritedData::StyleRareInheritedData() ...@@ -90,6 +90,7 @@ StyleRareInheritedData::StyleRareInheritedData()
, m_textUnderlinePosition(RenderStyle::initialTextUnderlinePosition()) , m_textUnderlinePosition(RenderStyle::initialTextUnderlinePosition())
, m_rubyPosition(RenderStyle::initialRubyPosition()) , m_rubyPosition(RenderStyle::initialRubyPosition())
, m_touchActionDelay(RenderStyle::initialTouchActionDelay()) , m_touchActionDelay(RenderStyle::initialTouchActionDelay())
, m_subtreeWillChangeContents(false)
, hyphenationLimitBefore(-1) , hyphenationLimitBefore(-1)
, hyphenationLimitAfter(-1) , hyphenationLimitAfter(-1)
, hyphenationLimitLines(-1) , hyphenationLimitLines(-1)
...@@ -145,6 +146,7 @@ StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedData& o) ...@@ -145,6 +146,7 @@ StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedData& o)
, m_textUnderlinePosition(o.m_textUnderlinePosition) , m_textUnderlinePosition(o.m_textUnderlinePosition)
, m_rubyPosition(o.m_rubyPosition) , m_rubyPosition(o.m_rubyPosition)
, m_touchActionDelay(o.m_touchActionDelay) , m_touchActionDelay(o.m_touchActionDelay)
, m_subtreeWillChangeContents(o.m_subtreeWillChangeContents)
, hyphenationString(o.hyphenationString) , hyphenationString(o.hyphenationString)
, hyphenationLimitBefore(o.hyphenationLimitBefore) , hyphenationLimitBefore(o.hyphenationLimitBefore)
, hyphenationLimitAfter(o.hyphenationLimitAfter) , hyphenationLimitAfter(o.hyphenationLimitAfter)
...@@ -208,6 +210,7 @@ bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const ...@@ -208,6 +210,7 @@ bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const
&& m_textIndentLine == o.m_textIndentLine && m_textIndentLine == o.m_textIndentLine
&& m_textIndentType == o.m_textIndentType && m_textIndentType == o.m_textIndentType
&& m_lineBoxContain == o.m_lineBoxContain && m_lineBoxContain == o.m_lineBoxContain
&& m_subtreeWillChangeContents == o.m_subtreeWillChangeContents
&& hyphenationString == o.hyphenationString && hyphenationString == o.hyphenationString
&& locale == o.locale && locale == o.locale
&& textEmphasisCustomMark == o.textEmphasisCustomMark && textEmphasisCustomMark == o.textEmphasisCustomMark
......
...@@ -131,6 +131,10 @@ public: ...@@ -131,6 +131,10 @@ public:
unsigned m_rubyPosition : 1; // RubyPosition unsigned m_rubyPosition : 1; // RubyPosition
unsigned m_touchActionDelay : 1; // TouchActionDelay unsigned m_touchActionDelay : 1; // TouchActionDelay
// Though will-change is not itself an inherited property, the intent
// expressed by 'will-change: contents' includes descendants.
unsigned m_subtreeWillChangeContents : 1;
AtomicString hyphenationString; AtomicString hyphenationString;
short hyphenationLimitBefore; short hyphenationLimitBefore;
short hyphenationLimitAfter; short hyphenationLimitAfter;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment