Pass sampling to drawImage

Bug: skia:7650
Change-Id: I050841a401610b4a68b549602e27c0bac8e62067
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/358196
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Mike Reed <reed@google.com>
diff --git a/gm/animated_gif.cpp b/gm/animated_gif.cpp
index 4a5cd1a..5a5ba51 100644
--- a/gm/animated_gif.cpp
+++ b/gm/animated_gif.cpp
@@ -213,7 +213,7 @@
     void onDraw(SkCanvas* canvas) override {
         canvas->scale(0.25f, 0.25f);
         for (auto& p : fPlayers) {
-            canvas->drawImage(p->getFrame(), 0, 0, nullptr);
+            canvas->drawImage(p->getFrame(), 0, 0);
             canvas->translate(p->dimensions().width(), 0);
         }
     }
@@ -285,7 +285,7 @@
 
 
             auto image = fPlayer->getFrame();
-            canvas->drawImage(image, 0, 0, nullptr);
+            canvas->drawImage(image, 0, 0);
             duration += fFrameInfos[frame].fDuration;
             fPlayer->seek(duration);
         }
diff --git a/gm/animated_image_orientation.cpp b/gm/animated_image_orientation.cpp
index e969d7f..efb0d0c 100644
--- a/gm/animated_image_orientation.cpp
+++ b/gm/animated_image_orientation.cpp
@@ -93,7 +93,7 @@
                     canvas->drawPicture(pic);
                 } else {
                     auto image = animatedImage->getCurrentFrame();
-                    canvas->drawImage(image, 0, 0, nullptr);
+                    canvas->drawImage(image, 0, 0);
                 }
             };
             for (float scale : { 1.25f, 1.0f, .75f, .5f }) {
diff --git a/gm/asyncrescaleandread.cpp b/gm/asyncrescaleandread.cpp
index c9f91bc..89bfb57 100644
--- a/gm/asyncrescaleandread.cpp
+++ b/gm/asyncrescaleandread.cpp
@@ -209,7 +209,7 @@
         }
         SkPaint paint;
         paint.setBlendMode(SkBlendMode::kSrc);
-        surface->getCanvas()->drawImage(image, 0, 0, &paint);
+        surface->getCanvas()->drawImage(image, 0, 0, SkSamplingOptions(), &paint);
         return do_rescale_grid(canvas, surface.get(), dContext, srcRect, newSize,
                                doYUV420, errorMsg);
     } else if (dContext) {
diff --git a/gm/bleed.cpp b/gm/bleed.cpp
index 656f58a..6a2506f 100644
--- a/gm/bleed.cpp
+++ b/gm/bleed.cpp
@@ -34,7 +34,7 @@
 /** Creates an image with two one-pixel wide borders around a checkerboard. The checkerboard is 2x2
     checks where each check has as many pixels as is necessary to fill the interior. It returns
     the image and a src rect that bounds the checkerboard portion. */
-std::tuple<sk_sp<SkImage>, SkIRect> make_ringed_image(int width, int height) {
+std::tuple<sk_sp<SkImage>, SkRect> make_ringed_image(int width, int height) {
 
     // These are kRGBA_8888_SkColorType values.
     static constexpr uint32_t kOuterRingColor = 0xFFFF0000,
@@ -102,7 +102,7 @@
         scanline[x] = kOuterRingColor;
     }
     bitmap.setImmutable();
-    return {bitmap.asImage(), {2, 2, width - 2, height - 2}};
+    return {bitmap.asImage(), SkRect::Make({2, 2, width - 2, height - 2})};
 }
 
 /**
@@ -121,95 +121,95 @@
     SkString onShortName() override { return fShortName; }
     SkISize onISize() override { return SkISize::Make(800, 1000); }
 
-    void drawImage(SkCanvas* canvas, sk_sp<SkImage> image,
-                   SkIRect srcRect, SkRect dstRect, SkPaint* paint) {
+    void drawImage(SkCanvas* canvas, sk_sp<SkImage> image, SkRect srcRect, SkRect dstRect,
+                   const SkSamplingOptions& sampling, SkPaint* paint) {
         if (fBatch) {
             SkCanvas::ImageSetEntry imageSetEntry[1];
             imageSetEntry[0].fImage = image;
-            imageSetEntry[0].fSrcRect = SkRect::Make(srcRect);
+            imageSetEntry[0].fSrcRect = srcRect;
             imageSetEntry[0].fDstRect = dstRect;
             imageSetEntry[0].fAAFlags = paint->isAntiAlias() ? SkCanvas::kAll_QuadAAFlags
                                                              : SkCanvas::kNone_QuadAAFlags;
             canvas->experimental_DrawEdgeAAImageSet(imageSetEntry, SK_ARRAY_COUNT(imageSetEntry),
                                                     /*dstClips=*/nullptr,
                                                     /*preViewMatrices=*/nullptr,
-                                                    paint, fConstraint);
+                                                    sampling, paint, fConstraint);
         } else {
-            canvas->drawImageRect(image.get(), srcRect, dstRect, paint, fConstraint);
+            canvas->drawImageRect(image.get(), srcRect, dstRect, sampling, paint, fConstraint);
         }
     }
 
     // Draw the area of interest of the small image
