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