[go: up one dir, main page]

Fix the case where an element contains both filter and backdrop-filter

Previous to this CL, if an element was styled with both filter and
backdrop-filter, the filter effect was not properly applied to the
filtered backdrop contents, because a separate filter property node
gets created for the filter, and the backdrop-filter effect node
does not contain the filters. With this CL, paint_layer appends
the filters to the backdrop-filters list, so that Viz has access
to those.

TBR=masonfreed@chromium.org

(cherry picked from commit 1ff21a43a07257ccc2f56da17e03c0c74b2f070c)

Bug: 973907
Change-Id: I255b73433d75e0551d817134fa50d5e0e35b87df
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1658654
Commit-Queue: Mason Freed <masonfreed@chromium.org>
Auto-Submit: Mason Freed <masonfreed@chromium.org>
Reviewed-by: enne <enne@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#669006}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1660944
Reviewed-by: Mason Freed <masonfreed@chromium.org>
Cr-Commit-Position: refs/branch-heads/3809@{#317}
Cr-Branched-From: d82dec1a818f378c464ba307ddd9c92133eac355-refs/heads/master@{#665002}
diff --git a/components/viz/service/display/gl_renderer.cc b/components/viz/service/display/gl_renderer.cc
index 64f2992..3b93c6b 100644
--- a/components/viz/service/display/gl_renderer.cc
+++ b/components/viz/service/display/gl_renderer.cc
@@ -843,21 +843,19 @@
       (params->background_rect.top_right() - unclipped_rect.top_right()) +
       (params->background_rect.bottom_left() - unclipped_rect.bottom_left());
 
-  // Update the backdrop filter to include "regular" filters and opacity.
-  cc::FilterOperations backdrop_filters_plus_effects =
+  // Update the backdrop filter to include opacity.
+  cc::FilterOperations backdrop_filters_plus_opacity =
       *params->backdrop_filters;
-  if (params->filters) {
-    for (const auto& filter_op : params->filters->operations())
-      backdrop_filters_plus_effects.Append(filter_op);
-  }
+  DCHECK(!params->filters)
+      << "Filters should always be in a separate Effect node";
   if (quad->shared_quad_state->opacity < 1.0) {
-    backdrop_filters_plus_effects.Append(
+    backdrop_filters_plus_opacity.Append(
         cc::FilterOperation::CreateOpacityFilter(
             quad->shared_quad_state->opacity));
   }
 
   auto paint_filter = cc::RenderSurfaceFilters::BuildImageFilter(
-      backdrop_filters_plus_effects, gfx::SizeF(params->background_rect.size()),
+      backdrop_filters_plus_opacity, gfx::SizeF(params->background_rect.size()),
       gfx::Vector2dF(clipping_offset));
 
   // TODO(senorblanco): background filters should be moved to the
diff --git a/components/viz/service/display/software_renderer.cc b/components/viz/service/display/software_renderer.cc
index e783b198..37e16ef 100644
--- a/components/viz/service/display/software_renderer.cc
+++ b/components/viz/service/display/software_renderer.cc
@@ -803,14 +803,12 @@
       (unclipped_rect.top_right() - backdrop_rect.top_right()) +
       (backdrop_rect.bottom_left() - unclipped_rect.bottom_left());
 
-  // Update the backdrop filter to include "regular" filters and opacity.
-  cc::FilterOperations backdrop_filters_plus_effects = *backdrop_filters;
-  if (regular_filters) {
-    for (const auto& filter_op : regular_filters->operations())
-      backdrop_filters_plus_effects.Append(filter_op);
-  }
+  // Update the backdrop filter to include opacity.
+  cc::FilterOperations backdrop_filters_plus_opacity = *backdrop_filters;
+  DCHECK(!regular_filters)
+      << "Filters should always be in a separate Effect node";
   if (quad->shared_quad_state->opacity < 1.0) {
-    backdrop_filters_plus_effects.Append(
+    backdrop_filters_plus_opacity.Append(
         cc::FilterOperation::CreateOpacityFilter(
             quad->shared_quad_state->opacity));
   }
@@ -819,7 +817,7 @@
       gfx::Rect(0, 0, backdrop_bitmap.width(), backdrop_bitmap.height());
   sk_sp<SkImageFilter> filter =
       cc::RenderSurfaceFilters::BuildImageFilter(
-          backdrop_filters_plus_effects,
+          backdrop_filters_plus_opacity,
           gfx::SizeF(bitmap_rect.width(), bitmap_rect.height()),
           clipping_offset)
           ->cached_sk_filter_;
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc
index ae57e30e..758967d 100644
--- a/third_party/blink/renderer/core/paint/paint_layer.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -3329,11 +3329,22 @@
   }
   float zoom = style.EffectiveZoom();
   FloatRect reference_box = BackdropFilterReferenceBox();
+  // Tack on regular filter values here - they need to be applied to the
+  // backdrop image as well, in addition to being applied to the painted content
+  // and children of the element. This is a bit of a hack - according to the
+  // spec, filters should apply to the entire render pass as a whole, including
+  // the backdrop-filtered content. However, because in the case that we have
+  // both filters and backdrop-filters on a single element, we create two effect
+  // nodes, and two render surfaces, and the backdrop-filter node comes first.
+  // To get around that, we add the "regular" filters to the backdrop filters to
+  // approximate.
+  FilterOperations filter_operations = style.BackdropFilter();
+  filter_operations.Operations().AppendVector(style.Filter().Operations());
   // Use kClamp tile mode to avoid pixel moving filters bringing in black
   // transparent pixels from the viewport edge.
   return_value = FilterEffectBuilder(reference_box, zoom, nullptr, nullptr,
                                      SkBlurImageFilter::kClamp_TileMode)
-                     .BuildFilterOperations(style.BackdropFilter());
+                     .BuildFilterOperations(filter_operations);
   DCHECK(!return_value.IsEmpty());
   return return_value;
 }
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 d417982..2cb2a2e 100644
--- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
+++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
@@ -396,7 +396,6 @@
 crbug.com/923429 css3/filters/backdrop-filter-browser-zoom.html [ Failure ]
 crbug.com/923429 css3/filters/backdrop-filter-border-radius.html [ Failure ]
 crbug.com/923429 css3/filters/backdrop-filter-clip-rect-zoom.html [ Failure ]
-crbug.com/923429 css3/filters/backdrop-filter-plus-filter.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 css3/filters/backdrop-filter-transform.html [ Failure ]
diff --git a/third_party/blink/web_tests/css3/filters/backdrop-filter-plus-filter-expected.png b/third_party/blink/web_tests/css3/filters/backdrop-filter-plus-filter-expected.png
deleted file mode 100644
index 89c49dc..0000000
--- a/third_party/blink/web_tests/css3/filters/backdrop-filter-plus-filter-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/css3/filters/backdrop-filter-plus-filter.html b/third_party/blink/web_tests/css3/filters/backdrop-filter-plus-filter.html
deleted file mode 100644
index 602a4a3..0000000
--- a/third_party/blink/web_tests/css3/filters/backdrop-filter-plus-filter.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html>
-<div class="container">
-  <div class="orangebox"></div>
-  <div class="bluebox blur blur-bd"></div>
-</div>
-
-
-<style>
-div {
-  width: 100px;
-  height: 100px;
-  position :absolute;
-}
-.container {
-  width:200px;
-  height:200px;
-  position:absolute;
-}
-.blur {
-  -webkit-filter: blur(3px);
-  filter: blur(3px);
-}
-.blur-bd {
-  backdrop-filter: blur(15px);
-}
-.orangebox {
-  left: 10px;
-  top: 50px;
-  background: orange;
-}
-.bluebox {
-  left: 60px;
-  top: 110px;
-  background: #0000ff33;
-}
-</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-filter-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-filter-ref.html
new file mode 100644
index 0000000..bf476ea
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-filter-ref.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>backdrop-filter: Only filter objects painted before</title>
+<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org">
+
+
+
+<p>Expected: A green box with an overlapping purple box.<br>
+The overlapping portion of the boxes should be bright magenta.<br>
+
+<div class="container">
+  <div class="orangebox"></div>
+  <div class="bluebox blur-bd"></div>
+  <div class="invert"></div>
+</div>
+
+
+<style>
+div {
+  position: absolute;
+  width: 100px;
+  height: 100px;
+}
+.container {
+  width:200px;
+  height:200px;
+  top: 50px;
+  position:absolute;
+}
+.blur-bd {
+  backdrop-filter: blur(10px);
+}
+.orangebox {
+  left: 10px;
+  top: 50px;
+  background: green;
+}
+.bluebox {
+  left: 60px;
+  top: 110px;
+  background: #00ff0055;
+}
+.invert {
+  left: 60px;
+  top: 110px;
+  background: transparent;
+  backdrop-filter: invert(1);
+}
+</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-filter.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-filter.html
new file mode 100644
index 0000000..3a2d8fe
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-filter.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>backdrop-filter: Correctly apply filters to backdrop-filter content</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-plus-filter-ref.html">
+
+<p>Expected: A green box with an overlapping purple box.<br>
+The overlapping portion of the boxes should be bright magenta.<br>
+
+<div class="container">
+  <div class="orangebox"></div>
+  <div class="bluebox blur blur-bd"></div>
+</div>
+
+
+<style>
+div {
+  position: absolute;
+  width: 100px;
+  height: 100px;
+}
+.container {
+  width:200px;
+  height:200px;
+  top: 50px;
+  position:absolute;
+}
+.blur {
+  filter: invert(1);
+}
+.blur-bd {
+  backdrop-filter: blur(10px);
+}
+.orangebox {
+  left: 10px;
+  top: 50px;
+  background: green;
+}
+.bluebox {
+  left: 60px;
+  top: 110px;
+  background: #00ff0055;
+}
+</style>
diff --git a/third_party/blink/web_tests/virtual/scalefactor200/css3/filters/backdrop-filter-plus-filter-expected.png b/third_party/blink/web_tests/virtual/scalefactor200/css3/filters/backdrop-filter-plus-filter-expected.png
deleted file mode 100644
index 398cdce..0000000
--- a/third_party/blink/web_tests/virtual/scalefactor200/css3/filters/backdrop-filter-plus-filter-expected.png
+++ /dev/null
Binary files differ