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