• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 class SK_API SkSurface : public SkRefCnt {
29 public:
30     SK_DECLARE_INST_COUNT(SkSurface)
31 
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     static SkSurface* NewRasterDirect(const SkImageInfo&, void* pixels, size_t rowBytes,
40                                       const SkSurfaceProps* = NULL);
41 
42     /**
43      *  The same as NewRasterDirect, but also accepts a call-back routine, which is invoked
44      *  when the surface is deleted, and is passed the pixel memory and the specified context.
45      */
46     static SkSurface* NewRasterDirectReleaseProc(const SkImageInfo&, void* pixels, size_t rowBytes,
47                                                  void (*releaseProc)(void* pixels, void* context),
48                                                  void* context, const SkSurfaceProps* = NULL);
49 
50     /**
51      *  Return a new surface, with the memory for the pixels automatically
52      *  allocated.
53      *
54      *  If the requested surface cannot be created, or the request is not a
55      *  supported configuration, NULL will be returned.
56      */
57     static SkSurface* NewRaster(const SkImageInfo&, const SkSurfaceProps* = NULL);
58 
59     /**
60      *  Helper version of NewRaster. It creates a SkImageInfo with the
61      *  specified width and height, and populates the rest of info to match
62      *  pixels in SkPMColor format.
63      */
64     static SkSurface* NewRasterPMColor(int width, int height, const SkSurfaceProps* props = NULL) {
65         return NewRaster(SkImageInfo::MakeN32Premul(width, height), props);
66     }
67 
68     /**
69      *  Return a new surface using the specified render target.
70      */
71     static SkSurface* NewRenderTargetDirect(GrRenderTarget*, const SkSurfaceProps*);
72 
NewRenderTargetDirect(GrRenderTarget * target)73     static SkSurface* NewRenderTargetDirect(GrRenderTarget* target) {
74         return NewRenderTargetDirect(target, NULL);
75     }
76 
77     /**
78      *  Return a new surface whose contents will be drawn to an offscreen
79      *  render target, allocated by the surface.
80      */
81     static SkSurface* NewRenderTarget(GrContext*, const SkImageInfo&, int sampleCount,
82                                       const SkSurfaceProps* = NULL);
83 
NewRenderTarget(GrContext * gr,const SkImageInfo & info)84     static SkSurface* NewRenderTarget(GrContext* gr, const SkImageInfo& info) {
85         return NewRenderTarget(gr, info, 0, NULL);
86     }
87 
88     /**
89      *  Return a new surface whose contents will be drawn to an offscreen
90      *  render target, allocated by the surface from the scratch texture pool
91      *  managed by the GrContext. The scratch texture pool serves the purpose
92      *  of retaining textures after they are no longer in use in order to
93      *  re-use them later without having to re-allocate.  Scratch textures
94      *  should be used in cases where high turnover is expected. This allows,
95      *  for example, the copy on write to recycle a texture from a recently
96      *  released SkImage snapshot of the surface.
97      *  Note: Scratch textures count against the GrContext's cached resource
98      *  budget.
99      */
100     static SkSurface* NewScratchRenderTarget(GrContext*, const SkImageInfo&, int sampleCount,
101                                              const SkSurfaceProps* = NULL);
102 
NewScratchRenderTarget(GrContext * gr,const SkImageInfo & info)103     static SkSurface* NewScratchRenderTarget(GrContext* gr, const SkImageInfo& info) {
104         return NewScratchRenderTarget(gr, info, 0, NULL);
105     }
106 
107 #ifdef SK_SUPPORT_LEGACY_TEXTRENDERMODE
108     /**
109      *  Text rendering modes that can be passed to NewRenderTarget*
110      */
111     enum TextRenderMode {
112         /**
113          *  This will use the standard text rendering method
114          */
115         kStandard_TextRenderMode,
116         /**
117          *  This will use signed distance fields for text rendering when possible
118          */
119         kDistanceField_TextRenderMode,
120     };
121     static SkSurface* NewRenderTargetDirect(GrRenderTarget*, TextRenderMode);
122     static SkSurface* NewRenderTarget(GrContext*, const SkImageInfo&, int sampleCount,
123                                       TextRenderMode);
124     static SkSurface* NewScratchRenderTarget(GrContext*, const SkImageInfo&, int sampleCount,
125                                              TextRenderMode);
126 #endif
127 
width()128     int width() const { return fWidth; }
height()129     int height() const { return fHeight; }
130 
131     /**
132      *  Returns a unique non-zero, unique value identifying the content of this
133      *  surface. Each time the content is changed changed, either by drawing
134      *  into this surface, or explicitly calling notifyContentChanged()) this
135      *  method will return a new value.
136      *
137      *  If this surface is empty (i.e. has a zero-dimention), this will return
138      *  0.
139      */
140     uint32_t generationID();
141 
142     /**
143      *  Modes that can be passed to notifyContentWillChange
144      */
145     enum ContentChangeMode {
146         /**
147          *  Use this mode if it is known that the upcoming content changes will
148          *  clear or overwrite prior contents, thus making them discardable.
149          */
150         kDiscard_ContentChangeMode,
151         /**
152          *  Use this mode if prior surface contents need to be preserved or
153          *  if in doubt.
154          */
155         kRetain_ContentChangeMode,
156     };
157 
158     /**
159      *  Call this if the contents are about to change. This will (lazily) force a new
160      *  value to be returned from generationID() when it is called next.
161      */
162     void notifyContentWillChange(ContentChangeMode mode);
163 
164     /**
165      *  Return a canvas that will draw into this surface. This will always
166      *  return the same canvas for a given surface, and is manged/owned by the
167      *  surface. It should not be used when its parent surface has gone out of
168      *  scope.
169      */
170     SkCanvas* getCanvas();
171 
172     /**
173      *  Return a new surface that is "compatible" with this one, in that it will
174      *  efficiently be able to be drawn into this surface. Typical calling
175      *  pattern:
176      *
177      *  SkSurface* A = SkSurface::New...();
178      *  SkCanvas* canvasA = surfaceA->newCanvas();
179      *  ...
180      *  SkSurface* surfaceB = surfaceA->newSurface(...);
181      *  SkCanvas* canvasB = surfaceB->newCanvas();
182      *  ... // draw using canvasB
183      *  canvasA->drawSurface(surfaceB); // <--- this will always be optimal!
184      */
185     SkSurface* newSurface(const SkImageInfo&);
186 
187     /**
188      *  Returns an image of the current state of the surface pixels up to this
189      *  point. Subsequent changes to the surface (by drawing into its canvas)
190      *  will not be reflected in this image.
191      */
192     SkImage* newImageSnapshot();
193 
194     /**
195      *  Thought the caller could get a snapshot image explicitly, and draw that,
196      *  it seems that directly drawing a surface into another canvas might be
197      *  a common pattern, and that we could possibly be more efficient, since
198      *  we'd know that the "snapshot" need only live until we've handed it off
199      *  to the canvas.
200      */
201     void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*);
202 
203     /**
204      *  If the surface has direct access to its pixels (i.e. they are in local
205      *  RAM) return the const-address of those pixels, and if not null, return
206      *  the ImageInfo and rowBytes. The returned address is only valid while
207      *  the surface object is in scope, and no API call is made on the surface
208      *  or its canvas.
209      *
210      *  On failure, returns NULL and the info and rowBytes parameters are
211      *  ignored.
212      */
213     const void* peekPixels(SkImageInfo* info, size_t* rowBytes);
214 
props()215     const SkSurfaceProps& props() const { return fProps; }
216 
217 protected:
218     SkSurface(int width, int height, const SkSurfaceProps*);
219     SkSurface(const SkImageInfo&, const SkSurfaceProps*);
220 
221     // called by subclass if their contents have changed
dirtyGenerationID()222     void dirtyGenerationID() {
223         fGenerationID = 0;
224     }
225 
226 private:
227     const SkSurfaceProps fProps;
228     const int            fWidth;
229     const int            fHeight;
230     uint32_t             fGenerationID;
231 
232     typedef SkRefCnt INHERITED;
233 };
234 
235 #endif
236