Skip to content
Permalink
Browse files
[CSS Blending] Compositing requirements for blending are not computed…
… correctly

https://bugs.webkit.org/show_bug.cgi?id=130664

Patch by Ion Rosca <rosca@adobe.com> on 2014-04-02
Reviewed by Dean Jackson.

Source/WebCore:

Tests: css3/compositing/blend-mode-accelerated-with-multiple-stacking-contexts.html
       css3/compositing/blend-mode-with-accelerated-sibling.html

Compositing requirements for blending: if a layer having blend mode
other than normal is composited for any reason, its closest stacking
context ancestor should be composited as well.

* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::RenderLayer):
* rendering/RenderLayer.h: added a new field,
m_hasUnisolatedCompositedBlendingDescendants, which is true if the layer
has composited blending descendants not isolated by any stacking context child;
added a new method: isolatesCompositedBlending(), which is true if we should
accelerate that layer in order to perform isolation correctly.

* rendering/RenderLayerCompositor.cpp:
(WebCore::CompositingState::CompositingState): m_subtreeHasBlending was renamed
m_hasUnisolatedCompositedBlendingDescendants in order to be more self-explanatory.
(WebCore::RenderLayerCompositor::computeCompositingRequirements):
computes the isolation requirements for composited blending by
(re)setting RenderLayer::m_hasUnisolatedCompositedBlendingDescendants flag.

(WebCore::RenderLayerCompositor::reasonsForCompositing):
fixed the reason of compositing: isolation instead of blending.

(WebCore::RenderLayerCompositor::requiresCompositingForIndirectReason):
* rendering/RenderLayerCompositor.h:

LayoutTests:

* css3/compositing/blend-mode-accelerated-with-multiple-stacking-contexts-expected.txt: Added.
* css3/compositing/blend-mode-accelerated-with-multiple-stacking-contexts.html: Added.
* css3/compositing/blend-mode-with-accelerated-sibling-expected.txt: Added.
* css3/compositing/blend-mode-with-accelerated-sibling.html: Added.

Canonical link: https://commits.webkit.org/149138@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@166634 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
rosca authored and webkit-commit-queue committed Apr 2, 2014
1 parent 760eb76 commit 0c2ccf6e282bece98ac254cfa6dc988449e6f411
Showing 10 changed files with 197 additions and 15 deletions.
@@ -1,3 +1,15 @@
2014-04-02 Ion Rosca <rosca@adobe.com>

[CSS Blending] Compositing requirements for blending are not computed correctly
https://bugs.webkit.org/show_bug.cgi?id=130664

Reviewed by Dean Jackson.

* css3/compositing/blend-mode-accelerated-with-multiple-stacking-contexts-expected.txt: Added.
* css3/compositing/blend-mode-accelerated-with-multiple-stacking-contexts.html: Added.
* css3/compositing/blend-mode-with-accelerated-sibling-expected.txt: Added.
* css3/compositing/blend-mode-with-accelerated-sibling.html: Added.

2014-04-01 Mihnea Ovidenie <mihnea@adobe.com>

[CSSRegions] Displaying region's children in another region not supported
@@ -0,0 +1,23 @@
(GraphicsLayer
(bounds 800.00 600.00)
(children 1
(GraphicsLayer
(bounds 800.00 600.00)
(contentsOpaque 1)
(children 1
(GraphicsLayer
(position 8.00 8.00)
(bounds 784.00 10.00)
(children 1
(GraphicsLayer
(bounds 10.00 10.00)
(blendMode multiply)
(contentsOpaque 1)
)
)
)
)
)
)
)

@@ -0,0 +1,32 @@
<!DOCTYPE HTML>
<!-- This test will check that only the direct parent of blending element gets accelerated -->
<style>
.accelerated {
-webkit-transform: rotateX(0deg);
}
.blended {
-webkit-mix-blend-mode: multiply;
}
.child {
width: 10px;
height: 10px;
background-color: green;
}
.parent {
-webkit-isolation: isolate;
}
</style>

