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 "SkRefCnt.h" 12 #include "SkImage.h" 13 #include "SkSurfaceProps.h" 14 15 #include "GrTypes.h" 16 17 class SkCanvas; 18 class SkDeferredDisplayList; 19 class SkPaint; 20 class SkSurfaceCharacterization; 21 class GrBackendRenderTarget; 22 class GrBackendSemaphore; 23 class GrContext; 24 class GrRenderTarget; 25 26 /** 27 * SkSurface is responsible for managing the pixels that a canvas draws into. The pixels can be 28 * allocated either in CPU memory (a Raster surface) or on the GPU (a RenderTarget surface). 29 * 30 * SkSurface takes care of allocating a SkCanvas that will draw into the surface. Call 31 * surface->getCanvas() to use that canvas (but don't delete it, it is owned by the surface). 32 * 33 * SkSurface always has non-zero dimensions. If there is a request for a new surface, and either 34 * of the requested dimensions are zero, then NULL will be returned. 35 */ 36 class SK_API SkSurface : public SkRefCnt { 37 public: 38 /** 39 * Create a new surface, using the specified pixels/rowbytes as its 40 * backend. 41 * 42 * If the requested surface cannot be created, or the request is not a 43 * supported configuration, NULL will be returned. 44 * 45 * Callers are responsible for initialiazing the surface pixels. 46 */ 47 static sk_sp<SkSurface> MakeRasterDirect(const SkImageInfo& imageInfo, void* pixels, 48 size_t rowBytes, 49 const SkSurfaceProps* surfaceProps = nullptr); 50 51 /** 52 * The same as NewRasterDirect, but also accepts a call-back routine, which is invoked 53 * when the surface is deleted, and is passed the pixel memory and the specified context. 54 */ 55 static sk_sp<SkSurface> MakeRasterDirectReleaseProc(const SkImageInfo& imageInfo, void* pixels, 56 size_t rowBytes, 57 void (*releaseProc)(void* pixels, void* context), 58 void* context, const SkSurfaceProps* surfaceProps = nullptr); 59 60 /** 61 * Return a new surface, with the memory for the pixels automatically allocated and 62 * zero-initialized, but respecting the specified rowBytes. If rowBytes==0, then a default 63 * value will be chosen. If a non-zero rowBytes is specified, then any images snapped off of 64 * this surface (via makeImageSnapshot()) are guaranteed to have the same rowBytes. 65 * 66 * If the requested surface cannot be created, or the request is not a 67 * supported configuration, NULL will be returned. 68 */ 69 static sk_sp<SkSurface> MakeRaster(const SkImageInfo& imageInfo, size_t rowBytes, 70 const SkSurfaceProps* surfaceProps); 71 72 /** 73 * Allocate a new surface, automatically computing the rowBytes. 74 */ 75 static sk_sp<SkSurface> MakeRaster(const SkImageInfo& imageInfo, 76 const SkSurfaceProps* props = nullptr) { 77 return MakeRaster(imageInfo, 0, props); 78 } 79 80 /** 81 * Helper version of NewRaster. It creates a SkImageInfo with the 82 * specified width and height, and populates the rest of info to match 83 * pixels in SkPMColor format. 84 */ 85 static sk_sp<SkSurface> MakeRasterN32Premul(int width, int height, 86 const SkSurfaceProps* surfaceProps = nullptr) { 87 return MakeRaster(SkImageInfo::MakeN32Premul(width, height), surfaceProps); 88 } 89 90 /** 91 * Used to wrap a pre-existing backend 3D API texture as a SkSurface. Skia will not assume 92 * ownership of the texture and the client must ensure the texture is valid for the lifetime 93 * of the SkSurface. If sampleCnt > 1, then we will create an intermediate mssa surface which 94 * we will use for rendering. We then resolve into the passed in texture. 95 */ 96 static sk_sp<SkSurface> MakeFromBackendTexture(GrContext* context, 97 const GrBackendTexture& backendTexture, 98 GrSurfaceOrigin origin, int sampleCnt, 99 sk_sp<SkColorSpace> colorSpace, 100 const SkSurfaceProps* surfaceProps); 101 102 /** 103 * Used to wrap a pre-existing backend 3D API texture as a SkSurface. Skia will not assume 104 * ownership of the texture and the client must ensure the texture is valid for the lifetime 105 * of the SkSurface. If sampleCnt > 1, then we will create an intermediate mssa surface which 106 * we will use for rendering. We then resolve into the passed in texture. 107 * 108 * The GrBackendTexture must have a valid backend format supplied (GrGLTextureInfo::fFormat, 109 * GrVkImageInfo::fFormat, etc.) in it. The passed in SkColorType informs skia how it should 110 * interpret the backend format supplied by the GrBackendTexture. If the format in the 111 * GrBackendTexture is not compatible with the sampleCnt, SkColorType, and SkColorSpace we 112 * will return nullptr. 113 */ 114 static sk_sp<SkSurface> MakeFromBackendTexture(GrContext* context, 115 const GrBackendTexture& backendTexture, 116 GrSurfaceOrigin origin, int sampleCnt, 117 SkColorType colorType, 118 sk_sp<SkColorSpace> colorSpace, 119 const SkSurfaceProps* surfaceProps); 120 121 static sk_sp<SkSurface> MakeFromBackendRenderTarget(GrContext* context, 122 const GrBackendRenderTarget& backendRenderTarget, 123 GrSurfaceOrigin origin, 124 sk_sp<SkColorSpace> colorSpace, 125 const SkSurfaceProps* surfaceProps); 126 127 /** 128 * The GrBackendRenderTarget must have a valid backend format set (GrGLTextureInfo::fFormat, 129 * GrVkImageInfo::fFormat, etc.) in it. The passed in SkColorType informs skia how it should 130 * interpret the backend format supplied by the GrBackendRenderTarget. If the format in the 131 * GrBackendRenderTarget is not compatible with the sampleCnt, SkColorType, and SkColorSpace 132 * we will return nullptr. 133 */ 134 static sk_sp<SkSurface> MakeFromBackendRenderTarget(GrContext* context, 135 const GrBackendRenderTarget& backendRenderTarget, 136 GrSurfaceOrigin origin, 137 SkColorType colorType, 138 sk_sp<SkColorSpace> colorSpace, 139 const SkSurfaceProps* surfaceProps); 140 141 /** 142 * Used to wrap a pre-existing 3D API texture as a SkSurface. Skia will treat the texture as 143 * a rendering target only, but unlike NewFromBackendRenderTarget, Skia will manage and own 144 * the associated render target objects (but not the provided texture). Skia will not assume 145 * ownership of the texture and the client must ensure the texture is valid for the lifetime 146 * of the SkSurface. 147 */ 148 static sk_sp<SkSurface> MakeFromBackendTextureAsRenderTarget(GrContext* context, 149 const GrBackendTexture& backendTexture, 150 GrSurfaceOrigin origin, 151 int sampleCnt, 152 sk_sp<SkColorSpace> colorSpace, 153 const SkSurfaceProps* surfaceProps); 154 155 /** 156 * Used to wrap a pre-existing 3D API texture as a SkSurface. Skia will treat the texture as 157 * a rendering target only, but unlike NewFromBackendRenderTarget, Skia will manage and own 158 * the associated render target objects (but not the provided texture). Skia will not assume 159 * ownership of the texture and the client must ensure the texture is valid for the lifetime 160 * of the SkSurface. 161 * 162 * The GrBackendTexture must have a valid backend format supplied (GrGLTextureInfo::fFormat, 163 * GrVkImageInfo::fFormat, etc.) in it. The passed in SkColorType informs skia how it should 164 * interpret the backend format supplied by the GrBackendTexture. If the format in the 165 * GrBackendTexture is not compatible with the sampleCnt, SkColorType, and SkColorSpace we 166 * will return nullptr. 167 */ 168 static sk_sp<SkSurface> MakeFromBackendTextureAsRenderTarget(GrContext* context, 169 const GrBackendTexture& backendTexture, 170 GrSurfaceOrigin origin, 171 int sampleCnt, 172 SkColorType colorType, 173 sk_sp<SkColorSpace> colorSpace, 174 const SkSurfaceProps* surfaceProps); 175 176 /** 177 * Return a new surface whose contents will be drawn to an offscreen 178 * render target, allocated by the surface. The optional shouldCreateWithMips flag is a hint 179 * that this surface may be snapped to an SkImage which will be used with mip maps so we should 180 * create the backend gpu RenderTarget with mips to avoid a copy later on. 181 */ 182 static sk_sp<SkSurface> MakeRenderTarget(GrContext* context, SkBudgeted budgeted, 183 const SkImageInfo& imageInfo, 184 int sampleCount, GrSurfaceOrigin surfaceOrigin, 185 const SkSurfaceProps* surfaceProps, 186 bool shouldCreateWithMips = false); 187 MakeRenderTarget(GrContext * context,SkBudgeted budgeted,const SkImageInfo & imageInfo,int sampleCount,const SkSurfaceProps * props)188 static sk_sp<SkSurface> MakeRenderTarget(GrContext* context, SkBudgeted budgeted, 189 const SkImageInfo& imageInfo, int sampleCount, 190 const SkSurfaceProps* props) { 191 return MakeRenderTarget(context, budgeted, imageInfo, sampleCount, 192 kBottomLeft_GrSurfaceOrigin, props); 193 } 194 MakeRenderTarget(GrContext * context,SkBudgeted budgeted,const SkImageInfo & imageInfo)195 static sk_sp<SkSurface> MakeRenderTarget(GrContext* context, SkBudgeted budgeted, 196 const SkImageInfo& imageInfo) { 197 if (!imageInfo.width() || !imageInfo.height()) { 198 return nullptr; 199 } 200 return MakeRenderTarget(context, budgeted, imageInfo, 0, kBottomLeft_GrSurfaceOrigin, 201 nullptr); 202 } 203 204 /** 205 * Returns a surface that stores no pixels. It can be drawn to via its canvas, but that 206 * canvas does not draw anything. Calling makeImageSnapshot() will return nullptr. 207 */ 208 static sk_sp<SkSurface> MakeNull(int width, int height); 209 width()210 int width() const { return fWidth; } height()211 int height() const { return fHeight; } 212 213 /** 214 * Returns a unique non-zero, unique value identifying the content of this 215 * surface. Each time the content is changed changed, either by drawing 216 * into this surface, or explicitly calling notifyContentChanged()) this 217 * method will return a new value. 218 * 219 * If this surface is empty (i.e. has a zero-dimention), this will return 220 * 0. 221 */ 222 uint32_t generationID(); 223 224 /** 225 * Modes that can be passed to notifyContentWillChange 226 */ 227 enum ContentChangeMode { 228 /** 229 * Use this mode if it is known that the upcoming content changes will 230 * clear or overwrite prior contents, thus making them discardable. 231 */ 232 kDiscard_ContentChangeMode, 233 /** 234 * Use this mode if prior surface contents need to be preserved or 235 * if in doubt. 236 */ 237 kRetain_ContentChangeMode, 238 }; 239 240 /** 241 * Call this if the contents are about to change. This will (lazily) force a new 242 * value to be returned from generationID() when it is called next. 243 * 244 * CAN WE DEPRECATE THIS? 245 */ 246 void notifyContentWillChange(ContentChangeMode mode); 247 248 enum BackendHandleAccess { 249 kFlushRead_BackendHandleAccess, //!< caller may read from the backend object 250 kFlushWrite_BackendHandleAccess, //!< caller may write to the backend object 251 kDiscardWrite_BackendHandleAccess, //!< caller must over-write the entire backend object 252 }; 253 254 /* 255 * These are legacy aliases which will be removed soon 256 */ 257 static const BackendHandleAccess kFlushRead_TextureHandleAccess = 258 kFlushRead_BackendHandleAccess; 259 static const BackendHandleAccess kFlushWrite_TextureHandleAccess = 260 kFlushWrite_BackendHandleAccess; 261 static const BackendHandleAccess kDiscardWrite_TextureHandleAccess = 262 kDiscardWrite_BackendHandleAccess; 263 264 265 /** 266 * Retrieves the backend API handle of the texture used by this surface, or 0 if the surface 267 * is not backed by a GPU texture. 268 * 269 * The returned texture-handle is only valid until the next draw-call into the surface, 270 * or the surface is deleted. 271 */ 272 GrBackendObject getTextureHandle(BackendHandleAccess backendHandleAccess); 273 274 /** 275 * Retrieves the backend API handle of the RenderTarget backing this surface. Callers must 276 * ensure this function returns 'true' or else the GrBackendObject will be invalid 277 * 278 * In OpenGL this will return the FramebufferObject ID. 279 */ 280 bool getRenderTargetHandle(GrBackendObject* backendObject, 281 BackendHandleAccess backendHandleAccess); 282 283 /** 284 * Return a canvas that will draw into this surface. This will always 285 * return the same canvas for a given surface, and is manged/owned by the 286 * surface. It should not be used when its parent surface has gone out of 287 * scope. 288 */ 289 SkCanvas* getCanvas(); 290 291 /** 292 * Return a new surface that is "compatible" with this one, in that it will 293 * efficiently be able to be drawn into this surface. Typical calling 294 * pattern: 295 * 296 * SkSurface* A = SkSurface::New...(); 297 * SkCanvas* canvasA = surfaceA->newCanvas(); 298 * ... 299 * SkSurface* surfaceB = surfaceA->newSurface(...); 300 * SkCanvas* canvasB = surfaceB->newCanvas(); 301 * ... // draw using canvasB 302 * canvasA->drawSurface(surfaceB); // <--- this will always be optimal! 303 */ 304 sk_sp<SkSurface> makeSurface(const SkImageInfo& imageInfo); 305 306 /** 307 * Returns an image of the current state of the surface pixels up to this 308 * point. Subsequent changes to the surface (by drawing into its canvas) 309 * will not be reflected in this image. For the GPU-backend, the budgeting 310 * decision for the snapped image will match that of the surface. 311 */ 312 sk_sp<SkImage> makeImageSnapshot(); 313 314 /** 315 * Though the caller could get a snapshot image explicitly, and draw that, 316 * it seems that directly drawing a surface into another canvas might be 317 * a common pattern, and that we could possibly be more efficient, since 318 * we'd know that the "snapshot" need only live until we've handed it off 319 * to the canvas. 320 */ 321 void draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint); 322 323 /** 324 * If the surface has direct access to its pixels (i.e. they are in local 325 * RAM) return true, and if not null, set the pixmap parameter to point to the information 326 * about the surface's pixels. The pixel address in the pixmap is only valid while 327 * the surface object is in scope, and no API call is made on the surface 328 * or its canvas. 329 * 330 * On failure, returns false and the pixmap parameter is ignored. 331 */ 332 bool peekPixels(SkPixmap* pixmap); 333 334 /** 335 * Copy the pixels from the surface into the specified pixmap, 336 * converting them into the pixmap's format. The surface pixels are read 337 * starting at the specified (srcX,srcY) location. 338 * 339 * The pixmap and (srcX,srcY) offset specifies a source rectangle 340 * 341 * srcR.setXYWH(srcX, srcY, pixmap.width(), pixmap.height()); 342 * 343 * srcR is intersected with the bounds of the base-layer. If this intersection is not empty, 344 * then we have two sets of pixels (of equal size). Replace the dst pixels with the 345 * corresponding src pixels, performing any colortype/alphatype transformations needed 346 * (in the case where the src and dst have different colortypes or alphatypes). 347 * 348 * This call can fail, returning false, for several reasons: 349 * - If srcR does not intersect the surface bounds. 350 * - If the requested colortype/alphatype cannot be converted from the surface's types. 351 */ 352 bool readPixels(const SkPixmap& dst, int srcX, int srcY); 353 bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, 354 int srcX, int srcY); 355 bool readPixels(const SkBitmap& dst, int srcX, int srcY); 356 props()357 const SkSurfaceProps& props() const { return fProps; } 358 359 /** 360 * Issue any pending surface IO to the current backend 3D API and resolve any surface MSAA. 361 * 362 * The flush calls below are the new preferred way to flush calls to a surface, and this call 363 * will eventually be removed. 364 */ 365 void prepareForExternalIO(); 366 367 /** 368 * Issue any pending surface IO to the current backend 3D API 369 */ 370 void flush(); 371 372 /** 373 * Issue any pending surface IO to the current backend 3D API. After issuing all commands, 374 * numSemaphore semaphores will be signaled by the gpu. The client passes in an array of 375 * numSemaphores GrBackendSemaphores. In general these GrBackendSemaphore's can be either 376 * initialized or not. If they are initialized, the backend uses the passed in semaphore. 377 * If it is not initialized, a new semaphore is created and the GrBackendSemaphore object 378 * is initialized with that semaphore. 379 * 380 * The client will own and be responsible for deleting the underlying semaphores that are stored 381 * and returned in initialized GrBackendSemaphore objects. The GrBackendSemaphore objects 382 * themselves can be deleted as soon as this function returns. 383 * 384 * If the backend API is OpenGL only uninitialized GrBackendSemaphores are supported. 385 * If the backend API is Vulkan either initialized or unitialized semaphores are supported. 386 * If unitialized, the semaphores which are created will be valid for use only with the VkDevice 387 * with which they were created. 388 * 389 * If this call returns GrSemaphoresSubmited::kNo, the GPU backend will not have created or 390 * added any semaphores to signal on the GPU. Thus the client should not have the GPU wait on 391 * any of the semaphores. However, any pending surface IO will still be flushed. 392 */ 393 GrSemaphoresSubmitted flushAndSignalSemaphores(int numSemaphores, 394 GrBackendSemaphore signalSemaphores[]); 395 396 /** 397 * Inserts a list of GPU semaphores that the current backend 3D API must wait on before 398 * executing any more commands on the GPU for this surface. Skia will take ownership of the 399 * underlying semaphores and delete them once they have been signaled and waited on. 400 * 401 * If this call returns false, then the GPU backend will not wait on any passed in semaphores, 402 * and the client will still own the semaphores. 403 */ 404 bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores); 405 406 /** 407 * This creates a characterization of this SkSurface's properties that can 408 * be used to perform gpu-backend preprocessing in a separate thread (via 409 * the SkDeferredDisplayListRecorder). 410 * It will return false on failure (e.g., if the SkSurface is cpu-backed). 411 */ 412 bool characterize(SkSurfaceCharacterization* characterization) const; 413 414 /** 415 * Draw a deferred display list (created via SkDeferredDisplayListRecorder). 416 * The draw will be skipped if the characterization stored in the display list 417 * isn't compatible with this surface. 418 */ 419 bool draw(SkDeferredDisplayList* deferredDisplayList); 420 421 protected: 422 SkSurface(int width, int height, const SkSurfaceProps* surfaceProps); 423 SkSurface(const SkImageInfo& imageInfo, const SkSurfaceProps* surfaceProps); 424 425 // called by subclass if their contents have changed dirtyGenerationID()426 void dirtyGenerationID() { 427 fGenerationID = 0; 428 } 429 430 private: 431 const SkSurfaceProps fProps; 432 const int fWidth; 433 const int fHeight; 434 uint32_t fGenerationID; 435 436 typedef SkRefCnt INHERITED; 437 }; 438 439 #endif 440