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