-    void drawCase1(SkCanvas* canvas, int transX, int transY, bool aa, SkFilterQuality filter) {
+    void drawCase1(SkCanvas* canvas, int transX, int transY, bool aa,
+                   const SkSamplingOptions& sampling) {
         SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY),
                                       SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
 
         SkPaint paint;
-        paint.setFilterQuality(filter);
         paint.setColor(SK_ColorBLUE);
         paint.setAntiAlias(aa);
 
-        drawImage(canvas, fSmallImage, fSmallSrcRect, dst, &paint);
+        drawImage(canvas, fSmallImage, fSmallSrcRect, dst, sampling, &paint);
     }
 
     // Draw the area of interest of the large image
-    void drawCase2(SkCanvas* canvas, int transX, int transY, bool aa, SkFilterQuality filter) {
+    void drawCase2(SkCanvas* canvas, int transX, int transY, bool aa,
+                   const SkSamplingOptions& sampling) {
         SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY),
                                       SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
 
         SkPaint paint;
-        paint.setFilterQuality(filter);
         paint.setColor(SK_ColorBLUE);
         paint.setAntiAlias(aa);
 
-        drawImage(canvas, fBigImage, fBigSrcRect, dst, &paint);
+        drawImage(canvas, fBigImage, fBigSrcRect, dst, sampling, &paint);
     }
 
     // Draw upper-left 1/4 of the area of interest of the large image
-    void drawCase3(SkCanvas* canvas, int transX, int transY, bool aa, SkFilterQuality filter) {
-        SkIRect src = SkIRect::MakeXYWH(fBigSrcRect.fLeft,
-                                        fBigSrcRect.fTop,
-                                        fBigSrcRect.width()/2,
-                                        fBigSrcRect.height()/2);
+    void drawCase3(SkCanvas* canvas, int transX, int transY, bool aa,
+                   const SkSamplingOptions& sampling) {
+        SkRect src = SkRect::MakeXYWH(fBigSrcRect.fLeft,
+                                      fBigSrcRect.fTop,
+                                      fBigSrcRect.width()/2,
+                                      fBigSrcRect.height()/2);
         SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY),
                                       SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
 
         SkPaint paint;
-        paint.setFilterQuality(filter);
         paint.setColor(SK_ColorBLUE);
         paint.setAntiAlias(aa);
 
-        drawImage(canvas, fBigImage, src, dst, &paint);
+        drawImage(canvas, fBigImage, src, dst, sampling, &paint);
     }
 
     // Draw the area of interest of the small image with a normal blur
-    void drawCase4(SkCanvas* canvas, int transX, int transY, bool aa, SkFilterQuality filter) {
+    void drawCase4(SkCanvas* canvas, int transX, int transY, bool aa,
+                   const SkSamplingOptions& sampling) {
         SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY),
                                       SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
 
         SkPaint paint;
-        paint.setFilterQuality(filter);
         paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle,
                                                    SkBlurMask::ConvertRadiusToSigma(3)));
         paint.setColor(SK_ColorBLUE);
         paint.setAntiAlias(aa);
 