<div class="parent">
<div class="parent">
<div class="accelerated blended child"></div>
</div>
</div>
<pre id="layerTree"></pre>
<script>
if (window.testRunner)
window.testRunner.dumpAsText();

var text = document.getElementById("layerTree");
text.innerHTML = window.internals.layerTreeAsText(document);
</script>
@@ -0,0 +1,17 @@
(GraphicsLayer
(bounds 800.00 600.00)
(children 1
(GraphicsLayer
(bounds 800.00 600.00)
(contentsOpaque 1)
(children 1
(GraphicsLayer
(position 8.00 8.00)
(bounds 10.00 10.00)
(contentsOpaque 1)
)
)
)
)
)

@@ -0,0 +1,31 @@
<!DOCTYPE HTML>
<!-- This test will check that parent is not accelerated when it has non-accelerated blended children -->
<style>
.accelerated {
-webkit-transform: rotateX(0deg);
}
.blended {
-webkit-mix-blend-mode: multiply;
}
.child {
width: 10px;
height: 10px;
background-color: green;
}
.parent {
-webkit-isolation: isolate;
}
</style>

<div class="parent">
<div class="accelerated child"></div>
<div class="blended child"></div>
</div>
<pre id="layerTree"></pre>
<script>
if (window.testRunner)
window.testRunner.dumpAsText();

var text = document.getElementById("layerTree");
text.innerHTML = window.internals.layerTreeAsText(document);
</script>
@@ -1,3 +1,38 @@
2014-04-02 Ion Rosca <rosca@adobe.com>

[CSS Blending] Compositing requirements for blending are not computed correctly
https://bugs.webkit.org/show_bug.cgi?id=130664

Reviewed by Dean Jackson.

Tests: css3/compositing/blend-mode-accelerated-with-multiple-stacking-contexts.html
css3/compositing/blend-mode-with-accelerated-sibling.html

Compositing requirements for blending: if a layer having blend mode
other than normal is composited for any reason, its closest stacking
context ancestor should be composited as well.

* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::RenderLayer):
* rendering/RenderLayer.h: added a new field,
m_hasUnisolatedCompositedBlendingDescendants, which is true if the layer
has composited blending descendants not isolated by any stacking context child;
added a new method: isolatesCompositedBlending(), which is true if we should
accelerate that layer in order to perform isolation correctly.

* rendering/RenderLayerCompositor.cpp:
(WebCore::CompositingState::CompositingState): m_subtreeHasBlending was renamed
m_hasUnisolatedCompositedBlendingDescendants in order to be more self-explanatory.
(WebCore::RenderLayerCompositor::computeCompositingRequirements):
computes the isolation requirements for composited blending by
(re)setting RenderLayer::m_hasUnisolatedCompositedBlendingDescendants flag.

(WebCore::RenderLayerCompositor::reasonsForCompositing):
fixed the reason of compositing: isolation instead of blending.

(WebCore::RenderLayerCompositor::requiresCompositingForIndirectReason):
* rendering/RenderLayerCompositor.h:

2014-04-02 Frédéric Wang <fred.wang@free.fr>

