From 6670ab9e6313e219284bb1df9005c9c3217a52dd Mon Sep 17 00:00:00 2001 From: "robertphillips@google.com" Date: Thu, 9 May 2013 19:03:48 +0000 Subject: Added game-like bench marks https://codereview.chromium.org/14772019/ git-svn-id: http://skia.googlecode.com/svn/trunk@9078 2bbb7eff-a529-9590-31e7-b0007b416f81 --- bench/GameBench.cpp | 206 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 bench/GameBench.cpp (limited to 'bench/GameBench.cpp') 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)); ) + -- cgit v1.2.3