-        drawImage(canvas, fSmallImage, fSmallSrcRect, dst, &paint);
+        drawImage(canvas, fSmallImage, fSmallSrcRect, dst, sampling, &paint);
     }
 
     // Draw the area of interest of the small image with a outer blur
-    void drawCase5(SkCanvas* canvas, int transX, int transY, bool aa, SkFilterQuality filter) {
+    void drawCase5(SkCanvas* canvas, int transX, int transY, bool aa,
+                   const SkSamplingOptions& sampling) {
         SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY),
                                       SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
 
         SkPaint paint;
-        paint.setFilterQuality(filter);
         paint.setMaskFilter(SkMaskFilter::MakeBlur(kOuter_SkBlurStyle,
                                                    SkBlurMask::ConvertRadiusToSigma(7)));
         paint.setColor(SK_ColorBLUE);
         paint.setAntiAlias(aa);
 
-        drawImage(canvas, fSmallImage, fSmallSrcRect, dst, &paint);
+        drawImage(canvas, fSmallImage, fSmallSrcRect, dst, sampling, &paint);
     }
 
     void onOnceBeforeDraw() override {
@@ -240,6 +240,10 @@
         m.preScale(0.2f, 0.2f);
         matrices.push_back(m);
 
+        const SkSamplingOptions none(SkFilterMode::kNearest);
+        const SkSamplingOptions  low(SkFilterMode::kLinear);
+        const SkSamplingOptions high({1.0f/3, 1.0f/3});
+
         SkScalar maxX = 0;
         for (bool antiAlias : {false, true}) {
             canvas->save();
@@ -249,18 +253,18 @@
                 canvas->concat(matrix);
 
                 // First draw a column with no filtering
-                this->drawCase1(canvas, kCol0X, kRow0Y, antiAlias, kNone_SkFilterQuality);
-                this->drawCase2(canvas, kCol0X, kRow1Y, antiAlias, kNone_SkFilterQuality);
-                this->drawCase3(canvas, kCol0X, kRow2Y, antiAlias, kNone_SkFilterQuality);
-                this->drawCase4(canvas, kCol0X, kRow3Y, antiAlias, kNone_SkFilterQuality);
-                this->drawCase5(canvas, kCol0X, kRow4Y, antiAlias, kNone_SkFilterQuality);
+                this->drawCase1(canvas, kCol0X, kRow0Y, antiAlias, none);
+                this->drawCase2(canvas, kCol0X, kRow1Y, antiAlias, none);
+                this->drawCase3(canvas, kCol0X, kRow2Y, antiAlias, none);
+                this->drawCase4(canvas, kCol0X, kRow3Y, antiAlias, none);
+                this->drawCase5(canvas, kCol0X, kRow4Y, antiAlias, none);
 
                 // Then draw a column with low filtering
-                this->drawCase1(canvas, kCol1X, kRow0Y, antiAlias, kLow_SkFilterQuality);
-                this->drawCase2(canvas, kCol1X, kRow1Y, antiAlias, kLow_SkFilterQuality);
-                this->drawCase3(canvas, kCol1X, kRow2Y, antiAlias, kLow_SkFilterQuality);
-                this->drawCase4(canvas, kCol1X, kRow3Y, antiAlias, kLow_SkFilterQuality);
-                this->drawCase5(canvas, kCol1X, kRow4Y, antiAlias, kLow_SkFilterQuality);
+                this->drawCase1(canvas, kCol1X, kRow0Y, antiAlias, low);
+                this->drawCase2(canvas, kCol1X, kRow1Y, antiAlias, low);
+                this->drawCase3(canvas, kCol1X, kRow2Y, antiAlias, low);
+                this->drawCase4(canvas, kCol1X, kRow3Y, antiAlias, low);
+                this->drawCase5(canvas, kCol1X, kRow4Y, antiAlias, low);
 
                 // Then draw a column with high filtering. Skip it if in kStrict mode and MIP
                 // mapping will be used. On GPU we allow bleeding at non-base levels because
@@ -268,11 +272,11 @@
                 SkScalar scales[2];
                 SkAssertResult(matrix.getMinMaxScales(scales));
                 if (fConstraint != SkCanvas::kStrict_SrcRectConstraint || scales[0] >= 1.f) {
-                    this->drawCase1(canvas, kCol2X, kRow0Y, antiAlias, kHigh_SkFilterQuality);
-                    this->drawCase2(canvas, kCol2X, kRow1Y, antiAlias, kHigh_SkFilterQuality);
-                    this->drawCase3(canvas, kCol2X, kRow2Y, antiAlias, kHigh_SkFilterQuality);
-                    this->drawCase4(canvas, kCol2X, kRow3Y, antiAlias, kHigh_SkFilterQuality);
-                    this->drawCase5(canvas, kCol2X, kRow4Y, antiAlias, kHigh_SkFilterQuality);
+                    this->drawCase1(canvas, kCol2X, kRow0Y, antiAlias, high);
+                    this->drawCase2(canvas, kCol2X, kRow1Y, antiAlias, high);
+                    this->drawCase3(canvas, kCol2X, kRow2Y, antiAlias, high);
+                    this->drawCase4(canvas, kCol2X, kRow3Y, antiAlias, high);
+                    this->drawCase5(canvas, kCol2X, kRow4Y, antiAlias, high);
                 }
 
                 SkPoint innerCorners[] = {{0, 0}, {0, kBottom}, {kWidth, kBottom}, {kWidth, 0}};
@@ -311,8 +315,8 @@
     SkString fShortName;
     sk_sp<SkImage> fBigImage;
     sk_sp<SkImage> fSmallImage;
-    SkIRect fBigSrcRect;
-    SkIRect fSmallSrcRect;
+    SkRect fBigSrcRect;
+    SkRect fSmallSrcRect;
     SkCanvas::SrcRectConstraint fConstraint;
     bool fBatch = false;
     using INHERITED = GM;
diff --git a/gm/blurs.cpp b/gm/blurs.cpp
index 8ca356f..e0ddb57 100644
--- a/gm/blurs.cpp
+++ b/gm/blurs.cpp
@@ -127,7 +127,7 @@
     canvas->clear(0xFF88FF88);
     if (auto image = GetResourceAsImage("images/mandrill_512_q075.jpg")) {
         canvas->scale(0.25, 0.25);
-        canvas->drawImage(image, 256, 256, &paint);
+        canvas->drawImage(image, 256, 256, SkSamplingOptions(), &paint);
     }
 }
 
diff --git a/gm/complexclip.cpp b/gm/complexclip.cpp
index c8a5220..84bebe8 100644
--- a/gm/complexclip.cpp
+++ b/gm/complexclip.cpp
@@ -217,7 +217,7 @@
     SkPaint p;
 
     canvas->translate(10, 10);
-    canvas->drawImage(img, 0, 0, nullptr);
+    canvas->drawImage(img, 0, 0);
 
     canvas->save();
     canvas->translate(img->width() + 10, 0);
@@ -240,7 +240,7 @@
     SkMatrix lm = SkMatrix::Scale(1.0f/5, 1.0f/5);
     canvas->clipShader(img->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat,
                                        SkSamplingOptions(), lm));
