blob: f646a386d995d392d4e60d28eae60162f2a7ad1b [file] [log] [blame]
reed871872f2015-06-22 12:48:26 -07001/*
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
bsalomon8e74f802016-01-30 10:01:40 -08008#include <functional>
bsalomon0d996862016-03-09 18:44:43 -08009#include <initializer_list>
bsalomon8e74f802016-01-30 10:01:40 -080010#include "DMGpuSupport.h"
11
halcanaryc56c6ef2015-09-28 11:55:28 -070012#include "SkBitmap.h"
reed871872f2015-06-22 12:48:26 -070013#include "SkCanvas.h"
14#include "SkData.h"
15#include "SkDevice.h"
16#include "SkImageEncoder.h"
kkinnunen7b94c142015-11-24 07:39:40 -080017#include "SkImageGenerator.h"
reed871872f2015-06-22 12:48:26 -070018#include "SkImage_Base.h"
fmalitac3470342015-09-04 11:36:39 -070019#include "SkPicture.h"
20#include "SkPictureRecorder.h"
fmalita2be71252015-09-03 07:17:25 -070021#include "SkPixelSerializer.h"
reed871872f2015-06-22 12:48:26 -070022#include "SkRRect.h"
fmalitac3470342015-09-04 11:36:39 -070023#include "SkStream.h"
reed871872f2015-06-22 12:48:26 -070024#include "SkSurface.h"
25#include "SkUtils.h"
26#include "Test.h"
27
reed871872f2015-06-22 12:48:26 -070028static void assert_equal(skiatest::Reporter* reporter, SkImage* a, const SkIRect* subsetA,
29 SkImage* b) {
30 const int widthA = subsetA ? subsetA->width() : a->width();
31 const int heightA = subsetA ? subsetA->height() : a->height();
32
33 REPORTER_ASSERT(reporter, widthA == b->width());
34 REPORTER_ASSERT(reporter, heightA == b->height());
reed1cb36462016-03-09 15:21:32 -080035
36 // see https://bug.skia.org/3965
37 //REPORTER_ASSERT(reporter, a->isOpaque() == b->isOpaque());
reed871872f2015-06-22 12:48:26 -070038
39 SkImageInfo info = SkImageInfo::MakeN32(widthA, heightA,
40 a->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
41 SkAutoPixmapStorage pmapA, pmapB;
42 pmapA.alloc(info);
43 pmapB.alloc(info);
44
45 const int srcX = subsetA ? subsetA->x() : 0;
46 const int srcY = subsetA ? subsetA->y() : 0;
47
48 REPORTER_ASSERT(reporter, a->readPixels(pmapA, srcX, srcY));
49 REPORTER_ASSERT(reporter, b->readPixels(pmapB, 0, 0));
50
51 const size_t widthBytes = widthA * info.bytesPerPixel();
52 for (int y = 0; y < heightA; ++y) {
53 REPORTER_ASSERT(reporter, !memcmp(pmapA.addr32(0, y), pmapB.addr32(0, y), widthBytes));
54 }
55}
kkinnunen7b94c142015-11-24 07:39:40 -080056static void draw_image_test_pattern(SkCanvas* canvas) {
reed871872f2015-06-22 12:48:26 -070057 canvas->clear(SK_ColorWHITE);
reed871872f2015-06-22 12:48:26 -070058 SkPaint paint;
59 paint.setColor(SK_ColorBLACK);
kkinnunen7b94c142015-11-24 07:39:40 -080060 canvas->drawRect(SkRect::MakeXYWH(5, 5, 10, 10), paint);
61}
62static SkImage* create_image() {
63 const SkImageInfo info = SkImageInfo::MakeN32(20, 20, kOpaque_SkAlphaType);
64 SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info));
65 draw_image_test_pattern(surface->getCanvas());
reed871872f2015-06-22 12:48:26 -070066 return surface->newImageSnapshot();
67}
bsalomon0d996862016-03-09 18:44:43 -080068#if 0
69static SkImage* create_image_565() {
70 const SkImageInfo info = SkImageInfo::Make(20, 20, kRGB_565_SkColorType, kOpaque_SkAlphaType);
71 SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info));
72 draw_image_test_pattern(surface->getCanvas());
73 return surface->newImageSnapshot();
74}
75#endif
76static SkImage* create_image_ct() {
77 SkPMColor colors[] = {
78 SkPreMultiplyARGB(0xFF, 0xFF, 0xFF, 0x00),
79 SkPreMultiplyARGB(0x80, 0x00, 0xA0, 0xFF),
80 SkPreMultiplyARGB(0xFF, 0xBB, 0x00, 0xBB)
81 };
82 SkAutoTUnref<SkColorTable> colorTable(new SkColorTable(colors, SK_ARRAY_COUNT(colors)));
83 uint8_t data[] = {
84 0, 0, 0, 0, 0,
85 0, 1, 1, 1, 0,
86 0, 1, 2, 1, 0,
87 0, 1, 1, 1, 0,
88 0, 0, 0, 0, 0
89 };
90 SkImageInfo info = SkImageInfo::Make(5, 5, kIndex_8_SkColorType, kPremul_SkAlphaType);
91 return SkImage::NewRasterCopy(info, data, 5, colorTable);
92}
kkinnunen7b94c142015-11-24 07:39:40 -080093static SkData* create_image_data(SkImageInfo* info) {
94 *info = SkImageInfo::MakeN32(20, 20, kOpaque_SkAlphaType);
95 const size_t rowBytes = info->minRowBytes();
96 SkAutoTUnref<SkData> data(SkData::NewUninitialized(rowBytes * info->height()));
97 {
98 SkBitmap bm;
99 bm.installPixels(*info, data->writable_data(), rowBytes);
100 SkCanvas canvas(bm);
101 draw_image_test_pattern(&canvas);
102 }
103 return data.release();
104}
105static SkImage* create_data_image() {
106 SkImageInfo info;
107 SkAutoTUnref<SkData> data(create_image_data(&info));
108 return SkImage::NewRasterData(info, data, info.minRowBytes());
109}
bsalomon8e74f802016-01-30 10:01:40 -0800110#if SK_SUPPORT_GPU // not gpu-specific but currently only used in GPU tests
111static SkImage* create_picture_image() {
112 SkPictureRecorder recorder;
113 SkCanvas* canvas = recorder.beginRecording(10, 10);
114 canvas->clear(SK_ColorCYAN);
115 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
116 return SkImage::NewFromPicture(picture, SkISize::Make(10, 10), nullptr, nullptr);
117};
118#endif
kkinnunen7b94c142015-11-24 07:39:40 -0800119// Want to ensure that our Release is called when the owning image is destroyed
120struct RasterDataHolder {
121 RasterDataHolder() : fReleaseCount(0) {}
122 SkAutoTUnref<SkData> fData;
123 int fReleaseCount;
124 static void Release(const void* pixels, void* context) {
125 RasterDataHolder* self = static_cast<RasterDataHolder*>(context);
126 self->fReleaseCount++;
127 self->fData.reset();
128 }
129};
130static SkImage* create_rasterproc_image(RasterDataHolder* dataHolder) {
131 SkASSERT(dataHolder);
132 SkImageInfo info;
133 SkAutoTUnref<SkData> data(create_image_data(&info));
134 dataHolder->fData.reset(SkRef(data.get()));
135 return SkImage::NewFromRaster(info, data->data(), info.minRowBytes(),
136 RasterDataHolder::Release, dataHolder);
137}
138static SkImage* create_codec_image() {
139 SkImageInfo info;
140 SkAutoTUnref<SkData> data(create_image_data(&info));
141 SkBitmap bitmap;
142 bitmap.installPixels(info, data->writable_data(), info.minRowBytes());
143 SkAutoTUnref<SkData> src(
144 SkImageEncoder::EncodeData(bitmap, SkImageEncoder::kPNG_Type, 100));
145 return SkImage::NewFromEncoded(src);
146}
147#if SK_SUPPORT_GPU
148static SkImage* create_gpu_image(GrContext* context) {
149 const SkImageInfo info = SkImageInfo::MakeN32(20, 20, kOpaque_SkAlphaType);
bsalomon5ec26ae2016-02-25 08:33:02 -0800150 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context, SkBudgeted::kNo,
kkinnunen7b94c142015-11-24 07:39:40 -0800151 info));
152 draw_image_test_pattern(surface->getCanvas());
153 return surface->newImageSnapshot();
154}
155#endif
reed871872f2015-06-22 12:48:26 -0700156
kkinnunen7b94c142015-11-24 07:39:40 -0800157static void test_encode(skiatest::Reporter* reporter, SkImage* image) {
reed871872f2015-06-22 12:48:26 -0700158 const SkIRect ir = SkIRect::MakeXYWH(5, 5, 10, 10);
kkinnunen7b94c142015-11-24 07:39:40 -0800159 SkAutoTUnref<SkData> origEncoded(image->encode());
reed871872f2015-06-22 12:48:26 -0700160 REPORTER_ASSERT(reporter, origEncoded);
161 REPORTER_ASSERT(reporter, origEncoded->size() > 0);
162
163 SkAutoTUnref<SkImage> decoded(SkImage::NewFromEncoded(origEncoded));
164 REPORTER_ASSERT(reporter, decoded);
kkinnunen7b94c142015-11-24 07:39:40 -0800165 assert_equal(reporter, image, nullptr, decoded);
reed871872f2015-06-22 12:48:26 -0700166
167 // Now see if we can instantiate an image from a subset of the surface/origEncoded
168
169 decoded.reset(SkImage::NewFromEncoded(origEncoded, &ir));
170 REPORTER_ASSERT(reporter, decoded);
kkinnunen7b94c142015-11-24 07:39:40 -0800171 assert_equal(reporter, image, &ir, decoded);
reed871872f2015-06-22 12:48:26 -0700172}
173
kkinnunen7b94c142015-11-24 07:39:40 -0800174DEF_TEST(ImageEncode, reporter) {
175 SkAutoTUnref<SkImage> image(create_image());
176 test_encode(reporter, image);
reed871872f2015-06-22 12:48:26 -0700177}
178
179#if SK_SUPPORT_GPU
kkinnunen7b94c142015-11-24 07:39:40 -0800180DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageEncode_Gpu, reporter, context) {
181 SkAutoTUnref<SkImage> image(create_gpu_image(context));
182 test_encode(reporter, image);
reed871872f2015-06-22 12:48:26 -0700183}
184#endif
reed759373a2015-07-03 21:01:10 -0700185
fmalita2be71252015-09-03 07:17:25 -0700186namespace {
187
188const char* kSerializedData = "serialized";
189
190class MockSerializer : public SkPixelSerializer {
fmalitac3470342015-09-04 11:36:39 -0700191public:
192 MockSerializer(SkData* (*func)()) : fFunc(func), fDidEncode(false) { }
193
194 bool didEncode() const { return fDidEncode; }
195
fmalita2be71252015-09-03 07:17:25 -0700196protected:
reedc9e190d2015-09-28 09:58:41 -0700197 bool onUseEncodedData(const void*, size_t) override {
198 return false;
fmalita2be71252015-09-03 07:17:25 -0700199 }
200
halcanary99073712015-12-10 09:30:57 -0800201 SkData* onEncode(const SkPixmap&) override {
fmalitac3470342015-09-04 11:36:39 -0700202 fDidEncode = true;
203 return fFunc();
fmalita2be71252015-09-03 07:17:25 -0700204 }
fmalitac3470342015-09-04 11:36:39 -0700205
206private:
207 SkData* (*fFunc)();
208 bool fDidEncode;
209
210 typedef SkPixelSerializer INHERITED;
fmalita2be71252015-09-03 07:17:25 -0700211};
212
213} // anonymous namespace
214
215// Test that SkImage encoding observes custom pixel serializers.
216DEF_TEST(Image_Encode_Serializer, reporter) {
fmalitac3470342015-09-04 11:36:39 -0700217 MockSerializer serializer([]() -> SkData* { return SkData::NewWithCString(kSerializedData); });
kkinnunen7b94c142015-11-24 07:39:40 -0800218 SkAutoTUnref<SkImage> image(create_image());
fmalita2be71252015-09-03 07:17:25 -0700219 SkAutoTUnref<SkData> encoded(image->encode(&serializer));
220 SkAutoTUnref<SkData> reference(SkData::NewWithCString(kSerializedData));
221
fmalitac3470342015-09-04 11:36:39 -0700222 REPORTER_ASSERT(reporter, serializer.didEncode());
fmalita2be71252015-09-03 07:17:25 -0700223 REPORTER_ASSERT(reporter, encoded);
224 REPORTER_ASSERT(reporter, encoded->size() > 0);
225 REPORTER_ASSERT(reporter, encoded->equals(reference));
226}
227
fmalitac3470342015-09-04 11:36:39 -0700228// Test that image encoding failures do not break picture serialization/deserialization.
229DEF_TEST(Image_Serialize_Encoding_Failure, reporter) {
230 SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(100, 100));
231 surface->getCanvas()->clear(SK_ColorGREEN);
232 SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
233 REPORTER_ASSERT(reporter, image);
234
235 SkPictureRecorder recorder;
236 SkCanvas* canvas = recorder.beginRecording(100, 100);
237 canvas->drawImage(image, 0, 0);
238 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
239 REPORTER_ASSERT(reporter, picture);
240 REPORTER_ASSERT(reporter, picture->approximateOpCount() > 0);
241
242 MockSerializer emptySerializer([]() -> SkData* { return SkData::NewEmpty(); });
243 MockSerializer nullSerializer([]() -> SkData* { return nullptr; });
244 MockSerializer* serializers[] = { &emptySerializer, &nullSerializer };
245
246 for (size_t i = 0; i < SK_ARRAY_COUNT(serializers); ++i) {
247 SkDynamicMemoryWStream wstream;
248 REPORTER_ASSERT(reporter, !serializers[i]->didEncode());
249 picture->serialize(&wstream, serializers[i]);
250 REPORTER_ASSERT(reporter, serializers[i]->didEncode());
251
252 SkAutoTDelete<SkStream> rstream(wstream.detachAsStream());
253 SkAutoTUnref<SkPicture> deserialized(SkPicture::CreateFromStream(rstream));
254 REPORTER_ASSERT(reporter, deserialized);
255 REPORTER_ASSERT(reporter, deserialized->approximateOpCount() > 0);
256 }
257}
258
reed759373a2015-07-03 21:01:10 -0700259DEF_TEST(Image_NewRasterCopy, reporter) {
260 const SkPMColor red = SkPackARGB32(0xFF, 0xFF, 0, 0);
261 const SkPMColor green = SkPackARGB32(0xFF, 0, 0xFF, 0);
262 const SkPMColor blue = SkPackARGB32(0xFF, 0, 0, 0xFF);
263 SkPMColor colors[] = { red, green, blue, 0 };
halcanary385fe4d2015-08-26 13:07:48 -0700264 SkAutoTUnref<SkColorTable> ctable(new SkColorTable(colors, SK_ARRAY_COUNT(colors)));
reed759373a2015-07-03 21:01:10 -0700265 // The colortable made a copy, so we can trash the original colors
266 memset(colors, 0xFF, sizeof(colors));
267
268 const SkImageInfo srcInfo = SkImageInfo::Make(2, 2, kIndex_8_SkColorType, kPremul_SkAlphaType);
269 const size_t srcRowBytes = 2 * sizeof(uint8_t);
270 uint8_t indices[] = { 0, 1, 2, 3 };
271 SkAutoTUnref<SkImage> image(SkImage::NewRasterCopy(srcInfo, indices, srcRowBytes, ctable));
272 // The image made a copy, so we can trash the original indices
273 memset(indices, 0xFF, sizeof(indices));
274
275 const SkImageInfo dstInfo = SkImageInfo::MakeN32Premul(2, 2);
276 const size_t dstRowBytes = 2 * sizeof(SkPMColor);
277 SkPMColor pixels[4];
278 memset(pixels, 0xFF, sizeof(pixels)); // init with values we don't expect
279 image->readPixels(dstInfo, pixels, dstRowBytes, 0, 0);
280 REPORTER_ASSERT(reporter, red == pixels[0]);
281 REPORTER_ASSERT(reporter, green == pixels[1]);
282 REPORTER_ASSERT(reporter, blue == pixels[2]);
283 REPORTER_ASSERT(reporter, 0 == pixels[3]);
284}
fmalita8c0144c2015-07-22 05:56:16 -0700285
286// Test that a draw that only partially covers the drawing surface isn't
287// interpreted as covering the entire drawing surface (i.e., exercise one of the
288// conditions of SkCanvas::wouldOverwriteEntireSurface()).
289DEF_TEST(Image_RetainSnapshot, reporter) {
290 const SkPMColor red = SkPackARGB32(0xFF, 0xFF, 0, 0);
291 const SkPMColor green = SkPackARGB32(0xFF, 0, 0xFF, 0);
292 SkImageInfo info = SkImageInfo::MakeN32Premul(2, 2);
293 SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info));
294 surface->getCanvas()->clear(0xFF00FF00);
295
296 SkPMColor pixels[4];
297 memset(pixels, 0xFF, sizeof(pixels)); // init with values we don't expect
298 const SkImageInfo dstInfo = SkImageInfo::MakeN32Premul(2, 2);
299 const size_t dstRowBytes = 2 * sizeof(SkPMColor);
300
301 SkAutoTUnref<SkImage> image1(surface->newImageSnapshot());
302 REPORTER_ASSERT(reporter, image1->readPixels(dstInfo, pixels, dstRowBytes, 0, 0));
303 for (size_t i = 0; i < SK_ARRAY_COUNT(pixels); ++i) {
304 REPORTER_ASSERT(reporter, pixels[i] == green);
305 }
306
307 SkPaint paint;
308 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
309 paint.setColor(SK_ColorRED);
310
311 surface->getCanvas()->drawRect(SkRect::MakeXYWH(1, 1, 1, 1), paint);
312
313 SkAutoTUnref<SkImage> image2(surface->newImageSnapshot());
314 REPORTER_ASSERT(reporter, image2->readPixels(dstInfo, pixels, dstRowBytes, 0, 0));
315 REPORTER_ASSERT(reporter, pixels[0] == green);
316 REPORTER_ASSERT(reporter, pixels[1] == green);
317 REPORTER_ASSERT(reporter, pixels[2] == green);
318 REPORTER_ASSERT(reporter, pixels[3] == red);
319}
reed80c772b2015-07-30 18:58:23 -0700320
321/////////////////////////////////////////////////////////////////////////////////////////////////
reed80c772b2015-07-30 18:58:23 -0700322
323static void make_bitmap_mutable(SkBitmap* bm) {
324 bm->allocN32Pixels(10, 10);
325}
326
327static void make_bitmap_immutable(SkBitmap* bm) {
328 bm->allocN32Pixels(10, 10);
329 bm->setImmutable();
330}
331
332DEF_TEST(image_newfrombitmap, reporter) {
333 const struct {
334 void (*fMakeProc)(SkBitmap*);
335 bool fExpectPeekSuccess;
336 bool fExpectSharedID;
fmalitaddbbdda2015-08-20 08:47:26 -0700337 bool fExpectLazy;
reed80c772b2015-07-30 18:58:23 -0700338 } rec[] = {
fmalitaddbbdda2015-08-20 08:47:26 -0700339 { make_bitmap_mutable, true, false, false },
340 { make_bitmap_immutable, true, true, false },
reed80c772b2015-07-30 18:58:23 -0700341 };
342
343 for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) {
344 SkBitmap bm;
345 rec[i].fMakeProc(&bm);
346
347 SkAutoTUnref<SkImage> image(SkImage::NewFromBitmap(bm));
348 SkPixmap pmap;
349
350 const bool sharedID = (image->uniqueID() == bm.getGenerationID());
351 REPORTER_ASSERT(reporter, sharedID == rec[i].fExpectSharedID);
352
reed80c772b2015-07-30 18:58:23 -0700353 const bool peekSuccess = image->peekPixels(&pmap);
354 REPORTER_ASSERT(reporter, peekSuccess == rec[i].fExpectPeekSuccess);
fmalitaddbbdda2015-08-20 08:47:26 -0700355
356 const bool lazy = image->isLazyGenerated();
357 REPORTER_ASSERT(reporter, lazy == rec[i].fExpectLazy);
reed80c772b2015-07-30 18:58:23 -0700358 }
359}
reed6f1216a2015-08-04 08:10:13 -0700360
361///////////////////////////////////////////////////////////////////////////////////////////////////
362#if SK_SUPPORT_GPU
363
reed6f1216a2015-08-04 08:10:13 -0700364#include "SkBitmapCache.h"
365
366/*
367 * This tests the caching (and preemptive purge) of the raster equivalent of a gpu-image.
368 * We cache it for performance when drawing into a raster surface.
369 *
370 * A cleaner test would know if each drawImage call triggered a read-back from the gpu,
371 * but we don't have that facility (at the moment) so we use a little internal knowledge
372 * of *how* the raster version is cached, and look for that.
373 */
kkinnunen7b94c142015-11-24 07:39:40 -0800374DEF_GPUTEST_FOR_NATIVE_CONTEXT(SkImage_Gpu2Cpu, reporter, context) {
375 SkImageInfo info = SkImageInfo::MakeN32(20, 20, kOpaque_SkAlphaType);
376 SkAutoTUnref<SkImage> image(create_gpu_image(context));
reed6f1216a2015-08-04 08:10:13 -0700377 const uint32_t uniqueID = image->uniqueID();
378
379 SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info));
380
381 // now we can test drawing a gpu-backed image into a cpu-backed surface
382
383 {
384 SkBitmap cachedBitmap;
385 REPORTER_ASSERT(reporter, !SkBitmapCache::Find(uniqueID, &cachedBitmap));
386 }
387
388 surface->getCanvas()->drawImage(image, 0, 0);
389 {
390 SkBitmap cachedBitmap;
391 if (SkBitmapCache::Find(uniqueID, &cachedBitmap)) {
392 REPORTER_ASSERT(reporter, cachedBitmap.getGenerationID() == uniqueID);
393 REPORTER_ASSERT(reporter, cachedBitmap.isImmutable());
394 REPORTER_ASSERT(reporter, cachedBitmap.getPixels());
395 } else {
396 // unexpected, but not really a bug, since the cache is global and this test may be
397 // run w/ other threads competing for its budget.
398 SkDebugf("SkImage_Gpu2Cpu : cachedBitmap was already purged\n");
399 }
400 }
401
402 image.reset(nullptr);
403 {
404 SkBitmap cachedBitmap;
405 REPORTER_ASSERT(reporter, !SkBitmapCache::Find(uniqueID, &cachedBitmap));
406 }
407}
bsalomon8e74f802016-01-30 10:01:40 -0800408
409DEF_GPUTEST_FOR_NATIVE_CONTEXT(SkImage_newTextureImage, reporter, context, glContext) {
410 GrContextFactory otherFactory;
411 GrContextFactory::ContextInfo otherContextInfo =
412 otherFactory.getContextInfo(GrContextFactory::kNative_GLContextType);
413 glContext->makeCurrent();
414
415 std::function<SkImage*()> imageFactories[] = {
416 create_image,
417 create_codec_image,
418 create_data_image,
419 // Create an image from a picture.
420 create_picture_image,
421 // Create a texture image.
422 [context] { return create_gpu_image(context); },
423 // Create a texture image in a another GrContext.
424 [glContext, otherContextInfo] {
425 otherContextInfo.fGLContext->makeCurrent();
426 SkImage* otherContextImage = create_gpu_image(otherContextInfo.fGrContext);
427 glContext->makeCurrent();
428 return otherContextImage;
429 }
430 };
431
432 for (auto factory : imageFactories) {
433 SkAutoTUnref<SkImage> image(factory());
434 if (!image) {
435 ERRORF(reporter, "Error creating image.");
436 continue;
437 }
438 GrTexture* origTexture = as_IB(image)->peekTexture();
439
440 SkAutoTUnref<SkImage> texImage(image->newTextureImage(context));
441 if (!texImage) {
442 // We execpt to fail if image comes from a different GrContext.
443 if (!origTexture || origTexture->getContext() == context) {
444 ERRORF(reporter, "newTextureImage failed.");
445 }
446 continue;
447 }
448 GrTexture* copyTexture = as_IB(texImage)->peekTexture();
449 if (!copyTexture) {
450 ERRORF(reporter, "newTextureImage returned non-texture image.");
451 continue;
452 }
453 if (origTexture) {
454 if (origTexture != copyTexture) {
455 ERRORF(reporter, "newTextureImage made unnecessary texture copy.");
456 }
457 }
458 if (image->width() != texImage->width() || image->height() != texImage->height()) {
459 ERRORF(reporter, "newTextureImage changed the image size.");
460 }
461 if (image->isOpaque() != texImage->isOpaque()) {
462 ERRORF(reporter, "newTextureImage changed image opaqueness.");
463 }
464 }
465}
reed6f1216a2015-08-04 08:10:13 -0700466#endif
halcanaryc56c6ef2015-09-28 11:55:28 -0700467
halcanary6950de62015-11-07 05:29:00 -0800468// https://bug.skia.org/4390
halcanaryc56c6ef2015-09-28 11:55:28 -0700469DEF_TEST(ImageFromIndex8Bitmap, r) {
470 SkPMColor pmColors[1] = {SkPreMultiplyColor(SK_ColorWHITE)};
471 SkBitmap bm;
472 SkAutoTUnref<SkColorTable> ctable(
473 new SkColorTable(pmColors, SK_ARRAY_COUNT(pmColors)));
474 SkImageInfo info =
475 SkImageInfo::Make(1, 1, kIndex_8_SkColorType, kPremul_SkAlphaType);
476 bm.allocPixels(info, nullptr, ctable);
477 SkAutoLockPixels autoLockPixels(bm);
478 *bm.getAddr8(0, 0) = 0;
479 SkAutoTUnref<SkImage> img(SkImage::NewFromBitmap(bm));
480 REPORTER_ASSERT(r, img.get() != nullptr);
481}
kkinnunen4e184132015-11-17 22:53:28 -0800482
kkinnunen4e184132015-11-17 22:53:28 -0800483class EmptyGenerator : public SkImageGenerator {
484public:
485 EmptyGenerator() : SkImageGenerator(SkImageInfo::MakeN32Premul(0, 0)) {}
486};
487
kkinnunen7b94c142015-11-24 07:39:40 -0800488DEF_TEST(ImageEmpty, reporter) {
kkinnunen4e184132015-11-17 22:53:28 -0800489 const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType);
kkinnunen4e184132015-11-17 22:53:28 -0800490 REPORTER_ASSERT(reporter, nullptr == SkImage::NewRasterCopy(info, nullptr, 0));
491 REPORTER_ASSERT(reporter, nullptr == SkImage::NewRasterData(info, nullptr, 0));
492 REPORTER_ASSERT(reporter, nullptr == SkImage::NewFromRaster(info, nullptr, 0, nullptr, nullptr));
493 REPORTER_ASSERT(reporter, nullptr == SkImage::NewFromGenerator(new EmptyGenerator));
494}
495
kkinnunen7b94c142015-11-24 07:39:40 -0800496DEF_TEST(ImageDataRef, reporter) {
kkinnunen4e184132015-11-17 22:53:28 -0800497 SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
498 size_t rowBytes = info.minRowBytes();
499 size_t size = info.getSafeSize(rowBytes);
500 SkData* data = SkData::NewUninitialized(size);
kkinnunen4e184132015-11-17 22:53:28 -0800501 REPORTER_ASSERT(reporter, data->unique());
502 SkImage* image = SkImage::NewRasterData(info, data, rowBytes);
503 REPORTER_ASSERT(reporter, !data->unique());
504 image->unref();
505 REPORTER_ASSERT(reporter, data->unique());
506 data->unref();
507}
508
kkinnunen4e184132015-11-17 22:53:28 -0800509static bool has_pixels(const SkPMColor pixels[], int count, SkPMColor expected) {
510 for (int i = 0; i < count; ++i) {
511 if (pixels[i] != expected) {
512 return false;
513 }
514 }
515 return true;
516}
517
kkinnunen7b94c142015-11-24 07:39:40 -0800518static void test_read_pixels(skiatest::Reporter* reporter, SkImage* image) {
519 const SkPMColor expected = SkPreMultiplyColor(SK_ColorWHITE);
kkinnunen4e184132015-11-17 22:53:28 -0800520 const SkPMColor notExpected = ~expected;
521
522 const int w = 2, h = 2;
523 const size_t rowBytes = w * sizeof(SkPMColor);
524 SkPMColor pixels[w*h];
525
526 SkImageInfo info;
527
528 info = SkImageInfo::MakeUnknown(w, h);
529 REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, 0, 0));
530
531 // out-of-bounds should fail
532 info = SkImageInfo::MakeN32Premul(w, h);
533 REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, -w, 0));
534 REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, 0, -h));
535 REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, image->width(), 0));
536 REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, 0, image->height()));
537
538 // top-left should succeed
kkinnunen7b94c142015-11-24 07:39:40 -0800539 sk_memset32(pixels, notExpected, w*h);
kkinnunen4e184132015-11-17 22:53:28 -0800540 REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes, 0, 0));
541 REPORTER_ASSERT(reporter, has_pixels(pixels, w*h, expected));
542
543 // bottom-right should succeed
kkinnunen7b94c142015-11-24 07:39:40 -0800544 sk_memset32(pixels, notExpected, w*h);
kkinnunen4e184132015-11-17 22:53:28 -0800545 REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes,
546 image->width() - w, image->height() - h));
547 REPORTER_ASSERT(reporter, has_pixels(pixels, w*h, expected));
548
549 // partial top-left should succeed
kkinnunen7b94c142015-11-24 07:39:40 -0800550 sk_memset32(pixels, notExpected, w*h);
kkinnunen4e184132015-11-17 22:53:28 -0800551 REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes, -1, -1));
552 REPORTER_ASSERT(reporter, pixels[3] == expected);
553 REPORTER_ASSERT(reporter, has_pixels(pixels, w*h - 1, notExpected));
554
555 // partial bottom-right should succeed
kkinnunen7b94c142015-11-24 07:39:40 -0800556 sk_memset32(pixels, notExpected, w*h);
kkinnunen4e184132015-11-17 22:53:28 -0800557 REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes,
558 image->width() - 1, image->height() - 1));
559 REPORTER_ASSERT(reporter, pixels[0] == expected);
560 REPORTER_ASSERT(reporter, has_pixels(&pixels[1], w*h - 1, notExpected));
561}
kkinnunen7b94c142015-11-24 07:39:40 -0800562DEF_TEST(ImageReadPixels, reporter) {
563 SkAutoTUnref<SkImage> image(create_image());
564 test_read_pixels(reporter, image);
565
566 image.reset(create_data_image());
567 test_read_pixels(reporter, image);
568
569 RasterDataHolder dataHolder;
570 image.reset(create_rasterproc_image(&dataHolder));
571 test_read_pixels(reporter, image);
572 image.reset();
573 REPORTER_ASSERT(reporter, 1 == dataHolder.fReleaseCount);
574
575 image.reset(create_codec_image());
576 test_read_pixels(reporter, image);
577}
578#if SK_SUPPORT_GPU
579DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageReadPixels_Gpu, reporter, context) {
580 SkAutoTUnref<SkImage> image(create_gpu_image(context));
581 test_read_pixels(reporter, image);
582}
583#endif
kkinnunen4e184132015-11-17 22:53:28 -0800584
585static void check_legacy_bitmap(skiatest::Reporter* reporter, const SkImage* image,
586 const SkBitmap& bitmap, SkImage::LegacyBitmapMode mode) {
587 REPORTER_ASSERT(reporter, image->width() == bitmap.width());
588 REPORTER_ASSERT(reporter, image->height() == bitmap.height());
589 REPORTER_ASSERT(reporter, image->isOpaque() == bitmap.isOpaque());
590
591 if (SkImage::kRO_LegacyBitmapMode == mode) {
592 REPORTER_ASSERT(reporter, bitmap.isImmutable());
593 }
594
595 SkAutoLockPixels alp(bitmap);
596 REPORTER_ASSERT(reporter, bitmap.getPixels());
597
598 const SkImageInfo info = SkImageInfo::MakeN32(1, 1, bitmap.alphaType());
599 SkPMColor imageColor;
600 REPORTER_ASSERT(reporter, image->readPixels(info, &imageColor, sizeof(SkPMColor), 0, 0));
601 REPORTER_ASSERT(reporter, imageColor == *bitmap.getAddr32(0, 0));
602}
603
kkinnunen7b94c142015-11-24 07:39:40 -0800604static void test_legacy_bitmap(skiatest::Reporter* reporter, const SkImage* image, SkImage::LegacyBitmapMode mode) {
605 SkBitmap bitmap;
606 REPORTER_ASSERT(reporter, image->asLegacyBitmap(&bitmap, mode));
607 check_legacy_bitmap(reporter, image, bitmap, mode);
608
609 // Test subsetting to exercise the rowBytes logic.
610 SkBitmap tmp;
611 REPORTER_ASSERT(reporter, bitmap.extractSubset(&tmp, SkIRect::MakeWH(image->width() / 2,
612 image->height() / 2)));
613 SkAutoTUnref<SkImage> subsetImage(SkImage::NewFromBitmap(tmp));
614 REPORTER_ASSERT(reporter, subsetImage);
615
616 SkBitmap subsetBitmap;
617 REPORTER_ASSERT(reporter, subsetImage->asLegacyBitmap(&subsetBitmap, mode));
618 check_legacy_bitmap(reporter, subsetImage, subsetBitmap, mode);
619}
620DEF_TEST(ImageLegacyBitmap, reporter) {
kkinnunen4e184132015-11-17 22:53:28 -0800621 const SkImage::LegacyBitmapMode modes[] = {
622 SkImage::kRO_LegacyBitmapMode,
623 SkImage::kRW_LegacyBitmapMode,
624 };
kkinnunen7b94c142015-11-24 07:39:40 -0800625 for (auto& mode : modes) {
626 SkAutoTUnref<SkImage> image(create_image());
627 test_legacy_bitmap(reporter, image, mode);
kkinnunen4e184132015-11-17 22:53:28 -0800628
kkinnunen7b94c142015-11-24 07:39:40 -0800629 image.reset(create_data_image());
630 test_legacy_bitmap(reporter, image, mode);
kkinnunen4e184132015-11-17 22:53:28 -0800631
kkinnunen7b94c142015-11-24 07:39:40 -0800632 RasterDataHolder dataHolder;
633 image.reset(create_rasterproc_image(&dataHolder));
634 test_legacy_bitmap(reporter, image, mode);
635 image.reset();
636 REPORTER_ASSERT(reporter, 1 == dataHolder.fReleaseCount);
637
638 image.reset(create_codec_image());
639 test_legacy_bitmap(reporter, image, mode);
kkinnunen4e184132015-11-17 22:53:28 -0800640 }
641}
kkinnunen4e184132015-11-17 22:53:28 -0800642#if SK_SUPPORT_GPU
kkinnunen7b94c142015-11-24 07:39:40 -0800643DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageLegacyBitmap_Gpu, reporter, context) {
644 const SkImage::LegacyBitmapMode modes[] = {
645 SkImage::kRO_LegacyBitmapMode,
646 SkImage::kRW_LegacyBitmapMode,
647 };
648 for (auto& mode : modes) {
649 SkAutoTUnref<SkImage> image(create_gpu_image(context));
650 test_legacy_bitmap(reporter, image, mode);
kkinnunen4e184132015-11-17 22:53:28 -0800651 }
kkinnunen7b94c142015-11-24 07:39:40 -0800652}
kkinnunen4e184132015-11-17 22:53:28 -0800653#endif
654
kkinnunen7b94c142015-11-24 07:39:40 -0800655static void test_peek(skiatest::Reporter* reporter, SkImage* image, bool expectPeekSuccess) {
reed6ceeebd2016-03-09 14:26:26 -0800656 SkPixmap pm;
657 bool success = image->peekPixels(&pm);
kkinnunen7b94c142015-11-24 07:39:40 -0800658 REPORTER_ASSERT(reporter, expectPeekSuccess == success);
659 if (success) {
reed6ceeebd2016-03-09 14:26:26 -0800660 const SkImageInfo& info = pm.info();
kkinnunen7b94c142015-11-24 07:39:40 -0800661 REPORTER_ASSERT(reporter, 20 == info.width());
662 REPORTER_ASSERT(reporter, 20 == info.height());
663 REPORTER_ASSERT(reporter, kN32_SkColorType == info.colorType());
664 REPORTER_ASSERT(reporter, kPremul_SkAlphaType == info.alphaType() ||
665 kOpaque_SkAlphaType == info.alphaType());
reed6ceeebd2016-03-09 14:26:26 -0800666 REPORTER_ASSERT(reporter, info.minRowBytes() <= pm.rowBytes());
667 REPORTER_ASSERT(reporter, SkPreMultiplyColor(SK_ColorWHITE) == *pm.addr32(0, 0));
kkinnunen4e184132015-11-17 22:53:28 -0800668 }
kkinnunen7b94c142015-11-24 07:39:40 -0800669}
670DEF_TEST(ImagePeek, reporter) {
671 SkAutoTUnref<SkImage> image(create_image());
672 test_peek(reporter, image, true);
673
674 image.reset(create_data_image());
675 test_peek(reporter, image, true);
676
677 RasterDataHolder dataHolder;
678 image.reset(create_rasterproc_image(&dataHolder));
679 test_peek(reporter, image, true);
680 image.reset();
681 REPORTER_ASSERT(reporter, 1 == dataHolder.fReleaseCount);
682
683 image.reset(create_codec_image());
684 test_peek(reporter, image, false);
kkinnunen4e184132015-11-17 22:53:28 -0800685}
686#if SK_SUPPORT_GPU
kkinnunen7b94c142015-11-24 07:39:40 -0800687DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImagePeek_Gpu, reporter, context) {
688 SkAutoTUnref<SkImage> image(create_gpu_image(context));
689 test_peek(reporter, image, false);
690}
691#endif
kkinnunen4e184132015-11-17 22:53:28 -0800692
kkinnunen7b94c142015-11-24 07:39:40 -0800693#if SK_SUPPORT_GPU
694struct TextureReleaseChecker {
695 TextureReleaseChecker() : fReleaseCount(0) {}
696 int fReleaseCount;
697 static void Release(void* self) {
698 static_cast<TextureReleaseChecker*>(self)->fReleaseCount++;
kkinnunen4e184132015-11-17 22:53:28 -0800699 }
700};
kkinnunen7b94c142015-11-24 07:39:40 -0800701static void check_image_color(skiatest::Reporter* reporter, SkImage* image, SkPMColor expected) {
kkinnunen4e184132015-11-17 22:53:28 -0800702 const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
703 SkPMColor pixel;
704 REPORTER_ASSERT(reporter, image->readPixels(info, &pixel, sizeof(pixel), 0, 0));
705 REPORTER_ASSERT(reporter, pixel == expected);
706}
kkinnunen7b94c142015-11-24 07:39:40 -0800707DEF_GPUTEST_FOR_NATIVE_CONTEXT(SkImage_NewFromTexture, reporter, context) {
708 GrTextureProvider* provider = context->textureProvider();
kkinnunen4e184132015-11-17 22:53:28 -0800709 const int w = 10;
710 const int h = 10;
711 SkPMColor storage[w * h];
712 const SkPMColor expected0 = SkPreMultiplyColor(SK_ColorRED);
713 sk_memset32(storage, expected0, w * h);
kkinnunen4e184132015-11-17 22:53:28 -0800714 GrSurfaceDesc desc;
715 desc.fFlags = kRenderTarget_GrSurfaceFlag; // needs to be a rendertarget for readpixels();
716 desc.fOrigin = kDefault_GrSurfaceOrigin;
717 desc.fWidth = w;
718 desc.fHeight = h;
719 desc.fConfig = kSkia8888_GrPixelConfig;
720 desc.fSampleCnt = 0;
bsalomon5ec26ae2016-02-25 08:33:02 -0800721 SkAutoTUnref<GrTexture> tex(provider->createTexture(desc, SkBudgeted::kNo, storage, w * 4));
kkinnunen4e184132015-11-17 22:53:28 -0800722 if (!tex) {
723 REPORTER_ASSERT(reporter, false);
724 return;
725 }
726
kkinnunen7b94c142015-11-24 07:39:40 -0800727 GrBackendTextureDesc backendDesc;
728 backendDesc.fConfig = kSkia8888_GrPixelConfig;
729 backendDesc.fFlags = kRenderTarget_GrBackendTextureFlag;
730 backendDesc.fWidth = w;
731 backendDesc.fHeight = h;
732 backendDesc.fSampleCnt = 0;
733 backendDesc.fTextureHandle = tex->getTextureHandle();
734 TextureReleaseChecker releaseChecker;
735 SkAutoTUnref<SkImage> refImg(
736 SkImage::NewFromTexture(context, backendDesc, kPremul_SkAlphaType,
737 TextureReleaseChecker::Release, &releaseChecker));
738 SkAutoTUnref<SkImage> cpyImg(SkImage::NewFromTextureCopy(context, backendDesc,
739 kPremul_SkAlphaType));
kkinnunen4e184132015-11-17 22:53:28 -0800740
kkinnunen7b94c142015-11-24 07:39:40 -0800741 check_image_color(reporter, refImg, expected0);
742 check_image_color(reporter, cpyImg, expected0);
kkinnunen4e184132015-11-17 22:53:28 -0800743
744 // Now lets jam new colors into our "external" texture, and see if the images notice
745 const SkPMColor expected1 = SkPreMultiplyColor(SK_ColorBLUE);
746 sk_memset32(storage, expected1, w * h);
747 tex->writePixels(0, 0, w, h, kSkia8888_GrPixelConfig, storage, GrContext::kFlushWrites_PixelOp);
748
749 // The cpy'd one should still see the old color
750#if 0
751 // There is no guarantee that refImg sees the new color. We are free to have made a copy. Our
752 // write pixels call violated the contract with refImg and refImg is now undefined.
kkinnunen7b94c142015-11-24 07:39:40 -0800753 check_image_color(reporter, refImg, expected1);
kkinnunen4e184132015-11-17 22:53:28 -0800754#endif
kkinnunen7b94c142015-11-24 07:39:40 -0800755 check_image_color(reporter, cpyImg, expected0);
kkinnunen4e184132015-11-17 22:53:28 -0800756
757 // Now exercise the release proc
kkinnunen7b94c142015-11-24 07:39:40 -0800758 REPORTER_ASSERT(reporter, 0 == releaseChecker.fReleaseCount);
kkinnunen4e184132015-11-17 22:53:28 -0800759 refImg.reset(nullptr); // force a release of the image
kkinnunen7b94c142015-11-24 07:39:40 -0800760 REPORTER_ASSERT(reporter, 1 == releaseChecker.fReleaseCount);
kkinnunen4e184132015-11-17 22:53:28 -0800761}
bsalomon0d996862016-03-09 18:44:43 -0800762
763static void check_images_same(skiatest::Reporter* reporter, const SkImage* a, const SkImage* b) {
764 if (a->width() != b->width() || a->height() != b->height()) {
765 ERRORF(reporter, "Images must have the same size");
766 return;
767 }
768 if (a->isOpaque() != b->isOpaque()) {
769 ERRORF(reporter, "Images must have the same opaquness");
770 return;
771 }
772
773 SkImageInfo info = SkImageInfo::MakeN32Premul(a->width(), a->height());
774 SkAutoPixmapStorage apm;
775 SkAutoPixmapStorage bpm;
776
777 apm.alloc(info);
778 bpm.alloc(info);
779
780 if (!a->readPixels(apm, 0, 0)) {
781 ERRORF(reporter, "Could not read image a's pixels");
782 return;
783 }
784 if (!b->readPixels(bpm, 0, 0)) {
785 ERRORF(reporter, "Could not read image b's pixels");
786 return;
787 }
788
789 for (auto y = 0; y < info.height(); ++y) {
790 for (auto x = 0; x < info.width(); ++x) {
791 uint32_t pixelA = *apm.addr32(x, y);
792 uint32_t pixelB = *bpm.addr32(x, y);
793 if (pixelA != pixelB) {
794 ERRORF(reporter, "Expected image pixels to be the same. At %d,%d 0x%08x != 0x%08x",
795 x, y, pixelA, pixelB);
796 return;
797 }
798 }
799 }
800}
801
802DEF_GPUTEST_FOR_RENDERING_CONTEXTS(NewTextureFromPixmap, reporter, context) {
803 for (auto create : {&create_image
804#if 0 // read pixels failing for non RT formats (565 not a RT on some desktop GLs).
805 , &create_image_565
806#endif
807 , &create_image_ct
808 }) {
809 SkAutoTUnref<SkImage> image((*create)());
810 if (!image) {
811 ERRORF(reporter, "Could not create image");
812 return;
813 }
814
815 SkPixmap pixmap;
816 if (!image->peekPixels(&pixmap)) {
817 ERRORF(reporter, "peek failed");
818 } else {
819 SkAutoTUnref<SkImage> texImage(SkImage::NewTextureFromPixmap(context, pixmap,
820 SkBudgeted::kNo));
821 if (!texImage) {
822 ERRORF(reporter, "NewTextureFromPixmap failed.");
823 } else {
824 check_images_same(reporter, image, texImage);
825 }
826 }
827 }
828}
829
kkinnunen4e184132015-11-17 22:53:28 -0800830#endif