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