-    canvas->drawImage(img, 0, 0, nullptr);
+    canvas->drawImage(img, 0, 0);
 
     canvas->restore();
     canvas->restore();
diff --git a/gm/crosscontextimage.cpp b/gm/crosscontextimage.cpp
index e3c60d0..1490fef 100644
--- a/gm/crosscontextimage.cpp
+++ b/gm/crosscontextimage.cpp
@@ -60,9 +60,9 @@
                           0, 0);
         canvas->translate(128, 0);
 
-        SkPaint paint;
-        paint.setFilterQuality(kMedium_SkFilterQuality);
-        canvas->drawImageRect(images[i], SkRect::MakeWH(128, 128), &paint);
+        canvas->drawImageRect(images[i], SkRect::MakeWH(128, 128),
+                              SkSamplingOptions(SkFilterMode::kLinear,
+                                                SkMipmapMode::kLinear));
 
         canvas->restore();
         canvas->translate(256 + 10, 0);
diff --git a/gm/hsl.cpp b/gm/hsl.cpp
index 0a6441e..7bd52ca 100644
--- a/gm/hsl.cpp
+++ b/gm/hsl.cpp
@@ -247,7 +247,7 @@
             p.setShader(nullptr);
             p.setBlendMode(mode);
             p.setAlphaf(src_a);
