Add SkSpecialImage::extractSubset & NewFromPixmap

This is calved off of: https://codereview.chromium.org/1785643003/ (Switch SkBlurImageFilter over to new onFilterImage interface)

This now relies on: https://codereview.chromium.org/1813483002/ (ImagePixelLocker now manually allocates SkPixmap) to clean up the uses of SkAutoPixmapStorage in Chromium

GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1787883002

Committed: https://skia.googlesource.com/skia/+/250581493a0859987e482810879e85e5ac2dc002

Review URL: https://codereview.chromium.org/1787883002
diff --git a/src/core/SkSpecialImage.cpp b/src/core/SkSpecialImage.cpp
index a55fe65..b17d5d4 100644
--- a/src/core/SkSpecialImage.cpp
+++ b/src/core/SkSpecialImage.cpp
@@ -20,7 +20,7 @@
 
     virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const = 0;
 
-    virtual bool testingOnlyOnPeekPixels(SkPixmap*) const { return false; }
+    virtual bool onPeekPixels(SkPixmap*) const { return false; }
 
     virtual GrTexture* onPeekTexture() const { return nullptr; }
 
@@ -29,7 +29,9 @@
     // Delete this entry point ASAP (see skbug.com/4965)
     virtual bool getBitmapDeprecated(SkBitmap* result) const = 0;
 
-    virtual SkSpecialSurface* onNewSurface(const SkImageInfo& info) const { return nullptr; }
+    virtual SkSpecialSurface* onNewSurface(const SkImageInfo& info) const = 0;
+
+    virtual SkSpecialImage* onExtractSubset(const SkIRect& subset) const = 0;
 
 private:
     typedef SkSpecialImage INHERITED;
@@ -44,8 +46,8 @@
     return as_SIB(this)->onDraw(canvas, x, y, paint);
 }
 
-bool SkSpecialImage::testingOnlyPeekPixels(SkPixmap* pixmap) const {
-    return as_SIB(this)->testingOnlyOnPeekPixels(pixmap);
+bool SkSpecialImage::peekPixels(SkPixmap* pixmap) const {
+    return as_SIB(this)->onPeekPixels(pixmap);
 }
 
 GrTexture* SkSpecialImage::peekTexture() const {
@@ -60,6 +62,10 @@
     return as_SIB(this)->onNewSurface(info);
 }
 
+SkSpecialImage* SkSpecialImage::extractSubset(const SkIRect& subset) const {
+    return as_SIB(this)->onExtractSubset(subset);
+}
+
 #if SK_SUPPORT_GPU
 #include "SkGr.h"
 #include "SkGrPixelRef.h"
@@ -85,8 +91,7 @@
     return ib->getBitmapDeprecated(result);
 }
 
-SkImageFilter::Proxy* SkSpecialImage::internal_getProxy() {
-    SkASSERT(fProxy);
+SkImageFilter::Proxy* SkSpecialImage::internal_getProxy() const {
     return fProxy;
 }
 
@@ -129,7 +134,7 @@
                               dst, paint, SkCanvas::kStrict_SrcRectConstraint);
     }
 
-    bool testingOnlyOnPeekPixels(SkPixmap* pixmap) const override {
+    bool onPeekPixels(SkPixmap* pixmap) const override {
         return fImage->peekPixels(pixmap);
     }
 
@@ -170,6 +175,17 @@
         return SkSpecialSurface::NewRaster(this->proxy(), info, nullptr);
     }
 
+    SkSpecialImage* onExtractSubset(const SkIRect& subset) const override {
+        SkAutoTUnref<SkImage> subsetImg(fImage->newSubset(subset));
+        if (!subsetImg) {
+            return nullptr;
+        }
+
+        return SkSpecialImage::NewFromImage(this->internal_getProxy(),
+                                            SkIRect::MakeWH(subset.width(), subset.height()),
+                                            subsetImg);
+    }
+
 private:
     SkAutoTUnref<const SkImage> fImage;
 
