blob: e0e60ab7fbc20f7cd7459ed4b4873ae56317a65d [file] [log] [blame]
reed@google.com889b09e2012-07-27 21:10:42 +00001/*
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"
reed3716fd02014-09-21 09:39:55 -070013#include "SkSurfaceProps.h"
14
15//#define SK_SUPPORT_LEGACY_TEXTRENDERMODE
reed@google.com889b09e2012-07-27 21:10:42 +000016
17class SkCanvas;
18class SkPaint;
reed@google.com5d4ba882012-07-31 15:45:27 +000019class GrContext;
20class GrRenderTarget;
reed@google.com889b09e2012-07-27 21:10:42 +000021
22/**
23 * SkSurface represents the backend/results of drawing to a canvas. For raster
24 * drawing, the surface will be pixels, but (for example) when drawing into
25 * a PDF or Picture canvas, the surface stores the recorded commands.
26 *
27 * To draw into a canvas, first create the appropriate type of Surface, and
28 * then request the canvas from the surface.
29 */
junov@chromium.org96447be2013-04-18 13:28:19 +000030class SK_API SkSurface : public SkRefCnt {
reed@google.com889b09e2012-07-27 21:10:42 +000031public:
reed@google.comfd875e82012-08-28 12:43:54 +000032 SK_DECLARE_INST_COUNT(SkSurface)
robertphillips@google.coma22e2112012-08-16 14:58:06 +000033
reed@google.com889b09e2012-07-27 21:10:42 +000034 /**
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 */
reed3716fd02014-09-21 09:39:55 -070041 static SkSurface* NewRasterDirect(const SkImageInfo&, void* pixels, size_t rowBytes,
42 const SkSurfaceProps* = NULL);
reed@google.com889b09e2012-07-27 21:10:42 +000043
44 /**
reed982542d2014-06-27 06:48:14 -070045 * 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 SkSurface* NewRasterDirectReleaseProc(const SkImageInfo&, void* pixels, size_t rowBytes,
49 void (*releaseProc)(void* pixels, void* context),
reed3716fd02014-09-21 09:39:55 -070050 void* context, const SkSurfaceProps* = NULL);
reed982542d2014-06-27 06:48:14 -070051
52 /**
reed@google.com889b09e2012-07-27 21:10:42 +000053 * Return a new surface, with the memory for the pixels automatically
54 * allocated.
55 *
56 * If the requested surface cannot be created, or the request is not a
57 * supported configuration, NULL will be returned.
58 */
reed3716fd02014-09-21 09:39:55 -070059 static SkSurface* NewRaster(const SkImageInfo&, const SkSurfaceProps* = NULL);
reed@google.com889b09e2012-07-27 21:10:42 +000060
61 /**
reed@google.com2bd8b812013-11-01 13:46:54 +000062 * Helper version of NewRaster. It creates a SkImageInfo with the
reed@google.com636d87a2013-09-17 20:03:43 +000063 * specified width and height, and populates the rest of info to match
64 * pixels in SkPMColor format.
65 */
reed3716fd02014-09-21 09:39:55 -070066 static SkSurface* NewRasterPMColor(int width, int height, const SkSurfaceProps* props = NULL) {
67 return NewRaster(SkImageInfo::MakeN32Premul(width, height), props);
reed@google.com636d87a2013-09-17 20:03:43 +000068 }
69
70 /**
reed@google.com5d4ba882012-07-31 15:45:27 +000071 * Return a new surface using the specified render target.
72 */
reed3716fd02014-09-21 09:39:55 -070073 static SkSurface* NewRenderTargetDirect(GrRenderTarget*, const SkSurfaceProps*);
74
75 static SkSurface* NewRenderTargetDirect(GrRenderTarget* target) {
76 return NewRenderTargetDirect(target, NULL);
77 }
78
reed@google.com5d4ba882012-07-31 15:45:27 +000079 /**
80 * Return a new surface whose contents will be drawn to an offscreen
81 * render target, allocated by the surface.
82 */
reed3716fd02014-09-21 09:39:55 -070083 static SkSurface* NewRenderTarget(GrContext*, const SkImageInfo&, int sampleCount,
84 const SkSurfaceProps* = NULL);
85
86 static SkSurface* NewRenderTarget(GrContext* gr, const SkImageInfo& info) {
87 return NewRenderTarget(gr, info, 0, NULL);
88 }
reed@google.com5d4ba882012-07-31 15:45:27 +000089
commit-bot@chromium.orgd8a57af2014-03-19 21:19:16 +000090 /**
91 * Return a new surface whose contents will be drawn to an offscreen
92 * render target, allocated by the surface from the scratch texture pool
93 * managed by the GrContext. The scratch texture pool serves the purpose
94 * of retaining textures after they are no longer in use in order to
95 * re-use them later without having to re-allocate. Scratch textures
96 * should be used in cases where high turnover is expected. This allows,
97 * for example, the copy on write to recycle a texture from a recently
98 * released SkImage snapshot of the surface.
99 * Note: Scratch textures count against the GrContext's cached resource
100 * budget.
101 */
reed3716fd02014-09-21 09:39:55 -0700102 static SkSurface* NewScratchRenderTarget(GrContext*, const SkImageInfo&, int sampleCount,
103 const SkSurfaceProps*);
104
105 static SkSurface* NewScratchRenderTarget(GrContext* gr, const SkImageInfo& info) {
106 return NewScratchRenderTarget(gr, info, 0, NULL);
107 }
108
109#ifdef SK_SUPPORT_LEGACY_TEXTRENDERMODE
110 /**
111 * Text rendering modes that can be passed to NewRenderTarget*
112 */
113 enum TextRenderMode {
114 /**
115 * This will use the standard text rendering method
116 */
117 kStandard_TextRenderMode,
118 /**
119 * This will use signed distance fields for text rendering when possible
120 */
121 kDistanceField_TextRenderMode,
122 };
123 static SkSurface* NewRenderTargetDirect(GrRenderTarget*, TextRenderMode);
124 static SkSurface* NewRenderTarget(GrContext*, const SkImageInfo&, int sampleCount,
125 TextRenderMode);
126 static SkSurface* NewScratchRenderTarget(GrContext*, const SkImageInfo&, int sampleCount,
127 TextRenderMode);
128#endif
commit-bot@chromium.orgd8a57af2014-03-19 21:19:16 +0000129
reed@google.com889b09e2012-07-27 21:10:42 +0000130 int width() const { return fWidth; }
131 int height() const { return fHeight; }
132
133 /**
134 * Returns a unique non-zero, unique value identifying the content of this
135 * surface. Each time the content is changed changed, either by drawing
136 * into this surface, or explicitly calling notifyContentChanged()) this
137 * method will return a new value.
138 *
139 * If this surface is empty (i.e. has a zero-dimention), this will return
140 * 0.
141 */
reed@google.com97af1a62012-08-28 12:19:02 +0000142 uint32_t generationID();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000143
reed@google.com889b09e2012-07-27 21:10:42 +0000144 /**
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +0000145 * Modes that can be passed to notifyContentWillChange
146 */
147 enum ContentChangeMode {
skia.committer@gmail.come36a1682013-04-23 07:01:29 +0000148 /**
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +0000149 * Use this mode if it is known that the upcoming content changes will
150 * clear or overwrite prior contents, thus making them discardable.
151 */
152 kDiscard_ContentChangeMode,
skia.committer@gmail.come36a1682013-04-23 07:01:29 +0000153 /**
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +0000154 * Use this mode if prior surface contents need to be preserved or
155 * if in doubt.
156 */
157 kRetain_ContentChangeMode,
158 };
159
160 /**
161 * Call this if the contents are about to change. This will (lazily) force a new
reed@google.com889b09e2012-07-27 21:10:42 +0000162 * value to be returned from generationID() when it is called next.
163 */
commit-bot@chromium.orgc4c98702013-04-22 14:28:01 +0000164 void notifyContentWillChange(ContentChangeMode mode);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000165
reed@google.com889b09e2012-07-27 21:10:42 +0000166 /**
reed@google.com9ea5a3b2012-07-30 21:03:46 +0000167 * Return a canvas that will draw into this surface. This will always
168 * return the same canvas for a given surface, and is manged/owned by the
169 * surface. It should not be used when its parent surface has gone out of
170 * scope.
reed@google.com889b09e2012-07-27 21:10:42 +0000171 */
reed@google.com9ea5a3b2012-07-30 21:03:46 +0000172 SkCanvas* getCanvas();
reed@google.com889b09e2012-07-27 21:10:42 +0000173
174 /**
175 * Return a new surface that is "compatible" with this one, in that it will
176 * efficiently be able to be drawn into this surface. Typical calling
177 * pattern:
178 *
179 * SkSurface* A = SkSurface::New...();
180 * SkCanvas* canvasA = surfaceA->newCanvas();
181 * ...
182 * SkSurface* surfaceB = surfaceA->newSurface(...);
183 * SkCanvas* canvasB = surfaceB->newCanvas();
184 * ... // draw using canvasB
185 * canvasA->drawSurface(surfaceB); // <--- this will always be optimal!
186 */
reed@google.com2bd8b812013-11-01 13:46:54 +0000187 SkSurface* newSurface(const SkImageInfo&);
reed@google.com889b09e2012-07-27 21:10:42 +0000188
189 /**
190 * Returns an image of the current state of the surface pixels up to this
191 * point. Subsequent changes to the surface (by drawing into its canvas)
192 * will not be reflected in this image.
193 */
junov@chromium.org5ee449a2013-04-12 20:20:50 +0000194 SkImage* newImageSnapshot();
reed@google.com889b09e2012-07-27 21:10:42 +0000195
196 /**
197 * Thought the caller could get a snapshot image explicitly, and draw that,
198 * it seems that directly drawing a surface into another canvas might be
199 * a common pattern, and that we could possibly be more efficient, since
200 * we'd know that the "snapshot" need only live until we've handed it off
201 * to the canvas.
202 */
203 void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*);
204
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000205 /**
206 * If the surface has direct access to its pixels (i.e. they are in local
207 * RAM) return the const-address of those pixels, and if not null, return
208 * the ImageInfo and rowBytes. The returned address is only valid while
209 * the surface object is in scope, and no API call is made on the surface
210 * or its canvas.
211 *
212 * On failure, returns NULL and the info and rowBytes parameters are
213 * ignored.
214 */
215 const void* peekPixels(SkImageInfo* info, size_t* rowBytes);
216
reed3716fd02014-09-21 09:39:55 -0700217 const SkSurfaceProps& props() const { return fProps; }
218
reed@google.com889b09e2012-07-27 21:10:42 +0000219protected:
reed3716fd02014-09-21 09:39:55 -0700220 SkSurface(int width, int height, const SkSurfaceProps*);
221 SkSurface(const SkImageInfo&, const SkSurfaceProps*);
reed@google.com889b09e2012-07-27 21:10:42 +0000222
reed@google.com97af1a62012-08-28 12:19:02 +0000223 // called by subclass if their contents have changed
224 void dirtyGenerationID() {
225 fGenerationID = 0;
226 }
227
reed@google.com889b09e2012-07-27 21:10:42 +0000228private:
reed3716fd02014-09-21 09:39:55 -0700229 const SkSurfaceProps fProps;
230 const int fWidth;
231 const int fHeight;
232 uint32_t fGenerationID;
skia.committer@gmail.coma27096b2012-08-30 14:38:00 +0000233
reed@google.com7edfb492012-08-28 12:48:35 +0000234 typedef SkRefCnt INHERITED;
reed@google.com889b09e2012-07-27 21:10:42 +0000235};
236
237#endif