| 1 | /* |
| 2 | * Copyright 2012 Google Inc. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
| 6 | */ |
| 7 | |
| 8 | #ifndef SkSurface_DEFINED |
| 9 | #define SkSurface_DEFINED |
| 10 | |
| 11 | #include "include/core/SkImage.h" |
| 12 | #include "include/core/SkImageInfo.h" |
| 13 | #include "include/core/SkPixmap.h" |
| 14 | #include "include/core/SkRefCnt.h" |
| 15 | #include "include/core/SkSamplingOptions.h" |
| 16 | #include "include/core/SkScalar.h" |
| 17 | #include "include/core/SkSurfaceProps.h" |
| 18 | #include "include/core/SkTypes.h" |
| 19 | |
| 20 | #include <cstddef> |
| 21 | #include <cstdint> |
| 22 | #include <memory> |
| 23 | |
| 24 | class GrBackendSemaphore; |
| 25 | class GrBackendTexture; |
| 26 | class GrRecordingContext; |
| 27 | class GrSurfaceCharacterization; |
| 28 | enum GrSurfaceOrigin : int; |
| 29 | class SkBitmap; |
| 30 | class SkCanvas; |
| 31 | class SkCapabilities; |
| 32 | class SkColorSpace; |
| 33 | class SkPaint; |
| 34 | class SkSurface; |
| 35 | struct SkIRect; |
| 36 | struct SkISize; |
| 37 | |
| 38 | namespace skgpu::graphite { |
| 39 | class Recorder; |
| 40 | } |
| 41 | |
| 42 | namespace SkSurfaces { |
| 43 | |
| 44 | enum class BackendSurfaceAccess { |
| 45 | kNoAccess, //!< back-end surface will not be used by client |
| 46 | kPresent, //!< back-end surface will be used for presenting to screen |
| 47 | }; |
| 48 | |
| 49 | /** Returns SkSurface without backing pixels. Drawing to SkCanvas returned from SkSurface |
| 50 | has no effect. Calling makeImageSnapshot() on returned SkSurface returns nullptr. |
| 51 | |
| 52 | @param width one or greater |
| 53 | @param height one or greater |
| 54 | @return SkSurface if width and height are positive; otherwise, nullptr |
| 55 | |
| 56 | example: https://fiddle.skia.org/c/@Surface_MakeNull |
| 57 | */ |
| 58 | SK_API sk_sp<SkSurface> Null(int width, int height); |
| 59 | |
| 60 | /** Allocates raster SkSurface. SkCanvas returned by SkSurface draws directly into those allocated |
| 61 | pixels, which are zeroed before use. Pixel memory size is imageInfo.height() times |
| 62 | imageInfo.minRowBytes() or rowBytes, if provided and non-zero. |
| 63 | |
| 64 | Pixel memory is deleted when SkSurface is deleted. |
| 65 | |
| 66 | Validity constraints include: |
| 67 | - info dimensions are greater than zero; |
| 68 | - info contains SkColorType and SkAlphaType supported by raster surface. |
| 69 | |
| 70 | @param imageInfo width, height, SkColorType, SkAlphaType, SkColorSpace, |
| 71 | of raster surface; width and height must be greater than zero |
| 72 | @param rowBytes interval from one SkSurface row to the next. |
| 73 | @param props LCD striping orientation and setting for device independent fonts; |
| 74 | may be nullptr |
| 75 | @return SkSurface if parameters are valid and memory was allocated, else nullptr. |
| 76 | */ |
| 77 | SK_API sk_sp<SkSurface> Raster(const SkImageInfo& imageInfo, |
| 78 | size_t rowBytes, |
| 79 | const SkSurfaceProps* surfaceProps); |
| 80 | inline sk_sp<SkSurface> Raster(const SkImageInfo& imageInfo, |
| 81 | const SkSurfaceProps* props = nullptr) { |
| 82 | return Raster(imageInfo, rowBytes: 0, surfaceProps: props); |
| 83 | } |
| 84 | |
| 85 | /** Allocates raster SkSurface. SkCanvas returned by SkSurface draws directly into the |
| 86 | provided pixels. |
| 87 | |
| 88 | SkSurface is returned if all parameters are valid. |
| 89 | Valid parameters include: |
| 90 | info dimensions are greater than zero; |
| 91 | info contains SkColorType and SkAlphaType supported by raster surface; |
| 92 | pixels is not nullptr; |
| 93 | rowBytes is large enough to contain info width pixels of SkColorType. |
| 94 | |
| 95 | Pixel buffer size should be info height times computed rowBytes. |
| 96 | Pixels are not initialized. |
| 97 | To access pixels after drawing, peekPixels() or readPixels(). |
| 98 | |
| 99 | @param imageInfo width, height, SkColorType, SkAlphaType, SkColorSpace, |
| 100 | of raster surface; width and height must be greater than zero |
| 101 | @param pixels pointer to destination pixels buffer |
| 102 | @param rowBytes interval from one SkSurface row to the next |
| 103 | @param surfaceProps LCD striping orientation and setting for device independent fonts; |
| 104 | may be nullptr |
| 105 | @return SkSurface if all parameters are valid; otherwise, nullptr |
| 106 | */ |
| 107 | |
| 108 | SK_API sk_sp<SkSurface> WrapPixels(const SkImageInfo& imageInfo, |
| 109 | void* pixels, |
| 110 | size_t rowBytes, |
| 111 | const SkSurfaceProps* surfaceProps = nullptr); |
| 112 | inline sk_sp<SkSurface> WrapPixels(const SkPixmap& pm, const SkSurfaceProps* props = nullptr) { |
| 113 | return WrapPixels(imageInfo: pm.info(), pixels: pm.writable_addr(), rowBytes: pm.rowBytes(), surfaceProps: props); |
| 114 | } |
| 115 | |
| 116 | using PixelsReleaseProc = void(void* pixels, void* context); |
| 117 | |
| 118 | /** Allocates raster SkSurface. SkCanvas returned by SkSurface draws directly into the provided |
| 119 | pixels. releaseProc is called with pixels and context when SkSurface is deleted. |
| 120 | |
| 121 | SkSurface is returned if all parameters are valid. |
| 122 | Valid parameters include: |
| 123 | info dimensions are greater than zero; |
| 124 | info contains SkColorType and SkAlphaType supported by raster surface; |
| 125 | pixels is not nullptr; |
| 126 | rowBytes is large enough to contain info width pixels of SkColorType. |
| 127 | |
| 128 | Pixel buffer size should be info height times computed rowBytes. |
| 129 | Pixels are not initialized. |
| 130 | To access pixels after drawing, call flush() or peekPixels(). |
| 131 | |
| 132 | @param imageInfo width, height, SkColorType, SkAlphaType, SkColorSpace, |
| 133 | of raster surface; width and height must be greater than zero |
| 134 | @param pixels pointer to destination pixels buffer |
| 135 | @param rowBytes interval from one SkSurface row to the next |
| 136 | @param releaseProc called when SkSurface is deleted; may be nullptr |
| 137 | @param context passed to releaseProc; may be nullptr |
| 138 | @param surfaceProps LCD striping orientation and setting for device independent fonts; |
| 139 | may be nullptr |
| 140 | @return SkSurface if all parameters are valid; otherwise, nullptr |
| 141 | */ |
| 142 | SK_API sk_sp<SkSurface> WrapPixels(const SkImageInfo& imageInfo, |
| 143 | void* pixels, |
| 144 | size_t rowBytes, |
| 145 | PixelsReleaseProc, |
| 146 | void* context, |
| 147 | const SkSurfaceProps* surfaceProps = nullptr); |
| 148 | } // namespace SkSurfaces |
| 149 | |
| 150 | /** \class SkSurface |
| 151 | SkSurface is responsible for managing the pixels that a canvas draws into. The pixels can be |
| 152 | allocated either in CPU memory (a raster surface) or on the GPU (a GrRenderTarget surface). |
| 153 | SkSurface takes care of allocating a SkCanvas that will draw into the surface. Call |
| 154 | surface->getCanvas() to use that canvas (but don't delete it, it is owned by the surface). |
| 155 | SkSurface always has non-zero dimensions. If there is a request for a new surface, and either |
| 156 | of the requested dimensions are zero, then nullptr will be returned. |
| 157 | |
| 158 | Clients should *not* subclass SkSurface as there is a lot of internal machinery that is |
| 159 | not publicly accessible. |
| 160 | */ |
| 161 | class SK_API SkSurface : public SkRefCnt { |
| 162 | public: |
| 163 | /** Is this surface compatible with the provided characterization? |
| 164 | |
| 165 | This method can be used to determine if an existing SkSurface is a viable destination |
| 166 | for an GrDeferredDisplayList. |
| 167 | |
| 168 | @param characterization The characterization for which a compatibility check is desired |
| 169 | @return true if this surface is compatible with the characterization; |
| 170 | false otherwise |
| 171 | */ |
| 172 | bool isCompatible(const GrSurfaceCharacterization& characterization) const; |
| 173 | |
| 174 | /** Returns pixel count in each row; may be zero or greater. |
| 175 | |
| 176 | @return number of pixel columns |
| 177 | */ |
| 178 | int width() const { return fWidth; } |
| 179 | |
| 180 | /** Returns pixel row count; may be zero or greater. |
| 181 | |
| 182 | @return number of pixel rows |
| 183 | */ |
| 184 | int height() const { return fHeight; } |
| 185 | |
| 186 | /** Returns an ImageInfo describing the surface. |
| 187 | */ |
| 188 | virtual SkImageInfo imageInfo() const { return SkImageInfo::MakeUnknown(width: fWidth, height: fHeight); } |
| 189 | |
| 190 | /** Returns unique value identifying the content of SkSurface. Returned value changes |
| 191 | each time the content changes. Content is changed by drawing, or by calling |
| 192 | notifyContentWillChange(). |
| 193 | |
| 194 | @return unique content identifier |
| 195 | |
| 196 | example: https://fiddle.skia.org/c/@Surface_notifyContentWillChange |
| 197 | */ |
| 198 | uint32_t generationID(); |
| 199 | |
| 200 | /** \enum SkSurface::ContentChangeMode |
| 201 | ContentChangeMode members are parameters to notifyContentWillChange(). |
| 202 | */ |
| 203 | enum ContentChangeMode { |
| 204 | kDiscard_ContentChangeMode, //!< discards surface on change |
| 205 | kRetain_ContentChangeMode, //!< preserves surface on change |
| 206 | }; |
| 207 | |
| 208 | /** Notifies that SkSurface contents will be changed by code outside of Skia. |
| 209 | Subsequent calls to generationID() return a different value. |
| 210 | |
| 211 | TODO: Can kRetain_ContentChangeMode be deprecated? |
| 212 | |
| 213 | example: https://fiddle.skia.org/c/@Surface_notifyContentWillChange |
| 214 | */ |
| 215 | void notifyContentWillChange(ContentChangeMode mode); |
| 216 | |
| 217 | /** Returns the recording context being used by the SkSurface. |
| 218 | |
| 219 | @return the recording context, if available; nullptr otherwise |
| 220 | */ |
| 221 | GrRecordingContext* recordingContext() const; |
| 222 | |
| 223 | /** Returns the recorder being used by the SkSurface. |
| 224 | |
| 225 | @return the recorder, if available; nullptr otherwise |
| 226 | */ |
| 227 | skgpu::graphite::Recorder* recorder() const; |
| 228 | |
| 229 | enum class BackendHandleAccess { |
| 230 | kFlushRead, //!< back-end object is readable |
| 231 | kFlushWrite, //!< back-end object is writable |
| 232 | kDiscardWrite, //!< back-end object must be overwritten |
| 233 | |
| 234 | // Legacy names, remove when clients are migrated |
| 235 | kFlushRead_BackendHandleAccess = kFlushRead, |
| 236 | kFlushWrite_BackendHandleAccess = kFlushWrite, |
| 237 | kDiscardWrite_BackendHandleAccess = kDiscardWrite, |
| 238 | }; |
| 239 | |
| 240 | // Legacy names, remove when clients are migrated |
| 241 | static constexpr BackendHandleAccess kFlushRead_BackendHandleAccess = |
| 242 | BackendHandleAccess::kFlushRead; |
| 243 | static constexpr BackendHandleAccess kFlushWrite_BackendHandleAccess = |
| 244 | BackendHandleAccess::kFlushWrite; |
| 245 | static constexpr BackendHandleAccess kDiscardWrite_BackendHandleAccess = |
| 246 | BackendHandleAccess::kDiscardWrite; |
| 247 | |
| 248 | /** Caller data passed to TextureReleaseProc; may be nullptr. */ |
| 249 | using ReleaseContext = void*; |
| 250 | /** User function called when supplied texture may be deleted. */ |
| 251 | using TextureReleaseProc = void (*)(ReleaseContext); |
| 252 | |
| 253 | /** If the surface was made via MakeFromBackendTexture then it's backing texture may be |
| 254 | substituted with a different texture. The contents of the previous backing texture are |
| 255 | copied into the new texture. SkCanvas state is preserved. The original sample count is |
| 256 | used. The GrBackendFormat and dimensions of replacement texture must match that of |
| 257 | the original. |
| 258 | |
| 259 | Upon success textureReleaseProc is called when it is safe to delete the texture in the |
| 260 | backend API (accounting only for use of the texture by this surface). If SkSurface creation |
| 261 | fails textureReleaseProc is called before this function returns. |
| 262 | |
| 263 | @param backendTexture the new backing texture for the surface |
| 264 | @param mode Retain or discard current Content |
| 265 | @param TextureReleaseProc function called when texture can be released |
| 266 | @param ReleaseContext state passed to textureReleaseProc |
| 267 | */ |
| 268 | virtual bool replaceBackendTexture(const GrBackendTexture& backendTexture, |
| 269 | GrSurfaceOrigin origin, |
| 270 | ContentChangeMode mode = kRetain_ContentChangeMode, |
| 271 | TextureReleaseProc = nullptr, |
| 272 | ReleaseContext = nullptr) = 0; |
| 273 | |
| 274 | /** Returns SkCanvas that draws into SkSurface. Subsequent calls return the same SkCanvas. |
| 275 | SkCanvas returned is managed and owned by SkSurface, and is deleted when SkSurface |
| 276 | is deleted. |
| 277 | |
| 278 | @return drawing SkCanvas for SkSurface |
| 279 | |
| 280 | example: https://fiddle.skia.org/c/@Surface_getCanvas |
| 281 | */ |
| 282 | SkCanvas* getCanvas(); |
| 283 | |
| 284 | /** Returns SkCapabilities that describes the capabilities of the SkSurface's device. |
| 285 | |
| 286 | @return SkCapabilities of SkSurface's device. |
| 287 | */ |
| 288 | sk_sp<const SkCapabilities> capabilities(); |
| 289 | |
| 290 | /** Returns a compatible SkSurface, or nullptr. Returned SkSurface contains |
| 291 | the same raster, GPU, or null properties as the original. Returned SkSurface |
| 292 | does not share the same pixels. |
| 293 | |
| 294 | Returns nullptr if imageInfo width or height are zero, or if imageInfo |
| 295 | is incompatible with SkSurface. |
| 296 | |
| 297 | @param imageInfo width, height, SkColorType, SkAlphaType, SkColorSpace, |
| 298 | of SkSurface; width and height must be greater than zero |
| 299 | @return compatible SkSurface or nullptr |
| 300 | |
| 301 | example: https://fiddle.skia.org/c/@Surface_makeSurface |
| 302 | */ |
| 303 | sk_sp<SkSurface> makeSurface(const SkImageInfo& imageInfo); |
| 304 | |
| 305 | /** Calls makeSurface(ImageInfo) with the same ImageInfo as this surface, but with the |
| 306 | * specified width and height. |
| 307 | */ |
| 308 | sk_sp<SkSurface> makeSurface(int width, int height); |
| 309 | |
| 310 | /** Returns SkImage capturing SkSurface contents. Subsequent drawing to SkSurface contents |
| 311 | are not captured. SkImage allocation is accounted for if SkSurface was created with |
| 312 | skgpu::Budgeted::kYes. |
| 313 | |
| 314 | @return SkImage initialized with SkSurface contents |
| 315 | |
| 316 | example: https://fiddle.skia.org/c/@Surface_makeImageSnapshot |
| 317 | */ |
| 318 | sk_sp<SkImage> makeImageSnapshot(); |
| 319 | |
| 320 | /** |
| 321 | * Like the no-parameter version, this returns an image of the current surface contents. |
| 322 | * This variant takes a rectangle specifying the subset of the surface that is of interest. |
| 323 | * These bounds will be sanitized before being used. |
| 324 | * - If bounds extends beyond the surface, it will be trimmed to just the intersection of |
| 325 | * it and the surface. |
| 326 | * - If bounds does not intersect the surface, then this returns nullptr. |
| 327 | * - If bounds == the surface, then this is the same as calling the no-parameter variant. |
| 328 | |
| 329 | example: https://fiddle.skia.org/c/@Surface_makeImageSnapshot_2 |
| 330 | */ |
| 331 | sk_sp<SkImage> makeImageSnapshot(const SkIRect& bounds); |
| 332 | |
| 333 | /** Draws SkSurface contents to canvas, with its top-left corner at (x, y). |
| 334 | |
| 335 | If SkPaint paint is not nullptr, apply SkColorFilter, alpha, SkImageFilter, and SkBlendMode. |
| 336 | |
| 337 | @param canvas SkCanvas drawn into |
| 338 | @param x horizontal offset in SkCanvas |
| 339 | @param y vertical offset in SkCanvas |
| 340 | @param sampling what technique to use when sampling the surface pixels |
| 341 | @param paint SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter, |
| 342 | and so on; or nullptr |
| 343 | |
| 344 | example: https://fiddle.skia.org/c/@Surface_draw |
| 345 | */ |
| 346 | void draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkSamplingOptions& sampling, |
| 347 | const SkPaint* paint); |
| 348 | |
| 349 | void draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint = nullptr) { |
| 350 | this->draw(canvas, x, y, sampling: SkSamplingOptions(), paint); |
| 351 | } |
| 352 | |
| 353 | /** Copies SkSurface pixel address, row bytes, and SkImageInfo to SkPixmap, if address |
| 354 | is available, and returns true. If pixel address is not available, return |
| 355 | false and leave SkPixmap unchanged. |
| 356 | |
| 357 | pixmap contents become invalid on any future change to SkSurface. |
| 358 | |
| 359 | @param pixmap storage for pixel state if pixels are readable; otherwise, ignored |
| 360 | @return true if SkSurface has direct access to pixels |
| 361 | |
| 362 | example: https://fiddle.skia.org/c/@Surface_peekPixels |
| 363 | */ |
| 364 | bool peekPixels(SkPixmap* pixmap); |
| 365 | |
| 366 | /** Copies SkRect of pixels to dst. |
| 367 | |
| 368 | Source SkRect corners are (srcX, srcY) and SkSurface (width(), height()). |
| 369 | Destination SkRect corners are (0, 0) and (dst.width(), dst.height()). |
| 370 | Copies each readable pixel intersecting both rectangles, without scaling, |
| 371 | converting to dst.colorType() and dst.alphaType() if required. |
| 372 | |
| 373 | Pixels are readable when SkSurface is raster, or backed by a GPU. |
| 374 | |
| 375 | The destination pixel storage must be allocated by the caller. |
| 376 | |
| 377 | Pixel values are converted only if SkColorType and SkAlphaType |
| 378 | do not match. Only pixels within both source and destination rectangles |
| 379 | are copied. dst contents outside SkRect intersection are unchanged. |
| 380 | |
| 381 | Pass negative values for srcX or srcY to offset pixels across or down destination. |
| 382 | |
| 383 | Does not copy, and returns false if: |
| 384 | - Source and destination rectangles do not intersect. |
| 385 | - SkPixmap pixels could not be allocated. |
| 386 | - dst.rowBytes() is too small to contain one row of pixels. |
| 387 | |
| 388 | @param dst storage for pixels copied from SkSurface |
| 389 | @param srcX offset into readable pixels on x-axis; may be negative |
| 390 | @param srcY offset into readable pixels on y-axis; may be negative |
| 391 | @return true if pixels were copied |
| 392 | |
| 393 | example: https://fiddle.skia.org/c/@Surface_readPixels |
| 394 | */ |
| 395 | bool readPixels(const SkPixmap& dst, int srcX, int srcY); |
| 396 | |
| 397 | /** Copies SkRect of pixels from SkCanvas into dstPixels. |
| 398 | |
| 399 | Source SkRect corners are (srcX, srcY) and SkSurface (width(), height()). |
| 400 | Destination SkRect corners are (0, 0) and (dstInfo.width(), dstInfo.height()). |
| 401 | Copies each readable pixel intersecting both rectangles, without scaling, |
| 402 | converting to dstInfo.colorType() and dstInfo.alphaType() if required. |
| 403 | |
| 404 | Pixels are readable when SkSurface is raster, or backed by a GPU. |
| 405 | |
| 406 | The destination pixel storage must be allocated by the caller. |
| 407 | |
| 408 | Pixel values are converted only if SkColorType and SkAlphaType |
| 409 | do not match. Only pixels within both source and destination rectangles |
| 410 | are copied. dstPixels contents outside SkRect intersection are unchanged. |
| 411 | |
| 412 | Pass negative values for srcX or srcY to offset pixels across or down destination. |
| 413 | |
| 414 | Does not copy, and returns false if: |
| 415 | - Source and destination rectangles do not intersect. |
| 416 | - SkSurface pixels could not be converted to dstInfo.colorType() or dstInfo.alphaType(). |
| 417 | - dstRowBytes is too small to contain one row of pixels. |
| 418 | |
| 419 | @param dstInfo width, height, SkColorType, and SkAlphaType of dstPixels |
| 420 | @param dstPixels storage for pixels; dstInfo.height() times dstRowBytes, or larger |
| 421 | @param dstRowBytes size of one destination row; dstInfo.width() times pixel size, or larger |
| 422 | @param srcX offset into readable pixels on x-axis; may be negative |
| 423 | @param srcY offset into readable pixels on y-axis; may be negative |
| 424 | @return true if pixels were copied |
| 425 | */ |
| 426 | bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, |
| 427 | int srcX, int srcY); |
| 428 | |
| 429 | /** Copies SkRect of pixels from SkSurface into bitmap. |
| 430 | |
| 431 | Source SkRect corners are (srcX, srcY) and SkSurface (width(), height()). |
| 432 | Destination SkRect corners are (0, 0) and (bitmap.width(), bitmap.height()). |
| 433 | Copies each readable pixel intersecting both rectangles, without scaling, |
| 434 | converting to bitmap.colorType() and bitmap.alphaType() if required. |
| 435 | |
| 436 | Pixels are readable when SkSurface is raster, or backed by a GPU. |
| 437 | |
| 438 | The destination pixel storage must be allocated by the caller. |
| 439 | |
| 440 | Pixel values are converted only if SkColorType and SkAlphaType |
| 441 | do not match. Only pixels within both source and destination rectangles |
| 442 | are copied. dst contents outside SkRect intersection are unchanged. |
| 443 | |
| 444 | Pass negative values for srcX or srcY to offset pixels across or down destination. |
| 445 | |
| 446 | Does not copy, and returns false if: |
| 447 | - Source and destination rectangles do not intersect. |
| 448 | - SkSurface pixels could not be converted to dst.colorType() or dst.alphaType(). |
| 449 | - dst pixels could not be allocated. |
| 450 | - dst.rowBytes() is too small to contain one row of pixels. |
| 451 | |
| 452 | @param dst storage for pixels copied from SkSurface |
| 453 | @param srcX offset into readable pixels on x-axis; may be negative |
| 454 | @param srcY offset into readable pixels on y-axis; may be negative |
| 455 | @return true if pixels were copied |
| 456 | |
| 457 | example: https://fiddle.skia.org/c/@Surface_readPixels_3 |
| 458 | */ |
| 459 | bool readPixels(const SkBitmap& dst, int srcX, int srcY); |
| 460 | |
| 461 | using AsyncReadResult = SkImage::AsyncReadResult; |
| 462 | |
| 463 | /** Client-provided context that is passed to client-provided ReadPixelsContext. */ |
| 464 | using ReadPixelsContext = void*; |
| 465 | |
| 466 | /** Client-provided callback to asyncRescaleAndReadPixels() or |
| 467 | asyncRescaleAndReadPixelsYUV420() that is called when read result is ready or on failure. |
| 468 | */ |
| 469 | using ReadPixelsCallback = void(ReadPixelsContext, std::unique_ptr<const AsyncReadResult>); |
| 470 | |
| 471 | /** Controls the gamma that rescaling occurs in for asyncRescaleAndReadPixels() and |
| 472 | asyncRescaleAndReadPixelsYUV420(). |
| 473 | */ |
| 474 | using RescaleGamma = SkImage::RescaleGamma; |
| 475 | using RescaleMode = SkImage::RescaleMode; |
| 476 | |
| 477 | /** Makes surface pixel data available to caller, possibly asynchronously. It can also rescale |
| 478 | the surface pixels. |
| 479 | |
| 480 | Currently asynchronous reads are only supported on the GPU backend and only when the |
| 481 | underlying 3D API supports transfer buffers and CPU/GPU synchronization primitives. In all |
| 482 | other cases this operates synchronously. |
| 483 | |
| 484 | Data is read from the source sub-rectangle, is optionally converted to a linear gamma, is |
| 485 | rescaled to the size indicated by 'info', is then converted to the color space, color type, |
| 486 | and alpha type of 'info'. A 'srcRect' that is not contained by the bounds of the surface |
| 487 | causes failure. |
| 488 | |
| 489 | When the pixel data is ready the caller's ReadPixelsCallback is called with a |
| 490 | AsyncReadResult containing pixel data in the requested color type, alpha type, and color |
| 491 | space. The AsyncReadResult will have count() == 1. Upon failure the callback is called |
| 492 | with nullptr for AsyncReadResult. For a GPU surface this flushes work but a submit must |
| 493 | occur to guarantee a finite time before the callback is called. |
| 494 | |
| 495 | The data is valid for the lifetime of AsyncReadResult with the exception that if the |
| 496 | SkSurface is GPU-backed the data is immediately invalidated if the context is abandoned |
| 497 | or destroyed. |
| 498 | |
| 499 | @param info info of the requested pixels |
| 500 | @param srcRect subrectangle of surface to read |
| 501 | @param rescaleGamma controls whether rescaling is done in the surface's gamma or whether |
| 502 | the source data is transformed to a linear gamma before rescaling. |
| 503 | @param rescaleMode controls the technique of the rescaling |
| 504 | @param callback function to call with result of the read |
| 505 | @param context passed to callback |
| 506 | */ |
| 507 | void asyncRescaleAndReadPixels(const SkImageInfo& info, |
| 508 | const SkIRect& srcRect, |
| 509 | RescaleGamma rescaleGamma, |
| 510 | RescaleMode rescaleMode, |
| 511 | ReadPixelsCallback callback, |
| 512 | ReadPixelsContext context); |
| 513 | |
| 514 | /** |
| 515 | Similar to asyncRescaleAndReadPixels but performs an additional conversion to YUV. The |
| 516 | RGB->YUV conversion is controlled by 'yuvColorSpace'. The YUV data is returned as three |
| 517 | planes ordered y, u, v. The u and v planes are half the width and height of the resized |
| 518 | rectangle. The y, u, and v values are single bytes. Currently this fails if 'dstSize' |
| 519 | width and height are not even. A 'srcRect' that is not contained by the bounds of the |
| 520 | surface causes failure. |
| 521 | |
| 522 | When the pixel data is ready the caller's ReadPixelsCallback is called with a |
| 523 | AsyncReadResult containing the planar data. The AsyncReadResult will have count() == 3. |
| 524 | Upon failure the callback is called with nullptr for AsyncReadResult. For a GPU surface this |
| 525 | flushes work but a submit must occur to guarantee a finite time before the callback is |
| 526 | called. |
| 527 | |
| 528 | The data is valid for the lifetime of AsyncReadResult with the exception that if the |
| 529 | SkSurface is GPU-backed the data is immediately invalidated if the context is abandoned |
| 530 | or destroyed. |
| 531 | |
| 532 | @param yuvColorSpace The transformation from RGB to YUV. Applied to the resized image |
| 533 | after it is converted to dstColorSpace. |
| 534 | @param dstColorSpace The color space to convert the resized image to, after rescaling. |
| 535 | @param srcRect The portion of the surface to rescale and convert to YUV planes. |
| 536 | @param dstSize The size to rescale srcRect to |
| 537 | @param rescaleGamma controls whether rescaling is done in the surface's gamma or whether |
| 538 | the source data is transformed to a linear gamma before rescaling. |
| 539 | @param rescaleMode controls the sampling technique of the rescaling |
| 540 | @param callback function to call with the planar read result |
| 541 | @param context passed to callback |
| 542 | */ |
| 543 | void asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace, |
| 544 | sk_sp<SkColorSpace> dstColorSpace, |
| 545 | const SkIRect& srcRect, |
| 546 | const SkISize& dstSize, |
| 547 | RescaleGamma rescaleGamma, |
| 548 | RescaleMode rescaleMode, |
| 549 | ReadPixelsCallback callback, |
| 550 | ReadPixelsContext context); |
| 551 | |
| 552 | /** |
| 553 | * Identical to asyncRescaleAndReadPixelsYUV420 but a fourth plane is returned in the |
| 554 | * AsyncReadResult passed to 'callback'. The fourth plane contains the alpha chanel at the |
| 555 | * same full resolution as the Y plane. |
| 556 | */ |
| 557 | void asyncRescaleAndReadPixelsYUVA420(SkYUVColorSpace yuvColorSpace, |
| 558 | sk_sp<SkColorSpace> dstColorSpace, |
| 559 | const SkIRect& srcRect, |
| 560 | const SkISize& dstSize, |
| 561 | RescaleGamma rescaleGamma, |
| 562 | RescaleMode rescaleMode, |
| 563 | ReadPixelsCallback callback, |
| 564 | ReadPixelsContext context); |
| 565 | |
| 566 | /** Copies SkRect of pixels from the src SkPixmap to the SkSurface. |
| 567 | |
| 568 | Source SkRect corners are (0, 0) and (src.width(), src.height()). |
| 569 | Destination SkRect corners are (dstX, dstY) and |
| 570 | (dstX + Surface width(), dstY + Surface height()). |
| 571 | |
| 572 | Copies each readable pixel intersecting both rectangles, without scaling, |
| 573 | converting to SkSurface colorType() and SkSurface alphaType() if required. |
| 574 | |
| 575 | @param src storage for pixels to copy to SkSurface |
| 576 | @param dstX x-axis position relative to SkSurface to begin copy; may be negative |
| 577 | @param dstY y-axis position relative to SkSurface to begin copy; may be negative |
| 578 | |
| 579 | example: https://fiddle.skia.org/c/@Surface_writePixels |
| 580 | */ |
| 581 | void writePixels(const SkPixmap& src, int dstX, int dstY); |
| 582 | |
| 583 | /** Copies SkRect of pixels from the src SkBitmap to the SkSurface. |
| 584 | |
| 585 | Source SkRect corners are (0, 0) and (src.width(), src.height()). |
| 586 | Destination SkRect corners are (dstX, dstY) and |
| 587 | (dstX + Surface width(), dstY + Surface height()). |
| 588 | |
| 589 | Copies each readable pixel intersecting both rectangles, without scaling, |
| 590 | converting to SkSurface colorType() and SkSurface alphaType() if required. |
| 591 | |
| 592 | @param src storage for pixels to copy to SkSurface |
| 593 | @param dstX x-axis position relative to SkSurface to begin copy; may be negative |
| 594 | @param dstY y-axis position relative to SkSurface to begin copy; may be negative |
| 595 | |
| 596 | example: https://fiddle.skia.org/c/@Surface_writePixels_2 |
| 597 | */ |
| 598 | void writePixels(const SkBitmap& src, int dstX, int dstY); |
| 599 | |
| 600 | /** Returns SkSurfaceProps for surface. |
| 601 | |
| 602 | @return LCD striping orientation and setting for device independent fonts |
| 603 | */ |
| 604 | const SkSurfaceProps& props() const { return fProps; } |
| 605 | |
| 606 | /** Inserts a list of GPU semaphores that the current GPU-backed API must wait on before |
| 607 | executing any more commands on the GPU for this surface. If this call returns false, then |
| 608 | the GPU back-end will not wait on any passed in semaphores, and the client will still own |
| 609 | the semaphores, regardless of the value of deleteSemaphoresAfterWait. |
| 610 | |
| 611 | If deleteSemaphoresAfterWait is false then Skia will not delete the semaphores. In this case |
| 612 | it is the client's responsibility to not destroy or attempt to reuse the semaphores until it |
| 613 | knows that Skia has finished waiting on them. This can be done by using finishedProcs |
| 614 | on flush calls. |
| 615 | |
| 616 | @param numSemaphores size of waitSemaphores array |
| 617 | @param waitSemaphores array of semaphore containers |
| 618 | @paramm deleteSemaphoresAfterWait who owns and should delete the semaphores |
| 619 | @return true if GPU is waiting on semaphores |
| 620 | */ |
| 621 | bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores, |
| 622 | bool deleteSemaphoresAfterWait = true); |
| 623 | |
| 624 | /** Initializes GrSurfaceCharacterization that can be used to perform GPU back-end |
| 625 | processing in a separate thread. Typically this is used to divide drawing |
| 626 | into multiple tiles. GrDeferredDisplayListRecorder records the drawing commands |
| 627 | for each tile. |
| 628 | |
| 629 | Return true if SkSurface supports characterization. raster surface returns false. |
| 630 | |
| 631 | @param characterization properties for parallel drawing |
| 632 | @return true if supported |
| 633 | |
| 634 | example: https://fiddle.skia.org/c/@Surface_characterize |
| 635 | */ |
| 636 | bool characterize(GrSurfaceCharacterization* characterization) const; |
| 637 | |
| 638 | protected: |
| 639 | SkSurface(int width, int height, const SkSurfaceProps* surfaceProps); |
| 640 | SkSurface(const SkImageInfo& imageInfo, const SkSurfaceProps* surfaceProps); |
| 641 | |
| 642 | // called by subclass if their contents have changed |
| 643 | void dirtyGenerationID() { |
| 644 | fGenerationID = 0; |
| 645 | } |
| 646 | |
| 647 | private: |
| 648 | const SkSurfaceProps fProps; |
| 649 | const int fWidth; |
| 650 | const int fHeight; |
| 651 | uint32_t fGenerationID; |
| 652 | |
| 653 | using INHERITED = SkRefCnt; |
| 654 | }; |
| 655 | |
| 656 | #endif |
| 657 | |