Index: bench/ShapesBench.cpp |
diff --git a/bench/ShapesBench.cpp b/bench/ShapesBench.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4a15c984a8eff3be896bc524ed7125afc592588c |
--- /dev/null |
+++ b/bench/ShapesBench.cpp |
@@ -0,0 +1,210 @@ |
+ |
+/* |
+ * Copyright 2016 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+#include "Benchmark.h" |
+#include "SkCanvas.h" |
+#include "SkCommandLineFlags.h" |
+#include "SkPaint.h" |
+#include "SkRandom.h" |
+#include "SkRRect.h" |
+#include "SkString.h" |
+#include <stdio.h> |
+#include <stdlib.h> |
+#include <functional> |
+ |
+DEFINE_string(shapesType, "mixed", "Type of shape to use in ShapesBench. Must be one of: " |
+ "rect, oval, rrect, mixed."); |
+DEFINE_string(innerShapesType, "none", "Type of inner shape to use in ShapesBench. Must be one of: " |
+ "none, rect, oval, rrect, mixed."); |
+DEFINE_int32(numShapes, 10000, "Number of shapes to draw in ShapesBench."); |
+DEFINE_string(shapesSize, "32x32", "Size of shapes to draw in ShapesBench."); |
+DEFINE_bool(shapesPersp, false, "Use slight perspective tilt in ShapesBench?"); |
Chris Dalton
2016/02/08 20:49:18
This is one extreme where everything comes from co
|
+ |
+class ShapesBench : public Benchmark { |
+public: |
+ ShapesBench() { |
+ if (!strcmp(FLAGS_shapesType[0], "rect")) { |
+ fShapesType = kRect_ShapesType; |
+ } else if (!strcmp(FLAGS_shapesType[0], "oval")) { |
+ fShapesType = kOval_ShapesType; |
+ } else if (!strcmp(FLAGS_shapesType[0], "rrect")) { |
+ fShapesType = kRRect_ShapesType; |
+ } else if (!strcmp(FLAGS_shapesType[0], "mixed")) { |
+ fShapesType = kMixed_ShapesType; |
+ } else { |
+ SkDebugf("Invalid shapesType \"%s\". Must be one of: rect, oval, rrect, mixed.", |
+ FLAGS_shapesType[0]); |
+ exit(-1); |
+ } |
+ if (!strcmp(FLAGS_innerShapesType[0], "none")) { |
+ fInnerShapesType = kNone_ShapesType; |
+ } else if (!strcmp(FLAGS_innerShapesType[0], "rect")) { |
+ fInnerShapesType = kRect_ShapesType; |
+ } else if (!strcmp(FLAGS_innerShapesType[0], "oval")) { |
+ fInnerShapesType = kOval_ShapesType; |
+ } else if (!strcmp(FLAGS_innerShapesType[0], "rrect")) { |
+ fInnerShapesType = kRRect_ShapesType; |
+ } else if (!strcmp(FLAGS_innerShapesType[0], "mixed")) { |
+ fInnerShapesType = kMixed_ShapesType; |
+ } else { |
+ SkDebugf("Invalid innerShapesType \"%s\". Must be one of: " |
+ "none, rect, oval, rrect, mixed.", FLAGS_innerShapesType[0]); |
+ exit(-1); |
+ } |
+ if (2 != sscanf(FLAGS_shapesSize[0], "%ix%i", &fShapesSize.fWidth, &fShapesSize.fHeight)) { |
+ SkDebugf("Could not parse shapesSize from \"%s\". Expected \"%%ix%%i\"\n", |
+ FLAGS_shapesSize[0]); |
+ exit(-1); |
+ } |
+ float maxDiagonal = static_cast<float>(SkTMin(kBenchWidth, kBenchHeight)); |
+ float diagonal = sqrtf(static_cast<float>(fShapesSize.width() * fShapesSize.width()) + |
+ static_cast<float>(fShapesSize.height() * fShapesSize.height())); |
+ if (diagonal > maxDiagonal) { |
+ fShapesSize.fWidth = static_cast<int>(fShapesSize.width() * maxDiagonal / diagonal); |
+ fShapesSize.fHeight = static_cast<int>(fShapesSize.height() * maxDiagonal / diagonal); |
+ } |
+ fName.printf("shapes_%s", FLAGS_shapesType[0]); |
+ if (kNone_ShapesType != fInnerShapesType) { |
+ fName.appendf("_%s", FLAGS_innerShapesType[0]); |
+ } |
+ fName.appendf("_%i_%ix%i", FLAGS_numShapes, fShapesSize.width(), fShapesSize.height()); |
+ if (FLAGS_shapesPersp) { |
+ fName.append("_persp"); |
+ } |
+ } |
+ |
+ bool isVisual() override { return true; } |
+ |
+private: |
+ const char* onGetName() override { return fName.c_str(); } |
+ SkIPoint onGetSize() override { return SkIPoint::Make(kBenchWidth, kBenchHeight); } |
+ |
+ void onDelayedSetup() override { |
+ SkScalar w = SkIntToScalar(fShapesSize.width()); |
+ SkScalar h = SkIntToScalar(fShapesSize.height()); |
+ |
+ fRect.setRect(SkRect::MakeXYWH(-w / 2, -h / 2, w, h)); |
+ fOval.setOval(fRect.rect()); |
+ fRRect.setNinePatch(fRect.rect(), w / 8, h / 13, w / 11, h / 7); |
+ |
+ if (kNone_ShapesType != fInnerShapesType) { |
+ fRect.inset(w / 7, h / 11, &fInnerRect); |
+ fInnerRect.offset(w / 28, h / 44); |
+ fInnerOval.setOval(fInnerRect.rect()); |
+ fInnerRRect.setRectXY(fInnerRect.rect(), w / 13, w / 7); |
+ } |
+ |
+ SkRandom rand; |
+ fShapes.push_back_n(FLAGS_numShapes); |
+ for (int i = 0; i < FLAGS_numShapes; i++) { |
+ float pad = sqrtf(static_cast<float>(fShapesSize.width() * fShapesSize.width()) + |
+ static_cast<float>(fShapesSize.height() * fShapesSize.height())); |
+ fShapes[i].fMatrix.setTranslate(0.5 * pad + rand.nextF() * (kBenchWidth - pad), |
+ 0.5 * pad + rand.nextF() * (kBenchHeight - pad)); |
+ fShapes[i].fMatrix.preRotate(rand.nextF() * 360.0f); |
+ if (FLAGS_shapesPersp) { |
+ fShapes[i].fMatrix.setPerspX(0.00015); |
+ fShapes[i].fMatrix.setPerspY(-0.00015); |
+ } |
+ fShapes[i].fColor = rand.nextU() | 0xff808080; |
+ } |
+ for (int i = 0; i < FLAGS_numShapes; i++) { |
+ // Do this in a separate loop so mixed shapes get the same random numbers during |
+ // placement as non-mixed do. |
+ int shapeType = fShapesType; |
+ if (kMixed_ShapesType == shapeType) { |
+ shapeType = rand.nextRangeU(kRect_ShapesType, kRRect_ShapesType); |
+ } |
+ int innerShapeType = fInnerShapesType; |
+ if (kMixed_ShapesType == innerShapeType) { |
+ innerShapeType = rand.nextRangeU(kRect_ShapesType, kRRect_ShapesType); |
+ } |
+ if (kNone_ShapesType == innerShapeType) { |
+ switch (shapeType) { |
+ using namespace std; |
+ using namespace std::placeholders; |
+ case kRect_ShapesType: |
+ fShapes[i].fDraw = bind(&SkCanvas::drawRect, _1, cref(fRect.rect()), _2); |
+ break; |
+ case kOval_ShapesType: |
+ fShapes[i].fDraw = bind(&SkCanvas::drawOval, _1, cref(fOval.rect()), _2); |
+ break; |
+ case kRRect_ShapesType: |
+ fShapes[i].fDraw = bind(&SkCanvas::drawRRect, _1, cref(fRRect), _2); |
+ break; |
+ } |
+ } else { |
+ const SkRRect* outer; |
+ switch (shapeType) { |
+ case kRect_ShapesType: outer = &fRect; break; |
+ case kOval_ShapesType: outer = &fOval; break; |
+ case kRRect_ShapesType: outer = &fRRect; break; |
+ } |
+ const SkRRect* inner; |
+ switch (innerShapeType) { |
+ case kRect_ShapesType: inner = &fInnerRect; break; |
+ case kOval_ShapesType: inner = &fInnerOval; break; |
+ case kRRect_ShapesType: inner = &fInnerRRect; break; |
+ } |
+ fShapes[i].fDraw = std::bind(&SkCanvas::drawDRRect, std::placeholders::_1, |
+ std::cref(*outer), std::cref(*inner), |
+ std::placeholders::_2); |
+ } |
+ } |
+ } |
+ |
+ void onDraw(int loops, SkCanvas* canvas) override { |
+ SkPaint paint; |
+ this->setupPaint(&paint); |
+ for (int j = 0; j < loops; j++) { |
+ for (int i = 0; i < FLAGS_numShapes; i++) { |
+ canvas->save(); |
+ canvas->setMatrix(fShapes[i].fMatrix); |
+ paint.setColor(fShapes[i].fColor); |
+ fShapes[i].fDraw(canvas, paint); |
+ canvas->restore(); |
+ } |
+ } |
+ } |
+ |
+ enum { |
+ kBenchWidth = 1000, |
+ kBenchHeight = 1000 |
+ }; |
+ |
+ enum ShapesType { |
+ kNone_ShapesType, |
+ kRect_ShapesType, |
+ kOval_ShapesType, |
+ kRRect_ShapesType, |
+ kMixed_ShapesType |
+ }; |
+ |
+ struct ShapeInfo { |
+ SkMatrix fMatrix; |
+ SkColor fColor; |
+ std::function<void(SkCanvas*, const SkPaint&)> fDraw; |
+ }; |
+ |
+ ShapesType fShapesType; |
+ ShapesType fInnerShapesType; |
+ int fNumShapes; |
+ SkISize fShapesSize; |
+ SkString fName; |
+ SkRRect fRect; |
+ SkRRect fOval; |
+ SkRRect fRRect; |
+ SkRRect fInnerRect; |
+ SkRRect fInnerOval; |
+ SkRRect fInnerRRect; |
+ SkTArray<ShapeInfo> fShapes; |
+ |
+ |
+ typedef Benchmark INHERITED; |
+}; |
+ |
+DEF_BENCH(return new ShapesBench;) |