Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: gm/multipicturedraw.cpp

Issue 491313003: SkMultiPictureDraw API (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | gyp/core.gypi » ('j') | include/core/SkMultiPictureDraw.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2014 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 #include "gm.h"
9
10 #include "SkColorFilter.h"
11 #include "SkMultiPictureDraw.h"
12 #include "SkPictureRecorder.h"
13 #include "SkSurface.h"
14
15 // TODO:
16 // pass around SkPicture*[2]
17 // add diff clips (path, invpath, region)
18 // research Chrome SkRegion usage
19 // break out make_hex_path mtd
20 // add rest of clip types to mpd object
21 // add static asserts
22 // fix up pub vs. protected in GM
23
24 static const SkScalar kRoot3Over2 = 0.86602545f; // sin(60)
25
26 static const int kHexSide = 30;
27 static const int kNumHexX = 6;
28 static const int kNumHexY = 6;
29 static const int kPicWidth = kNumHexX * kHexSide;
30 static const int kPicHeight = SkScalarCeilToInt((kNumHexY - 0.5f) * 2 * kHexSide * kRoot3Over2);
31 static const SkScalar kInset = 20.0f;
32
33 // Make a picture that is a tiling of the plane with stroked hexagons where
34 // each hexagon is in its own layer. The layers are to exercise Ganesh's
35 // layer hoisting.
36 static const SkPicture* make_picture(SkColor fillColor) {
37
38 // Create a hexagon with its center at the origin
39 SkPath hex;
40 hex.moveTo(-kHexSide, 0);
41 hex.rLineTo(SkScalarHalf(kHexSide), kRoot3Over2 * kHexSide);
42 hex.rLineTo(SkIntToScalar(kHexSide), 0);
43 hex.rLineTo(SkScalarHalf(kHexSide), -kHexSide * kRoot3Over2);
44 hex.rLineTo(-SkScalarHalf(kHexSide), -kHexSide * kRoot3Over2);
45 hex.rLineTo(-SkIntToScalar(kHexSide), 0);
46 hex.close();
47
48 SkPaint fill;
49 fill.setStyle(SkPaint::kFill_Style);
50 fill.setColor(fillColor);
51
52 SkPaint stroke;
53 stroke.setStyle(SkPaint::kStroke_Style);
54 stroke.setStrokeWidth(3);
55
56 SkPictureRecorder recorder;
57
58 SkCanvas* canvas = recorder.beginRecording(kPicWidth, kPicHeight);
59
60 SkScalar xPos, yPos = 0;
61
62 for (int y = 0; y < kNumHexY; ++y) {
63 xPos = 0;
64
65 for (int x = 0; x < kNumHexX; ++x) {
66 canvas->saveLayer(NULL, NULL);
67 canvas->translate(xPos, yPos + ((x % 2) ? kRoot3Over2 * kHexSide : 0 ));
68 canvas->drawPath(hex, fill);
69 canvas->drawPath(hex, stroke);
70 canvas->restore();
71
72 xPos += 1.5f * kHexSide;
73 }
74
75 yPos += 2 * kHexSide * kRoot3Over2;
76 }
77
78 return recorder.endRecording();
79 }
80
81 static SkSurface* compat_surface(SkCanvas* canvas, int width, int height) {
82 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
83
84 SkSurface* surface = canvas->newSurface(info);
85 if (NULL == surface) {
86 // picture canvas returns NULL so fall back to raster
87 surface = SkSurface::NewRaster(info);
88 }
89
90 return surface;
91 }
92
93 // This class stores the information required to compose all the result
94 // fragments potentially generated by the MultiPictureDraw object
95 class ComposeStep {
96 public:
97 ComposeStep() : fSurf(NULL), fX(0.0f), fY(0.0f), fPaint(NULL) { }
98 ~ComposeStep() { SkSafeUnref(fSurf); SkDELETE(fPaint); }
99
100 SkSurface* fSurf;
101 SkScalar fX;
102 SkScalar fY;
103 SkPaint* fPaint;
104 };
105
106 typedef void (*PFContentMtd)(SkMultiPictureDraw* mpd,
107 const SkPicture* pic0, const SkPicture* pic1,
108 SkCanvas* dest,
109 const SkMatrix& xform);
110
111 // Just a single picture with no clip
112 static void no_clip(SkMultiPictureDraw* mpd,
113 const SkPicture* pic0, const SkPicture* pic1,
114 SkCanvas* dest, const SkMatrix& xform) {
115 mpd->add(pic0, dest, &xform);
116 }
117
118 // Two pictures with a rect clip on the second one
119 static void rect_clip(SkMultiPictureDraw* mpd,
120 const SkPicture* pic0, const SkPicture* pic1,
121 SkCanvas* dest, const SkMatrix& xform) {
122 mpd->add(pic0, dest, &xform);
123
124 SkRect rect = SkRect::MakeWH(SkIntToScalar(kPicWidth), SkIntToScalar(kPicHei ght));
125 rect.inset(kInset, kInset);
126 xform.mapRect(&rect);
127
128 mpd->add(pic1, dest, rect, &xform);
129 }
130
131 // Two pictures with a round rect clip on the second one
132 static void rrect_clip(SkMultiPictureDraw* mpd,
133 const SkPicture* pic0, const SkPicture* pic1,
134 SkCanvas* dest, const SkMatrix& xform) {
135 mpd->add(pic0, dest, &xform);
136
137 SkRect rect = SkRect::MakeWH(SkIntToScalar(kPicWidth), SkIntToScalar(kPicHei ght));
138 rect.inset(kInset, kInset);
139 xform.mapRect(&rect);
140
141 SkRRect rrect;
142 rrect.setRectXY(rect, kInset, kInset);
143
144 mpd->add(pic1, dest, rrect, &xform);
145 }
146
147 static const PFContentMtd gContentMtds[] = {
148 no_clip,
149 rect_clip,
150 rrect_clip
151 };
152 // TODO: static asserts
153
154 typedef void(*PFLayoutMtd)(SkCanvas*, SkMultiPictureDraw*, PFContentMtd,
155 const SkPicture*, const SkPicture*,
156 SkTArray<ComposeStep>*);
157
158 // Draw the content into a single canvas
159 static void simple(SkCanvas* finalCanvas, SkMultiPictureDraw* mpd,
160 PFContentMtd pfGen,
161 const SkPicture* pic0, const SkPicture* pic1,
162 SkTArray<ComposeStep> *composeSteps) {
163
164 ComposeStep& step = composeSteps->push_back();
165
166 step.fSurf = SkSafeRef(compat_surface(finalCanvas, kPicWidth, kPicHeight));
167
168 SkCanvas* subCanvas = step.fSurf->getCanvas();
169
170 (*pfGen)(mpd, pic0, pic1, subCanvas, SkMatrix::I());
171 }
172
173 // Draw the content into multiple canvases/tiles
174 static void tiled(SkCanvas* finalCanvas, SkMultiPictureDraw* mpd,
175 PFContentMtd pfGen,
176 const SkPicture* pic0, const SkPicture* pic1,
177 SkTArray<ComposeStep> *composeSteps) {
178 static const int kNumTilesX = 2;
179 static const int kNumTilesY = 2;
180 static const int kTileWidth = kPicWidth / kNumTilesX;
181 static const int kTileHeight = kPicHeight / kNumTilesY;
182
183 SkASSERT(kPicWidth == kNumTilesX * kTileWidth);
184 SkASSERT(kPicHeight == kNumTilesY * kTileHeight);
185
186 static const SkColor colors[kNumTilesX][kNumTilesY] = {
187 SK_ColorCYAN, SK_ColorMAGENTA, SK_ColorYELLOW, SK_ColorGREEN
188 };
189
190 for (int y = 0; y < kNumTilesY; ++y) {
191 for (int x = 0; x < kNumTilesX; ++x) {
192 ComposeStep& step = composeSteps->push_back();
193
194 step.fX = SkIntToScalar(x*kTileWidth);
195 step.fY = SkIntToScalar(y*kTileHeight);
196 step.fPaint = SkNEW(SkPaint);
197 step.fPaint->setColorFilter(
198 SkColorFilter::CreateModeFilter(colors[x][y], SkXfermode::kModul ate_Mode))->unref();
199
200 step.fSurf = SkSafeRef(compat_surface(finalCanvas, kTileWidth, kTile Height));
201
202 SkCanvas* subCanvas = step.fSurf->getCanvas();
203
204 SkMatrix trans;
205 trans.setTranslate(-SkIntToScalar(x*kTileWidth), -SkIntToScalar(y*kT ileHeight));
206
207 (*pfGen)(mpd, pic0, pic1, subCanvas, trans);
208 }
209 }
210 }
211
212 static const PFLayoutMtd gLayoutMthds[] = { simple, tiled };
213 // TODO: static asserts
214
215 namespace skiagm {
216 /**
217 * This GM exercises the SkMultiPictureDraw object. It tests the
218 * cross product of:
219 * tiled vs. all-at-once rendering (e.g., into many or just 1 canvas)
220 * different clips (e.g., none, rect, rrect)
221 * single vs. multiple pictures (e.g., normal vs. picture-pile-style co ntent)
222 */
223 class MultiPictureDraw : public GM {
224 public:
225 enum Content {
226 NoClipSingle_Content,
227 RectClipMulti_Content,
228 RRectClipMulti_Content,
229 };
230
231 enum Layout {
232 Simple_Layout,
233 Tiled_Layout
234 };
235
236 MultiPictureDraw(Content content, Layout layout) : fContent(content), fL ayout(layout) { }
237
238 virtual SkString onShortName() SK_OVERRIDE {
239 static const char* gContentNames[] = { "noclip", "rectclip", "rrectc lip" };
240 static const char* gLayoutNames[] = { "simple", "tiled" };
241 // TODO: static asserts
242
243 SkString name("multipicturedraw_");
244
245 name.append(gContentNames[fContent]);
246 name.append("_");
247 name.append(gLayoutNames[fLayout]);
248 return name;
249 }
250
251 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
252 SkMultiPictureDraw mpd;
253 SkTArray<ComposeStep> composeSteps;
254
255 // Fill up the MultiPictureDraw
256 (*gLayoutMthds[fLayout])(canvas, &mpd, gContentMtds[fContent], fPict ures[0], fPictures[1], &composeSteps);
257
258 mpd.draw();
259
260 // Compose all the drawn canvases into the final canvas
261 for (int i = 0; i < composeSteps.count(); ++i) {
262 const ComposeStep& step = composeSteps[i];
263
264 SkAutoTUnref<SkImage> image(step.fSurf->newImageSnapshot());
265
266 image->draw(canvas, step.fX, step.fY, step.fPaint);
267 }
268 }
269
270 protected:
271 Content fContent;
272 Layout fLayout;
273 SkAutoTUnref<const SkPicture> fPictures[2];
274
275 virtual SkISize onISize() SK_OVERRIDE { return SkISize::Make(kPicWidth, kPicHeight); }
276
277 virtual void onOnceBeforeDraw() SK_OVERRIDE {
278 fPictures[0].reset(make_picture(SK_ColorWHITE));
279 fPictures[1].reset(make_picture(SK_ColorLTGRAY));
280 }
281
282 virtual uint32_t onGetFlags() const SK_OVERRIDE { return kAsBench_Flag | kSkipTiled_Flag; }
283
284 private:
285 typedef GM INHERITED;
286 };
287
288 DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::NoClipSingle_C ontent, MultiPictureDraw::Simple_Layout));)
289 DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::RectClipMulti_ Content, MultiPictureDraw::Simple_Layout));)
290 DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::RRectClipMulti _Content, MultiPictureDraw::Simple_Layout));)
291
292 DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::NoClipSingle_C ontent, MultiPictureDraw::Tiled_Layout));)
293 DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::RectClipMulti_ Content, MultiPictureDraw::Tiled_Layout));)
294 DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::RRectClipMulti _Content, MultiPictureDraw::Tiled_Layout));)
295 }
OLDNEW
« no previous file with comments | « no previous file | gyp/core.gypi » ('j') | include/core/SkMultiPictureDraw.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698