Skip to content

Commit

Permalink
Use compositedDraw when it's needed due to the selected blend mode an…
Browse files Browse the repository at this point in the history
…d use of shadows.

When setting a shadow using properties in canvas, the spec specifies that the shadow has to be composited with the shape that is being painted (see https://html.spec.whatwg.org/#drawing-model). This means that for certain blend modes, CompositedDraw must be used when a shadow is set via properties.

The setting of the blend mode was missing before the saveLayer call in CompositedDraw, it has been added. Additionally, a ShouldUseCompositedDraw method has been created to contain the logic of the decision to use CompositedDraw or not in DrawInternal, in order to make the DCHECKs around this conditional clearer, and to facilitate the maintenance of the code as a whole. This new method includes the situations in which, when certain blend modes are used and shadows are set, CompositedDraw must be used to include the compositing operation between the shadow and the shape being painted.

The issue this CL fixes can be seen in the change on the expected outcome for the canvas-composite-video-shadow test. The other updated tests are just a rebaseline due to minor differences.

Bug: 1348573
Change-Id: Ic5d861bb56124b30db2198d2ef43c4daa14a2ee6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3817461
Reviewed-by: Juanmi Huertas <juanmihd@chromium.org>
Reviewed-by: Justin Novosad <junov@chromium.org>
Commit-Queue: Andres Perez <andresrperez@google.com>
Cr-Commit-Position: refs/heads/main@{#1033489}
  • Loading branch information
AndresRPerez12 authored and Chromium LUCI CQ committed Aug 10, 2022
1 parent 582b21b commit 54fe105
Show file tree
Hide file tree
Showing 41 changed files with 49 additions and 7 deletions.
Expand Up @@ -523,6 +523,49 @@ class MODULES_EXPORT BaseRenderingContext2D : public CanvasPath {
image_type == CanvasRenderingContext2DState::kNonOpaqueImage;
}

// Blend modes that require compositing with layers when shadows are drawn.
ALWAYS_INLINE bool BlendModeRequiresLayersForShadows(SkBlendMode blendMode) {
return blendMode == SkBlendMode::kDstOver ||
blendMode == SkBlendMode::kMultiply ||
blendMode == SkBlendMode::kOverlay ||
blendMode == SkBlendMode::kDarken ||
blendMode == SkBlendMode::kLighten ||
blendMode == SkBlendMode::kColorDodge ||
blendMode == SkBlendMode::kColorBurn ||
blendMode == SkBlendMode::kHardLight ||
blendMode == SkBlendMode::kSoftLight ||
blendMode == SkBlendMode::kDifference ||
blendMode == SkBlendMode::kExclusion ||
blendMode == SkBlendMode::kHue ||
blendMode == SkBlendMode::kSaturation ||
blendMode == SkBlendMode::kColor ||
blendMode == SkBlendMode::kLuminosity;
}

ALWAYS_INLINE bool BlendModeRequiresCompositedDraw(SkBlendMode blendMode) {
// Blend modes that require CompositedDraw in every case.
if (IsFullCanvasCompositeMode(blendMode))
return true;
const CanvasRenderingContext2DState& state = GetState();
// Blend modes that require CompositedDraw if shadows are drawn.
return state.ShouldDrawShadows() &&
BlendModeRequiresLayersForShadows(blendMode);
}

ALWAYS_INLINE bool ShouldUseCompositedDraw(
CanvasRenderingContext2DState::PaintType paint_type,
CanvasRenderingContext2DState::ImageType image_type) {
const CanvasRenderingContext2DState& state = GetState();
if (BlendModeRequiresCompositedDraw(state.GlobalComposite()))
return true;
if (StateHasFilter())
return true;
if (state.ShouldDrawShadows() &&
ShouldUseDropShadowPaintFilter(paint_type, image_type))
return true;
return false;
}

template <OverdrawOp CurrentOverdrawOp,
typename DrawFunc,
typename DrawCoversClipBoundsFunc>
Expand Down Expand Up @@ -653,9 +696,7 @@ void BaseRenderingContext2D::DrawInternal(
CanvasPerformanceMonitor::DrawType draw_type) {
const CanvasRenderingContext2DState& state = GetState();
SkBlendMode global_composite = state.GlobalComposite();
if (IsFullCanvasCompositeMode(global_composite) || StateHasFilter() ||
(state.ShouldDrawShadows() &&
ShouldUseDropShadowPaintFilter(paint_type, image_type))) {
if (ShouldUseCompositedDraw(paint_type, image_type)) {
CompositedDraw(draw_func, GetPaintCanvasForDraw(clip_bounds, draw_type),
paint_type, image_type);
} else if (global_composite == SkBlendMode::kSrc) {
Expand Down Expand Up @@ -742,9 +783,7 @@ void BaseRenderingContext2D::CompositedDraw(

sk_sp<PaintFilter> canvas_filter = StateGetFilter();
const CanvasRenderingContext2DState& state = GetState();
DCHECK(IsFullCanvasCompositeMode(state.GlobalComposite()) || canvas_filter ||
(state.ShouldDrawShadows() &&
ShouldUseDropShadowPaintFilter(paint_type, image_type)));
DCHECK(ShouldUseCompositedDraw(paint_type, image_type));
SkM44 ctm = c->getLocalToDevice();
c->setMatrix(SkM44());
cc::PaintFlags composite_flags;
Expand All @@ -768,11 +807,14 @@ void BaseRenderingContext2D::CompositedDraw(
shadow_flags.setAlpha(255);
// Saving the shadow layer before setting the matrix, so the shadow offset
// does not get modified by the transformation matrix
shadow_flags.setBlendMode(state.GlobalComposite());
c->saveLayer(nullptr, &shadow_flags);
foreground_flags.setBlendMode(SkBlendMode::kSrcOver);
c->setMatrix(ctm);
draw_func(c, &foreground_flags);
} else {
DCHECK(IsFullCanvasCompositeMode(state.GlobalComposite()));
DCHECK(IsFullCanvasCompositeMode(state.GlobalComposite()) ||
BlendModeRequiresCompositedDraw(state.GlobalComposite()));
c->saveLayer(nullptr, &composite_flags);
shadow_flags.setBlendMode(SkBlendMode::kSrcOver);
c->setMatrix(ctm);
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 54fe105

Please sign in to comment.