-            canvas->drawImageRect(src, r, &p);
+            canvas->drawImageRect(src, r, SkSamplingOptions(), &p);
 
             canvas->translate(r.width() + 10, 0);
         }
diff --git a/gm/imageblurrepeatmode.cpp b/gm/imageblurrepeatmode.cpp
index 7373c88..1376efc 100644
--- a/gm/imageblurrepeatmode.cpp
+++ b/gm/imageblurrepeatmode.cpp
@@ -155,14 +155,14 @@
 
     // Draw the blurred image once
     canvas->translate(0, 50);
-    canvas->drawImage(img, 0, 0, &paint);
+    canvas->drawImage(img, 0, 0, SkSamplingOptions(), &paint);
 
     // Draw the blurred image with a clip positioned such that the draw would be excluded except
     // that the image filter causes it to intersect with the clip. Ideally should look like the
     // left image, but clipped to the debug-black rectangle (Narrator: it does not look like that).
     canvas->translate(110, 0);
     canvas->clipRect(SkRect::MakeXYWH(0, -30, 100, 10));
-    canvas->drawImage(img, 0, 0, &paint);
+    canvas->drawImage(img, 0, 0, SkSamplingOptions(), &paint);
 
     // Visualize the clip
     SkPaint line;
diff --git a/gm/imagefilterstransformed.cpp b/gm/imagefilterstransformed.cpp
index 83fca2a..75566aa 100644
--- a/gm/imagefilterstransformed.cpp
+++ b/gm/imagefilterstransformed.cpp
@@ -207,7 +207,7 @@
 
         SkPaint p;
         p.setImageFilter(filter);
-        canvas->drawImage(fImage.get(), 128, 128, &p);
+        canvas->drawImage(fImage.get(), 128, 128, SkSamplingOptions(), &p);
     }
 
 private:
@@ -264,7 +264,7 @@
         canvas->clipRect(SkRect::MakeIWH(256, 256));
         canvas->scale(0.5f, 0.5f);
         canvas->translate(128, 128);
-        canvas->drawImage(fImage, 0, 0, &p);
+        canvas->drawImage(fImage, 0, 0, SkSamplingOptions(), &p);
         canvas->restore();
     }
 
diff --git a/gm/imagemakewithfilter.cpp b/gm/imagemakewithfilter.cpp
index 03b214f..f561e21 100644
--- a/gm/imagemakewithfilter.cpp
+++ b/gm/imagemakewithfilter.cpp
@@ -216,7 +216,8 @@
         // Resize to 100x100
         surface->getCanvas()->drawImageRect(
                 colorImage, SkRect::MakeWH(colorImage->width(), colorImage->height()),
-                SkRect::MakeWH(info.width(), info.height()), nullptr);
+                SkRect::MakeWH(info.width(), info.height()), SkSamplingOptions(), nullptr,
+                                            SkCanvas::kStrict_SrcRectConstraint);
         fMainImage = surface->makeImageSnapshot();
 
         ToolUtils::draw_checkerboard(surface->getCanvas());
@@ -319,7 +320,7 @@
                 // filtered result.
                 SkPaint alpha;
                 alpha.setAlphaf(0.3f);
-                canvas->drawImage(mainImage, 0, 0, &alpha);
+                canvas->drawImage(mainImage, 0, 0, SkSamplingOptions(), &alpha);
 
                 this->drawImageWithFilter(canvas, mainImage, auxImage, filters[i], clipBound,
                                           subset, &outSubset);
@@ -368,7 +369,9 @@
             canvas->saveLayer(nullptr, &paint);
 
             // Draw the original subset of the image
