Revert "Reland "render BackdropFilter layers directly to DisplayListBuilder"" (#34367)

diff --git a/display_list/display_list_image_filter.h b/display_list/display_list_image_filter.h
index ea98b49..2cea000 100644
--- a/display_list/display_list_image_filter.h
+++ b/display_list/display_list_image_filter.h
@@ -102,10 +102,9 @@
   // based on the supplied input bounds where both are measured in the local
   // (untransformed) coordinate space.
   //
-  // The method will return a pointer to the output_bounds parameter if it
-  // can successfully compute the output bounds of the filter, otherwise the
-  // method will return a nullptr and the output_bounds will be filled with
-  // a best guess for the answer, even if just a copy of the input_bounds.
+  // The output bounds parameter must be supplied and the method will either
+  // return a pointer to it with the result filled in, or it will return a
+  // nullptr if it cannot determine the results.
   virtual SkRect* map_local_bounds(const SkRect& input_bounds,
                                    SkRect& output_bounds) const = 0;
 
@@ -116,108 +115,12 @@
   // is used in a rendering operation (for example, the blur radius of a
   // Blur filter will expand based on the ctm).
   //
-  // The method will return a pointer to the output_bounds parameter if it
-  // can successfully compute the output bounds of the filter, otherwise the
-  // method will return a nullptr and the output_bounds will be filled with
-  // a best guess for the answer, even if just a copy of the input_bounds.
+  // The output bounds parameter must be supplied and the method will either
+  // return a pointer to it with the result filled in, or it will return a
+  // nullptr if it cannot determine the results.
   virtual SkIRect* map_device_bounds(const SkIRect& input_bounds,
                                      const SkMatrix& ctm,
                                      SkIRect& output_bounds) const = 0;
-
-  // Return the input bounds that will be needed in order for the filter to
-  // properly fill the indicated output_bounds under the specified
-  // transformation matrix. Both output_bounds and input_bounds are taken to
-  // be relative to the transformed coordinate space of the provided |ctm|.
-  //
-  // The method will return a pointer to the input_bounds parameter if it
-  // can successfully compute the required input bounds, otherwise the
-  // method will return a nullptr and the input_bounds will be filled with
-  // a best guess for the answer, even if just a copy of the output_bounds.
-  virtual SkIRect* get_input_device_bounds(const SkIRect& output_bounds,
-                                           const SkMatrix& ctm,
-                                           SkIRect& input_bounds) const = 0;
-
- protected:
-  static SkVector map_vectors_affine(const SkMatrix& ctm,
-                                     SkScalar x,
-                                     SkScalar y) {
-    FML_DCHECK(SkScalarIsFinite(x) && x >= 0);
-    FML_DCHECK(SkScalarIsFinite(y) && y >= 0);
-    FML_DCHECK(ctm.isFinite() && !ctm.hasPerspective());
-
-    // The x and y scalars would have been used to expand a local space
-    // rectangle which is then transformed by ctm. In order to do the
-    // expansion correctly, we should look at the relevant math. The
-    // 4 corners will be moved outward by the following vectors:
-    //     (UL,UR,LR,LL) = ((-x, -y), (+x, -y), (+x, +y), (-x, +y))
-    // After applying the transform, each of these vectors could be
-    // pointing in any direction so we need to examine each transformed
-    // delta vector and how it affected the bounds.
-    // Looking at just the affine 2x3 entries of the CTM we can delta
-    // transform these corner offsets and get the following:
-    //     UL = dCTM(-x, -y) = (- x*m00 - y*m01, - x*m10 - y*m11)
-    //     UR = dCTM(+x, -y) = (  x*m00 - y*m01,   x*m10 - y*m11)
-    //     LR = dCTM(+x, +y) = (  x*m00 + y*m01,   x*m10 + y*m11)
-    //     LL = dCTM(-x, +y) = (- x*m00 + y*m01, - x*m10 + y*m11)
-    // The X vectors are all some variation of adding or subtracting
-    // the sum of x*m00 and y*m01 or their difference. Similarly the Y
-    // vectors are +/- the associated sum/difference of x*m10 and y*m11.
-    // The largest displacements, both left/right or up/down, will
-    // happen when the signs of the m00/m01/m10/m11 matrix entries
-    // coincide with the signs of the scalars, i.e. are all positive.
-    return {x * abs(ctm[0]) + y * abs(ctm[1]),
-            x * abs(ctm[3]) + y * abs(ctm[4])};
-  }
-
-  static SkIRect* inset_device_bounds(const SkIRect& input_bounds,
-                                      SkScalar radius_x,
-                                      SkScalar radius_y,
-                                      const SkMatrix& ctm,
-                                      SkIRect& output_bounds) {
-    if (ctm.isFinite()) {
-      if (ctm.hasPerspective()) {
-        SkMatrix inverse;
-        if (ctm.invert(&inverse)) {
-          SkRect local_bounds = inverse.mapRect(SkRect::Make(input_bounds));
-          local_bounds.inset(radius_x, radius_y);
-          output_bounds = ctm.mapRect(local_bounds).roundOut();
-          return &output_bounds;
-        }
-      } else {
-        SkVector device_radius = map_vectors_affine(ctm, radius_x, radius_y);
-        output_bounds = input_bounds.makeInset(floor(device_radius.fX),  //
-                                               floor(device_radius.fY));
-        return &output_bounds;
-      }
-    }
-    output_bounds = input_bounds;
-    return nullptr;
-  }
-
-  static SkIRect* outset_device_bounds(const SkIRect& input_bounds,
-                                       SkScalar radius_x,
-                                       SkScalar radius_y,
-                                       const SkMatrix& ctm,
-                                       SkIRect& output_bounds) {
-    if (ctm.isFinite()) {
-      if (ctm.hasPerspective()) {
-        SkMatrix inverse;
-        if (ctm.invert(&inverse)) {
-          SkRect local_bounds = inverse.mapRect(SkRect::Make(input_bounds));
-          local_bounds.outset(radius_x, radius_y);
-          output_bounds = ctm.mapRect(local_bounds).roundOut();
-          return &output_bounds;
-        }
-      } else {
-        SkVector device_radius = map_vectors_affine(ctm, radius_x, radius_y);
-        output_bounds = input_bounds.makeOutset(ceil(device_radius.fX),  //
-                                                ceil(device_radius.fY));
-        return &output_bounds;
-      }
-    }
-    output_bounds = input_bounds;
-    return nullptr;
-  }
 };
 
 class DlBlurImageFilter final : public DlImageFilter {
@@ -251,15 +154,16 @@
   SkIRect* map_device_bounds(const SkIRect& input_bounds,
                              const SkMatrix& ctm,
                              SkIRect& output_bounds) const override {
-    return outset_device_bounds(input_bounds, sigma_x_ * 3.0, sigma_y_ * 3.0,
-                                ctm, output_bounds);
-  }
-
-  SkIRect* get_input_device_bounds(const SkIRect& output_bounds,
-                                   const SkMatrix& ctm,
-                                   SkIRect& input_bounds) const override {
-    // Blurs are symmetric in terms of output-for-input and input-for-output
-    return map_device_bounds(output_bounds, ctm, input_bounds);
+    SkVector device_sigma = ctm.mapVector(sigma_x_ * 3, sigma_y_ * 3);
+    if (!SkScalarIsFinite(device_sigma.fX)) {
+      device_sigma.fX = 0;
+    }
+    if (!SkScalarIsFinite(device_sigma.fY)) {
+      device_sigma.fY = 0;
+    }
+    output_bounds = input_bounds.makeOutset(ceil(abs(device_sigma.fX)),
+                                            ceil(abs(device_sigma.fY)));
+    return &output_bounds;
   }
 
   SkScalar sigma_x() const { return sigma_x_; }
@@ -313,15 +217,16 @@
   SkIRect* map_device_bounds(const SkIRect& input_bounds,
                              const SkMatrix& ctm,
                              SkIRect& output_bounds) const override {
-    return outset_device_bounds(input_bounds, radius_x_, radius_y_, ctm,
-                                output_bounds);
-  }
-
-  SkIRect* get_input_device_bounds(const SkIRect& output_bounds,
-                                   const SkMatrix& ctm,
-                                   SkIRect& input_bounds) const override {
-    return inset_device_bounds(output_bounds, radius_x_, radius_y_, ctm,
-                               input_bounds);
+    SkVector device_radius = ctm.mapVector(radius_x_, radius_y_);
+    if (!SkScalarIsFinite(device_radius.fX)) {
+      device_radius.fX = 0;
+    }
+    if (!SkScalarIsFinite(device_radius.fY)) {
+      device_radius.fY = 0;
+    }
+    output_bounds = input_bounds.makeOutset(ceil(abs(device_radius.fX)),
+                                            ceil(abs(device_radius.fY)));
+    return &output_bounds;
   }
 
   SkScalar radius_x() const { return radius_x_; }
@@ -365,22 +270,23 @@
 
   SkRect* map_local_bounds(const SkRect& input_bounds,
                            SkRect& output_bounds) const override {
-    output_bounds = input_bounds.makeInset(radius_x_, radius_y_);
+    output_bounds = input_bounds.makeOutset(radius_x_, radius_y_);
     return &output_bounds;
   }
 
   SkIRect* map_device_bounds(const SkIRect& input_bounds,
                              const SkMatrix& ctm,
                              SkIRect& output_bounds) const override {
-    return inset_device_bounds(input_bounds, radius_x_, radius_y_, ctm,
-                               output_bounds);
-  }
-
-  SkIRect* get_input_device_bounds(const SkIRect& output_bounds,
-                                   const SkMatrix& ctm,
-                                   SkIRect& input_bounds) const override {
-    return outset_device_bounds(output_bounds, radius_x_, radius_y_, ctm,
-                                input_bounds);
+    SkVector device_radius = ctm.mapVector(radius_x_, radius_y_);
+    if (!SkScalarIsFinite(device_radius.fX)) {
+      device_radius.fX = 0;
+    }
+    if (!SkScalarIsFinite(device_radius.fY)) {
+      device_radius.fY = 0;
+    }
+    output_bounds = input_bounds.makeOutset(ceil(abs(device_radius.fX)),
+                                            ceil(abs(device_radius.fY)));
+    return &output_bounds;
   }
 
   SkScalar radius_x() const { return radius_x_; }
@@ -447,23 +353,6 @@
     return &output_bounds;
   }
 
