From 982542dce8acbd2f3e7642268b21e76b93230daf Mon Sep 17 00:00:00 2001 From: reed Date: Fri, 27 Jun 2014 06:48:14 -0700 Subject: [PATCH] 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 --- include/core/SkSurface.h | 8 ++++++++ src/image/SkSurface_Raster.cpp | 23 +++++++++++++++++------ tests/SurfaceTest.cpp | 18 +++++++++++------- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/include/core/SkSurface.h b/include/core/SkSurface.h index d049d8c040..68d4702cb5 100644 --- a/include/core/SkSurface.h +++ b/include/core/SkSurface.h @@ -37,6 +37,14 @@ public: */ 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 0b6efe19fe..986994ab8f 100644 --- a/src/image/SkSurface_Raster.cpp +++ b/src/image/SkSurface_Raster.cpp @@ -17,7 +17,8 @@ class SkSurface_Raster : public SkSurface_Base { 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 @@ bool SkSurface_Raster::Valid(const SkImageInfo& info, size_t rowBytes) { 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 @@ void SkSurface_Raster::onCopyOnWrite(ContentChangeMode mode) { /////////////////////////////////////////////////////////////////////////////// -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 3f61f89abe..610e3370f6 100644 --- a/tests/SurfaceTest.cpp +++ b/tests/SurfaceTest.cpp @@ -27,13 +27,14 @@ enum SurfaceType { 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 @@ static SkSurface* createSurface(SurfaceType surfaceType, GrContext* context, 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;