Clean up prior backdrop-filter CL

This addresses reviewer comments from https://skia-review.googlesource.com/c/skia/+/239108 that were postponed to get the first CL landed ASAP.

Additionally, removes the now unnecessary applyCTMForBackdrop() function.

Bug: skia:9074
Change-Id: Ibc3ac4a4edd7e5546fa83145346869a68efc33f4
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/239440
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 519558d..357f3f5 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -885,14 +885,14 @@
 void SkCanvas::DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filter,
                                     SkBaseDevice* dst, const SkIPoint& dstOrigin,
                                     const SkMatrix& ctm) {
-    // The local bounds of the src device; all snap bounds must be intersected with this rect
+    // The local bounds of the src device; all the bounds passed to snapSpecial must be intersected
+    // with this rect.
     const SkIRect srcDevRect = SkIRect::MakeWH(src->width(), src->height());
 
-    SkPaint p;
     if (!filter) {
-        // All devices are currently axis aligned, so they only differ by their origin. This means
-        // that we only have to copy a dst-sized block of pixels out of src and translate it to the
-        // matching position relative to dst's origin.
+        // All non-filtered devices are currently axis aligned, so they only differ by their origin.
+        // This means that we only have to copy a dst-sized block of pixels out of src and translate
+        // it to the matching position relative to dst's origin.
         SkIRect snapBounds = SkIRect::MakeXYWH(dstOrigin.x() - src->getOrigin().x(),
                                                dstOrigin.y() - src->getOrigin().y(),
                                                dst->width(), dst->height());
@@ -902,6 +902,8 @@
 
         auto special = src->snapSpecial(snapBounds);
         if (special) {
+            // The image is drawn at 1-1 scale with integer translation, so no filtering is needed.
+            SkPaint p;
             dst->drawSpecial(special.get(), 0, 0, p, nullptr, SkMatrix::I());
         }
         return;
@@ -944,8 +946,8 @@
             &layerTargetBounds);
 
     // Map the required input into the root space, then make relative to the src device. This will
-    // be conservative contents required to fill a layerInputBounds-sized surface with the backdrop
-    // content (transformed back into the layer space using fromRoot).
+    // be the conservative contents required to fill a layerInputBounds-sized surface with the
+    // backdrop content (transformed back into the layer space using fromRoot).
     SkIRect backdropBounds = toRoot.mapRect(SkRect::Make(layerInputBounds)).roundOut();
     backdropBounds.offset(-src->getOrigin().x(), -src->getOrigin().y());
     if (!backdropBounds.intersect(srcDevRect)) {
@@ -962,14 +964,21 @@
         colorType = kRGBA_8888_SkColorType;
     }
     SkColorSpace* colorSpace = src->imageInfo().colorSpace();
+
+    SkPaint p;
     if (!toRoot.isIdentity()) {
+        // Drawing the temporary and final filtered image requires a higher filter quality if the
+        // 'toRoot' transformation is not identity, in order to minimize the impact on already
+        // rendered edges/content.
+        // TODO (michaelludwig) - Explore reducing this quality, identify visual tradeoffs
+        p.setFilterQuality(kHigh_SkFilterQuality);
+
         // The snapped backdrop content needs to be transformed by fromRoot into the layer space,
         // and stored in a temporary surface, which is then used as the input to the actual filter.
         auto tmpSurface = special->makeSurface(colorType, colorSpace, layerInputBounds.size());
         if (!tmpSurface) {
             return;
         }
-        p.setFilterQuality(kHigh_SkFilterQuality);
 
         auto tmpCanvas = tmpSurface->getCanvas();
         tmpCanvas->clear(SK_ColorTRANSPARENT);
@@ -980,6 +989,7 @@
         tmpCanvas->translate(-layerInputBounds.fLeft, -layerInputBounds.fTop);
         tmpCanvas->concat(fromRoot);
         tmpCanvas->translate(src->getOrigin().x(), src->getOrigin().y());
+
         tmpCanvas->drawImageRect(special->asImage(), special->subset(),
                                  SkRect::Make(backdropBounds), &p, kStrict_SrcRectConstraint);
         special = tmpSurface->makeImageSnapshot();
@@ -991,6 +1001,10 @@
         // back into the shared layer space
         layerInputBounds = backdropBounds;
         layerInputBounds.offset(src->getOrigin().x(), src->getOrigin().y());
+
+        // Similar to the unfiltered case above, when toRoot is the identity, then the final
+        // draw will be 1-1 so there is no need to increase filter quality.
+        p.setFilterQuality(kNone_SkFilterQuality);
     }
 
     // Now evaluate the filter on 'special', which contains the backdrop content mapped back into
@@ -1006,9 +1020,10 @@
     SkIPoint offset;
     special = as_IFB(filter)->filterImage(ctx).imageAndOffset(&offset);
     if (special) {
-        // Draw the filtered backdrop content into the dst device. Must adjust the reported offset
-        // to include the layerInputBounds origin shift, since the returned offset is in the coord
-        // system defined by filterCTM, and we want it to be in that of layerMatrix.
+        // Draw the filtered backdrop content into the dst device. We add layerInputBounds origin
+        // to offset because the original value in 'offset' was relative to 'filterCTM'. 'filterCTM'
+        // had subtracted the layerInputBounds origin, so adding that back makes 'offset' relative
+        // to 'layerMatrix' (what we need it to be when drawing the image by 'toRoot').
         offset += layerInputBounds.topLeft();
 
         // Manually setting the device's CTM requires accounting for the device's origin.
@@ -1022,9 +1037,9 @@
         // And because devices don't have a special-image draw function that supports arbitrary
         // matrices, we are abusing the asImage() functionality here...
         SkRect specialSrc = SkRect::Make(special->subset());
-        auto hackImageMeh = special->asImage();
+        auto looseImage = special->asImage();
         dst->drawImageRect(
-                hackImageMeh.get(), &specialSrc,
+                looseImage.get(), &specialSrc,
                 SkRect::MakeXYWH(offset.x(), offset.y(), special->width(), special->height()),
                 p, kStrict_SrcRectConstraint);
     }
diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp
index 4a76e5d..e5d7f18 100644
--- a/src/core/SkImageFilter.cpp
+++ b/src/core/SkImageFilter.cpp
@@ -524,7 +524,7 @@
 }
 
 static sk_sp<SkImageFilter> apply_ctm_to_filter(sk_sp<SkImageFilter> input, const SkMatrix& ctm,
-                                                SkMatrix* remainder, bool asBackdrop) {
+                                                SkMatrix* remainder) {
     if (ctm.isScaleTranslate() || as_IFB(input)->canHandleComplexCTM()) {
         // The filter supports the CTM, so leave it as-is and 'remainder' stores the whole CTM
         *remainder = ctm;
@@ -567,24 +567,9 @@
         remainder->setIdentity();
     }
 
-    if (asBackdrop) {
-        // In the backdrop case we also have to transform the existing device-space buffer content
-        // into the source coordinate space prior to the filtering. Non-backdrop filter inputs are
-        // already in the source space because of how the layer is drawn by SkCanvas.
-        SkMatrix invEmbed;
-        if (ctmToEmbed.invert(&invEmbed)) {
-            input = SkComposeImageFilter::Make(std::move(input),
-                            SkMatrixImageFilter::Make(invEmbed, kLow_SkFilterQuality, nullptr));
-        }
-    }
     return SkMatrixImageFilter::Make(ctmToEmbed, kLow_SkFilterQuality, input);
 }
 
 sk_sp<SkImageFilter> SkImageFilter_Base::applyCTM(const SkMatrix& ctm, SkMatrix* remainder) const {
-    return apply_ctm_to_filter(this->refMe(), ctm, remainder, false);
-}
-
-sk_sp<SkImageFilter> SkImageFilter_Base::applyCTMForBackdrop(const SkMatrix& ctm,
-                                                             SkMatrix* remainder) const {
-    return apply_ctm_to_filter(this->refMe(), ctm, remainder, true);
+    return apply_ctm_to_filter(this->refMe(), ctm, remainder);
 }
diff --git a/src/core/SkImageFilter_Base.h b/src/core/SkImageFilter_Base.h
index dff1842..5f49b7f 100644
--- a/src/core/SkImageFilter_Base.h
+++ b/src/core/SkImageFilter_Base.h
@@ -86,15 +86,6 @@
      * DEPRECATED - Should draw the results of filterImage() directly with the remainder matrix.
      */
     sk_sp<SkImageFilter> applyCTM(const SkMatrix& ctm, SkMatrix* remainder) const;
-    /**
-     * Similar to SkApplyCTMToFilter except this assumes the input content is an existing backdrop
-     * image to be filtered. As such,  the input to this filter will also be transformed by B^-1 if
-     * the filter can't support complex CTMs, since backdrop content is already in device space and
-     * must be transformed back into the CTM's local space.
-     *
-     * DEPRECATED - Should draw the results of filterImage() directly with the remainder matrix.
-     */
-    sk_sp<SkImageFilter> applyCTMForBackdrop(const SkMatrix& ctm, SkMatrix* remainder) const;
 
     uint32_t uniqueID() const { return fUniqueID; }