-  SkIRect* get_input_device_bounds(const SkIRect& output_bounds,
-                                   const SkMatrix& ctm,
-                                   SkIRect& input_bounds) const override {
-    SkMatrix matrix = SkMatrix::Concat(ctm, matrix_);
-    SkMatrix inverse;
-    if (!matrix.invert(&inverse)) {
-      input_bounds = output_bounds;
-      return nullptr;
-    }
-    inverse.postConcat(ctm);
-    SkRect bounds;
-    bounds.set(output_bounds);
-    inverse.mapRect(&bounds);
-    input_bounds = bounds.roundOut();
-    return &input_bounds;
-  }
-
   sk_sp<SkImageFilter> skia_object() const override {
     return SkImageFilters::MatrixTransform(matrix_, ToSk(sampling_), nullptr);
   }
@@ -520,61 +409,41 @@
 
   SkRect* map_local_bounds(const SkRect& input_bounds,
                            SkRect& output_bounds) const override {
-    SkRect cur_bounds = input_bounds;
-    // We set this result in case neither filter is present.
-    output_bounds = input_bounds;
+    SkRect* ret = &output_bounds;
     if (inner_) {
-      if (!inner_->map_local_bounds(cur_bounds, output_bounds)) {
-        return nullptr;
-      }
-      cur_bounds = output_bounds;
-    }
-    if (outer_) {
-      if (!outer_->map_local_bounds(cur_bounds, output_bounds)) {
-        return nullptr;
+      if (!inner_->map_local_bounds(input_bounds, output_bounds)) {
+        ret = nullptr;
       }
     }
-    return &output_bounds;
+    if (ret && outer_) {
+      if (!outer_->map_local_bounds(input_bounds, output_bounds)) {
+        ret = nullptr;
+      }
+    }
+    if (!ret) {
+      output_bounds = input_bounds;
+    }
+    return ret;
   }
 
   SkIRect* map_device_bounds(const SkIRect& input_bounds,
                              const SkMatrix& ctm,
                              SkIRect& output_bounds) const override {
-    SkIRect cur_bounds = input_bounds;
-    // We set this result in case neither filter is present.
-    output_bounds = input_bounds;
+    SkIRect* ret = &output_bounds;
     if (inner_) {
-      if (!inner_->map_device_bounds(cur_bounds, ctm, output_bounds)) {
-        return nullptr;
-      }
-      cur_bounds = output_bounds;
-    }
-    if (outer_) {
-      if (!outer_->map_device_bounds(cur_bounds, ctm, output_bounds)) {
-        return nullptr;
+      if (!inner_->map_device_bounds(input_bounds, ctm, output_bounds)) {
+        ret = nullptr;
       }
     }
-    return &output_bounds;
-  }
-
-  SkIRect* get_input_device_bounds(const SkIRect& output_bounds,
-                                   const SkMatrix& ctm,
-                                   SkIRect& input_bounds) const override {
-    SkIRect cur_bounds = output_bounds;
-    // We set this result in case neither filter is present.
-    input_bounds = output_bounds;
-    if (outer_) {
-      if (!outer_->get_input_device_bounds(cur_bounds, ctm, input_bounds)) {
-        return nullptr;
-      }
-      cur_bounds = output_bounds;
-    }
-    if (inner_) {
-      if (!inner_->get_input_device_bounds(cur_bounds, ctm, input_bounds)) {
-        return nullptr;
+    if (ret && outer_) {
+      if (!outer_->map_device_bounds(input_bounds, ctm, output_bounds)) {
+        ret = nullptr;
       }
     }
-    return &input_bounds;
+    if (!ret) {
+      output_bounds = input_bounds;
+    }
+    return ret;
   }
 
   sk_sp<SkImageFilter> skia_object() const override {
@@ -644,12 +513,6 @@
     return modifies_transparent_black() ? nullptr : &output_bounds;
   }
 
-  SkIRect* get_input_device_bounds(const SkIRect& output_bounds,
-                                   const SkMatrix& ctm,
-                                   SkIRect& input_bounds) const override {
-    return map_device_bounds(output_bounds, ctm, input_bounds);
-  }
-
   sk_sp<SkImageFilter> skia_object() const override {
     return SkImageFilters::ColorFilter(color_filter_->skia_object(), nullptr);
   }
@@ -701,8 +564,8 @@
 
   SkRect* map_local_bounds(const SkRect& input_bounds,
                            SkRect& output_bounds) const override {
+    output_bounds = input_bounds;
     if (modifies_transparent_black()) {
-      output_bounds = input_bounds;
       return nullptr;
     }
     output_bounds = sk_filter_->computeFastBounds(input_bounds);
@@ -712,8 +575,8 @@
   SkIRect* map_device_bounds(const SkIRect& input_bounds,
                              const SkMatrix& ctm,
                              SkIRect& output_bounds) const override {
+    output_bounds = input_bounds;
     if (modifies_transparent_black()) {
-      output_bounds = input_bounds;
       return nullptr;
     }
     output_bounds = sk_filter_->filterBounds(
@@ -721,18 +584,6 @@
     return &output_bounds;
   }
 
-  SkIRect* get_input_device_bounds(const SkIRect& output_bounds,
-                                   const SkMatrix& ctm,
-                                   SkIRect& input_bounds) const override {
-    if (modifies_transparent_black()) {
-      input_bounds = output_bounds;
-      return nullptr;
-    }
-    input_bounds = sk_filter_->filterBounds(
-        output_bounds, ctm, SkImageFilter::kReverse_MapDirection);
-    return &input_bounds;
-  }
-
   sk_sp<SkImageFilter> skia_object() const override { return sk_filter_; }
 
   virtual ~DlUnknownImageFilter() = default;
diff --git a/display_list/display_list_image_filter_unittests.cc b/display_list/display_list_image_filter_unittests.cc
index 2dc6ea5..729de1f 100644
--- a/display_list/display_list_image_filter_unittests.cc
+++ b/display_list/display_list_image_filter_unittests.cc
@@ -142,135 +142,6 @@
   ASSERT_NE(filter->asColorFilter(), nullptr);
 }
 
-// SkRect::contains treats the rect as a half-open interval which is
-// appropriate for so many operations. Unfortunately, we are using
-// it here to test containment of the corners of a transformed quad
-// so the corners of the quad that are measured against the right
-// and bottom edges are contained even if they are on the right or
-// bottom edge. This method does the "all sides inclusive" version
-// of SkRect::contains.
-static bool containsInclusive(const SkRect rect, const SkPoint p) {
-  // Test with a slight offset of 1E-9 to "forgive" IEEE bit-rounding
-  // Ending up with bounds that are off by 1E-9 (these numbers are all
-  // being tested in device space with this method) will be off by a
-  // negligible amount of a pixel that wouldn't contribute to changing
-  // the color of a pixel.
-  return (p.fX >= rect.fLeft - 1E-9 &&   //
-          p.fX <= rect.fRight + 1E-9 &&  //
-          p.fY >= rect.fTop - 1E-9 &&    //
-          p.fY <= rect.fBottom + 1E-9);
-}
-
-static bool containsInclusive(const SkRect rect, const SkPoint quad[4]) {
-  return (containsInclusive(rect, quad[0]) &&  //
-          containsInclusive(rect, quad[1]) &&  //
-          containsInclusive(rect, quad[2]) &&  //
-          containsInclusive(rect, quad[3]));
-}
-
-static bool containsInclusive(const SkIRect rect, const SkPoint quad[4]) {
-  return containsInclusive(SkRect::Make(rect), quad);
-}
-
-static bool containsInclusive(const SkIRect rect, const SkRect bounds) {
-  return (bounds.fLeft >= rect.fLeft - 1E-9 &&
-          bounds.fTop >= rect.fTop - 1E-9 &&
-          bounds.fRight <= rect.fRight + 1E-9 &&
-          bounds.fBottom <= rect.fBottom + 1E-9);
-}
-
-// Used to verify that the expected output bounds and revers engineered
-// "input bounds for output bounds" rectangles are included in the rectangle
-// returned from the various bounds computation methods under the specified
-// matrix.
-static void TestBoundsWithMatrix(const DlImageFilter& filter,
-                                 const SkMatrix& matrix,
-                                 const SkRect& sourceBounds,
-                                 const SkPoint expectedLocalOutputQuad[4]) {
-  SkRect deviceInputBounds = matrix.mapRect(sourceBounds);
-  SkPoint expectedDeviceOutputQuad[4];
-  matrix.mapPoints(expectedDeviceOutputQuad, expectedLocalOutputQuad, 4);
-
-  SkIRect deviceFilterIBounds;
-  ASSERT_EQ(filter.map_device_bounds(deviceInputBounds.roundOut(), matrix,
-                                     deviceFilterIBounds),
-            &deviceFilterIBounds);
-  ASSERT_TRUE(containsInclusive(deviceFilterIBounds, expectedDeviceOutputQuad));
-
-  SkIRect reverseInputIBounds;
-  ASSERT_EQ(filter.get_input_device_bounds(deviceFilterIBounds, matrix,
-                                           reverseInputIBounds),
-            &reverseInputIBounds);
-  ASSERT_TRUE(containsInclusive(reverseInputIBounds, deviceInputBounds));
-}
-
-static void TestInvalidBounds(const DlImageFilter& filter,
-                              const SkMatrix& matrix,
-                              const SkRect& localInputBounds) {
-  SkIRect deviceInputBounds = matrix.mapRect(localInputBounds).roundOut();
-
-  SkRect localFilterBounds;
-  ASSERT_EQ(filter.map_local_bounds(localInputBounds, localFilterBounds),
-            nullptr);
-  ASSERT_EQ(localFilterBounds, localInputBounds);
-
-  SkIRect deviceFilterIBounds;
-  ASSERT_EQ(
-      filter.map_device_bounds(deviceInputBounds, matrix, deviceFilterIBounds),
-      nullptr);
-  ASSERT_EQ(deviceFilterIBounds, deviceInputBounds);
-
-  SkIRect reverseInputIBounds;
-  ASSERT_EQ(filter.get_input_device_bounds(deviceInputBounds, matrix,
-                                           reverseInputIBounds),
-            nullptr);
-  ASSERT_EQ(reverseInputIBounds, deviceInputBounds);
-}
-
-// localInputBounds is a sample bounds for testing as input to the filter.
-// localExpectOutputBounds is the theoretical output bounds for applying
-// the filter to the localInputBounds.
-// localExpectInputBounds is the theoretical input bounds required for the
-// filter to cover the localExpectOutputBounds
-// If either of the expected bounds are nullptr then the bounds methods will
-// be assumed to be unable to perform their computations for the given
-// image filter and will be returning null.
-static void TestBounds(const DlImageFilter& filter,
-                       const SkRect& sourceBounds,
-                       const SkPoint expectedLocalOutputQuad[4]) {
-  SkRect localFilterBounds;
-  ASSERT_EQ(filter.map_local_bounds(sourceBounds, localFilterBounds),
-            &localFilterBounds);
-  ASSERT_TRUE(containsInclusive(localFilterBounds, expectedLocalOutputQuad));
-
-  for (int scale = 1; scale <= 4; scale++) {
-    for (int skew = 0; skew < 8; skew++) {
-      for (int degrees = 0; degrees <= 360; degrees += 15) {
-        SkMatrix matrix;
-        matrix.setScale(scale, scale);
-        matrix.postSkew(skew / 8.0, skew / 8.0);
-        matrix.postRotate(degrees);
-        ASSERT_TRUE(matrix.invert(nullptr));
-        TestBoundsWithMatrix(filter, matrix, sourceBounds,
-                             expectedLocalOutputQuad);
-        matrix.setPerspX(0.01);
-        matrix.setPerspY(0.01);
-        ASSERT_TRUE(matrix.invert(nullptr));
-        TestBoundsWithMatrix(filter, matrix, sourceBounds,
-                             expectedLocalOutputQuad);
-      }
-    }
-  }
-}
-
-static void TestBounds(const DlImageFilter& filter,
-                       const SkRect& sourceBounds,
-                       const SkRect& expectedLocalOutputBounds) {
-  SkPoint expectedLocalOutputQuad[4];
-  expectedLocalOutputBounds.toQuad(expectedLocalOutputQuad);
-  TestBounds(filter, sourceBounds, expectedLocalOutputQuad);
-}
-
 TEST(DisplayListImageFilter, BlurConstructor) {
   DlBlurImageFilter filter(5.0, 6.0, DlTileMode::kMirror);
 }
@@ -315,14 +186,6 @@
   TestNotEquals(filter1, filter4, "Tile Mode differs");
 }
 
-TEST(DisplayListImageFilter, BlurBounds) {
-  DlBlurImageFilter filter = DlBlurImageFilter(5, 10, DlTileMode::kDecal);
-  SkRect inputBounds = SkRect::MakeLTRB(20, 20, 80, 80);
-  SkRect expectOutputBounds = inputBounds.makeOutset(15, 30);
-  // SkRect expectInputBounds = expectOutputBounds.makeOutset(15, 30);
-  TestBounds(filter, inputBounds, expectOutputBounds);
-}
-
 TEST(DisplayListImageFilter, DilateConstructor) {
   DlDilateImageFilter filter(5.0, 6.0);
 }
@@ -364,13 +227,6 @@
   TestNotEquals(filter1, filter3, "Radius Y differs");
 }
 
-TEST(DisplayListImageFilter, DilateBounds) {
-  DlDilateImageFilter filter = DlDilateImageFilter(5, 10);
-  SkRect inputBounds = SkRect::MakeLTRB(20, 20, 80, 80);
-  SkRect expectOutputBounds = inputBounds.makeOutset(5, 10);
-  TestBounds(filter, inputBounds, expectOutputBounds);
-}
-
 TEST(DisplayListImageFilter, ErodeConstructor) {
   DlErodeImageFilter filter(5.0, 6.0);
 }
@@ -412,13 +268,6 @@
   TestNotEquals(filter1, filter3, "Radius Y differs");
 }
 
-TEST(DisplayListImageFilter, ErodeBounds) {
-  DlErodeImageFilter filter = DlErodeImageFilter(5, 10);
-  SkRect inputBounds = SkRect::MakeLTRB(20, 20, 80, 80);
-  SkRect expectOutputBounds = inputBounds.makeInset(5, 10);
-  TestBounds(filter, inputBounds, expectOutputBounds);
-}
-
 TEST(DisplayListImageFilter, MatrixConstructor) {
   DlMatrixImageFilter filter(SkMatrix::MakeAll(2.0, 0.0, 10,  //
                                                0.5, 3.0, 15,  //
@@ -481,23 +330,6 @@
   TestNotEquals(filter1, filter3, "Sampling differs");
 }
 
-TEST(DisplayListImageFilter, MatrixBounds) {
-  SkMatrix matrix = SkMatrix::MakeAll(2.0, 0.0, 10,  //
-                                      0.5, 3.0, 7,   //
-                                      0.0, 0.0, 1);
-  SkMatrix inverse;
-  ASSERT_TRUE(matrix.invert(&inverse));
-  DlMatrixImageFilter filter(matrix, DlImageSampling::kLinear);
-  SkRect inputBounds = SkRect::MakeLTRB(20, 20, 80, 80);
-  SkPoint expectedOutputQuad[4] = {
-      {50, 77},    // (20,20) => (20*2 + 10, 20/2 + 20*3 + 7) == (50, 77)
-      {50, 257},   // (20,80) => (20*2 + 10, 20/2 + 80*3 + 7) == (50, 257)
-      {170, 287},  // (80,80) => (80*2 + 10, 80/2 + 80*3 + 7) == (170, 287)
-      {170, 107},  // (80,20) => (80*2 + 10, 80/2 + 20*3 + 7) == (170, 107)
-  };
-  TestBounds(filter, inputBounds, expectedOutputQuad);
-}
-
 TEST(DisplayListImageFilter, ComposeConstructor) {
   DlMatrixImageFilter outer(SkMatrix::MakeAll(2.0, 0.0, 10,  //
                                               0.5, 3.0, 15,  //
@@ -582,15 +414,6 @@
   TestNotEquals(filter1, filter3, "Inner differs");
 }
 
-TEST(DisplayListImageFilter, ComposeBounds) {
-  DlDilateImageFilter outer = DlDilateImageFilter(5, 10);
-  DlBlurImageFilter inner = DlBlurImageFilter(12, 5, DlTileMode::kDecal);
-  DlComposeImageFilter filter = DlComposeImageFilter(outer, inner);
-  SkRect inputBounds = SkRect::MakeLTRB(20, 20, 80, 80);
-  SkRect expectOutputBounds = inputBounds.makeOutset(36, 15).makeOutset(5, 10);
-  TestBounds(filter, inputBounds, expectOutputBounds);
-}
-
 TEST(DisplayListImageFilter, ColorFilterConstructor) {
   DlBlendColorFilter dl_color_filter(DlColor::kRed(), DlBlendMode::kLighten);
   DlColorFilterImageFilter filter(dl_color_filter);
@@ -642,20 +465,6 @@
   TestNotEquals(filter1, filter3, "Blend Mode differs");
 }
 
-TEST(DisplayListImageFilter, ColorFilterBounds) {
-  DlBlendColorFilter dl_color_filter(DlColor::kRed(), DlBlendMode::kSrcIn);
-  DlColorFilterImageFilter filter(dl_color_filter);
-  SkRect inputBounds = SkRect::MakeLTRB(20, 20, 80, 80);
-  TestBounds(filter, inputBounds, inputBounds);
-}
-
-TEST(DisplayListImageFilter, ColorFilterModifiesTransparencyBounds) {
-  DlBlendColorFilter dl_color_filter(DlColor::kRed(), DlBlendMode::kSrcOver);
-  DlColorFilterImageFilter filter(dl_color_filter);
-  SkRect inputBounds = SkRect::MakeLTRB(20, 20, 80, 80);
-  TestInvalidBounds(filter, SkMatrix::I(), inputBounds);
-}
-
 TEST(DisplayListImageFilter, UnknownConstructor) {
   DlUnknownImageFilter filter(
       SkImageFilters::Blur(5.0, 6.0, SkTileMode::kRepeat, nullptr));
diff --git a/flow/layers/backdrop_filter_layer.cc b/flow/layers/backdrop_filter_layer.cc
index cc3a007..8e8ef26 100644
--- a/flow/layers/backdrop_filter_layer.cc
+++ b/flow/layers/backdrop_filter_layer.cc
@@ -6,9 +6,8 @@
 
 namespace flutter {
 
-BackdropFilterLayer::BackdropFilterLayer(
-    std::shared_ptr<const DlImageFilter> filter,
-    DlBlendMode blend_mode)
+BackdropFilterLayer::BackdropFilterLayer(sk_sp<SkImageFilter> filter,
+                                         SkBlendMode blend_mode)
     : filter_(std::move(filter)), blend_mode_(blend_mode) {}
 
 void BackdropFilterLayer::Diff(DiffContext* context, const Layer* old_layer) {
@@ -16,7 +15,7 @@
   auto* prev = static_cast<const BackdropFilterLayer*>(old_layer);
   if (!context->IsSubtreeDirty()) {
     FML_DCHECK(prev);
-    if (NotEquals(filter_, prev->filter_)) {
+    if (filter_ != prev->filter_) {
       context->MarkSubtreeDirty(context->GetOldLayerPaintRegion(old_layer));
     }
   }
@@ -27,11 +26,11 @@
 
   if (filter_) {
     context->GetTransform().mapRect(&paint_bounds);
-    auto filter_target_bounds = paint_bounds.roundOut();
-    SkIRect filter_input_bounds;  // in screen coordinates
-    filter_->get_input_device_bounds(
-        filter_target_bounds, context->GetTransform(), filter_input_bounds);
-    context->AddReadbackRegion(filter_input_bounds);
+    auto input_filter_bounds = paint_bounds.roundOut();
+    auto filter_bounds =  // in screen coordinates
+        filter_->filterBounds(input_filter_bounds, context->GetTransform(),
+                              SkImageFilter::kReverse_MapDirection);
+    context->AddReadbackRegion(filter_bounds);
   }
 
   DiffChildren(context, prev);
@@ -53,28 +52,15 @@
   TRACE_EVENT0("flutter", "BackdropFilterLayer::Paint");
   FML_DCHECK(needs_painting(context));
 
-  if (context.leaf_nodes_builder) {
-    DlPaint paint;
-    paint.setBlendMode(blend_mode_);
-    context.leaf_nodes_builder->saveLayer(&paint_bounds(), &paint,
-                                          filter_.get());
-
-    PaintChildren(context);
-
-    context.leaf_nodes_builder->restore();
-  } else {
-    SkPaint paint;
-    paint.setBlendMode(ToSk(blend_mode_));
-    auto sk_filter = filter_ ? filter_->skia_object() : nullptr;
-    Layer::AutoSaveLayer save = Layer::AutoSaveLayer::Create(
-        context,
-        SkCanvas::SaveLayerRec{&paint_bounds(), &paint, sk_filter.get(), 0},
-        // BackdropFilter should only happen on the leaf nodes canvas.
-        // See https:://flutter.dev/go/backdrop-filter-with-overlay-canvas
-        AutoSaveLayer::SaveMode::kLeafNodesCanvas);
-
-    PaintChildren(context);
-  }
+  SkPaint paint;
+  paint.setBlendMode(blend_mode_);
+  Layer::AutoSaveLayer save = Layer::AutoSaveLayer::Create(
+      context,
+      SkCanvas::SaveLayerRec{&paint_bounds(), &paint, filter_.get(), 0},
+      // BackdropFilter should only happen on the leaf nodes canvas.
+      // See https:://flutter.dev/go/backdrop-filter-with-overlay-canvas
+      AutoSaveLayer::SaveMode::kLeafNodesCanvas);
+  PaintChildren(context);
 }
 
 }  // namespace flutter
diff --git a/flow/layers/backdrop_filter_layer.h b/flow/layers/backdrop_filter_layer.h
index 8584413..c8cbeba 100644
--- a/flow/layers/backdrop_filter_layer.h
+++ b/flow/layers/backdrop_filter_layer.h
@@ -12,8 +12,7 @@
 
 class BackdropFilterLayer : public ContainerLayer {
  public:
-  BackdropFilterLayer(std::shared_ptr<const DlImageFilter> filter,
-                      DlBlendMode blend_mode);
+  BackdropFilterLayer(sk_sp<SkImageFilter> filter, SkBlendMode blend_mode);
 
   void Diff(DiffContext* context, const Layer* old_layer) override;
 
@@ -22,8 +21,8 @@
   void Paint(PaintContext& context) const override;
 
  private:
-  std::shared_ptr<const DlImageFilter> filter_;
-  DlBlendMode blend_mode_;
+  sk_sp<SkImageFilter> filter_;
+  SkBlendMode blend_mode_;
 
   FML_DISALLOW_COPY_AND_ASSIGN(BackdropFilterLayer);
 };
diff --git a/flow/layers/backdrop_filter_layer_unittests.cc b/flow/layers/backdrop_filter_layer_unittests.cc
index 0cb82f3..33792a7 100644
--- a/flow/layers/backdrop_filter_layer_unittests.cc
+++ b/flow/layers/backdrop_filter_layer_unittests.cc
@@ -22,9 +22,8 @@
 
 #ifndef NDEBUG
 TEST_F(BackdropFilterLayerTest, PaintingEmptyLayerDies) {
-  auto filter = DlBlurImageFilter(5, 5, DlTileMode::kClamp);
-  auto layer = std::make_shared<BackdropFilterLayer>(filter.shared(),
-                                                     DlBlendMode::kSrcOver);
+  auto layer = std::make_shared<BackdropFilterLayer>(sk_sp<SkImageFilter>(),
+                                                     SkBlendMode::kSrcOver);
   auto parent = std::make_shared<ClipRectLayer>(kEmptyRect, Clip::hardEdge);
   parent->Add(layer);
 
@@ -41,9 +40,8 @@
   const SkRect child_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
   const SkPath child_path = SkPath().addRect(child_bounds);
   auto mock_layer = std::make_shared<MockLayer>(child_path);
-  auto filter = DlBlurImageFilter(5, 5, DlTileMode::kClamp);
-  auto layer = std::make_shared<BackdropFilterLayer>(filter.shared(),
-                                                     DlBlendMode::kSrcOver);
+  auto layer = std::make_shared<BackdropFilterLayer>(sk_sp<SkImageFilter>(),
+                                                     SkBlendMode::kSrcOver);
   layer->Add(mock_layer);
 
   EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
@@ -60,7 +58,7 @@
   const SkPaint child_paint = SkPaint(SkColors::kYellow);
   auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
   auto layer =
-      std::make_shared<BackdropFilterLayer>(nullptr, DlBlendMode::kSrcOver);
+      std::make_shared<BackdropFilterLayer>(nullptr, SkBlendMode::kSrcOver);
   layer->Add(mock_layer);
   auto parent = std::make_shared<ClipRectLayer>(child_bounds, Clip::hardEdge);
   parent->Add(layer);
@@ -89,8 +87,8 @@
   const SkPaint child_paint = SkPaint(SkColors::kYellow);
   auto layer_filter = SkImageFilters::Paint(SkPaint(SkColors::kMagenta));
   auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
-  auto layer = std::make_shared<BackdropFilterLayer>(
-      DlImageFilter::From(layer_filter), DlBlendMode::kSrcOver);
+  auto layer = std::make_shared<BackdropFilterLayer>(layer_filter,
+                                                     SkBlendMode::kSrcOver);
   layer->Add(mock_layer);
   auto parent = std::make_shared<ClipRectLayer>(child_bounds, Clip::hardEdge);
   parent->Add(layer);
@@ -119,8 +117,8 @@
   const SkPaint child_paint = SkPaint(SkColors::kYellow);
   auto layer_filter = SkImageFilters::Paint(SkPaint(SkColors::kMagenta));
   auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
-  auto layer = std::make_shared<BackdropFilterLayer>(
-      DlImageFilter::From(layer_filter), DlBlendMode::kSrc);
+  auto layer =
+      std::make_shared<BackdropFilterLayer>(layer_filter, SkBlendMode::kSrc);
   layer->Add(mock_layer);
   auto parent = std::make_shared<ClipRectLayer>(child_bounds, Clip::hardEdge);
   parent->Add(layer);
@@ -158,8 +156,8 @@
   auto layer_filter = SkImageFilters::Paint(SkPaint(SkColors::kMagenta));
   auto mock_layer1 = std::make_shared<MockLayer>(child_path1, child_paint1);
   auto mock_layer2 = std::make_shared<MockLayer>(child_path2, child_paint2);
-  auto layer = std::make_shared<BackdropFilterLayer>(
-      DlImageFilter::From(layer_filter), DlBlendMode::kSrcOver);
+  auto layer = std::make_shared<BackdropFilterLayer>(layer_filter,
+                                                     SkBlendMode::kSrcOver);
   layer->Add(mock_layer1);
   layer->Add(mock_layer2);
   auto parent =
@@ -204,10 +202,10 @@
   auto layer_filter2 = SkImageFilters::Paint(SkPaint(SkColors::kDkGray));
   auto mock_layer1 = std::make_shared<MockLayer>(child_path1, child_paint1);
   auto mock_layer2 = std::make_shared<MockLayer>(child_path2, child_paint2);
-  auto layer1 = std::make_shared<BackdropFilterLayer>(
-      DlImageFilter::From(layer_filter1), DlBlendMode::kSrcOver);
-  auto layer2 = std::make_shared<BackdropFilterLayer>(
-      DlImageFilter::From(layer_filter2), DlBlendMode::kSrcOver);
+  auto layer1 = std::make_shared<BackdropFilterLayer>(layer_filter1,
+                                                      SkBlendMode::kSrcOver);
+  auto layer2 = std::make_shared<BackdropFilterLayer>(layer_filter2,
+                                                      SkBlendMode::kSrcOver);
   layer2->Add(mock_layer2);
   layer1->Add(mock_layer1);
   layer1->Add(layer2);
@@ -245,20 +243,20 @@
 }
 
 TEST_F(BackdropFilterLayerTest, Readback) {
-  std::shared_ptr<DlImageFilter> no_filter;
-  auto layer_filter = DlBlurImageFilter(5, 5, DlTileMode::kClamp);
+  sk_sp<SkImageFilter> no_filter;
+  auto layer_filter = SkImageFilters::Paint(SkPaint(SkColors::kMagenta));
   auto initial_transform = SkMatrix();
 
   // BDF with filter always reads from surface
-  auto layer1 = std::make_shared<BackdropFilterLayer>(layer_filter.shared(),
-                                                      DlBlendMode::kSrcOver);
+  auto layer1 = std::make_shared<BackdropFilterLayer>(layer_filter,
+                                                      SkBlendMode::kSrcOver);
   preroll_context()->surface_needs_readback = false;
   layer1->Preroll(preroll_context(), initial_transform);
   EXPECT_TRUE(preroll_context()->surface_needs_readback);
 
   // BDF with no filter does not read from surface itself
   auto layer2 =
-      std::make_shared<BackdropFilterLayer>(no_filter, DlBlendMode::kSrcOver);
+      std::make_shared<BackdropFilterLayer>(no_filter, SkBlendMode::kSrcOver);
   preroll_context()->surface_needs_readback = false;
   layer2->Preroll(preroll_context(), initial_transform);
   EXPECT_FALSE(preroll_context()->surface_needs_readback);
@@ -280,20 +278,18 @@
 using BackdropLayerDiffTest = DiffContextTest;
 
 TEST_F(BackdropLayerDiffTest, BackdropLayer) {
-  auto filter = DlBlurImageFilter(10, 10, DlTileMode::kClamp);
+  auto filter = SkImageFilters::Blur(10, 10, SkTileMode::kClamp, nullptr);
 
   {
     // tests later assume 30px readback area, fail early if that's not the case
-    SkIRect readback;
-    EXPECT_EQ(filter.get_input_device_bounds(SkIRect::MakeWH(10, 10),
-                                             SkMatrix::I(), readback),
-              &readback);
+    auto readback = filter->filterBounds(SkIRect::MakeWH(10, 10), SkMatrix::I(),
+                                         SkImageFilter::kReverse_MapDirection);
     EXPECT_EQ(readback, SkIRect::MakeLTRB(-30, -30, 40, 40));
   }
 
   MockLayerTree l1(SkISize::Make(100, 100));
-  l1.root()->Add(std::make_shared<BackdropFilterLayer>(filter.shared(),
-                                                       DlBlendMode::kSrcOver));
+  l1.root()->Add(
+      std::make_shared<BackdropFilterLayer>(filter, SkBlendMode::kSrcOver));
 
   // no clip, effect over entire surface
   auto damage = DiffLayerTree(l1, MockLayerTree(SkISize::Make(100, 100)));
@@ -303,8 +299,8 @@
 
   auto clip = std::make_shared<ClipRectLayer>(SkRect::MakeLTRB(20, 20, 60, 60),
                                               Clip::hardEdge);
-  clip->Add(std::make_shared<BackdropFilterLayer>(filter.shared(),
-                                                  DlBlendMode::kSrcOver));
+  clip->Add(
+      std::make_shared<BackdropFilterLayer>(filter, SkBlendMode::kSrcOver));
   l2.root()->Add(clip);
   damage = DiffLayerTree(l2, MockLayerTree(SkISize::Make(100, 100)));
 
@@ -338,14 +334,12 @@
 }
 
 TEST_F(BackdropLayerDiffTest, BackdropLayerInvalidTransform) {
-  auto filter = DlBlurImageFilter(10, 10, DlTileMode::kClamp);
+  auto filter = SkImageFilters::Blur(10, 10, SkTileMode::kClamp, nullptr);
 
   {
     // tests later assume 30px readback area, fail early if that's not the case
-    SkIRect readback;
-    EXPECT_EQ(filter.get_input_device_bounds(SkIRect::MakeWH(10, 10),
-                                             SkMatrix::I(), readback),
-              &readback);
+    auto readback = filter->filterBounds(SkIRect::MakeWH(10, 10), SkMatrix::I(),
+                                         SkImageFilter::kReverse_MapDirection);
     EXPECT_EQ(readback, SkIRect::MakeLTRB(-30, -30, 40, 40));
   }
 
@@ -356,11 +350,11 @@
 
   auto transform_layer = std::make_shared<TransformLayer>(transform);
   l1.root()->Add(transform_layer);
-  transform_layer->Add(std::make_shared<BackdropFilterLayer>(
-      filter.shared(), DlBlendMode::kSrcOver));
+  transform_layer->Add(
+      std::make_shared<BackdropFilterLayer>(filter, SkBlendMode::kSrcOver));
 
   auto damage = DiffLayerTree(l1, MockLayerTree(SkISize::Make(100, 100)));
-  EXPECT_EQ(damage.frame_damage, SkIRect::MakeWH(100, 100));
+  EXPECT_EQ(damage.frame_damage, SkIRect::MakeWH(15, 15));
 }
 
 }  // namespace testing
diff --git a/lib/ui/compositing/scene_builder.cc b/lib/ui/compositing/scene_builder.cc
index 297e3b7..2a2810b 100644
--- a/lib/ui/compositing/scene_builder.cc
+++ b/lib/ui/compositing/scene_builder.cc
@@ -203,7 +203,7 @@
                                       int blendMode,
                                       fml::RefPtr<EngineLayer> oldLayer) {
   auto layer = std::make_shared<flutter::BackdropFilterLayer>(
-      filter->filter(), static_cast<DlBlendMode>(blendMode));
+      filter->filter()->skia_object(), static_cast<SkBlendMode>(blendMode));
   PushLayer(layer);
   EngineLayer::MakeRetained(layer_handle, layer);