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 SK_DECLARE_INST_COUNT(SkSurface) 34 35 /** 36 * Indicates whether a new surface or image should count against a cache budget. Currently this 37 * is only used by the GPU backend (sw-raster surfaces and images are never counted against the 38 * resource cache budget.) 39 */ 40 enum Budgeted { 41 /** The surface or image does not count against the cache budget. */ 42 kNo_Budgeted, 43 /** The surface or image counts against the cache budget. */ 44 kYes_Budgeted 45 }; 46 47 /** 48 * Create a new surface, using the specified pixels/rowbytes as its 49 * backend. 50 * 51 * If the requested surface cannot be created, or the request is not a 52 * supported configuration, NULL will be returned. 53 */ 54 static SkSurface* NewRasterDirect(const SkImageInfo&, void* pixels, size_t rowBytes, 55 const SkSurfaceProps* = NULL); 56 57 /** 58 * The same as NewRasterDirect, but also accepts a call-back routine, which is invoked 59 * when the surface is deleted, and is passed the pixel memory and the specified context. 60 */ 61 static SkSurface* NewRasterDirectReleaseProc(const SkImageInfo&, void* pixels, size_t rowBytes, 62 void (*releaseProc)(void* pixels, void* context), 63 void* context, const SkSurfaceProps* = NULL); 64 65 /** 66 * Return a new surface, with the memory for the pixels automatically 67 * allocated. 68 * 69 * If the requested surface cannot be created, or the request is not a 70 * supported configuration, NULL will be returned. 71 */ 72 static SkSurface* NewRaster(const SkImageInfo&, const SkSurfaceProps* = NULL); 73 74 /** 75 * Helper version of NewRaster. It creates a SkImageInfo with the 76 * specified width and height, and populates the rest of info to match 77 * pixels in SkPMColor format. 78 */ 79 #ifdef SK_SUPPORT_LEGACY_NewRasterPMColor 80 static SkSurface* NewRasterPMColor(int width, int height, const SkSurfaceProps* props = NULL) { 81 return NewRaster(SkImageInfo::MakeN32Premul(width, height), props); 82 } 83 #endif 84 static SkSurface* NewRasterN32Premul(int width, int height, const SkSurfaceProps* props = NULL) { 85 return NewRaster(SkImageInfo::MakeN32Premul(width, height), props); 86 } 87 88 /** 89 * Return a new surface using the specified render target. 90 */ 91 static SkSurface* NewRenderTargetDirect(GrRenderTarget*, const SkSurfaceProps*); 92 NewRenderTargetDirect(GrRenderTarget * target)93 static SkSurface* NewRenderTargetDirect(GrRenderTarget* target) { 94 return NewRenderTargetDirect(target, NULL); 95 } 96 97 /** 98 * Used to wrap a pre-existing backend 3D API texture in a SkSurface. The kRenderTarget flag 99 * must be set on GrBackendTextureDesc for this to succeed. 100 */ 101 static SkSurface* NewWrappedRenderTarget(GrContext*, GrBackendTextureDesc, 102 const SkSurfaceProps*); 103 104 /** 105 * Return a new surface whose contents will be drawn to an offscreen 106 * render target, allocated by the surface. 107 */ 108 static SkSurface* NewRenderTarget(GrContext*, Budgeted, const SkImageInfo&, int sampleCount, 109 const SkSurfaceProps* = NULL); 110 NewRenderTarget(GrContext * gr,Budgeted b,const SkImageInfo & info)111 static SkSurface* NewRenderTarget(GrContext* gr, Budgeted b, const SkImageInfo& info) { 112 return NewRenderTarget(gr, b, info, 0, NULL); 113 } 114 width()115 int width() const { return fWidth; } height()116 int height() const { return fHeight; } 117 118 /** 119 * Returns a unique non-zero, unique value identifying the content of this 120 * surface. Each time the content is changed changed, either by drawing 121 * into this surface, or explicitly calling notifyContentChanged()) this 122 * method will return a new value. 123 * 124 * If this surface is empty (i.e. has a zero-dimention), this will return 125 * 0. 126 */ 127 uint32_t generationID(); 128 129 /** 130 * Modes that can be passed to notifyContentWillChange 131 */ 132 enum ContentChangeMode { 133 /** 134 * Use this mode if it is known that the upcoming content changes will 135 * clear or overwrite prior contents, thus making them discardable. 136 */ 137 kDiscard_ContentChangeMode, 138 /** 139 * Use this mode if prior surface contents need to be preserved or 140 * if in doubt. 141 */ 142 kRetain_ContentChangeMode, 143 }; 144 145 /** 146 * Call this if the contents are about to change. This will (lazily) force a new 147 * value to be returned from generationID() when it is called next. 148 */ 149 void notifyContentWillChange(ContentChangeMode mode); 150 151 /** 152 * Return a canvas that will draw into this surface. This will always 153 * return the same canvas for a given surface, and is manged/owned by the 154 * surface. It should not be used when its parent surface has gone out of 155 * scope. 156 */ 157 SkCanvas* getCanvas(); 158 159 /** 160 * Return a new surface that is "compatible" with this one, in that it will 161 * efficiently be able to be drawn into this surface. Typical calling 162 * pattern: 163 * 164 * SkSurface* A = SkSurface::New...(); 165 * SkCanvas* canvasA = surfaceA->newCanvas(); 166 * ... 167 * SkSurface* surfaceB = surfaceA->newSurface(...); 168 * SkCanvas* canvasB = surfaceB->newCanvas(); 169 * ... // draw using canvasB 170 * canvasA->drawSurface(surfaceB); // <--- this will always be optimal! 171 */ 172 SkSurface* newSurface(const SkImageInfo&); 173 174 /** 175 * Returns an image of the current state of the surface pixels up to this 176 * point. Subsequent changes to the surface (by drawing into its canvas) 177 * will not be reflected in this image. If a copy must be made the Budgeted 178 * parameter controls whether it counts against the resource budget 179 * (currently for the gpu backend only). 180 */ 181 SkImage* newImageSnapshot(Budgeted = kYes_Budgeted); 182 183 /** 184 * Though the caller could get a snapshot image explicitly, and draw that, 185 * it seems that directly drawing a surface into another canvas might be 186 * a common pattern, and that we could possibly be more efficient, since 187 * we'd know that the "snapshot" need only live until we've handed it off 188 * to the canvas. 189 */ 190 void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*); 191 192 /** 193 * If the surface has direct access to its pixels (i.e. they are in local 194 * RAM) return the const-address of those pixels, and if not null, return 195 * the ImageInfo and rowBytes. The returned address is only valid while 196 * the surface object is in scope, and no API call is made on the surface 197 * or its canvas. 198 * 199 * On failure, returns NULL and the info and rowBytes parameters are 200 * ignored. 201 */ 202 const void* peekPixels(SkImageInfo* info, size_t* rowBytes); 203 204 /** 205 * Copy the pixels from the surface into the specified buffer (pixels + rowBytes), 206 * converting them into the requested format (dstInfo). The surface pixels are read 207 * starting at the specified (srcX,srcY) location. 208 * 209 * The specified ImageInfo and (srcX,srcY) offset specifies a source rectangle 210 * 211 * srcR.setXYWH(srcX, srcY, dstInfo.width(), dstInfo.height()); 212 * 213 * srcR is intersected with the bounds of the base-layer. If this intersection is not empty, 214 * then we have two sets of pixels (of equal size). Replace the dst pixels with the 215 * corresponding src pixels, performing any colortype/alphatype transformations needed 216 * (in the case where the src and dst have different colortypes or alphatypes). 217 * 218 * This call can fail, returning false, for several reasons: 219 * - If srcR does not intersect the surface bounds. 220 * - If the requested colortype/alphatype cannot be converted from the surface's types. 221 */ 222 bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, 223 int srcX, int srcY); 224 props()225 const SkSurfaceProps& props() const { return fProps; } 226 227 protected: 228 SkSurface(int width, int height, const SkSurfaceProps*); 229 SkSurface(const SkImageInfo&, const SkSurfaceProps*); 230 231 // called by subclass if their contents have changed dirtyGenerationID()232 void dirtyGenerationID() { 233 fGenerationID = 0; 234 } 235 236 private: 237 const SkSurfaceProps fProps; 238 const int fWidth; 239 const int fHeight; 240 uint32_t fGenerationID; 241 242 typedef SkRefCnt INHERITED; 243 }; 244 245 #endif 246