Home | History | Annotate | Download | only in docs
      1 #Topic Surface
      2 #Alias Surface_Reference ##
      3 
      4 #Class SkSurface
      5 
      6 #Code
      7 #Populate
      8 ##
      9 
     10 SkSurface is responsible for managing the pixels that a canvas draws into. The pixels can be
     11 allocated either in CPU memory, if a raster surface; or on the GPU, for a GrRenderTarget surface.
     12 SkSurface takes care of allocating a SkCanvas that will draw into the surface. Call
     13 surface->getCanvas() to use that canvas. The caller should not delete the returned canvas;
     14 it is owned by surface.
     15 
     16 SkSurface always has non-zero dimensions. If there is a request for a new surface, and either
     17 of the requested dimensions are zero, then nullptr will be returned.
     18 
     19 # ------------------------------------------------------------------------------
     20 
     21 #Method static sk_sp<SkSurface> MakeRasterDirect(const SkImageInfo& imageInfo, void* pixels,
     22                                              size_t rowBytes,
     23                                              const SkSurfaceProps* surfaceProps = nullptr)
     24 #In Constructors
     25 #Line # creates Surface from SkImageInfo and Pixel_Storage ##
     26 #Populate
     27 
     28 #Example
     29 void draw(SkCanvas* ) {
     30     SkImageInfo info = SkImageInfo::MakeN32Premul(3, 3);
     31     const size_t size = info.computeMinByteSize();
     32     SkAutoTMalloc<SkPMColor> storage(size);
     33     SkPMColor* pixels = storage.get();
     34     sk_sp<SkSurface> surface(SkSurface::MakeRasterDirect(info, pixels, info.minRowBytes()));
     35     SkCanvas* canvas = surface->getCanvas();
     36     canvas->clear(SK_ColorWHITE);
     37     SkPMColor pmWhite = pixels[0];
     38     SkPaint paint;
     39     canvas->drawPoint(1, 1, paint);
     40     canvas->flush();  // ensure that point was drawn
     41     for (int y = 0; y < info.height(); ++y) {
     42         for (int x = 0; x < info.width(); ++x) {
     43             SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
     44         }
     45         SkDebugf("\n");
     46     }
     47 }
     48     #StdOut
     49         ---
     50         -x-
     51         ---
     52     ##
     53 ##
     54 
     55 #SeeAlso MakeRasterDirectReleaseProc MakeRaster MakeRasterN32Premul SkCanvas::MakeRasterDirect
     56 
     57 #Method ##
     58 
     59 # ------------------------------------------------------------------------------
     60 
     61 #Method static sk_sp<SkSurface> MakeRasterDirectReleaseProc(const SkImageInfo& imageInfo, void* pixels,
     62                                     size_t rowBytes,
     63                                     void (*releaseProc)(void* pixels, void* context),
     64                                     void* context, const SkSurfaceProps* surfaceProps = nullptr)
     65 #In Constructors
     66 #Line # creates Surface from SkImageInfo and Pixel_Storage ##
     67 #Populate
     68 
     69 #Example
     70 #Function
     71 static void release_direct_surface_storage(void* pixels, void* context) {
     72     if (pixels == context) {
     73         SkDebugf("expected release context\n");
     74     }
     75     sk_free(pixels);
     76 }
     77 
     78 ##
     79 void draw(SkCanvas* ) {
     80     SkImageInfo info = SkImageInfo::MakeN32Premul(3, 3);
     81     const size_t rowBytes = info.minRowBytes();
     82     void* pixels = sk_malloc_throw(info.computeByteSize(rowBytes));
     83     sk_sp<SkSurface> surface(SkSurface::MakeRasterDirectReleaseProc(info, pixels, rowBytes,
     84             release_direct_surface_storage, pixels));
     85     SkCanvas* canvas = surface->getCanvas();
     86     canvas->clear(SK_ColorWHITE);
     87     SkPMColor* colorPtr = (SkPMColor*) pixels;
     88     SkPMColor pmWhite = colorPtr[0];
     89     SkPaint paint;
     90     canvas->drawPoint(1, 1, paint);
     91     canvas->flush();  // ensure that point was drawn
     92     for (int y = 0; y < info.height(); ++y) {
     93         for (int x = 0; x < info.width(); ++x) {
     94             SkDebugf("%c", *colorPtr++ == pmWhite ? '-' : 'x');
     95         }
     96         SkDebugf("\n");
     97     }
     98 }
     99 #StdOut
    100 ---
    101 -x-
    102 ---
    103 expected release context
    104 ##
    105 ##
    106 
    107 #SeeAlso MakeRasterDirect MakeRasterN32Premul MakeRaster
    108 
    109 #Method ##
    110 
    111 # ------------------------------------------------------------------------------
    112 
    113 #Method static sk_sp<SkSurface> MakeRaster(const SkImageInfo& imageInfo, size_t rowBytes,
    114                                        const SkSurfaceProps* surfaceProps)
    115 #In Constructors
    116 #Line # creates Surface from SkImageInfo ##
    117 #Populate
    118 
    119 #Example
    120 void draw(SkCanvas* ) {
    121     SkImageInfo info = SkImageInfo::MakeN32Premul(3, 3);
    122     const size_t rowBytes = 64;
    123     sk_sp<SkSurface> surface(SkSurface::MakeRaster(info, rowBytes, nullptr));
    124     SkCanvas* canvas = surface->getCanvas();
    125     canvas->clear(SK_ColorWHITE);
    126     SkPixmap pixmap;
    127     if (surface->peekPixels(&pixmap)) {
    128         const uint32_t* colorPtr = pixmap.addr32();
    129         SkPMColor pmWhite = colorPtr[0];
    130         SkPaint paint;
    131         canvas->drawPoint(1, 1, paint);
    132         canvas->flush();  // ensure that point was drawn
    133         for (int y = 0; y < info.height(); ++y) {
    134             for (int x = 0; x < info.width(); ++x) {
    135                 SkDebugf("%c", colorPtr[x] == pmWhite ? '-' : 'x');
    136             }
    137             colorPtr += rowBytes / sizeof(colorPtr[0]);
    138             SkDebugf("\n");
    139         }
    140     }
    141 }
    142 #StdOut
    143 ---
    144 -x-
    145 ---
    146 ##
    147 ##
    148 
    149 #SeeAlso MakeRasterDirect MakeRasterN32Premul MakeRasterDirectReleaseProc
    150 
    151 #Method ##
    152 
    153 # ------------------------------------------------------------------------------
    154 
    155 #Method static sk_sp<SkSurface> MakeRaster(const SkImageInfo& imageInfo,
    156                                        const SkSurfaceProps* props = nullptr)
    157 #Populate
    158 
    159 #Example
    160 void draw(SkCanvas* ) {
    161     SkImageInfo info = SkImageInfo::MakeN32Premul(3, 3);
    162     sk_sp<SkSurface> surface(SkSurface::MakeRaster(info));
    163     SkCanvas* canvas = surface->getCanvas();
    164     canvas->clear(SK_ColorWHITE);
    165     SkPixmap pixmap;
    166     if (surface->peekPixels(&pixmap)) {
    167         const uint32_t* colorPtr = pixmap.addr32();
    168         SkPMColor pmWhite = colorPtr[0];
    169         SkPaint paint;
    170         canvas->drawPoint(1, 1, paint);
    171         canvas->flush();  // ensure that point was drawn
    172         for (int y = 0; y < info.height(); ++y) {
    173             for (int x = 0; x < info.width(); ++x) {
    174                 SkDebugf("%c", colorPtr[x] == pmWhite ? '-' : 'x');
    175             }
    176             colorPtr += info.width();
    177             SkDebugf("\n");
    178         }
    179     }
    180 }
    181 ##
    182 
    183 #SeeAlso MakeRasterDirect MakeRasterN32Premul MakeRasterDirectReleaseProc
    184 
    185 #Method ##
    186 
    187 # ------------------------------------------------------------------------------
    188 
    189 #Method static sk_sp<SkSurface> MakeRasterN32Premul(int width, int height,
    190                                                 const SkSurfaceProps* surfaceProps = nullptr)
    191 #In Constructors
    192 #Line # creates Surface from width, height matching output ##
    193 #Populate
    194 
    195 #Example
    196 void draw(SkCanvas* ) {
    197     sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(3, 3));
    198     SkCanvas* canvas = surface->getCanvas();
    199     canvas->clear(SK_ColorWHITE);
    200     SkPixmap pixmap;
    201     if (surface->peekPixels(&pixmap)) {
    202         const uint32_t* colorPtr = pixmap.addr32();
    203         SkPMColor pmWhite = colorPtr[0];
    204         SkPaint paint;
    205         canvas->drawPoint(1, 1, paint);
    206         canvas->flush();  // ensure that point was drawn
    207         for (int y = 0; y < surface->height(); ++y) {
    208             for (int x = 0; x < surface->width(); ++x) {
    209                 SkDebugf("%c", colorPtr[x] == pmWhite ? '-' : 'x');
    210             }
    211             colorPtr += surface->width();
    212             SkDebugf("\n");
    213         }
    214     }
    215 }
    216 #StdOut
    217 ---
    218 -x-
    219 ---
    220 ##
    221 ##
    222 
    223 #SeeAlso MakeRasterDirect MakeRasterN32Premul MakeRasterDirectReleaseProc
    224 
    225 #Method ##
    226 
    227 # ------------------------------------------------------------------------------
    228 
    229 #Method static sk_sp<SkSurface> MakeFromBackendTexture(GrContext* context,
    230                                                    const GrBackendTexture& backendTexture,
    231                                                    GrSurfaceOrigin origin, int sampleCnt,
    232                                                    SkColorType colorType,
    233                                                    sk_sp<SkColorSpace> colorSpace,
    234                                                    const SkSurfaceProps* surfaceProps)
    235 #In Constructors
    236 #Line # creates Surface from GPU texture ##
    237 #Populate
    238 
    239 #Example
    240 #Platform gpu cpu
    241 #Image 3
    242     SkPaint paint;
    243     paint.setTextSize(32);
    244     GrContext* context = canvas->getGrContext();
    245     if (!context) {
    246          canvas->drawString("GPU only!", 20, 40, paint);
    247          return;
    248     }
    249     sk_sp<SkSurface> gpuSurface = SkSurface::MakeFromBackendTexture(context,
    250             backEndTexture, kTopLeft_GrSurfaceOrigin, 0,
    251             kRGBA_8888_SkColorType, nullptr, nullptr);
    252     auto surfaceCanvas = gpuSurface->getCanvas();
    253     surfaceCanvas->drawString("GPU rocks!", 20, 40, paint);
    254     sk_sp<SkImage> image(gpuSurface->makeImageSnapshot());
    255     canvas->drawImage(image, 0, 0);
    256 ##
    257 
    258 #SeeAlso GrBackendTexture MakeFromBackendRenderTarget MakeRenderTarget
    259 
    260 #Method ##
    261 
    262 # ------------------------------------------------------------------------------
    263 
    264 #Method static sk_sp<SkSurface> MakeFromBackendRenderTarget(GrContext* context,
    265                                                 const GrBackendRenderTarget& backendRenderTarget,
    266                                                 GrSurfaceOrigin origin,
    267                                                 SkColorType colorType,
    268                                                 sk_sp<SkColorSpace> colorSpace,
    269                                                 const SkSurfaceProps* surfaceProps)
    270 #In Constructors
    271 #Line # creates Surface from GPU render target ##
    272 #Populate
    273 
    274 #Example
    275 #ToDo  remove !fiddle below once backEndTextureRenderTarget is available ##
    276 #Platform !fiddle gpu
    277     SkPaint paint;
    278     paint.setTextSize(32);
    279     GrContext* context = canvas->getGrContext();
    280     if (!context) {
    281          canvas->drawString("GPU only!", 20, 40, paint);
    282          return;
    283     }
    284     sk_sp<SkSurface> gpuSurface = SkSurface::MakeFromBackendRenderTarget(context,
    285             backEndRenderTarget, kTopLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType,
    286             nullptr, nullptr);
    287     auto surfaceCanvas = gpuSurface->getCanvas();
    288     surfaceCanvas->drawString("GPU rocks!", 20, 40, paint);
    289     sk_sp<SkImage> image(gpuSurface->makeImageSnapshot());
    290     canvas->drawImage(image, 0, 0);
    291 ##
    292 
    293 #SeeAlso MakeFromBackendTexture MakeRenderTarget
    294 
    295 #Method ##
    296 
    297 # ------------------------------------------------------------------------------
    298 
    299 #Method static sk_sp<SkSurface> MakeFromBackendTextureAsRenderTarget(GrContext* context,
    300                                                             const GrBackendTexture& backendTexture,
    301                                                             GrSurfaceOrigin origin,
    302                                                             int sampleCnt,
    303                                                             SkColorType colorType,
    304                                                             sk_sp<SkColorSpace> colorSpace,
    305                                                             const SkSurfaceProps* surfaceProps)
    306 #In Constructors
    307 #Line # creates Surface from GPU back-end render target ##
    308 #Populate
    309 
    310 #Example
    311 #ToDo example is bogus; gpuSurface should not make image ##
    312 #Platform gpu
    313 #Image 3
    314     SkPaint paint;
    315     paint.setTextSize(32);
    316     GrContext* context = canvas->getGrContext();
    317     if (!context) {
    318          canvas->drawString("GPU only!", 20, 40, paint);
    319          return;
    320     }
    321     sk_sp<SkSurface> gpuSurface = SkSurface::MakeFromBackendTextureAsRenderTarget(
    322             context, backEndTexture, kTopLeft_GrSurfaceOrigin, 0,
    323             kRGBA_8888_SkColorType, nullptr, nullptr);
    324     auto surfaceCanvas = gpuSurface->getCanvas();
    325     surfaceCanvas->drawString("GPU rocks!", 20, 40, paint);
    326     sk_sp<SkImage> image(gpuSurface->makeImageSnapshot());
    327     canvas->drawImage(image, 0, 0);
    328 ##
    329 
    330 #SeeAlso MakeFromBackendRenderTarget MakeRenderTarget
    331 
    332 #Method ##
    333 
    334 # ------------------------------------------------------------------------------
    335 
    336 #Method static sk_sp<SkSurface> MakeRenderTarget(GrContext* context, SkBudgeted budgeted,
    337                                              const SkImageInfo& imageInfo,
    338                                              int sampleCount, GrSurfaceOrigin surfaceOrigin,
    339                                              const SkSurfaceProps* surfaceProps,
    340                                              bool shouldCreateWithMips = false)
    341 #In Constructors
    342 #Line # creates Surface pointing to new GPU memory buffer ##
    343 #Populate
    344 
    345 #Example
    346 #Platform gpu
    347 #Height 64
    348     SkPaint paint;
    349     paint.setTextSize(32);
    350     GrContext* context = canvas->getGrContext();
    351     if (!context) {
    352          canvas->drawString("GPU only!", 20, 40, paint);
    353          return;
    354     }
    355     SkImageInfo info = SkImageInfo::MakeN32(256, 64, kOpaque_SkAlphaType);
    356     for (auto surfaceOrigin : { kTopLeft_GrSurfaceOrigin, kBottomLeft_GrSurfaceOrigin } ) {
    357         auto gpuSurface(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info, 0,
    358                surfaceOrigin, nullptr));
    359         auto surfaceCanvas = gpuSurface->getCanvas();
    360         surfaceCanvas->clear(SK_ColorWHITE);
    361         surfaceCanvas->drawString("GPU rocks!", 20, 40, paint);
    362         sk_sp<SkImage> image(gpuSurface->makeImageSnapshot());
    363         canvas->drawImage(image, 0, 0);
    364        canvas->translate(0, 128);
    365     }
    366 ##
    367 
    368 #SeeAlso MakeFromBackendRenderTarget MakeFromBackendTextureAsRenderTarget
    369 
    370 #Method ##
    371 
    372 # ------------------------------------------------------------------------------
    373 
    374 #Method static sk_sp<SkSurface> MakeRenderTarget(GrContext* context, SkBudgeted budgeted,
    375                                              const SkImageInfo& imageInfo, int sampleCount,
    376                                              const SkSurfaceProps* props)
    377 #Populate
    378 
    379 #Example
    380 #Platform cpu gpu
    381 #Description
    382 LCD text takes advantage of raster striping to improve resolution. Only one of
    383 the four combinations is correct, depending on whether monitor LCD striping is
    384 horizontal or vertical, and whether the order of the stripes is red blue green
    385 or red green blue.
    386 ##
    387 void draw(SkCanvas* canvas) {
    388     auto test_draw = [](SkCanvas* surfaceCanvas) -> void {
    389         SkPaint paint;
    390         paint.setAntiAlias(true);
    391         paint.setLCDRenderText(true);
    392         paint.setColor(0xFFBBBBBB);
    393         surfaceCanvas->drawRect(SkRect::MakeWH(128, 64), paint);
    394         paint.setColor(SK_ColorWHITE);
    395         paint.setTextSize(32);
    396         surfaceCanvas->drawString("Pest", 0, 25, paint);
    397     };
    398     GrContext* context = canvas->getGrContext();
    399     SkImageInfo info = SkImageInfo::MakeN32(128, 64, kOpaque_SkAlphaType);
    400     int y = 0;
    401     for (auto geometry : { kRGB_H_SkPixelGeometry, kBGR_H_SkPixelGeometry,
    402                            kRGB_V_SkPixelGeometry, kBGR_V_SkPixelGeometry } ) {
    403         SkSurfaceProps props(0, geometry);
    404         sk_sp<SkSurface> surface = context ? SkSurface::MakeRenderTarget(
    405                 context, SkBudgeted::kNo, info, 0, &props) : SkSurface::MakeRaster(info, &props);
    406         test_draw(surface->getCanvas());
    407         surface->draw(canvas, 0, y, nullptr);
    408         sk_sp<SkImage> image(surface->makeImageSnapshot());
    409         SkAutoCanvasRestore acr(canvas, true);
    410         canvas->scale(8, 8);
    411         canvas->drawImage(image, 12, y / 8);
    412         y += 64;
    413     }
    414 }
    415 ##
    416 
    417 #SeeAlso MakeFromBackendRenderTarget MakeFromBackendTextureAsRenderTarget
    418 
    419 #Method ##
    420 
    421 # ------------------------------------------------------------------------------
    422 
    423 #Method static sk_sp<SkSurface> MakeRenderTarget(GrContext* context, SkBudgeted budgeted,
    424                                              const SkImageInfo& imageInfo)
    425 #Populate
    426 
    427 #Example
    428 #Platform gpu
    429     SkPaint paint;
    430     paint.setTextSize(32);
    431     GrContext* context = canvas->getGrContext();
    432     if (!context) {
    433          canvas->drawString("GPU only!", 20, 40, paint);
    434          return;
    435     }
    436     SkImageInfo info = SkImageInfo::MakeN32(256, 64, kOpaque_SkAlphaType);
    437     auto gpuSurface(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info));
    438     auto surfaceCanvas = gpuSurface->getCanvas();
    439     surfaceCanvas->clear(SK_ColorWHITE);
    440     surfaceCanvas->drawString("GPU rocks!", 20, 40, paint);
    441     sk_sp<SkImage> image(gpuSurface->makeImageSnapshot());
    442     canvas->drawImage(image, 0, 0);
    443 ##
    444 
    445 #SeeAlso MakeFromBackendRenderTarget MakeFromBackendTextureAsRenderTarget
    446 
    447 #Method ##
    448 
    449 # ------------------------------------------------------------------------------
    450 
    451 #Method static sk_sp<SkSurface> MakeRenderTarget(GrContext* context,
    452                                              const SkSurfaceCharacterization& characterization,
    453                                              SkBudgeted budgeted)
    454 #Populate
    455 
    456 #NoExample
    457 ##
    458 
    459 #SeeAlso MakeFromBackendRenderTarget MakeFromBackendTextureAsRenderTarget
    460 
    461 #Method ##
    462 
    463 # ------------------------------------------------------------------------------
    464 
    465 #Method static sk_sp<SkSurface> MakeNull(int width, int height)
    466 
    467 #In Constructors
    468 #Line # creates Surface without backing pixels ##
    469 #Populate
    470 
    471 #Example
    472     SkDebugf("SkSurface::MakeNull(0, 0) %c= nullptr\n", SkSurface::MakeNull(0, 0) == nullptr ?
    473              '=' : '!');
    474     const int w = 37;
    475     const int h = 1000;
    476     auto surf = SkSurface::MakeNull(w, h);
    477     auto nullCanvas = surf->getCanvas();
    478     nullCanvas->drawPaint(SkPaint());   // does not crash, nothing draws
    479     SkDebugf("surf->makeImageSnapshot() %c= nullptr\n", surf->makeImageSnapshot() == nullptr ?
    480             '=' : '!');
    481 #StdOut
    482 SkSurface::MakeNull(0, 0) == nullptr
    483 surf->makeImageSnapshot() == nullptr
    484 ##
    485 ##
    486 
    487 #SeeAlso MakeRaster MakeRenderTarget
    488 
    489 #Method ##
    490 
    491 # ------------------------------------------------------------------------------
    492 #Subtopic Property
    493 #Line # member values ##
    494 ##
    495 
    496 #Method int width() const
    497 
    498 #In Property
    499 #Line # returns pixel column count ##
    500 #Populate
    501 
    502 #Example
    503     const int width = 37;
    504     const int height = 1000;
    505     auto surf = SkSurface::MakeNull(width, height);
    506     auto nullCanvas = surf->getCanvas();
    507     SkDebugf("surface width=%d  canvas width=%d\n", surf->width(),
    508              nullCanvas->getBaseLayerSize().fWidth);
    509 #StdOut
    510 surface width=37  canvas width=37
    511 ##
    512 ##
    513 
    514 #SeeAlso height()
    515 
    516 #Method ##
    517 
    518 # ------------------------------------------------------------------------------
    519 
    520 #Method int height() const
    521 #In Property
    522 #Line # returns pixel row count ##
    523 #Populate
    524 
    525 #Example
    526     const int width = 37;
    527     const int height = 1000;
    528     auto surf = SkSurface::MakeNull(width, height);
    529     auto nullCanvas = surf->getCanvas();
    530     SkDebugf("surface height=%d  canvas height=%d\n", surf->height(),
    531              nullCanvas->getBaseLayerSize().fHeight);
    532 #StdOut
    533 surface height=1000  canvas height=1000
    534 ##
    535 ##
    536 
    537 #SeeAlso width()
    538 
    539 #Method ##
    540 
    541 # ------------------------------------------------------------------------------
    542 
    543 #Method uint32_t generationID()
    544 #In Property
    545 #Line # returns unique ID ##
    546 #Populate
    547 
    548 #Example
    549     auto surface = SkSurface::MakeRasterN32Premul(1, 1);
    550     for (int i = 0; i < 3; ++i) {
    551         SkDebugf("surface generationID: %d\n", surface->generationID());
    552         if (0 == i) {
    553             surface->getCanvas()->drawColor(SK_ColorBLACK);
    554         } else {
    555             surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode);
    556         }
    557     }
    558 #StdOut
    559 surface generationID: 1
    560 surface generationID: 2
    561 surface generationID: 3
    562 ##
    563 ##
    564 
    565 #SeeAlso notifyContentWillChange ContentChangeMode getCanvas
    566 
    567 #Method ##
    568 
    569 # ------------------------------------------------------------------------------
    570 
    571 #Enum ContentChangeMode
    572 #Line # parameter options for notifyContentWillChange ##
    573 #Code
    574     enum ContentChangeMode {
    575         kDiscard_ContentChangeMode,
    576         kRetain_ContentChangeMode,
    577     };
    578 ##
    579 
    580 ContentChangeMode members are parameters to notifyContentWillChange.
    581 
    582 #Const kDiscard_ContentChangeMode
    583 #Line # discards surface on change ##
    584 Pass to notifyContentWillChange to discard surface contents when
    585 the surface is cleared or overwritten.
    586 ##
    587 #Const kRetain_ContentChangeMode
    588 #Line # preserves surface on change ##
    589 Pass to notifyContentWillChange when to preserve surface contents.
    590 If a snapshot has been generated, this copies the Surface contents.
    591 ##
    592 
    593 #SeeAlso notifyContentWillChange generationID
    594 
    595 #Enum ##
    596 
    597 # ------------------------------------------------------------------------------
    598 
    599 #ToDo not crazy about misc catagory -- hopefully will become clear with time
    600 ##
    601 
    602 #Subtopic Miscellaneous
    603 #Line # other functions ##
    604 ##
    605 
    606 #Method void notifyContentWillChange(ContentChangeMode mode)
    607 #In Miscellaneous
    608 #Line # notifies that contents will be changed outside of Skia ##
    609 #Populate
    610 
    611 #Example
    612     auto surface = SkSurface::MakeRasterN32Premul(1, 1);
    613     for (int i = 0; i < 3; ++i) {
    614         SkDebugf("surface generationID: %d\n", surface->generationID());
    615         if (0 == i) {
    616             surface->getCanvas()->drawColor(SK_ColorBLACK);
    617         } else {
    618             surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode);
    619         }
    620     }
    621 ##
    622 
    623 #SeeAlso ContentChangeMode generationID
    624 
    625 #Method ##
    626 
    627 # ------------------------------------------------------------------------------
    628 
    629 #Enum BackendHandleAccess
    630 #Line # options to read and write back-end object ##
    631 #Code
    632     enum BackendHandleAccess {
    633         kFlushRead_BackendHandleAccess,
    634         kFlushWrite_BackendHandleAccess,
    635         kDiscardWrite_BackendHandleAccess,
    636     };
    637 
    638     static const BackendHandleAccess kFlushRead_TextureHandleAccess =
    639             kFlushRead_BackendHandleAccess;
    640     static const BackendHandleAccess kFlushWrite_TextureHandleAccess =
    641             kFlushWrite_BackendHandleAccess;
    642     static const BackendHandleAccess kDiscardWrite_TextureHandleAccess =
    643             kDiscardWrite_BackendHandleAccess;
    644 ##
    645 
    646 #Const kFlushRead_BackendHandleAccess 0
    647 #Line # back-end object is readable ##
    648 Caller may read from the back-end object.
    649 ##
    650 #Const kFlushWrite_BackendHandleAccess 1
    651 #Line # back-end object is writable ##
    652 Caller may write to the back-end object.
    653 ##
    654 #Const kDiscardWrite_BackendHandleAccess 2
    655 #Line # back-end object must be overwritten ##
    656 Caller must overwrite the entire back-end object.
    657 ##
    658 
    659 #NoExample
    660 // todo: need to update example to use GrBackendTexture instead of GrBackendObject
    661 #Platform gpu
    662     SkPaint paint;
    663     paint.setTextSize(32);
    664     GrContext* context = canvas->getGrContext();
    665     if (!context) {
    666          canvas->drawString("GPU only!", 20, 40, paint);
    667          return;
    668     }
    669     sk_sp<SkSurface> gpuSurface = SkSurface::MakeRenderTarget(
    670             context, SkBudgeted::kYes, SkImageInfo::MakeN32Premul(10, 10));
    671     int y = 20;
    672     SkString str;
    673     paint.setTextSize(16);
    674     for (auto access : { SkSurface::kFlushRead_BackendHandleAccess,
    675                          SkSurface::kFlushWrite_BackendHandleAccess,
    676                          SkSurface::kDiscardWrite_BackendHandleAccess } ) {
    677         sk_sp<SkImage> image(gpuSurface->makeImageSnapshot());
    678         str.printf("uniqueID=%d", image->uniqueID());
    679         canvas->drawString(str, 20, y += 20, paint);
    680         GrBackendTexture backendTex = gpuSurface->getBackendTexture(access);
    681         str.printf("backendTex is %svalid", backendTex.isValid() ? '' : 'not ');
    682         canvas->drawString(str, 20, y += 20, paint);
    683     }
    684     sk_sp<SkImage> image(gpuSurface->makeImageSnapshot());
    685     str.printf("final image uniqueID=%d", image->uniqueID());
    686     canvas->drawString(str, 20, y += 20, paint);
    687 ##
    688 
    689 #SeeAlso getBackendTexture getBackendRenderTarget
    690 
    691 #Enum ##
    692 
    693 # ------------------------------------------------------------------------------
    694 
    695 #Method GrBackendTexture getBackendTexture(BackendHandleAccess backendHandleAccess)
    696 #In Property
    697 #Line # returns the GPU reference to texture ##
    698 #Populate
    699 
    700 #NoExample
    701 ##
    702 
    703 #SeeAlso GrBackendTexture BackendHandleAccess getBackendRenderTarget
    704 
    705 #Method ##
    706 
    707 # ------------------------------------------------------------------------------
    708 
    709 #Method GrBackendRenderTarget getBackendRenderTarget(BackendHandleAccess backendHandleAccess)
    710 #In Property
    711 #Line # returns the GPU reference to render target ##
    712 #Populate
    713 
    714 #NoExample
    715 ##
    716 
    717 #SeeAlso GrBackendRenderTarget BackendHandleAccess getBackendTexture
    718 
    719 #Method ##
    720 
    721 # ------------------------------------------------------------------------------
    722 
    723 #Method SkCanvas* getCanvas()
    724 #In Property
    725 #Line # returns Canvas that draws into Surface ##
    726 #Populate
    727 
    728 #Example
    729 #Height 64
    730     sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(64, 64));
    731     SkCanvas* surfaceCanvas = surface->getCanvas();
    732     surfaceCanvas->clear(SK_ColorBLUE);
    733     SkPaint paint;
    734     paint.setTextSize(40);
    735     surfaceCanvas->drawString("\xF0\x9F\x98\x81", 12, 45, paint);
    736     surface->draw(canvas, 0, 0, nullptr);
    737 ##
    738 
    739 #SeeAlso makeSurface makeImageSnapshot draw
    740 
    741 #Method ##
    742 
    743 # ------------------------------------------------------------------------------
    744 
    745 #Method sk_sp<SkSurface> makeSurface(const SkImageInfo& imageInfo)
    746 #In Constructors
    747 #Line # creates a compatible Surface ##
    748 #Populate
    749 
    750 #Example
    751 #Height 96
    752     sk_sp<SkSurface> big(SkSurface::MakeRasterN32Premul(64, 64));
    753     sk_sp<SkSurface> lil(big->makeSurface(SkImageInfo::MakeN32(32, 32, kPremul_SkAlphaType)));
    754     big->getCanvas()->clear(SK_ColorRED);
    755     lil->getCanvas()->clear(SK_ColorBLACK);
    756     SkPixmap pixmap;
    757     if (big->peekPixels(&pixmap)) {
    758         SkBitmap bigBits;
    759         bigBits.installPixels(pixmap);
    760         canvas->drawBitmap(bigBits, 0, 0);
    761     }
    762     if (lil->peekPixels(&pixmap)) {
    763         SkBitmap lilBits;
    764         lilBits.installPixels(pixmap);
    765         canvas->drawBitmap(lilBits, 64, 64);
    766     }
    767 ##
    768 
    769 #SeeAlso makeImageSnapshot getCanvas draw
    770 
    771 #Method ##
    772 
    773 # ------------------------------------------------------------------------------
    774 
    775 #Method sk_sp<SkImage> makeImageSnapshot()
    776 #In Constructors
    777 #Line # creates Image capturing Surface contents ##
    778 #Populate
    779 
    780 #Example
    781 #Height 64
    782     sk_sp<SkSurface> big(SkSurface::MakeRasterN32Premul(64, 64));
    783     sk_sp<SkSurface> lil(big->makeSurface(SkImageInfo::MakeN32(32, 32, kPremul_SkAlphaType)));
    784     big->getCanvas()->clear(SK_ColorRED);
    785     lil->getCanvas()->clear(SK_ColorBLACK);
    786     sk_sp<SkImage> early(big->makeImageSnapshot());
    787     lil->draw(big->getCanvas(), 16, 16, nullptr);
    788     sk_sp<SkImage> later(big->makeImageSnapshot());
    789     canvas->drawImage(early, 0, 0);
    790     canvas->drawImage(later, 128, 0);
    791 ##
    792 
    793 #SeeAlso draw getCanvas
    794 
    795 #Method ##
    796 
    797 # ------------------------------------------------------------------------------
    798 
    799 #Method sk_sp<SkImage> makeImageSnapshot(const SkIRect& bounds)
    800 #In Constructors
    801 #Line # creates Image capturing subset of Surface contents ##
    802 #Populate
    803 
    804 #Example
    805 #Height 64
    806     sk_sp<SkSurface> big(SkSurface::MakeRasterN32Premul(64, 64));
    807     sk_sp<SkSurface> lil(big->makeSurface(SkImageInfo::MakeN32(32, 32, kPremul_SkAlphaType)));
    808     big->getCanvas()->clear(SK_ColorRED);
    809     lil->getCanvas()->clear(SK_ColorBLACK);
    810     sk_sp<SkImage> early(big->makeImageSnapshot());
    811     lil->draw(big->getCanvas(), 16, 16, nullptr);
    812     sk_sp<SkImage> later(big->makeImageSnapshot({0, 0, 16, 16}));
    813     canvas->drawImage(early, 0, 0);
    814     canvas->drawImage(later, 0, 0);
    815 ##
    816 
    817 #SeeAlso draw getCanvas
    818 
    819 #Method ##
    820 
    821 # ------------------------------------------------------------------------------
    822 #Subtopic Pixels
    823 #Line # functions with pixel access ##
    824 ##
    825 
    826 #Method void draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint)
    827 #In Pixels
    828 #Line # draws Surface contents to canvas ##
    829 #Populate
    830 
    831 #Example
    832 #Height 64
    833     sk_sp<SkSurface> big(SkSurface::MakeRasterN32Premul(64, 64));
    834     sk_sp<SkSurface> lil(big->makeSurface(SkImageInfo::MakeN32(32, 32, kPremul_SkAlphaType)));
    835     big->getCanvas()->clear(SK_ColorRED);
    836     lil->getCanvas()->clear(SK_ColorBLACK);
    837     lil->draw(big->getCanvas(), 16, 16, nullptr);
    838     SkPixmap pixmap;
    839     if (big->peekPixels(&pixmap)) {
    840         SkBitmap bigBits;
    841         bigBits.installPixels(pixmap);
    842         canvas->drawBitmap(bigBits, 0, 0);
    843     }
    844 ##
    845 
    846 #SeeAlso makeImageSnapshot getCanvas
    847 
    848 #Method ##
    849 
    850 # ------------------------------------------------------------------------------
    851 
    852 #Method bool peekPixels(SkPixmap* pixmap)
    853 #In Pixels
    854 #Line # copies Surface parameters to Pixmap ##
    855 #Populate
    856 
    857 #Example
    858 #Height 64
    859     sk_sp<SkSurface> surf(SkSurface::MakeRasterN32Premul(64, 64));
    860     auto surfCanvas = surf->getCanvas();
    861     surfCanvas->clear(SK_ColorRED);
    862     SkPaint paint;
    863     paint.setTextSize(40);
    864     surfCanvas->drawString("&", 16, 48, paint);
    865     SkPixmap pixmap;
    866     if (surf->peekPixels(&pixmap)) {
    867         SkBitmap surfBits;
    868         surfBits.installPixels(pixmap);
    869         canvas->drawBitmap(surfBits, 0, 0);
    870     }
    871 ##
    872 
    873 #SeeAlso readPixels writePixels
    874 
    875 #Method ##
    876 
    877 # ------------------------------------------------------------------------------
    878 
    879 #Method bool readPixels(const SkPixmap& dst, int srcX, int srcY)
    880 #In Pixels
    881 #Line # copies Rect of pixels ##
    882 Copies Rect of pixels to dst.
    883 
    884 Source Rect corners are (srcX, srcY) and Surface (width(), height()).
    885 Destination Rect corners are (0, 0) and (dst.width(), dst.height()).
    886 Copies each readable pixel intersecting both rectangles, without scaling,
    887 converting to dst.colorType() and dst.alphaType() if required.
    888 
    889 Pixels are readable when Surface is raster, or backed by a GPU.
    890 
    891 The destination pixel storage must be allocated by the caller.
    892 
    893 Pixel values are converted only if Color_Type and Alpha_Type
    894 do not match. Only pixels within both source and destination rectangles
    895 are copied. dst contents outside Rect intersection are unchanged.
    896 
    897 Pass negative values for srcX or srcY to offset pixels across or down destination.
    898 
    899 Does not copy, and returns false if:
    900 
    901 #List
    902 # Source and destination rectangles do not intersect. ##
    903 # Pixmap pixels could not be allocated. ##
    904 # dst.rowBytes() is too small to contain one row of pixels. ##
    905 ##
    906 
    907 #Param dst  storage for pixels copied from Surface ##
    908 #Param srcX  offset into readable pixels on x-axis; may be negative ##
    909 #Param srcY  offset into readable pixels on y-axis; may be negative ##
    910 
    911 #Return true if pixels were copied ##
    912 
    913 #Example
    914 #Height 32
    915     sk_sp<SkSurface> surf(SkSurface::MakeRasterN32Premul(64, 64));
    916     auto surfCanvas = surf->getCanvas();
    917     surfCanvas->clear(SK_ColorRED);
    918     SkPaint paint;
    919     paint.setTextSize(40);
    920     surfCanvas->drawString("&", 0, 32, paint);
    921     std::vector<SkPMColor> storage;
    922     storage.resize(surf->width() * surf->height());
    923     SkPixmap pixmap(SkImageInfo::MakeN32Premul(32, 32), &storage.front(),
    924                     surf->width() * sizeof(storage[0]));
    925     if (surf->readPixels(pixmap, 0, 0)) {
    926         SkBitmap surfBits;
    927         surfBits.installPixels(pixmap);
    928         canvas->drawBitmap(surfBits, 0, 0);
    929     }
    930 ##
    931 
    932 #SeeAlso peekPixels writePixels
    933 
    934 #Method ##
    935 
    936 # ------------------------------------------------------------------------------
    937 
    938 #Method bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
    939                     int srcX, int srcY)
    940 
    941 Copies Rect of pixels from Canvas into dstPixels.
    942 
    943 Source Rect corners are (srcX, srcY) and Surface (width(), height()).
    944 Destination Rect corners are (0, 0) and (dstInfo.width(), dstInfo.height()).
    945 Copies each readable pixel intersecting both rectangles, without scaling,
    946 converting to dstInfo.colorType() and dstInfo.alphaType() if required.
    947 
    948 Pixels are readable when Surface is raster, or backed by a GPU.
    949 
    950 The destination pixel storage must be allocated by the caller.
    951 
    952 Pixel values are converted only if Color_Type and Alpha_Type
    953 do not match. Only pixels within both source and destination rectangles
    954 are copied. dstPixels contents outside Rect intersection are unchanged.
    955 
    956 Pass negative values for srcX or srcY to offset pixels across or down destination.
    957 
    958 Does not copy, and returns false if:
    959 
    960 #List
    961 # Source and destination rectangles do not intersect. ##
    962 # Surface pixels could not be converted to dstInfo.colorType() or dstInfo.alphaType(). ##
    963 # dstRowBytes is too small to contain one row of pixels. ##
    964 ##
    965 
    966 #Param dstInfo  width, height, Color_Type, and Alpha_Type of dstPixels ##
    967 #Param dstPixels  storage for pixels; dstInfo.height() times dstRowBytes, or larger ##
    968 #Param dstRowBytes  size of one destination row; dstInfo.width() times pixel size, or larger ##
    969 #Param srcX  offset into readable pixels on x-axis; may be negative ##
    970 #Param srcY  offset into readable pixels on y-axis; may be negative ##
    971 
    972 #Return true if pixels were copied ##
    973 
    974 #Example
    975 #Height 64
    976 #Description
    977     A black oval drawn on a red background provides an image to copy.
    978     readPixels copies one quarter of the Surface into each of the four corners.
    979     The copied quarter ovals overdraw the original oval.
    980 ##
    981     sk_sp<SkSurface> surf(SkSurface::MakeRasterN32Premul(64, 64));
    982     auto surfCanvas = surf->getCanvas();
    983     surfCanvas->clear(SK_ColorRED);
    984     SkPaint paint;
    985     surfCanvas->drawOval({4, 8, 58, 54}, paint);
    986     SkImageInfo info = SkImageInfo::Make(64, 64, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
    987     sk_sp<SkData> data(SkData::MakeUninitialized(info.minRowBytes() * info.height()));
    988     sk_bzero(data->writable_data(), info.minRowBytes() * info.height());
    989     for (int x : { 32, -32 } ) {
    990         for (int y : { 32, -32 } ) {
    991             surf->readPixels(info, data->writable_data(), info.minRowBytes(), x, y);
    992         }
    993     }
    994     sk_sp<SkImage> image = SkImage::MakeRasterData(info, data, info.minRowBytes());
    995     canvas->drawImage(image, 0, 0);
    996 ##
    997 
    998 #SeeAlso peekPixels writePixels
    999 
   1000 #Method ##
   1001 
   1002 # ------------------------------------------------------------------------------
   1003 
   1004 #Method bool readPixels(const SkBitmap& dst, int srcX, int srcY)
   1005 
   1006 Copies Rect of pixels from Surface into bitmap.
   1007 
   1008 Source Rect corners are (srcX, srcY) and Surface (width(), height()).
   1009 Destination Rect corners are (0, 0) and (bitmap.width(), bitmap.height()).
   1010 Copies each readable pixel intersecting both rectangles, without scaling,
   1011 converting to dst.colorType() and dst.alphaType() if required.
   1012 
   1013 Pixels are readable when Surface is raster, or backed by a GPU.
   1014 
   1015 The destination pixel storage must be allocated by the caller.
   1016 
   1017 Pixel values are converted only if Color_Type and Alpha_Type
   1018 do not match. Only pixels within both source and destination rectangles
   1019 are copied. dst contents outside Rect intersection are unchanged.
   1020 
   1021 Pass negative values for srcX or srcY to offset pixels across or down destination.
   1022 
   1023 Does not copy, and returns false if:
   1024 
   1025 #List
   1026 # Source and destination rectangles do not intersect. ##
   1027 # Surface pixels could not be converted to dst.colorType() or dst.alphaType(). ##
   1028 # dst pixels could not be allocated. ##
   1029 # dst.rowBytes() is too small to contain one row of pixels. ##
   1030 ##
   1031 
   1032 #Param dst  storage for pixels copied from Surface ##
   1033 #Param srcX  offset into readable pixels on x-axis; may be negative ##
   1034 #Param srcY  offset into readable pixels on y-axis; may be negative ##
   1035 
   1036 #Return true if pixels were copied ##
   1037 
   1038 #Example
   1039     sk_sp<SkSurface> surf(SkSurface::MakeRasterN32Premul(64, 64));
   1040     auto surfCanvas = surf->getCanvas();
   1041     surfCanvas->clear(SK_ColorGREEN);
   1042     SkPaint paint;
   1043     surfCanvas->drawOval({2, 10, 58, 54}, paint);
   1044     SkImageInfo info = SkImageInfo::Make(64, 64, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
   1045     SkBitmap bitmap;
   1046     bitmap.setInfo(info);
   1047     bitmap.allocPixels();
   1048     for (int x : { 32, -32 } ) {
   1049         for (int y : { 32, -32 } ) {
   1050             surf->readPixels(bitmap, x, y);
   1051         }
   1052     }
   1053     canvas->drawBitmap(bitmap, 0, 0);
   1054 ##
   1055 
   1056 #SeeAlso peekPixels writePixels
   1057 
   1058 #Method ##
   1059 
   1060 # ------------------------------------------------------------------------------
   1061 
   1062 #Method void writePixels(const SkPixmap& src, int dstX, int dstY)
   1063 #In Pixels
   1064 #Line # copies Rect of pixels ##
   1065 Copies Rect of pixels from the src Pixmap to the Surface.
   1066 
   1067 Source Rect corners are (0, 0) and (src.width(), src.height()).
   1068 Destination Rect corners are (dstX, dstY) and
   1069 #Formula # (dstX + Surface width(), dstY + Surface height()) ##.
   1070 
   1071 Copies each readable pixel intersecting both rectangles, without scaling,
   1072 converting to Surface SkColorType and SkAlphaType if required.
   1073 
   1074 #Param src  storage for pixels to copy to Surface ##
   1075 #Param dstX x-axis position relative to Surface to begin copy; may be negative ##
   1076 #Param dstY y-axis position relative to Surface to begin copy; may be negative ##
   1077 
   1078 #Example
   1079 #Image 4
   1080 #Height 96
   1081     sk_sp<SkSurface> surf(SkSurface::MakeRasterN32Premul(64, 64));
   1082     auto surfCanvas = surf->getCanvas();
   1083     surfCanvas->clear(SK_ColorRED);
   1084     SkPaint paint;
   1085     paint.setTextSize(40);
   1086     surfCanvas->drawString("&", 16, 40, paint);
   1087     SkPixmap pixmap;
   1088     if (surf->peekPixels(&pixmap)) {
   1089         surf->writePixels(pixmap, 25, 25);
   1090         sk_sp<SkImage> image(surf->makeImageSnapshot());
   1091         canvas->drawImage(image, 0, 0);
   1092     }
   1093 ##
   1094 
   1095 #SeeAlso readPixels peekPixels
   1096 
   1097 #Method ##
   1098 
   1099 # ------------------------------------------------------------------------------
   1100 
   1101 #Method void writePixels(const SkBitmap& src, int dstX, int dstY)
   1102 
   1103 Copies Rect of pixels from the src Bitmap to the Surface.
   1104 
   1105 Source Rect corners are (0, 0) and (src.width(), src.height()).
   1106 Destination Rect corners are (dstX, dstY) and
   1107 #Formula # (dstX + Surface width(), dstY + Surface height()) ##.
   1108 
   1109 Copies each readable pixel intersecting both rectangles, without scaling,
   1110 converting to Surface SkColorType and SkAlphaType if required.
   1111 
   1112 #Param src  storage for pixels to copy to Surface ##
   1113 #Param dstX x-axis position relative to Surface to begin copy; may be negative ##
   1114 #Param dstY y-axis position relative to Surface to begin copy; may be negative ##
   1115 
   1116 #Example
   1117 #Image 4
   1118 #Height 96
   1119     sk_sp<SkSurface> surf(SkSurface::MakeRasterN32Premul(64, 64));
   1120     auto surfCanvas = surf->getCanvas();
   1121     surfCanvas->clear(SK_ColorGREEN);
   1122     surf->writePixels(source, 25, 25);
   1123     sk_sp<SkImage> image(surf->makeImageSnapshot());
   1124     canvas->drawImage(image, 0, 0);
   1125 ##
   1126 
   1127 #SeeAlso readPixels peekPixels
   1128 
   1129 #Method ##
   1130 
   1131 # ------------------------------------------------------------------------------
   1132 
   1133 #Method const SkSurfaceProps& props() const
   1134 #In Property
   1135 #Line # returns Surface_Properties ##
   1136 #Populate
   1137 
   1138 #Example
   1139     const char* names[] = { "Unknown", "RGB_H", "BGR_H", "RGB_V", "BGR_V" };
   1140     sk_sp<SkSurface> surf(SkSurface::MakeRasterN32Premul(64, 64));
   1141     SkDebugf("surf.props(): k%s_SkPixelGeometry\n", names[surf->props().pixelGeometry()]);
   1142 #StdOut
   1143 surf.props(): kRGB_H_SkPixelGeometry
   1144 ##
   1145 ##
   1146 
   1147 #SeeAlso SkSurfaceProps
   1148 
   1149 #Method ##
   1150 
   1151 # ------------------------------------------------------------------------------
   1152 #Subtopic Utility
   1153 #Line # rarely called management functions ##
   1154 ##
   1155 
   1156 #Method void flush()
   1157 #In Utility
   1158 #Line # resolves pending I/O ##
   1159 #Populate
   1160 
   1161 #NoExample
   1162 ##
   1163 
   1164 #SeeAlso GrBackendSemaphore
   1165 
   1166 #Method ##
   1167 
   1168 # ------------------------------------------------------------------------------
   1169 
   1170 #Method GrSemaphoresSubmitted flushAndSignalSemaphores(int numSemaphores,
   1171                                                    GrBackendSemaphore signalSemaphores[])
   1172 #In Utility
   1173 #Line # resolves pending I/O, and signal ##
   1174 #Populate
   1175 
   1176 #NoExample
   1177 ##
   1178 
   1179 #SeeAlso wait GrBackendSemaphore
   1180 
   1181 #Method ##
   1182 
   1183 # ------------------------------------------------------------------------------
   1184 
   1185 #Method bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores)
   1186 #In Utility
   1187 #Line # pauses commands until signaled ##
   1188 #Populate
   1189 
   1190 #NoExample
   1191 #ToDo this is copy and paste silliness masquerading as an example. Probably need gpu
   1192       globals and definitely need gpu expertise to make a real example out of this
   1193       also, note need to replace GrBackendObject with GrBackendTexture
   1194  ##
   1195 #Platform gpu
   1196 #Height 64
   1197     SkPaint paint;
   1198     paint.setTextSize(32);
   1199     GrContext* context = canvas->getGrContext();
   1200     if (!context) {
   1201          canvas->drawString("GPU only!", 20, 40, paint);
   1202          return;
   1203     }
   1204     GrBackendSemaphore semaphore;
   1205     sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(
   1206             context, SkBudgeted::kYes, SkImageInfo::MakeN32Premul(64, 64));
   1207     surface->flushAndSignalSemaphores(1, &semaphore);
   1208     sk_sp<SkImage> image = surface->makeImageSnapshot();
   1209     GrBackendTexture backendTex = image->getBackendTexture(false); // unused
   1210     SkASSERT(backendTex.isValid());
   1211     const SkImageInfo childImageInfo = SkImageInfo::Make(64, 64,
   1212               kRGBA_8888_SkColorType, kPremul_SkAlphaType);
   1213     sk_sp<SkSurface> childSurface(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo,
   1214               childImageInfo, 0, kTopLeft_GrSurfaceOrigin, nullptr));
   1215     GrBackendTexture backendTexture;
   1216     sk_sp<SkImage> childImage = SkImage::MakeFromTexture(context,
   1217               backendTexture,   // undefined
   1218               kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, nullptr);
   1219     SkCanvas* childCanvas = childSurface->getCanvas();
   1220     childCanvas->clear(SK_ColorRED);
   1221     childSurface->wait(1, &semaphore);
   1222     childCanvas->drawImage(childImage, 32, 0);
   1223     childSurface->draw(canvas, 0, 0, nullptr);
   1224 ##
   1225 
   1226 #SeeAlso flushAndSignalSemaphores GrBackendSemaphore
   1227 
   1228 #Method ##
   1229 
   1230 # ------------------------------------------------------------------------------
   1231 
   1232 #Method bool characterize(SkSurfaceCharacterization* characterization) const
   1233 #In Utility
   1234 #Line # sets Surface_Characterization for threaded GPU processing ##
   1235 #Populate
   1236 
   1237 #Example
   1238 #Platform gpu
   1239 #Height 64
   1240     SkPaint paint;
   1241     paint.setTextSize(32);
   1242     GrContext* context = canvas->getGrContext();
   1243     if (!context) {
   1244          canvas->drawString("GPU only!", 20, 40, paint);
   1245          return;
   1246     }
   1247     sk_sp<SkSurface> gpuSurface = SkSurface::MakeRenderTarget(
   1248             context, SkBudgeted::kYes, SkImageInfo::MakeN32Premul(64, 64));
   1249     SkSurfaceCharacterization characterization;
   1250     if (!gpuSurface->characterize(&characterization)) {
   1251          canvas->drawString("characterization unsupported", 20, 40, paint);
   1252          return;
   1253     }
   1254     // start of threadable work
   1255     SkDeferredDisplayListRecorder recorder(characterization);
   1256     SkCanvas* subCanvas = recorder.getCanvas();
   1257     subCanvas->clear(SK_ColorGREEN);
   1258     std::unique_ptr<SkDeferredDisplayList> displayList = recorder.detach();
   1259     // end of threadable work
   1260     gpuSurface->draw(displayList.get());
   1261     sk_sp<SkImage> img = gpuSurface->makeImageSnapshot();
   1262     canvas->drawImage(std::move(img), 0, 0);
   1263 ##
   1264 
   1265 #SeeAlso draw() SkSurfaceCharacterization SkDeferredDisplayList
   1266 
   1267 #Method ##
   1268 
   1269 # ------------------------------------------------------------------------------
   1270 
   1271 #Method bool draw(SkDeferredDisplayList* deferredDisplayList)
   1272 #Populate
   1273 
   1274 #Example
   1275 #Height 64
   1276 #Platform gpu cpu
   1277     SkPaint paint;
   1278     paint.setTextSize(16);
   1279     sk_sp<SkSurface> gpuSurface = SkSurface::MakeRasterN32Premul(64, 64);
   1280     SkSurfaceCharacterization characterization;
   1281     if (!gpuSurface->characterize(&characterization)) {
   1282          canvas->drawString("characterization unsupported", 20, 40, paint);
   1283          return;
   1284     }
   1285     // start of threadable work
   1286     SkDeferredDisplayListRecorder recorder(characterization);
   1287     SkCanvas* subCanvas = recorder.getCanvas();
   1288     subCanvas->clear(SK_ColorGREEN);
   1289     std::unique_ptr<SkDeferredDisplayList> displayList = recorder.detach();
   1290     // end of threadable work
   1291     gpuSurface->draw(displayList.get());
   1292     sk_sp<SkImage> img = gpuSurface->makeImageSnapshot();
   1293     canvas->drawImage(std::move(img), 0, 0);
   1294 ##
   1295 
   1296 #SeeAlso characterize() SkSurfaceCharacterization SkDeferredDisplayList
   1297 
   1298 #Method ##
   1299 
   1300 #Class SkSurface ##
   1301 
   1302 #Topic Surface ##
   1303