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 class SkCanvas; 16 class SkPaint; 17 class GrContext; 18 class GrRenderTarget; 19 20 /** 21 * SkSurface represents the backend/results of drawing to a canvas. For raster 22 * drawing, the surface will be pixels, but (for example) when drawing into 23 * a PDF or Picture canvas, the surface stores the recorded commands. 24 * 25 * To draw into a canvas, first create the appropriate type of Surface, and 26 * then request the canvas from the surface. 27 * 28 * SkSurface always has non-zero dimensions. If there is a request for a new surface, and either 29 * of the requested dimensions are zero, then NULL will be returned. 30 */ 31 class SK_API SkSurface : public SkRefCnt { 32 public: 33 /** 34 * Create a new surface, using the specified pixels/rowbytes as its 35 * backend. 36 * 37 * If the requested surface cannot be created, or the request is not a 38 * supported configuration, NULL will be returned. 39 * 40 * Callers are responsible for initialiazing the surface pixels. 41 */ 42 static sk_sp<SkSurface> MakeRasterDirect(const SkImageInfo&, void* pixels, size_t rowBytes, 43 const SkSurfaceProps* = nullptr); 44 45 /** 46 * The same as NewRasterDirect, but also accepts a call-back routine, which is invoked 47 * when the surface is deleted, and is passed the pixel memory and the specified context. 48 */ 49 static sk_sp<SkSurface> MakeRasterDirectReleaseProc(const SkImageInfo&, void* pixels, size_t rowBytes, 50 void (*releaseProc)(void* pixels, void* context), 51 void* context, const SkSurfaceProps* = nullptr); 52 53 /** 54 * Return a new surface, with the memory for the pixels automatically allocated but respecting 55 * the specified rowBytes. If rowBytes==0, then a default value will be chosen. If a non-zero 56 * rowBytes is specified, then any images snapped off of this surface (via makeImageSnapshot()) 57 * are guaranteed to have the same rowBytes. 58 * 59 * If the requested alpha type is not opaque, then the surface's pixel memory will be 60 * zero-initialized. If it is opaque, then it will be left uninitialized, and the caller is 61 * responsible for initially clearing the surface. 62 * 63 * If the requested surface cannot be created, or the request is not a 64 * supported configuration, NULL will be returned. 65 */ 66 static sk_sp<SkSurface> MakeRaster(const SkImageInfo&, size_t rowBytes, const SkSurfaceProps*); 67 68 /** 69 * Allocate a new surface, automatically computing the rowBytes. 70 */ 71 static sk_sp<SkSurface> MakeRaster(const SkImageInfo& info, 72 const SkSurfaceProps* props = nullptr) { 73 return MakeRaster(info, 0, props); 74 } 75 76 /** 77 * Helper version of NewRaster. It creates a SkImageInfo with the 78 * specified width and height, and populates the rest of info to match 79 * pixels in SkPMColor format. 80 */ 81 static sk_sp<SkSurface> MakeRasterN32Premul(int width, int height, 82 const SkSurfaceProps* props = nullptr) { 83 return MakeRaster(SkImageInfo::MakeN32Premul(width, height), props); 84 } 85 86 /** 87 * Used to wrap a pre-existing backend 3D API texture as a SkSurface. The kRenderTarget flag 88 * must be set on GrBackendTextureDesc for this to succeed. Skia will not assume ownership 89 * of the texture and the client must ensure the texture is valid for the lifetime of the 90 * SkSurface. 91 */ 92 static sk_sp<SkSurface> MakeFromBackendTexture(GrContext*, const GrBackendTextureDesc&, 93 sk_sp<SkColorSpace>, const SkSurfaceProps*); 94 95 /** 96 * Used to wrap a pre-existing 3D API rendering target as a SkSurface. Skia will not assume 97 * ownership of the render target and the client must ensure the render target is valid for the 98 * lifetime of the SkSurface. 99 */ 100 static sk_sp<SkSurface> MakeFromBackendRenderTarget(GrContext*, 101 const GrBackendRenderTargetDesc&, 102 sk_sp<SkColorSpace>, 103 const SkSurfaceProps*); 104 105 /** 106 * Used to wrap a pre-existing 3D API texture as a SkSurface. Skia will treat the texture as 107 * a rendering target only, but unlike NewFromBackendRenderTarget, Skia will manage and own 108 * the associated render target objects (but not the provided texture). The kRenderTarget flag 109 * must be set on GrBackendTextureDesc for this to succeed. Skia will not assume ownership 110 * of the texture and the client must ensure the texture is valid for the lifetime of the 111 * SkSurface. 112 */ 113 static sk_sp<SkSurface> MakeFromBackendTextureAsRenderTarget( 114 GrContext*, const GrBackendTextureDesc&, sk_sp<SkColorSpace>, const SkSurfaceProps*); 115 116 /** 117 * Legacy versions of the above factories, without color space support. These create "legacy" 118 * surfaces that operate without gamma correction or color management. 119 */ MakeFromBackendTexture(GrContext * ctx,const GrBackendTextureDesc & desc,const SkSurfaceProps * props)120 static sk_sp<SkSurface> MakeFromBackendTexture(GrContext* ctx, const GrBackendTextureDesc& desc, 121 const SkSurfaceProps* props) { 122 return MakeFromBackendTexture(ctx, desc, nullptr, props); 123 } 124 MakeFromBackendRenderTarget(GrContext * ctx,const GrBackendRenderTargetDesc & desc,const SkSurfaceProps * props)125 static sk_sp<SkSurface> MakeFromBackendRenderTarget(GrContext* ctx, 126 const GrBackendRenderTargetDesc& desc, 127 const SkSurfaceProps* props) { 128 return MakeFromBackendRenderTarget(ctx, desc, nullptr, props); 129 } 130 MakeFromBackendTextureAsRenderTarget(GrContext * ctx,const GrBackendTextureDesc & desc,const SkSurfaceProps * props)131 static sk_sp<SkSurface> MakeFromBackendTextureAsRenderTarget( 132 GrContext* ctx, const GrBackendTextureDesc& desc, const SkSurfaceProps* props) { 133 return MakeFromBackendTextureAsRenderTarget(ctx, desc, nullptr, props); 134 } 135 136 137 /** 138 * Return a new surface whose contents will be drawn to an offscreen 139 * render target, allocated by the surface. 140 */ 141 static sk_sp<SkSurface> MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&, 142 int sampleCount, GrSurfaceOrigin, 143 const SkSurfaceProps*); 144 MakeRenderTarget(GrContext * context,SkBudgeted budgeted,const SkImageInfo & info,int sampleCount,const SkSurfaceProps * props)145 static sk_sp<SkSurface> MakeRenderTarget(GrContext* context, SkBudgeted budgeted, 146 const SkImageInfo& info, int sampleCount, 147 const SkSurfaceProps* props) { 148 return MakeRenderTarget(context, budgeted, info, sampleCount, 149 kBottomLeft_GrSurfaceOrigin, props); 150 } 151 MakeRenderTarget(GrContext * gr,SkBudgeted b,const SkImageInfo & info)152 static sk_sp<SkSurface> MakeRenderTarget(GrContext* gr, SkBudgeted b, const SkImageInfo& info) { 153 return MakeRenderTarget(gr, b, info, 0, kBottomLeft_GrSurfaceOrigin, nullptr); 154 } 155 156 #ifdef SK_SUPPORT_LEGACY_NEW_SURFACE_API 157 static SkSurface* NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes, 158 const SkSurfaceProps* props = NULL) { 159 return MakeRasterDirect(info, pixels, rowBytes, props).release(); 160 } 161 static SkSurface* NewRasterDirectReleaseProc(const SkImageInfo& info, void* pixels, 162 size_t rowBytes, 163 void (*releaseProc)(void* pixels, void* context), 164 void* context, const SkSurfaceProps* props = NULL){ 165 return MakeRasterDirectReleaseProc(info, pixels, rowBytes, releaseProc, context, 166 props).release(); 167 } NewRaster(const SkImageInfo & info,size_t rowBytes,const SkSurfaceProps * props)168 static SkSurface* NewRaster(const SkImageInfo& info, size_t rowBytes, 169 const SkSurfaceProps* props) { 170 return MakeRaster(info, rowBytes, props).release(); 171 } 172 static SkSurface* NewRaster(const SkImageInfo& info, const SkSurfaceProps* props = NULL) { 173 return MakeRaster(info, props).release(); 174 } 175 static SkSurface* NewRasterN32Premul(int width, int height, 176 const SkSurfaceProps* props = NULL) { 177 return NewRaster(SkImageInfo::MakeN32Premul(width, height), props); 178 } NewFromBackendTexture(GrContext * ctx,const GrBackendTextureDesc & desc,const SkSurfaceProps * props)179 static SkSurface* NewFromBackendTexture(GrContext* ctx, const GrBackendTextureDesc& desc, 180 const SkSurfaceProps* props) { 181 return MakeFromBackendTexture(ctx, desc, props).release(); 182 } 183 // Legacy alias NewWrappedRenderTarget(GrContext * ctx,const GrBackendTextureDesc & desc,const SkSurfaceProps * props)184 static SkSurface* NewWrappedRenderTarget(GrContext* ctx, const GrBackendTextureDesc& desc, 185 const SkSurfaceProps* props) { 186 return NewFromBackendTexture(ctx, desc, props); 187 } NewFromBackendRenderTarget(GrContext * ctx,const GrBackendRenderTargetDesc & d,const SkSurfaceProps * props)188 static SkSurface* NewFromBackendRenderTarget(GrContext* ctx, const GrBackendRenderTargetDesc& d, 189 const SkSurfaceProps* props) { 190 return MakeFromBackendRenderTarget(ctx, d, props).release(); 191 } NewFromBackendTextureAsRenderTarget(GrContext * ctx,const GrBackendTextureDesc & desc,const SkSurfaceProps * props)192 static SkSurface* NewFromBackendTextureAsRenderTarget(GrContext* ctx, 193 const GrBackendTextureDesc& desc, 194 const SkSurfaceProps* props) { 195 return MakeFromBackendTextureAsRenderTarget(ctx, desc, props).release(); 196 } 197 static SkSurface* NewRenderTarget(GrContext* ctx, SkBudgeted b, const SkImageInfo& info, 198 int sampleCount, const SkSurfaceProps* props = NULL) { 199 return MakeRenderTarget(ctx, b, info, sampleCount, props).release(); 200 } NewRenderTarget(GrContext * gr,SkBudgeted b,const SkImageInfo & info)201 static SkSurface* NewRenderTarget(GrContext* gr, SkBudgeted b, const SkImageInfo& info) { 202 return NewRenderTarget(gr, b, info, 0); 203 } newSurface(const SkImageInfo & info)204 SkSurface* newSurface(const SkImageInfo& info) { return this->makeSurface(info).release(); } 205 #endif 206 width()207 int width() const { return fWidth; } height()208 int height() const { return fHeight; } 209 210 /** 211 * Returns a unique non-zero, unique value identifying the content of this 212 * surface. Each time the content is changed changed, either by drawing 213 * into this surface, or explicitly calling notifyContentChanged()) this 214 * method will return a new value. 215 * 216 * If this surface is empty (i.e. has a zero-dimention), this will return 217 * 0. 218 */ 219 uint32_t generationID(); 220 221 /** 222 * Modes that can be passed to notifyContentWillChange 223 */ 224 enum ContentChangeMode { 225 /** 226 * Use this mode if it is known that the upcoming content changes will 227 * clear or overwrite prior contents, thus making them discardable. 228 */ 229 kDiscard_ContentChangeMode, 230 /** 231 * Use this mode if prior surface contents need to be preserved or 232 * if in doubt. 233 */ 234 kRetain_ContentChangeMode, 235 }; 236 237 /** 238 * Call this if the contents are about to change. This will (lazily) force a new 239 * value to be returned from generationID() when it is called next. 240 * 241 * CAN WE DEPRECATE THIS? 242 */ 243 void notifyContentWillChange(ContentChangeMode mode); 244 245 enum BackendHandleAccess { 246 kFlushRead_BackendHandleAccess, //!< caller may read from the backend object 247 kFlushWrite_BackendHandleAccess, //!< caller may write to the backend object 248 kDiscardWrite_BackendHandleAccess, //!< caller must over-write the entire backend object 249 }; 250 251 /* 252 * These are legacy aliases which will be removed soon 253 */ 254 static const BackendHandleAccess kFlushRead_TextureHandleAccess = 255 kFlushRead_BackendHandleAccess; 256 static const BackendHandleAccess kFlushWrite_TextureHandleAccess = 257 kFlushWrite_BackendHandleAccess; 258 static const BackendHandleAccess kDiscardWrite_TextureHandleAccess = 259 kDiscardWrite_BackendHandleAccess; 260 261 262 /** 263 * Retrieves the backend API handle of the texture used by this surface, or 0 if the surface 264 * is not backed by a GPU texture. 265 * 266 * The returned texture-handle is only valid until the next draw-call into the surface, 267 * or the surface is deleted. 268 */ 269 GrBackendObject getTextureHandle(BackendHandleAccess); 270 271 /** 272 * Retrieves the backend API handle of the RenderTarget backing this surface. Callers must 273 * ensure this function returns 'true' or else the GrBackendObject will be invalid 274 * 275 * In OpenGL this will return the FramebufferObject ID. 276 */ 277 bool getRenderTargetHandle(GrBackendObject*, BackendHandleAccess); 278 279 /** 280 * Return a canvas that will draw into this surface. This will always 281 * return the same canvas for a given surface, and is manged/owned by the 282 * surface. It should not be used when its parent surface has gone out of 283 * scope. 284 */ 285 SkCanvas* getCanvas(); 286 287 /** 288 * Return a new surface that is "compatible" with this one, in that it will 289 * efficiently be able to be drawn into this surface. Typical calling 290 * pattern: 291 * 292 * SkSurface* A = SkSurface::New...(); 293 * SkCanvas* canvasA = surfaceA->newCanvas(); 294 * ... 295 * SkSurface* surfaceB = surfaceA->newSurface(...); 296 * SkCanvas* canvasB = surfaceB->newCanvas(); 297 * ... // draw using canvasB 298 * canvasA->drawSurface(surfaceB); // <--- this will always be optimal! 299 */ 300 sk_sp<SkSurface> makeSurface(const SkImageInfo&); 301 302 /** 303 * Returns an image of the current state of the surface pixels up to this 304 * point. Subsequent changes to the surface (by drawing into its canvas) 305 * will not be reflected in this image. If a copy must be made the Budgeted 306 * parameter controls whether it counts against the resource budget 307 * (currently for the gpu backend only). 308 */ 309 sk_sp<SkImage> makeImageSnapshot(SkBudgeted = SkBudgeted::kYes); 310 311 /** 312 * In rare instances a client may want a unique copy of the SkSurface's contents in an image 313 * snapshot. This enum can be used to enforce that the image snapshot's backing store is not 314 * shared with another image snapshot or the surface's backing store. This is generally more 315 * expensive. This was added for Chromium bug 585250. 316 */ 317 enum ForceUnique { 318 kNo_ForceUnique, 319 kYes_ForceUnique 320 }; 321 sk_sp<SkImage> makeImageSnapshot(SkBudgeted, ForceUnique); 322 323 #ifdef SK_SUPPORT_LEGACY_IMAGEFACTORY 324 SkImage* newImageSnapshot(SkBudgeted budgeted = SkBudgeted::kYes) { 325 return this->makeImageSnapshot(budgeted).release(); 326 } newImageSnapshot(SkBudgeted budgeted,ForceUnique force)327 SkImage* newImageSnapshot(SkBudgeted budgeted, ForceUnique force) { 328 return this->makeImageSnapshot(budgeted, force).release(); 329 } 330 #endif 331 332 /** 333 * Though the caller could get a snapshot image explicitly, and draw that, 334 * it seems that directly drawing a surface into another canvas might be 335 * a common pattern, and that we could possibly be more efficient, since 336 * we'd know that the "snapshot" need only live until we've handed it off 337 * to the canvas. 338 */ 339 void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*); 340 341 /** 342 * If the surface has direct access to its pixels (i.e. they are in local 343 * RAM) return true, and if not null, set the pixmap parameter to point to the information 344 * about the surface's pixels. The pixel address in the pixmap is only valid while 345 * the surface object is in scope, and no API call is made on the surface 346 * or its canvas. 347 * 348 * On failure, returns false and the pixmap parameter is ignored. 349 */ 350 bool peekPixels(SkPixmap*); 351 352 #ifdef SK_SUPPORT_LEGACY_PEEKPIXELS_PARMS 353 const void* peekPixels(SkImageInfo* info, size_t* rowBytes); 354 #endif 355 356 /** 357 * Copy the pixels from the surface into the specified buffer (pixels + rowBytes), 358 * converting them into the requested format (dstInfo). The surface pixels are read 359 * starting at the specified (srcX,srcY) location. 360 * 361 * The specified ImageInfo and (srcX,srcY) offset specifies a source rectangle 362 * 363 * srcR.setXYWH(srcX, srcY, dstInfo.width(), dstInfo.height()); 364 * 365 * srcR is intersected with the bounds of the base-layer. If this intersection is not empty, 366 * then we have two sets of pixels (of equal size). Replace the dst pixels with the 367 * corresponding src pixels, performing any colortype/alphatype transformations needed 368 * (in the case where the src and dst have different colortypes or alphatypes). 369 * 370 * This call can fail, returning false, for several reasons: 371 * - If srcR does not intersect the surface bounds. 372 * - If the requested colortype/alphatype cannot be converted from the surface's types. 373 */ 374 bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, 375 int srcX, int srcY); 376 props()377 const SkSurfaceProps& props() const { return fProps; } 378 379 /** 380 * Issue any pending surface IO to the current backend 3D API and resolve any surface MSAA. 381 */ 382 void prepareForExternalIO(); 383 384 protected: 385 SkSurface(int width, int height, const SkSurfaceProps*); 386 SkSurface(const SkImageInfo&, const SkSurfaceProps*); 387 388 // called by subclass if their contents have changed dirtyGenerationID()389 void dirtyGenerationID() { 390 fGenerationID = 0; 391 } 392 393 private: 394 const SkSurfaceProps fProps; 395 const int fWidth; 396 const int fHeight; 397 uint32_t fGenerationID; 398 399 typedef SkRefCnt INHERITED; 400 }; 401 402 #endif 403