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