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

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: 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 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()) {

Powered by Google App Engine
This is Rietveld 408576698