Fix BGPT backdrop-filter with opacity<1 parent
Previous to this CL, a layer with opacity<1 that contained a single compositing
child with backdrop-filter would not be properly rendered, due to an
optimization that removed the render surface for the opacity<1 layer. That
would cause the backdrop-filter to filter elements higher up the tree than it
should, due to the lack of isolation imposed by the opacity<1 layer. With this
CL, this situation is properly detected and a render surface is assigned to the
opacity<1 layer.
As part of this CL, backdrop-filter was moved from the Filter node to the
Effect node. This is required, because a single element with both opacity
and backdrop-filter need to be contained in the same node, so that the
render surface created for the backdrop filter also sees the opacity.
Bug: 497522, 836885
Change-Id: Ie6ad38231ddfda02fae8d574ca8f30d075c673e5
Reviewed-on: https://chromium-review.googlesource.com/c/1399467
Commit-Queue: Mason Freed <masonfreed@chromium.org>
Reviewed-by: Chris Harrelson <chrishtr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#629835}
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc
index 25bafa2..3b0833daf 100644
--- a/cc/trees/property_tree_builder.cc
+++ b/cc/trees/property_tree_builder.cc
@@ -820,7 +820,12 @@
}
// If the layer uses a CSS filter.
- if (!Filters(layer).IsEmpty() || !BackdropFilters(layer).IsEmpty()) {
+ if (!Filters(layer).IsEmpty()) {
+ return true;
+ }
+
+ // If the layer uses a CSS backdrop-filter.
+ if (!BackdropFilters(layer).IsEmpty()) {
return true;
}
diff --git a/third_party/blink/renderer/core/paint/object_paint_properties.h b/third_party/blink/renderer/core/paint/object_paint_properties.h
index 168fff1..c1a1f74 100644
--- a/third_party/blink/renderer/core/paint/object_paint_properties.h
+++ b/third_party/blink/renderer/core/paint/object_paint_properties.h
@@ -142,8 +142,8 @@
// follows:
// [ effect ]
// | Isolated group to apply various CSS effects, including opacity,
- // | mix-blend-mode, and for isolation if a mask needs to be applied or
- // | backdrop-dependent children are present.
+ // | mix-blend-mode, backdrop-filter, and for isolation if a mask needs
+ // | to be applied or backdrop-dependent children are present.
// +-[ filter ]
// | Isolated group for CSS filter.
// +-[ vertical/horizontal scrollbar effect ]
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc
index a197d63e..47822f3 100644
--- a/third_party/blink/renderer/core/paint/paint_layer.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -3262,6 +3262,7 @@
const auto& style = GetLayoutObject().StyleRef();
if (style.BackdropFilter().IsEmpty()) {
operations.Clear();
+ *backdrop_filter_bounds = gfx::RRectF();
return;
}
FloatRect reference_box = BackdropFilterReferenceBox();
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
index e0b3d16..3158aa38 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -801,6 +801,9 @@
if (blend_mode != SkBlendMode::kSrcOver)
return true;
+ if (!style.BackdropFilter().IsEmpty())
+ return true;
+
if (style.Opacity() != 1.0f || style.HasWillChangeOpacityHint())
return true;
@@ -928,6 +931,25 @@
state.blend_mode = WebCoreCompositeToSkiaComposite(
kCompositeSourceOver, style.GetBlendMode());
}
+ if (object_.IsBoxModelObject()) {
+ if (auto* layer = ToLayoutBoxModelObject(object_).Layer()) {
+ // Try to use the cached effect for backdrop-filter.
+ if (properties_->Effect()) {
+ state.backdrop_filter = properties_->Effect()->BackdropFilter();
+ state.backdrop_filter_bounds =
+ properties_->Effect()->BackdropFilterBounds();
+ }
+ // With BGPT disabled, UpdateFilterReferenceBox gets called from
+ // CompositedLayerMapping::UpdateGraphicsLayerGeometry, but only
+ // for composited layers.
+ if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() ||
+ layer->GetCompositingState() != kPaintsIntoOwnBacking) {
+ layer->UpdateFilterReferenceBox();
+ }
+ layer->UpdateCompositorFilterOperationsForBackdropFilter(
+ state.backdrop_filter, &state.backdrop_filter_bounds);
+ }
+ }
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() ||
RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
// We may begin to composite our subtree prior to an animation starts,
@@ -1025,8 +1047,7 @@
return false;
// TODO(trchen): SVG caches filters in SVGResources. Implement it.
- if (object.StyleRef().HasFilter() || object.HasReflection() ||
- object.HasBackdropFilter())
+ if (object.StyleRef().HasFilter() || object.HasReflection())
return true;
// TODO(flackr): Check for nodes for each KeyframeModel target
@@ -1056,9 +1077,6 @@
// Try to use the cached filter.
if (properties_->Filter()) {
state.filter = properties_->Filter()->Filter();
- state.backdrop_filter = properties_->Filter()->BackdropFilter();
- state.backdrop_filter_bounds =
- properties_->Filter()->BackdropFilterBounds();
}
// With BGPT disabled, UpdateFilterReferenceBox gets called from
@@ -1069,8 +1087,6 @@
layer->UpdateFilterReferenceBox();
}
layer->UpdateCompositorFilterOperationsForFilter(state.filter);
- layer->UpdateCompositorFilterOperationsForBackdropFilter(
- state.backdrop_filter, &state.backdrop_filter_bounds);
layer->ClearFilterOnEffectNodeDirty();
}
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
index 392ca60..b59a2d9 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -970,13 +970,17 @@
HashSet<int> pending_render_surfaces;
auto& effect_tree = host.property_trees()->effect_tree;
for (const auto& layer : layers) {
+ bool found_backdrop_filter = false;
for (auto* effect = effect_tree.Node(layer->effect_tree_index());
- !effect->has_render_surface;
+ !effect->has_render_surface || !effect->backdrop_filters.IsEmpty();
effect = effect_tree.Node(effect->parent_id)) {
+ found_backdrop_filter |= !effect->backdrop_filters.IsEmpty();
if (effect->opacity != 1.f &&
- !pending_render_surfaces.insert(effect->id).is_new_entry) {
- // The opacity-only effect is seen the second time, which means that it
- // has more than one compositing child and needs a render surface.
+ (!pending_render_surfaces.insert(effect->id).is_new_entry ||
+ found_backdrop_filter)) {
+ // The opacity-only effect is seen a second time, which means that it
+ // has more than one compositing child and needs a render surface. Or
+ // the opacity effect has a backdrop-filter child.
effect->has_render_surface = true;
break;
}
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
index c5ea197..f5a6823 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
@@ -3346,6 +3346,32 @@
kHasRenderSurface);
}
+TEST_P(PaintArtifactCompositorTest, OpacityRenderSurfacesWithBackdropChildren) {
+ // Opacity effect with a single compositing backdrop-filter child. Normally
+ // the opacity effect would not get a render surface. However, because
+ // backdrop-filter needs to only filter up to the backdrop root, it always
+ // gets a render surface.
+ auto e = CreateOpacityEffect(e0(), 0.4f);
+ auto a = CreateOpacityEffect(*e, 0.5f);
+ CompositorFilterOperations blur_filter;
+ blur_filter.AppendBlurFilter(5);
+ auto bd = CreateBackdropFilterEffect(
+ *a, blur_filter, FloatPoint(),
+ CompositingReason::kActiveBackdropFilterAnimation);
+
+ TestPaintArtifact artifact;
+ FloatRect r(150, 150, 100, 100);
+ artifact.Chunk(t0(), c0(), *a).RectDrawing(r, Color::kWhite);
+ artifact.Chunk(t0(), c0(), *bd).RectDrawing(r, Color::kWhite);
+ Update(artifact.Build());
+ ASSERT_EQ(2u, ContentLayerCount());
+
+ EXPECT_OPACITY(ContentLayerAt(0)->effect_tree_index(), 0.5,
+ kHasRenderSurface);
+ EXPECT_OPACITY(ContentLayerAt(1)->effect_tree_index(), 1.0,
+ kHasRenderSurface);
+}
+
TEST_P(PaintArtifactCompositorTest, OpacityIndirectlyAffectingTwoLayers) {
auto opacity = CreateOpacityEffect(e0(), 0.5f);
auto child_composited_effect = CreateOpacityEffect(
diff --git a/third_party/blink/renderer/platform/testing/paint_property_test_helpers.h b/third_party/blink/renderer/platform/testing/paint_property_test_helpers.h
index 12a40b2..9ad4051 100644
--- a/third_party/blink/renderer/platform/testing/paint_property_test_helpers.h
+++ b/third_party/blink/renderer/platform/testing/paint_property_test_helpers.h
@@ -72,6 +72,33 @@
compositing_reasons);
}
+inline scoped_refptr<EffectPaintPropertyNode> CreateBackdropFilterEffect(
+ const EffectPaintPropertyNode& parent,
+ const TransformPaintPropertyNode& local_transform_space,
+ const ClipPaintPropertyNode* output_clip,
+ CompositorFilterOperations backdrop_filter,
+ const FloatPoint& filters_origin = FloatPoint(),
+ CompositingReasons compositing_reasons = CompositingReason::kNone) {
+ EffectPaintPropertyNode::State state;
+ state.local_transform_space = &local_transform_space;
+ state.output_clip = output_clip;
+ state.backdrop_filter = std::move(backdrop_filter);
+ state.filters_origin = filters_origin;
+ state.direct_compositing_reasons = compositing_reasons;
+ return EffectPaintPropertyNode::Create(parent, std::move(state));
+}
+
+inline scoped_refptr<EffectPaintPropertyNode> CreateBackdropFilterEffect(
+ const EffectPaintPropertyNode& parent,
+ CompositorFilterOperations backdrop_filter,
+ const FloatPoint& paint_offset = FloatPoint(),
+ CompositingReasons compositing_reasons = CompositingReason::kNone) {
+ return CreateBackdropFilterEffect(
+ parent, parent.Unalias().LocalTransformSpace(),
+ parent.Unalias().OutputClip(), backdrop_filter, paint_offset,
+ compositing_reasons);
+}
+
inline scoped_refptr<ClipPaintPropertyNode> CreateClip(
const ClipPaintPropertyNode& parent,
const TransformPaintPropertyNode& local_transform_space,
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
index d6e3678..d0d1a1e 100644
--- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
+++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
@@ -425,11 +425,15 @@
crbug.com/923429 compositing/layer-creation/fixed-position-out-of-view-with-backdrop-filter.html [ Failure ]
crbug.com/923429 compositing/overflow/scroll-parent-absolute-with-backdrop-filter.html [ Failure ]
crbug.com/923429 css3/filters/backdrop-filter-basic-blur.html [ Failure ]
+crbug.com/923429 css3/filters/backdrop-filter-border-radius.html [ Failure ]
+crbug.com/923429 css3/filters/backdrop-filter-rendering.html [ Failure ]
crbug.com/923429 css3/filters/backdrop-filter-rendering-no-background.html [ Failure ]
crbug.com/923429 external/wpt/css/filter-effects/backdrop-filter-basic-background-color.html [ Failure ]
crbug.com/923429 external/wpt/css/filter-effects/backdrop-filter-basic-opacity-2.html [ Failure ]
crbug.com/923429 external/wpt/css/filter-effects/backdrop-filter-basic.html [ Failure ]
crbug.com/923429 external/wpt/css/filter-effects/backdrop-filter-fixed-clip.html [ Failure ]
+crbug.com/923429 external/wpt/css/filter-effects/backdrop-filter-isolation.html [ Failure ]
+
Bug(none) css3/filters/blur-filter-page-scroll-self.html [ Failure ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 4700ab2..15a0fc59 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1918,13 +1918,10 @@
crbug.com/497522 css3/filters/backdrop-filter-svg.html [ Failure ]
#crbug.com/497522 css3/filters/backdrop-filter-plus-filter.html [ Failure ]
# This fails, but only in CAP mode:
-crbug.com/497522 css3/filters/backdrop-filter-rendering.html [ Failure ]
crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-isolation-isolate.html [ Failure ]
-crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-border-radius.html [ Failure ]
crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-paint-order.html [ Failure ]
crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-isolation-fixed.html [ Failure ]
crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-edge-pixels.html [ Pass Failure ]
-crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-isolation.html [ Failure ]
# Until backdrop filter is enabled by default, backdrop tests will not pass in virtual/stable.
Bug(none) virtual/stable/compositing/layer-creation/fixed-position-out-of-view-with-backdrop-filter.html [ Skip ]
Bug(none) virtual/stable/compositing/overflow/scroll-parent-absolute-with-backdrop-filter.html [ Skip ]
diff --git a/third_party/blink/web_tests/css3/filters/backdrop-filter-border-radius-expected.png b/third_party/blink/web_tests/css3/filters/backdrop-filter-border-radius-expected.png
new file mode 100644
index 0000000..1ead16785
--- /dev/null
+++ b/third_party/blink/web_tests/css3/filters/backdrop-filter-border-radius-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/css3/filters/backdrop-filter-border-radius.html b/third_party/blink/web_tests/css3/filters/backdrop-filter-border-radius.html
new file mode 100644
index 0000000..2981af3
--- /dev/null
+++ b/third_party/blink/web_tests/css3/filters/backdrop-filter-border-radius.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+
+<div style="opacity: 0.9999;">
+ <div class="circle filter"></div>
+
+</div>
+
+
+<style>
+div {
+ position: absolute;
+ width: 100px;
+ height: 100px;
+ top: 10px;
+ left: 10px;
+ background: green;
+}
+.circle {
+ top: 30px;
+ left: 30px;
+ border-radius: 50px;
+ background: #ffff0060;
+}
+.filter {
+ backdrop-filter: invert(1);
+}
+</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-border-radius-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-border-radius-ref.html
deleted file mode 100644
index e5712a23..0000000
--- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-border-radius-ref.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>backdrop-filter: Should clip using border radius.</title>
-<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org">
-
-
-
-<div>
- <div class="circle outside"></div>
- <div class="circle inside"></div>
-</div>
-
-
-<style>
-div {
- position: absolute;
- width: 100px;
- height: 100px;
- top: 10px;
- left: 10px;
- background: green;
-}
-.circle {
- top: 30px;
- left: 30px;
- border-radius: 50px;
- background: #ffff0060;
-}
-.inside {
- background: #ffaf9f;
- clip-path: inset(0px 30px 30px 0px);
-}
-.outside {
- background: #ffff9f;
-}
-</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-border-radius.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-border-radius.html
deleted file mode 100644
index ec93de6..0000000
--- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-border-radius.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>backdrop-filter: Should clip using border radius.</title>
-<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org">
-<link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty">
-<link rel="match" href="backdrop-filter-border-radius-ref.html">
-
-<div style="opacity: 0.9999;">
- <div class="circle filter"></div>
-
-</div>
-
-
-<style>
-div {
- position: absolute;
- width: 100px;
- height: 100px;
- top: 10px;
- left: 10px;
- background: green;
-}
-.circle {
- top: 30px;
- left: 30px;
- border-radius: 50px;
- background: #ffff0060;
-}
-.filter {
- backdrop-filter: invert(1);
-}
-</style>