add SkSurface::NewRasterDirectReleaseProc

allows for lifetime control of pixel memory on raster surface

BUG=skia:
R=fmalita@google.com, bsalomon@google.com, fmalita@chromium.org

Author: reed@google.com

Review URL: https://codereview.chromium.org/351373005
diff --git a/include/core/SkSurface.h b/include/core/SkSurface.h
index d049d8c..68d4702 100644
--- a/include/core/SkSurface.h
+++ b/include/core/SkSurface.h
@@ -38,6 +38,14 @@
     static SkSurface* NewRasterDirect(const SkImageInfo&, void* pixels, size_t rowBytes);
 
     /**
+     *  The same as NewRasterDirect, but also accepts a call-back routine, which is invoked
+     *  when the surface is deleted, and is passed the pixel memory and the specified context.
+     */
+    static SkSurface* NewRasterDirectReleaseProc(const SkImageInfo&, void* pixels, size_t rowBytes,
+                                                 void (*releaseProc)(void* pixels, void* context),
+                                                 void* context);
+
+    /**
      *  Return a new surface, with the memory for the pixels automatically
      *  allocated.
      *
diff --git a/src/image/SkSurface_Raster.cpp b/src/image/SkSurface_Raster.cpp
index 0b6efe1..986994a 100644
--- a/src/image/SkSurface_Raster.cpp
+++ b/src/image/SkSurface_Raster.cpp
@@ -17,7 +17,8 @@
 public:
     static bool Valid(const SkImageInfo&, size_t rb = kIgnoreRowBytesValue);
 
-    SkSurface_Raster(const SkImageInfo&, void*, size_t rb);
+    SkSurface_Raster(const SkImageInfo&, void*, size_t rb,
+                     void (*releaseProc)(void* pixels, void* context), void* context);
     SkSurface_Raster(SkPixelRef*);
 
     virtual SkCanvas* onNewCanvas() SK_OVERRIDE;
@@ -76,10 +77,11 @@
     return true;
 }
 
-SkSurface_Raster::SkSurface_Raster(const SkImageInfo& info, void* pixels, size_t rb)
+SkSurface_Raster::SkSurface_Raster(const SkImageInfo& info, void* pixels, size_t rb,
+                                   void (*releaseProc)(void* pixels, void* context), void* context)
     : INHERITED(info)
 {
-    fBitmap.installPixels(info, pixels, rb);
+    fBitmap.installPixels(info, pixels, rb, NULL, releaseProc, context);
     fWeOwnThePixels = false;    // We are "Direct"
 }
 
@@ -136,15 +138,24 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-SkSurface* SkSurface::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
-    if (!SkSurface_Raster::Valid(info, rowBytes)) {
+SkSurface* SkSurface::NewRasterDirectReleaseProc(const SkImageInfo& info, void* pixels, size_t rb,
+                                                 void (*releaseProc)(void* pixels, void* context),
+                                                 void* context) {
+    if (NULL == releaseProc) {
+        context = NULL;
+    }
+    if (!SkSurface_Raster::Valid(info, rb)) {
         return NULL;
     }
     if (NULL == pixels) {
         return NULL;
     }
+    
+    return SkNEW_ARGS(SkSurface_Raster, (info, pixels, rb, releaseProc, context));
+}
 
-    return SkNEW_ARGS(SkSurface_Raster, (info, pixels, rowBytes));
+SkSurface* SkSurface::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
+    return NewRasterDirectReleaseProc(info, pixels, rowBytes, NULL, NULL);
 }
 
 SkSurface* SkSurface::NewRaster(const SkImageInfo& info) {
diff --git a/tests/SurfaceTest.cpp b/tests/SurfaceTest.cpp
index 3f61f89..610e337 100644
--- a/tests/SurfaceTest.cpp
+++ b/tests/SurfaceTest.cpp
@@ -27,13 +27,14 @@
     kGpuScratch_SurfaceType,
 };
 
-static const int gSurfaceSize = 10;
-static SkPMColor gSurfaceStorage[gSurfaceSize * gSurfaceSize];
+static void release_storage(void* pixels, void* context) {
+    SkASSERT(pixels == context);
+    sk_free(pixels);
+}
 
 static SkSurface* createSurface(SurfaceType surfaceType, GrContext* context,
                                 SkImageInfo* requestedInfo = NULL) {
-    static const SkImageInfo info = SkImageInfo::MakeN32Premul(gSurfaceSize,
-                                                               gSurfaceSize);
+    static const SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10);
 
     if (requestedInfo) {
         *requestedInfo = info;
@@ -42,9 +43,12 @@
     switch (surfaceType) {
         case kRaster_SurfaceType:
             return SkSurface::NewRaster(info);
-        case kRasterDirect_SurfaceType:
-            return SkSurface::NewRasterDirect(info, gSurfaceStorage,
-                                              info.minRowBytes());
+        case kRasterDirect_SurfaceType: {
+            const size_t rowBytes = info.minRowBytes();
+            void* storage = sk_malloc_throw(info.getSafeSize(rowBytes));
+            return SkSurface::NewRasterDirectReleaseProc(info, storage, rowBytes,
+                                                         release_storage, storage);
+        }
         case kGpu_SurfaceType:
 #if SK_SUPPORT_GPU
             return context ? SkSurface::NewRenderTarget(context, info) : NULL;