Index: Source/core/rendering/RenderLayer.cpp |
diff --git a/Source/core/rendering/RenderLayer.cpp b/Source/core/rendering/RenderLayer.cpp |
index 2e5e260ea0e15f0a2537a147ad40e33b2640eb5e..c6fb051e6dd4ed79577a733024180120687823fc 100644 |
--- a/Source/core/rendering/RenderLayer.cpp |
+++ b/Source/core/rendering/RenderLayer.cpp |
@@ -133,6 +133,7 @@ RenderLayer::RenderLayer(RenderLayerModelObject* renderer) |
, m_canBePromotedToStackingContainerDirty(true) |
, m_isRootLayer(renderer->isRenderView()) |
, m_usedTransparency(false) |
+ , m_isolateForDescendantBlendMode(false) |
, m_paintingInsideReflection(false) |
, m_repaintStatus(NeedsNormalRepaint) |
, m_visibleContentStatusDirty(true) |
@@ -409,6 +410,22 @@ LayoutRect RenderLayer::repaintRectIncludingNonCompositingDescendants() const |
return repaintRect; |
} |
+bool RenderLayer::hasNonAcceleratedBlendedChildInCurrentStackingContext() const |
+{ |
+ if (isComposited() && !backing()->paintsIntoCompositedAncestor()) |
+ return false; |
+ |
+ for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) { |
+ if (child->hasBlendMode()) |
+ return true; |
+ |
+ if (!child->isStackingContext() && child->hasNonAcceleratedBlendedChildInCurrentStackingContext()) |
Julien - ping for review
2013/09/23 18:55:38
Doesn't this means we will walk the whole subtree
mitica
2013/09/23 20:12:20
If, for each time a blend mode would be set on a R
Julien - ping for review
2013/09/23 22:15:09
Yes and this is a fairly common paradigm in Render
|
+ return true; |
+ } |
+ |
+ return false; |
+} |
+ |
void RenderLayer::setAncestorChainHasSelfPaintingLayerDescendant() |
{ |
for (RenderLayer* layer = this; layer; layer = layer->parent()) { |
@@ -1697,18 +1714,21 @@ LayoutRect RenderLayer::paintingExtent(const RenderLayer* rootLayer, const Layou |
void RenderLayer::beginTransparencyLayers(GraphicsContext* context, const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, PaintBehavior paintBehavior) |
{ |
- if (context->paintingDisabled() || (paintsWithTransparency(paintBehavior) && m_usedTransparency)) |
+ if (context->paintingDisabled() || ((paintsWithTransparency(paintBehavior) || hasBlendMode() || m_isolateForDescendantBlendMode) && m_usedTransparency)) |
return; |
RenderLayer* ancestor = transparentPaintingAncestor(); |
if (ancestor) |
ancestor->beginTransparencyLayers(context, rootLayer, paintDirtyRect, paintBehavior); |
- if (paintsWithTransparency(paintBehavior)) { |
+ if (paintsWithTransparency(paintBehavior) || hasBlendMode() || m_isolateForDescendantBlendMode) { |
m_usedTransparency = true; |
context->save(); |
LayoutRect clipRect = paintingExtent(rootLayer, paintDirtyRect, paintBehavior); |
context->clip(clipRect); |
+ if (hasBlendMode()) |
+ context->setCompositeOperation(context->compositeOperation(), m_blendMode); |
+ |
context->beginTransparencyLayer(renderer()->opacity()); |
#ifdef REVEAL_TRANSPARENCY_LAYERS |
context->setFillColor(Color(0.0f, 0.0f, 0.5f, 0.2f)); |
@@ -3272,6 +3292,11 @@ void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPainti |
} |
} |
+ // Blending operations must be performed only with the nearest ancestor stacking context. |
+ m_isolateForDescendantBlendMode = isStackingContext() && hasNonAcceleratedBlendedChildInCurrentStackingContext(); |
Julien - ping for review
2013/09/23 18:55:38
Trying to understand the need to have this stored
mitica
2013/09/23 20:12:20
This member is computed using the recursive layer
Julien - ping for review
2013/09/23 22:15:09
That's not what I meant: it is possible for this c
|
+ if (m_isolateForDescendantBlendMode) |
+ beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.paintBehavior); |
+ |
LayerPaintingInfo localPaintingInfo(paintingInfo); |
FilterEffectRendererHelper filterPainter(filterRenderer() && paintsWithFilters()); |
if (filterPainter.haveFilterEffect() && !context->paintingDisabled()) { |
@@ -3387,10 +3412,11 @@ void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPainti |
paintMaskForFragments(layerFragments, context, localPaintingInfo, paintingRootForRenderer); |
// End our transparency layer |
- if (haveTransparency && m_usedTransparency && !m_paintingInsideReflection) { |
+ if ((haveTransparency || hasBlendMode() || m_isolateForDescendantBlendMode) && m_usedTransparency && !m_paintingInsideReflection) { |
context->endLayer(); |
context->restore(); |
m_usedTransparency = false; |
+ m_isolateForDescendantBlendMode = false; |
} |
if (resourceClipper) |
@@ -3572,7 +3598,7 @@ void RenderLayer::paintBackgroundForFragments(const LayerFragments& layerFragmen |
continue; |
// Begin transparency layers lazily now that we know we have to paint something. |
- if (haveTransparency) |
+ if (haveTransparency || hasBlendMode()) |
beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.rootLayer, transparencyPaintDirtyRect, localPaintingInfo.paintBehavior); |
if (localPaintingInfo.clipToDirtyRect) { |
@@ -3596,7 +3622,7 @@ void RenderLayer::paintForegroundForFragments(const LayerFragments& layerFragmen |
RenderObject* paintingRootForRenderer, bool selectionOnly, bool forceBlackText) |
{ |
// Begin transparency if we have something to paint. |
- if (haveTransparency) { |
+ if (haveTransparency || hasBlendMode()) { |
for (size_t i = 0; i < layerFragments.size(); ++i) { |
const LayerFragment& fragment = layerFragments.at(i); |
if (fragment.shouldPaintContent && !fragment.foregroundRect.isEmpty()) { |