-            canvas->drawImageRect(mainImage, subset, SkRect::Make(subset), nullptr);
+            SkRect r = SkRect::Make(subset);
+            canvas->drawImageRect(mainImage, r, r, SkSamplingOptions(),
+                                  nullptr, SkCanvas::kStrict_SrcRectConstraint);
 
             *dstRect = subset;
         } else {
@@ -385,7 +388,9 @@
 
             *dstRect = SkIRect::MakeXYWH(offset.x(), offset.y(),
                                          outSubset.width(), outSubset.height());
-            canvas->drawImageRect(result, outSubset, SkRect::Make(*dstRect), nullptr);
+            canvas->drawImageRect(result, SkRect::Make(outSubset), SkRect::Make(*dstRect),
+                                  SkSamplingOptions(), nullptr,
+                                  SkCanvas::kStrict_SrcRectConstraint);
         }
     }
 
diff --git a/gm/lattice.cpp b/gm/lattice.cpp
index 21d3d8b..75f733b 100644
--- a/gm/lattice.cpp
+++ b/gm/lattice.cpp
@@ -125,7 +125,7 @@
             { 200, 200, },
         };
 
-        canvas->drawImage(image, 10, 10, nullptr);
+        canvas->drawImage(image, 10, 10);
 
         SkScalar x = SkIntToScalar(100);
         SkScalar y = SkIntToScalar(100);
@@ -299,7 +299,7 @@
 
         sk_sp<SkImage> image = makeImage(canvas, padLeft, padTop, padRight, padBottom);
 
-        canvas->drawImage(image, 10, 10, nullptr);
+        canvas->drawImage(image, 10, 10);
 
         SkCanvas::Lattice lattice;
         lattice.fXCount = 2;
diff --git a/gm/overdrawcanvas.cpp b/gm/overdrawcanvas.cpp
index b24d0b6..a695101 100644
--- a/gm/overdrawcanvas.cpp
+++ b/gm/overdrawcanvas.cpp
@@ -52,7 +52,7 @@
     // Draw overdraw colors to the canvas.  The color filter will convert counts to colors.
     SkPaint paint;
     paint.setColorFilter(SkOverdrawColorFilter::MakeWithSkColors(kOverdrawColors));
-    canvas->drawImage(counts.get(), 0.0f, 0.0f, &paint);
+    canvas->drawImage(counts.get(), 0.0f, 0.0f, SkSamplingOptions(), &paint);
     canvas->drawString("This is some text:", 180, 300, SkFont(), SkPaint());
 }
 
