Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1710)

Unified Diff: Source/core/rendering/RenderLayer.cpp

Issue 23503046: [CSS Blending] Implement mix-blend-mode in software. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Completely remove CompositingReasonBlending Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/rendering/RenderLayer.cpp
diff --git a/Source/core/rendering/RenderLayer.cpp b/Source/core/rendering/RenderLayer.cpp
index 318f91c9622a6b708dbd4aa8689f06bb1b7e8c77..133ee3e4e80711c82251c951a572fffc766b7422 100644
--- a/Source/core/rendering/RenderLayer.cpp
+++ b/Source/core/rendering/RenderLayer.cpp
@@ -138,6 +138,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)
@@ -418,6 +419,24 @@ LayoutRect RenderLayer::repaintRectIncludingNonCompositingDescendants() const
return repaintRect;
}
+bool RenderLayer::hasNonAcceleratedBlendedChildInCurrentStackingContext() const
+{
+ if (isComposited())
shawnsingh 2013/09/19 11:05:56 So I've just recently debugged two issues about th
+ return false;
+
+ for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
+ bool childIsBlended = child->hasBlendMode();
+
+ if (!childIsBlended && child->isStackingContext())
shawnsingh 2013/09/19 11:05:56 Yeah this is much nicer - but I still think we can
mitica 2013/09/19 11:49:00 Indeed, that looks better, I'll change the method
+ continue;
+
+ if (childIsBlended || child->hasNonAcceleratedBlendedChildInCurrentStackingContext())
+ return true;
+ }
+
+ return false;
+}
+
void RenderLayer::setAncestorChainHasSelfPaintingLayerDescendant()
{
for (RenderLayer* layer = this; layer; layer = layer->parent()) {
@@ -1702,18 +1721,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_isolateLayerFromBlendedContent) && m_usedTransparency))
return;
RenderLayer* ancestor = transparentPaintingAncestor();
if (ancestor)
ancestor->beginTransparencyLayers(context, rootLayer, paintDirtyRect, paintBehavior);
- if (paintsWithTransparency(paintBehavior)) {
+ if (paintsWithTransparency(paintBehavior) || hasBlendMode() || m_isolateLayerFromBlendedContent) {
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));
@@ -3638,6 +3660,11 @@ void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPainti
}
}
+ // Blending operations must be performed only with the nearest ancestor stacking context.
+ m_isolateLayerFromBlendedContent = isStackingContext() && hasNonAcceleratedBlendedChildInCurrentStackingContext();
+ if (m_isolateLayerFromBlendedContent)
+ beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.paintBehavior);
+
LayerPaintingInfo localPaintingInfo(paintingInfo);
FilterEffectRendererHelper filterPainter(filterRenderer() && paintsWithFilters());
if (filterPainter.haveFilterEffect() && !context->paintingDisabled()) {
@@ -3753,10 +3780,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_isolateLayerFromBlendedContent) && m_usedTransparency && !m_paintingInsideReflection) {
context->endLayer();
context->restore();
m_usedTransparency = false;
+ m_isolateLayerFromBlendedContent = false;
}
if (resourceClipper)
@@ -3938,7 +3966,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) {
@@ -3962,7 +3990,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()) {

Powered by Google App Engine
This is Rietveld 408576698