#Topic Surface #Alias Surface_Reference ## #Class SkSurface #Code #Populate ## SkSurface is responsible for managing the pixels that a canvas draws into. The pixels can be allocated either in CPU memory, if a raster surface; or on the GPU, for a GrRenderTarget surface. SkSurface takes care of allocating a SkCanvas that will draw into the surface. Call surface->getCanvas() to use that canvas. The caller should not delete the returned canvas; it is owned by surface. SkSurface always has non-zero dimensions. If there is a request for a new surface, and either of the requested dimensions are zero, then nullptr will be returned. # ------------------------------------------------------------------------------ #Typedef void* ReleaseContext #Line # context for release procs ## ## #Typedef void (*RenderTargetReleaseProc)(ReleaseContext releaseContext) #Line # context for release procs ## ## #Typedef void (*TextureReleaseProc)(ReleaseContext releaseContext) #Line # context for release procs ## ## #Method static sk_sp MakeRasterDirect(const SkImageInfo& imageInfo, void* pixels, size_t rowBytes, const SkSurfaceProps* surfaceProps = nullptr) #In Constructors #Line # creates Surface from SkImageInfo and Pixel_Storage ## #Populate #Example void draw(SkCanvas* ) { SkImageInfo info = SkImageInfo::MakeN32Premul(3, 3); const size_t size = info.computeMinByteSize(); SkAutoTMalloc storage(size); SkPMColor* pixels = storage.get(); sk_sp surface(SkSurface::MakeRasterDirect(info, pixels, info.minRowBytes())); SkCanvas* canvas = surface->getCanvas(); canvas->clear(SK_ColorWHITE); SkPMColor pmWhite = pixels[0]; SkPaint paint; canvas->drawPoint(1, 1, paint); canvas->flush(); // ensure that point was drawn for (int y = 0; y < info.height(); ++y) { for (int x = 0; x < info.width(); ++x) { SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x'); } SkDebugf("\n"); } } #StdOut --- -x- --- ## ## #SeeAlso MakeRasterDirectReleaseProc MakeRaster MakeRasterN32Premul SkCanvas::MakeRasterDirect #Method ## # ------------------------------------------------------------------------------ #Method static sk_sp MakeRasterDirectReleaseProc(const SkImageInfo& imageInfo, void* pixels, size_t rowBytes, void (*releaseProc)(void* pixels, void* context), void* context, const SkSurfaceProps* surfaceProps = nullptr) #In Constructors #Line # creates Surface from SkImageInfo and Pixel_Storage ## #Populate #Example #Function static void release_direct_surface_storage(void* pixels, void* context) { if (pixels == context) { SkDebugf("expected release context\n"); } sk_free(pixels); } ## void draw(SkCanvas* ) { SkImageInfo info = SkImageInfo::MakeN32Premul(3, 3); const size_t rowBytes = info.minRowBytes(); void* pixels = sk_malloc_throw(info.computeByteSize(rowBytes)); sk_sp surface(SkSurface::MakeRasterDirectReleaseProc(info, pixels, rowBytes, release_direct_surface_storage, pixels)); SkCanvas* canvas = surface->getCanvas(); canvas->clear(SK_ColorWHITE); SkPMColor* colorPtr = (SkPMColor*) pixels; SkPMColor pmWhite = colorPtr[0]; SkPaint paint; canvas->drawPoint(1, 1, paint); canvas->flush(); // ensure that point was drawn for (int y = 0; y < info.height(); ++y) { for (int x = 0; x < info.width(); ++x) { SkDebugf("%c", *colorPtr++ == pmWhite ? '-' : 'x'); } SkDebugf("\n"); } } #StdOut --- -x- --- expected release context ## ## #SeeAlso MakeRasterDirect MakeRasterN32Premul MakeRaster #Method ## # ------------------------------------------------------------------------------ #Method static sk_sp MakeRaster(const SkImageInfo& imageInfo, size_t rowBytes, const SkSurfaceProps* surfaceProps) #In Constructors #Line # creates Surface from SkImageInfo ## #Populate #Example void draw(SkCanvas* ) { SkImageInfo info = SkImageInfo::MakeN32Premul(3, 3); const size_t rowBytes = 64; sk_sp surface(SkSurface::MakeRaster(info, rowBytes, nullptr)); SkCanvas* canvas = surface->getCanvas(); canvas->clear(SK_ColorWHITE); SkPixmap pixmap; if (surface->peekPixels(&pixmap)) { const uint32_t* colorPtr = pixmap.addr32(); SkPMColor pmWhite = colorPtr[0]; SkPaint paint; canvas->drawPoint(1, 1, paint); canvas->flush(); // ensure that point was drawn for (int y = 0; y < info.height(); ++y) { for (int x = 0; x < info.width(); ++x) { SkDebugf("%c", colorPtr[x] == pmWhite ? '-' : 'x'); } colorPtr += rowBytes / sizeof(colorPtr[0]); SkDebugf("\n"); } } } #StdOut --- -x- --- ## ## #SeeAlso MakeRasterDirect MakeRasterN32Premul MakeRasterDirectReleaseProc #Method ## # ------------------------------------------------------------------------------ #Method static sk_sp MakeRaster(const SkImageInfo& imageInfo, const SkSurfaceProps* props = nullptr) #Populate #Example void draw(SkCanvas* ) { SkImageInfo info = SkImageInfo::MakeN32Premul(3, 3); sk_sp surface(SkSurface::MakeRaster(info)); SkCanvas* canvas = surface->getCanvas(); canvas->clear(SK_ColorWHITE); SkPixmap pixmap; if (surface->peekPixels(&pixmap)) { const uint32_t* colorPtr = pixmap.addr32(); SkPMColor pmWhite = colorPtr[0]; SkPaint paint; canvas->drawPoint(1, 1, paint); canvas->flush(); // ensure that point was drawn for (int y = 0; y < info.height(); ++y) { for (int x = 0; x < info.width(); ++x) { SkDebugf("%c", colorPtr[x] == pmWhite ? '-' : 'x'); } colorPtr += info.width(); SkDebugf("\n"); } } } ## #SeeAlso MakeRasterDirect MakeRasterN32Premul MakeRasterDirectReleaseProc #Method ## # ------------------------------------------------------------------------------ #Method static sk_sp MakeRasterN32Premul(int width, int height, const SkSurfaceProps* surfaceProps = nullptr) #In Constructors #Line # creates Surface from width, height matching output ## #Populate #Example void draw(SkCanvas* ) { sk_sp surface(SkSurface::MakeRasterN32Premul(3, 3)); SkCanvas* canvas = surface->getCanvas(); canvas->clear(SK_ColorWHITE); SkPixmap pixmap; if (surface->peekPixels(&pixmap)) { const uint32_t* colorPtr = pixmap.addr32(); SkPMColor pmWhite = colorPtr[0]; SkPaint paint; canvas->drawPoint(1, 1, paint); canvas->flush(); // ensure that point was drawn for (int y = 0; y < surface->height(); ++y) { for (int x = 0; x < surface->width(); ++x) { SkDebugf("%c", colorPtr[x] == pmWhite ? '-' : 'x'); } colorPtr += surface->width(); SkDebugf("\n"); } } } #StdOut --- -x- --- ## ## #SeeAlso MakeRasterDirect MakeRasterN32Premul MakeRasterDirectReleaseProc #Method ## # ------------------------------------------------------------------------------ #Method static sk_sp MakeFromBackendTexture(GrContext* context, const GrBackendTexture& backendTexture, GrSurfaceOrigin origin, int sampleCnt, SkColorType colorType, sk_sp colorSpace, const SkSurfaceProps* surfaceProps, TextureReleaseProc textureReleaseProc = nullptr, ReleaseContext releaseContext = nullptr) #In Constructors #Line # creates Surface from GPU texture ## #Populate #Example #Platform gpu cpu #Image 3 SkPaint paint; paint.setTextSize(32); GrContext* context = canvas->getGrContext(); if (!context) { canvas->drawString("GPU only!", 20, 40, paint); return; } sk_sp gpuSurface = SkSurface::MakeFromBackendTexture(context, backEndTexture, kTopLeft_GrSurfaceOrigin, 0, kRGBA_8888_SkColorType, nullptr, nullptr); auto surfaceCanvas = gpuSurface->getCanvas(); surfaceCanvas->drawString("GPU rocks!", 20, 40, paint); sk_sp image(gpuSurface->makeImageSnapshot()); canvas->drawImage(image, 0, 0); ## #SeeAlso GrBackendTexture MakeFromBackendRenderTarget MakeRenderTarget #Method ## # ------------------------------------------------------------------------------ #Method static sk_sp MakeFromBackendRenderTarget(GrContext* context, const GrBackendRenderTarget& backendRenderTarget, GrSurfaceOrigin origin, SkColorType colorType, sk_sp colorSpace, const SkSurfaceProps* surfaceProps, RenderTargetReleaseProc releaseProc = nullptr, ReleaseContext releaseContext = nullptr) #In Constructors #Line # creates Surface from GPU render target ## #Populate #Example #ToDo remove !fiddle below once backEndTextureRenderTarget is available ## #Platform !fiddle gpu SkPaint paint; paint.setTextSize(32); GrContext* context = canvas->getGrContext(); if (!context) { canvas->drawString("GPU only!", 20, 40, paint); return; } sk_sp gpuSurface = SkSurface::MakeFromBackendRenderTarget(context, backEndRenderTarget, kTopLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType, nullptr, nullptr); auto surfaceCanvas = gpuSurface->getCanvas(); surfaceCanvas->drawString("GPU rocks!", 20, 40, paint); sk_sp image(gpuSurface->makeImageSnapshot()); canvas->drawImage(image, 0, 0); ## #SeeAlso MakeFromBackendTexture MakeRenderTarget #Method ## # ------------------------------------------------------------------------------ #Method static sk_sp MakeFromBackendTextureAsRenderTarget(GrContext* context, const GrBackendTexture& backendTexture, GrSurfaceOrigin origin, int sampleCnt, SkColorType colorType, sk_sp colorSpace, const SkSurfaceProps* surfaceProps) #In Constructors #Line # creates Surface from GPU back-end render target ## #Populate #Example #ToDo example is bogus; gpuSurface should not make image ## #Platform gpu #Image 3 SkPaint paint; paint.setTextSize(32); GrContext* context = canvas->getGrContext(); if (!context) { canvas->drawString("GPU only!", 20, 40, paint); return; } sk_sp gpuSurface = SkSurface::MakeFromBackendTextureAsRenderTarget( context, backEndTexture, kTopLeft_GrSurfaceOrigin, 0, kRGBA_8888_SkColorType, nullptr, nullptr); auto surfaceCanvas = gpuSurface->getCanvas(); surfaceCanvas->drawString("GPU rocks!", 20, 40, paint); sk_sp image(gpuSurface->makeImageSnapshot()); canvas->drawImage(image, 0, 0); ## #SeeAlso MakeFromBackendRenderTarget MakeRenderTarget #Method ## # ------------------------------------------------------------------------------ #Method static sk_sp MakeRenderTarget(GrContext* context, SkBudgeted budgeted, const SkImageInfo& imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps* surfaceProps, bool shouldCreateWithMips = false) #In Constructors #Line # creates Surface pointing to new GPU memory buffer ## #Populate #Example #Platform gpu #Height 64 SkPaint paint; paint.setTextSize(32); GrContext* context = canvas->getGrContext(); if (!context) { canvas->drawString("GPU only!", 20, 40, paint); return; } SkImageInfo info = SkImageInfo::MakeN32(256, 64, kOpaque_SkAlphaType); for (auto surfaceOrigin : { kTopLeft_GrSurfaceOrigin, kBottomLeft_GrSurfaceOrigin } ) { auto gpuSurface(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info, 0, surfaceOrigin, nullptr)); auto surfaceCanvas = gpuSurface->getCanvas(); surfaceCanvas->clear(SK_ColorWHITE); surfaceCanvas->drawString("GPU rocks!", 20, 40, paint); sk_sp image(gpuSurface->makeImageSnapshot()); canvas->drawImage(image, 0, 0); canvas->translate(0, 128); } ## #SeeAlso MakeFromBackendRenderTarget MakeFromBackendTextureAsRenderTarget #Method ## # ------------------------------------------------------------------------------ #Method static sk_sp MakeRenderTarget(GrContext* context, SkBudgeted budgeted, const SkImageInfo& imageInfo, int sampleCount, const SkSurfaceProps* props) #Populate #Example #Platform cpu gpu #Description LCD text takes advantage of raster striping to improve resolution. Only one of the four combinations is correct, depending on whether monitor LCD striping is horizontal or vertical, and whether the order of the stripes is red blue green or red green blue. ## void draw(SkCanvas* canvas) { auto test_draw = [](SkCanvas* surfaceCanvas) -> void { SkPaint paint; paint.setAntiAlias(true); paint.setLCDRenderText(true); paint.setColor(0xFFBBBBBB); surfaceCanvas->drawRect(SkRect::MakeWH(128, 64), paint); paint.setColor(SK_ColorWHITE); paint.setTextSize(32); surfaceCanvas->drawString("Pest", 0, 25, paint); }; GrContext* context = canvas->getGrContext(); SkImageInfo info = SkImageInfo::MakeN32(128, 64, kOpaque_SkAlphaType); int y = 0; for (auto geometry : { kRGB_H_SkPixelGeometry, kBGR_H_SkPixelGeometry, kRGB_V_SkPixelGeometry, kBGR_V_SkPixelGeometry } ) { SkSurfaceProps props(0, geometry); sk_sp surface = context ? SkSurface::MakeRenderTarget( context, SkBudgeted::kNo, info, 0, &props) : SkSurface::MakeRaster(info, &props); test_draw(surface->getCanvas()); surface->draw(canvas, 0, y, nullptr); sk_sp image(surface->makeImageSnapshot()); SkAutoCanvasRestore acr(canvas, true); canvas->scale(8, 8); canvas->drawImage(image, 12, y / 8); y += 64; } } ## #SeeAlso MakeFromBackendRenderTarget MakeFromBackendTextureAsRenderTarget #Method ## # ------------------------------------------------------------------------------ #Method static sk_sp MakeRenderTarget(GrContext* context, SkBudgeted budgeted, const SkImageInfo& imageInfo) #Populate #Example #Platform gpu SkPaint paint; paint.setTextSize(32); GrContext* context = canvas->getGrContext(); if (!context) { canvas->drawString("GPU only!", 20, 40, paint); return; } SkImageInfo info = SkImageInfo::MakeN32(256, 64, kOpaque_SkAlphaType); auto gpuSurface(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info)); auto surfaceCanvas = gpuSurface->getCanvas(); surfaceCanvas->clear(SK_ColorWHITE); surfaceCanvas->drawString("GPU rocks!", 20, 40, paint); sk_sp image(gpuSurface->makeImageSnapshot()); canvas->drawImage(image, 0, 0); ## #SeeAlso MakeFromBackendRenderTarget MakeFromBackendTextureAsRenderTarget #Method ## # ------------------------------------------------------------------------------ #Method static sk_sp MakeRenderTarget(GrRecordingContext* context, const SkSurfaceCharacterization& characterization, SkBudgeted budgeted) #Populate #NoExample ## #SeeAlso MakeFromBackendRenderTarget MakeFromBackendTextureAsRenderTarget #Method ## # ------------------------------------------------------------------------------ #Method static sk_sp MakeNull(int width, int height) #In Constructors #Line # creates Surface without backing pixels ## #Populate #Example SkDebugf("SkSurface::MakeNull(0, 0) %c= nullptr\n", SkSurface::MakeNull(0, 0) == nullptr ? '=' : '!'); const int w = 37; const int h = 1000; auto surf = SkSurface::MakeNull(w, h); auto nullCanvas = surf->getCanvas(); nullCanvas->drawPaint(SkPaint()); // does not crash, nothing draws SkDebugf("surf->makeImageSnapshot() %c= nullptr\n", surf->makeImageSnapshot() == nullptr ? '=' : '!'); #StdOut SkSurface::MakeNull(0, 0) == nullptr surf->makeImageSnapshot() == nullptr ## ## #SeeAlso MakeRaster MakeRenderTarget #Method ## # ------------------------------------------------------------------------------ #Subtopic Property #Line # member values ## ## #Method int width() const #In Property #Line # returns pixel column count ## #Populate #Example const int width = 37; const int height = 1000; auto surf = SkSurface::MakeNull(width, height); auto nullCanvas = surf->getCanvas(); SkDebugf("surface width=%d canvas width=%d\n", surf->width(), nullCanvas->getBaseLayerSize().fWidth); #StdOut surface width=37 canvas width=37 ## ## #SeeAlso height() #Method ## # ------------------------------------------------------------------------------ #Method int height() const #In Property #Line # returns pixel row count ## #Populate #Example const int width = 37; const int height = 1000; auto surf = SkSurface::MakeNull(width, height); auto nullCanvas = surf->getCanvas(); SkDebugf("surface height=%d canvas height=%d\n", surf->height(), nullCanvas->getBaseLayerSize().fHeight); #StdOut surface height=1000 canvas height=1000 ## ## #SeeAlso width() #Method ## # ------------------------------------------------------------------------------ #Method uint32_t generationID() #In Property #Line # returns unique ID ## #Populate #Example auto surface = SkSurface::MakeRasterN32Premul(1, 1); for (int i = 0; i < 3; ++i) { SkDebugf("surface generationID: %d\n", surface->generationID()); if (0 == i) { surface->getCanvas()->drawColor(SK_ColorBLACK); } else { surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode); } } #StdOut surface generationID: 1 surface generationID: 2 surface generationID: 3 ## ## #SeeAlso notifyContentWillChange ContentChangeMode getCanvas #Method ## # ------------------------------------------------------------------------------ #Enum ContentChangeMode #Line # parameter options for notifyContentWillChange ## #Code enum ContentChangeMode { kDiscard_ContentChangeMode, kRetain_ContentChangeMode, }; ## ContentChangeMode members are parameters to notifyContentWillChange. #Const kDiscard_ContentChangeMode #Line # discards surface on change ## Pass to notifyContentWillChange to discard surface contents when the surface is cleared or overwritten. ## #Const kRetain_ContentChangeMode #Line # preserves surface on change ## Pass to notifyContentWillChange when to preserve surface contents. If a snapshot has been generated, this copies the Surface contents. ## #SeeAlso notifyContentWillChange generationID #Enum ## # ------------------------------------------------------------------------------ #ToDo not crazy about misc catagory -- hopefully will become clear with time ## #Subtopic Miscellaneous #Line # other functions ## ## #Method void notifyContentWillChange(ContentChangeMode mode) #In Miscellaneous #Line # notifies that contents will be changed outside of Skia ## #Populate #Example auto surface = SkSurface::MakeRasterN32Premul(1, 1); for (int i = 0; i < 3; ++i) { SkDebugf("surface generationID: %d\n", surface->generationID()); if (0 == i) { surface->getCanvas()->drawColor(SK_ColorBLACK); } else { surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode); } } ## #SeeAlso ContentChangeMode generationID #Method ## # ------------------------------------------------------------------------------ #Enum BackendHandleAccess #Line # options to read and write back-end object ## #Code enum BackendHandleAccess { kFlushRead_BackendHandleAccess, kFlushWrite_BackendHandleAccess, kDiscardWrite_BackendHandleAccess, }; static const BackendHandleAccess kFlushRead_TextureHandleAccess = kFlushRead_BackendHandleAccess; static const BackendHandleAccess kFlushWrite_TextureHandleAccess = kFlushWrite_BackendHandleAccess; static const BackendHandleAccess kDiscardWrite_TextureHandleAccess = kDiscardWrite_BackendHandleAccess; ## #Const kFlushRead_BackendHandleAccess 0 #Line # back-end object is readable ## Caller may read from the back-end object. ## #Const kFlushWrite_BackendHandleAccess 1 #Line # back-end object is writable ## Caller may write to the back-end object. ## #Const kDiscardWrite_BackendHandleAccess 2 #Line # back-end object must be overwritten ## Caller must overwrite the entire back-end object. ## #NoExample // todo: need to update example to use GrBackendTexture instead of GrBackendObject #Platform gpu SkPaint paint; paint.setTextSize(32); GrContext* context = canvas->getGrContext(); if (!context) { canvas->drawString("GPU only!", 20, 40, paint); return; } sk_sp gpuSurface = SkSurface::MakeRenderTarget( context, SkBudgeted::kYes, SkImageInfo::MakeN32Premul(10, 10)); int y = 20; SkString str; paint.setTextSize(16); for (auto access : { SkSurface::kFlushRead_BackendHandleAccess, SkSurface::kFlushWrite_BackendHandleAccess, SkSurface::kDiscardWrite_BackendHandleAccess } ) { sk_sp image(gpuSurface->makeImageSnapshot()); str.printf("uniqueID=%d", image->uniqueID()); canvas->drawString(str, 20, y += 20, paint); GrBackendTexture backendTex = gpuSurface->getBackendTexture(access); str.printf("backendTex is %svalid", backendTex.isValid() ? '' : 'not '); canvas->drawString(str, 20, y += 20, paint); } sk_sp image(gpuSurface->makeImageSnapshot()); str.printf("final image uniqueID=%d", image->uniqueID()); canvas->drawString(str, 20, y += 20, paint); ## #SeeAlso getBackendTexture getBackendRenderTarget #Enum ## # ------------------------------------------------------------------------------ #Method GrBackendTexture getBackendTexture(BackendHandleAccess backendHandleAccess) #In Property #Line # returns the GPU reference to texture ## #Populate #NoExample ## #SeeAlso GrBackendTexture BackendHandleAccess getBackendRenderTarget #Method ## # ------------------------------------------------------------------------------ #Method GrBackendRenderTarget getBackendRenderTarget(BackendHandleAccess backendHandleAccess) #In Property #Line # returns the GPU reference to render target ## #Populate #NoExample ## #SeeAlso GrBackendRenderTarget BackendHandleAccess getBackendTexture #Method ## # ------------------------------------------------------------------------------ #Method SkCanvas* getCanvas() #In Property #Line # returns Canvas that draws into Surface ## #Populate #Example #Height 64 sk_sp surface(SkSurface::MakeRasterN32Premul(64, 64)); SkCanvas* surfaceCanvas = surface->getCanvas(); surfaceCanvas->clear(SK_ColorBLUE); SkPaint paint; paint.setTextSize(40); surfaceCanvas->drawString("\xF0\x9F\x98\x81", 12, 45, paint); surface->draw(canvas, 0, 0, nullptr); ## #SeeAlso makeSurface makeImageSnapshot draw #Method ## # ------------------------------------------------------------------------------ #Method sk_sp makeSurface(const SkImageInfo& imageInfo) #In Constructors #Line # creates a compatible Surface ## #Populate #Example #Height 96 sk_sp big(SkSurface::MakeRasterN32Premul(64, 64)); sk_sp lil(big->makeSurface(SkImageInfo::MakeN32(32, 32, kPremul_SkAlphaType))); big->getCanvas()->clear(SK_ColorRED); lil->getCanvas()->clear(SK_ColorBLACK); SkPixmap pixmap; if (big->peekPixels(&pixmap)) { SkBitmap bigBits; bigBits.installPixels(pixmap); canvas->drawBitmap(bigBits, 0, 0); } if (lil->peekPixels(&pixmap)) { SkBitmap lilBits; lilBits.installPixels(pixmap); canvas->drawBitmap(lilBits, 64, 64); } ## #SeeAlso makeImageSnapshot getCanvas draw #Method ## # ------------------------------------------------------------------------------ #Method sk_sp makeImageSnapshot() #In Constructors #Line # creates Image capturing Surface contents ## #Populate #Example #Height 64 sk_sp big(SkSurface::MakeRasterN32Premul(64, 64)); sk_sp lil(big->makeSurface(SkImageInfo::MakeN32(32, 32, kPremul_SkAlphaType))); big->getCanvas()->clear(SK_ColorRED); lil->getCanvas()->clear(SK_ColorBLACK); sk_sp early(big->makeImageSnapshot()); lil->draw(big->getCanvas(), 16, 16, nullptr); sk_sp later(big->makeImageSnapshot()); canvas->drawImage(early, 0, 0); canvas->drawImage(later, 128, 0); ## #SeeAlso draw getCanvas #Method ## # ------------------------------------------------------------------------------ #Method sk_sp makeImageSnapshot(const SkIRect& bounds) #In Constructors #Line # creates Image capturing subset of Surface contents ## #Populate #Example #Height 64 sk_sp big(SkSurface::MakeRasterN32Premul(64, 64)); sk_sp lil(big->makeSurface(SkImageInfo::MakeN32(32, 32, kPremul_SkAlphaType))); big->getCanvas()->clear(SK_ColorRED); lil->getCanvas()->clear(SK_ColorBLACK); sk_sp early(big->makeImageSnapshot()); lil->draw(big->getCanvas(), 16, 16, nullptr); sk_sp later(big->makeImageSnapshot({0, 0, 16, 16})); canvas->drawImage(early, 0, 0); canvas->drawImage(later, 0, 0); ## #SeeAlso draw getCanvas #Method ## # ------------------------------------------------------------------------------ #Subtopic Pixels #Line # functions with pixel access ## ## #Method void draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) #In Pixels #Line # draws Surface contents to canvas ## #Populate #Example #Height 64 sk_sp big(SkSurface::MakeRasterN32Premul(64, 64)); sk_sp lil(big->makeSurface(SkImageInfo::MakeN32(32, 32, kPremul_SkAlphaType))); big->getCanvas()->clear(SK_ColorRED); lil->getCanvas()->clear(SK_ColorBLACK); lil->draw(big->getCanvas(), 16, 16, nullptr); SkPixmap pixmap; if (big->peekPixels(&pixmap)) { SkBitmap bigBits; bigBits.installPixels(pixmap); canvas->drawBitmap(bigBits, 0, 0); } ## #SeeAlso makeImageSnapshot getCanvas #Method ## # ------------------------------------------------------------------------------ #Method bool peekPixels(SkPixmap* pixmap) #In Pixels #Line # copies Surface parameters to Pixmap ## #Populate #Example #Height 64 sk_sp surf(SkSurface::MakeRasterN32Premul(64, 64)); auto surfCanvas = surf->getCanvas(); surfCanvas->clear(SK_ColorRED); SkPaint paint; paint.setTextSize(40); surfCanvas->drawString("&", 16, 48, paint); SkPixmap pixmap; if (surf->peekPixels(&pixmap)) { SkBitmap surfBits; surfBits.installPixels(pixmap); canvas->drawBitmap(surfBits, 0, 0); } ## #SeeAlso readPixels writePixels #Method ## # ------------------------------------------------------------------------------ #Method bool readPixels(const SkPixmap& dst, int srcX, int srcY) #In Pixels #Line # copies Rect of pixels ## Copies Rect of pixels to dst. Source Rect corners are (srcX, srcY) and Surface (width(), height()). Destination Rect corners are (0, 0) and (dst.width(), dst.height()). Copies each readable pixel intersecting both rectangles, without scaling, converting to dst.colorType() and dst.alphaType() if required. Pixels are readable when Surface is raster, or backed by a GPU. The destination pixel storage must be allocated by the caller. Pixel values are converted only if Color_Type and Alpha_Type do not match. Only pixels within both source and destination rectangles are copied. dst contents outside Rect intersection are unchanged. Pass negative values for srcX or srcY to offset pixels across or down destination. Does not copy, and returns false if: #List # Source and destination rectangles do not intersect. ## # Pixmap pixels could not be allocated. ## # dst.rowBytes() is too small to contain one row of pixels. ## ## #Param dst storage for pixels copied from Surface ## #Param srcX offset into readable pixels on x-axis; may be negative ## #Param srcY offset into readable pixels on y-axis; may be negative ## #Return true if pixels were copied ## #Example #Height 32 sk_sp surf(SkSurface::MakeRasterN32Premul(64, 64)); auto surfCanvas = surf->getCanvas(); surfCanvas->clear(SK_ColorRED); SkPaint paint; paint.setTextSize(40); surfCanvas->drawString("&", 0, 32, paint); std::vector storage; storage.resize(surf->width() * surf->height()); SkPixmap pixmap(SkImageInfo::MakeN32Premul(32, 32), &storage.front(), surf->width() * sizeof(storage[0])); if (surf->readPixels(pixmap, 0, 0)) { SkBitmap surfBits; surfBits.installPixels(pixmap); canvas->drawBitmap(surfBits, 0, 0); } ## #SeeAlso peekPixels writePixels #Method ## # ------------------------------------------------------------------------------ #Method bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, int srcX, int srcY) Copies Rect of pixels from Canvas into dstPixels. Source Rect corners are (srcX, srcY) and Surface (width(), height()). Destination Rect corners are (0, 0) and (dstInfo.width(), dstInfo.height()). Copies each readable pixel intersecting both rectangles, without scaling, converting to dstInfo.colorType() and dstInfo.alphaType() if required. Pixels are readable when Surface is raster, or backed by a GPU. The destination pixel storage must be allocated by the caller. Pixel values are converted only if Color_Type and Alpha_Type do not match. Only pixels within both source and destination rectangles are copied. dstPixels contents outside Rect intersection are unchanged. Pass negative values for srcX or srcY to offset pixels across or down destination. Does not copy, and returns false if: #List # Source and destination rectangles do not intersect. ## # Surface pixels could not be converted to dstInfo.colorType() or dstInfo.alphaType(). ## # dstRowBytes is too small to contain one row of pixels. ## ## #Param dstInfo width, height, Color_Type, and Alpha_Type of dstPixels ## #Param dstPixels storage for pixels; dstInfo.height() times dstRowBytes, or larger ## #Param dstRowBytes size of one destination row; dstInfo.width() times pixel size, or larger ## #Param srcX offset into readable pixels on x-axis; may be negative ## #Param srcY offset into readable pixels on y-axis; may be negative ## #Return true if pixels were copied ## #Example #Height 64 #Description A black oval drawn on a red background provides an image to copy. readPixels copies one quarter of the Surface into each of the four corners. The copied quarter ovals overdraw the original oval. ## sk_sp surf(SkSurface::MakeRasterN32Premul(64, 64)); auto surfCanvas = surf->getCanvas(); surfCanvas->clear(SK_ColorRED); SkPaint paint; surfCanvas->drawOval({4, 8, 58, 54}, paint); SkImageInfo info = SkImageInfo::Make(64, 64, kBGRA_8888_SkColorType, kPremul_SkAlphaType); sk_sp data(SkData::MakeUninitialized(info.minRowBytes() * info.height())); sk_bzero(data->writable_data(), info.minRowBytes() * info.height()); for (int x : { 32, -32 } ) { for (int y : { 32, -32 } ) { surf->readPixels(info, data->writable_data(), info.minRowBytes(), x, y); } } sk_sp image = SkImage::MakeRasterData(info, data, info.minRowBytes()); canvas->drawImage(image, 0, 0); ## #SeeAlso peekPixels writePixels #Method ## # ------------------------------------------------------------------------------ #Method bool readPixels(const SkBitmap& dst, int srcX, int srcY) Copies Rect of pixels from Surface into bitmap. Source Rect corners are (srcX, srcY) and Surface (width(), height()). Destination Rect corners are (0, 0) and (bitmap.width(), bitmap.height()). Copies each readable pixel intersecting both rectangles, without scaling, converting to dst.colorType() and dst.alphaType() if required. Pixels are readable when Surface is raster, or backed by a GPU. The destination pixel storage must be allocated by the caller. Pixel values are converted only if Color_Type and Alpha_Type do not match. Only pixels within both source and destination rectangles are copied. dst contents outside Rect intersection are unchanged. Pass negative values for srcX or srcY to offset pixels across or down destination. Does not copy, and returns false if: #List # Source and destination rectangles do not intersect. ## # Surface pixels could not be converted to dst.colorType() or dst.alphaType(). ## # dst pixels could not be allocated. ## # dst.rowBytes() is too small to contain one row of pixels. ## ## #Param dst storage for pixels copied from Surface ## #Param srcX offset into readable pixels on x-axis; may be negative ## #Param srcY offset into readable pixels on y-axis; may be negative ## #Return true if pixels were copied ## #Example sk_sp surf(SkSurface::MakeRasterN32Premul(64, 64)); auto surfCanvas = surf->getCanvas(); surfCanvas->clear(SK_ColorGREEN); SkPaint paint; surfCanvas->drawOval({2, 10, 58, 54}, paint); SkImageInfo info = SkImageInfo::Make(64, 64, kBGRA_8888_SkColorType, kPremul_SkAlphaType); SkBitmap bitmap; bitmap.setInfo(info); bitmap.allocPixels(); for (int x : { 32, -32 } ) { for (int y : { 32, -32 } ) { surf->readPixels(bitmap, x, y); } } canvas->drawBitmap(bitmap, 0, 0); ## #SeeAlso peekPixels writePixels #Method ## # ------------------------------------------------------------------------------ #Method void writePixels(const SkPixmap& src, int dstX, int dstY) #In Pixels #Line # copies Rect of pixels ## Copies Rect of pixels from the src Pixmap to the Surface. Source Rect corners are (0, 0) and (src.width(), src.height()). Destination Rect corners are (dstX, dstY) and #Formula # (dstX + Surface width(), dstY + Surface height()) ##. Copies each readable pixel intersecting both rectangles, without scaling, converting to Surface SkColorType and SkAlphaType if required. #Param src storage for pixels to copy to Surface ## #Param dstX x-axis position relative to Surface to begin copy; may be negative ## #Param dstY y-axis position relative to Surface to begin copy; may be negative ## #Example #Image 4 #Height 96 sk_sp surf(SkSurface::MakeRasterN32Premul(64, 64)); auto surfCanvas = surf->getCanvas(); surfCanvas->clear(SK_ColorRED); SkPaint paint; paint.setTextSize(40); surfCanvas->drawString("&", 16, 40, paint); SkPixmap pixmap; if (surf->peekPixels(&pixmap)) { surf->writePixels(pixmap, 25, 25); sk_sp image(surf->makeImageSnapshot()); canvas->drawImage(image, 0, 0); } ## #SeeAlso readPixels peekPixels #Method ## # ------------------------------------------------------------------------------ #Method void writePixels(const SkBitmap& src, int dstX, int dstY) Copies Rect of pixels from the src Bitmap to the Surface. Source Rect corners are (0, 0) and (src.width(), src.height()). Destination Rect corners are (dstX, dstY) and #Formula # (dstX + Surface width(), dstY + Surface height()) ##. Copies each readable pixel intersecting both rectangles, without scaling, converting to Surface SkColorType and SkAlphaType if required. #Param src storage for pixels to copy to Surface ## #Param dstX x-axis position relative to Surface to begin copy; may be negative ## #Param dstY y-axis position relative to Surface to begin copy; may be negative ## #Example #Image 4 #Height 96 sk_sp surf(SkSurface::MakeRasterN32Premul(64, 64)); auto surfCanvas = surf->getCanvas(); surfCanvas->clear(SK_ColorGREEN); surf->writePixels(source, 25, 25); sk_sp image(surf->makeImageSnapshot()); canvas->drawImage(image, 0, 0); ## #SeeAlso readPixels peekPixels #Method ## # ------------------------------------------------------------------------------ #Method const SkSurfaceProps& props() const #In Property #Line # returns Surface_Properties ## #Populate #Example const char* names[] = { "Unknown", "RGB_H", "BGR_H", "RGB_V", "BGR_V" }; sk_sp surf(SkSurface::MakeRasterN32Premul(64, 64)); SkDebugf("surf.props(): k%s_SkPixelGeometry\n", names[surf->props().pixelGeometry()]); #StdOut surf.props(): kRGB_H_SkPixelGeometry ## ## #SeeAlso SkSurfaceProps #Method ## # ------------------------------------------------------------------------------ #Subtopic Utility #Line # rarely called management functions ## ## #Method void flush() #In Utility #Line # resolves pending I/O ## #Populate #NoExample ## #SeeAlso GrBackendSemaphore #Method ## # ------------------------------------------------------------------------------ #Method GrSemaphoresSubmitted flushAndSignalSemaphores(int numSemaphores, GrBackendSemaphore signalSemaphores[]) #In Utility #Line # resolves pending I/O, and signal ## #Populate #NoExample ## #SeeAlso wait GrBackendSemaphore #Method ## # ------------------------------------------------------------------------------ #Method bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) #In Utility #Line # pauses commands until signaled ## #Populate #NoExample #ToDo this is copy and paste silliness masquerading as an example. Probably need gpu globals and definitely need gpu expertise to make a real example out of this also, note need to replace GrBackendObject with GrBackendTexture ## #Platform gpu #Height 64 SkPaint paint; paint.setTextSize(32); GrContext* context = canvas->getGrContext(); if (!context) { canvas->drawString("GPU only!", 20, 40, paint); return; } GrBackendSemaphore semaphore; sk_sp surface = SkSurface::MakeRenderTarget( context, SkBudgeted::kYes, SkImageInfo::MakeN32Premul(64, 64)); surface->flushAndSignalSemaphores(1, &semaphore); sk_sp image = surface->makeImageSnapshot(); GrBackendTexture backendTex = image->getBackendTexture(false); // unused SkASSERT(backendTex.isValid()); const SkImageInfo childImageInfo = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType, kPremul_SkAlphaType); sk_sp childSurface(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, childImageInfo, 0, kTopLeft_GrSurfaceOrigin, nullptr)); GrBackendTexture backendTexture; sk_sp childImage = SkImage::MakeFromTexture(context, backendTexture, // undefined kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, nullptr); SkCanvas* childCanvas = childSurface->getCanvas(); childCanvas->clear(SK_ColorRED); childSurface->wait(1, &semaphore); childCanvas->drawImage(childImage, 32, 0); childSurface->draw(canvas, 0, 0, nullptr); ## #SeeAlso flushAndSignalSemaphores GrBackendSemaphore #Method ## # ------------------------------------------------------------------------------ #Method bool characterize(SkSurfaceCharacterization* characterization) const #In Utility #Line # sets Surface_Characterization for threaded GPU processing ## #Populate #Example #Platform gpu #Height 64 SkPaint paint; paint.setTextSize(32); GrContext* context = canvas->getGrContext(); if (!context) { canvas->drawString("GPU only!", 20, 40, paint); return; } sk_sp gpuSurface = SkSurface::MakeRenderTarget( context, SkBudgeted::kYes, SkImageInfo::MakeN32Premul(64, 64)); SkSurfaceCharacterization characterization; if (!gpuSurface->characterize(&characterization)) { canvas->drawString("characterization unsupported", 20, 40, paint); return; } // start of threadable work SkDeferredDisplayListRecorder recorder(characterization); SkCanvas* subCanvas = recorder.getCanvas(); subCanvas->clear(SK_ColorGREEN); std::unique_ptr displayList = recorder.detach(); // end of threadable work gpuSurface->draw(displayList.get()); sk_sp img = gpuSurface->makeImageSnapshot(); canvas->drawImage(std::move(img), 0, 0); ## #SeeAlso draw() SkSurfaceCharacterization SkDeferredDisplayList #Method ## # ------------------------------------------------------------------------------ #Method bool draw(SkDeferredDisplayList* deferredDisplayList) #Populate #Example #Height 64 #Platform gpu cpu SkPaint paint; paint.setTextSize(16); sk_sp gpuSurface = SkSurface::MakeRasterN32Premul(64, 64); SkSurfaceCharacterization characterization; if (!gpuSurface->characterize(&characterization)) { canvas->drawString("characterization unsupported", 20, 40, paint); return; } // start of threadable work SkDeferredDisplayListRecorder recorder(characterization); SkCanvas* subCanvas = recorder.getCanvas(); subCanvas->clear(SK_ColorGREEN); std::unique_ptr displayList = recorder.detach(); // end of threadable work gpuSurface->draw(displayList.get()); sk_sp img = gpuSurface->makeImageSnapshot(); canvas->drawImage(std::move(img), 0, 0); ## #SeeAlso characterize() SkSurfaceCharacterization SkDeferredDisplayList #Method ## #Class SkSurface ## #Topic Surface ##