aboutsummaryrefslogtreecommitdiffhomepage
path: root/bench/GameBench.cpp
diff options
context:
space:
mode:
authorGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-05-09 19:03:48 +0000
committerGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-05-09 19:03:48 +0000
commit6670ab9e6313e219284bb1df9005c9c3217a52dd (patch)
treeadcd9c6191a4fa9fa17ce51556435719e1e5ec6b /bench/GameBench.cpp
parentee2c3b9fb31987fc0db5143b91c0dddd006d112e (diff)
Added game-like bench marks
Diffstat (limited to 'bench/GameBench.cpp')
-rw-r--r--bench/GameBench.cpp206
1 files changed, 206 insertions, 0 deletions
diff --git a/bench/GameBench.cpp b/bench/GameBench.cpp
new file mode 100644
index 0000000000..2dcdf6720d
--- /dev/null
+++ b/bench/GameBench.cpp
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkBenchmark.h"
+#include "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkRandom.h"
+#include "SkString.h"
+
+
+// This bench simulates the calls Skia sees from various HTML5 canvas
+// game bench marks
+class GameBench : public SkBenchmark {
+public:
+ enum Type {
+ kScale_Type,
+ kTranslate_Type,
+ kRotate_Type
+ };
+
+ GameBench(void* param, Type type, bool partialClear)
+ : INHERITED(param)
+ , fType(type)
+ , fPartialClear(partialClear)
+ , fName("game")
+ , fNumSaved(0)
+ , fInitialized(false) {
+
+ switch (fType) {
+ case kScale_Type:
+ fName.append("_scale");
+ break;
+ case kTranslate_Type:
+ fName.append("_trans");
+ break;
+ case kRotate_Type:
+ fName.append("_rot");
+ break;
+ };
+
+ if (partialClear) {
+ fName.append("_partial");
+ } else {
+ fName.append("_full");
+ }
+
+ // It's HTML 5 canvas, so always AA
+ fName.append("_aa");
+ }
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return fName.c_str();;
+ }
+
+ virtual void onPreDraw() SK_OVERRIDE {
+ if (!fInitialized) {
+ this->makeCheckerboard();
+ fInitialized = true;
+ }
+ }
+
+ virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
+ static SkMWCRandom scaleRand;
+ static SkMWCRandom transRand;
+ static SkMWCRandom rotRand;
+
+ SkPaint clearPaint;
+ clearPaint.setColor(0xFF000000);
+ clearPaint.setAntiAlias(true);
+
+ SkISize size = canvas->getDeviceSize();
+
+ SkScalar maxTransX, maxTransY;
+
+ if (kScale_Type == fType) {
+ maxTransX = size.fWidth - (1.5f * kCheckerboardWidth);
+ maxTransY = size.fHeight - (1.5f * kCheckerboardHeight);
+ } else if (kTranslate_Type == fType) {
+ maxTransX = SkIntToScalar(size.fWidth - kCheckerboardWidth);
+ maxTransY = SkIntToScalar(size.fHeight - kCheckerboardHeight);
+ } else {
+ SkASSERT(kRotate_Type == fType);
+ // Yes, some rotations will be off the top and left sides
+ maxTransX = size.fWidth - SK_ScalarSqrt2 * kCheckerboardHeight;
+ maxTransY = size.fHeight - SK_ScalarSqrt2 * kCheckerboardHeight;
+ }
+
+ SkMatrix mat;
+ SkIRect src = { 0, 0, kCheckerboardWidth, kCheckerboardHeight };
+ SkRect dst = { 0, 0, kCheckerboardWidth, kCheckerboardHeight };
+ SkRect clearRect = { -1.0f, -1.0f,
+ kCheckerboardWidth+1.0f, kCheckerboardHeight+1.0f };
+
+ SkPaint p;
+ p.setColor(0xFF000000);
+ p.setFilterBitmap(true);
+
+ for (int i = 0; i < kNumRects; ++i, ++fNumSaved) {
+
+ if (0 == i % kNumBeforeClear) {
+ if (fPartialClear) {
+ for (int j = 0; j < fNumSaved; ++j) {
+ canvas->setMatrix(SkMatrix::I());
+ mat.setTranslate(fSaved[j][0], fSaved[j][1]);
+
+ if (kScale_Type == fType) {
+ mat.preScale(fSaved[j][2], fSaved[j][2]);
+ } else if (kRotate_Type == fType) {
+ mat.preRotate(fSaved[j][2]);
+ }
+
+ canvas->concat(mat);
+ canvas->drawRect(clearRect, clearPaint);
+ }
+ } else {
+ canvas->clear(0xFF000000);
+ }
+
+ fNumSaved = 0;
+ }
+
+ SkASSERT(fNumSaved < kNumBeforeClear);
+
+ canvas->setMatrix(SkMatrix::I());
+
+ fSaved[fNumSaved][0] = transRand.nextRangeScalar(0.0f, maxTransX);
+ fSaved[fNumSaved][1] = transRand.nextRangeScalar(0.0f, maxTransY);
+
+ mat.setTranslate(fSaved[fNumSaved][0], fSaved[fNumSaved][1]);
+
+ if (kScale_Type == fType) {
+ fSaved[fNumSaved][2] = scaleRand.nextRangeScalar(0.5f, 1.5f);
+ mat.preScale(fSaved[fNumSaved][2], fSaved[fNumSaved][2]);
+ } else if (kRotate_Type == fType) {
+ fSaved[fNumSaved][2] = rotRand.nextRangeScalar(0.0f, 360.0f);
+ mat.preRotate(fSaved[fNumSaved][2]);
+ }
+
+ canvas->concat(mat);
+ canvas->drawBitmapRect(fCheckerboard, &src, dst, &p);
+ }
+ }
+
+private:
+ static const int kCheckerboardWidth = 64;
+ static const int kCheckerboardHeight = 128;
+#ifdef SK_DEBUG
+ static const int kNumRects = 100;
+ static const int kNumBeforeClear = 10;
+#else
+ static const int kNumRects = 5000;
+ static const int kNumBeforeClear = 300;
+#endif
+
+
+ Type fType;
+ bool fPartialClear;
+ SkString fName;
+ int fNumSaved; // num draws stored in 'fSaved'
+ bool fInitialized;
+
+ // 0 & 1 are always x & y translate. 2 is either scale or rotate.
+ SkScalar fSaved[kNumBeforeClear][3];
+ SkBitmap fCheckerboard;
+
+ // Note: the resulting checker board has transparency
+ void makeCheckerboard() {
+ static unsigned int kCheckSize = 16;
+
+ fCheckerboard.setConfig(SkBitmap::kARGB_8888_Config,
+ kCheckerboardWidth, kCheckerboardHeight);
+ fCheckerboard.allocPixels();
+ SkAutoLockPixels lock(fCheckerboard);
+ for (unsigned int y = 0; y < kCheckerboardHeight; ++y) {
+ int even = (y / kCheckSize) % 2;
+
+ SkPMColor* scanline = fCheckerboard.getAddr32(0, y);
+
+ for (unsigned int x = 0; x < kCheckerboardWidth; ++x) {
+ if (even == (x / kCheckSize) % 2) {
+ *scanline++ = 0xFFFF0000;
+ } else {
+ *scanline++ = 0x00000000;
+ }
+ }
+ }
+ }
+
+ typedef SkBenchmark INHERITED;
+};
+
+// Partial clear
+DEF_BENCH( return SkNEW_ARGS(GameBench, (p, GameBench::kScale_Type, false)); )
+DEF_BENCH( return SkNEW_ARGS(GameBench, (p, GameBench::kTranslate_Type, false)); )
+DEF_BENCH( return SkNEW_ARGS(GameBench, (p, GameBench::kRotate_Type, false)); )
+
+// Full clear
+DEF_BENCH( return SkNEW_ARGS(GameBench, (p, GameBench::kScale_Type, true)); )
+DEF_BENCH( return SkNEW_ARGS(GameBench, (p, GameBench::kTranslate_Type, true)); )
+DEF_BENCH( return SkNEW_ARGS(GameBench, (p, GameBench::kRotate_Type, true)); )
+