diff --git a/gm/perspshaders.cpp b/gm/perspshaders.cpp
index bcc9531..96d2433 100644
--- a/gm/perspshaders.cpp
+++ b/gm/perspshaders.cpp
@@ -56,9 +56,8 @@
     }
 
     void onOnceBeforeDraw() override {
-        fBitmap = ToolUtils::create_checkerboard_bitmap(
+        fBitmapImage = ToolUtils::create_checkerboard_image(
                 kCellSize, kCellSize, SK_ColorBLUE, SK_ColorYELLOW, kCellSize / 10);
-        fBitmap.setImmutable();
 
         SkPoint pts1[] = {
             { 0, 0 },
@@ -89,13 +88,12 @@
         fPath.close();
     }
 
-    void drawRow(SkCanvas* canvas, SkFilterQuality filterQ) {
+    void drawRow(SkCanvas* canvas, const SkSamplingOptions& sampling) {
         SkPaint filterPaint;
-        filterPaint.setFilterQuality(filterQ);
         filterPaint.setAntiAlias(fDoAA);
 
         SkPaint pathPaint;
-        pathPaint.setShader(fBitmap.makeShader(SkSamplingOptions(filterQ)));
+        pathPaint.setShader(fBitmapImage->makeShader(sampling));
         pathPaint.setAntiAlias(fDoAA);
 
         SkPaint gradPaint1;
@@ -111,13 +109,13 @@
 
         canvas->save();
         canvas->concat(fPerspMatrix);
-        canvas->drawBitmapRect(fBitmap, r, &filterPaint);
+        canvas->drawImageRect(fBitmapImage, r, sampling, &filterPaint);
         canvas->restore();
 
         canvas->translate(SkIntToScalar(kCellSize), 0);
         canvas->save();
         canvas->concat(fPerspMatrix);
-        canvas->drawImage(fImage.get(), 0, 0, &filterPaint);
+        canvas->drawImage(fImage.get(), 0, 0, sampling, &filterPaint);
         canvas->restore();
 
         canvas->translate(SkIntToScalar(kCellSize), 0);
@@ -152,13 +150,14 @@
             fImage = make_image(canvas, kCellSize, kCellSize);
         }
 
-        this->drawRow(canvas, kNone_SkFilterQuality);
+        this->drawRow(canvas, SkSamplingOptions(SkFilterMode::kNearest));
         canvas->translate(0, SkIntToScalar(kCellSize));
-        this->drawRow(canvas, kLow_SkFilterQuality);
+        this->drawRow(canvas, SkSamplingOptions(SkFilterMode::kLinear));
         canvas->translate(0, SkIntToScalar(kCellSize));
-        this->drawRow(canvas, kMedium_SkFilterQuality);
+        this->drawRow(canvas, SkSamplingOptions(SkFilterMode::kLinear,
+                                                SkMipmapMode::kNearest));
         canvas->translate(0, SkIntToScalar(kCellSize));
-        this->drawRow(canvas, kHigh_SkFilterQuality);
+        this->drawRow(canvas, SkSamplingOptions({1.0f/3, 1.0f/3}));
         canvas->translate(0, SkIntToScalar(kCellSize));
     }
 private:
@@ -172,7 +171,7 @@
     sk_sp<SkShader> fLinearGrad2;
     SkMatrix        fPerspMatrix;
     sk_sp<SkImage>  fImage;
-    SkBitmap        fBitmap;
+    sk_sp<SkImage>  fBitmapImage;
 
     using INHERITED = GM;
 };
diff --git a/gm/readpixels.cpp b/gm/readpixels.cpp
index f238cdf..fcc52a2 100644
--- a/gm/readpixels.cpp
+++ b/gm/readpixels.cpp
@@ -124,7 +124,7 @@
     // Now that we have called readPixels(), dump the raw pixels into an srgb image.
     sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
     sk_sp<SkImage> raw = SkImage::MakeRasterData(dstInfo.makeColorSpace(srgb), data, rowBytes);
-    canvas->drawImage(raw.get(), 0.0f, 0.0f, nullptr);
+    canvas->drawImage(raw.get(), 0.0f, 0.0f);
 }
 
 class ReadPixelsGM : public skiagm::GM {
diff --git a/gm/runtimecolorfilter.cpp b/gm/runtimecolorfilter.cpp
index 5857702..091d1af 100644
--- a/gm/runtimecolorfilter.cpp
+++ b/gm/runtimecolorfilter.cpp
@@ -109,7 +109,7 @@
         SkPaint p;
         sk_sp<SkColorFilter> input = nullptr;
         p.setColorFilter(effect->makeColorFilter(nullptr, &input, 1));
-        canvas->drawImage(img, 0, 0, &p);
+        canvas->drawImage(img, 0, 0, SkSamplingOptions(), &p);
         canvas->translate(256, 0);
     };
 
diff --git a/gm/savelayer.cpp b/gm/savelayer.cpp
index 3d9bd50..dbb6676 100644
--- a/gm/savelayer.cpp
+++ b/gm/savelayer.cpp
@@ -47,7 +47,7 @@
 // restore with kPlus mode, which should show the mandrill super-bright on the outside, but
 // normal where we punched the hole.
 DEF_SIMPLE_GM(savelayer_initfromprev, canvas, 256, 256) {
-    canvas->drawImage(GetResourceAsImage("images/mandrill_256.png"), 0, 0, nullptr);
+    canvas->drawImage(GetResourceAsImage("images/mandrill_256.png"), 0, 0);
 
     SkCanvas::SaveLayerRec rec;
     SkPaint paint;
@@ -88,7 +88,7 @@
             canvas->translate(x * 200.f, y * 200.f);
 
             SkCanvas::SaveLayerRec rec(&r, &layerPaint, yflags[y] | xflags[x]);
-            canvas->drawImageRect(image, r, nullptr);
+            canvas->drawImageRect(image, r, SkSamplingOptions(), nullptr);
             proc(canvas, rec);
 
             canvas->restore();
diff --git a/gm/surface.cpp b/gm/surface.cpp
index 9af76d9..a0d96af 100644
--- a/gm/surface.cpp
+++ b/gm/surface.cpp
@@ -148,7 +148,7 @@
         drawInto(surf->getCanvas());
 
         sk_sp<SkImage> image(surf->makeImageSnapshot());
-        canvas->drawImage(image, 10, 10, nullptr);
+        canvas->drawImage(image, 10, 10);
 
         auto surf2(surf->makeSurface(info));
         drawInto(surf2->getCanvas());
@@ -157,7 +157,7 @@
         SkASSERT(equal(surf->props(), surf2->props()));
 
         sk_sp<SkImage> image2(surf2->makeImageSnapshot());
-        canvas->drawImage(image2.get(), 10 + SkIntToScalar(image->width()) + 10, 10, nullptr);
+        canvas->drawImage(image2.get(), 10 + SkIntToScalar(image->width()) + 10, 10);
     }
 
 private:
