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