Extend MultiPictureDraw GM
This new GM case is intended to exercise the matrix oriented aspects of layer caching. R=jvanverth@google.com Author: robertphillips@google.com Review URL: https://codereview.chromium.org/582113004
This commit is contained in:
parent
43d361f7fa
commit
3bc25e7247
@ -13,6 +13,7 @@
|
||||
#include "SkSurface.h"
|
||||
|
||||
static const SkScalar kRoot3Over2 = 0.86602545f; // sin(60)
|
||||
static const SkScalar kRoot3 = 1.73205081f;
|
||||
|
||||
static const int kHexSide = 30;
|
||||
static const int kNumHexX = 6;
|
||||
@ -20,6 +21,9 @@ static const int kNumHexY = 6;
|
||||
static const int kPicWidth = kNumHexX * kHexSide;
|
||||
static const int kPicHeight = SkScalarCeilToInt((kNumHexY - 0.5f) * 2 * kHexSide * kRoot3Over2);
|
||||
static const SkScalar kInset = 20.0f;
|
||||
static const int kNumPictures = 3;
|
||||
|
||||
static const int kTriSide = 40;
|
||||
|
||||
// Create a hexagon centered at (originX, originY)
|
||||
static SkPath make_hex_path(SkScalar originX, SkScalar originY) {
|
||||
@ -37,7 +41,7 @@ static SkPath make_hex_path(SkScalar originX, SkScalar originY) {
|
||||
// Make a picture that is a tiling of the plane with stroked hexagons where
|
||||
// each hexagon is in its own layer. The layers are to exercise Ganesh's
|
||||
// layer hoisting.
|
||||
static const SkPicture* make_picture(SkColor fillColor) {
|
||||
static const SkPicture* make_hex_plane_picture(SkColor fillColor) {
|
||||
|
||||
// Create a hexagon with its center at the origin
|
||||
SkPath hex = make_hex_path(0, 0);
|
||||
@ -76,6 +80,93 @@ static const SkPicture* make_picture(SkColor fillColor) {
|
||||
return recorder.endRecording();
|
||||
}
|
||||
|
||||
// Make an equilateral triangle path with its top corner at (originX, originY)
|
||||
static SkPath make_tri_path(SkScalar originX, SkScalar originY) {
|
||||
SkPath tri;
|
||||
tri.moveTo(originX, originY);
|
||||
tri.rLineTo(SkScalarHalf(kTriSide), 1.5f * kTriSide / kRoot3);
|
||||
tri.rLineTo(-kTriSide, 0);
|
||||
tri.close();
|
||||
return tri;
|
||||
}
|
||||
|
||||
static const SkPicture* make_tri_picture() {
|
||||
SkPath tri = make_tri_path(0, 0);
|
||||
|
||||
SkPaint fill;
|
||||
fill.setStyle(SkPaint::kFill_Style);
|
||||
fill.setColor(SK_ColorLTGRAY);;
|
||||
|
||||
SkPaint stroke;
|
||||
stroke.setStyle(SkPaint::kStroke_Style);
|
||||
stroke.setStrokeWidth(3);
|
||||
|
||||
SkPictureRecorder recorder;
|
||||
|
||||
SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kPicWidth),
|
||||
SkIntToScalar(kPicHeight));
|
||||
// The saveLayer/restore block is to exercise layer hoisting
|
||||
canvas->saveLayer(NULL, NULL);
|
||||
canvas->drawPath(tri, fill);
|
||||
canvas->drawPath(tri, stroke);
|
||||
canvas->restore();
|
||||
|
||||
return recorder.endRecording();
|
||||
}
|
||||
|
||||
static const SkPicture* make_sub_picture(const SkPicture* tri) {
|
||||
SkPictureRecorder recorder;
|
||||
|
||||
SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kPicWidth),
|
||||
SkIntToScalar(kPicHeight));
|
||||
|
||||
canvas->scale(1.0f/2.0f, 1.0f/2.0f);
|
||||
|
||||
canvas->drawPicture(tri);
|
||||
|
||||
canvas->save();
|
||||
canvas->translate(SkScalarHalf(kTriSide), 1.5f * kTriSide / kRoot3);
|
||||
canvas->drawPicture(tri);
|
||||
canvas->restore();
|
||||
|
||||
canvas->save();
|
||||
canvas->translate(-SkScalarHalf(kTriSide), 1.5f * kTriSide / kRoot3);
|
||||
canvas->drawPicture(tri);
|
||||
canvas->restore();
|
||||
|
||||
return recorder.endRecording();
|
||||
}
|
||||
|
||||
// Create a Sierpinkski-like picture that starts with a top row with a picture
|
||||
// that just contains a triangle. Subsequent rows take the prior row's picture,
|
||||
// shrinks it and replicates it 3 times then draws and appropriate number of
|
||||
// copies of it.
|
||||
static const SkPicture* make_sierpinski_picture() {
|
||||
SkAutoTUnref<const SkPicture> pic(make_tri_picture());
|
||||
|
||||
SkPictureRecorder recorder;
|
||||
|
||||
SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kPicWidth),
|
||||
SkIntToScalar(kPicHeight));
|
||||
|
||||
static const int kNumLevels = 4;
|
||||
for (int i = 0; i < kNumLevels; ++i) {
|
||||
canvas->save();
|
||||
canvas->translate(-i*kTriSide / 2.0f, 0);
|
||||
for (int j = 0; j < i+1; ++j) {
|
||||
canvas->drawPicture(pic);
|
||||
canvas->translate(SkIntToScalar(kTriSide), 0);
|
||||
}
|
||||
canvas->restore();
|
||||
|
||||
pic.reset(make_sub_picture(pic));
|
||||
|
||||
canvas->translate(0, 1.5f * kTriSide / kRoot3);
|
||||
}
|
||||
|
||||
return recorder.endRecording();
|
||||
}
|
||||
|
||||
static SkSurface* create_compat_surface(SkCanvas* canvas, int width, int height) {
|
||||
SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
|
||||
|
||||
@ -101,15 +192,15 @@ public:
|
||||
SkPaint* fPaint;
|
||||
};
|
||||
|
||||
typedef void (*PFContentMtd)(SkCanvas* canvas, const SkPicture* pictures[2]);
|
||||
typedef void (*PFContentMtd)(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]);
|
||||
|
||||
// Just a single picture with no clip
|
||||
static void no_clip(SkCanvas* canvas, const SkPicture* pictures[2]) {
|
||||
static void no_clip(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) {
|
||||
canvas->drawPicture(pictures[0]);
|
||||
}
|
||||
|
||||
// Two pictures with a rect clip on the second one
|
||||
static void rect_clip(SkCanvas* canvas, const SkPicture* pictures[2]) {
|
||||
static void rect_clip(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) {
|
||||
canvas->drawPicture(pictures[0]);
|
||||
|
||||
SkRect rect = pictures[0]->cullRect();
|
||||
@ -121,7 +212,7 @@ static void rect_clip(SkCanvas* canvas, const SkPicture* pictures[2]) {
|
||||
}
|
||||
|
||||
// Two pictures with a round rect clip on the second one
|
||||
static void rrect_clip(SkCanvas* canvas, const SkPicture* pictures[2]) {
|
||||
static void rrect_clip(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) {
|
||||
canvas->drawPicture(pictures[0]);
|
||||
|
||||
SkRect rect = pictures[0]->cullRect();
|
||||
@ -136,7 +227,7 @@ static void rrect_clip(SkCanvas* canvas, const SkPicture* pictures[2]) {
|
||||
}
|
||||
|
||||
// Two pictures with a clip path on the second one
|
||||
static void path_clip(SkCanvas* canvas, const SkPicture* pictures[2]) {
|
||||
static void path_clip(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) {
|
||||
canvas->drawPicture(pictures[0]);
|
||||
|
||||
// Create a hexagon centered on the middle of the hex grid
|
||||
@ -148,7 +239,7 @@ static void path_clip(SkCanvas* canvas, const SkPicture* pictures[2]) {
|
||||
}
|
||||
|
||||
// Two pictures with an inverse clip path on the second one
|
||||
static void invpath_clip(SkCanvas* canvas, const SkPicture* pictures[2]) {
|
||||
static void invpath_clip(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) {
|
||||
canvas->drawPicture(pictures[0]);
|
||||
|
||||
// Create a hexagon centered on the middle of the hex grid
|
||||
@ -160,16 +251,29 @@ static void invpath_clip(SkCanvas* canvas, const SkPicture* pictures[2]) {
|
||||
canvas->drawPicture(pictures[1]);
|
||||
}
|
||||
|
||||
// Reuse a single base (triangular) picture a _lot_ (rotated, scaled and translated).
|
||||
static void sierpinski(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) {
|
||||
canvas->save();
|
||||
canvas->translate(kPicWidth / 2.0f, 0.0f);
|
||||
canvas->drawPicture(pictures[2]);
|
||||
|
||||
canvas->rotate(180.0f);
|
||||
canvas->translate(0.0f, -SkIntToScalar(kPicHeight));
|
||||
canvas->drawPicture(pictures[2]);
|
||||
canvas->restore();
|
||||
}
|
||||
|
||||
static const PFContentMtd gContentMthds[] = {
|
||||
no_clip,
|
||||
rect_clip,
|
||||
rrect_clip,
|
||||
path_clip,
|
||||
invpath_clip
|
||||
invpath_clip,
|
||||
sierpinski
|
||||
};
|
||||
|
||||
static void create_content(SkMultiPictureDraw* mpd, PFContentMtd pfGen,
|
||||
const SkPicture* pictures[2],
|
||||
const SkPicture* pictures[kNumPictures],
|
||||
SkCanvas* dest, const SkMatrix& xform) {
|
||||
SkAutoTUnref<SkPicture> composite;
|
||||
|
||||
@ -188,13 +292,13 @@ static void create_content(SkMultiPictureDraw* mpd, PFContentMtd pfGen,
|
||||
}
|
||||
|
||||
typedef void(*PFLayoutMtd)(SkCanvas* finalCanvas, SkMultiPictureDraw* mpd,
|
||||
PFContentMtd pfGen, const SkPicture* pictures[2],
|
||||
PFContentMtd pfGen, const SkPicture* pictures[kNumPictures],
|
||||
SkTArray<ComposeStep>* composeSteps);
|
||||
|
||||
// Draw the content into a single canvas
|
||||
static void simple(SkCanvas* finalCanvas, SkMultiPictureDraw* mpd,
|
||||
PFContentMtd pfGen,
|
||||
const SkPicture* pictures[2],
|
||||
const SkPicture* pictures[kNumPictures],
|
||||
SkTArray<ComposeStep> *composeSteps) {
|
||||
|
||||
ComposeStep& step = composeSteps->push_back();
|
||||
@ -209,7 +313,7 @@ static void simple(SkCanvas* finalCanvas, SkMultiPictureDraw* mpd,
|
||||
// Draw the content into multiple canvases/tiles
|
||||
static void tiled(SkCanvas* finalCanvas, SkMultiPictureDraw* mpd,
|
||||
PFContentMtd pfGen,
|
||||
const SkPicture* pictures[2],
|
||||
const SkPicture* pictures[kNumPictures],
|
||||
SkTArray<ComposeStep> *composeSteps) {
|
||||
static const int kNumTilesX = 2;
|
||||
static const int kNumTilesY = 2;
|
||||
@ -264,8 +368,9 @@ namespace skiagm {
|
||||
kRRectClipMulti_Content,
|
||||
kPathClipMulti_Content,
|
||||
kInvPathClipMulti_Content,
|
||||
kSierpinski_Content,
|
||||
|
||||
kLast_Content = kInvPathClipMulti_Content
|
||||
kLast_Content = kSierpinski_Content
|
||||
};
|
||||
|
||||
static const int kContentCnt = kLast_Content + 1;
|
||||
@ -283,22 +388,26 @@ namespace skiagm {
|
||||
SkASSERT(SK_ARRAY_COUNT(gLayoutMthds) == kLayoutCnt);
|
||||
SkASSERT(SK_ARRAY_COUNT(gContentMthds) == kContentCnt);
|
||||
|
||||
fPictures[0] = fPictures[1] = NULL;
|
||||
for (int i = 0; i < kNumPictures; ++i) {
|
||||
fPictures[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~MultiPictureDraw() {
|
||||
SkSafeUnref(fPictures[0]);
|
||||
SkSafeUnref(fPictures[1]);
|
||||
for (int i = 0; i < kNumPictures; ++i) {
|
||||
SkSafeUnref(fPictures[i]);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
Content fContent;
|
||||
Layout fLayout;
|
||||
const SkPicture* fPictures[2];
|
||||
const SkPicture* fPictures[kNumPictures];
|
||||
|
||||
virtual void onOnceBeforeDraw() SK_OVERRIDE {
|
||||
fPictures[0] = make_picture(SK_ColorWHITE);
|
||||
fPictures[1] = make_picture(SK_ColorGRAY);
|
||||
fPictures[0] = make_hex_plane_picture(SK_ColorWHITE);
|
||||
fPictures[1] = make_hex_plane_picture(SK_ColorGRAY);
|
||||
fPictures[2] = SkRef(make_sierpinski_picture());
|
||||
}
|
||||
|
||||
virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
|
||||
@ -326,7 +435,7 @@ namespace skiagm {
|
||||
|
||||
virtual SkString onShortName() SK_OVERRIDE {
|
||||
static const char* gContentNames[] = {
|
||||
"noclip", "rectclip", "rrectclip", "pathclip", "invpathclip"
|
||||
"noclip", "rectclip", "rrectclip", "pathclip", "invpathclip", "sierpinski"
|
||||
};
|
||||
static const char* gLayoutNames[] = { "simple", "tiled" };
|
||||
|
||||
@ -357,6 +466,8 @@ namespace skiagm {
|
||||
MultiPictureDraw::kSimple_Layout));)
|
||||
DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kInvPathClipMulti_Content,
|
||||
MultiPictureDraw::kSimple_Layout));)
|
||||
DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kSierpinski_Content,
|
||||
MultiPictureDraw::kSimple_Layout));)
|
||||
|
||||
DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kNoClipSingle_Content,
|
||||
MultiPictureDraw::kTiled_Layout));)
|
||||
@ -368,4 +479,6 @@ namespace skiagm {
|
||||
MultiPictureDraw::kTiled_Layout));)
|
||||
DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kInvPathClipMulti_Content,
|
||||
MultiPictureDraw::kTiled_Layout));)
|
||||
DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kSierpinski_Content,
|
||||
MultiPictureDraw::kTiled_Layout));)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user