1 /*
2  * Copyright 2015 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include <functional>
9 #include "DMGpuSupport.h"
10 
11 #include "SkBitmap.h"
12 #include "SkCanvas.h"
13 #include "SkData.h"
14 #include "SkDevice.h"
15 #include "SkImageEncoder.h"
16 #include "SkImageGenerator.h"
17 #include "SkImage_Base.h"
18 #include "SkPicture.h"
19 #include "SkPictureRecorder.h"
20 #include "SkPixelSerializer.h"
21 #include "SkRRect.h"
22 #include "SkStream.h"
23 #include "SkSurface.h"
24 #include "SkUtils.h"
25 #include "Test.h"
26 
assert_equal(skiatest::Reporter * reporter,SkImage * a,const SkIRect * subsetA,SkImage * b)27 static void assert_equal(skiatest::Reporter* reporter, SkImage* a, const SkIRect* subsetA,
28                          SkImage* b) {
29     const int widthA = subsetA ? subsetA->width() : a->width();
30     const int heightA = subsetA ? subsetA->height() : a->height();
31 
32     REPORTER_ASSERT(reporter, widthA == b->width());
33     REPORTER_ASSERT(reporter, heightA == b->height());
34 #if 0
35     // see https://bug.skia.org/3965
36     bool AO = a->isOpaque();
37     bool BO = b->isOpaque();
38     REPORTER_ASSERT(reporter, AO == BO);
39 #endif
40 
41     SkImageInfo info = SkImageInfo::MakeN32(widthA, heightA,
42                                         a->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
43     SkAutoPixmapStorage pmapA, pmapB;
44     pmapA.alloc(info);
45     pmapB.alloc(info);
46 
47     const int srcX = subsetA ? subsetA->x() : 0;
48     const int srcY = subsetA ? subsetA->y() : 0;
49 
50     REPORTER_ASSERT(reporter, a->readPixels(pmapA, srcX, srcY));
51     REPORTER_ASSERT(reporter, b->readPixels(pmapB, 0, 0));
52 
53     const size_t widthBytes = widthA * info.bytesPerPixel();
54     for (int y = 0; y < heightA; ++y) {
55         REPORTER_ASSERT(reporter, !memcmp(pmapA.addr32(0, y), pmapB.addr32(0, y), widthBytes));
56     }
57 }
draw_image_test_pattern(SkCanvas * canvas)58 static void draw_image_test_pattern(SkCanvas* canvas) {
59     canvas->clear(SK_ColorWHITE);
60     SkPaint paint;
61     paint.setColor(SK_ColorBLACK);
62     canvas->drawRect(SkRect::MakeXYWH(5, 5, 10, 10), paint);
63 }
create_image()64 static SkImage* create_image() {
65     const SkImageInfo info = SkImageInfo::MakeN32(20, 20, kOpaque_SkAlphaType);
66     SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info));
67     draw_image_test_pattern(surface->getCanvas());
68     return surface->newImageSnapshot();
69 }
create_image_data(SkImageInfo * info)70 static SkData* create_image_data(SkImageInfo* info) {
71     *info = SkImageInfo::MakeN32(20, 20, kOpaque_SkAlphaType);
72     const size_t rowBytes = info->minRowBytes();
73     SkAutoTUnref<SkData> data(SkData::NewUninitialized(rowBytes * info->height()));
74     {
75         SkBitmap bm;
76         bm.installPixels(*info, data->writable_data(), rowBytes);
77         SkCanvas canvas(bm);
78         draw_image_test_pattern(&canvas);
79     }
80     return data.release();
81 }
create_data_image()82 static SkImage* create_data_image() {
83     SkImageInfo info;
84     SkAutoTUnref<SkData> data(create_image_data(&info));
85     return SkImage::NewRasterData(info, data, info.minRowBytes());
86 }
87 #if SK_SUPPORT_GPU // not gpu-specific but currently only used in GPU tests
create_picture_image()88 static SkImage* create_picture_image() {
89     SkPictureRecorder recorder;
90     SkCanvas* canvas = recorder.beginRecording(10, 10);
91     canvas->clear(SK_ColorCYAN);
92     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
93     return SkImage::NewFromPicture(picture, SkISize::Make(10, 10), nullptr, nullptr);
94 };
95 #endif
96 // Want to ensure that our Release is called when the owning image is destroyed
97 struct RasterDataHolder {
RasterDataHolderRasterDataHolder98     RasterDataHolder() : fReleaseCount(0) {}
99     SkAutoTUnref<SkData> fData;
100     int fReleaseCount;
ReleaseRasterDataHolder101     static void Release(const void* pixels, void* context) {
102         RasterDataHolder* self = static_cast<RasterDataHolder*>(context);
103         self->fReleaseCount++;
104         self->fData.reset();
105     }
106 };
create_rasterproc_image(RasterDataHolder * dataHolder)107 static SkImage* create_rasterproc_image(RasterDataHolder* dataHolder) {
108     SkASSERT(dataHolder);
109     SkImageInfo info;
110     SkAutoTUnref<SkData> data(create_image_data(&info));
111     dataHolder->fData.reset(SkRef(data.get()));
112     return SkImage::NewFromRaster(info, data->data(), info.minRowBytes(),
113                                   RasterDataHolder::Release, dataHolder);
114 }
create_codec_image()115 static SkImage* create_codec_image() {
116     SkImageInfo info;
117     SkAutoTUnref<SkData> data(create_image_data(&info));
118     SkBitmap bitmap;
119     bitmap.installPixels(info, data->writable_data(), info.minRowBytes());
120     SkAutoTUnref<SkData> src(
121         SkImageEncoder::EncodeData(bitmap, SkImageEncoder::kPNG_Type, 100));
122     return SkImage::NewFromEncoded(src);
123 }
124 #if SK_SUPPORT_GPU
create_gpu_image(GrContext * context)125 static SkImage* create_gpu_image(GrContext* context) {
126     const SkImageInfo info = SkImageInfo::MakeN32(20, 20, kOpaque_SkAlphaType);
127     SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context, SkBudgeted::kNo,
128                                                                info));
129     draw_image_test_pattern(surface->getCanvas());
130     return surface->newImageSnapshot();
131 }
132 #endif
133 
test_encode(skiatest::Reporter * reporter,SkImage * image)134 static void test_encode(skiatest::Reporter* reporter, SkImage* image) {
135     const SkIRect ir = SkIRect::MakeXYWH(5, 5, 10, 10);
136     SkAutoTUnref<SkData> origEncoded(image->encode());
137     REPORTER_ASSERT(reporter, origEncoded);
138     REPORTER_ASSERT(reporter, origEncoded->size() > 0);
139 
140     SkAutoTUnref<SkImage> decoded(SkImage::NewFromEncoded(origEncoded));
141     REPORTER_ASSERT(reporter, decoded);
142     assert_equal(reporter, image, nullptr, decoded);
143 
144     // Now see if we can instantiate an image from a subset of the surface/origEncoded
145 
146     decoded.reset(SkImage::NewFromEncoded(origEncoded, &ir));
147     REPORTER_ASSERT(reporter, decoded);
148     assert_equal(reporter, image, &ir, decoded);
149 }
150 
DEF_TEST(ImageEncode,reporter)151 DEF_TEST(ImageEncode, reporter) {
152     SkAutoTUnref<SkImage> image(create_image());
153     test_encode(reporter, image);
154 }
155 
156 #if SK_SUPPORT_GPU
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageEncode_Gpu,reporter,context)157 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageEncode_Gpu, reporter, context) {
158     SkAutoTUnref<SkImage> image(create_gpu_image(context));
159     test_encode(reporter, image);
160 }
161 #endif
162 
163 namespace {
164 
165 const char* kSerializedData = "serialized";
166 
167 class MockSerializer : public SkPixelSerializer {
168 public:
MockSerializer(SkData * (* func)())169     MockSerializer(SkData* (*func)()) : fFunc(func), fDidEncode(false) { }
170 
didEncode() const171     bool didEncode() const { return fDidEncode; }
172 
173 protected:
onUseEncodedData(const void *,size_t)174     bool onUseEncodedData(const void*, size_t) override {
175         return false;
176     }
177 
onEncode(const SkPixmap &)178     SkData* onEncode(const SkPixmap&) override {
179         fDidEncode = true;
180         return fFunc();
181     }
182 
183 private:
184     SkData* (*fFunc)();
185     bool fDidEncode;
186 
187     typedef SkPixelSerializer INHERITED;
188 };
189 
190 } // anonymous namespace
191 
192 // Test that SkImage encoding observes custom pixel serializers.
DEF_TEST(Image_Encode_Serializer,reporter)193 DEF_TEST(Image_Encode_Serializer, reporter) {
194     MockSerializer serializer([]() -> SkData* { return SkData::NewWithCString(kSerializedData); });
195     SkAutoTUnref<SkImage> image(create_image());
196     SkAutoTUnref<SkData> encoded(image->encode(&serializer));
197     SkAutoTUnref<SkData> reference(SkData::NewWithCString(kSerializedData));
198 
199     REPORTER_ASSERT(reporter, serializer.didEncode());
200     REPORTER_ASSERT(reporter, encoded);
201     REPORTER_ASSERT(reporter, encoded->size() > 0);
202     REPORTER_ASSERT(reporter, encoded->equals(reference));
203 }
204 
205 // Test that image encoding failures do not break picture serialization/deserialization.
DEF_TEST(Image_Serialize_Encoding_Failure,reporter)206 DEF_TEST(Image_Serialize_Encoding_Failure, reporter) {
207     SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(100, 100));
208     surface->getCanvas()->clear(SK_ColorGREEN);
209     SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
210     REPORTER_ASSERT(reporter, image);
211 
212     SkPictureRecorder recorder;
213     SkCanvas* canvas = recorder.beginRecording(100, 100);
214     canvas->drawImage(image, 0, 0);
215     SkAutoTUnref<SkPicture> picture(recorder.endRecording());
216     REPORTER_ASSERT(reporter, picture);
217     REPORTER_ASSERT(reporter, picture->approximateOpCount() > 0);
218 
219     MockSerializer emptySerializer([]() -> SkData* { return SkData::NewEmpty(); });
220     MockSerializer nullSerializer([]() -> SkData* { return nullptr; });
221     MockSerializer* serializers[] = { &emptySerializer, &nullSerializer };
222 
223     for (size_t i = 0; i < SK_ARRAY_COUNT(serializers); ++i) {
224         SkDynamicMemoryWStream wstream;
225         REPORTER_ASSERT(reporter, !serializers[i]->didEncode());
226         picture->serialize(&wstream, serializers[i]);
227         REPORTER_ASSERT(reporter, serializers[i]->didEncode());
228 
229         SkAutoTDelete<SkStream> rstream(wstream.detachAsStream());
230         SkAutoTUnref<SkPicture> deserialized(SkPicture::CreateFromStream(rstream));
231         REPORTER_ASSERT(reporter, deserialized);
232         REPORTER_ASSERT(reporter, deserialized->approximateOpCount() > 0);
233     }
234 }
235 
DEF_TEST(Image_NewRasterCopy,reporter)236 DEF_TEST(Image_NewRasterCopy, reporter) {
237     const SkPMColor red =   SkPackARGB32(0xFF, 0xFF, 0, 0);
238     const SkPMColor green = SkPackARGB32(0xFF, 0, 0xFF, 0);
239     const SkPMColor blue =  SkPackARGB32(0xFF, 0, 0, 0xFF);
240     SkPMColor colors[] = { red, green, blue, 0 };
241     SkAutoTUnref<SkColorTable> ctable(new SkColorTable(colors, SK_ARRAY_COUNT(colors)));
242     // The colortable made a copy, so we can trash the original colors
243     memset(colors, 0xFF, sizeof(colors));
244 
245     const SkImageInfo srcInfo = SkImageInfo::Make(2, 2, kIndex_8_SkColorType, kPremul_SkAlphaType);
246     const size_t srcRowBytes = 2 * sizeof(uint8_t);
247     uint8_t indices[] = { 0, 1, 2, 3 };
248     SkAutoTUnref<SkImage> image(SkImage::NewRasterCopy(srcInfo, indices, srcRowBytes, ctable));
249     // The image made a copy, so we can trash the original indices
250     memset(indices, 0xFF, sizeof(indices));
251 
252     const SkImageInfo dstInfo = SkImageInfo::MakeN32Premul(2, 2);
253     const size_t dstRowBytes = 2 * sizeof(SkPMColor);
254     SkPMColor pixels[4];
255     memset(pixels, 0xFF, sizeof(pixels));   // init with values we don't expect
256     image->readPixels(dstInfo, pixels, dstRowBytes, 0, 0);
257     REPORTER_ASSERT(reporter, red == pixels[0]);
258     REPORTER_ASSERT(reporter, green == pixels[1]);
259     REPORTER_ASSERT(reporter, blue == pixels[2]);
260     REPORTER_ASSERT(reporter, 0 == pixels[3]);
261 }
262 
263 // Test that a draw that only partially covers the drawing surface isn't
264 // interpreted as covering the entire drawing surface (i.e., exercise one of the
265 // conditions of SkCanvas::wouldOverwriteEntireSurface()).
DEF_TEST(Image_RetainSnapshot,reporter)266 DEF_TEST(Image_RetainSnapshot, reporter) {
267     const SkPMColor red   = SkPackARGB32(0xFF, 0xFF, 0, 0);
268     const SkPMColor green = SkPackARGB32(0xFF, 0, 0xFF, 0);
269     SkImageInfo info = SkImageInfo::MakeN32Premul(2, 2);
270     SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info));
271     surface->getCanvas()->clear(0xFF00FF00);
272 
273     SkPMColor pixels[4];
274     memset(pixels, 0xFF, sizeof(pixels));   // init with values we don't expect
275     const SkImageInfo dstInfo = SkImageInfo::MakeN32Premul(2, 2);
276     const size_t dstRowBytes = 2 * sizeof(SkPMColor);
277 
278     SkAutoTUnref<SkImage> image1(surface->newImageSnapshot());
279     REPORTER_ASSERT(reporter, image1->readPixels(dstInfo, pixels, dstRowBytes, 0, 0));
280     for (size_t i = 0; i < SK_ARRAY_COUNT(pixels); ++i) {
281         REPORTER_ASSERT(reporter, pixels[i] == green);
282     }
283 
284     SkPaint paint;
285     paint.setXfermodeMode(SkXfermode::kSrc_Mode);
286     paint.setColor(SK_ColorRED);
287 
288     surface->getCanvas()->drawRect(SkRect::MakeXYWH(1, 1, 1, 1), paint);
289 
290     SkAutoTUnref<SkImage> image2(surface->newImageSnapshot());
291     REPORTER_ASSERT(reporter, image2->readPixels(dstInfo, pixels, dstRowBytes, 0, 0));
292     REPORTER_ASSERT(reporter, pixels[0] == green);
293     REPORTER_ASSERT(reporter, pixels[1] == green);
294     REPORTER_ASSERT(reporter, pixels[2] == green);
295     REPORTER_ASSERT(reporter, pixels[3] == red);
296 }
297 
298 /////////////////////////////////////////////////////////////////////////////////////////////////
299 
make_bitmap_mutable(SkBitmap * bm)300 static void make_bitmap_mutable(SkBitmap* bm) {
301     bm->allocN32Pixels(10, 10);
302 }
303 
make_bitmap_immutable(SkBitmap * bm)304 static void make_bitmap_immutable(SkBitmap* bm) {
305     bm->allocN32Pixels(10, 10);
306     bm->setImmutable();
307 }
308 
DEF_TEST(image_newfrombitmap,reporter)309 DEF_TEST(image_newfrombitmap, reporter) {
310     const struct {
311         void (*fMakeProc)(SkBitmap*);
312         bool fExpectPeekSuccess;
313         bool fExpectSharedID;
314         bool fExpectLazy;
315     } rec[] = {
316         { make_bitmap_mutable,      true,   false, false },
317         { make_bitmap_immutable,    true,   true,  false },
318     };
319 
320     for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) {
321         SkBitmap bm;
322         rec[i].fMakeProc(&bm);
323 
324         SkAutoTUnref<SkImage> image(SkImage::NewFromBitmap(bm));
325         SkPixmap pmap;
326 
327         const bool sharedID = (image->uniqueID() == bm.getGenerationID());
328         REPORTER_ASSERT(reporter, sharedID == rec[i].fExpectSharedID);
329 
330         const bool peekSuccess = image->peekPixels(&pmap);
331         REPORTER_ASSERT(reporter, peekSuccess == rec[i].fExpectPeekSuccess);
332 
333         const bool lazy = image->isLazyGenerated();
334         REPORTER_ASSERT(reporter, lazy == rec[i].fExpectLazy);
335     }
336 }
337 
338 ///////////////////////////////////////////////////////////////////////////////////////////////////
339 #if SK_SUPPORT_GPU
340 
341 #include "SkBitmapCache.h"
342 
343 /*
344  *  This tests the caching (and preemptive purge) of the raster equivalent of a gpu-image.
345  *  We cache it for performance when drawing into a raster surface.
346  *
347  *  A cleaner test would know if each drawImage call triggered a read-back from the gpu,
348  *  but we don't have that facility (at the moment) so we use a little internal knowledge
349  *  of *how* the raster version is cached, and look for that.
350  */
DEF_GPUTEST_FOR_NATIVE_CONTEXT(SkImage_Gpu2Cpu,reporter,context)351 DEF_GPUTEST_FOR_NATIVE_CONTEXT(SkImage_Gpu2Cpu, reporter, context) {
352     SkImageInfo info = SkImageInfo::MakeN32(20, 20, kOpaque_SkAlphaType);
353     SkAutoTUnref<SkImage> image(create_gpu_image(context));
354     const uint32_t uniqueID = image->uniqueID();
355 
356     SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info));
357 
358     // now we can test drawing a gpu-backed image into a cpu-backed surface
359 
360     {
361         SkBitmap cachedBitmap;
362         REPORTER_ASSERT(reporter, !SkBitmapCache::Find(uniqueID, &cachedBitmap));
363     }
364 
365     surface->getCanvas()->drawImage(image, 0, 0);
366     {
367         SkBitmap cachedBitmap;
368         if (SkBitmapCache::Find(uniqueID, &cachedBitmap)) {
369             REPORTER_ASSERT(reporter, cachedBitmap.getGenerationID() == uniqueID);
370             REPORTER_ASSERT(reporter, cachedBitmap.isImmutable());
371             REPORTER_ASSERT(reporter, cachedBitmap.getPixels());
372         } else {
373             // unexpected, but not really a bug, since the cache is global and this test may be
374             // run w/ other threads competing for its budget.
375             SkDebugf("SkImage_Gpu2Cpu : cachedBitmap was already purged\n");
376         }
377     }
378 
379     image.reset(nullptr);
380     {
381         SkBitmap cachedBitmap;
382         REPORTER_ASSERT(reporter, !SkBitmapCache::Find(uniqueID, &cachedBitmap));
383     }
384 }
385 
DEF_GPUTEST_FOR_NATIVE_CONTEXT(SkImage_newTextureImage,reporter,context,glContext)386 DEF_GPUTEST_FOR_NATIVE_CONTEXT(SkImage_newTextureImage, reporter, context, glContext) {
387     GrContextFactory otherFactory;
388     GrContextFactory::ContextInfo otherContextInfo =
389         otherFactory.getContextInfo(GrContextFactory::kNative_GLContextType);
390     glContext->makeCurrent();
391 
392     std::function<SkImage*()> imageFactories[] = {
393         create_image,
394         create_codec_image,
395         create_data_image,
396         // Create an image from a picture.
397         create_picture_image,
398         // Create a texture image.
399         [context] { return create_gpu_image(context); },
400         // Create a texture image in a another GrContext.
401         [glContext, otherContextInfo] {
402             otherContextInfo.fGLContext->makeCurrent();
403             SkImage* otherContextImage = create_gpu_image(otherContextInfo.fGrContext);
404             glContext->makeCurrent();
405             return otherContextImage;
406         }
407     };
408 
409     for (auto factory : imageFactories) {
410         SkAutoTUnref<SkImage> image(factory());
411         if (!image) {
412             ERRORF(reporter, "Error creating image.");
413             continue;
414         }
415         GrTexture* origTexture = as_IB(image)->peekTexture();
416 
417         SkAutoTUnref<SkImage> texImage(image->newTextureImage(context));
418         if (!texImage) {
419             // We execpt to fail if image comes from a different GrContext.
420             if (!origTexture || origTexture->getContext() == context) {
421                 ERRORF(reporter, "newTextureImage failed.");
422             }
423             continue;
424         }
425         GrTexture* copyTexture = as_IB(texImage)->peekTexture();
426         if (!copyTexture) {
427             ERRORF(reporter, "newTextureImage returned non-texture image.");
428             continue;
429         }
430         if (origTexture) {
431             if (origTexture != copyTexture) {
432                 ERRORF(reporter, "newTextureImage made unnecessary texture copy.");
433             }
434         }
435         if (image->width() != texImage->width() || image->height() != texImage->height()) {
436             ERRORF(reporter, "newTextureImage changed the image size.");
437         }
438         if (image->isOpaque() != texImage->isOpaque()) {
439             ERRORF(reporter, "newTextureImage changed image opaqueness.");
440         }
441     }
442 }
443 #endif
444 
445 // https://bug.skia.org/4390
DEF_TEST(ImageFromIndex8Bitmap,r)446 DEF_TEST(ImageFromIndex8Bitmap, r) {
447     SkPMColor pmColors[1] = {SkPreMultiplyColor(SK_ColorWHITE)};
448     SkBitmap bm;
449     SkAutoTUnref<SkColorTable> ctable(
450             new SkColorTable(pmColors, SK_ARRAY_COUNT(pmColors)));
451     SkImageInfo info =
452             SkImageInfo::Make(1, 1, kIndex_8_SkColorType, kPremul_SkAlphaType);
453     bm.allocPixels(info, nullptr, ctable);
454     SkAutoLockPixels autoLockPixels(bm);
455     *bm.getAddr8(0, 0) = 0;
456     SkAutoTUnref<SkImage> img(SkImage::NewFromBitmap(bm));
457     REPORTER_ASSERT(r, img.get() != nullptr);
458 }
459 
460 class EmptyGenerator : public SkImageGenerator {
461 public:
EmptyGenerator()462     EmptyGenerator() : SkImageGenerator(SkImageInfo::MakeN32Premul(0, 0)) {}
463 };
464 
DEF_TEST(ImageEmpty,reporter)465 DEF_TEST(ImageEmpty, reporter) {
466     const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType);
467     REPORTER_ASSERT(reporter, nullptr == SkImage::NewRasterCopy(info, nullptr, 0));
468     REPORTER_ASSERT(reporter, nullptr == SkImage::NewRasterData(info, nullptr, 0));
469     REPORTER_ASSERT(reporter, nullptr == SkImage::NewFromRaster(info, nullptr, 0, nullptr, nullptr));
470     REPORTER_ASSERT(reporter, nullptr == SkImage::NewFromGenerator(new EmptyGenerator));
471 }
472 
DEF_TEST(ImageDataRef,reporter)473 DEF_TEST(ImageDataRef, reporter) {
474     SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
475     size_t rowBytes = info.minRowBytes();
476     size_t size = info.getSafeSize(rowBytes);
477     SkData* data = SkData::NewUninitialized(size);
478     REPORTER_ASSERT(reporter, data->unique());
479     SkImage* image = SkImage::NewRasterData(info, data, rowBytes);
480     REPORTER_ASSERT(reporter, !data->unique());
481     image->unref();
482     REPORTER_ASSERT(reporter, data->unique());
483     data->unref();
484 }
485 
has_pixels(const SkPMColor pixels[],int count,SkPMColor expected)486 static bool has_pixels(const SkPMColor pixels[], int count, SkPMColor expected) {
487     for (int i = 0; i < count; ++i) {
488         if (pixels[i] != expected) {
489             return false;
490         }
491     }
492     return true;
493 }
494 
test_read_pixels(skiatest::Reporter * reporter,SkImage * image)495 static void test_read_pixels(skiatest::Reporter* reporter, SkImage* image) {
496     const SkPMColor expected = SkPreMultiplyColor(SK_ColorWHITE);
497     const SkPMColor notExpected = ~expected;
498 
499     const int w = 2, h = 2;
500     const size_t rowBytes = w * sizeof(SkPMColor);
501     SkPMColor pixels[w*h];
502 
503     SkImageInfo info;
504 
505     info = SkImageInfo::MakeUnknown(w, h);
506     REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, 0, 0));
507 
508     // out-of-bounds should fail
509     info = SkImageInfo::MakeN32Premul(w, h);
510     REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, -w, 0));
511     REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, 0, -h));
512     REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, image->width(), 0));
513     REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, 0, image->height()));
514 
515     // top-left should succeed
516     sk_memset32(pixels, notExpected, w*h);
517     REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes, 0, 0));
518     REPORTER_ASSERT(reporter, has_pixels(pixels, w*h, expected));
519 
520     // bottom-right should succeed
521     sk_memset32(pixels, notExpected, w*h);
522     REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes,
523                                                 image->width() - w, image->height() - h));
524     REPORTER_ASSERT(reporter, has_pixels(pixels, w*h, expected));
525 
526     // partial top-left should succeed
527     sk_memset32(pixels, notExpected, w*h);
528     REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes, -1, -1));
529     REPORTER_ASSERT(reporter, pixels[3] == expected);
530     REPORTER_ASSERT(reporter, has_pixels(pixels, w*h - 1, notExpected));
531 
532     // partial bottom-right should succeed
533     sk_memset32(pixels, notExpected, w*h);
534     REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes,
535                                                 image->width() - 1, image->height() - 1));
536     REPORTER_ASSERT(reporter, pixels[0] == expected);
537     REPORTER_ASSERT(reporter, has_pixels(&pixels[1], w*h - 1, notExpected));
538 }
DEF_TEST(ImageReadPixels,reporter)539 DEF_TEST(ImageReadPixels, reporter) {
540     SkAutoTUnref<SkImage> image(create_image());
541     test_read_pixels(reporter, image);
542 
543     image.reset(create_data_image());
544     test_read_pixels(reporter, image);
545 
546     RasterDataHolder dataHolder;
547     image.reset(create_rasterproc_image(&dataHolder));
548     test_read_pixels(reporter, image);
549     image.reset();
550     REPORTER_ASSERT(reporter, 1 == dataHolder.fReleaseCount);
551 
552     image.reset(create_codec_image());
553     test_read_pixels(reporter, image);
554 }
555 #if SK_SUPPORT_GPU
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageReadPixels_Gpu,reporter,context)556 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageReadPixels_Gpu, reporter, context) {
557     SkAutoTUnref<SkImage> image(create_gpu_image(context));
558     test_read_pixels(reporter, image);
559 }
560 #endif
561 
check_legacy_bitmap(skiatest::Reporter * reporter,const SkImage * image,const SkBitmap & bitmap,SkImage::LegacyBitmapMode mode)562 static void check_legacy_bitmap(skiatest::Reporter* reporter, const SkImage* image,
563                                 const SkBitmap& bitmap, SkImage::LegacyBitmapMode mode) {
564     REPORTER_ASSERT(reporter, image->width() == bitmap.width());
565     REPORTER_ASSERT(reporter, image->height() == bitmap.height());
566     REPORTER_ASSERT(reporter, image->isOpaque() == bitmap.isOpaque());
567 
568     if (SkImage::kRO_LegacyBitmapMode == mode) {
569         REPORTER_ASSERT(reporter, bitmap.isImmutable());
570     }
571 
572     SkAutoLockPixels alp(bitmap);
573     REPORTER_ASSERT(reporter, bitmap.getPixels());
574 
575     const SkImageInfo info = SkImageInfo::MakeN32(1, 1, bitmap.alphaType());
576     SkPMColor imageColor;
577     REPORTER_ASSERT(reporter, image->readPixels(info, &imageColor, sizeof(SkPMColor), 0, 0));
578     REPORTER_ASSERT(reporter, imageColor == *bitmap.getAddr32(0, 0));
579 }
580 
test_legacy_bitmap(skiatest::Reporter * reporter,const SkImage * image,SkImage::LegacyBitmapMode mode)581 static void test_legacy_bitmap(skiatest::Reporter* reporter, const SkImage* image, SkImage::LegacyBitmapMode mode) {
582     SkBitmap bitmap;
583     REPORTER_ASSERT(reporter, image->asLegacyBitmap(&bitmap, mode));
584     check_legacy_bitmap(reporter, image, bitmap, mode);
585 
586     // Test subsetting to exercise the rowBytes logic.
587     SkBitmap tmp;
588     REPORTER_ASSERT(reporter, bitmap.extractSubset(&tmp, SkIRect::MakeWH(image->width() / 2,
589                                                                          image->height() / 2)));
590     SkAutoTUnref<SkImage> subsetImage(SkImage::NewFromBitmap(tmp));
591     REPORTER_ASSERT(reporter, subsetImage);
592 
593     SkBitmap subsetBitmap;
594     REPORTER_ASSERT(reporter, subsetImage->asLegacyBitmap(&subsetBitmap, mode));
595     check_legacy_bitmap(reporter, subsetImage, subsetBitmap, mode);
596 }
DEF_TEST(ImageLegacyBitmap,reporter)597 DEF_TEST(ImageLegacyBitmap, reporter) {
598     const SkImage::LegacyBitmapMode modes[] = {
599         SkImage::kRO_LegacyBitmapMode,
600         SkImage::kRW_LegacyBitmapMode,
601     };
602     for (auto& mode : modes) {
603         SkAutoTUnref<SkImage> image(create_image());
604         test_legacy_bitmap(reporter, image, mode);
605 
606         image.reset(create_data_image());
607         test_legacy_bitmap(reporter, image, mode);
608 
609         RasterDataHolder dataHolder;
610         image.reset(create_rasterproc_image(&dataHolder));
611         test_legacy_bitmap(reporter, image, mode);
612         image.reset();
613         REPORTER_ASSERT(reporter, 1 == dataHolder.fReleaseCount);
614 
615         image.reset(create_codec_image());
616         test_legacy_bitmap(reporter, image, mode);
617     }
618 }
619 #if SK_SUPPORT_GPU
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageLegacyBitmap_Gpu,reporter,context)620 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageLegacyBitmap_Gpu, reporter, context) {
621     const SkImage::LegacyBitmapMode modes[] = {
622         SkImage::kRO_LegacyBitmapMode,
623         SkImage::kRW_LegacyBitmapMode,
624     };
625     for (auto& mode : modes) {
626         SkAutoTUnref<SkImage> image(create_gpu_image(context));
627         test_legacy_bitmap(reporter, image, mode);
628     }
629 }
630 #endif
631 
test_peek(skiatest::Reporter * reporter,SkImage * image,bool expectPeekSuccess)632 static void test_peek(skiatest::Reporter* reporter, SkImage* image, bool expectPeekSuccess) {
633     SkImageInfo info;
634     size_t rowBytes;
635     const void* addr = image->peekPixels(&info, &rowBytes);
636     bool success = SkToBool(addr);
637     REPORTER_ASSERT(reporter, expectPeekSuccess == success);
638     if (success) {
639         REPORTER_ASSERT(reporter, 20 == info.width());
640         REPORTER_ASSERT(reporter, 20 == info.height());
641         REPORTER_ASSERT(reporter, kN32_SkColorType == info.colorType());
642         REPORTER_ASSERT(reporter, kPremul_SkAlphaType == info.alphaType() ||
643                         kOpaque_SkAlphaType == info.alphaType());
644         REPORTER_ASSERT(reporter, info.minRowBytes() <= rowBytes);
645         REPORTER_ASSERT(reporter, SkPreMultiplyColor(SK_ColorWHITE) == *(const SkPMColor*)addr);
646     }
647 }
DEF_TEST(ImagePeek,reporter)648 DEF_TEST(ImagePeek, reporter) {
649     SkAutoTUnref<SkImage> image(create_image());
650     test_peek(reporter, image, true);
651 
652     image.reset(create_data_image());
653     test_peek(reporter, image, true);
654 
655     RasterDataHolder dataHolder;
656     image.reset(create_rasterproc_image(&dataHolder));
657     test_peek(reporter, image, true);
658     image.reset();
659     REPORTER_ASSERT(reporter, 1 == dataHolder.fReleaseCount);
660 
661     image.reset(create_codec_image());
662     test_peek(reporter, image, false);
663 }
664 #if SK_SUPPORT_GPU
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImagePeek_Gpu,reporter,context)665 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImagePeek_Gpu, reporter, context) {
666     SkAutoTUnref<SkImage> image(create_gpu_image(context));
667     test_peek(reporter, image, false);
668 }
669 #endif
670 
671 #if SK_SUPPORT_GPU
672 struct TextureReleaseChecker {
TextureReleaseCheckerTextureReleaseChecker673     TextureReleaseChecker() : fReleaseCount(0) {}
674     int fReleaseCount;
ReleaseTextureReleaseChecker675     static void Release(void* self) {
676         static_cast<TextureReleaseChecker*>(self)->fReleaseCount++;
677     }
678 };
check_image_color(skiatest::Reporter * reporter,SkImage * image,SkPMColor expected)679 static void check_image_color(skiatest::Reporter* reporter, SkImage* image, SkPMColor expected) {
680     const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
681     SkPMColor pixel;
682     REPORTER_ASSERT(reporter, image->readPixels(info, &pixel, sizeof(pixel), 0, 0));
683     REPORTER_ASSERT(reporter, pixel == expected);
684 }
DEF_GPUTEST_FOR_NATIVE_CONTEXT(SkImage_NewFromTexture,reporter,context)685 DEF_GPUTEST_FOR_NATIVE_CONTEXT(SkImage_NewFromTexture, reporter, context) {
686     GrTextureProvider* provider = context->textureProvider();
687     const int w = 10;
688     const int h = 10;
689     SkPMColor storage[w * h];
690     const SkPMColor expected0 = SkPreMultiplyColor(SK_ColorRED);
691     sk_memset32(storage, expected0, w * h);
692     GrSurfaceDesc desc;
693     desc.fFlags = kRenderTarget_GrSurfaceFlag;  // needs to be a rendertarget for readpixels();
694     desc.fOrigin = kDefault_GrSurfaceOrigin;
695     desc.fWidth = w;
696     desc.fHeight = h;
697     desc.fConfig = kSkia8888_GrPixelConfig;
698     desc.fSampleCnt = 0;
699     SkAutoTUnref<GrTexture> tex(provider->createTexture(desc, SkBudgeted::kNo, storage, w * 4));
700     if (!tex) {
701         REPORTER_ASSERT(reporter, false);
702         return;
703     }
704 
705     GrBackendTextureDesc backendDesc;
706     backendDesc.fConfig = kSkia8888_GrPixelConfig;
707     backendDesc.fFlags = kRenderTarget_GrBackendTextureFlag;
708     backendDesc.fWidth = w;
709     backendDesc.fHeight = h;
710     backendDesc.fSampleCnt = 0;
711     backendDesc.fTextureHandle = tex->getTextureHandle();
712     TextureReleaseChecker releaseChecker;
713     SkAutoTUnref<SkImage> refImg(
714         SkImage::NewFromTexture(context, backendDesc, kPremul_SkAlphaType,
715                                 TextureReleaseChecker::Release, &releaseChecker));
716     SkAutoTUnref<SkImage> cpyImg(SkImage::NewFromTextureCopy(context, backendDesc,
717                                                              kPremul_SkAlphaType));
718 
719     check_image_color(reporter, refImg, expected0);
720     check_image_color(reporter, cpyImg, expected0);
721 
722     // Now lets jam new colors into our "external" texture, and see if the images notice
723     const SkPMColor expected1 = SkPreMultiplyColor(SK_ColorBLUE);
724     sk_memset32(storage, expected1, w * h);
725     tex->writePixels(0, 0, w, h, kSkia8888_GrPixelConfig, storage, GrContext::kFlushWrites_PixelOp);
726 
727     // The cpy'd one should still see the old color
728 #if 0
729     // There is no guarantee that refImg sees the new color. We are free to have made a copy. Our
730     // write pixels call violated the contract with refImg and refImg is now undefined.
731     check_image_color(reporter, refImg, expected1);
732 #endif
733     check_image_color(reporter, cpyImg, expected0);
734 
735     // Now exercise the release proc
736     REPORTER_ASSERT(reporter, 0 == releaseChecker.fReleaseCount);
737     refImg.reset(nullptr); // force a release of the image
738     REPORTER_ASSERT(reporter, 1 == releaseChecker.fReleaseCount);
739 }
740 #endif
741