Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2013 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 "SkCanvas.h"
     10 #include "SkData.h"
     11 #include "SkDevice.h"
     12 #include "SkImage_Base.h"
     13 #include "SkPath.h"
     14 #include "SkRRect.h"
     15 #include "SkSurface.h"
     16 #include "SkUtils.h"
     17 #include "Test.h"
     18 
     19 #if SK_SUPPORT_GPU
     20 #include "GrContext.h"
     21 #include "GrGpu.h"
     22 #endif
     23 
     24 #include <initializer_list>
     25 
     26 static void release_direct_surface_storage(void* pixels, void* context) {
     27     SkASSERT(pixels == context);
     28     sk_free(pixels);
     29 }
     30 static SkSurface* create_surface(SkAlphaType at = kPremul_SkAlphaType,
     31                                  SkImageInfo* requestedInfo = nullptr) {
     32     const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
     33     if (requestedInfo) {
     34         *requestedInfo = info;
     35     }
     36     return SkSurface::NewRaster(info);
     37 }
     38 static SkSurface* create_direct_surface(SkAlphaType at = kPremul_SkAlphaType,
     39                                         SkImageInfo* requestedInfo = nullptr) {
     40     const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
     41     if (requestedInfo) {
     42         *requestedInfo = info;
     43     }
     44     const size_t rowBytes = info.minRowBytes();
     45     void* storage = sk_malloc_throw(info.getSafeSize(rowBytes));
     46     return SkSurface::NewRasterDirectReleaseProc(info, storage, rowBytes,
     47                                                  release_direct_surface_storage,
     48                                                  storage);
     49 }
     50 #if SK_SUPPORT_GPU
     51 static SkSurface* create_gpu_surface(GrContext* context, SkAlphaType at = kPremul_SkAlphaType,
     52                                      SkImageInfo* requestedInfo = nullptr) {
     53     const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
     54     if (requestedInfo) {
     55         *requestedInfo = info;
     56     }
     57     return SkSurface::NewRenderTarget(context, SkBudgeted::kNo, info, 0, nullptr);
     58 }
     59 static SkSurface* create_gpu_scratch_surface(GrContext* context,
     60                                              SkAlphaType at = kPremul_SkAlphaType,
     61                                              SkImageInfo* requestedInfo = nullptr) {
     62     const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
     63     if (requestedInfo) {
     64         *requestedInfo = info;
     65     }
     66     return SkSurface::NewRenderTarget(context, SkBudgeted::kYes, info, 0, nullptr);
     67 }
     68 #endif
     69 
     70 DEF_TEST(SurfaceEmpty, reporter) {
     71     const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType);
     72     REPORTER_ASSERT(reporter, nullptr == SkSurface::NewRaster(info));
     73     REPORTER_ASSERT(reporter, nullptr == SkSurface::NewRasterDirect(info, nullptr, 0));
     74 
     75 }
     76 #if SK_SUPPORT_GPU
     77 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceEmpty_Gpu, reporter, context) {
     78     const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType);
     79     REPORTER_ASSERT(reporter, nullptr ==
     80                     SkSurface::NewRenderTarget(context, SkBudgeted::kNo, info, 0, nullptr));
     81 }
     82 #endif
     83 
     84 #if SK_SUPPORT_GPU
     85 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceWrappedTexture, reporter, context) {
     86     GrGpu* gpu = context->getGpu();
     87     if (!gpu) {
     88         return;
     89     }
     90 
     91     // Test the wrapped factory for SkSurface by creating a backend texture and then wrap it in
     92     // a SkSurface.
     93     static const int kW = 100;
     94     static const int kH = 100;
     95     static const uint32_t kOrigColor = 0xFFAABBCC;
     96     SkAutoTArray<uint32_t> pixels(kW * kH);
     97     sk_memset32(pixels.get(), kOrigColor, kW * kH);
     98     GrBackendObject texHandle = gpu->createTestingOnlyBackendTexture(pixels.get(), kW, kH,
     99                                                                      kRGBA_8888_GrPixelConfig);
    100 
    101     GrBackendTextureDesc wrappedDesc;
    102     wrappedDesc.fConfig = kRGBA_8888_GrPixelConfig;
    103     wrappedDesc.fWidth = kW;
    104     wrappedDesc.fHeight = kH;
    105     wrappedDesc.fOrigin = kBottomLeft_GrSurfaceOrigin;
    106     wrappedDesc.fSampleCnt = 0;
    107     wrappedDesc.fFlags = kRenderTarget_GrBackendTextureFlag;
    108     wrappedDesc.fTextureHandle = texHandle;
    109 
    110     SkAutoTUnref<SkSurface> surface(
    111         SkSurface::NewWrappedRenderTarget(context, wrappedDesc, nullptr));
    112     REPORTER_ASSERT(reporter, surface);
    113     if (surface) {
    114         // Validate that we can draw to the canvas and that the original texture color is preserved
    115         // in pixels that aren't rendered to via the surface.
    116         SkPaint paint;
    117         static const SkColor kRectColor = ~kOrigColor | 0xFF000000;
    118         paint.setColor(kRectColor);
    119         surface->getCanvas()->drawRect(SkRect::MakeWH(SkIntToScalar(kW), SkIntToScalar(kH)/2),
    120                                        paint);
    121         SkImageInfo readInfo = SkImageInfo::MakeN32Premul(kW, kH);
    122         surface->readPixels(readInfo, pixels.get(), kW * sizeof(uint32_t), 0, 0);
    123         bool stop = false;
    124         SkPMColor origColorPM = SkPackARGB32((kOrigColor >> 24 & 0xFF),
    125                                              (kOrigColor >>  0 & 0xFF),
    126                                              (kOrigColor >>  8 & 0xFF),
    127                                              (kOrigColor >> 16 & 0xFF));
    128         SkPMColor rectColorPM = SkPackARGB32((kRectColor >> 24 & 0xFF),
    129                                              (kRectColor >> 16 & 0xFF),
    130                                              (kRectColor >>  8 & 0xFF),
    131                                              (kRectColor >>  0 & 0xFF));
    132         for (int y = 0; y < kH/2 && !stop; ++y) {
    133             for (int x = 0; x < kW && !stop; ++x) {
    134                 REPORTER_ASSERT(reporter, rectColorPM == pixels[x + y * kW]);
    135                 if (rectColorPM != pixels[x + y * kW]) {
    136                     stop = true;
    137                 }
    138             }
    139         }
    140         stop = false;
    141         for (int y = kH/2; y < kH && !stop; ++y) {
    142             for (int x = 0; x < kW && !stop; ++x) {
    143                 REPORTER_ASSERT(reporter, origColorPM == pixels[x + y * kW]);
    144                 if (origColorPM != pixels[x + y * kW]) {
    145                     stop = true;
    146                 }
    147             }
    148         }
    149     }
    150     gpu->deleteTestingOnlyBackendTexture(texHandle);
    151 }
    152 #endif
    153 
    154 static void test_canvas_peek(skiatest::Reporter* reporter,
    155                              SkSurface* surface,
    156                              const SkImageInfo& requestInfo,
    157                              bool expectPeekSuccess) {
    158     const SkColor color = SK_ColorRED;
    159     const SkPMColor pmcolor = SkPreMultiplyColor(color);
    160     SkImageInfo info;
    161     size_t rowBytes;
    162     surface->getCanvas()->clear(color);
    163 
    164     const void* addr = surface->getCanvas()->peekPixels(&info, &rowBytes);
    165     bool success = SkToBool(addr);
    166     REPORTER_ASSERT(reporter, expectPeekSuccess == success);
    167 
    168     SkImageInfo info2;
    169     size_t rb2;
    170     const void* addr2 = surface->peekPixels(&info2, &rb2);
    171 
    172     if (success) {
    173         REPORTER_ASSERT(reporter, requestInfo == info);
    174         REPORTER_ASSERT(reporter, requestInfo.minRowBytes() <= rowBytes);
    175         REPORTER_ASSERT(reporter, pmcolor == *(const SkPMColor*)addr);
    176 
    177         REPORTER_ASSERT(reporter, addr2 == addr);
    178         REPORTER_ASSERT(reporter, info2 == info);
    179         REPORTER_ASSERT(reporter, rb2 == rowBytes);
    180     } else {
    181         REPORTER_ASSERT(reporter, nullptr == addr2);
    182     }
    183 }
    184 DEF_TEST(SurfaceCanvasPeek, reporter) {
    185     for (auto& surface_func : { &create_surface, &create_direct_surface }) {
    186         SkImageInfo requestInfo;
    187         SkAutoTUnref<SkSurface> surface(surface_func(kPremul_SkAlphaType, &requestInfo));
    188         test_canvas_peek(reporter, surface, requestInfo, true);
    189     }
    190 }
    191 #if SK_SUPPORT_GPU
    192 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCanvasPeek_Gpu, reporter, context) {
    193     for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
    194         SkImageInfo requestInfo;
    195         SkAutoTUnref<SkSurface> surface(surface_func(context, kPremul_SkAlphaType, &requestInfo));
    196         test_canvas_peek(reporter, surface, requestInfo, false);
    197     }
    198 }
    199 #endif
    200 
    201 // For compatibility with clients that still call accessBitmap(), we need to ensure that we bump
    202 // the bitmap's genID when we draw to it, else they won't know it has new values. When they are
    203 // exclusively using surface/image, and we can hide accessBitmap from device, we can remove this
    204 // test.
    205 void test_access_pixels(skiatest::Reporter* reporter, SkSurface* surface) {
    206     SkCanvas* canvas = surface->getCanvas();
    207     canvas->clear(0);
    208 
    209     SkBaseDevice* device = canvas->getDevice_just_for_deprecated_compatibility_testing();
    210     SkBitmap bm = device->accessBitmap(false);
    211     uint32_t genID0 = bm.getGenerationID();
    212     // Now we draw something, which needs to "dirty" the genID (sorta like copy-on-write)
    213     canvas->drawColor(SK_ColorBLUE);
    214     // Now check that we get a different genID
    215     uint32_t genID1 = bm.getGenerationID();
    216     REPORTER_ASSERT(reporter, genID0 != genID1);
    217 }
    218 DEF_TEST(SurfaceAccessPixels, reporter) {
    219     for (auto& surface_func : { &create_surface, &create_direct_surface }) {
    220         SkAutoTUnref<SkSurface> surface(surface_func(kPremul_SkAlphaType, nullptr));
    221         test_access_pixels(reporter, surface);
    222     }
    223 }
    224 #if SK_SUPPORT_GPU
    225 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceAccessPixels_Gpu, reporter, context) {
    226     for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
    227         SkAutoTUnref<SkSurface> surface(surface_func(context, kPremul_SkAlphaType, nullptr));
    228         test_access_pixels(reporter, surface);
    229     }
    230 }
    231 #endif
    232 
    233 static void test_snapshot_alphatype(skiatest::Reporter* reporter, SkSurface* surface,
    234                                     bool expectOpaque) {
    235     REPORTER_ASSERT(reporter, surface);
    236     if (surface) {
    237         SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
    238         REPORTER_ASSERT(reporter, image);
    239         if (image) {
    240             REPORTER_ASSERT(reporter, image->isOpaque() == SkToBool(expectOpaque));
    241         }
    242     }
    243 }
    244 DEF_TEST(SurfaceSnapshotAlphaType, reporter) {
    245     for (auto& surface_func : { &create_surface, &create_direct_surface }) {
    246         for (auto& isOpaque : { true, false }) {
    247             SkAlphaType alphaType = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
    248             SkAutoTUnref<SkSurface> surface(surface_func(alphaType, nullptr));
    249             test_snapshot_alphatype(reporter, surface, isOpaque);
    250         }
    251     }
    252 }
    253 #if SK_SUPPORT_GPU
    254 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceSnapshotAlphaType_Gpu, reporter, context) {
    255     for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
    256         for (auto& isOpaque : { true, false }) {
    257             SkAlphaType alphaType = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
    258             SkAutoTUnref<SkSurface> surface(surface_func(context, alphaType, nullptr));
    259             test_snapshot_alphatype(reporter, surface, isOpaque);
    260         }
    261     }
    262 }
    263 #endif
    264 
    265 static GrBackendObject get_surface_backend_texture_handle(
    266     SkSurface* s, SkSurface::BackendHandleAccess a) {
    267     return s->getTextureHandle(a);
    268 }
    269 static GrBackendObject get_surface_backend_render_target_handle(
    270     SkSurface* s, SkSurface::BackendHandleAccess a) {
    271     GrBackendObject result;
    272     if (!s->getRenderTargetHandle(&result, a)) {
    273         return 0;
    274     }
    275     return result;
    276 }
    277 
    278 static void test_backend_handle_access_copy_on_write(
    279     skiatest::Reporter* reporter, SkSurface* surface, SkSurface::BackendHandleAccess mode,
    280     GrBackendObject (*func)(SkSurface*, SkSurface::BackendHandleAccess)) {
    281     GrBackendObject obj1 = func(surface, mode);
    282     SkAutoTUnref<SkImage> snap1(surface->newImageSnapshot());
    283 
    284     GrBackendObject obj2 = func(surface, mode);
    285     SkAutoTUnref<SkImage> snap2(surface->newImageSnapshot());
    286 
    287     // If the access mode triggers CoW, then the backend objects should reflect it.
    288     REPORTER_ASSERT(reporter, (obj1 == obj2) == (snap1 == snap2));
    289 }
    290 DEF_TEST(SurfaceBackendHandleAccessCopyOnWrite, reporter) {
    291     const SkSurface::BackendHandleAccess accessModes[] = {
    292         SkSurface::kFlushRead_BackendHandleAccess,
    293         SkSurface::kFlushWrite_BackendHandleAccess,
    294         SkSurface::kDiscardWrite_BackendHandleAccess,
    295     };
    296     for (auto& handle_access_func :
    297             { &get_surface_backend_texture_handle, &get_surface_backend_render_target_handle }) {
    298         for (auto& accessMode : accessModes) {
    299             SkAutoTUnref<SkSurface> surface(create_surface());
    300             test_backend_handle_access_copy_on_write(reporter, surface, accessMode,
    301                                                      handle_access_func);
    302         }
    303     }
    304 }
    305 #if SK_SUPPORT_GPU
    306 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendHandleAccessCopyOnWrite_Gpu, reporter, context) {
    307         const SkSurface::BackendHandleAccess accessModes[] = {
    308         SkSurface::kFlushRead_BackendHandleAccess,
    309         SkSurface::kFlushWrite_BackendHandleAccess,
    310         SkSurface::kDiscardWrite_BackendHandleAccess,
    311     };
    312     for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
    313         for (auto& handle_access_func :
    314                 { &get_surface_backend_texture_handle, &get_surface_backend_render_target_handle }) {
    315             for (auto& accessMode : accessModes) {
    316                 SkAutoTUnref<SkSurface> surface(surface_func(context, kPremul_SkAlphaType,
    317                                                              nullptr));
    318                 test_backend_handle_access_copy_on_write(reporter, surface, accessMode,
    319                                                          handle_access_func);
    320             }
    321         }
    322     }
    323 }
    324 #endif
    325 
    326 static bool same_image(SkImage* a, SkImage* b,
    327                        std::function<intptr_t(SkImage*)> getImageBackingStore) {
    328     return getImageBackingStore(a) == getImageBackingStore(b);
    329 }
    330 
    331 static bool same_image_surf(SkImage* a, SkSurface* b,
    332                             std::function<intptr_t(SkImage*)> getImageBackingStore,
    333                             std::function<intptr_t(SkSurface*)> getSurfaceBackingStore) {
    334     return getImageBackingStore(a) == getSurfaceBackingStore(b);
    335 }
    336 
    337 static void test_unique_image_snap(skiatest::Reporter* reporter, SkSurface* surface,
    338                                    bool surfaceIsDirect,
    339                                    std::function<intptr_t(SkImage*)> imageBackingStore,
    340                                    std::function<intptr_t(SkSurface*)> surfaceBackingStore) {
    341     std::function<intptr_t(SkImage*)> ibs = imageBackingStore;
    342     std::function<intptr_t(SkSurface*)> sbs = surfaceBackingStore;
    343     static const SkBudgeted kB = SkBudgeted::kNo;
    344     {
    345         SkAutoTUnref<SkImage> image(surface->newImageSnapshot(kB, SkSurface::kYes_ForceUnique));
    346         REPORTER_ASSERT(reporter, !same_image_surf(image, surface, ibs, sbs));
    347         REPORTER_ASSERT(reporter, image->unique());
    348     }
    349     {
    350         SkAutoTUnref<SkImage> image1(surface->newImageSnapshot(kB, SkSurface::kYes_ForceUnique));
    351         REPORTER_ASSERT(reporter, !same_image_surf(image1, surface, ibs, sbs));
    352         REPORTER_ASSERT(reporter, image1->unique());
    353         SkAutoTUnref<SkImage> image2(surface->newImageSnapshot(kB, SkSurface::kYes_ForceUnique));
    354         REPORTER_ASSERT(reporter, !same_image_surf(image2, surface, ibs, sbs));
    355         REPORTER_ASSERT(reporter, !same_image(image1, image2, ibs));
    356         REPORTER_ASSERT(reporter, image2->unique());
    357     }
    358     {
    359         SkAutoTUnref<SkImage> image1(surface->newImageSnapshot(kB, SkSurface::kNo_ForceUnique));
    360         SkAutoTUnref<SkImage> image2(surface->newImageSnapshot(kB, SkSurface::kYes_ForceUnique));
    361         SkAutoTUnref<SkImage> image3(surface->newImageSnapshot(kB, SkSurface::kNo_ForceUnique));
    362         SkAutoTUnref<SkImage> image4(surface->newImageSnapshot(kB, SkSurface::kYes_ForceUnique));
    363         // Image 1 and 3 ought to be the same (or we're missing an optimization).
    364         REPORTER_ASSERT(reporter, same_image(image1, image3, ibs));
    365         // If the surface is not direct then images 1 and 3 should alias the surface's
    366         // store.
    367         REPORTER_ASSERT(reporter, !surfaceIsDirect == same_image_surf(image1, surface, ibs, sbs));
    368         // Image 2 should not be shared with any other image.
    369         REPORTER_ASSERT(reporter, !same_image(image1, image2, ibs) &&
    370                                   !same_image(image3, image2, ibs) &&
    371                                   !same_image(image4, image2, ibs));
    372         REPORTER_ASSERT(reporter, image2->unique());
    373         REPORTER_ASSERT(reporter, !same_image_surf(image2, surface, ibs, sbs));
    374         // Image 4 should not be shared with any other image.
    375         REPORTER_ASSERT(reporter, !same_image(image1, image4, ibs) &&
    376                                   !same_image(image3, image4, ibs));
    377         REPORTER_ASSERT(reporter, !same_image_surf(image4, surface, ibs, sbs));
    378         REPORTER_ASSERT(reporter, image4->unique());
    379     }
    380 }
    381 
    382 DEF_TEST(UniqueImageSnapshot, reporter) {
    383     auto getImageBackingStore = [reporter](SkImage* image) {
    384         SkPixmap pm;
    385         bool success = image->peekPixels(&pm);
    386         REPORTER_ASSERT(reporter, success);
    387         return reinterpret_cast<intptr_t>(pm.addr());
    388     };
    389     auto getSufaceBackingStore = [reporter](SkSurface* surface) {
    390         SkImageInfo info;
    391         size_t rowBytes;
    392         const void* pixels = surface->getCanvas()->peekPixels(&info, &rowBytes);
    393         REPORTER_ASSERT(reporter, pixels);
    394         return reinterpret_cast<intptr_t>(pixels);
    395     };
    396 
    397     SkAutoTUnref<SkSurface> surface(create_surface());
    398     test_unique_image_snap(reporter, surface, false, getImageBackingStore, getSufaceBackingStore);
    399     surface.reset(create_direct_surface());
    400     test_unique_image_snap(reporter, surface, true, getImageBackingStore, getSufaceBackingStore);
    401 }
    402 
    403 #if SK_SUPPORT_GPU
    404 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(UniqueImageSnapshot_Gpu, reporter, context) {
    405     for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
    406         SkAutoTUnref<SkSurface> surface(surface_func(context, kOpaque_SkAlphaType, nullptr));
    407 
    408         auto imageBackingStore = [reporter](SkImage* image) {
    409             GrTexture* texture = as_IB(image)->peekTexture();
    410             if (!texture) {
    411                 ERRORF(reporter, "Not texture backed.");
    412                 return static_cast<intptr_t>(0);
    413             }
    414             return static_cast<intptr_t>(texture->getUniqueID());
    415         };
    416 
    417         auto surfaceBackingStore = [reporter](SkSurface* surface) {
    418             GrRenderTarget* rt =
    419                 surface->getCanvas()->internal_private_accessTopLayerRenderTarget();
    420             if (!rt) {
    421                 ERRORF(reporter, "Not render target backed.");
    422                 return static_cast<intptr_t>(0);
    423             }
    424             return static_cast<intptr_t>(rt->getUniqueID());
    425         };
    426 
    427         test_unique_image_snap(reporter, surface, false, imageBackingStore, surfaceBackingStore);
    428 
    429         // Test again with a "direct" render target;
    430         GrBackendObject textureObject = context->getGpu()->createTestingOnlyBackendTexture(nullptr,
    431             10, 10, kRGBA_8888_GrPixelConfig);
    432         GrBackendTextureDesc desc;
    433         desc.fConfig = kRGBA_8888_GrPixelConfig;
    434         desc.fWidth = 10;
    435         desc.fHeight = 10;
    436         desc.fFlags = kRenderTarget_GrBackendTextureFlag;
    437         desc.fTextureHandle = textureObject;
    438         GrTexture* texture = context->textureProvider()->wrapBackendTexture(desc);
    439         {
    440             SkAutoTUnref<SkSurface> surface(
    441                 SkSurface::NewRenderTargetDirect(texture->asRenderTarget()));
    442             // We should be able to pass true here, but disallowing copy on write for direct GPU
    443             // surfaces is not yet implemented.
    444             test_unique_image_snap(reporter, surface, false, imageBackingStore,
    445                                    surfaceBackingStore);
    446         }
    447         texture->unref();
    448         context->getGpu()->deleteTestingOnlyBackendTexture(textureObject);
    449     }
    450 }
    451 #endif
    452 
    453 #if SK_SUPPORT_GPU
    454 // May we (soon) eliminate the need to keep testing this, by hiding the bloody device!
    455 static uint32_t get_legacy_gen_id(SkSurface* surface) {
    456     SkBaseDevice* device =
    457             surface->getCanvas()->getDevice_just_for_deprecated_compatibility_testing();
    458     return device->accessBitmap(false).getGenerationID();
    459 }
    460 /*
    461  *  Test legacy behavor of bumping the surface's device's bitmap's genID when we access its
    462  *  texture handle for writing.
    463  *
    464  *  Note: this needs to be tested separately from checking newImageSnapshot, as calling that
    465  *  can also incidentally bump the genID (when a new backing surface is created).
    466  */
    467 static void test_backend_handle_gen_id(
    468     skiatest::Reporter* reporter, SkSurface* surface,
    469     GrBackendObject (*func)(SkSurface*, SkSurface::BackendHandleAccess)) {
    470     const uint32_t gen0 = get_legacy_gen_id(surface);
    471     func(surface, SkSurface::kFlushRead_BackendHandleAccess);
    472     const uint32_t gen1 = get_legacy_gen_id(surface);
    473     REPORTER_ASSERT(reporter, gen0 == gen1);
    474 
    475     func(surface, SkSurface::kFlushWrite_BackendHandleAccess);
    476     const uint32_t gen2 = get_legacy_gen_id(surface);
    477     REPORTER_ASSERT(reporter, gen0 != gen2);
    478 
    479     func(surface, SkSurface::kDiscardWrite_BackendHandleAccess);
    480     const uint32_t gen3 = get_legacy_gen_id(surface);
    481     REPORTER_ASSERT(reporter, gen0 != gen3);
    482     REPORTER_ASSERT(reporter, gen2 != gen3);
    483 }
    484 static void test_backend_handle_unique_id(
    485     skiatest::Reporter* reporter, SkSurface* surface,
    486     GrBackendObject (*func)(SkSurface*, SkSurface::BackendHandleAccess)) {
    487     SkAutoTUnref<SkImage> image0(surface->newImageSnapshot());
    488     GrBackendObject obj = func(surface, SkSurface::kFlushRead_BackendHandleAccess);
    489     REPORTER_ASSERT(reporter, obj != 0);
    490     SkAutoTUnref<SkImage> image1(surface->newImageSnapshot());
    491     // just read access should not affect the snapshot
    492     REPORTER_ASSERT(reporter, image0->uniqueID() == image1->uniqueID());
    493 
    494     obj = func(surface, SkSurface::kFlushWrite_BackendHandleAccess);
    495     REPORTER_ASSERT(reporter, obj != 0);
    496     SkAutoTUnref<SkImage> image2(surface->newImageSnapshot());
    497     // expect a new image, since we claimed we would write
    498     REPORTER_ASSERT(reporter, image0->uniqueID() != image2->uniqueID());
    499 
    500     obj = func(surface, SkSurface::kDiscardWrite_BackendHandleAccess);
    501     REPORTER_ASSERT(reporter, obj != 0);
    502     SkAutoTUnref<SkImage> image3(surface->newImageSnapshot());
    503     // expect a new(er) image, since we claimed we would write
    504     REPORTER_ASSERT(reporter, image0->uniqueID() != image3->uniqueID());
    505     REPORTER_ASSERT(reporter, image2->uniqueID() != image3->uniqueID());
    506 }
    507 // No CPU test.
    508 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendHandleAccessIDs_Gpu, reporter, context) {
    509     for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
    510         for (auto& test_func : { &test_backend_handle_unique_id, &test_backend_handle_gen_id }) {
    511             for (auto& handle_access_func :
    512                 { &get_surface_backend_texture_handle, &get_surface_backend_render_target_handle}) {
    513                 SkAutoTUnref<SkSurface> surface(surface_func(context, kPremul_SkAlphaType,
    514                                                              nullptr));
    515                 test_func(reporter, surface, handle_access_func);
    516             }
    517         }
    518     }
    519 }
    520 #endif
    521 
    522 // Verify that the right canvas commands trigger a copy on write.
    523 static void test_copy_on_write(skiatest::Reporter* reporter, SkSurface* surface) {
    524     SkCanvas* canvas = surface->getCanvas();
    525 
    526     const SkRect testRect =
    527         SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
    528                          SkIntToScalar(4), SkIntToScalar(5));
    529     SkPath testPath;
    530     testPath.addRect(SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
    531                                       SkIntToScalar(2), SkIntToScalar(1)));
    532 
    533     const SkIRect testIRect = SkIRect::MakeXYWH(0, 0, 2, 1);
    534 
    535     SkRegion testRegion;
    536     testRegion.setRect(testIRect);
    537 
    538 
    539     const SkColor testColor = 0x01020304;
    540     const SkPaint testPaint;
    541     const SkPoint testPoints[3] = {
    542         {SkIntToScalar(0), SkIntToScalar(0)},
    543         {SkIntToScalar(2), SkIntToScalar(1)},
    544         {SkIntToScalar(0), SkIntToScalar(2)}
    545     };
    546     const size_t testPointCount = 3;
    547 
    548     SkBitmap testBitmap;
    549     testBitmap.allocN32Pixels(10, 10);
    550     testBitmap.eraseColor(0);
    551 
    552     SkRRect testRRect;
    553     testRRect.setRectXY(testRect, SK_Scalar1, SK_Scalar1);
    554 
    555     SkString testText("Hello World");
    556     const SkPoint testPoints2[] = {
    557         { SkIntToScalar(0), SkIntToScalar(1) },
    558         { SkIntToScalar(1), SkIntToScalar(1) },
    559         { SkIntToScalar(2), SkIntToScalar(1) },
    560         { SkIntToScalar(3), SkIntToScalar(1) },
    561         { SkIntToScalar(4), SkIntToScalar(1) },
    562         { SkIntToScalar(5), SkIntToScalar(1) },
    563         { SkIntToScalar(6), SkIntToScalar(1) },
    564         { SkIntToScalar(7), SkIntToScalar(1) },
    565         { SkIntToScalar(8), SkIntToScalar(1) },
    566         { SkIntToScalar(9), SkIntToScalar(1) },
    567         { SkIntToScalar(10), SkIntToScalar(1) },
    568     };
    569 
    570 #define EXPECT_COPY_ON_WRITE(command)                               \
    571     {                                                               \
    572         SkImage* imageBefore = surface->newImageSnapshot();         \
    573         SkAutoTUnref<SkImage> aur_before(imageBefore);              \
    574         canvas-> command ;                                          \
    575         SkImage* imageAfter = surface->newImageSnapshot();          \
    576         SkAutoTUnref<SkImage> aur_after(imageAfter);                \
    577         REPORTER_ASSERT(reporter, imageBefore != imageAfter);       \
    578     }
    579 
    580     EXPECT_COPY_ON_WRITE(clear(testColor))
    581     EXPECT_COPY_ON_WRITE(drawPaint(testPaint))
    582     EXPECT_COPY_ON_WRITE(drawPoints(SkCanvas::kPoints_PointMode, testPointCount, testPoints, \
    583         testPaint))
    584     EXPECT_COPY_ON_WRITE(drawOval(testRect, testPaint))
    585     EXPECT_COPY_ON_WRITE(drawRect(testRect, testPaint))
    586     EXPECT_COPY_ON_WRITE(drawRRect(testRRect, testPaint))
    587     EXPECT_COPY_ON_WRITE(drawPath(testPath, testPaint))
    588     EXPECT_COPY_ON_WRITE(drawBitmap(testBitmap, 0, 0))
    589     EXPECT_COPY_ON_WRITE(drawBitmapRect(testBitmap, testRect, nullptr))
    590     EXPECT_COPY_ON_WRITE(drawBitmapNine(testBitmap, testIRect, testRect, nullptr))
    591     EXPECT_COPY_ON_WRITE(drawText(testText.c_str(), testText.size(), 0, 1, testPaint))
    592     EXPECT_COPY_ON_WRITE(drawPosText(testText.c_str(), testText.size(), testPoints2, \
    593         testPaint))
    594     EXPECT_COPY_ON_WRITE(drawTextOnPath(testText.c_str(), testText.size(), testPath, nullptr, \
    595         testPaint))
    596 }
    597 DEF_TEST(SurfaceCopyOnWrite, reporter) {
    598     SkAutoTUnref<SkSurface> surface(create_surface());
    599     test_copy_on_write(reporter, surface);
    600 }
    601 #if SK_SUPPORT_GPU
    602 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCopyOnWrite_Gpu, reporter, context) {
    603     for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
    604         SkAutoTUnref<SkSurface> surface(surface_func(context, kPremul_SkAlphaType, nullptr));
    605         test_copy_on_write(reporter, surface);
    606     }
    607 }
    608 #endif
    609 
    610 static void test_writable_after_snapshot_release(skiatest::Reporter* reporter,
    611                                                  SkSurface* surface) {
    612     // This test succeeds by not triggering an assertion.
    613     // The test verifies that the surface remains writable (usable) after
    614     // acquiring and releasing a snapshot without triggering a copy on write.
    615     SkCanvas* canvas = surface->getCanvas();
    616     canvas->clear(1);
    617     surface->newImageSnapshot()->unref();  // Create and destroy SkImage
    618     canvas->clear(2);  // Must not assert internally
    619 }
    620 DEF_TEST(SurfaceWriteableAfterSnapshotRelease, reporter) {
    621     SkAutoTUnref<SkSurface> surface(create_surface());
    622     test_writable_after_snapshot_release(reporter, surface);
    623 }
    624 #if SK_SUPPORT_GPU
    625 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceWriteableAfterSnapshotRelease_Gpu, reporter, context) {
    626     for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
    627         SkAutoTUnref<SkSurface> surface(surface_func(context, kPremul_SkAlphaType, nullptr));
    628         test_writable_after_snapshot_release(reporter, surface);
    629     }
    630 }
    631 #endif
    632 
    633 #if SK_SUPPORT_GPU
    634 static void test_crbug263329(skiatest::Reporter* reporter,
    635                              SkSurface* surface1,
    636                              SkSurface* surface2) {
    637     // This is a regression test for crbug.com/263329
    638     // Bug was caused by onCopyOnWrite releasing the old surface texture
    639     // back to the scratch texture pool even though the texture is used
    640     // by and active SkImage_Gpu.
    641     SkCanvas* canvas1 = surface1->getCanvas();
    642     SkCanvas* canvas2 = surface2->getCanvas();
    643     canvas1->clear(1);
    644     SkAutoTUnref<SkImage> image1(surface1->newImageSnapshot());
    645     // Trigger copy on write, new backing is a scratch texture
    646     canvas1->clear(2);
    647     SkAutoTUnref<SkImage> image2(surface1->newImageSnapshot());
    648     // Trigger copy on write, old backing should not be returned to scratch
    649     // pool because it is held by image2
    650     canvas1->clear(3);
    651 
    652     canvas2->clear(4);
    653     SkAutoTUnref<SkImage> image3(surface2->newImageSnapshot());
    654     // Trigger copy on write on surface2. The new backing store should not
    655     // be recycling a texture that is held by an existing image.
    656     canvas2->clear(5);
    657     SkAutoTUnref<SkImage> image4(surface2->newImageSnapshot());
    658     REPORTER_ASSERT(reporter, as_IB(image4)->getTexture() != as_IB(image3)->getTexture());
    659     // The following assertion checks crbug.com/263329
    660     REPORTER_ASSERT(reporter, as_IB(image4)->getTexture() != as_IB(image2)->getTexture());
    661     REPORTER_ASSERT(reporter, as_IB(image4)->getTexture() != as_IB(image1)->getTexture());
    662     REPORTER_ASSERT(reporter, as_IB(image3)->getTexture() != as_IB(image2)->getTexture());
    663     REPORTER_ASSERT(reporter, as_IB(image3)->getTexture() != as_IB(image1)->getTexture());
    664     REPORTER_ASSERT(reporter, as_IB(image2)->getTexture() != as_IB(image1)->getTexture());
    665 }
    666 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCRBug263329_Gpu, reporter, context) {
    667     for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
    668         SkAutoTUnref<SkSurface> surface1(surface_func(context, kPremul_SkAlphaType, nullptr));
    669         SkAutoTUnref<SkSurface> surface2(surface_func(context, kPremul_SkAlphaType, nullptr));
    670         test_crbug263329(reporter, surface1, surface2);
    671     }
    672 }
    673 #endif
    674 
    675 DEF_TEST(SurfaceGetTexture, reporter) {
    676     SkAutoTUnref<SkSurface> surface(create_surface());
    677     SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
    678     REPORTER_ASSERT(reporter, as_IB(image)->getTexture() == nullptr);
    679     surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode);
    680     REPORTER_ASSERT(reporter, as_IB(image)->getTexture() == nullptr);
    681 }
    682 #if SK_SUPPORT_GPU
    683 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceGetTexture_Gpu, reporter, context) {
    684     for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
    685         SkAutoTUnref<SkSurface> surface(surface_func(context, kPremul_SkAlphaType, nullptr));
    686         SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
    687         GrTexture* texture = as_IB(image)->getTexture();
    688         REPORTER_ASSERT(reporter, texture);
    689         REPORTER_ASSERT(reporter, 0 != texture->getTextureHandle());
    690         surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode);
    691         REPORTER_ASSERT(reporter, as_IB(image)->getTexture() == texture);
    692     }
    693 }
    694 #endif
    695 
    696 #if SK_SUPPORT_GPU
    697 #include "GrGpuResourcePriv.h"
    698 #include "SkGpuDevice.h"
    699 #include "SkImage_Gpu.h"
    700 #include "SkSurface_Gpu.h"
    701 
    702 static SkBudgeted is_budgeted(SkSurface* surf) {
    703     return ((SkSurface_Gpu*)surf)->getDevice()->accessRenderTarget()->resourcePriv().isBudgeted();
    704 }
    705 
    706 static SkBudgeted is_budgeted(SkImage* image) {
    707     return ((SkImage_Gpu*)image)->getTexture()->resourcePriv().isBudgeted();
    708 }
    709 
    710 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBudget, reporter, context) {
    711     SkImageInfo info = SkImageInfo::MakeN32Premul(8,8);
    712     for (auto sbudgeted : { SkBudgeted::kNo, SkBudgeted::kYes }) {
    713         for (auto ibudgeted : { SkBudgeted::kNo, SkBudgeted::kYes }) {
    714             SkAutoTUnref<SkSurface>
    715                 surface(SkSurface::NewRenderTarget(context, sbudgeted, info, 0));
    716             SkASSERT(surface);
    717             REPORTER_ASSERT(reporter, sbudgeted == is_budgeted(surface));
    718 
    719             SkAutoTUnref<SkImage> image(surface->newImageSnapshot(ibudgeted));
    720 
    721             // Initially the image shares a texture with the surface, and the surface decides
    722             // whether it is budgeted or not.
    723             REPORTER_ASSERT(reporter, sbudgeted == is_budgeted(surface));
    724             REPORTER_ASSERT(reporter, sbudgeted == is_budgeted(image));
    725 
    726             // Now trigger copy-on-write
    727             surface->getCanvas()->clear(SK_ColorBLUE);
    728 
    729             // They don't share a texture anymore. They should each have made their own budget
    730             // decision.
    731             REPORTER_ASSERT(reporter, sbudgeted == is_budgeted(surface));
    732             REPORTER_ASSERT(reporter, ibudgeted == is_budgeted(image));
    733         }
    734     }
    735 }
    736 #endif
    737 
    738 static void test_no_canvas1(skiatest::Reporter* reporter,
    739                             SkSurface* surface,
    740                             SkSurface::ContentChangeMode mode) {
    741     // Test passes by not asserting
    742     surface->notifyContentWillChange(mode);
    743     SkDEBUGCODE(surface->validate();)
    744 }
    745 static void test_no_canvas2(skiatest::Reporter* reporter,
    746                             SkSurface* surface,
    747                             SkSurface::ContentChangeMode mode) {
    748     // Verifies the robustness of SkSurface for handling use cases where calls
    749     // are made before a canvas is created.
    750     SkImage* image1 = surface->newImageSnapshot();
    751     SkAutoTUnref<SkImage> aur_image1(image1);
    752     SkDEBUGCODE(image1->validate();)
    753     SkDEBUGCODE(surface->validate();)
    754     surface->notifyContentWillChange(mode);
    755     SkDEBUGCODE(image1->validate();)
    756     SkDEBUGCODE(surface->validate();)
    757     SkImage* image2 = surface->newImageSnapshot();
    758     SkAutoTUnref<SkImage> aur_image2(image2);
    759     SkDEBUGCODE(image2->validate();)
    760     SkDEBUGCODE(surface->validate();)
    761     REPORTER_ASSERT(reporter, image1 != image2);
    762 }
    763 DEF_TEST(SurfaceNoCanvas, reporter) {
    764     SkSurface::ContentChangeMode modes[] =
    765             { SkSurface::kDiscard_ContentChangeMode, SkSurface::kRetain_ContentChangeMode};
    766     for (auto& test_func : { &test_no_canvas1, &test_no_canvas2 }) {
    767         for (auto& mode : modes) {
    768             SkAutoTUnref<SkSurface> surface(create_surface());
    769             test_func(reporter, surface, mode);
    770         }
    771     }
    772 }
    773 #if SK_SUPPORT_GPU
    774 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceNoCanvas_Gpu, reporter, context) {
    775     SkSurface::ContentChangeMode modes[] =
    776             { SkSurface::kDiscard_ContentChangeMode, SkSurface::kRetain_ContentChangeMode};
    777     for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
    778         for (auto& test_func : { &test_no_canvas1, &test_no_canvas2 }) {
    779             for (auto& mode : modes) {
    780                 SkAutoTUnref<SkSurface> surface(
    781                     surface_func(context, kPremul_SkAlphaType, nullptr));
    782                 test_func(reporter, surface, mode);
    783             }
    784         }
    785     }
    786 }
    787 #endif
    788 
    789 static void check_rowbytes_remain_consistent(SkSurface* surface, skiatest::Reporter* reporter) {
    790     SkImageInfo info;
    791     size_t rowBytes;
    792     REPORTER_ASSERT(reporter, surface->peekPixels(&info, &rowBytes));
    793 
    794     SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
    795     SkImageInfo im_info;
    796     size_t im_rowbytes;
    797     REPORTER_ASSERT(reporter, image->peekPixels(&im_info, &im_rowbytes));
    798 
    799     REPORTER_ASSERT(reporter, rowBytes == im_rowbytes);
    800 
    801     // trigger a copy-on-write
    802     surface->getCanvas()->drawPaint(SkPaint());
    803     SkAutoTUnref<SkImage> image2(surface->newImageSnapshot());
    804     REPORTER_ASSERT(reporter, image->uniqueID() != image2->uniqueID());
    805 
    806     SkImageInfo im_info2;
    807     size_t im_rowbytes2;
    808     REPORTER_ASSERT(reporter, image2->peekPixels(&im_info2, &im_rowbytes2));
    809 
    810     REPORTER_ASSERT(reporter, im_rowbytes2 == im_rowbytes);
    811 }
    812 
    813 DEF_TEST(surface_rowbytes, reporter) {
    814     const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
    815 
    816     SkAutoTUnref<SkSurface> surf0(SkSurface::NewRaster(info));
    817     check_rowbytes_remain_consistent(surf0, reporter);
    818 
    819     // specify a larger rowbytes
    820     SkAutoTUnref<SkSurface> surf1(SkSurface::NewRaster(info, 500, nullptr));
    821     check_rowbytes_remain_consistent(surf1, reporter);
    822 
    823     // Try some illegal rowByte values
    824     SkSurface* s = SkSurface::NewRaster(info, 396, nullptr);    // needs to be at least 400
    825     REPORTER_ASSERT(reporter, nullptr == s);
    826     s = SkSurface::NewRaster(info, 1 << 30, nullptr); // allocation to large
    827     REPORTER_ASSERT(reporter, nullptr == s);
    828 }
    829 
    830 #if SK_SUPPORT_GPU
    831 
    832 void test_surface_clear(skiatest::Reporter* reporter, SkSurface* surfacePtr,
    833                         std::function<GrSurface*(SkSurface*)> grSurfaceGetter,
    834                         uint32_t expectedValue) {
    835     SkAutoTUnref<SkSurface> surface(surfacePtr);
    836     if (!surface) {
    837         ERRORF(reporter, "Could not create GPU SkSurface.");
    838         return;
    839     }
    840     int w = surface->width();
    841     int h = surface->height();
    842     SkAutoTDeleteArray<uint32_t> pixels(new uint32_t[w * h]);
    843     memset(pixels.get(), ~expectedValue, sizeof(uint32_t) * w * h);
    844 
    845     SkAutoTUnref<GrSurface> grSurface(SkSafeRef(grSurfaceGetter(surface)));
    846     if (!grSurface) {
    847         ERRORF(reporter, "Could access render target of GPU SkSurface.");
    848         return;
    849     }
    850     SkASSERT(surface->unique());
    851     surface.reset();
    852     grSurface->readPixels(0, 0, w, h, kRGBA_8888_GrPixelConfig, pixels.get());
    853     for (int y = 0; y < h; ++y) {
    854         for (int x = 0; x < w; ++x) {
    855             uint32_t pixel = pixels.get()[y * w + x];
    856             if (pixel != expectedValue) {
    857                 SkString msg;
    858                 if (expectedValue) {
    859                     msg = "SkSurface should have left render target unmodified";
    860                 } else {
    861                     msg = "SkSurface should have cleared the render target";
    862                 }
    863                 ERRORF(reporter,
    864                        "%s but read 0x%08x (instead of 0x%08x) at %x,%d", msg.c_str(), pixel,
    865                        expectedValue, x, y);
    866                 return;
    867             }
    868         }
    869     }
    870 }
    871 
    872 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceClear_Gpu, reporter, context) {
    873     std::function<GrSurface*(SkSurface*)> grSurfaceGetters[] = {
    874         [] (SkSurface* s){ return s->getCanvas()->internal_private_accessTopLayerRenderTarget(); },
    875         [] (SkSurface* s){
    876             SkBaseDevice* d =
    877                 s->getCanvas()->getDevice_just_for_deprecated_compatibility_testing();
    878             return d->accessRenderTarget(); },
    879         [] (SkSurface* s){ SkAutoTUnref<SkImage> i(s->newImageSnapshot());
    880                            return i->getTexture(); },
    881         [] (SkSurface* s){ SkAutoTUnref<SkImage> i(s->newImageSnapshot());
    882                            return as_IB(i)->peekTexture(); },
    883     };
    884     for (auto grSurfaceGetter : grSurfaceGetters) {
    885         for (auto& surface_func : {&create_gpu_surface, &create_gpu_scratch_surface}) {
    886             SkSurface* surface = surface_func(context, kPremul_SkAlphaType, nullptr);
    887             test_surface_clear(reporter, surface, grSurfaceGetter, 0x0);
    888         }
    889         // Wrapped RTs are *not* supposed to clear (to allow client to partially update a surface).
    890         static const int kWidth = 10;
    891         static const int kHeight = 10;
    892         SkAutoTDeleteArray<uint32_t> pixels(new uint32_t[kWidth * kHeight]);
    893         memset(pixels.get(), 0xAB, sizeof(uint32_t) * kWidth * kHeight);
    894 
    895         GrBackendObject textureObject =
    896                 context->getGpu()->createTestingOnlyBackendTexture(pixels.get(), kWidth, kHeight,
    897                                                                    kRGBA_8888_GrPixelConfig);
    898 
    899         GrBackendTextureDesc desc;
    900         desc.fConfig = kRGBA_8888_GrPixelConfig;
    901         desc.fWidth = kWidth;
    902         desc.fHeight = kHeight;
    903         desc.fFlags = kRenderTarget_GrBackendTextureFlag;
    904         desc.fTextureHandle = textureObject;
    905 
    906         SkSurface* surface = SkSurface::NewFromBackendTexture(context, desc, nullptr);
    907         test_surface_clear(reporter, surface, grSurfaceGetter, 0xABABABAB);
    908         context->getGpu()->deleteTestingOnlyBackendTexture(textureObject);
    909     }
    910 }
    911 #endif
    912