Add portable allocator to raster allocator test.

Still use GDI and CG when available, but use a Skia backed native raster
allocator on other platforms. This allows for exercising this code on
all platforms as well as ensuring that Skia itself can back this
interface. This also means this gm should always draw something instead
of often just being the white background.

Change-Id: Ie607f7082dc40454fc60ea4b4fe94a1db2d7502f
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/234662
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Ben Wagner <bungeman@google.com>
diff --git a/gm/rasterhandleallocator.cpp b/gm/rasterhandleallocator.cpp
index 1f3f3ea..3a549b8 100644
--- a/gm/rasterhandleallocator.cpp
+++ b/gm/rasterhandleallocator.cpp
@@ -10,6 +10,7 @@
 #include "include/core/SkCanvas.h"
 #include "include/core/SkPixmap.h"
 #include "include/core/SkRasterHandleAllocator.h"
+#include "include/core/SkSurface.h"
 #include "src/core/SkMakeUnique.h"
 
 class GraphicsPort {
@@ -45,6 +46,47 @@
     SkCanvas* peekCanvas() const { return fCanvas; }
 };
 
+class SkiaGraphicsPort : public GraphicsPort {
+public:
+    SkiaGraphicsPort(SkCanvas* canvas) : GraphicsPort(canvas) {}
+
+    void drawRect(const SkRect& r, SkColor c) override {
+        SkCanvas* canvas = (SkCanvas*)fCanvas->accessTopRasterHandle();
+        canvas->drawRect(r, SkPaint(SkColor4f::FromColor(c)));
+    }
+};
+
+class SkiaAllocator : public SkRasterHandleAllocator {
+public:
+    SkiaAllocator() {}
+
+    bool allocHandle(const SkImageInfo& info, Rec* rec) override {
+        sk_sp<SkSurface> surface = SkSurface::MakeRaster(info);
+        if (!surface) {
+            return false;
+        }
+        SkCanvas* canvas = surface->getCanvas();
+        SkPixmap pixmap;
+        canvas->peekPixels(&pixmap);
+
+        rec->fReleaseProc = [](void* pixels, void* ctx){ SkSafeUnref((SkSurface*)ctx); };
+        rec->fReleaseCtx = surface.release();
+        rec->fPixels = pixmap.writable_addr();
+        rec->fRowBytes = pixmap.rowBytes();
+        rec->fHandle = canvas;
+        canvas->save();    // balanced each time updateHandle is called
+        return true;
+    }
+
+    void updateHandle(Handle hndl, const SkMatrix& ctm, const SkIRect& clip) override {
+        SkCanvas* canvas = (SkCanvas*)hndl;
+        canvas->restore();
+        canvas->save();
+        canvas->clipRect(SkRect::Make(clip));
+        canvas->concat(ctm);
+    }
+};
+
 #ifdef SK_BUILD_FOR_MAC
 
 #include "include/utils/mac/SkCGUtils.h"
@@ -79,9 +121,9 @@
                                  matrix[SkMatrix::kMTransY]);
 }
 
-class Allocator_CG : public SkRasterHandleAllocator {
+class CGAllocator : public SkRasterHandleAllocator {
 public:
-    Allocator_CG() {}
+    CGAllocator() {}
 
     bool allocHandle(const SkImageInfo& info, Rec* rec) override {
         // let CG allocate the pixels
@@ -94,7 +136,7 @@
         rec->fPixels = CGBitmapContextGetData(cg);
         rec->fRowBytes = CGBitmapContextGetBytesPerRow(cg);
         rec->fHandle = cg;
-        CGContextSaveGState(cg);    // balanced each time updateContext is called
+        CGContextSaveGState(cg);    // balanced each time updateHandle is called
         return true;
     }
 
@@ -108,8 +150,8 @@
     }
 };
 
-#define MyPort CGGraphicsPort
-#define MyAllocator Allocator_CG
+using MyPort = CGGraphicsPort;
+using MyAllocator = CGAllocator;
 
 #elif defined(SK_BUILD_FOR_WIN)
 
@@ -221,8 +263,13 @@
     }
 };
 
-#define MyPort GDIGraphicsPort
-#define MyAllocator GDIAllocator
+using MyPort = GDIGraphicsPort;
+using MyAllocator = GDIAllocator;
+
+#else
+
+using MyPort = SkiaGraphicsPort;
+using MyAllocator = SkiaAllocator;
 
 #endif
 
@@ -246,11 +293,9 @@
     };
 
     // TODO: this common code fails pic-8888 and serialize-8888
-    sk_ignore_unused_variable(doDraw);
     //GraphicsPort skiaPort(canvas);
     //doDraw(&skiaPort);
 
-#ifdef MyAllocator
     const SkImageInfo info = SkImageInfo::MakeN32Premul(256, 256);
     std::unique_ptr<SkCanvas> nativeCanvas =
         SkRasterHandleAllocator::MakeCanvas(skstd::make_unique<MyAllocator>(), info);
@@ -262,5 +307,4 @@
     SkBitmap bm;
     bm.installPixels(pm);
     canvas->drawBitmap(bm, 280, 0, nullptr);
-#endif
 }