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