Reland "Combine snapBackImage and snapSpecial"

This reverts commit fd849a537a4bbb38114f94be8ffd0d359ebfa6f3.

Reason for revert: Magnifier filter fixed, layout tests shouldn't break on this change anymore.

Original change's description:
> Revert "Combine snapBackImage and snapSpecial"
> 
> This reverts commit 45739aa1d8ca1b58e354fe82776d2264936c2f72.
> 
> Reason for revert: Looks like the magnifier filter doesn't handle subset origins correctly either, not caught by our tests, but does in layout tests.
> 
> Original change's description:
> > Combine snapBackImage and snapSpecial
> > 
> > Previously, snapBackImage always made a copy since that is required for
> > its use in saveBehind(). Backdrop filters also used snapBackImage because
> > it relied on its subset SkIRect argument to avoid using the entire
> > layer as input to the backdrop filter. The regular snapSpecial() originally
> > did not take a subset at all. The GPU implementations of snapSpecial()
> > and snapBackImage() were very similar. This merges them into a single call
> > that takes a subset SkIRect and a boolean to control if the copy is required.
> > 
> > Only saveBehind() requires that the copy is made, due to how it bypasses
> > the regular copy-on-write behavior managed by SkCanvas and SkSurface. The
> > no-argument saveSpecial() is still provided, but it is defined to just snap
> > the bounds of the device.
> > 
> > Flutter noticed a fairly serious performance regression on iOS that went
> > back to this CL: https://github.com/google/skia/commit/08b260c27b519ac8fb17b3ff8ddccf4a2ac0e278. It was determined that the only significant change in
> > behavior that was active given their minimum working example was switching
> > from snapSpecial() to snapBackImage(). Hopefully moving to a snapSpecial that
> > takes a subset, but doesn't copy when there is a texture already available
> > will restore the performance.
> > 
> > Bug: skia:9283, https://github.com/flutter/flutter/issues/36352, https://github.com/flutter/flutter/issues/37541, https://github.com/flutter/flutter/issues/36064
> > Change-Id: I448f8886347a1e0f4da8f61279744bb9254f7752
> > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/237127
> > Commit-Queue: Michael Ludwig <michaelludwig@google.com>
> > Reviewed-by: Brian Salomon <bsalomon@google.com>
> > Reviewed-by: Brian Osman <brianosman@google.com>
> 
> TBR=bsalomon@google.com,brianosman@google.com,michaelludwig@google.com
> 
> Change-Id: I7fd897da8a50b2fc0079e2aed9b6ad4bed6d3879
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: skia:9283, https://github.com/flutter/flutter/issues/36352, https://github.com/flutter/flutter/issues/37541, https://github.com/flutter/flutter/issues/36064
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/237616
> Reviewed-by: Michael Ludwig <michaelludwig@google.com>
> Commit-Queue: Michael Ludwig <michaelludwig@google.com>

TBR=bsalomon@google.com,brianosman@google.com,michaelludwig@google.com

Change-Id: Ieeb7e8c3b3261d9e900fea6e83a5726b4b6c86cd
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:9283, https://github.com/flutter/flutter/issues/36352, https://github.com/flutter/flutter/issues/37541, https://github.com/flutter/flutter/issues/36064
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/237904
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index ff9970e..7c05e11 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -920,7 +920,7 @@
         p.setImageFilter(modifiedFilter->makeWithLocalMatrix(localCTM));
     }
 
-    auto special = src->snapBackImage(snapBounds);
+    auto special = src->snapSpecial(snapBounds);
     if (special) {
         dst->drawSpecial(special.get(), x, y, p, nullptr, SkMatrix::I());
     }
@@ -1111,7 +1111,11 @@
     // need the bounds relative to the device itself
     devBounds.offset(-device->fOrigin.fX, -device->fOrigin.fY);
 
-    auto backImage = device->snapBackImage(devBounds);
+    // This is getting the special image from the current device, which is then drawn into (both by
+    // a client, and the drawClippedToSaveBehind below). Since this is not saving a layer, with its
+    // own device, we need to explicitly copy the back image contents so that its original content
+    // is available when we splat it back later during restore.
+    auto backImage = device->snapSpecial(devBounds, /* copy */ true);
     if (!backImage) {
         return;
     }