Operator stretching: expose a math data API
@@ -186,6 +186,7 @@ RenderLayer::RenderLayer(RenderLayerModelObject& rendererLayerModelObject)
#endif
#if ENABLE(CSS_COMPOSITING)
, m_blendMode(BlendModeNormal)
, m_hasUnisolatedCompositedBlendingDescendants(false)
, m_hasBlendedElementInChildStackingContext(false)
, m_hasBlendedElementInChildStackingContextStatusDirty(false)
#endif
@@ -790,6 +790,23 @@ class RenderLayer final : public ScrollableArea {
BlendMode blendMode() const { return m_blendMode; }
#endif

bool isolatesCompositedBlending() const
{
#if ENABLE(CSS_COMPOSITING)
return m_hasUnisolatedCompositedBlendingDescendants && isStackingContext();
#else
return false;
#endif
}

#if ENABLE(CSS_COMPOSITING)
bool hasUnisolatedCompositedBlendingDescendants() const { return m_hasUnisolatedCompositedBlendingDescendants; }
void setHasUnisolatedCompositedBlendingDescendants(bool hasUnisolatedCompositedBlendingDescendants)
{
m_hasUnisolatedCompositedBlendingDescendants = hasUnisolatedCompositedBlendingDescendants;
}
#endif

bool isolatesBlending() const
{
#if ENABLE(CSS_COMPOSITING)
@@ -1291,6 +1308,7 @@ class RenderLayer final : public ScrollableArea {

#if ENABLE(CSS_COMPOSITING)
BlendMode m_blendMode : 5;
bool m_hasUnisolatedCompositedBlendingDescendants : 1;
bool m_hasBlendedElementInChildStackingContext : 1;
bool m_hasBlendedElementInChildStackingContextStatusDirty : 1;
#endif
@@ -195,7 +195,9 @@ struct CompositingState {
: m_compositingAncestor(compAncestor)
, m_subtreeIsCompositing(false)
, m_testingOverlap(testOverlap)
, m_subtreeHasBlending(false)
#if ENABLE(CSS_COMPOSITING)
, m_hasUnisolatedCompositedBlendingDescendants(false)
#endif
#ifndef NDEBUG
, m_depth(0)
#endif
@@ -206,7 +208,9 @@ struct CompositingState {
: m_compositingAncestor(other.m_compositingAncestor)
, m_subtreeIsCompositing(other.m_subtreeIsCompositing)
, m_testingOverlap(other.m_testingOverlap)
, m_subtreeHasBlending(other.m_subtreeHasBlending)
#if ENABLE(CSS_COMPOSITING)
, m_hasUnisolatedCompositedBlendingDescendants(other.m_hasUnisolatedCompositedBlendingDescendants)
#endif
#ifndef NDEBUG
, m_depth(other.m_depth + 1)
#endif
@@ -216,7 +220,9 @@ struct CompositingState {
RenderLayer* m_compositingAncestor;
bool m_subtreeIsCompositing;
bool m_testingOverlap;
bool m_subtreeHasBlending;
#if ENABLE(CSS_COMPOSITING)
bool m_hasUnisolatedCompositedBlendingDescendants;
#endif
#ifndef NDEBUG
int m_depth;
#endif
@@ -1099,6 +1105,9 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor
// ancestor with m_subtreeIsCompositing set to false.
CompositingState childState(compositingState);
childState.m_subtreeIsCompositing = false;
#if ENABLE(CSS_COMPOSITING)
childState.m_hasUnisolatedCompositedBlendingDescendants = false;
#endif

bool willBeComposited = needsToBeComposited(layer);
if (willBeComposited) {
@@ -1172,10 +1181,6 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor
willBeComposited = true;
}

// If the layer composited for other reasons than blending, it is no longer needed to keep track of whether a child was blended.
if (compositingState.m_subtreeHasBlending && !layer.hasBlendMode())
compositingState.m_subtreeHasBlending = false;

ASSERT(willBeComposited == needsToBeComposited(layer));

// All layers (even ones that aren't being composited) need to get added to
@@ -1184,13 +1189,13 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor
if (overlapMap && childState.m_compositingAncestor && !childState.m_compositingAncestor->isRootLayer())
addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds);

if (childState.m_subtreeHasBlending || layer.hasBlendMode())
compositingState.m_subtreeHasBlending = true;

#if ENABLE(CSS_COMPOSITING)
layer.setHasUnisolatedCompositedBlendingDescendants(childState.m_hasUnisolatedCompositedBlendingDescendants);
#endif
// Now check for reasons to become composited that depend on the state of descendant layers.
RenderLayer::IndirectCompositingReason indirectCompositingReason;
if (!willBeComposited && canBeComposited(layer)
&& requiresCompositingForIndirectReason(layer.renderer(), childState.m_subtreeIsCompositing, compositingState.m_subtreeHasBlending, anyDescendantHas3DTransform, indirectCompositingReason)) {
&& requiresCompositingForIndirectReason(layer.renderer(), childState.m_subtreeIsCompositing, anyDescendantHas3DTransform, indirectCompositingReason)) {
layer.setIndirectCompositingReason(indirectCompositingReason);
childState.m_compositingAncestor = &layer;
if (overlapMap) {
@@ -1234,6 +1239,12 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor
}
}

#if ENABLE(CSS_COMPOSITING)
if ((willBeComposited && layer.hasBlendMode())
|| (layer.hasUnisolatedCompositedBlendingDescendants() && !layer.isolatesCompositedBlending()))
compositingState.m_hasUnisolatedCompositedBlendingDescendants = true;
#endif

if (overlapMap && childState.m_compositingAncestor == &layer && !layer.isRootLayer())
overlapMap->popCompositingContainer();

@@ -2114,8 +2125,10 @@ CompositingReasons RenderLayerCompositor::reasonsForCompositing(const RenderLaye
if (renderer->hasFilter())
reasons |= CompositingReasonFilterWithCompositedDescendants;

if (renderer->hasBlendMode())
#if ENABLE(CSS_COMPOSITING)
if (layer.isolatesCompositedBlending())
reasons |= CompositingReasonBlendingWithCompositedDescendants;
#endif

} else if (renderer->layer()->indirectCompositingReason() == RenderLayer::IndirectCompositingForPerspective)
reasons |= CompositingReasonPerspective;
@@ -2379,13 +2392,13 @@ bool RenderLayerCompositor::requiresCompositingForAnimation(RenderLayerModelObje
|| animController.isRunningAnimationOnRenderer(&renderer, CSSPropertyWebkitTransform, activeAnimationState);
}

bool RenderLayerCompositor::requiresCompositingForIndirectReason(RenderLayerModelObject& renderer, bool hasCompositedDescendants, bool hasBlendedDescendants, bool has3DTransformedDescendants, RenderLayer::IndirectCompositingReason& reason) const
bool RenderLayerCompositor::requiresCompositingForIndirectReason(RenderLayerModelObject& renderer, bool hasCompositedDescendants, bool has3DTransformedDescendants, RenderLayer::IndirectCompositingReason& reason) const
{
RenderLayer& layer = *toRenderBoxModelObject(renderer).layer();

// When a layer has composited descendants, some effects, like 2d transforms, filters, masks etc must be implemented
// via compositing so that they also apply to those composited descendants.
if (hasCompositedDescendants && (hasBlendedDescendants || layer.transform() || renderer.createsGroup() || renderer.hasReflection() || renderer.isRenderNamedFlowFragmentContainer())) {
if (hasCompositedDescendants && (layer.isolatesCompositedBlending() || layer.transform() || renderer.createsGroup() || renderer.hasReflection() || renderer.isRenderNamedFlowFragmentContainer())) {
reason = RenderLayer::IndirectCompositingForGraphicalEffect;
return true;
}
@@ -396,7 +396,7 @@ class RenderLayerCompositor : public GraphicsLayerClient, public GraphicsLayerUp
bool requiresCompositingForScrollableFrame() const;
bool requiresCompositingForPosition(RenderLayerModelObject&, const RenderLayer&, RenderLayer::ViewportConstrainedNotCompositedReason* = 0) const;
bool requiresCompositingForOverflowScrolling(const RenderLayer&) const;
bool requiresCompositingForIndirectReason(RenderLayerModelObject&, bool hasCompositedDescendants, bool hasBlendedDescendants, bool has3DTransformedDescendants, RenderLayer::IndirectCompositingReason&) const;
bool requiresCompositingForIndirectReason(RenderLayerModelObject&, bool hasCompositedDescendants, bool has3DTransformedDescendants, RenderLayer::IndirectCompositingReason&) const;

#if PLATFORM(IOS)
bool requiresCompositingForScrolling(const RenderLayer&) const;

0 comments on commit 0c2ccf6

Please sign in to comment.