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 *
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 */
31class SK_API SkSurface : public SkRefCnt {
32public:
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
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
111    static SkSurface* NewRenderTarget(GrContext* gr, Budgeted b, const SkImageInfo& info) {
112        return NewRenderTarget(gr, b, info, 0, NULL);
113    }
114
115    int width() const { return fWidth; }
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
225    const SkSurfaceProps& props() const { return fProps; }
226
227protected:
228    SkSurface(int width, int height, const SkSurfaceProps*);
229    SkSurface(const SkImageInfo&, const SkSurfaceProps*);
230
231    // called by subclass if their contents have changed
232    void dirtyGenerationID() {
233        fGenerationID = 0;
234    }
235
236private:
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