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
15class SkCanvas;
16class SkPaint;
17class GrContext;
18class 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 */
28class SK_API SkSurface : public SkRefCnt {
29public:
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
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
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
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
128    int width() const { return fWidth; }
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
215    const SkSurfaceProps& props() const { return fProps; }
216
217protected:
218    SkSurface(int width, int height, const SkSurfaceProps*);
219    SkSurface(const SkImageInfo&, const SkSurfaceProps*);
220
221    // called by subclass if their contents have changed
222    void dirtyGenerationID() {
223        fGenerationID = 0;
224    }
225
226private:
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