Commit 58c40a11 authored by Xianzhu Wang's avatar Xianzhu Wang Committed by Commit Bot

Fix mask-based clip-path with backdrop filter

Cc requires additional bookkeeping for the case, including setting the
mask layer as a backdrop mask layer, etc.

Also let CompositeAfterPaint composite the backdrop mask layer which is
also required by cc.

Bug: 1144520
Change-Id: Id9be79d398c1c4b41aa97a7c8c3e23546ce87365
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2518440Reviewed-by: default avatarMason Freed <masonfreed@chromium.org>
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#824041}
parent 5a53f6b1
...@@ -148,7 +148,8 @@ class CORE_EXPORT ObjectPaintProperties { ...@@ -148,7 +148,8 @@ class CORE_EXPORT ObjectPaintProperties {
// | +-[ ClipPathMask ] // | +-[ ClipPathMask ]
// | Isolated group for painting the mask-based CSS clip-path. This node // | Isolated group for painting the mask-based CSS clip-path. This node
// | will have SkBlendMode::kDstIn and shall paint last, i.e. after // | will have SkBlendMode::kDstIn and shall paint last, i.e. after
// | clipped contents. // | clipped contents. If there is no Mask node, then this node is a
// | direct child of the Effect node.
// +-[ VerticalScrollbarEffect / HorizontalScrollbarEffect ] // +-[ VerticalScrollbarEffect / HorizontalScrollbarEffect ]
// Overlay Scrollbars on Aura and Android need effect node for fade // Overlay Scrollbars on Aura and Android need effect node for fade
// animation. // animation.
......
...@@ -1228,6 +1228,12 @@ void FragmentPaintPropertyTreeBuilder::UpdateEffect() { ...@@ -1228,6 +1228,12 @@ void FragmentPaintPropertyTreeBuilder::UpdateEffect() {
} }
OnUpdate(effective_change_type); OnUpdate(effective_change_type);
auto mask_direct_compositing_reasons =
full_context_.direct_compositing_reasons &
CompositingReason::kDirectReasonsForBackdropFilter
? CompositingReason::kBackdropFilterMask
: CompositingReason::kNone;
if (mask_clip) { if (mask_clip) {
EffectPaintPropertyNode::State mask_state; EffectPaintPropertyNode::State mask_state;
mask_state.local_transform_space = context_.current.transform; mask_state.local_transform_space = context_.current.transform;
...@@ -1235,6 +1241,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateEffect() { ...@@ -1235,6 +1241,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateEffect() {
mask_state.color_filter = CSSMaskPainter::MaskColorFilter(object_); mask_state.color_filter = CSSMaskPainter::MaskColorFilter(object_);
mask_state.blend_mode = SkBlendMode::kDstIn; mask_state.blend_mode = SkBlendMode::kDstIn;
mask_state.compositor_element_id = mask_compositor_element_id; mask_state.compositor_element_id = mask_compositor_element_id;
mask_state.direct_compositing_reasons = mask_direct_compositing_reasons;
OnUpdate(properties_->UpdateMask(*properties_->Effect(), OnUpdate(properties_->UpdateMask(*properties_->Effect(),
std::move(mask_state))); std::move(mask_state)));
} else { } else {
...@@ -1248,6 +1255,10 @@ void FragmentPaintPropertyTreeBuilder::UpdateEffect() { ...@@ -1248,6 +1255,10 @@ void FragmentPaintPropertyTreeBuilder::UpdateEffect() {
clip_path_state.blend_mode = SkBlendMode::kDstIn; clip_path_state.blend_mode = SkBlendMode::kDstIn;
clip_path_state.compositor_element_id = GetCompositorElementId( clip_path_state.compositor_element_id = GetCompositorElementId(
CompositorElementIdNamespace::kEffectClipPath); CompositorElementIdNamespace::kEffectClipPath);
if (!mask_clip) {
clip_path_state.direct_compositing_reasons =
mask_direct_compositing_reasons;
}
OnUpdate(properties_->UpdateClipPathMask( OnUpdate(properties_->UpdateClipPathMask(
properties_->Mask() ? *properties_->Mask() : *properties_->Effect(), properties_->Mask() ? *properties_->Mask() : *properties_->Effect(),
std::move(clip_path_state))); std::move(clip_path_state)));
......
...@@ -1178,10 +1178,27 @@ void PaintArtifactCompositor::Update( ...@@ -1178,10 +1178,27 @@ void PaintArtifactCompositor::Update(
int transform_id = int transform_id =
property_tree_manager.EnsureCompositorTransformNode(transform); property_tree_manager.EnsureCompositorTransformNode(transform);
int clip_id = property_tree_manager.EnsureCompositorClipNode(clip); int clip_id = property_tree_manager.EnsureCompositorClipNode(clip);
int effect_id = property_tree_manager.SwitchToEffectNodeWithSynthesizedClip( int effect_id = property_tree_manager.SwitchToEffectNodeWithSynthesizedClip(
property_state.Effect(), clip, layer->DrawsContent()); property_state.Effect(), clip, layer->DrawsContent());
blink_effects.resize(effect_id + 1); if (blink_effects.size() <= static_cast<wtf_size_t>(effect_id))
blink_effects[effect_id] = &property_state.Effect(); blink_effects.resize(effect_id + 1);
if (!blink_effects[effect_id]) {
blink_effects[effect_id] = &property_state.Effect();
// We need additional bookkeeping for backdrop-filter mask.
if (property_state.Effect().RequiresCompositingForBackdropFilterMask()) {
static_cast<cc::PictureLayer*>(layer.get())
->SetIsBackdropFilterMask(true);
layer->SetElementId(property_state.Effect().GetCompositorElementId());
auto& effect_tree = host->property_trees()->effect_tree;
auto* cc_node = effect_tree.Node(effect_id);
effect_tree.Node(cc_node->parent_id)->backdrop_mask_element_id =
property_state.Effect().GetCompositorElementId();
}
} else {
DCHECK_EQ(blink_effects[effect_id], &property_state.Effect());
}
// The compositor scroll node is not directly stored in the property tree // The compositor scroll node is not directly stored in the property tree
// state but can be created via the scroll offset translation node. // state but can be created via the scroll offset translation node.
const auto& scroll_translation = const auto& scroll_translation =
......
...@@ -63,6 +63,8 @@ constexpr CompositingReasonStringMap kCompositingReasonsStringMap[] = { ...@@ -63,6 +63,8 @@ constexpr CompositingReasonStringMap kCompositingReasonsStringMap[] = {
"Has a will-change compositing hint other than transform and opacity"}, "Has a will-change compositing hint other than transform and opacity"},
{CompositingReason::kBackdropFilter, "backdropFilter", {CompositingReason::kBackdropFilter, "backdropFilter",
"Has a backdrop filter"}, "Has a backdrop filter"},
{CompositingReason::kBackdropFilterMask, "backdropFilterMask",
"Is a mask for backdrop filter"},
{CompositingReason::kRootScroller, "rootScroller", {CompositingReason::kRootScroller, "rootScroller",
"Is the document.rootScroller"}, "Is the document.rootScroller"},
{CompositingReason::kAssumedOverlap, "assumedOverlap", {CompositingReason::kAssumedOverlap, "assumedOverlap",
......
...@@ -44,6 +44,7 @@ using CompositingReasons = uint64_t; ...@@ -44,6 +44,7 @@ using CompositingReasons = uint64_t;
are set. */ \ are set. */ \
V(WillChangeOther) \ V(WillChangeOther) \
V(BackdropFilter) \ V(BackdropFilter) \
V(BackdropFilterMask) \
V(RootScroller) \ V(RootScroller) \
V(XrOverlay) \ V(XrOverlay) \
V(Viewport) \ V(Viewport) \
...@@ -170,6 +171,9 @@ class PLATFORM_EXPORT CompositingReason { ...@@ -170,6 +171,9 @@ class PLATFORM_EXPORT CompositingReason {
kWillChangeBackdropFilter | kActiveBackdropFilterAnimation, kWillChangeBackdropFilter | kActiveBackdropFilterAnimation,
kDirectReasonsForFilterProperty = kDirectReasonsForFilterProperty =
kActiveFilterAnimation | kWillChangeFilter, kActiveFilterAnimation | kWillChangeFilter,
kDirectReasonsForBackdropFilter = kBackdropFilter |
kActiveBackdropFilterAnimation |
kWillChangeBackdropFilter,
}; };
}; };
......
...@@ -231,13 +231,17 @@ class PLATFORM_EXPORT EffectPaintPropertyNode ...@@ -231,13 +231,17 @@ class PLATFORM_EXPORT EffectPaintPropertyNode
FloatRect MapRect(const FloatRect& input_rect) const; FloatRect MapRect(const FloatRect& input_rect) const;
bool HasDirectCompositingReasons() const { bool HasDirectCompositingReasons() const {
return DirectCompositingReasons() != CompositingReason::kNone; return state_.direct_compositing_reasons != CompositingReason::kNone;
}
bool RequiresCompositingForBackdropFilterMask() const {
return state_.direct_compositing_reasons &
CompositingReason::kBackdropFilterMask;
} }
// TODO(crbug.com/900241): Use HaveActiveXXXAnimation() instead of this // TODO(crbug.com/900241): Use HaveActiveXXXAnimation() instead of this
// function when we can track animations for each property type. // function when we can track animations for each property type.
bool RequiresCompositingForAnimation() const { bool RequiresCompositingForAnimation() const {
return DirectCompositingReasons() & return state_.direct_compositing_reasons &
CompositingReason::kComboActiveAnimation; CompositingReason::kComboActiveAnimation;
} }
bool HasActiveOpacityAnimation() const { bool HasActiveOpacityAnimation() const {
...@@ -270,7 +274,7 @@ class PLATFORM_EXPORT EffectPaintPropertyNode ...@@ -270,7 +274,7 @@ class PLATFORM_EXPORT EffectPaintPropertyNode
} }
CompositingReasons DirectCompositingReasonsForDebugging() const { CompositingReasons DirectCompositingReasonsForDebugging() const {
return DirectCompositingReasons(); return state_.direct_compositing_reasons;
} }
const CompositorElementId& GetCompositorElementId() const { const CompositorElementId& GetCompositorElementId() const {
...@@ -286,10 +290,6 @@ class PLATFORM_EXPORT EffectPaintPropertyNode ...@@ -286,10 +290,6 @@ class PLATFORM_EXPORT EffectPaintPropertyNode
using EffectPaintPropertyNodeOrAlias::SetParent; using EffectPaintPropertyNodeOrAlias::SetParent;
CompositingReasons DirectCompositingReasons() const {
return state_.direct_compositing_reasons;
}
State state_; State state_;
}; };
......
<!doctype html>
<meta name="flags" content="ahem">
<link rel="stylesheet" href="/fonts/ahem.css" />
<style>
#svgText {
font: 100px/1 Ahem;
}
</style>
<svg width="500" height="300">
<text id="svgText" x="10" y="100">Text</text>
</svg>
<!doctype html>
<link rel="help" href="http://www.w3.org/TR/css-masking-1/#the-clip-path">
<link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty">
<link rel="match" href="clip-path-svg-text-backdrop-filter-ref.html">
<meta name="flags" content="ahem">
<link rel="stylesheet" href="/fonts/ahem.css" />
<style>
.masked {
width: 500px;
height: 300px;
clip-path: url(#svgPath);
backdrop-filter: invert(100%);
background: transparent;
}
#svgText {
font: 100px/1 Ahem;
}
</style>
<div class="masked"></div>
<svg>
<clipPath id="svgPath">
<text id="svgText" x="10" y="100">Text</text>
</clipPath>
</svg>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment