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 GrBackendRenderTarget;
18class GrBackendSemaphore;
19class GrContext;
20class 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 */
32class SK_API SkSurface : public SkRefCnt {
33public:
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     */
140    static sk_sp<SkSurface> MakeFromBackendTexture(GrContext* ctx, const GrBackendTextureDesc& desc,
141                                                   const SkSurfaceProps* props) {
142        return MakeFromBackendTexture(ctx, desc, nullptr, props);
143    }
144
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
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
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
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
185    int width() const { return fWidth; }
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
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
367protected:
368    SkSurface(int width, int height, const SkSurfaceProps*);
369    SkSurface(const SkImageInfo&, const SkSurfaceProps*);
370
371    // called by subclass if their contents have changed
372    void dirtyGenerationID() {
373        fGenerationID = 0;
374    }
375
376private:
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