Chromium Code Reviews| Index: Source/core/rendering/RenderLayer.cpp |
| diff --git a/Source/core/rendering/RenderLayer.cpp b/Source/core/rendering/RenderLayer.cpp |
| index 957df9c1bf388fec56c0767215b5535b1c098bbc..fe17f1192a066547010534c9792ab32c31e19c55 100644 |
| --- a/Source/core/rendering/RenderLayer.cpp |
| +++ b/Source/core/rendering/RenderLayer.cpp |
| @@ -135,6 +135,7 @@ RenderLayer::RenderLayer(RenderLayerModelObject* renderer) |
| , m_canBePromotedToStackingContainerDirty(true) |
| , m_isRootLayer(renderer->isRenderView()) |
| , m_usedTransparency(false) |
| + , m_isolateLayerFromBlendedContent(false) |
| , m_paintingInsideReflection(false) |
| , m_inOverflowRelayout(false) |
| , m_repaintStatus(NeedsNormalRepaint) |
| @@ -415,6 +416,25 @@ LayoutRect RenderLayer::repaintRectIncludingNonCompositingDescendants() const |
| return repaintRect; |
| } |
| +bool RenderLayer::hasNonAcceleratedBlendedChildInCurrentStackingContext() const |
| +{ |
| + for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) { |
| + if (child->isComposited()) |
| + continue; |
| + |
| + if (child->hasBlendMode()) |
| + return true; |
| + |
| + if (child->isStackingContext()) |
|
shawnsingh
2013/09/10 21:23:40
The ordering of this logic here is a little bit nu
mitica
2013/09/11 16:04:14
Sounds good, I'll rewrite this method.
|
| + continue; |
| + |
| + if (child->hasNonAcceleratedBlendedChildInCurrentStackingContext()) |
| + return true; |
| + } |
| + |
| + return false; |
| +} |
| + |
| void RenderLayer::setAncestorChainHasSelfPaintingLayerDescendant() |
| { |
| for (RenderLayer* layer = this; layer; layer = layer->parent()) { |
| @@ -1694,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_usedTransparency)) |
| return; |
| RenderLayer* ancestor = transparentPaintingAncestor(); |
| if (ancestor) |
| ancestor->beginTransparencyLayers(context, rootLayer, paintDirtyRect, paintBehavior); |
| - if (paintsWithTransparency(paintBehavior)) { |
| + if (paintsWithTransparency(paintBehavior) || hasBlendMode()) { |
| 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)); |
| @@ -3544,6 +3567,13 @@ void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPainti |
| } |
| } |
| + if (isStackingContext() && hasNonAcceleratedBlendedChildInCurrentStackingContext()) { |
| + // Blending operations must be performed only with the nearest ancestor stacking context. |
| + ASSERT(!m_isolateLayerFromBlendedContent); |
| + context->beginTransparencyLayer(renderer()->opacity()); |
|
shawnsingh
2013/09/10 21:23:40
Would it be possible to re-use the existing beginT
mitica
2013/09/11 16:04:14
I've refactored my code to use this logic, good su
|
| + m_isolateLayerFromBlendedContent = true; |
| + } |
| + |
| LayerPaintingInfo localPaintingInfo(paintingInfo); |
| FilterEffectRendererHelper filterPainter(filterRenderer() && paintsWithFilters()); |
| if (filterPainter.haveFilterEffect() && !context->paintingDisabled()) { |
| @@ -3659,12 +3689,18 @@ 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_usedTransparency && !m_paintingInsideReflection) { |
| context->endLayer(); |
| context->restore(); |
| m_usedTransparency = false; |
| } |
| + // End the transparency layer creating for isolating blended elements. |
| + if (m_isolateLayerFromBlendedContent) { |
| + context->endLayer(); |
| + m_isolateLayerFromBlendedContent = false; |
| + } |
| + |
| if (resourceClipper) |
| resourceClipper->postApplyResource(renderer(), context, ApplyToDefaultMode, 0, 0); |
| @@ -3844,7 +3880,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) { |
| @@ -3868,7 +3904,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()) { |