blob: 8ce3deb7638a251f8da84634ac4e30fd4eb084d0 [file] [log] [blame]
robertphillips7eacd772014-08-21 13:12:42 -07001/*
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
15static const SkScalar kRoot3Over2 = 0.86602545f; // sin(60)
robertphillips3bc25e72014-09-19 08:56:09 -070016static const SkScalar kRoot3 = 1.73205081f;
robertphillips7eacd772014-08-21 13:12:42 -070017
18static const int kHexSide = 30;
19static const int kNumHexX = 6;
20static const int kNumHexY = 6;
21static const int kPicWidth = kNumHexX * kHexSide;
22static const int kPicHeight = SkScalarCeilToInt((kNumHexY - 0.5f) * 2 * kHexSide * kRoot3Over2);
23static const SkScalar kInset = 20.0f;
robertphillipsb1fc64b2014-10-02 08:32:43 -070024static const int kNumPictures = 4;
robertphillips3bc25e72014-09-19 08:56:09 -070025
26static const int kTriSide = 40;
robertphillips7eacd772014-08-21 13:12:42 -070027
28// Create a hexagon centered at (originX, originY)
29static SkPath make_hex_path(SkScalar originX, SkScalar originY) {
30 SkPath hex;
31 hex.moveTo(originX-kHexSide, originY);
32 hex.rLineTo(SkScalarHalf(kHexSide), kRoot3Over2 * kHexSide);
33 hex.rLineTo(SkIntToScalar(kHexSide), 0);
34 hex.rLineTo(SkScalarHalf(kHexSide), -kHexSide * kRoot3Over2);
35 hex.rLineTo(-SkScalarHalf(kHexSide), -kHexSide * kRoot3Over2);
36 hex.rLineTo(-SkIntToScalar(kHexSide), 0);
37 hex.close();
38 return hex;
39}
40
41// Make a picture that is a tiling of the plane with stroked hexagons where
42// each hexagon is in its own layer. The layers are to exercise Ganesh's
43// layer hoisting.
robertphillips3bc25e72014-09-19 08:56:09 -070044static const SkPicture* make_hex_plane_picture(SkColor fillColor) {
robertphillips7eacd772014-08-21 13:12:42 -070045
46 // Create a hexagon with its center at the origin
47 SkPath hex = make_hex_path(0, 0);
48
49 SkPaint fill;
50 fill.setStyle(SkPaint::kFill_Style);
51 fill.setColor(fillColor);
52
53 SkPaint stroke;
54 stroke.setStyle(SkPaint::kStroke_Style);
55 stroke.setStrokeWidth(3);
56
57 SkPictureRecorder recorder;
58
piotaixrb5fae932014-09-24 13:03:30 -070059 SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kPicWidth),
robertphillipsa8d7f0b2014-08-29 08:03:56 -070060 SkIntToScalar(kPicHeight));
robertphillips7eacd772014-08-21 13:12:42 -070061
62 SkScalar xPos, yPos = 0;
63
64 for (int y = 0; y < kNumHexY; ++y) {
65 xPos = 0;
66
67 for (int x = 0; x < kNumHexX; ++x) {
68 canvas->saveLayer(NULL, NULL);
69 canvas->translate(xPos, yPos + ((x % 2) ? kRoot3Over2 * kHexSide : 0));
70 canvas->drawPath(hex, fill);
71 canvas->drawPath(hex, stroke);
72 canvas->restore();
73
74 xPos += 1.5f * kHexSide;
75 }
76
77 yPos += 2 * kHexSide * kRoot3Over2;
78 }
79
80 return recorder.endRecording();
81}
82
robertphillipsb1fc64b2014-10-02 08:32:43 -070083// Create a picture that consists of a single large layer that is tiled
84// with hexagons.
85// This is intended to exercise the layer hoisting code's clip handling (in
86// tile mode).
87static const SkPicture* make_single_layer_hex_plane_picture() {
88
89 // Create a hexagon with its center at the origin
90 SkPath hex = make_hex_path(0, 0);
91
92 SkPaint whiteFill;
93 whiteFill.setStyle(SkPaint::kFill_Style);
94 whiteFill.setColor(SK_ColorWHITE);
95
96 SkPaint greyFill;
97 greyFill.setStyle(SkPaint::kFill_Style);
98 greyFill.setColor(SK_ColorLTGRAY);
99
100 SkPaint stroke;
101 stroke.setStyle(SkPaint::kStroke_Style);
102 stroke.setStrokeWidth(3);
103
104 SkPictureRecorder recorder;
105
106 static const SkScalar kBig = 10000.0f;
107 SkCanvas* canvas = recorder.beginRecording(kBig, kBig);
108
robertphillips1564dde2014-10-06 11:50:31 -0700109 canvas->saveLayer(NULL, NULL);
110
robertphillipsb1fc64b2014-10-02 08:32:43 -0700111 SkScalar xPos = 0.0f, yPos = 0.0f;
112
113 for (int y = 0; yPos < kBig; ++y) {
114 xPos = 0;
115
116 for (int x = 0; xPos < kBig; ++x) {
117 canvas->save();
118 canvas->translate(xPos, yPos + ((x % 2) ? kRoot3Over2 * kHexSide : 0));
119 // The color of the filled hex is swapped to yield a different
120 // pattern in each tile. This allows an error in layer hoisting (e.g.,
121 // the clip isn't blocking cache reuse) to cause a visual discrepancy.
122 canvas->drawPath(hex, ((x+y) % 3) ? whiteFill : greyFill);
123 canvas->drawPath(hex, stroke);
124 canvas->restore();
125
126 xPos += 1.5f * kHexSide;
127 }
128
129 yPos += 2 * kHexSide * kRoot3Over2;
130 }
131
robertphillips1564dde2014-10-06 11:50:31 -0700132 canvas->restore();
133
robertphillipsb1fc64b2014-10-02 08:32:43 -0700134 return recorder.endRecording();
135}
136
robertphillips3bc25e72014-09-19 08:56:09 -0700137// Make an equilateral triangle path with its top corner at (originX, originY)
138static SkPath make_tri_path(SkScalar originX, SkScalar originY) {
139 SkPath tri;
140 tri.moveTo(originX, originY);
141 tri.rLineTo(SkScalarHalf(kTriSide), 1.5f * kTriSide / kRoot3);
142 tri.rLineTo(-kTriSide, 0);
143 tri.close();
144 return tri;
145}
146
147static const SkPicture* make_tri_picture() {
robertphillipsaa0c8372014-09-29 05:07:39 -0700148 SkPath tri = make_tri_path(SkScalarHalf(kTriSide), 0);
robertphillips3bc25e72014-09-19 08:56:09 -0700149
150 SkPaint fill;
151 fill.setStyle(SkPaint::kFill_Style);
152 fill.setColor(SK_ColorLTGRAY);;
153
154 SkPaint stroke;
155 stroke.setStyle(SkPaint::kStroke_Style);
156 stroke.setStrokeWidth(3);
157
158 SkPictureRecorder recorder;
159
160 SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kPicWidth),
161 SkIntToScalar(kPicHeight));
robertphillips7f1ed832014-10-03 07:29:20 -0700162 SkRect r = tri.getBounds();
163 r.outset(2.0f, 2.0f); // outset for stroke
164 canvas->clipRect(r);
robertphillips3bc25e72014-09-19 08:56:09 -0700165 // The saveLayer/restore block is to exercise layer hoisting
166 canvas->saveLayer(NULL, NULL);
167 canvas->drawPath(tri, fill);
168 canvas->drawPath(tri, stroke);
169 canvas->restore();
170
171 return recorder.endRecording();
172}
173
174static const SkPicture* make_sub_picture(const SkPicture* tri) {
175 SkPictureRecorder recorder;
176
177 SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kPicWidth),
178 SkIntToScalar(kPicHeight));
179
180 canvas->scale(1.0f/2.0f, 1.0f/2.0f);
181
robertphillips3bc25e72014-09-19 08:56:09 -0700182 canvas->save();
robertphillipsaa0c8372014-09-29 05:07:39 -0700183 canvas->translate(SkScalarHalf(kTriSide), 0);
robertphillips3bc25e72014-09-19 08:56:09 -0700184 canvas->drawPicture(tri);
185 canvas->restore();
186
187 canvas->save();
robertphillipsaa0c8372014-09-29 05:07:39 -0700188 canvas->translate(SkIntToScalar(kTriSide), 1.5f * kTriSide / kRoot3);
189 canvas->drawPicture(tri);
190 canvas->restore();
191
192 canvas->save();
193 canvas->translate(0, 1.5f * kTriSide / kRoot3);
robertphillips3bc25e72014-09-19 08:56:09 -0700194 canvas->drawPicture(tri);
195 canvas->restore();
196
197 return recorder.endRecording();
198}
199
200// Create a Sierpinkski-like picture that starts with a top row with a picture
piotaixrb5fae932014-09-24 13:03:30 -0700201// that just contains a triangle. Subsequent rows take the prior row's picture,
robertphillips3bc25e72014-09-19 08:56:09 -0700202// shrinks it and replicates it 3 times then draws and appropriate number of
203// copies of it.
204static const SkPicture* make_sierpinski_picture() {
205 SkAutoTUnref<const SkPicture> pic(make_tri_picture());
206
207 SkPictureRecorder recorder;
208
209 SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kPicWidth),
210 SkIntToScalar(kPicHeight));
211
212 static const int kNumLevels = 4;
213 for (int i = 0; i < kNumLevels; ++i) {
214 canvas->save();
robertphillipsaa0c8372014-09-29 05:07:39 -0700215 canvas->translate(kPicWidth/2 - (i+1) * (kTriSide/2.0f), 0.0f);
robertphillips3bc25e72014-09-19 08:56:09 -0700216 for (int j = 0; j < i+1; ++j) {
217 canvas->drawPicture(pic);
218 canvas->translate(SkIntToScalar(kTriSide), 0);
219 }
220 canvas->restore();
221
222 pic.reset(make_sub_picture(pic));
223
224 canvas->translate(0, 1.5f * kTriSide / kRoot3);
225 }
226
227 return recorder.endRecording();
228}
229
bsalomon892f31a2014-08-21 14:40:36 -0700230static SkSurface* create_compat_surface(SkCanvas* canvas, int width, int height) {
robertphillips7eacd772014-08-21 13:12:42 -0700231 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
232
233 SkSurface* surface = canvas->newSurface(info);
234 if (NULL == surface) {
235 // picture canvas returns NULL so fall back to raster
236 surface = SkSurface::NewRaster(info);
237 }
238
239 return surface;
240}
241
242// This class stores the information required to compose all the result
243// fragments potentially generated by the MultiPictureDraw object
244class ComposeStep {
245public:
246 ComposeStep() : fSurf(NULL), fX(0.0f), fY(0.0f), fPaint(NULL) { }
247 ~ComposeStep() { SkSafeUnref(fSurf); SkDELETE(fPaint); }
248
249 SkSurface* fSurf;
250 SkScalar fX;
251 SkScalar fY;
252 SkPaint* fPaint;
253};
254
robertphillips3bc25e72014-09-19 08:56:09 -0700255typedef void (*PFContentMtd)(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]);
robertphillips7eacd772014-08-21 13:12:42 -0700256
257// Just a single picture with no clip
robertphillips3bc25e72014-09-19 08:56:09 -0700258static void no_clip(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) {
robertphillips7eacd772014-08-21 13:12:42 -0700259 canvas->drawPicture(pictures[0]);
260}
261
262// Two pictures with a rect clip on the second one
robertphillips3bc25e72014-09-19 08:56:09 -0700263static void rect_clip(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) {
robertphillips7eacd772014-08-21 13:12:42 -0700264 canvas->drawPicture(pictures[0]);
265
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700266 SkRect rect = pictures[0]->cullRect();
robertphillips7eacd772014-08-21 13:12:42 -0700267 rect.inset(kInset, kInset);
268
269 canvas->clipRect(rect);
270
271 canvas->drawPicture(pictures[1]);
272}
273
274// Two pictures with a round rect clip on the second one
robertphillips3bc25e72014-09-19 08:56:09 -0700275static void rrect_clip(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) {
robertphillips7eacd772014-08-21 13:12:42 -0700276 canvas->drawPicture(pictures[0]);
277
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700278 SkRect rect = pictures[0]->cullRect();
robertphillips7eacd772014-08-21 13:12:42 -0700279 rect.inset(kInset, kInset);
piotaixrb5fae932014-09-24 13:03:30 -0700280
robertphillips7eacd772014-08-21 13:12:42 -0700281 SkRRect rrect;
282 rrect.setRectXY(rect, kInset, kInset);
283
284 canvas->clipRRect(rrect);
285
286 canvas->drawPicture(pictures[1]);
287}
288
289// Two pictures with a clip path on the second one
robertphillips3bc25e72014-09-19 08:56:09 -0700290static void path_clip(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) {
robertphillips7eacd772014-08-21 13:12:42 -0700291 canvas->drawPicture(pictures[0]);
292
293 // Create a hexagon centered on the middle of the hex grid
294 SkPath hex = make_hex_path((kNumHexX / 2.0f) * kHexSide, kNumHexY * kHexSide * kRoot3Over2);
295
296 canvas->clipPath(hex);
297
298 canvas->drawPicture(pictures[1]);
299}
300
301// Two pictures with an inverse clip path on the second one
robertphillips3bc25e72014-09-19 08:56:09 -0700302static void invpath_clip(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) {
robertphillips7eacd772014-08-21 13:12:42 -0700303 canvas->drawPicture(pictures[0]);
304
305 // Create a hexagon centered on the middle of the hex grid
306 SkPath hex = make_hex_path((kNumHexX / 2.0f) * kHexSide, kNumHexY * kHexSide * kRoot3Over2);
307 hex.setFillType(SkPath::kInverseEvenOdd_FillType);
308
309 canvas->clipPath(hex);
310
311 canvas->drawPicture(pictures[1]);
312}
313
robertphillips3bc25e72014-09-19 08:56:09 -0700314// Reuse a single base (triangular) picture a _lot_ (rotated, scaled and translated).
315static void sierpinski(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) {
316 canvas->save();
robertphillips3bc25e72014-09-19 08:56:09 -0700317 canvas->drawPicture(pictures[2]);
318
319 canvas->rotate(180.0f);
robertphillipsaa0c8372014-09-29 05:07:39 -0700320 canvas->translate(-SkIntToScalar(kPicWidth), -SkIntToScalar(kPicHeight));
robertphillips3bc25e72014-09-19 08:56:09 -0700321 canvas->drawPicture(pictures[2]);
322 canvas->restore();
323}
324
robertphillipsb1fc64b2014-10-02 08:32:43 -0700325static void big_layer(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) {
326 canvas->drawPicture(pictures[3]);
327}
328
robertphillips7eacd772014-08-21 13:12:42 -0700329static const PFContentMtd gContentMthds[] = {
330 no_clip,
331 rect_clip,
332 rrect_clip,
333 path_clip,
robertphillips3bc25e72014-09-19 08:56:09 -0700334 invpath_clip,
robertphillipsb1fc64b2014-10-02 08:32:43 -0700335 sierpinski,
336 big_layer,
robertphillips7eacd772014-08-21 13:12:42 -0700337};
338
339static void create_content(SkMultiPictureDraw* mpd, PFContentMtd pfGen,
robertphillips3bc25e72014-09-19 08:56:09 -0700340 const SkPicture* pictures[kNumPictures],
robertphillips7eacd772014-08-21 13:12:42 -0700341 SkCanvas* dest, const SkMatrix& xform) {
342 SkAutoTUnref<SkPicture> composite;
343
344 {
345 SkPictureRecorder recorder;
346
piotaixrb5fae932014-09-24 13:03:30 -0700347 SkCanvas* pictureCanvas = recorder.beginRecording(SkIntToScalar(kPicWidth),
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700348 SkIntToScalar(kPicHeight));
robertphillips7eacd772014-08-21 13:12:42 -0700349
350 (*pfGen)(pictureCanvas, pictures);
351
352 composite.reset(recorder.endRecording());
353 }
354
355 mpd->add(dest, composite, &xform);
356}
357
piotaixrb5fae932014-09-24 13:03:30 -0700358typedef void(*PFLayoutMtd)(SkCanvas* finalCanvas, SkMultiPictureDraw* mpd,
robertphillips3bc25e72014-09-19 08:56:09 -0700359 PFContentMtd pfGen, const SkPicture* pictures[kNumPictures],
robertphillips7eacd772014-08-21 13:12:42 -0700360 SkTArray<ComposeStep>* composeSteps);
361
362// Draw the content into a single canvas
piotaixrb5fae932014-09-24 13:03:30 -0700363static void simple(SkCanvas* finalCanvas, SkMultiPictureDraw* mpd,
364 PFContentMtd pfGen,
robertphillips3bc25e72014-09-19 08:56:09 -0700365 const SkPicture* pictures[kNumPictures],
robertphillips7eacd772014-08-21 13:12:42 -0700366 SkTArray<ComposeStep> *composeSteps) {
367
368 ComposeStep& step = composeSteps->push_back();
369
bsalomon892f31a2014-08-21 14:40:36 -0700370 step.fSurf = create_compat_surface(finalCanvas, kPicWidth, kPicHeight);
robertphillips7eacd772014-08-21 13:12:42 -0700371
372 SkCanvas* subCanvas = step.fSurf->getCanvas();
373
374 create_content(mpd, pfGen, pictures, subCanvas, SkMatrix::I());
375}
376
377// Draw the content into multiple canvases/tiles
378static void tiled(SkCanvas* finalCanvas, SkMultiPictureDraw* mpd,
piotaixrb5fae932014-09-24 13:03:30 -0700379 PFContentMtd pfGen,
robertphillips3bc25e72014-09-19 08:56:09 -0700380 const SkPicture* pictures[kNumPictures],
robertphillips7eacd772014-08-21 13:12:42 -0700381 SkTArray<ComposeStep> *composeSteps) {
382 static const int kNumTilesX = 2;
383 static const int kNumTilesY = 2;
384 static const int kTileWidth = kPicWidth / kNumTilesX;
385 static const int kTileHeight = kPicHeight / kNumTilesY;
386
387 SkASSERT(kPicWidth == kNumTilesX * kTileWidth);
388 SkASSERT(kPicHeight == kNumTilesY * kTileHeight);
389
390 static const SkColor colors[kNumTilesX][kNumTilesY] = {
piotaixrb5fae932014-09-24 13:03:30 -0700391 { SK_ColorCYAN, SK_ColorMAGENTA },
robertphillips7eacd772014-08-21 13:12:42 -0700392 { SK_ColorYELLOW, SK_ColorGREEN }
393 };
394
395 for (int y = 0; y < kNumTilesY; ++y) {
396 for (int x = 0; x < kNumTilesX; ++x) {
397 ComposeStep& step = composeSteps->push_back();
398
399 step.fX = SkIntToScalar(x*kTileWidth);
400 step.fY = SkIntToScalar(y*kTileHeight);
401 step.fPaint = SkNEW(SkPaint);
402 step.fPaint->setColorFilter(
403 SkColorFilter::CreateModeFilter(colors[x][y], SkXfermode::kModulate_Mode))->unref();
404
bsalomon892f31a2014-08-21 14:40:36 -0700405 step.fSurf = create_compat_surface(finalCanvas, kTileWidth, kTileHeight);
robertphillips7eacd772014-08-21 13:12:42 -0700406
407 SkCanvas* subCanvas = step.fSurf->getCanvas();
408
409 SkMatrix trans;
410 trans.setTranslate(-SkIntToScalar(x*kTileWidth), -SkIntToScalar(y*kTileHeight));
411
412 create_content(mpd, pfGen, pictures, subCanvas, trans);
413 }
414 }
415}
416
417static const PFLayoutMtd gLayoutMthds[] = { simple, tiled };
418
419namespace skiagm {
420 /**
421 * This GM exercises the SkMultiPictureDraw object. It tests the
422 * cross product of:
423 * tiled vs. all-at-once rendering (e.g., into many or just 1 canvas)
424 * different clips (e.g., none, rect, rrect)
425 * single vs. multiple pictures (e.g., normal vs. picture-pile-style content)
426 */
427 class MultiPictureDraw : public GM {
428 public:
429 enum Content {
430 kNoClipSingle_Content,
431 kRectClipMulti_Content,
432 kRRectClipMulti_Content,
433 kPathClipMulti_Content,
434 kInvPathClipMulti_Content,
robertphillips3bc25e72014-09-19 08:56:09 -0700435 kSierpinski_Content,
robertphillipsb1fc64b2014-10-02 08:32:43 -0700436 kBigLayer_Content,
robertphillips7eacd772014-08-21 13:12:42 -0700437
robertphillipsb1fc64b2014-10-02 08:32:43 -0700438 kLast_Content = kBigLayer_Content
robertphillips7eacd772014-08-21 13:12:42 -0700439 };
440
441 static const int kContentCnt = kLast_Content + 1;
442
443 enum Layout {
444 kSimple_Layout,
445 kTiled_Layout,
446
447 kLast_Layout = kTiled_Layout
448 };
449
450 static const int kLayoutCnt = kLast_Layout + 1;
451
452 MultiPictureDraw(Content content, Layout layout) : fContent(content), fLayout(layout) {
453 SkASSERT(SK_ARRAY_COUNT(gLayoutMthds) == kLayoutCnt);
454 SkASSERT(SK_ARRAY_COUNT(gContentMthds) == kContentCnt);
455
robertphillips3bc25e72014-09-19 08:56:09 -0700456 for (int i = 0; i < kNumPictures; ++i) {
457 fPictures[i] = NULL;
458 }
robertphillips7eacd772014-08-21 13:12:42 -0700459 }
460
461 virtual ~MultiPictureDraw() {
robertphillips3bc25e72014-09-19 08:56:09 -0700462 for (int i = 0; i < kNumPictures; ++i) {
463 SkSafeUnref(fPictures[i]);
464 }
robertphillips7eacd772014-08-21 13:12:42 -0700465 }
466
467 protected:
468 Content fContent;
469 Layout fLayout;
robertphillips3bc25e72014-09-19 08:56:09 -0700470 const SkPicture* fPictures[kNumPictures];
robertphillips7eacd772014-08-21 13:12:42 -0700471
472 virtual void onOnceBeforeDraw() SK_OVERRIDE {
robertphillips3bc25e72014-09-19 08:56:09 -0700473 fPictures[0] = make_hex_plane_picture(SK_ColorWHITE);
474 fPictures[1] = make_hex_plane_picture(SK_ColorGRAY);
robertphillipsab79ab52014-09-19 11:30:37 -0700475 fPictures[2] = make_sierpinski_picture();
robertphillipsb1fc64b2014-10-02 08:32:43 -0700476 fPictures[3] = make_single_layer_hex_plane_picture();
robertphillips7eacd772014-08-21 13:12:42 -0700477 }
478
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700479 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
robertphillips7eacd772014-08-21 13:12:42 -0700480 SkMultiPictureDraw mpd;
481 SkTArray<ComposeStep> composeSteps;
482
483 // Fill up the MultiPictureDraw
piotaixrb5fae932014-09-24 13:03:30 -0700484 (*gLayoutMthds[fLayout])(canvas, &mpd,
485 gContentMthds[fContent],
robertphillips7eacd772014-08-21 13:12:42 -0700486 fPictures, &composeSteps);
487
488 mpd.draw();
489
490 // Compose all the drawn canvases into the final canvas
491 for (int i = 0; i < composeSteps.count(); ++i) {
492 const ComposeStep& step = composeSteps[i];
493
494 SkAutoTUnref<SkImage> image(step.fSurf->newImageSnapshot());
495
piotaixrb5fae932014-09-24 13:03:30 -0700496 canvas->drawImage(image, step.fX, step.fY, step.fPaint);
robertphillips7eacd772014-08-21 13:12:42 -0700497 }
498 }
499
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700500 virtual SkISize onISize() SK_OVERRIDE { return SkISize::Make(kPicWidth, kPicHeight); }
robertphillips7eacd772014-08-21 13:12:42 -0700501
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700502 virtual SkString onShortName() SK_OVERRIDE {
piotaixrb5fae932014-09-24 13:03:30 -0700503 static const char* gContentNames[] = {
robertphillipsb1fc64b2014-10-02 08:32:43 -0700504 "noclip", "rectclip", "rrectclip", "pathclip",
505 "invpathclip", "sierpinski", "biglayer"
robertphillips7eacd772014-08-21 13:12:42 -0700506 };
507 static const char* gLayoutNames[] = { "simple", "tiled" };
508
509 SkASSERT(SK_ARRAY_COUNT(gLayoutNames) == kLayoutCnt);
510 SkASSERT(SK_ARRAY_COUNT(gContentNames) == kContentCnt);
511
512 SkString name("multipicturedraw_");
513
514 name.append(gContentNames[fContent]);
515 name.append("_");
516 name.append(gLayoutNames[fLayout]);
517 return name;
518 }
519
520 virtual uint32_t onGetFlags() const SK_OVERRIDE { return kAsBench_Flag | kSkipTiled_Flag; }
521
522 private:
523 typedef GM INHERITED;
524 };
525
piotaixrb5fae932014-09-24 13:03:30 -0700526 DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kNoClipSingle_Content,
robertphillips7eacd772014-08-21 13:12:42 -0700527 MultiPictureDraw::kSimple_Layout));)
piotaixrb5fae932014-09-24 13:03:30 -0700528 DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kRectClipMulti_Content,
robertphillips7eacd772014-08-21 13:12:42 -0700529 MultiPictureDraw::kSimple_Layout));)
piotaixrb5fae932014-09-24 13:03:30 -0700530 DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kRRectClipMulti_Content,
robertphillips7eacd772014-08-21 13:12:42 -0700531 MultiPictureDraw::kSimple_Layout));)
piotaixrb5fae932014-09-24 13:03:30 -0700532 DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kPathClipMulti_Content,
robertphillips7eacd772014-08-21 13:12:42 -0700533 MultiPictureDraw::kSimple_Layout));)
piotaixrb5fae932014-09-24 13:03:30 -0700534 DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kInvPathClipMulti_Content,
robertphillips7eacd772014-08-21 13:12:42 -0700535 MultiPictureDraw::kSimple_Layout));)
robertphillips3bc25e72014-09-19 08:56:09 -0700536 DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kSierpinski_Content,
537 MultiPictureDraw::kSimple_Layout));)
robertphillipsb1fc64b2014-10-02 08:32:43 -0700538 DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kBigLayer_Content,
539 MultiPictureDraw::kSimple_Layout));)
robertphillips7eacd772014-08-21 13:12:42 -0700540
piotaixrb5fae932014-09-24 13:03:30 -0700541 DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kNoClipSingle_Content,
robertphillips7eacd772014-08-21 13:12:42 -0700542 MultiPictureDraw::kTiled_Layout));)
piotaixrb5fae932014-09-24 13:03:30 -0700543 DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kRectClipMulti_Content,
robertphillips7eacd772014-08-21 13:12:42 -0700544 MultiPictureDraw::kTiled_Layout));)
piotaixrb5fae932014-09-24 13:03:30 -0700545 DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kRRectClipMulti_Content,
robertphillips7eacd772014-08-21 13:12:42 -0700546 MultiPictureDraw::kTiled_Layout));)
piotaixrb5fae932014-09-24 13:03:30 -0700547 DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kPathClipMulti_Content,
robertphillips7eacd772014-08-21 13:12:42 -0700548 MultiPictureDraw::kTiled_Layout));)
piotaixrb5fae932014-09-24 13:03:30 -0700549 DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kInvPathClipMulti_Content,
robertphillips7eacd772014-08-21 13:12:42 -0700550 MultiPictureDraw::kTiled_Layout));)
robertphillips3bc25e72014-09-19 08:56:09 -0700551 DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kSierpinski_Content,
552 MultiPictureDraw::kTiled_Layout));)
robertphillipsb1fc64b2014-10-02 08:32:43 -0700553 DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kBigLayer_Content,
554 MultiPictureDraw::kTiled_Layout));)
robertphillips7eacd772014-08-21 13:12:42 -0700555}