@@ -214,6 +230,17 @@
         }
     }
 
+    SkSpecialImage_Raster(SkImageFilter::Proxy* proxy,
+                          const SkIRect& subset,
+                          const SkPixmap& pixmap,
+                          void (*releaseProc)(void* addr, void* context),
+                          void* context)
+        : INHERITED(proxy, subset, kNeedNewImageUniqueID_SpecialImage) {
+        fBitmap.installPixels(pixmap.info(), pixmap.writable_addr(),
+                              pixmap.rowBytes(), pixmap.ctable(),
+                              releaseProc, context);
+    }
+
     ~SkSpecialImage_Raster() override { }
 
     bool isOpaque() const override { return fBitmap.isOpaque(); }
@@ -228,19 +255,13 @@
                                dst, paint, SkCanvas::kStrict_SrcRectConstraint);
     }
 
-    bool testingOnlyOnPeekPixels(SkPixmap* pixmap) const override {
+    bool onPeekPixels(SkPixmap* pixmap) const override {
         const SkImageInfo info = fBitmap.info();
         if ((kUnknown_SkColorType == info.colorType()) || !fBitmap.getPixels()) {
             return false;
         }
-        const void* pixels = fBitmap.getPixels();
-        if (pixels) {
-            if (pixmap) {
-                pixmap->reset(info, pixels, fBitmap.rowBytes());
-            }
-            return true;
-        }
-        return false;
+
+        return fBitmap.peekPixels(pixmap);
     }
 
     bool getBitmapDeprecated(SkBitmap* result) const override {
@@ -257,6 +278,18 @@
         return SkSpecialSurface::NewRaster(this->proxy(), info, nullptr);
     }
 
+    SkSpecialImage* onExtractSubset(const SkIRect& subset) const override {
+        SkBitmap subsetBM;
+        
+        if (!fBitmap.extractSubset(&subsetBM, subset)) {
+            return nullptr;
+        }
+
+        return SkSpecialImage::NewFromRaster(this->internal_getProxy(),
+                                             SkIRect::MakeWH(subset.width(), subset.height()),
+                                             subsetBM);
+    }
+
 private:
     SkBitmap fBitmap;
 
@@ -271,6 +304,15 @@
     return new SkSpecialImage_Raster(proxy, subset, bm);
 }
 
+SkSpecialImage* SkSpecialImage::NewFromPixmap(SkImageFilter::Proxy* proxy,
+                                              const SkIRect& subset,
+                                              const SkPixmap& src,
+                                              void (*releaseProc)(void* addr, void* context),
+                                              void* context) {
+    return new SkSpecialImage_Raster(proxy, subset, src, releaseProc, context);
+}
+
+
 #if SK_SUPPORT_GPU
 ///////////////////////////////////////////////////////////////////////////////
 #include "GrTexture.h"
@@ -315,7 +357,10 @@
             return false;
         }
 
-        result->setPixelRef(new SkGrPixelRef(info, fTexture))->unref();
+        const SkImageInfo prInfo = info.makeWH(fTexture->width(), fTexture->height());
+
+        SkAutoTUnref<SkGrPixelRef> pixelRef(new SkGrPixelRef(prInfo, fTexture));
+        result->setPixelRef(pixelRef, this->subset().fLeft, this->subset().fTop);
         return true;
     }
 
@@ -345,6 +390,14 @@
         return SkSpecialSurface::NewRenderTarget(this->proxy(), fTexture->getContext(), desc);
     }
 
+    SkSpecialImage* onExtractSubset(const SkIRect& subset) const override {
+        return SkSpecialImage::NewFromGpu(this->internal_getProxy(),
+                                          subset,
+                                          this->uniqueID(),
+                                          fTexture, 
+                                          fAlphaType);
+    }
+
 private:
     SkAutoTUnref<GrTexture> fTexture;
     const SkAlphaType       fAlphaType;