Home | History | Annotate | Download | only in tests
      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 <initializer_list>
     10 #include <vector>
     11 
     12 #include "SkAutoPixmapStorage.h"
     13 #include "SkBitmap.h"
     14 #include "SkCanvas.h"
     15 #include "SkColorSpacePriv.h"
     16 #include "SkData.h"
     17 #include "SkImageEncoder.h"
     18 #include "SkImageGenerator.h"
     19 #include "SkImage_Base.h"
     20 #include "SkImagePriv.h"
     21 #include "SkMakeUnique.h"
     22 #include "SkPicture.h"
     23 #include "SkPictureRecorder.h"
     24 #include "SkPixelSerializer.h"
     25 #include "SkRRect.h"
     26 #include "SkStream.h"
     27 #include "SkSurface.h"
     28 #include "SkUtils.h"
     29 #include "Test.h"
     30 
     31 #include "Resources.h"
     32 #include "sk_tool_utils.h"
     33 
     34 #if SK_SUPPORT_GPU
     35 #include "GrContextPriv.h"
     36 #include "GrGpu.h"
     37 #include "GrResourceCache.h"
     38 #include "GrTest.h"
     39 #include "GrTexture.h"
     40 #endif
     41 
     42 using namespace sk_gpu_test;
     43 
     44 SkImageInfo read_pixels_info(SkImage* image) {
     45     if (as_IB(image)->onImageInfo().colorSpace()) {
     46         return SkImageInfo::MakeS32(image->width(), image->height(), image->alphaType());
     47     }
     48 
     49     return SkImageInfo::MakeN32(image->width(), image->height(), image->alphaType());
     50 }
     51 
     52 static void assert_equal(skiatest::Reporter* reporter, SkImage* a, const SkIRect* subsetA,
     53                          SkImage* b) {
     54     const int widthA = subsetA ? subsetA->width() : a->width();
     55     const int heightA = subsetA ? subsetA->height() : a->height();
     56 
     57     REPORTER_ASSERT(reporter, widthA == b->width());
     58     REPORTER_ASSERT(reporter, heightA == b->height());
     59 
     60     // see https://bug.skia.org/3965
     61     //REPORTER_ASSERT(reporter, a->isOpaque() == b->isOpaque());
     62 
     63     SkAutoPixmapStorage pmapA, pmapB;
     64     pmapA.alloc(read_pixels_info(a));
     65     pmapB.alloc(read_pixels_info(b));
     66 
     67     const int srcX = subsetA ? subsetA->x() : 0;
     68     const int srcY = subsetA ? subsetA->y() : 0;
     69 
     70     REPORTER_ASSERT(reporter, a->readPixels(pmapA, srcX, srcY));
     71     REPORTER_ASSERT(reporter, b->readPixels(pmapB, 0, 0));
     72 
     73     const size_t widthBytes = widthA * 4;
     74     for (int y = 0; y < heightA; ++y) {
     75         REPORTER_ASSERT(reporter, !memcmp(pmapA.addr32(0, y), pmapB.addr32(0, y), widthBytes));
     76     }
     77 }
     78 static void draw_image_test_pattern(SkCanvas* canvas) {
     79     canvas->clear(SK_ColorWHITE);
     80     SkPaint paint;
     81     paint.setColor(SK_ColorBLACK);
     82     canvas->drawRect(SkRect::MakeXYWH(5, 5, 10, 10), paint);
     83 }
     84 static sk_sp<SkImage> create_image() {
     85     const SkImageInfo info = SkImageInfo::MakeN32(20, 20, kOpaque_SkAlphaType);
     86     auto surface(SkSurface::MakeRaster(info));
     87     draw_image_test_pattern(surface->getCanvas());
     88     return surface->makeImageSnapshot();
     89 }
     90 static sk_sp<SkData> create_image_data(SkImageInfo* info) {
     91     *info = SkImageInfo::MakeN32(20, 20, kOpaque_SkAlphaType);
     92     const size_t rowBytes = info->minRowBytes();
     93     sk_sp<SkData> data(SkData::MakeUninitialized(rowBytes * info->height()));
     94     {
     95         SkBitmap bm;
     96         bm.installPixels(*info, data->writable_data(), rowBytes);
     97         SkCanvas canvas(bm);
     98         draw_image_test_pattern(&canvas);
     99     }
    100     return data;
    101 }
    102 static sk_sp<SkImage> create_data_image() {
    103     SkImageInfo info;
    104     sk_sp<SkData> data(create_image_data(&info));
    105     return SkImage::MakeRasterData(info, std::move(data), info.minRowBytes());
    106 }
    107 #if SK_SUPPORT_GPU // not gpu-specific but currently only used in GPU tests
    108 static sk_sp<SkImage> create_image_large(int maxTextureSize) {
    109     const SkImageInfo info = SkImageInfo::MakeN32(maxTextureSize + 1, 32, kOpaque_SkAlphaType);
    110     auto surface(SkSurface::MakeRaster(info));
    111     surface->getCanvas()->clear(SK_ColorWHITE);
    112     SkPaint paint;
    113     paint.setColor(SK_ColorBLACK);
    114     surface->getCanvas()->drawRect(SkRect::MakeXYWH(4000, 2, 28000, 30), paint);
    115     return surface->makeImageSnapshot();
    116 }
    117 static sk_sp<SkImage> create_picture_image() {
    118     SkPictureRecorder recorder;
    119     SkCanvas* canvas = recorder.beginRecording(10, 10);
    120     canvas->clear(SK_ColorCYAN);
    121     return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(), SkISize::Make(10, 10),
    122                                     nullptr, nullptr, SkImage::BitDepth::kU8,
    123                                     SkColorSpace::MakeSRGB());
    124 };
    125 #endif
    126 // Want to ensure that our Release is called when the owning image is destroyed
    127 struct RasterDataHolder {
    128     RasterDataHolder() : fReleaseCount(0) {}
    129     sk_sp<SkData> fData;
    130     int fReleaseCount;
    131     static void Release(const void* pixels, void* context) {
    132         RasterDataHolder* self = static_cast<RasterDataHolder*>(context);
    133         self->fReleaseCount++;
    134         self->fData.reset();
    135     }
    136 };
    137 static sk_sp<SkImage> create_rasterproc_image(RasterDataHolder* dataHolder) {
    138     SkASSERT(dataHolder);
    139     SkImageInfo info;
    140     dataHolder->fData = create_image_data(&info);
    141     return SkImage::MakeFromRaster(SkPixmap(info, dataHolder->fData->data(), info.minRowBytes()),
    142                                    RasterDataHolder::Release, dataHolder);
    143 }
    144 static sk_sp<SkImage> create_codec_image() {
    145     SkImageInfo info;
    146     sk_sp<SkData> data(create_image_data(&info));
    147     SkBitmap bitmap;
    148     bitmap.installPixels(info, data->writable_data(), info.minRowBytes());
    149     sk_sp<SkData> src(sk_tool_utils::EncodeImageToData(bitmap, SkEncodedImageFormat::kPNG, 100));
    150     return SkImage::MakeFromEncoded(std::move(src));
    151 }
    152 #if SK_SUPPORT_GPU
    153 static sk_sp<SkImage> create_gpu_image(GrContext* context) {
    154     const SkImageInfo info = SkImageInfo::MakeN32(20, 20, kOpaque_SkAlphaType);
    155     auto surface(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info));
    156     draw_image_test_pattern(surface->getCanvas());
    157     return surface->makeImageSnapshot();
    158 }
    159 #endif
    160 
    161 static void test_encode(skiatest::Reporter* reporter, SkImage* image) {
    162     const SkIRect ir = SkIRect::MakeXYWH(5, 5, 10, 10);
    163     sk_sp<SkData> origEncoded = image->encodeToData();
    164     REPORTER_ASSERT(reporter, origEncoded);
    165     REPORTER_ASSERT(reporter, origEncoded->size() > 0);
    166 
    167     sk_sp<SkImage> decoded(SkImage::MakeFromEncoded(origEncoded));
    168     if (!decoded) {
    169         ERRORF(reporter, "failed to decode image!");
    170         return;
    171     }
    172     REPORTER_ASSERT(reporter, decoded);
    173     assert_equal(reporter, image, nullptr, decoded.get());
    174 
    175     // Now see if we can instantiate an image from a subset of the surface/origEncoded
    176 
    177     decoded = SkImage::MakeFromEncoded(origEncoded, &ir);
    178     REPORTER_ASSERT(reporter, decoded);
    179     assert_equal(reporter, image, &ir, decoded.get());
    180 }
    181 
    182 DEF_TEST(ImageEncode, reporter) {
    183     test_encode(reporter, create_image().get());
    184 }
    185 
    186 #if SK_SUPPORT_GPU
    187 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageEncode_Gpu, reporter, ctxInfo) {
    188     test_encode(reporter, create_gpu_image(ctxInfo.grContext()).get());
    189 }
    190 #endif
    191 
    192 DEF_TEST(Image_MakeFromRasterBitmap, reporter) {
    193     const struct {
    194         SkCopyPixelsMode fCPM;
    195         bool            fExpectSameAsMutable;
    196         bool            fExpectSameAsImmutable;
    197     } recs[] = {
    198         { kIfMutable_SkCopyPixelsMode,  false,  true },
    199         { kAlways_SkCopyPixelsMode,     false,  false },
    200         { kNever_SkCopyPixelsMode,      true,   true },
    201     };
    202     for (auto rec : recs) {
    203         SkPixmap pm;
    204         SkBitmap bm;
    205         bm.allocN32Pixels(100, 100);
    206 
    207         auto img = SkMakeImageFromRasterBitmap(bm, rec.fCPM);
    208         REPORTER_ASSERT(reporter, img->peekPixels(&pm));
    209         const bool sameMutable = pm.addr32(0, 0) == bm.getAddr32(0, 0);
    210         REPORTER_ASSERT(reporter, rec.fExpectSameAsMutable == sameMutable);
    211         REPORTER_ASSERT(reporter, (bm.getGenerationID() == img->uniqueID()) == sameMutable);
    212 
    213         bm.notifyPixelsChanged();   // force a new generation ID
    214 
    215         bm.setImmutable();
    216         img = SkMakeImageFromRasterBitmap(bm, rec.fCPM);
    217         REPORTER_ASSERT(reporter, img->peekPixels(&pm));
    218         const bool sameImmutable = pm.addr32(0, 0) == bm.getAddr32(0, 0);
    219         REPORTER_ASSERT(reporter, rec.fExpectSameAsImmutable == sameImmutable);
    220         REPORTER_ASSERT(reporter, (bm.getGenerationID() == img->uniqueID()) == sameImmutable);
    221     }
    222 }
    223 
    224 namespace {
    225 
    226 const char* kSerializedData = "serialized";
    227 
    228 class MockSerializer : public SkPixelSerializer {
    229 public:
    230     MockSerializer(sk_sp<SkData> (*func)()) : fFunc(func), fDidEncode(false) { }
    231 
    232     bool didEncode() const { return fDidEncode; }
    233 
    234 protected:
    235     bool onUseEncodedData(const void*, size_t) override {
    236         return false;
    237     }
    238 
    239     SkData* onEncode(const SkPixmap&) override {
    240         fDidEncode = true;
    241         return fFunc().release();
    242     }
    243 
    244 private:
    245     sk_sp<SkData> (*fFunc)();
    246     bool fDidEncode;
    247 
    248     typedef SkPixelSerializer INHERITED;
    249 };
    250 
    251 } // anonymous namespace
    252 
    253 // Test that SkImage encoding observes custom pixel serializers.
    254 DEF_TEST(Image_Encode_Serializer, reporter) {
    255     MockSerializer serializer([]() -> sk_sp<SkData> {
    256         return SkData::MakeWithCString(kSerializedData);
    257     });
    258     sk_sp<SkImage> image(create_image());
    259     sk_sp<SkData> encoded = image->encodeToData(&serializer);
    260     sk_sp<SkData> reference(SkData::MakeWithCString(kSerializedData));
    261 
    262     REPORTER_ASSERT(reporter, serializer.didEncode());
    263     REPORTER_ASSERT(reporter, encoded);
    264     REPORTER_ASSERT(reporter, encoded->size() > 0);
    265     REPORTER_ASSERT(reporter, encoded->equals(reference.get()));
    266 }
    267 
    268 // Test that image encoding failures do not break picture serialization/deserialization.
    269 DEF_TEST(Image_Serialize_Encoding_Failure, reporter) {
    270     auto surface(SkSurface::MakeRasterN32Premul(100, 100));
    271     surface->getCanvas()->clear(SK_ColorGREEN);
    272     sk_sp<SkImage> image(surface->makeImageSnapshot());
    273     REPORTER_ASSERT(reporter, image);
    274 
    275     SkPictureRecorder recorder;
    276     SkCanvas* canvas = recorder.beginRecording(100, 100);
    277     canvas->drawImage(image, 0, 0);
    278     sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
    279     REPORTER_ASSERT(reporter, picture);
    280     REPORTER_ASSERT(reporter, picture->approximateOpCount() > 0);
    281 
    282     MockSerializer emptySerializer([]() -> sk_sp<SkData> { return SkData::MakeEmpty(); });
    283     MockSerializer nullSerializer([]() -> sk_sp<SkData> { return nullptr; });
    284     MockSerializer* serializers[] = { &emptySerializer, &nullSerializer };
    285 
    286     for (size_t i = 0; i < SK_ARRAY_COUNT(serializers); ++i) {
    287         SkDynamicMemoryWStream wstream;
    288         REPORTER_ASSERT(reporter, !serializers[i]->didEncode());
    289         picture->serialize(&wstream, serializers[i]);
    290         REPORTER_ASSERT(reporter, serializers[i]->didEncode());
    291 
    292         std::unique_ptr<SkStream> rstream(wstream.detachAsStream());
    293         sk_sp<SkPicture> deserialized(SkPicture::MakeFromStream(rstream.get()));
    294         REPORTER_ASSERT(reporter, deserialized);
    295         REPORTER_ASSERT(reporter, deserialized->approximateOpCount() > 0);
    296     }
    297 }
    298 
    299 // Test that a draw that only partially covers the drawing surface isn't
    300 // interpreted as covering the entire drawing surface (i.e., exercise one of the
    301 // conditions of SkCanvas::wouldOverwriteEntireSurface()).
    302 DEF_TEST(Image_RetainSnapshot, reporter) {
    303     const SkPMColor red   = SkPackARGB32(0xFF, 0xFF, 0, 0);
    304     const SkPMColor green = SkPackARGB32(0xFF, 0, 0xFF, 0);
    305     SkImageInfo info = SkImageInfo::MakeN32Premul(2, 2);
    306     auto surface(SkSurface::MakeRaster(info));
    307     surface->getCanvas()->clear(0xFF00FF00);
    308 
    309     SkPMColor pixels[4];
    310     memset(pixels, 0xFF, sizeof(pixels));   // init with values we don't expect
    311     const SkImageInfo dstInfo = SkImageInfo::MakeN32Premul(2, 2);
    312     const size_t dstRowBytes = 2 * sizeof(SkPMColor);
    313 
    314     sk_sp<SkImage> image1(surface->makeImageSnapshot());
    315     REPORTER_ASSERT(reporter, image1->readPixels(dstInfo, pixels, dstRowBytes, 0, 0));
    316     for (size_t i = 0; i < SK_ARRAY_COUNT(pixels); ++i) {
    317         REPORTER_ASSERT(reporter, pixels[i] == green);
    318     }
    319 
    320     SkPaint paint;
    321     paint.setBlendMode(SkBlendMode::kSrc);
    322     paint.setColor(SK_ColorRED);
    323 
    324     surface->getCanvas()->drawRect(SkRect::MakeXYWH(1, 1, 1, 1), paint);
    325 
    326     sk_sp<SkImage> image2(surface->makeImageSnapshot());
    327     REPORTER_ASSERT(reporter, image2->readPixels(dstInfo, pixels, dstRowBytes, 0, 0));
    328     REPORTER_ASSERT(reporter, pixels[0] == green);
    329     REPORTER_ASSERT(reporter, pixels[1] == green);
    330     REPORTER_ASSERT(reporter, pixels[2] == green);
    331     REPORTER_ASSERT(reporter, pixels[3] == red);
    332 }
    333 
    334 /////////////////////////////////////////////////////////////////////////////////////////////////
    335 
    336 static void make_bitmap_mutable(SkBitmap* bm) {
    337     bm->allocN32Pixels(10, 10);
    338 }
    339 
    340 static void make_bitmap_immutable(SkBitmap* bm) {
    341     bm->allocN32Pixels(10, 10);
    342     bm->setImmutable();
    343 }
    344 
    345 DEF_TEST(image_newfrombitmap, reporter) {
    346     const struct {
    347         void (*fMakeProc)(SkBitmap*);
    348         bool fExpectPeekSuccess;
    349         bool fExpectSharedID;
    350         bool fExpectLazy;
    351     } rec[] = {
    352         { make_bitmap_mutable,      true,   false, false },
    353         { make_bitmap_immutable,    true,   true,  false },
    354     };
    355 
    356     for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) {
    357         SkBitmap bm;
    358         rec[i].fMakeProc(&bm);
    359 
    360         sk_sp<SkImage> image(SkImage::MakeFromBitmap(bm));
    361         SkPixmap pmap;
    362 
    363         const bool sharedID = (image->uniqueID() == bm.getGenerationID());
    364         REPORTER_ASSERT(reporter, sharedID == rec[i].fExpectSharedID);
    365 
    366         const bool peekSuccess = image->peekPixels(&pmap);
    367         REPORTER_ASSERT(reporter, peekSuccess == rec[i].fExpectPeekSuccess);
    368 
    369         const bool lazy = image->isLazyGenerated();
    370         REPORTER_ASSERT(reporter, lazy == rec[i].fExpectLazy);
    371     }
    372 }
    373 
    374 ///////////////////////////////////////////////////////////////////////////////////////////////////
    375 #if SK_SUPPORT_GPU
    376 
    377 #include "SkBitmapCache.h"
    378 
    379 /*
    380  *  This tests the caching (and preemptive purge) of the raster equivalent of a gpu-image.
    381  *  We cache it for performance when drawing into a raster surface.
    382  *
    383  *  A cleaner test would know if each drawImage call triggered a read-back from the gpu,
    384  *  but we don't have that facility (at the moment) so we use a little internal knowledge
    385  *  of *how* the raster version is cached, and look for that.
    386  */
    387 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(c, reporter, ctxInfo) {
    388     SkImageInfo info = SkImageInfo::MakeN32(20, 20, kOpaque_SkAlphaType);
    389     sk_sp<SkImage> image(create_gpu_image(ctxInfo.grContext()));
    390     const uint32_t uniqueID = image->uniqueID();
    391     const auto desc = SkBitmapCacheDesc::Make(image.get());
    392 
    393     auto surface(SkSurface::MakeRaster(info));
    394 
    395     // now we can test drawing a gpu-backed image into a cpu-backed surface
    396 
    397     {
    398         SkBitmap cachedBitmap;
    399         REPORTER_ASSERT(reporter, !SkBitmapCache::Find(desc, &cachedBitmap));
    400     }
    401 
    402     surface->getCanvas()->drawImage(image, 0, 0);
    403     {
    404         SkBitmap cachedBitmap;
    405         if (SkBitmapCache::Find(desc, &cachedBitmap)) {
    406             REPORTER_ASSERT(reporter, cachedBitmap.getGenerationID() == uniqueID);
    407             REPORTER_ASSERT(reporter, cachedBitmap.isImmutable());
    408             REPORTER_ASSERT(reporter, cachedBitmap.getPixels());
    409         } else {
    410             // unexpected, but not really a bug, since the cache is global and this test may be
    411             // run w/ other threads competing for its budget.
    412             SkDebugf("SkImage_Gpu2Cpu : cachedBitmap was already purged\n");
    413         }
    414     }
    415 
    416     image.reset(nullptr);
    417     {
    418         SkBitmap cachedBitmap;
    419         REPORTER_ASSERT(reporter, !SkBitmapCache::Find(desc, &cachedBitmap));
    420     }
    421 }
    422 
    423 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkImage_makeTextureImage, reporter, contextInfo) {
    424     GrContext* context = contextInfo.grContext();
    425     sk_gpu_test::TestContext* testContext = contextInfo.testContext();
    426     GrContextFactory otherFactory;
    427     ContextInfo otherContextInfo = otherFactory.getContextInfo(contextInfo.type());
    428     testContext->makeCurrent();
    429 
    430     std::function<sk_sp<SkImage>()> imageFactories[] = {
    431         create_image,
    432         create_codec_image,
    433         create_data_image,
    434         // Create an image from a picture.
    435         create_picture_image,
    436         // Create a texture image.
    437         [context] { return create_gpu_image(context); },
    438         // Create a texture image in a another GrContext.
    439         [testContext, otherContextInfo] {
    440             otherContextInfo.testContext()->makeCurrent();
    441             sk_sp<SkImage> otherContextImage = create_gpu_image(otherContextInfo.grContext());
    442             testContext->makeCurrent();
    443             return otherContextImage;
    444         }
    445     };
    446 
    447     sk_sp<SkColorSpace> dstColorSpaces[] ={
    448         nullptr,
    449         SkColorSpace::MakeSRGB(),
    450     };
    451 
    452     for (auto& dstColorSpace : dstColorSpaces) {
    453         for (auto factory : imageFactories) {
    454             sk_sp<SkImage> image(factory());
    455             if (!image) {
    456                 ERRORF(reporter, "Error creating image.");
    457                 continue;
    458             }
    459 
    460             sk_sp<SkImage> texImage(image->makeTextureImage(context, dstColorSpace.get()));
    461             if (!texImage) {
    462                 GrContext* imageContext = as_IB(image)->context();
    463 
    464                 // We expect to fail if image comes from a different GrContext.
    465                 if (!image->isTextureBacked() || imageContext == context) {
    466                     ERRORF(reporter, "makeTextureImage failed.");
    467                 }
    468                 continue;
    469             }
    470             if (!texImage->isTextureBacked()) {
    471                 ERRORF(reporter, "makeTextureImage returned non-texture image.");
    472                 continue;
    473             }
    474             if (image->isTextureBacked()) {
    475                 GrSurfaceProxy* origProxy = as_IB(image)->peekProxy();
    476                 GrSurfaceProxy* copyProxy = as_IB(texImage)->peekProxy();
    477 
    478                 if (origProxy->underlyingUniqueID() != copyProxy->underlyingUniqueID()) {
    479                     ERRORF(reporter, "makeTextureImage made unnecessary texture copy.");
    480                 }
    481             }
    482             if (image->width() != texImage->width() || image->height() != texImage->height()) {
    483                 ERRORF(reporter, "makeTextureImage changed the image size.");
    484             }
    485             if (image->alphaType() != texImage->alphaType()) {
    486                 ERRORF(reporter, "makeTextureImage changed image alpha type.");
    487             }
    488         }
    489     }
    490 }
    491 
    492 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkImage_makeNonTextureImage, reporter, contextInfo) {
    493     GrContext* context = contextInfo.grContext();
    494 
    495     std::function<sk_sp<SkImage>()> imageFactories[] = {
    496         create_image,
    497         create_codec_image,
    498         create_data_image,
    499         create_picture_image,
    500         [context] { return create_gpu_image(context); },
    501     };
    502     SkColorSpace* legacyColorSpace = nullptr;
    503     for (auto factory : imageFactories) {
    504         sk_sp<SkImage> image = factory();
    505         if (!image->isTextureBacked()) {
    506             REPORTER_ASSERT(reporter, image->makeNonTextureImage().get() == image.get());
    507             if (!(image = image->makeTextureImage(context, legacyColorSpace))) {
    508                 continue;
    509             }
    510         }
    511         auto rasterImage = image->makeNonTextureImage();
    512         if (!rasterImage) {
    513             ERRORF(reporter, "makeNonTextureImage failed for texture-backed image.");
    514         }
    515         REPORTER_ASSERT(reporter, !rasterImage->isTextureBacked());
    516         assert_equal(reporter, image.get(), nullptr, rasterImage.get());
    517     }
    518 }
    519 
    520 DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SkImage_drawAbandonedGpuImage, reporter, contextInfo) {
    521     auto context = contextInfo.grContext();
    522     auto image = create_gpu_image(context);
    523     auto info = SkImageInfo::MakeN32(20, 20, kOpaque_SkAlphaType);
    524     auto surface(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info));
    525     image->getTexture()->abandon();
    526     surface->getCanvas()->drawImage(image, 0, 0);
    527 }
    528 
    529 #endif
    530 
    531 class EmptyGenerator : public SkImageGenerator {
    532 public:
    533     EmptyGenerator() : SkImageGenerator(SkImageInfo::MakeN32Premul(0, 0)) {}
    534 };
    535 
    536 DEF_TEST(ImageEmpty, reporter) {
    537     const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType);
    538     SkPixmap pmap(info, nullptr, 0);
    539     REPORTER_ASSERT(reporter, nullptr == SkImage::MakeRasterCopy(pmap));
    540     REPORTER_ASSERT(reporter, nullptr == SkImage::MakeRasterData(info, nullptr, 0));
    541     REPORTER_ASSERT(reporter, nullptr == SkImage::MakeFromRaster(pmap, nullptr, nullptr));
    542     REPORTER_ASSERT(reporter, nullptr == SkImage::MakeFromGenerator(
    543                                                             skstd::make_unique<EmptyGenerator>()));
    544 }
    545 
    546 DEF_TEST(ImageDataRef, reporter) {
    547     SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
    548     size_t rowBytes = info.minRowBytes();
    549     size_t size = info.getSafeSize(rowBytes);
    550     sk_sp<SkData> data = SkData::MakeUninitialized(size);
    551     REPORTER_ASSERT(reporter, data->unique());
    552     sk_sp<SkImage> image = SkImage::MakeRasterData(info, data, rowBytes);
    553     REPORTER_ASSERT(reporter, !data->unique());
    554     image.reset();
    555     REPORTER_ASSERT(reporter, data->unique());
    556 }
    557 
    558 static bool has_pixels(const SkPMColor pixels[], int count, SkPMColor expected) {
    559     for (int i = 0; i < count; ++i) {
    560         if (pixels[i] != expected) {
    561             return false;
    562         }
    563     }
    564     return true;
    565 }
    566 
    567 static void image_test_read_pixels(skiatest::Reporter* reporter, SkImage* image) {
    568     if (!image) {
    569         ERRORF(reporter, "Failed to create image!");
    570         return;
    571     }
    572     const SkPMColor expected = SkPreMultiplyColor(SK_ColorWHITE);
    573     const SkPMColor notExpected = ~expected;
    574 
    575     const int w = 2, h = 2;
    576     const size_t rowBytes = w * sizeof(SkPMColor);
    577     SkPMColor pixels[w*h];
    578 
    579     SkImageInfo info;
    580 
    581     info = SkImageInfo::MakeUnknown(w, h);
    582     REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, 0, 0));
    583 
    584     // out-of-bounds should fail
    585     info = SkImageInfo::MakeN32Premul(w, h);
    586     REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, -w, 0));
    587     REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, 0, -h));
    588     REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, image->width(), 0));
    589     REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, 0, image->height()));
    590 
    591     // top-left should succeed
    592     sk_memset32(pixels, notExpected, w*h);
    593     REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes, 0, 0));
    594     REPORTER_ASSERT(reporter, has_pixels(pixels, w*h, expected));
    595 
    596     // bottom-right should succeed
    597     sk_memset32(pixels, notExpected, w*h);
    598     REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes,
    599                                                 image->width() - w, image->height() - h));
    600     REPORTER_ASSERT(reporter, has_pixels(pixels, w*h, expected));
    601 
    602     // partial top-left should succeed
    603     sk_memset32(pixels, notExpected, w*h);
    604     REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes, -1, -1));
    605     REPORTER_ASSERT(reporter, pixels[3] == expected);
    606     REPORTER_ASSERT(reporter, has_pixels(pixels, w*h - 1, notExpected));
    607 
    608     // partial bottom-right should succeed
    609     sk_memset32(pixels, notExpected, w*h);
    610     REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes,
    611                                                 image->width() - 1, image->height() - 1));
    612     REPORTER_ASSERT(reporter, pixels[0] == expected);
    613     REPORTER_ASSERT(reporter, has_pixels(&pixels[1], w*h - 1, notExpected));
    614 }
    615 DEF_TEST(ImageReadPixels, reporter) {
    616     sk_sp<SkImage> image(create_image());
    617     image_test_read_pixels(reporter, image.get());
    618 
    619     image = create_data_image();
    620     image_test_read_pixels(reporter, image.get());
    621 
    622     RasterDataHolder dataHolder;
    623     image = create_rasterproc_image(&dataHolder);
    624     image_test_read_pixels(reporter, image.get());
    625     image.reset();
    626     REPORTER_ASSERT(reporter, 1 == dataHolder.fReleaseCount);
    627 
    628     image = create_codec_image();
    629     image_test_read_pixels(reporter, image.get());
    630 }
    631 #if SK_SUPPORT_GPU
    632 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageReadPixels_Gpu, reporter, ctxInfo) {
    633     image_test_read_pixels(reporter, create_gpu_image(ctxInfo.grContext()).get());
    634 }
    635 #endif
    636 
    637 static void check_legacy_bitmap(skiatest::Reporter* reporter, const SkImage* image,
    638                                 const SkBitmap& bitmap, SkImage::LegacyBitmapMode mode) {
    639     REPORTER_ASSERT(reporter, image->width() == bitmap.width());
    640     REPORTER_ASSERT(reporter, image->height() == bitmap.height());
    641     REPORTER_ASSERT(reporter, image->alphaType() == bitmap.alphaType());
    642 
    643     if (SkImage::kRO_LegacyBitmapMode == mode) {
    644         REPORTER_ASSERT(reporter, bitmap.isImmutable());
    645     }
    646 
    647     REPORTER_ASSERT(reporter, bitmap.getPixels());
    648 
    649     const SkImageInfo info = SkImageInfo::MakeN32(1, 1, bitmap.alphaType());
    650     SkPMColor imageColor;
    651     REPORTER_ASSERT(reporter, image->readPixels(info, &imageColor, sizeof(SkPMColor), 0, 0));
    652     REPORTER_ASSERT(reporter, imageColor == *bitmap.getAddr32(0, 0));
    653 }
    654 
    655 static void test_legacy_bitmap(skiatest::Reporter* reporter, const SkImage* image, SkImage::LegacyBitmapMode mode) {
    656     if (!image) {
    657         ERRORF(reporter, "Failed to create image.");
    658         return;
    659     }
    660     SkBitmap bitmap;
    661     REPORTER_ASSERT(reporter, image->asLegacyBitmap(&bitmap, mode));
    662     check_legacy_bitmap(reporter, image, bitmap, mode);
    663 
    664     // Test subsetting to exercise the rowBytes logic.
    665     SkBitmap tmp;
    666     REPORTER_ASSERT(reporter, bitmap.extractSubset(&tmp, SkIRect::MakeWH(image->width() / 2,
    667                                                                          image->height() / 2)));
    668     sk_sp<SkImage> subsetImage(SkImage::MakeFromBitmap(tmp));
    669     REPORTER_ASSERT(reporter, subsetImage.get());
    670 
    671     SkBitmap subsetBitmap;
    672     REPORTER_ASSERT(reporter, subsetImage->asLegacyBitmap(&subsetBitmap, mode));
    673     check_legacy_bitmap(reporter, subsetImage.get(), subsetBitmap, mode);
    674 }
    675 DEF_TEST(ImageLegacyBitmap, reporter) {
    676     const SkImage::LegacyBitmapMode modes[] = {
    677         SkImage::kRO_LegacyBitmapMode,
    678         SkImage::kRW_LegacyBitmapMode,
    679     };
    680     for (auto& mode : modes) {
    681         sk_sp<SkImage> image(create_image());
    682         test_legacy_bitmap(reporter, image.get(), mode);
    683 
    684         image = create_data_image();
    685         test_legacy_bitmap(reporter, image.get(), mode);
    686 
    687         RasterDataHolder dataHolder;
    688         image = create_rasterproc_image(&dataHolder);
    689         test_legacy_bitmap(reporter, image.get(), mode);
    690         image.reset();
    691         REPORTER_ASSERT(reporter, 1 == dataHolder.fReleaseCount);
    692 
    693         image = create_codec_image();
    694         test_legacy_bitmap(reporter, image.get(), mode);
    695     }
    696 }
    697 #if SK_SUPPORT_GPU
    698 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageLegacyBitmap_Gpu, reporter, ctxInfo) {
    699     const SkImage::LegacyBitmapMode modes[] = {
    700         SkImage::kRO_LegacyBitmapMode,
    701         SkImage::kRW_LegacyBitmapMode,
    702     };
    703     for (auto& mode : modes) {
    704         sk_sp<SkImage> image(create_gpu_image(ctxInfo.grContext()));
    705         test_legacy_bitmap(reporter, image.get(), mode);
    706     }
    707 }
    708 #endif
    709 
    710 static void test_peek(skiatest::Reporter* reporter, SkImage* image, bool expectPeekSuccess) {
    711     if (!image) {
    712         ERRORF(reporter, "Failed to create image!");
    713         return;
    714     }
    715     SkPixmap pm;
    716     bool success = image->peekPixels(&pm);
    717     REPORTER_ASSERT(reporter, expectPeekSuccess == success);
    718     if (success) {
    719         const SkImageInfo& info = pm.info();
    720         REPORTER_ASSERT(reporter, 20 == info.width());
    721         REPORTER_ASSERT(reporter, 20 == info.height());
    722         REPORTER_ASSERT(reporter, kN32_SkColorType == info.colorType());
    723         REPORTER_ASSERT(reporter, kPremul_SkAlphaType == info.alphaType() ||
    724                         kOpaque_SkAlphaType == info.alphaType());
    725         REPORTER_ASSERT(reporter, info.minRowBytes() <= pm.rowBytes());
    726         REPORTER_ASSERT(reporter, SkPreMultiplyColor(SK_ColorWHITE) == *pm.addr32(0, 0));
    727     }
    728 }
    729 DEF_TEST(ImagePeek, reporter) {
    730     sk_sp<SkImage> image(create_image());
    731     test_peek(reporter, image.get(), true);
    732 
    733     image = create_data_image();
    734     test_peek(reporter, image.get(), true);
    735 
    736     RasterDataHolder dataHolder;
    737     image = create_rasterproc_image(&dataHolder);
    738     test_peek(reporter, image.get(), true);
    739     image.reset();
    740     REPORTER_ASSERT(reporter, 1 == dataHolder.fReleaseCount);
    741 
    742     image = create_codec_image();
    743     test_peek(reporter, image.get(), false);
    744 }
    745 #if SK_SUPPORT_GPU
    746 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImagePeek_Gpu, reporter, ctxInfo) {
    747     sk_sp<SkImage> image(create_gpu_image(ctxInfo.grContext()));
    748     test_peek(reporter, image.get(), false);
    749 }
    750 #endif
    751 
    752 #if SK_SUPPORT_GPU
    753 struct TextureReleaseChecker {
    754     TextureReleaseChecker() : fReleaseCount(0) {}
    755     int fReleaseCount;
    756     static void Release(void* self) {
    757         static_cast<TextureReleaseChecker*>(self)->fReleaseCount++;
    758     }
    759 };
    760 
    761 DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SkImage_NewFromTextureRelease, reporter, ctxInfo) {
    762     const int kWidth = 10;
    763     const int kHeight = 10;
    764     std::unique_ptr<uint32_t[]> pixels(new uint32_t[kWidth * kHeight]);
    765 
    766     GrContext* ctx = ctxInfo.grContext();
    767 
    768     GrBackendObject backendTexHandle =
    769             ctxInfo.grContext()->getGpu()->createTestingOnlyBackendTexture(
    770                     pixels.get(), kWidth, kHeight, kRGBA_8888_GrPixelConfig, true);
    771 
    772     GrBackendTexture backendTex = GrTest::CreateBackendTexture(ctx->contextPriv().getBackend(),
    773                                                                kWidth,
    774                                                                kHeight,
    775                                                                kRGBA_8888_GrPixelConfig,
    776                                                                backendTexHandle);
    777 
    778     TextureReleaseChecker releaseChecker;
    779     GrSurfaceOrigin texOrigin = kBottomLeft_GrSurfaceOrigin;
    780     sk_sp<SkImage> refImg(
    781         SkImage::MakeFromTexture(ctx, backendTex, texOrigin, kPremul_SkAlphaType, nullptr,
    782                                  TextureReleaseChecker::Release, &releaseChecker));
    783 
    784     GrSurfaceOrigin readBackOrigin;
    785     GrBackendObject readBackHandle = refImg->getTextureHandle(false, &readBackOrigin);
    786     // TODO: Make it so we can check this (see skbug.com/5019)
    787 #if 0
    788     if (*readBackHandle != *(backendTexHandle)) {
    789         ERRORF(reporter, "backend mismatch %d %d\n",
    790                        (int)readBackHandle, (int)backendTexHandle);
    791     }
    792     REPORTER_ASSERT(reporter, readBackHandle == backendTexHandle);
    793 #else
    794     REPORTER_ASSERT(reporter, SkToBool(readBackHandle));
    795 #endif
    796     if (readBackOrigin != texOrigin) {
    797         ERRORF(reporter, "origin mismatch %d %d\n", readBackOrigin, texOrigin);
    798     }
    799     REPORTER_ASSERT(reporter, readBackOrigin == texOrigin);
    800 
    801     // Now exercise the release proc
    802     REPORTER_ASSERT(reporter, 0 == releaseChecker.fReleaseCount);
    803     refImg.reset(nullptr); // force a release of the image
    804     REPORTER_ASSERT(reporter, 1 == releaseChecker.fReleaseCount);
    805 
    806     ctxInfo.grContext()->getGpu()->deleteTestingOnlyBackendTexture(backendTexHandle);
    807 }
    808 
    809 DEF_GPUTEST(SkImage_MakeCrossContextRelease, reporter, /*factory*/) {
    810     GrContextFactory testFactory;
    811 
    812     sk_sp<SkData> data = GetResourceAsData("mandrill_128.png");
    813     SkASSERT(data.get());
    814 
    815     for (int i = 0; i < GrContextFactory::kContextTypeCnt; ++i) {
    816         GrContextFactory::ContextType ctxType = static_cast<GrContextFactory::ContextType>(i);
    817         ContextInfo ctxInfo = testFactory.getContextInfo(ctxType);
    818         GrContext* ctx = ctxInfo.grContext();
    819         if (!ctx) {
    820             continue;
    821         }
    822 
    823         // If we don't have proper support for this feature, the factory will fallback to returning
    824         // codec-backed images. Those will "work", but some of our checks will fail because we
    825         // expect the cross-context images not to work on multiple contexts at once.
    826         if (!ctx->caps()->crossContextTextureSupport()) {
    827             continue;
    828         }
    829 
    830         // We test three lifetime patterns for a single context:
    831         // 1) Create image, free image
    832         // 2) Create image, draw, flush, free image
    833         // 3) Create image, draw, free image, flush
    834         // ... and then repeat the last two patterns with drawing on a second* context:
    835         // 4) Create image, draw*, flush*, free image
    836         // 5) Create image, draw*, free iamge, flush*
    837 
    838         // Case #1: Create image, free image
    839         {
    840             sk_sp<SkImage> refImg(SkImage::MakeCrossContextFromEncoded(ctx, data, false, nullptr));
    841             refImg.reset(nullptr); // force a release of the image
    842         }
    843 
    844         SkImageInfo info = SkImageInfo::MakeN32Premul(128, 128);
    845         sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
    846         SkCanvas* canvas = surface->getCanvas();
    847 
    848         // Case #2: Create image, draw, flush, free image
    849         {
    850             sk_sp<SkImage> refImg(SkImage::MakeCrossContextFromEncoded(ctx, data, false, nullptr));
    851 
    852             canvas->drawImage(refImg, 0, 0);
    853             canvas->flush();
    854 
    855             refImg.reset(nullptr); // force a release of the image
    856         }
    857 
    858         // Case #3: Create image, draw, free image, flush
    859         {
    860             sk_sp<SkImage> refImg(SkImage::MakeCrossContextFromEncoded(ctx, data, false, nullptr));
    861 
    862             canvas->drawImage(refImg, 0, 0);
    863             refImg.reset(nullptr); // force a release of the image
    864 
    865             canvas->flush();
    866         }
    867 
    868         // Configure second context
    869         sk_gpu_test::TestContext* testContext = ctxInfo.testContext();
    870 
    871         ContextInfo otherContextInfo = testFactory.getSharedContextInfo(ctx);
    872         GrContext* otherCtx = otherContextInfo.grContext();
    873         sk_gpu_test::TestContext* otherTestContext = otherContextInfo.testContext();
    874 
    875         // Creating a context in a share group may fail
    876         if (!otherCtx) {
    877             continue;
    878         }
    879 
    880         surface = SkSurface::MakeRenderTarget(otherCtx, SkBudgeted::kNo, info);
    881         canvas = surface->getCanvas();
    882 
    883         // Case #4: Create image, draw*, flush*, free image
    884         {
    885             testContext->makeCurrent();
    886             sk_sp<SkImage> refImg(SkImage::MakeCrossContextFromEncoded(ctx, data, false, nullptr));
    887 
    888             otherTestContext->makeCurrent();
    889             canvas->drawImage(refImg, 0, 0);
    890             canvas->flush();
    891 
    892             testContext->makeCurrent();
    893             refImg.reset(nullptr); // force a release of the image
    894         }
    895 
    896         // Case #5: Create image, draw*, free image, flush*
    897         {
    898             testContext->makeCurrent();
    899             sk_sp<SkImage> refImg(SkImage::MakeCrossContextFromEncoded(ctx, data, false, nullptr));
    900 
    901             otherTestContext->makeCurrent();
    902             canvas->drawImage(refImg, 0, 0);
    903 
    904             testContext->makeCurrent();
    905             refImg.reset(nullptr); // force a release of the image
    906 
    907             otherTestContext->makeCurrent();
    908             canvas->flush();
    909         }
    910 
    911         // Case #6: Verify that only one context can be using the image at a time
    912         {
    913             testContext->makeCurrent();
    914             sk_sp<SkImage> refImg(SkImage::MakeCrossContextFromEncoded(ctx, data, false, nullptr));
    915 
    916             // Any context should be able to borrow the texture at this point
    917             sk_sp<SkColorSpace> texColorSpace;
    918             sk_sp<GrTextureProxy> proxy = as_IB(refImg)->asTextureProxyRef(
    919                 ctx, GrSamplerParams::ClampNoFilter(), nullptr, &texColorSpace, nullptr);
    920             REPORTER_ASSERT(reporter, proxy);
    921 
    922             // But once it's borrowed, no other context should be able to borrow
    923             otherTestContext->makeCurrent();
    924             sk_sp<GrTextureProxy> otherProxy = as_IB(refImg)->asTextureProxyRef(
    925                 otherCtx, GrSamplerParams::ClampNoFilter(), nullptr, &texColorSpace, nullptr);
    926             REPORTER_ASSERT(reporter, !otherProxy);
    927 
    928             // Original context (that's already borrowing) should be okay
    929             testContext->makeCurrent();
    930             sk_sp<GrTextureProxy> proxySecondRef = as_IB(refImg)->asTextureProxyRef(
    931                 ctx, GrSamplerParams::ClampNoFilter(), nullptr, &texColorSpace, nullptr);
    932             REPORTER_ASSERT(reporter, proxySecondRef);
    933 
    934             // Releae all refs from the original context
    935             proxy.reset(nullptr);
    936             proxySecondRef.reset(nullptr);
    937 
    938             // Now we should be able to borrow the texture from the other context
    939             otherTestContext->makeCurrent();
    940             otherProxy = as_IB(refImg)->asTextureProxyRef(
    941                 otherCtx, GrSamplerParams::ClampNoFilter(), nullptr, &texColorSpace, nullptr);
    942             REPORTER_ASSERT(reporter, otherProxy);
    943 
    944             // Release everything
    945             otherProxy.reset(nullptr);
    946             refImg.reset(nullptr);
    947         }
    948     }
    949 }
    950 
    951 static void check_images_same(skiatest::Reporter* reporter, const SkImage* a, const SkImage* b) {
    952     if (a->width() != b->width() || a->height() != b->height()) {
    953         ERRORF(reporter, "Images must have the same size");
    954         return;
    955     }
    956     if (a->alphaType() != b->alphaType()) {
    957         ERRORF(reporter, "Images must have the same alpha type");
    958         return;
    959     }
    960 
    961     SkImageInfo info = SkImageInfo::MakeN32Premul(a->width(), a->height());
    962     SkAutoPixmapStorage apm;
    963     SkAutoPixmapStorage bpm;
    964 
    965     apm.alloc(info);
    966     bpm.alloc(info);
    967 
    968     if (!a->readPixels(apm, 0, 0)) {
    969         ERRORF(reporter, "Could not read image a's pixels");
    970         return;
    971     }
    972     if (!b->readPixels(bpm, 0, 0)) {
    973         ERRORF(reporter, "Could not read image b's pixels");
    974         return;
    975     }
    976 
    977     for (auto y = 0; y < info.height(); ++y) {
    978         for (auto x = 0; x < info.width(); ++x) {
    979             uint32_t pixelA = *apm.addr32(x, y);
    980             uint32_t pixelB = *bpm.addr32(x, y);
    981             if (pixelA != pixelB) {
    982                 ERRORF(reporter, "Expected image pixels to be the same. At %d,%d 0x%08x != 0x%08x",
    983                        x, y, pixelA, pixelB);
    984                 return;
    985             }
    986         }
    987     }
    988 }
    989 
    990 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredTextureImage, reporter, ctxInfo) {
    991     GrContext* context = ctxInfo.grContext();
    992     sk_gpu_test::TestContext* testContext = ctxInfo.testContext();
    993     sk_sp<GrContextThreadSafeProxy> proxy = context->threadSafeProxy();
    994 
    995     GrContextFactory otherFactory;
    996     ContextInfo otherContextInfo = otherFactory.getContextInfo(ctxInfo.type());
    997 
    998     testContext->makeCurrent();
    999     REPORTER_ASSERT(reporter, proxy);
   1000     auto createLarge = [context] {
   1001         return create_image_large(context->caps()->maxTextureSize());
   1002     };
   1003     struct {
   1004         std::function<sk_sp<SkImage> ()>                      fImageFactory;
   1005         std::vector<SkImage::DeferredTextureImageUsageParams> fParams;
   1006         sk_sp<SkColorSpace>                                   fColorSpace;
   1007         SkColorType                                           fColorType;
   1008         SkFilterQuality                                       fExpectedQuality;
   1009         int                                                   fExpectedScaleFactor;
   1010         bool                                                  fExpectation;
   1011     } testCases[] = {
   1012         { create_image,          {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
   1013           nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, true },
   1014         { create_codec_image,    {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
   1015           nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, true },
   1016         { create_data_image,     {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
   1017           nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, true },
   1018         { create_picture_image,  {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
   1019           nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, false },
   1020         { [context] { return create_gpu_image(context); },
   1021           {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
   1022           nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, false },
   1023         // Create a texture image in a another GrContext.
   1024         { [testContext, otherContextInfo] {
   1025             otherContextInfo.testContext()->makeCurrent();
   1026             sk_sp<SkImage> otherContextImage = create_gpu_image(otherContextInfo.grContext());
   1027             testContext->makeCurrent();
   1028             return otherContextImage;
   1029           }, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
   1030           nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, false },
   1031         // Create an image that is too large to upload.
   1032         { createLarge, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
   1033           nullptr, kN32_SkColorType, kNone_SkFilterQuality, 1, false },
   1034         // Create an image that is too large, but is scaled to an acceptable size.
   1035         { createLarge, {{SkMatrix::I(), kMedium_SkFilterQuality, 4}},
   1036           nullptr, kN32_SkColorType, kMedium_SkFilterQuality, 16, true},
   1037         // Create an image with multiple low filter qualities, make sure we round up.
   1038         { createLarge, {{SkMatrix::I(), kNone_SkFilterQuality, 4},
   1039                         {SkMatrix::I(), kMedium_SkFilterQuality, 4}},
   1040           nullptr, kN32_SkColorType, kMedium_SkFilterQuality, 16, true},
   1041         // Create an image with multiple prescale levels, make sure we chose the minimum scale.
   1042         { createLarge, {{SkMatrix::I(), kMedium_SkFilterQuality, 5},
   1043                         {SkMatrix::I(), kMedium_SkFilterQuality, 4}},
   1044           nullptr, kN32_SkColorType, kMedium_SkFilterQuality, 16, true},
   1045         // Create a images which are decoded to a 4444 backing.
   1046         { create_image,       {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
   1047           nullptr, kARGB_4444_SkColorType, kNone_SkFilterQuality, 1, true },
   1048         { create_codec_image, {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
   1049           nullptr, kARGB_4444_SkColorType, kNone_SkFilterQuality, 1, true },
   1050         { create_data_image,  {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
   1051           nullptr, kARGB_4444_SkColorType, kNone_SkFilterQuality, 1, true },
   1052         // Valid SkColorSpace and SkColorType.
   1053         { create_data_image,  {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
   1054           SkColorSpace::MakeSRGB(), kN32_SkColorType, kNone_SkFilterQuality, 1, true },
   1055         // Invalid SkColorSpace and SkColorType.
   1056         { create_data_image,  {{SkMatrix::I(), kNone_SkFilterQuality, 0}},
   1057           SkColorSpace::MakeSRGB(), kARGB_4444_SkColorType, kNone_SkFilterQuality, 1, false },
   1058     };
   1059 
   1060 
   1061     for (auto testCase : testCases) {
   1062         sk_sp<SkImage> image(testCase.fImageFactory());
   1063         if (!image) {
   1064             ERRORF(reporter, "Failed to create image!");
   1065             continue;
   1066         }
   1067 
   1068         size_t size = image->getDeferredTextureImageData(*proxy, testCase.fParams.data(),
   1069                                                          static_cast<int>(testCase.fParams.size()),
   1070                                                          nullptr, testCase.fColorSpace.get(),
   1071                                                          testCase.fColorType);
   1072         static const char *const kFS[] = { "fail", "succeed" };
   1073         if (SkToBool(size) != testCase.fExpectation) {
   1074             ERRORF(reporter,  "This image was expected to %s but did not.",
   1075                    kFS[testCase.fExpectation]);
   1076         }
   1077         if (size) {
   1078             void* buffer = sk_malloc_throw(size);
   1079             void* misaligned = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(buffer) + 3);
   1080             if (image->getDeferredTextureImageData(*proxy, testCase.fParams.data(),
   1081                                                    static_cast<int>(testCase.fParams.size()),
   1082                                                    misaligned, testCase.fColorSpace.get(),
   1083                                                    testCase.fColorType)) {
   1084                 ERRORF(reporter, "Should fail when buffer is misaligned.");
   1085             }
   1086             if (!image->getDeferredTextureImageData(*proxy, testCase.fParams.data(),
   1087                                                     static_cast<int>(testCase.fParams.size()),
   1088                                                     buffer, testCase.fColorSpace.get(),
   1089                                                    testCase.fColorType)) {
   1090                 ERRORF(reporter, "deferred image size succeeded but creation failed.");
   1091             } else {
   1092                 for (auto budgeted : { SkBudgeted::kNo, SkBudgeted::kYes }) {
   1093                     sk_sp<SkImage> newImage(
   1094                         SkImage::MakeFromDeferredTextureImageData(context, buffer, budgeted));
   1095                     REPORTER_ASSERT(reporter, newImage != nullptr);
   1096                     if (newImage) {
   1097                         // Scale the image in software for comparison.
   1098                         SkImageInfo scaled_info = SkImageInfo::MakeN32(
   1099                                                     image->width() / testCase.fExpectedScaleFactor,
   1100                                                     image->height() / testCase.fExpectedScaleFactor,
   1101                                                     image->alphaType());
   1102                         SkAutoPixmapStorage scaled;
   1103                         scaled.alloc(scaled_info);
   1104                         image->scalePixels(scaled, testCase.fExpectedQuality);
   1105                         sk_sp<SkImage> scaledImage = SkImage::MakeRasterCopy(scaled);
   1106                         check_images_same(reporter, scaledImage.get(), newImage.get());
   1107                     }
   1108                     // The other context should not be able to create images from texture data
   1109                     // created by the original context.
   1110                     sk_sp<SkImage> newImage2(SkImage::MakeFromDeferredTextureImageData(
   1111                         otherContextInfo.grContext(), buffer, budgeted));
   1112                     REPORTER_ASSERT(reporter, !newImage2);
   1113                     testContext->makeCurrent();
   1114                 }
   1115             }
   1116             sk_free(buffer);
   1117         }
   1118     }
   1119 }
   1120 #endif
   1121 
   1122 ///////////////////////////////////////////////////////////////////////////////////////////////////
   1123 
   1124 static sk_sp<SkImage> create_picture_image(sk_sp<SkColorSpace> space) {
   1125     SkPictureRecorder recorder;
   1126     SkCanvas* canvas = recorder.beginRecording(10, 10);
   1127     canvas->clear(SK_ColorCYAN);
   1128     return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(), SkISize::Make(10, 10),
   1129                                     nullptr, nullptr, SkImage::BitDepth::kU8, std::move(space));
   1130 };
   1131 
   1132 static inline bool almost_equal(int a, int b) {
   1133     return SkTAbs(a - b) <= 1;
   1134 }
   1135 
   1136 DEF_TEST(Image_ColorSpace, r) {
   1137     sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
   1138     sk_sp<SkImage> image = GetResourceAsImage("mandrill_512_q075.jpg");
   1139     REPORTER_ASSERT(r, srgb.get() == image->colorSpace());
   1140 
   1141     image = GetResourceAsImage("webp-color-profile-lossy.webp");
   1142     SkColorSpaceTransferFn fn;
   1143     bool success = image->colorSpace()->isNumericalTransferFn(&fn);
   1144     REPORTER_ASSERT(r, success);
   1145     REPORTER_ASSERT(r, color_space_almost_equal(1.8f, fn.fG));
   1146 
   1147     sk_sp<SkColorSpace> rec2020 = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
   1148                                                         SkColorSpace::kRec2020_Gamut);
   1149     image = create_picture_image(rec2020);
   1150     REPORTER_ASSERT(r, SkColorSpace::Equals(rec2020.get(), image->colorSpace()));
   1151 
   1152     SkBitmap bitmap;
   1153     SkImageInfo info = SkImageInfo::MakeN32(10, 10, kPremul_SkAlphaType, rec2020);
   1154     bitmap.allocPixels(info);
   1155     image = SkImage::MakeFromBitmap(bitmap);
   1156     REPORTER_ASSERT(r, SkColorSpace::Equals(rec2020.get(), image->colorSpace()));
   1157 
   1158     sk_sp<SkSurface> surface = SkSurface::MakeRaster(
   1159             SkImageInfo::MakeN32Premul(SkISize::Make(10, 10)));
   1160     image = surface->makeImageSnapshot();
   1161     REPORTER_ASSERT(r, nullptr == image->colorSpace());
   1162 
   1163     surface = SkSurface::MakeRaster(info);
   1164     image = surface->makeImageSnapshot();
   1165     REPORTER_ASSERT(r, SkColorSpace::Equals(rec2020.get(), image->colorSpace()));
   1166 }
   1167 
   1168 DEF_TEST(Image_makeColorSpace, r) {
   1169     sk_sp<SkColorSpace> p3 = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
   1170                                                    SkColorSpace::kDCIP3_D65_Gamut);
   1171     SkColorSpaceTransferFn fn;
   1172     fn.fA = 1.f; fn.fB = 0.f; fn.fC = 0.f; fn.fD = 0.f; fn.fE = 0.f; fn.fF = 0.f; fn.fG = 1.8f;
   1173     sk_sp<SkColorSpace> adobeGamut = SkColorSpace::MakeRGB(fn, SkColorSpace::kAdobeRGB_Gamut);
   1174 
   1175     SkBitmap srgbBitmap;
   1176     srgbBitmap.allocPixels(SkImageInfo::MakeS32(1, 1, kOpaque_SkAlphaType));
   1177     *srgbBitmap.getAddr32(0, 0) = SkSwizzle_RGBA_to_PMColor(0xFF604020);
   1178     srgbBitmap.setImmutable();
   1179     sk_sp<SkImage> srgbImage = SkImage::MakeFromBitmap(srgbBitmap);
   1180     sk_sp<SkImage> p3Image = srgbImage->makeColorSpace(p3, SkTransferFunctionBehavior::kIgnore);
   1181     SkBitmap p3Bitmap;
   1182     bool success = p3Image->asLegacyBitmap(&p3Bitmap, SkImage::kRO_LegacyBitmapMode);
   1183     REPORTER_ASSERT(r, success);
   1184     REPORTER_ASSERT(r, almost_equal(0x28, SkGetPackedR32(*p3Bitmap.getAddr32(0, 0))));
   1185     REPORTER_ASSERT(r, almost_equal(0x40, SkGetPackedG32(*p3Bitmap.getAddr32(0, 0))));
   1186     REPORTER_ASSERT(r, almost_equal(0x5E, SkGetPackedB32(*p3Bitmap.getAddr32(0, 0))));
   1187 
   1188     sk_sp<SkImage> adobeImage = srgbImage->makeColorSpace(adobeGamut,
   1189                                                           SkTransferFunctionBehavior::kIgnore);
   1190     SkBitmap adobeBitmap;
   1191     success = adobeImage->asLegacyBitmap(&adobeBitmap, SkImage::kRO_LegacyBitmapMode);
   1192     REPORTER_ASSERT(r, success);
   1193     REPORTER_ASSERT(r, almost_equal(0x21, SkGetPackedR32(*adobeBitmap.getAddr32(0, 0))));
   1194     REPORTER_ASSERT(r, almost_equal(0x31, SkGetPackedG32(*adobeBitmap.getAddr32(0, 0))));
   1195     REPORTER_ASSERT(r, almost_equal(0x4C, SkGetPackedB32(*adobeBitmap.getAddr32(0, 0))));
   1196 
   1197     srgbImage = GetResourceAsImage("1x1.png");
   1198     p3Image = srgbImage->makeColorSpace(p3, SkTransferFunctionBehavior::kIgnore);
   1199     success = p3Image->asLegacyBitmap(&p3Bitmap, SkImage::kRO_LegacyBitmapMode);
   1200     REPORTER_ASSERT(r, success);
   1201     REPORTER_ASSERT(r, almost_equal(0x8B, SkGetPackedR32(*p3Bitmap.getAddr32(0, 0))));
   1202     REPORTER_ASSERT(r, almost_equal(0x82, SkGetPackedG32(*p3Bitmap.getAddr32(0, 0))));
   1203     REPORTER_ASSERT(r, almost_equal(0x77, SkGetPackedB32(*p3Bitmap.getAddr32(0, 0))));
   1204 }
   1205 
   1206 ///////////////////////////////////////////////////////////////////////////////////////////////////
   1207 
   1208 static void make_all_premul(SkBitmap* bm) {
   1209     bm->allocPixels(SkImageInfo::MakeN32(256, 256, kPremul_SkAlphaType));
   1210     for (int a = 0; a < 256; ++a) {
   1211         for (int r = 0; r < 256; ++r) {
   1212             // make all valid premul combinations
   1213             int c = SkTMin(a, r);
   1214             *bm->getAddr32(a, r) = SkPackARGB32(a, c, c, c);
   1215         }
   1216     }
   1217 }
   1218 
   1219 static bool equal(const SkBitmap& a, const SkBitmap& b) {
   1220     SkASSERT(a.width() == b.width());
   1221     SkASSERT(a.height() == b.height());
   1222     for (int y = 0; y < a.height(); ++y) {
   1223         for (int x = 0; x < a.width(); ++x) {
   1224             SkPMColor pa = *a.getAddr32(x, y);
   1225             SkPMColor pb = *b.getAddr32(x, y);
   1226             if (pa != pb) {
   1227                 return false;
   1228             }
   1229         }
   1230     }
   1231     return true;
   1232 }
   1233 
   1234 DEF_TEST(image_roundtrip_encode, reporter) {
   1235     SkBitmap bm0;
   1236     make_all_premul(&bm0);
   1237 
   1238     auto img0 = SkImage::MakeFromBitmap(bm0);
   1239     sk_sp<SkData> data = img0->encodeToData(SkEncodedImageFormat::kPNG, 100);
   1240     auto img1 = SkImage::MakeFromEncoded(data);
   1241 
   1242     SkBitmap bm1;
   1243     bm1.allocPixels(SkImageInfo::MakeN32(256, 256, kPremul_SkAlphaType));
   1244     img1->readPixels(bm1.info(), bm1.getPixels(), bm1.rowBytes(), 0, 0);
   1245 
   1246     REPORTER_ASSERT(reporter, equal(bm0, bm1));
   1247 }
   1248 
   1249 DEF_TEST(image_roundtrip_premul, reporter) {
   1250     SkBitmap bm0;
   1251     make_all_premul(&bm0);
   1252 
   1253     SkBitmap bm1;
   1254     bm1.allocPixels(SkImageInfo::MakeN32(256, 256, kUnpremul_SkAlphaType));
   1255     bm0.readPixels(bm1.info(), bm1.getPixels(), bm1.rowBytes(), 0, 0);
   1256 
   1257     SkBitmap bm2;
   1258     bm2.allocPixels(SkImageInfo::MakeN32(256, 256, kPremul_SkAlphaType));
   1259     bm1.readPixels(bm2.info(), bm2.getPixels(), bm2.rowBytes(), 0, 0);
   1260 
   1261     REPORTER_ASSERT(reporter, equal(bm0, bm2));
   1262 }
   1263 
   1264 ///////////////////////////////////////////////////////////////////////////////////////////////////
   1265 
   1266 static void check_scaled_pixels(skiatest::Reporter* reporter, SkPixmap* pmap, uint32_t expected) {
   1267     // Verify that all pixels contain the original test color
   1268     for (auto y = 0; y < pmap->height(); ++y) {
   1269         for (auto x = 0; x < pmap->width(); ++x) {
   1270             uint32_t pixel = *pmap->addr32(x, y);
   1271             if (pixel != expected) {
   1272                 ERRORF(reporter, "Expected scaled pixels to be the same. At %d,%d 0x%08x != 0x%08x",
   1273                        x, y, pixel, expected);
   1274                 return;
   1275             }
   1276         }
   1277     }
   1278 }
   1279 
   1280 static void test_scale_pixels(skiatest::Reporter* reporter, const SkImage* image,
   1281                               uint32_t expected) {
   1282     SkImageInfo info = SkImageInfo::MakeN32Premul(image->width() * 2, image->height() * 2);
   1283 
   1284     // Make sure to test kDisallow first, so we don't just get a cache hit in that case
   1285     for (auto chint : { SkImage::kDisallow_CachingHint, SkImage::kAllow_CachingHint }) {
   1286         SkAutoPixmapStorage scaled;
   1287         scaled.alloc(info);
   1288         if (!image->scalePixels(scaled, kLow_SkFilterQuality, chint)) {
   1289             ERRORF(reporter, "Failed to scale image");
   1290             continue;
   1291         }
   1292 
   1293         check_scaled_pixels(reporter, &scaled, expected);
   1294     }
   1295 }
   1296 
   1297 DEF_TEST(ImageScalePixels, reporter) {
   1298     const SkPMColor pmRed = SkPackARGB32(0xFF, 0xFF, 0, 0);
   1299     const SkColor red = SK_ColorRED;
   1300 
   1301     // Test raster image
   1302     SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
   1303     sk_sp<SkSurface> surface = SkSurface::MakeRaster(info);
   1304     surface->getCanvas()->clear(red);
   1305     sk_sp<SkImage> rasterImage = surface->makeImageSnapshot();
   1306     test_scale_pixels(reporter, rasterImage.get(), pmRed);
   1307 
   1308     // Test encoded image
   1309     sk_sp<SkData> data = rasterImage->encodeToData();
   1310     sk_sp<SkImage> codecImage = SkImage::MakeFromEncoded(data);
   1311     test_scale_pixels(reporter, codecImage.get(), pmRed);
   1312 }
   1313 
   1314 #if SK_SUPPORT_GPU
   1315 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageScalePixels_Gpu, reporter, ctxInfo) {
   1316     const SkPMColor pmRed = SkPackARGB32(0xFF, 0xFF, 0, 0);
   1317     const SkColor red = SK_ColorRED;
   1318 
   1319     SkImageInfo info = SkImageInfo::MakeN32Premul(16, 16);
   1320     sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctxInfo.grContext(), SkBudgeted::kNo,
   1321                                                            info);
   1322     surface->getCanvas()->clear(red);
   1323     sk_sp<SkImage> gpuImage = surface->makeImageSnapshot();
   1324     test_scale_pixels(reporter, gpuImage.get(), pmRed);
   1325 }
   1326 #endif
   1327