OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkCanvas.h" | 8 #include "SkCanvas.h" |
9 #include "SkData.h" | 9 #include "SkData.h" |
10 #include "SkDevice.h" | 10 #include "SkDevice.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 return SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted,
info, 0, NULL); | 58 return SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted,
info, 0, NULL); |
59 case kGpuScratch_SurfaceType: | 59 case kGpuScratch_SurfaceType: |
60 return SkSurface::NewRenderTarget(context, SkSurface::kYes_Budgeted,
info, 0, NULL); | 60 return SkSurface::NewRenderTarget(context, SkSurface::kYes_Budgeted,
info, 0, NULL); |
61 } | 61 } |
62 return NULL; | 62 return NULL; |
63 } | 63 } |
64 | 64 |
65 enum ImageType { | 65 enum ImageType { |
66 kRasterCopy_ImageType, | 66 kRasterCopy_ImageType, |
67 kRasterData_ImageType, | 67 kRasterData_ImageType, |
| 68 kRasterProc_ImageType, |
68 kGpu_ImageType, | 69 kGpu_ImageType, |
69 kCodec_ImageType, | 70 kCodec_ImageType, |
70 }; | 71 }; |
71 | 72 |
72 #include "SkImageGenerator.h" | 73 #include "SkImageGenerator.h" |
73 | 74 |
74 class EmptyGenerator : public SkImageGenerator { | 75 class EmptyGenerator : public SkImageGenerator { |
75 public: | 76 public: |
76 EmptyGenerator() : SkImageGenerator(SkImageInfo::MakeN32Premul(0, 0)) {} | 77 EmptyGenerator() : SkImageGenerator(SkImageInfo::MakeN32Premul(0, 0)) {} |
77 }; | 78 }; |
78 | 79 |
79 static void test_empty_image(skiatest::Reporter* reporter) { | 80 static void test_empty_image(skiatest::Reporter* reporter) { |
80 const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_S
kAlphaType); | 81 const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_S
kAlphaType); |
81 | 82 |
82 REPORTER_ASSERT(reporter, NULL == SkImage::NewRasterCopy(info, NULL, 0)); | 83 REPORTER_ASSERT(reporter, NULL == SkImage::NewRasterCopy(info, NULL, 0)); |
83 REPORTER_ASSERT(reporter, NULL == SkImage::NewRasterData(info, NULL, 0)); | 84 REPORTER_ASSERT(reporter, NULL == SkImage::NewRasterData(info, NULL, 0)); |
| 85 REPORTER_ASSERT(reporter, NULL == SkImage::NewFromRaster(info, NULL, 0, NULL
, NULL)); |
84 REPORTER_ASSERT(reporter, NULL == SkImage::NewFromGenerator(SkNEW(EmptyGener
ator))); | 86 REPORTER_ASSERT(reporter, NULL == SkImage::NewFromGenerator(SkNEW(EmptyGener
ator))); |
85 } | 87 } |
86 | 88 |
87 static void test_empty_surface(skiatest::Reporter* reporter, GrContext* ctx) { | 89 static void test_empty_surface(skiatest::Reporter* reporter, GrContext* ctx) { |
88 const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_S
kAlphaType); | 90 const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_S
kAlphaType); |
89 | 91 |
90 REPORTER_ASSERT(reporter, NULL == SkSurface::NewRaster(info)); | 92 REPORTER_ASSERT(reporter, NULL == SkSurface::NewRaster(info)); |
91 REPORTER_ASSERT(reporter, NULL == SkSurface::NewRasterDirect(info, NULL, 0))
; | 93 REPORTER_ASSERT(reporter, NULL == SkSurface::NewRasterDirect(info, NULL, 0))
; |
92 if (ctx) { | 94 if (ctx) { |
93 REPORTER_ASSERT(reporter, NULL == | 95 REPORTER_ASSERT(reporter, NULL == |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
197 SkData* data = SkData::NewUninitialized(size); | 199 SkData* data = SkData::NewUninitialized(size); |
198 | 200 |
199 REPORTER_ASSERT(reporter, data->unique()); | 201 REPORTER_ASSERT(reporter, data->unique()); |
200 SkImage* image = SkImage::NewRasterData(info, data, rowBytes); | 202 SkImage* image = SkImage::NewRasterData(info, data, rowBytes); |
201 REPORTER_ASSERT(reporter, !data->unique()); | 203 REPORTER_ASSERT(reporter, !data->unique()); |
202 image->unref(); | 204 image->unref(); |
203 REPORTER_ASSERT(reporter, data->unique()); | 205 REPORTER_ASSERT(reporter, data->unique()); |
204 data->unref(); | 206 data->unref(); |
205 } | 207 } |
206 | 208 |
207 static SkImage* createImage(ImageType imageType, GrContext* context, SkColor col
or) { | 209 // Want to ensure that our Release is called when the owning image is destroyed |
| 210 struct ReleaseDataContext { |
| 211 skiatest::Reporter* fReporter; |
| 212 SkData* fData; |
| 213 |
| 214 static void Release(const void* pixels, void* context) { |
| 215 ReleaseDataContext* state = (ReleaseDataContext*)context; |
| 216 REPORTER_ASSERT(state->fReporter, state->fData); |
| 217 state->fData->unref(); |
| 218 state->fData = NULL; |
| 219 } |
| 220 }; |
| 221 |
| 222 static SkImage* createImage(ImageType imageType, GrContext* context, SkColor col
or, |
| 223 ReleaseDataContext* releaseContext) { |
208 const SkPMColor pmcolor = SkPreMultiplyColor(color); | 224 const SkPMColor pmcolor = SkPreMultiplyColor(color); |
209 const SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10); | 225 const SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10); |
210 const size_t rowBytes = info.minRowBytes(); | 226 const size_t rowBytes = info.minRowBytes(); |
211 const size_t size = rowBytes * info.height(); | 227 const size_t size = rowBytes * info.height(); |
212 | 228 |
213 SkAutoTUnref<SkData> data(SkData::NewUninitialized(size)); | 229 SkAutoTUnref<SkData> data(SkData::NewUninitialized(size)); |
214 void* addr = data->writable_data(); | 230 void* addr = data->writable_data(); |
215 sk_memset32((SkPMColor*)addr, pmcolor, SkToInt(size >> 2)); | 231 sk_memset32((SkPMColor*)addr, pmcolor, SkToInt(size >> 2)); |
216 | 232 |
217 switch (imageType) { | 233 switch (imageType) { |
218 case kRasterCopy_ImageType: | 234 case kRasterCopy_ImageType: |
219 return SkImage::NewRasterCopy(info, addr, rowBytes); | 235 return SkImage::NewRasterCopy(info, addr, rowBytes); |
220 case kRasterData_ImageType: | 236 case kRasterData_ImageType: |
221 return SkImage::NewRasterData(info, data, rowBytes); | 237 return SkImage::NewRasterData(info, data, rowBytes); |
| 238 case kRasterProc_ImageType: |
| 239 SkASSERT(releaseContext); |
| 240 releaseContext->fData = SkRef(data.get()); |
| 241 return SkImage::NewFromRaster(info, addr, rowBytes, |
| 242 ReleaseDataContext::Release, releaseCo
ntext); |
222 case kGpu_ImageType: { | 243 case kGpu_ImageType: { |
223 SkAutoTUnref<SkSurface> surf( | 244 SkAutoTUnref<SkSurface> surf( |
224 SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, inf
o, 0)); | 245 SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, inf
o, 0)); |
225 surf->getCanvas()->clear(color); | 246 surf->getCanvas()->clear(color); |
226 return surf->newImageSnapshot(); | 247 return surf->newImageSnapshot(); |
227 } | 248 } |
228 case kCodec_ImageType: { | 249 case kCodec_ImageType: { |
229 SkBitmap bitmap; | 250 SkBitmap bitmap; |
230 bitmap.installPixels(info, addr, rowBytes); | 251 bitmap.installPixels(info, addr, rowBytes); |
231 SkAutoTUnref<SkData> src( | 252 SkAutoTUnref<SkData> src( |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 } | 316 } |
296 | 317 |
297 static void test_imagepeek(skiatest::Reporter* reporter, GrContextFactory* facto
ry) { | 318 static void test_imagepeek(skiatest::Reporter* reporter, GrContextFactory* facto
ry) { |
298 static const struct { | 319 static const struct { |
299 ImageType fType; | 320 ImageType fType; |
300 bool fPeekShouldSucceed; | 321 bool fPeekShouldSucceed; |
301 const char* fName; | 322 const char* fName; |
302 } gRec[] = { | 323 } gRec[] = { |
303 { kRasterCopy_ImageType, true, "RasterCopy" }, | 324 { kRasterCopy_ImageType, true, "RasterCopy" }, |
304 { kRasterData_ImageType, true, "RasterData" }, | 325 { kRasterData_ImageType, true, "RasterData" }, |
| 326 { kRasterProc_ImageType, true, "RasterProc" }, |
305 { kGpu_ImageType, false, "Gpu" }, | 327 { kGpu_ImageType, false, "Gpu" }, |
306 { kCodec_ImageType, false, "Codec" }, | 328 { kCodec_ImageType, false, "Codec" }, |
307 }; | 329 }; |
308 | 330 |
309 const SkColor color = SK_ColorRED; | 331 const SkColor color = SK_ColorRED; |
310 const SkPMColor pmcolor = SkPreMultiplyColor(color); | 332 const SkPMColor pmcolor = SkPreMultiplyColor(color); |
311 | 333 |
312 GrContext* ctx = NULL; | 334 GrContext* ctx = NULL; |
313 #if SK_SUPPORT_GPU | 335 #if SK_SUPPORT_GPU |
314 ctx = factory->get(GrContextFactory::kNative_GLContextType); | 336 ctx = factory->get(GrContextFactory::kNative_GLContextType); |
315 if (NULL == ctx) { | 337 if (NULL == ctx) { |
316 return; | 338 return; |
317 } | 339 } |
318 #endif | 340 #endif |
319 | 341 |
| 342 ReleaseDataContext releaseCtx; |
| 343 releaseCtx.fReporter = reporter; |
| 344 |
320 for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) { | 345 for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) { |
321 SkImageInfo info; | 346 SkImageInfo info; |
322 size_t rowBytes; | 347 size_t rowBytes; |
323 | 348 |
324 SkAutoTUnref<SkImage> image(createImage(gRec[i].fType, ctx, color)); | 349 releaseCtx.fData = NULL; |
| 350 SkAutoTUnref<SkImage> image(createImage(gRec[i].fType, ctx, color, &rele
aseCtx)); |
325 if (!image.get()) { | 351 if (!image.get()) { |
326 SkDebugf("failed to createImage[%d] %s\n", i, gRec[i].fName); | 352 SkDebugf("failed to createImage[%d] %s\n", i, gRec[i].fName); |
327 continue; // gpu may not be enabled | 353 continue; // gpu may not be enabled |
328 } | 354 } |
| 355 if (kRasterProc_ImageType == gRec[i].fType) { |
| 356 REPORTER_ASSERT(reporter, NULL != releaseCtx.fData); // we are trac
king the data |
| 357 } else { |
| 358 REPORTER_ASSERT(reporter, NULL == releaseCtx.fData); // we ignored
the context |
| 359 } |
| 360 |
329 const void* addr = image->peekPixels(&info, &rowBytes); | 361 const void* addr = image->peekPixels(&info, &rowBytes); |
330 bool success = SkToBool(addr); | 362 bool success = SkToBool(addr); |
331 REPORTER_ASSERT(reporter, gRec[i].fPeekShouldSucceed == success); | 363 REPORTER_ASSERT(reporter, gRec[i].fPeekShouldSucceed == success); |
332 if (success) { | 364 if (success) { |
333 REPORTER_ASSERT(reporter, 10 == info.width()); | 365 REPORTER_ASSERT(reporter, 10 == info.width()); |
334 REPORTER_ASSERT(reporter, 10 == info.height()); | 366 REPORTER_ASSERT(reporter, 10 == info.height()); |
335 REPORTER_ASSERT(reporter, kN32_SkColorType == info.colorType()); | 367 REPORTER_ASSERT(reporter, kN32_SkColorType == info.colorType()); |
336 REPORTER_ASSERT(reporter, kPremul_SkAlphaType == info.alphaType() || | 368 REPORTER_ASSERT(reporter, kPremul_SkAlphaType == info.alphaType() || |
337 kOpaque_SkAlphaType == info.alphaType()); | 369 kOpaque_SkAlphaType == info.alphaType()); |
338 REPORTER_ASSERT(reporter, info.minRowBytes() <= rowBytes); | 370 REPORTER_ASSERT(reporter, info.minRowBytes() <= rowBytes); |
339 REPORTER_ASSERT(reporter, pmcolor == *(const SkPMColor*)addr); | 371 REPORTER_ASSERT(reporter, pmcolor == *(const SkPMColor*)addr); |
340 } | 372 } |
341 | 373 |
342 test_image_readpixels(reporter, image, pmcolor); | 374 test_image_readpixels(reporter, image, pmcolor); |
343 } | 375 } |
| 376 REPORTER_ASSERT(reporter, NULL == releaseCtx.fData); // we released the dat
a |
344 } | 377 } |
345 | 378 |
346 static void test_canvaspeek(skiatest::Reporter* reporter, | 379 static void test_canvaspeek(skiatest::Reporter* reporter, |
347 GrContextFactory* factory) { | 380 GrContextFactory* factory) { |
348 static const struct { | 381 static const struct { |
349 SurfaceType fType; | 382 SurfaceType fType; |
350 bool fPeekShouldSucceed; | 383 bool fPeekShouldSucceed; |
351 } gRec[] = { | 384 } gRec[] = { |
352 { kRaster_SurfaceType, true }, | 385 { kRaster_SurfaceType, true }, |
353 { kRasterDirect_SurfaceType, true }, | 386 { kRasterDirect_SurfaceType, true }, |
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
732 test_empty_surface(reporter, context); | 765 test_empty_surface(reporter, context); |
733 test_surface_budget(reporter, context); | 766 test_surface_budget(reporter, context); |
734 test_wrapped_texture_surface(reporter, context); | 767 test_wrapped_texture_surface(reporter, context); |
735 } | 768 } |
736 } | 769 } |
737 } | 770 } |
738 #endif | 771 #endif |
739 } | 772 } |
740 | 773 |
741 #if SK_SUPPORT_GPU | 774 #if SK_SUPPORT_GPU |
742 static SkImage* make_desc_image(GrContext* ctx, int w, int h, GrBackendObject te
xID, bool doCopy) { | 775 |
| 776 struct ReleaseTextureContext { |
| 777 ReleaseTextureContext(skiatest::Reporter* reporter) { |
| 778 fReporter = reporter; |
| 779 fIsReleased = false; |
| 780 } |
| 781 |
| 782 skiatest::Reporter* fReporter; |
| 783 bool fIsReleased; |
| 784 |
| 785 void doRelease() { |
| 786 REPORTER_ASSERT(fReporter, false == fIsReleased); |
| 787 fIsReleased = true; |
| 788 } |
| 789 |
| 790 static void ReleaseProc(void* context) { |
| 791 ((ReleaseTextureContext*)context)->doRelease(); |
| 792 } |
| 793 }; |
| 794 |
| 795 static SkImage* make_desc_image(GrContext* ctx, int w, int h, GrBackendObject te
xID, |
| 796 ReleaseTextureContext* releaseContext) { |
743 GrBackendTextureDesc desc; | 797 GrBackendTextureDesc desc; |
744 desc.fConfig = kSkia8888_GrPixelConfig; | 798 desc.fConfig = kSkia8888_GrPixelConfig; |
745 // need to be a rendertarget for now... | 799 // need to be a rendertarget for now... |
746 desc.fFlags = kRenderTarget_GrBackendTextureFlag; | 800 desc.fFlags = kRenderTarget_GrBackendTextureFlag; |
747 desc.fWidth = w; | 801 desc.fWidth = w; |
748 desc.fHeight = h; | 802 desc.fHeight = h; |
749 desc.fSampleCnt = 0; | 803 desc.fSampleCnt = 0; |
750 desc.fTextureHandle = texID; | 804 desc.fTextureHandle = texID; |
751 return doCopy ? SkImage::NewFromTextureCopy(ctx, desc) : SkImage::NewFromTex
ture(ctx, desc); | 805 return releaseContext |
| 806 ? SkImage::NewFromTexture(ctx, desc, kPremul_SkAlphaType, |
| 807 ReleaseTextureContext::ReleaseProc, re
leaseContext) |
| 808 : SkImage::NewFromTextureCopy(ctx, desc, kPremul_SkAlphaType); |
752 } | 809 } |
753 | 810 |
754 static void test_image_color(skiatest::Reporter* reporter, SkImage* image, SkPMC
olor expected) { | 811 static void test_image_color(skiatest::Reporter* reporter, SkImage* image, SkPMC
olor expected) { |
755 const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1); | 812 const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1); |
756 SkPMColor pixel; | 813 SkPMColor pixel; |
757 REPORTER_ASSERT(reporter, image->readPixels(info, &pixel, sizeof(pixel), 0,
0)); | 814 REPORTER_ASSERT(reporter, image->readPixels(info, &pixel, sizeof(pixel), 0,
0)); |
758 REPORTER_ASSERT(reporter, pixel == expected); | 815 REPORTER_ASSERT(reporter, pixel == expected); |
759 } | 816 } |
760 | 817 |
761 DEF_GPUTEST(SkImage_NewFromTexture, reporter, factory) { | 818 DEF_GPUTEST(SkImage_NewFromTexture, reporter, factory) { |
(...skipping 16 matching lines...) Expand all Loading... |
778 desc.fWidth = w; | 835 desc.fWidth = w; |
779 desc.fHeight = h; | 836 desc.fHeight = h; |
780 desc.fConfig = kSkia8888_GrPixelConfig; | 837 desc.fConfig = kSkia8888_GrPixelConfig; |
781 desc.fSampleCnt = 0; | 838 desc.fSampleCnt = 0; |
782 | 839 |
783 SkAutoTUnref<GrTexture> tex(provider->createTexture(desc, false, storage, w
* 4)); | 840 SkAutoTUnref<GrTexture> tex(provider->createTexture(desc, false, storage, w
* 4)); |
784 if (!tex) { | 841 if (!tex) { |
785 REPORTER_ASSERT(reporter, false); | 842 REPORTER_ASSERT(reporter, false); |
786 return; | 843 return; |
787 } | 844 } |
788 | 845 |
789 GrBackendObject srcTex = tex->getTextureHandle(); | 846 GrBackendObject srcTex = tex->getTextureHandle(); |
790 SkAutoTUnref<SkImage> refImg(make_desc_image(ctx, w, h, srcTex, false)); | 847 ReleaseTextureContext releaseCtx(reporter); |
791 SkAutoTUnref<SkImage> cpyImg(make_desc_image(ctx, w, h, srcTex, true)); | 848 |
| 849 SkAutoTUnref<SkImage> refImg(make_desc_image(ctx, w, h, srcTex, &releaseCtx)
); |
| 850 SkAutoTUnref<SkImage> cpyImg(make_desc_image(ctx, w, h, srcTex, NULL)); |
792 | 851 |
793 test_image_color(reporter, refImg, expected0); | 852 test_image_color(reporter, refImg, expected0); |
794 test_image_color(reporter, cpyImg, expected0); | 853 test_image_color(reporter, cpyImg, expected0); |
795 | 854 |
796 // Now lets jam new colors into our "external" texture, and see if the image
s notice | 855 // Now lets jam new colors into our "external" texture, and see if the image
s notice |
797 const SkPMColor expected1 = SkPreMultiplyColor(SK_ColorBLUE); | 856 const SkPMColor expected1 = SkPreMultiplyColor(SK_ColorBLUE); |
798 sk_memset32(storage, expected1, w * h); | 857 sk_memset32(storage, expected1, w * h); |
799 tex->writePixels(0, 0, w, h, kSkia8888_GrPixelConfig, storage, GrContext::kF
lushWrites_PixelOp); | 858 tex->writePixels(0, 0, w, h, kSkia8888_GrPixelConfig, storage, GrContext::kF
lushWrites_PixelOp); |
800 | 859 |
801 // We expect the ref'd image to see the new color, but cpy'd one should stil
l see the old color | 860 // We expect the ref'd image to see the new color, but cpy'd one should stil
l see the old color |
802 test_image_color(reporter, refImg, expected1); | 861 test_image_color(reporter, refImg, expected1); |
803 test_image_color(reporter, cpyImg, expected0); | 862 test_image_color(reporter, cpyImg, expected0); |
| 863 |
| 864 // Now exercise the release proc |
| 865 REPORTER_ASSERT(reporter, !releaseCtx.fIsReleased); |
| 866 refImg.reset(NULL); // force a release of the image |
| 867 REPORTER_ASSERT(reporter, releaseCtx.fIsReleased); |
804 } | 868 } |
805 #endif | 869 #endif |
OLD | NEW |