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     static const SkBudgeted kYes_Budgeted = SkBudgeted::kYes;
34     static const SkBudgeted kNo_Budgeted = SkBudgeted::kNo;
35     using Budgeted = SkBudgeted;
36 
37     /**
38      *  Create a new surface, using the specified pixels/rowbytes as its
39      *  backend.
40      *
41      *  If the requested surface cannot be created, or the request is not a
42      *  supported configuration, NULL will be returned.
43      */
44     static SkSurface* NewRasterDirect(const SkImageInfo&, void* pixels, size_t rowBytes,
45                                       const SkSurfaceProps* = NULL);
46 
47     /**
48      *  The same as NewRasterDirect, but also accepts a call-back routine, which is invoked
49      *  when the surface is deleted, and is passed the pixel memory and the specified context.
50      */
51     static SkSurface* NewRasterDirectReleaseProc(const SkImageInfo&, void* pixels, size_t rowBytes,
52                                                  void (*releaseProc)(void* pixels, void* context),
53                                                  void* context, const SkSurfaceProps* = NULL);
54 
55     /**
56      *  Return a new surface, with the memory for the pixels automatically allocated, but respecting
57      *  the specified rowBytes. If rowBytes==0, then a default value will be chosen. If a non-zero
58      *  rowBytes is specified, then any images snapped off of this surface (via newImageSnapshot())
59      *  are guaranteed to have the same rowBytes.
60      *
61      *  If the requested surface cannot be created, or the request is not a
62      *  supported configuration, NULL will be returned.
63      */
64     static SkSurface* NewRaster(const SkImageInfo&, size_t rowBytes, const SkSurfaceProps*);
65 
66     /**
67      *  Allocate a new surface, automatically computing the rowBytes.
68      */
69     static SkSurface* NewRaster(const SkImageInfo&, const SkSurfaceProps* = NULL);
70 
71     /**
72      *  Helper version of NewRaster. It creates a SkImageInfo with the
73      *  specified width and height, and populates the rest of info to match
74      *  pixels in SkPMColor format.
75      */
76     static SkSurface* NewRasterN32Premul(int width, int height, const SkSurfaceProps* props = NULL) {
77         return NewRaster(SkImageInfo::MakeN32Premul(width, height), props);
78     }
79 
80     /**
81      *  Return a new surface using the specified render target.
82      */
83     static SkSurface* NewRenderTargetDirect(GrRenderTarget*, const SkSurfaceProps*);
84 
NewRenderTargetDirect(GrRenderTarget * target)85     static SkSurface* NewRenderTargetDirect(GrRenderTarget* target) {
86         return NewRenderTargetDirect(target, NULL);
87     }
88 
89     /**
90      *  Used to wrap a pre-existing backend 3D API texture as a SkSurface. The kRenderTarget flag
91      *  must be set on GrBackendTextureDesc for this to succeed. Skia will not assume ownership
92      *  of the texture and the client must ensure the texture is valid for the lifetime of the
93      *  SkSurface.
94      */
95     static SkSurface* NewFromBackendTexture(GrContext*, const GrBackendTextureDesc&,
96                                             const SkSurfaceProps*);
97     // Legacy alias
NewWrappedRenderTarget(GrContext * ctx,const GrBackendTextureDesc & desc,const SkSurfaceProps * props)98     static SkSurface* NewWrappedRenderTarget(GrContext* ctx, const GrBackendTextureDesc& desc,
99                                              const SkSurfaceProps* props) {
100         return NewFromBackendTexture(ctx, desc, props);
101     }
102 
103     /**
104      *  Used to wrap a pre-existing 3D API rendering target as a SkSurface. Skia will not assume
105      *  ownership of the render target and the client must ensure the render target is valid for the
106      *  lifetime of the SkSurface.
107      */
108     static SkSurface* NewFromBackendRenderTarget(GrContext*, const GrBackendRenderTargetDesc&,
109                                                  const SkSurfaceProps*);
110 
111     /**
112      *  Used to wrap a pre-existing 3D API texture as a SkSurface. Skia will treat the texture as
113      *  a rendering target only, but unlike NewFromBackendRenderTarget, Skia will manage and own
114      *  the associated render target objects (but not the provided texture). The kRenderTarget flag
115      *  must be set on GrBackendTextureDesc for this to succeed. Skia will not assume ownership
116      *  of the texture and the client must ensure the texture is valid for the lifetime of the
117      *  SkSurface.
118      */
119     static SkSurface* NewFromBackendTextureAsRenderTarget(
120             GrContext*, const GrBackendTextureDesc&, const SkSurfaceProps*);
121 
122     /**
123      *  Return a new surface whose contents will be drawn to an offscreen
124      *  render target, allocated by the surface.
125      *
126      *  The GrTextureStorageAllocator will be reused if SkImage snapshots create
127      *  additional textures.
128      */
129     static SkSurface* NewRenderTarget(
130             GrContext*, SkBudgeted, const SkImageInfo&, int sampleCount,
131             const SkSurfaceProps* = NULL, GrTextureStorageAllocator = GrTextureStorageAllocator());
132 
NewRenderTarget(GrContext * gr,SkBudgeted b,const SkImageInfo & info)133     static SkSurface* NewRenderTarget(GrContext* gr, SkBudgeted b, const SkImageInfo& info) {
134         return NewRenderTarget(gr, b, info, 0);
135     }
136 
width()137     int width() const { return fWidth; }
height()138     int height() const { return fHeight; }
139 
140     /**
141      *  Returns a unique non-zero, unique value identifying the content of this
142      *  surface. Each time the content is changed changed, either by drawing
143      *  into this surface, or explicitly calling notifyContentChanged()) this
144      *  method will return a new value.
145      *
146      *  If this surface is empty (i.e. has a zero-dimention), this will return
147      *  0.
148      */
149     uint32_t generationID();
150 
151     /**
152      *  Modes that can be passed to notifyContentWillChange
153      */
154     enum ContentChangeMode {
155         /**
156          *  Use this mode if it is known that the upcoming content changes will
157          *  clear or overwrite prior contents, thus making them discardable.
158          */
159         kDiscard_ContentChangeMode,
160         /**
161          *  Use this mode if prior surface contents need to be preserved or
162          *  if in doubt.
163          */
164         kRetain_ContentChangeMode,
165     };
166 
167     /**
168      *  Call this if the contents are about to change. This will (lazily) force a new
169      *  value to be returned from generationID() when it is called next.
170      *
171      *  CAN WE DEPRECATE THIS?
172      */
173     void notifyContentWillChange(ContentChangeMode mode);
174 
175     enum BackendHandleAccess {
176         kFlushRead_BackendHandleAccess,     //!< caller may read from the backend object
177         kFlushWrite_BackendHandleAccess,    //!< caller may write to the backend object
178         kDiscardWrite_BackendHandleAccess,  //!< caller must over-write the entire backend object
179     };
180 
181     /*
182      * These are legacy aliases which will be removed soon
183      */
184     static const BackendHandleAccess kFlushRead_TextureHandleAccess =
185             kFlushRead_BackendHandleAccess;
186     static const BackendHandleAccess kFlushWrite_TextureHandleAccess =
187             kFlushWrite_BackendHandleAccess;
188     static const BackendHandleAccess kDiscardWrite_TextureHandleAccess =
189             kDiscardWrite_BackendHandleAccess;
190 
191 
192     /**
193      *  Retrieves the backend API handle of the texture used by this surface, or 0 if the surface
194      *  is not backed by a GPU texture.
195      *
196      *  The returned texture-handle is only valid until the next draw-call into the surface,
197      *  or the surface is deleted.
198      */
199     GrBackendObject getTextureHandle(BackendHandleAccess);
200 
201     /**
202      *  Retrieves the backend API handle of the RenderTarget backing this surface.  Callers must
203      *  ensure this function returns 'true' or else the GrBackendObject will be invalid
204      *
205      *  In OpenGL this will return the FramebufferObject ID.
206      */
207     bool getRenderTargetHandle(GrBackendObject*, BackendHandleAccess);
208 
209     /**
210      *  Return a canvas that will draw into this surface. This will always
211      *  return the same canvas for a given surface, and is manged/owned by the
212      *  surface. It should not be used when its parent surface has gone out of
213      *  scope.
214      */
215     SkCanvas* getCanvas();
216 
217     /**
218      *  Return a new surface that is "compatible" with this one, in that it will
219      *  efficiently be able to be drawn into this surface. Typical calling
220      *  pattern:
221      *
222      *  SkSurface* A = SkSurface::New...();
223      *  SkCanvas* canvasA = surfaceA->newCanvas();
224      *  ...
225      *  SkSurface* surfaceB = surfaceA->newSurface(...);
226      *  SkCanvas* canvasB = surfaceB->newCanvas();
227      *  ... // draw using canvasB
228      *  canvasA->drawSurface(surfaceB); // <--- this will always be optimal!
229      */
230     SkSurface* newSurface(const SkImageInfo&);
231 
232     /**
233      *  Returns an image of the current state of the surface pixels up to this
234      *  point. Subsequent changes to the surface (by drawing into its canvas)
235      *  will not be reflected in this image. If a copy must be made the Budgeted
236      *  parameter controls whether it counts against the resource budget
237      *  (currently for the gpu backend only).
238      */
239     SkImage* newImageSnapshot(SkBudgeted = SkBudgeted::kYes);
240 
241     /**
242      * In rare instances a client may want a unique copy of the SkSurface's contents in an image
243      * snapshot. This enum can be used to enforce that the image snapshot's backing store is not
244      * shared with another image snapshot or the surface's backing store. This is generally more
245      * expensive. This was added for Chromium bug 585250.
246      */
247     enum ForceUnique {
248         kNo_ForceUnique,
249         kYes_ForceUnique
250     };
251     SkImage* newImageSnapshot(SkBudgeted, ForceUnique);
252 
253     /**
254      *  Though the caller could get a snapshot image explicitly, and draw that,
255      *  it seems that directly drawing a surface into another canvas might be
256      *  a common pattern, and that we could possibly be more efficient, since
257      *  we'd know that the "snapshot" need only live until we've handed it off
258      *  to the canvas.
259      */
260     void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*);
261 
262     /**
263      *  If the surface has direct access to its pixels (i.e. they are in local
264      *  RAM) return the const-address of those pixels, and if not null, return
265      *  the ImageInfo and rowBytes. The returned address is only valid while
266      *  the surface object is in scope, and no API call is made on the surface
267      *  or its canvas.
268      *
269      *  On failure, returns NULL and the info and rowBytes parameters are
270      *  ignored.
271      */
272     const void* peekPixels(SkImageInfo* info, size_t* rowBytes);
273 
274     /**
275      *  Copy the pixels from the surface into the specified buffer (pixels + rowBytes),
276      *  converting them into the requested format (dstInfo). The surface pixels are read
277      *  starting at the specified (srcX,srcY) location.
278      *
279      *  The specified ImageInfo and (srcX,srcY) offset specifies a source rectangle
280      *
281      *      srcR.setXYWH(srcX, srcY, dstInfo.width(), dstInfo.height());
282      *
283      *  srcR is intersected with the bounds of the base-layer. If this intersection is not empty,
284      *  then we have two sets of pixels (of equal size). Replace the dst pixels with the
285      *  corresponding src pixels, performing any colortype/alphatype transformations needed
286      *  (in the case where the src and dst have different colortypes or alphatypes).
287      *
288      *  This call can fail, returning false, for several reasons:
289      *  - If srcR does not intersect the surface bounds.
290      *  - If the requested colortype/alphatype cannot be converted from the surface's types.
291      */
292     bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
293                     int srcX, int srcY);
294 
props()295     const SkSurfaceProps& props() const { return fProps; }
296 
297     /**
298      * Issue any pending surface IO to the current backend 3D API and resolve any surface MSAA.
299      */
300     void prepareForExternalIO();
301 
302 protected:
303     SkSurface(int width, int height, const SkSurfaceProps*);
304     SkSurface(const SkImageInfo&, const SkSurfaceProps*);
305 
306     // called by subclass if their contents have changed
dirtyGenerationID()307     void dirtyGenerationID() {
308         fGenerationID = 0;
309     }
310 
311 private:
312     const SkSurfaceProps fProps;
313     const int            fWidth;
314     const int            fHeight;
315     uint32_t             fGenerationID;
316 
317     typedef SkRefCnt INHERITED;
318 };
319 
320 #endif
321