@@ -182,7 +182,7 @@
     surf->getCanvas()->clear(SK_ColorBLUE);
 
     // expect to see two rects: blue | red
-    canvas->drawImage(surf->makeImageSnapshot(), 0, 0, nullptr);
+    canvas->drawImage(surf->makeImageSnapshot(), 0, 0);
 }
 
 DEF_SIMPLE_GM(copy_on_write_savelayer, canvas, 256, 256) {
@@ -203,7 +203,7 @@
     surf->getCanvas()->restore();
 
     // expect to see two rects: blue blended on red
-    canvas->drawImage(surf->makeImageSnapshot(), 0, 0, nullptr);
+    canvas->drawImage(surf->makeImageSnapshot(), 0, 0);
 }
 
 DEF_SIMPLE_GM(surface_underdraw, canvas, 256, 256) {
@@ -258,7 +258,7 @@
         paint.setBlendMode(SkBlendMode::kDstOver);
         surf->getCanvas()->drawImage(saveImg,
                                      SkIntToScalar(subset.left()), SkIntToScalar(subset.top()),
-                                     &paint);
+                                     SkSamplingOptions(), &paint);
     }
 
     // show it on screen
diff --git a/gm/textblobmixedsizes.cpp b/gm/textblobmixedsizes.cpp
index edba3b8..4354607 100644
--- a/gm/textblobmixedsizes.cpp
+++ b/gm/textblobmixedsizes.cpp
@@ -176,7 +176,7 @@
             SkAutoCanvasRestore acr(inputCanvas, true);
             // since we prepended this matrix already, we blit using identity
             inputCanvas->resetMatrix();
-            inputCanvas->drawImage(surface->makeImageSnapshot().get(), 0, 0, nullptr);
+            inputCanvas->drawImage(surface->makeImageSnapshot().get(), 0, 0);
         }
     }
 
diff --git a/gm/verylargebitmap.cpp b/gm/verylargebitmap.cpp
index c5b8e10..2cade42 100644
--- a/gm/verylargebitmap.cpp
+++ b/gm/verylargebitmap.cpp
@@ -64,19 +64,20 @@
 
     canvas->save();
     canvas->clipRect(dstRect);
-    canvas->drawImage(image, 0, 0, nullptr);
+    canvas->drawImage(image, 0, 0);
     canvas->restore();
     canvas->drawRect(dstRect, borderPaint);
 
     dstRect.offset(SkIntToScalar(150), 0);
     int hw = width / 2;
     int hh = height / 2;
-    SkIRect subset = SkIRect::MakeLTRB(hw - 64, hh - 32, hw + 64, hh + 32);
-    canvas->drawImageRect(image, subset, dstRect, nullptr);
+    SkRect subset = SkRect::MakeLTRB(hw - 64, hh - 32, hw + 64, hh + 32);
+    canvas->drawImageRect(image, subset, dstRect, SkSamplingOptions(), nullptr,
+                          SkCanvas::kStrict_SrcRectConstraint);
     canvas->drawRect(dstRect, borderPaint);
 
     dstRect.offset(SkIntToScalar(150), 0);
-    canvas->drawImageRect(image, dstRect, nullptr);
+    canvas->drawImageRect(image, dstRect, SkSamplingOptions(), nullptr);
     canvas->drawRect(dstRect, borderPaint);
 }