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