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