Index: tests/SurfaceTest.cpp |
diff --git a/tests/SurfaceTest.cpp b/tests/SurfaceTest.cpp |
index 34e5ab524a06d4037d3ec742b86cf2af778e2a0c..0eebfeb4efe56aa7592089c3dcac7721e74c2e5b 100644 |
--- a/tests/SurfaceTest.cpp |
+++ b/tests/SurfaceTest.cpp |
@@ -65,6 +65,7 @@ static SkSurface* createSurface(SurfaceType surfaceType, GrContext* context, |
enum ImageType { |
kRasterCopy_ImageType, |
kRasterData_ImageType, |
+ kRasterProc_ImageType, |
kGpu_ImageType, |
kCodec_ImageType, |
}; |
@@ -81,6 +82,7 @@ static void test_empty_image(skiatest::Reporter* reporter) { |
REPORTER_ASSERT(reporter, NULL == SkImage::NewRasterCopy(info, NULL, 0)); |
REPORTER_ASSERT(reporter, NULL == SkImage::NewRasterData(info, NULL, 0)); |
+ REPORTER_ASSERT(reporter, NULL == SkImage::NewFromRaster(info, NULL, 0, NULL, NULL)); |
REPORTER_ASSERT(reporter, NULL == SkImage::NewFromGenerator(SkNEW(EmptyGenerator))); |
} |
@@ -204,7 +206,21 @@ static void test_image(skiatest::Reporter* reporter) { |
data->unref(); |
} |
-static SkImage* createImage(ImageType imageType, GrContext* context, SkColor color) { |
+// Want to ensure that our Release is called when the owning image is destroyed |
+struct ReleaseDataContext { |
+ skiatest::Reporter* fReporter; |
+ SkData* fData; |
+ |
+ static void Release(const void* pixels, void* context) { |
+ ReleaseDataContext* state = (ReleaseDataContext*)context; |
+ REPORTER_ASSERT(state->fReporter, state->fData); |
+ state->fData->unref(); |
+ state->fData = NULL; |
+ } |
+}; |
+ |
+static SkImage* createImage(ImageType imageType, GrContext* context, SkColor color, |
+ ReleaseDataContext* releaseContext) { |
const SkPMColor pmcolor = SkPreMultiplyColor(color); |
const SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10); |
const size_t rowBytes = info.minRowBytes(); |
@@ -219,6 +235,11 @@ static SkImage* createImage(ImageType imageType, GrContext* context, SkColor col |
return SkImage::NewRasterCopy(info, addr, rowBytes); |
case kRasterData_ImageType: |
return SkImage::NewRasterData(info, data, rowBytes); |
+ case kRasterProc_ImageType: |
+ SkASSERT(releaseContext); |
+ releaseContext->fData = SkRef(data.get()); |
+ return SkImage::NewFromRaster(info, addr, rowBytes, |
+ ReleaseDataContext::Release, releaseContext); |
case kGpu_ImageType: { |
SkAutoTUnref<SkSurface> surf( |
SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, info, 0)); |
@@ -302,6 +323,7 @@ static void test_imagepeek(skiatest::Reporter* reporter, GrContextFactory* facto |
} gRec[] = { |
{ kRasterCopy_ImageType, true, "RasterCopy" }, |
{ kRasterData_ImageType, true, "RasterData" }, |
+ { kRasterProc_ImageType, true, "RasterProc" }, |
{ kGpu_ImageType, false, "Gpu" }, |
{ kCodec_ImageType, false, "Codec" }, |
}; |
@@ -317,15 +339,25 @@ static void test_imagepeek(skiatest::Reporter* reporter, GrContextFactory* facto |
} |
#endif |
+ ReleaseDataContext releaseCtx; |
+ releaseCtx.fReporter = reporter; |
+ |
for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) { |
SkImageInfo info; |
size_t rowBytes; |
- SkAutoTUnref<SkImage> image(createImage(gRec[i].fType, ctx, color)); |
+ releaseCtx.fData = NULL; |
+ SkAutoTUnref<SkImage> image(createImage(gRec[i].fType, ctx, color, &releaseCtx)); |
if (!image.get()) { |
SkDebugf("failed to createImage[%d] %s\n", i, gRec[i].fName); |
continue; // gpu may not be enabled |
} |
+ if (kRasterProc_ImageType == gRec[i].fType) { |
+ REPORTER_ASSERT(reporter, NULL != releaseCtx.fData); // we are tracking the data |
+ } else { |
+ REPORTER_ASSERT(reporter, NULL == releaseCtx.fData); // we ignored the context |
+ } |
+ |
const void* addr = image->peekPixels(&info, &rowBytes); |
bool success = SkToBool(addr); |
REPORTER_ASSERT(reporter, gRec[i].fPeekShouldSucceed == success); |
@@ -341,6 +373,7 @@ static void test_imagepeek(skiatest::Reporter* reporter, GrContextFactory* facto |
test_image_readpixels(reporter, image, pmcolor); |
} |
+ REPORTER_ASSERT(reporter, NULL == releaseCtx.fData); // we released the data |
} |
static void test_canvaspeek(skiatest::Reporter* reporter, |
@@ -739,7 +772,28 @@ DEF_GPUTEST(Surface, reporter, factory) { |
} |
#if SK_SUPPORT_GPU |
-static SkImage* make_desc_image(GrContext* ctx, int w, int h, GrBackendObject texID, bool doCopy) { |
+ |
+struct ReleaseTextureContext { |
+ ReleaseTextureContext(skiatest::Reporter* reporter) { |
+ fReporter = reporter; |
+ fIsReleased = false; |
+ } |
+ |
+ skiatest::Reporter* fReporter; |
+ bool fIsReleased; |
+ |
+ void doRelease() { |
+ REPORTER_ASSERT(fReporter, false == fIsReleased); |
+ fIsReleased = true; |
+ } |
+ |
+ static void ReleaseProc(void* context) { |
+ ((ReleaseTextureContext*)context)->doRelease(); |
+ } |
+}; |
+ |
+static SkImage* make_desc_image(GrContext* ctx, int w, int h, GrBackendObject texID, |
+ ReleaseTextureContext* releaseContext) { |
GrBackendTextureDesc desc; |
desc.fConfig = kSkia8888_GrPixelConfig; |
// need to be a rendertarget for now... |
@@ -748,7 +802,10 @@ static SkImage* make_desc_image(GrContext* ctx, int w, int h, GrBackendObject te |
desc.fHeight = h; |
desc.fSampleCnt = 0; |
desc.fTextureHandle = texID; |
- return doCopy ? SkImage::NewFromTextureCopy(ctx, desc) : SkImage::NewFromTexture(ctx, desc); |
+ return releaseContext |
+ ? SkImage::NewFromTexture(ctx, desc, kPremul_SkAlphaType, |
+ ReleaseTextureContext::ReleaseProc, releaseContext) |
+ : SkImage::NewFromTextureCopy(ctx, desc, kPremul_SkAlphaType); |
} |
static void test_image_color(skiatest::Reporter* reporter, SkImage* image, SkPMColor expected) { |
@@ -785,10 +842,12 @@ DEF_GPUTEST(SkImage_NewFromTexture, reporter, factory) { |
REPORTER_ASSERT(reporter, false); |
return; |
} |
- |
+ |
GrBackendObject srcTex = tex->getTextureHandle(); |
- SkAutoTUnref<SkImage> refImg(make_desc_image(ctx, w, h, srcTex, false)); |
- SkAutoTUnref<SkImage> cpyImg(make_desc_image(ctx, w, h, srcTex, true)); |
+ ReleaseTextureContext releaseCtx(reporter); |
+ |
+ SkAutoTUnref<SkImage> refImg(make_desc_image(ctx, w, h, srcTex, &releaseCtx)); |
+ SkAutoTUnref<SkImage> cpyImg(make_desc_image(ctx, w, h, srcTex, NULL)); |
test_image_color(reporter, refImg, expected0); |
test_image_color(reporter, cpyImg, expected0); |
@@ -801,5 +860,10 @@ DEF_GPUTEST(SkImage_NewFromTexture, reporter, factory) { |
// We expect the ref'd image to see the new color, but cpy'd one should still see the old color |
test_image_color(reporter, refImg, expected1); |
test_image_color(reporter, cpyImg, expected0); |
+ |
+ // Now exercise the release proc |
+ REPORTER_ASSERT(reporter, !releaseCtx.fIsReleased); |
+ refImg.reset(NULL); // force a release of the image |
+ REPORTER_ASSERT(reporter, releaseCtx.fIsReleased); |
} |
#endif |