multipicturedraw.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  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. #include "gm/gm.h"
  8. #include "include/core/SkBBHFactory.h"
  9. #include "include/core/SkBlendMode.h"
  10. #include "include/core/SkCanvas.h"
  11. #include "include/core/SkColor.h"
  12. #include "include/core/SkColorFilter.h"
  13. #include "include/core/SkImageInfo.h"
  14. #include "include/core/SkMatrix.h"
  15. #include "include/core/SkMultiPictureDraw.h"
  16. #include "include/core/SkPaint.h"
  17. #include "include/core/SkPath.h"
  18. #include "include/core/SkPicture.h"
  19. #include "include/core/SkPictureRecorder.h"
  20. #include "include/core/SkRRect.h"
  21. #include "include/core/SkRect.h"
  22. #include "include/core/SkRefCnt.h"
  23. #include "include/core/SkScalar.h"
  24. #include "include/core/SkSize.h"
  25. #include "include/core/SkString.h"
  26. #include "include/core/SkSurface.h"
  27. #include "include/core/SkTypes.h"
  28. #include "include/private/SkTArray.h"
  29. #include "tools/ToolUtils.h"
  30. constexpr SkScalar kRoot3Over2 = 0.86602545f; // sin(60)
  31. constexpr SkScalar kRoot3 = 1.73205081f;
  32. constexpr int kHexSide = 30;
  33. constexpr int kNumHexX = 6;
  34. constexpr int kNumHexY = 6;
  35. constexpr int kPicWidth = kNumHexX * kHexSide;
  36. constexpr int kPicHeight = (int)((kNumHexY - 0.5f) * 2 * kHexSide * kRoot3Over2 + 0.5f);
  37. constexpr SkScalar kInset = 20.0f;
  38. constexpr int kNumPictures = 4;
  39. constexpr int kTriSide = 40;
  40. // Create a hexagon centered at (originX, originY)
  41. static SkPath make_hex_path(SkScalar originX, SkScalar originY) {
  42. SkPath hex;
  43. hex.moveTo(originX-kHexSide, originY);
  44. hex.rLineTo(SkScalarHalf(kHexSide), kRoot3Over2 * kHexSide);
  45. hex.rLineTo(SkIntToScalar(kHexSide), 0);
  46. hex.rLineTo(SkScalarHalf(kHexSide), -kHexSide * kRoot3Over2);
  47. hex.rLineTo(-SkScalarHalf(kHexSide), -kHexSide * kRoot3Over2);
  48. hex.rLineTo(-SkIntToScalar(kHexSide), 0);
  49. hex.close();
  50. return hex;
  51. }
  52. // Make a picture that is a tiling of the plane with stroked hexagons where
  53. // each hexagon is in its own layer. The layers are to exercise Ganesh's
  54. // layer hoisting.
  55. static sk_sp<SkPicture> make_hex_plane_picture(SkColor fillColor) {
  56. // Create a hexagon with its center at the origin
  57. SkPath hex = make_hex_path(0, 0);
  58. SkPaint fill;
  59. fill.setStyle(SkPaint::kFill_Style);
  60. fill.setColor(fillColor);
  61. SkPaint stroke;
  62. stroke.setStyle(SkPaint::kStroke_Style);
  63. stroke.setStrokeWidth(3);
  64. SkPictureRecorder recorder;
  65. SkRTreeFactory bbhFactory;
  66. SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kPicWidth),
  67. SkIntToScalar(kPicHeight),
  68. &bbhFactory);
  69. SkScalar xPos, yPos = 0;
  70. for (int y = 0; y < kNumHexY; ++y) {
  71. xPos = 0;
  72. for (int x = 0; x < kNumHexX; ++x) {
  73. canvas->saveLayer(nullptr, nullptr);
  74. canvas->translate(xPos, yPos + ((x % 2) ? kRoot3Over2 * kHexSide : 0));
  75. canvas->drawPath(hex, fill);
  76. canvas->drawPath(hex, stroke);
  77. canvas->restore();
  78. xPos += 1.5f * kHexSide;
  79. }
  80. yPos += 2 * kHexSide * kRoot3Over2;
  81. }
  82. return recorder.finishRecordingAsPicture();
  83. }
  84. // Create a picture that consists of a single large layer that is tiled
  85. // with hexagons.
  86. // This is intended to exercise the layer hoisting code's clip handling (in
  87. // tile mode).
  88. static sk_sp<SkPicture> make_single_layer_hex_plane_picture() {
  89. // Create a hexagon with its center at the origin
  90. SkPath hex = make_hex_path(0, 0);
  91. SkPaint whiteFill;
  92. whiteFill.setStyle(SkPaint::kFill_Style);
  93. whiteFill.setColor(SK_ColorWHITE);
  94. SkPaint greyFill;
  95. greyFill.setStyle(SkPaint::kFill_Style);
  96. greyFill.setColor(SK_ColorLTGRAY);
  97. SkPaint stroke;
  98. stroke.setStyle(SkPaint::kStroke_Style);
  99. stroke.setStrokeWidth(3);
  100. SkPictureRecorder recorder;
  101. SkRTreeFactory bbhFactory;
  102. constexpr SkScalar kBig = 10000.0f;
  103. SkCanvas* canvas = recorder.beginRecording(kBig, kBig, &bbhFactory);
  104. canvas->saveLayer(nullptr, nullptr);
  105. SkScalar xPos = 0.0f, yPos = 0.0f;
  106. for (int y = 0; yPos < kBig; ++y) {
  107. xPos = 0;
  108. for (int x = 0; xPos < kBig; ++x) {
  109. canvas->save();
  110. canvas->translate(xPos, yPos + ((x % 2) ? kRoot3Over2 * kHexSide : 0));
  111. // The color of the filled hex is swapped to yield a different
  112. // pattern in each tile. This allows an error in layer hoisting (e.g.,
  113. // the clip isn't blocking cache reuse) to cause a visual discrepancy.
  114. canvas->drawPath(hex, ((x+y) % 3) ? whiteFill : greyFill);
  115. canvas->drawPath(hex, stroke);
  116. canvas->restore();
  117. xPos += 1.5f * kHexSide;
  118. }
  119. yPos += 2 * kHexSide * kRoot3Over2;
  120. }
  121. canvas->restore();
  122. return recorder.finishRecordingAsPicture();
  123. }
  124. // Make an equilateral triangle path with its top corner at (originX, originY)
  125. static SkPath make_tri_path(SkScalar originX, SkScalar originY) {
  126. SkPath tri;
  127. tri.moveTo(originX, originY);
  128. tri.rLineTo(SkScalarHalf(kTriSide), 1.5f * kTriSide / kRoot3);
  129. tri.rLineTo(-kTriSide, 0);
  130. tri.close();
  131. return tri;
  132. }
  133. static sk_sp<SkPicture> make_tri_picture() {
  134. SkPath tri = make_tri_path(SkScalarHalf(kTriSide), 0);
  135. SkPaint fill;
  136. fill.setStyle(SkPaint::kFill_Style);
  137. fill.setColor(SK_ColorLTGRAY);
  138. SkPaint stroke;
  139. stroke.setStyle(SkPaint::kStroke_Style);
  140. stroke.setStrokeWidth(3);
  141. SkPictureRecorder recorder;
  142. SkRTreeFactory bbhFactory;
  143. SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kPicWidth),
  144. SkIntToScalar(kPicHeight),
  145. &bbhFactory);
  146. SkRect r = tri.getBounds();
  147. r.outset(2.0f, 2.0f); // outset for stroke
  148. canvas->clipRect(r);
  149. // The saveLayer/restore block is to exercise layer hoisting
  150. canvas->saveLayer(nullptr, nullptr);
  151. canvas->drawPath(tri, fill);
  152. canvas->drawPath(tri, stroke);
  153. canvas->restore();
  154. return recorder.finishRecordingAsPicture();
  155. }
  156. static sk_sp<SkPicture> make_sub_picture(const SkPicture* tri) {
  157. SkPictureRecorder recorder;
  158. SkRTreeFactory bbhFactory;
  159. SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kPicWidth),
  160. SkIntToScalar(kPicHeight),
  161. &bbhFactory);
  162. canvas->scale(1.0f/2.0f, 1.0f/2.0f);
  163. canvas->save();
  164. canvas->translate(SkScalarHalf(kTriSide), 0);
  165. canvas->drawPicture(tri);
  166. canvas->restore();
  167. canvas->save();
  168. canvas->translate(SkIntToScalar(kTriSide), 1.5f * kTriSide / kRoot3);
  169. canvas->drawPicture(tri);
  170. canvas->restore();
  171. canvas->save();
  172. canvas->translate(0, 1.5f * kTriSide / kRoot3);
  173. canvas->drawPicture(tri);
  174. canvas->restore();
  175. return recorder.finishRecordingAsPicture();
  176. }
  177. // Create a Sierpinkski-like picture that starts with a top row with a picture
  178. // that just contains a triangle. Subsequent rows take the prior row's picture,
  179. // shrinks it and replicates it 3 times then draws and appropriate number of
  180. // copies of it.
  181. static sk_sp<SkPicture> make_sierpinski_picture() {
  182. sk_sp<SkPicture> pic(make_tri_picture());
  183. SkPictureRecorder recorder;
  184. SkRTreeFactory bbhFactory;
  185. SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kPicWidth),
  186. SkIntToScalar(kPicHeight),
  187. &bbhFactory);
  188. constexpr int kNumLevels = 4;
  189. for (int i = 0; i < kNumLevels; ++i) {
  190. canvas->save();
  191. canvas->translate(kPicWidth/2 - (i+1) * (kTriSide/2.0f), 0.0f);
  192. for (int j = 0; j < i+1; ++j) {
  193. canvas->drawPicture(pic);
  194. canvas->translate(SkIntToScalar(kTriSide), 0);
  195. }
  196. canvas->restore();
  197. pic = make_sub_picture(pic.get());
  198. canvas->translate(0, 1.5f * kTriSide / kRoot3);
  199. }
  200. return recorder.finishRecordingAsPicture();
  201. }
  202. static sk_sp<SkSurface> create_compat_surface(SkCanvas* canvas, int width, int height) {
  203. SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
  204. return ToolUtils::makeSurface(canvas, info);
  205. }
  206. // This class stores the information required to compose all the result
  207. // fragments potentially generated by the MultiPictureDraw object
  208. class ComposeStep {
  209. public:
  210. ComposeStep() : fX(0.0f), fY(0.0f), fPaint(nullptr) { }
  211. ~ComposeStep() {
  212. delete fPaint;
  213. }
  214. sk_sp<SkSurface> fSurf;
  215. SkScalar fX;
  216. SkScalar fY;
  217. SkPaint* fPaint;
  218. };
  219. typedef void (*PFContentMtd)(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]);
  220. // Just a single picture with no clip
  221. static void no_clip(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) {
  222. canvas->drawPicture(pictures[0]);
  223. }
  224. // Two pictures with a rect clip on the second one
  225. static void rect_clip(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) {
  226. canvas->drawPicture(pictures[0]);
  227. SkRect rect = pictures[0]->cullRect();
  228. rect.inset(kInset, kInset);
  229. canvas->clipRect(rect);
  230. canvas->drawPicture(pictures[1]);
  231. }
  232. // Two pictures with a round rect clip on the second one
  233. static void rrect_clip(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) {
  234. canvas->drawPicture(pictures[0]);
  235. SkRect rect = pictures[0]->cullRect();
  236. rect.inset(kInset, kInset);
  237. SkRRect rrect;
  238. rrect.setRectXY(rect, kInset, kInset);
  239. canvas->clipRRect(rrect);
  240. canvas->drawPicture(pictures[1]);
  241. }
  242. // Two pictures with a clip path on the second one
  243. static void path_clip(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) {
  244. canvas->drawPicture(pictures[0]);
  245. // Create a hexagon centered on the middle of the hex grid
  246. SkPath hex = make_hex_path((kNumHexX / 2.0f) * kHexSide, kNumHexY * kHexSide * kRoot3Over2);
  247. canvas->clipPath(hex);
  248. canvas->drawPicture(pictures[1]);
  249. }
  250. // Two pictures with an inverse clip path on the second one
  251. static void invpath_clip(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) {
  252. canvas->drawPicture(pictures[0]);
  253. // Create a hexagon centered on the middle of the hex grid
  254. SkPath hex = make_hex_path((kNumHexX / 2.0f) * kHexSide, kNumHexY * kHexSide * kRoot3Over2);
  255. hex.setFillType(SkPath::kInverseEvenOdd_FillType);
  256. canvas->clipPath(hex);
  257. canvas->drawPicture(pictures[1]);
  258. }
  259. // Reuse a single base (triangular) picture a _lot_ (rotated, scaled and translated).
  260. static void sierpinski(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) {
  261. canvas->save();
  262. canvas->drawPicture(pictures[2]);
  263. canvas->rotate(180.0f);
  264. canvas->translate(-SkIntToScalar(kPicWidth), -SkIntToScalar(kPicHeight));
  265. canvas->drawPicture(pictures[2]);
  266. canvas->restore();
  267. }
  268. static void big_layer(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) {
  269. canvas->drawPicture(pictures[3]);
  270. }
  271. constexpr PFContentMtd gContentMthds[] = {
  272. no_clip,
  273. rect_clip,
  274. rrect_clip,
  275. path_clip,
  276. invpath_clip,
  277. sierpinski,
  278. big_layer,
  279. };
  280. static void create_content(SkMultiPictureDraw* mpd, PFContentMtd pfGen,
  281. const SkPicture* pictures[kNumPictures],
  282. SkCanvas* dest, const SkMatrix& xform) {
  283. sk_sp<SkPicture> composite;
  284. {
  285. SkPictureRecorder recorder;
  286. SkRTreeFactory bbhFactory;
  287. SkCanvas* pictureCanvas = recorder.beginRecording(SkIntToScalar(kPicWidth),
  288. SkIntToScalar(kPicHeight),
  289. &bbhFactory);
  290. (*pfGen)(pictureCanvas, pictures);
  291. composite = recorder.finishRecordingAsPicture();
  292. }
  293. mpd->add(dest, composite.get(), &xform);
  294. }
  295. typedef void(*PFLayoutMtd)(SkCanvas* finalCanvas, SkMultiPictureDraw* mpd,
  296. PFContentMtd pfGen, const SkPicture* pictures[kNumPictures],
  297. SkTArray<ComposeStep>* composeSteps);
  298. // Draw the content into a single canvas
  299. static void simple(SkCanvas* finalCanvas, SkMultiPictureDraw* mpd,
  300. PFContentMtd pfGen,
  301. const SkPicture* pictures[kNumPictures],
  302. SkTArray<ComposeStep> *composeSteps) {
  303. ComposeStep& step = composeSteps->push_back();
  304. step.fSurf = create_compat_surface(finalCanvas, kPicWidth, kPicHeight);
  305. SkCanvas* subCanvas = step.fSurf->getCanvas();
  306. create_content(mpd, pfGen, pictures, subCanvas, SkMatrix::I());
  307. }
  308. // Draw the content into multiple canvases/tiles
  309. static void tiled(SkCanvas* finalCanvas, SkMultiPictureDraw* mpd,
  310. PFContentMtd pfGen,
  311. const SkPicture* pictures[kNumPictures],
  312. SkTArray<ComposeStep> *composeSteps) {
  313. const int kNumTilesX = 2;
  314. const int kNumTilesY = 2;
  315. const int kTileWidth = kPicWidth / kNumTilesX;
  316. const int kTileHeight = kPicHeight / kNumTilesY;
  317. SkASSERT(kPicWidth == kNumTilesX * kTileWidth);
  318. SkASSERT(kPicHeight == kNumTilesY * kTileHeight);
  319. const SkColor colors[kNumTilesX][kNumTilesY] = {
  320. { SK_ColorCYAN, SK_ColorMAGENTA },
  321. { SK_ColorYELLOW, SK_ColorGREEN }
  322. };
  323. for (int y = 0; y < kNumTilesY; ++y) {
  324. for (int x = 0; x < kNumTilesX; ++x) {
  325. ComposeStep& step = composeSteps->push_back();
  326. step.fX = SkIntToScalar(x*kTileWidth);
  327. step.fY = SkIntToScalar(y*kTileHeight);
  328. step.fPaint = new SkPaint;
  329. step.fPaint->setColorFilter(
  330. SkColorFilters::Blend(colors[x][y], SkBlendMode::kModulate));
  331. step.fSurf = create_compat_surface(finalCanvas, kTileWidth, kTileHeight);
  332. SkCanvas* subCanvas = step.fSurf->getCanvas();
  333. const SkMatrix trans = SkMatrix::MakeTrans(-SkIntToScalar(x*kTileWidth),
  334. -SkIntToScalar(y*kTileHeight));
  335. create_content(mpd, pfGen, pictures, subCanvas, trans);
  336. }
  337. }
  338. }
  339. constexpr PFLayoutMtd gLayoutMthds[] = { simple, tiled };
  340. namespace skiagm {
  341. /**
  342. * This GM exercises the SkMultiPictureDraw object. It tests the
  343. * cross product of:
  344. * tiled vs. all-at-once rendering (e.g., into many or just 1 canvas)
  345. * different clips (e.g., none, rect, rrect)
  346. * single vs. multiple pictures (e.g., normal vs. picture-pile-style content)
  347. */
  348. class MultiPictureDraw : public GM {
  349. public:
  350. enum Content {
  351. kNoClipSingle_Content,
  352. kRectClipMulti_Content,
  353. kRRectClipMulti_Content,
  354. kPathClipMulti_Content,
  355. kInvPathClipMulti_Content,
  356. kSierpinski_Content,
  357. kBigLayer_Content,
  358. kLast_Content = kBigLayer_Content
  359. };
  360. const int kContentCnt = kLast_Content + 1;
  361. enum Layout {
  362. kSimple_Layout,
  363. kTiled_Layout,
  364. kLast_Layout = kTiled_Layout
  365. };
  366. const int kLayoutCnt = kLast_Layout + 1;
  367. MultiPictureDraw(Content content, Layout layout) : fContent(content), fLayout(layout) {
  368. SkASSERT(SK_ARRAY_COUNT(gLayoutMthds) == kLayoutCnt);
  369. SkASSERT(SK_ARRAY_COUNT(gContentMthds) == kContentCnt);
  370. for (int i = 0; i < kNumPictures; ++i) {
  371. fPictures[i] = nullptr;
  372. }
  373. }
  374. ~MultiPictureDraw() override {
  375. for (int i = 0; i < kNumPictures; ++i) {
  376. SkSafeUnref(fPictures[i]);
  377. }
  378. }
  379. protected:
  380. Content fContent;
  381. Layout fLayout;
  382. const SkPicture* fPictures[kNumPictures];
  383. void onOnceBeforeDraw() override {
  384. fPictures[0] = make_hex_plane_picture(SK_ColorWHITE).release();
  385. fPictures[1] = make_hex_plane_picture(SK_ColorGRAY).release();
  386. fPictures[2] = make_sierpinski_picture().release();
  387. fPictures[3] = make_single_layer_hex_plane_picture().release();
  388. }
  389. void onDraw(SkCanvas* canvas) override {
  390. SkMultiPictureDraw mpd;
  391. SkTArray<ComposeStep> composeSteps;
  392. // Fill up the MultiPictureDraw
  393. (*gLayoutMthds[fLayout])(canvas, &mpd,
  394. gContentMthds[fContent],
  395. fPictures, &composeSteps);
  396. mpd.draw();
  397. // Compose all the drawn canvases into the final canvas
  398. for (int i = 0; i < composeSteps.count(); ++i) {
  399. const ComposeStep& step = composeSteps[i];
  400. canvas->drawImage(step.fSurf->makeImageSnapshot().get(),
  401. step.fX, step.fY, step.fPaint);
  402. }
  403. }
  404. SkISize onISize() override { return SkISize::Make(kPicWidth, kPicHeight); }
  405. SkString onShortName() override {
  406. const char* gContentNames[] = {
  407. "noclip", "rectclip", "rrectclip", "pathclip",
  408. "invpathclip", "sierpinski", "biglayer"
  409. };
  410. const char* gLayoutNames[] = { "simple", "tiled" };
  411. SkASSERT(SK_ARRAY_COUNT(gLayoutNames) == kLayoutCnt);
  412. SkASSERT(SK_ARRAY_COUNT(gContentNames) == kContentCnt);
  413. SkString name("multipicturedraw_");
  414. name.append(gContentNames[fContent]);
  415. name.append("_");
  416. name.append(gLayoutNames[fLayout]);
  417. return name;
  418. }
  419. bool runAsBench() const override { return true; }
  420. private:
  421. typedef GM INHERITED;
  422. };
  423. DEF_GM(return new MultiPictureDraw(MultiPictureDraw::kNoClipSingle_Content,
  424. MultiPictureDraw::kSimple_Layout);)
  425. DEF_GM(return new MultiPictureDraw(MultiPictureDraw::kRectClipMulti_Content,
  426. MultiPictureDraw::kSimple_Layout);)
  427. DEF_GM(return new MultiPictureDraw(MultiPictureDraw::kRRectClipMulti_Content,
  428. MultiPictureDraw::kSimple_Layout);)
  429. DEF_GM(return new MultiPictureDraw(MultiPictureDraw::kPathClipMulti_Content,
  430. MultiPictureDraw::kSimple_Layout);)
  431. DEF_GM(return new MultiPictureDraw(MultiPictureDraw::kInvPathClipMulti_Content,
  432. MultiPictureDraw::kSimple_Layout);)
  433. DEF_GM(return new MultiPictureDraw(MultiPictureDraw::kSierpinski_Content,
  434. MultiPictureDraw::kSimple_Layout);)
  435. DEF_GM(return new MultiPictureDraw(MultiPictureDraw::kBigLayer_Content,
  436. MultiPictureDraw::kSimple_Layout);)
  437. DEF_GM(return new MultiPictureDraw(MultiPictureDraw::kNoClipSingle_Content,
  438. MultiPictureDraw::kTiled_Layout);)
  439. DEF_GM(return new MultiPictureDraw(MultiPictureDraw::kRectClipMulti_Content,
  440. MultiPictureDraw::kTiled_Layout);)
  441. DEF_GM(return new MultiPictureDraw(MultiPictureDraw::kRRectClipMulti_Content,
  442. MultiPictureDraw::kTiled_Layout);)
  443. DEF_GM(return new MultiPictureDraw(MultiPictureDraw::kPathClipMulti_Content,
  444. MultiPictureDraw::kTiled_Layout);)
  445. DEF_GM(return new MultiPictureDraw(MultiPictureDraw::kInvPathClipMulti_Content,
  446. MultiPictureDraw::kTiled_Layout);)
  447. DEF_GM(return new MultiPictureDraw(MultiPictureDraw::kSierpinski_Content,
  448. MultiPictureDraw::kTiled_Layout);)
  449. DEF_GM(return new MultiPictureDraw(MultiPictureDraw::kBigLayer_Content,
  450. MultiPictureDraw::kTiled_Layout);)
  451. }