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

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: Rebase Created 7 years, 2 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
« no previous file with comments | « Source/core/rendering/RenderLayer.h ('k') | Source/core/rendering/RenderLayerCompositor.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/rendering/RenderLayer.cpp
diff --git a/Source/core/rendering/RenderLayer.cpp b/Source/core/rendering/RenderLayer.cpp
index 3db81e33e92bb8b428490476965e92164f5d84e0..1feec46b424d2956b68ab716aee7ee2903ef5b06 100644
--- a/Source/core/rendering/RenderLayer.cpp
+++ b/Source/core/rendering/RenderLayer.cpp
@@ -121,6 +121,8 @@ RenderLayer::RenderLayer(RenderLayerModelObject* renderer)
, m_canBePromotedToStackingContainerDirty(true)
, m_isRootLayer(renderer->isRenderView())
, m_usedTransparency(false)
+ , m_childLayerHasBlendMode(false)
+ , m_childLayerHasBlendModeStatusDirty(false)
, m_paintingInsideReflection(false)
, m_visibleContentStatusDirty(true)
, m_hasVisibleContent(false)
@@ -725,9 +727,15 @@ void RenderLayer::updateBlendMode()
if (!RuntimeEnabledFeatures::cssCompositingEnabled())
return;
+ bool hadBlendMode = m_blendMode != BlendModeNormal;
BlendMode newBlendMode = renderer()->style()->blendMode();
if (newBlendMode != m_blendMode) {
m_blendMode = newBlendMode;
+
+ // Only update the flag if a blend mode is set or unset.
+ if (!hadBlendMode || !hasBlendMode())
+ dirtyAncestorChainBlendedDescendantStatus();
+
if (compositedLayerMapping())
compositedLayerMapping()->setBlendMode(newBlendMode);
}
@@ -960,6 +968,33 @@ void RenderLayer::setAncestorChainHasVisibleDescendant()
}
}
+void RenderLayer::dirtyAncestorChainBlendedDescendantStatus()
+{
+ for (RenderLayer* layer = this; layer; layer = layer->parent()) {
+ if (layer->m_childLayerHasBlendModeStatusDirty)
+ break;
+
+ layer->m_childLayerHasBlendModeStatusDirty = true;
+
+ if (layer->isStackingContext())
+ break;
+ }
+}
+
+void RenderLayer::setAncestorChainBlendedDescendant()
+{
+ for (RenderLayer* layer = this; layer; layer = layer->parent()) {
+ if (!layer->m_childLayerHasBlendModeStatusDirty && layer->childLayerHasBlendMode())
+ break;
+
+ layer->m_childLayerHasBlendMode = true;
+ layer->m_childLayerHasBlendModeStatusDirty = false;
+
+ if (layer->isStackingContext())
+ break;
+ }
+}
+
void RenderLayer::updateHasUnclippedDescendant()
{
TRACE_EVENT0("blink_rendering", "RenderLayer::updateHasUnclippedDescendant");
@@ -1019,6 +1054,20 @@ void RenderLayer::updateDescendantDependentFlags()
m_hasOutOfFlowPositionedDescendantDirty = false;
}
+ if (m_childLayerHasBlendModeStatusDirty) {
+ for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
+ if (!child->isStackingContext())
+ child->updateDescendantDependentFlags();
+
+ bool childLayerHasBlendMode = child->hasBlendMode() || (child->m_childLayerHasBlendMode && !child->isStackingContext());
+ m_childLayerHasBlendMode |= childLayerHasBlendMode;
+
+ if (m_childLayerHasBlendMode)
+ break;
+ }
+ m_childLayerHasBlendModeStatusDirty = false;
+ }
+
if (m_visibleContentStatusDirty) {
if (renderer()->style()->visibility() == VISIBLE)
m_hasVisibleContent = true;
@@ -1547,18 +1596,22 @@ 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))
+ bool createTransparencyLayerForBlendMode = isStackingContext() && m_childLayerHasBlendMode;
+ if (context->paintingDisabled() || ((paintsWithTransparency(paintBehavior) || hasBlendMode() || createTransparencyLayerForBlendMode) && m_usedTransparency))
return;
RenderLayer* ancestor = transparentPaintingAncestor();
if (ancestor)
ancestor->beginTransparencyLayers(context, rootLayer, paintDirtyRect, paintBehavior);
- if (paintsWithTransparency(paintBehavior)) {
+ if (paintsWithTransparency(paintBehavior) || hasBlendMode() || createTransparencyLayerForBlendMode) {
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));
@@ -1613,6 +1666,9 @@ void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild)
if (child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendant())
setAncestorChainHasSelfPaintingLayerDescendant();
+ if (child->hasBlendMode() || child->childLayerHasBlendMode())
+ setAncestorChainBlendedDescendant();
+
if (subtreeContainsOutOfFlowPositionedLayer(child)) {
// Now that the out of flow positioned descendant is in the tree, we
// need to tell the compositor to reevaluate the compositing
@@ -1671,6 +1727,9 @@ RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
if (oldChild->m_hasVisibleContent || oldChild->m_hasVisibleDescendant)
dirtyAncestorChainVisibleDescendantStatus();
+ if (oldChild->hasBlendMode() || oldChild->childLayerHasBlendMode())
+ dirtyAncestorChainBlendedDescendantStatus();
+
if (oldChild->isSelfPaintingLayer() || oldChild->hasSelfPaintingLayerDescendant())
dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
@@ -2689,6 +2748,12 @@ void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPainti
}
}
+ // Blending operations must be performed only with the nearest ancestor stacking context.
+ bool createTransparencyLayerForBlendMode = isStackingContext() && m_childLayerHasBlendMode;
+
+ if (createTransparencyLayerForBlendMode)
+ beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.paintBehavior);
+
LayerPaintingInfo localPaintingInfo(paintingInfo);
FilterEffectRendererHelper filterPainter(filterRenderer() && paintsWithFilters());
if (filterPainter.haveFilterEffect() && !context->paintingDisabled()) {
@@ -2810,7 +2875,7 @@ void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPainti
}
// End our transparency layer
- if (haveTransparency && m_usedTransparency && !m_paintingInsideReflection) {
+ if ((haveTransparency || hasBlendMode() || createTransparencyLayerForBlendMode) && m_usedTransparency && !m_paintingInsideReflection) {
context->endLayer();
context->restore();
m_usedTransparency = false;
@@ -2995,7 +3060,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) {
@@ -3019,7 +3084,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()) {
@@ -5074,12 +5139,12 @@ void RenderLayer::styleChanged(StyleDifference, const RenderStyle* oldStyle)
updateReflectionStyle();
}
- updateDescendantDependentFlags();
- updateTransform();
-
if (RuntimeEnabledFeatures::cssCompositingEnabled())
updateBlendMode();
+ updateDescendantDependentFlags();
+ updateTransform();
+
bool didPaintWithFilters = false;
if (paintsWithFilters())
« no previous file with comments | « Source/core/rendering/RenderLayer.h ('k') | Source/core/rendering/RenderLayerCompositor.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698