|  | /* | 
|  | * Copyright 2014 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 "SkPaint.h" | 
|  |  | 
|  | #include <ctype.h> | 
|  |  | 
|  | /** This benchmark tests rendering rotated rectangles. It can optionally apply AA and/or change the | 
|  | paint color between each rect in different ways using the ColorType enum. The xfermode used can | 
|  | be specified as well. | 
|  | */ | 
|  |  | 
|  | enum ColorType { | 
|  | kConstantOpaque_ColorType, | 
|  | kConstantTransparent_ColorType, | 
|  | kChangingOpaque_ColorType, | 
|  | kChangingTransparent_ColorType, | 
|  | kAlternatingOpaqueAndTransparent_ColorType, | 
|  | }; | 
|  |  | 
|  | static inline SkColor start_color(ColorType ct) { | 
|  | switch (ct) { | 
|  | case kConstantOpaque_ColorType: | 
|  | case kChangingOpaque_ColorType: | 
|  | case kAlternatingOpaqueAndTransparent_ColorType: | 
|  | return 0xFFA07040; | 
|  | case kConstantTransparent_ColorType: | 
|  | case kChangingTransparent_ColorType: | 
|  | return 0x80A07040; | 
|  | } | 
|  | SkFAIL("Shouldn't reach here."); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static inline SkColor advance_color(SkColor old, ColorType ct, int step) { | 
|  | if (kAlternatingOpaqueAndTransparent_ColorType == ct) { | 
|  | ct = (step & 0x1) ? kChangingOpaque_ColorType : kChangingTransparent_ColorType ; | 
|  | } | 
|  | switch (ct) { | 
|  | case kConstantOpaque_ColorType: | 
|  | case kConstantTransparent_ColorType: | 
|  | return old; | 
|  | case kChangingOpaque_ColorType: | 
|  | return 0xFF000000 | (old + 0x00010307); | 
|  | case kChangingTransparent_ColorType: | 
|  | return (0x00FFFFFF & (old + 0x00010307)) | 0x80000000; | 
|  | case kAlternatingOpaqueAndTransparent_ColorType: | 
|  | SkFAIL("Can't get here"); | 
|  | } | 
|  | SkFAIL("Shouldn't reach here."); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static SkString to_lower(const char* str) { | 
|  | SkString lower(str); | 
|  | for (size_t i = 0; i < lower.size(); i++) { | 
|  | lower[i] = tolower(lower[i]); | 
|  | } | 
|  | return lower; | 
|  | } | 
|  |  | 
|  | class RotRectBench: public Benchmark { | 
|  | public: | 
|  | RotRectBench(bool aa, ColorType ct, SkXfermode::Mode mode) | 
|  | : fAA(aa) | 
|  | , fColorType(ct) | 
|  | , fMode(mode) { | 
|  | this->makeName(); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | virtual const char* onGetName() SK_OVERRIDE { return fName.c_str(); } | 
|  |  | 
|  | virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE { | 
|  | SkPaint paint; | 
|  | paint.setAntiAlias(fAA); | 
|  | paint.setXfermodeMode(fMode); | 
|  | SkColor color = start_color(fColorType); | 
|  |  | 
|  | int w = canvas->getBaseLayerSize().width(); | 
|  | int h = canvas->getBaseLayerSize().height(); | 
|  |  | 
|  | static const SkScalar kRectW = 25.1f; | 
|  | static const SkScalar kRectH = 25.9f; | 
|  |  | 
|  | SkMatrix rotate; | 
|  | // This value was chosen so that we frequently hit the axis-aligned case. | 
|  | rotate.setRotate(30.f, kRectW / 2, kRectH / 2); | 
|  | SkMatrix m = rotate; | 
|  |  | 
|  | SkScalar tx = 0, ty = 0; | 
|  |  | 
|  | for (int i = 0; i < loops; ++i) { | 
|  | canvas->save(); | 
|  | canvas->translate(tx, ty); | 
|  | canvas->concat(m); | 
|  | paint.setColor(color); | 
|  | color = advance_color(color, fColorType, i); | 
|  |  | 
|  | canvas->drawRect(SkRect::MakeWH(kRectW, kRectH), paint); | 
|  | canvas->restore(); | 
|  |  | 
|  | tx += kRectW + 2; | 
|  | if (tx > w) { | 
|  | tx = 0; | 
|  | ty += kRectH + 2; | 
|  | if (ty > h) { | 
|  | ty = 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | m.postConcat(rotate); | 
|  | } | 
|  | } | 
|  |  | 
|  | private: | 
|  | void makeName() { | 
|  | fName = "rotated_rects"; | 
|  | if (fAA) { | 
|  | fName.append("_aa"); | 
|  | } else { | 
|  | fName.append("_bw"); | 
|  | } | 
|  | switch (fColorType) { | 
|  | case kConstantOpaque_ColorType: | 
|  | fName.append("_same_opaque"); | 
|  | break; | 
|  | case kConstantTransparent_ColorType: | 
|  | fName.append("_same_transparent"); | 
|  | break; | 
|  | case kChangingOpaque_ColorType: | 
|  | fName.append("_changing_opaque"); | 
|  | break; | 
|  | case kChangingTransparent_ColorType: | 
|  | fName.append("_changing_transparent"); | 
|  | break; | 
|  | case kAlternatingOpaqueAndTransparent_ColorType: | 
|  | fName.append("_alternating_transparent_and_opaque"); | 
|  | break; | 
|  | } | 
|  | fName.appendf("_%s", to_lower(SkXfermode::ModeName(fMode)).c_str()); | 
|  | } | 
|  |  | 
|  | bool             fAA; | 
|  | ColorType        fColorType; | 
|  | SkXfermode::Mode fMode; | 
|  | SkString         fName; | 
|  |  | 
|  | typedef Benchmark INHERITED; | 
|  | }; | 
|  |  | 
|  | // Choose kSrcOver because it always allows coverage and alpha to be conflated. kSrc only allows | 
|  | // conflation when opaque, and kDarken because it isn't possilbe with standard GL blending. | 
|  | DEF_BENCH(return new RotRectBench(true,  kConstantOpaque_ColorType,                  SkXfermode::kSrcOver_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(true,  kConstantTransparent_ColorType,             SkXfermode::kSrcOver_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(true,  kChangingOpaque_ColorType,                  SkXfermode::kSrcOver_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(true,  kChangingTransparent_ColorType,             SkXfermode::kSrcOver_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(true,  kAlternatingOpaqueAndTransparent_ColorType, SkXfermode::kSrcOver_Mode);) | 
|  |  | 
|  | DEF_BENCH(return new RotRectBench(false, kConstantOpaque_ColorType,                  SkXfermode::kSrcOver_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(false, kConstantTransparent_ColorType,             SkXfermode::kSrcOver_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(false, kChangingOpaque_ColorType,                  SkXfermode::kSrcOver_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(false, kChangingTransparent_ColorType,             SkXfermode::kSrcOver_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(false, kAlternatingOpaqueAndTransparent_ColorType, SkXfermode::kSrcOver_Mode);) | 
|  |  | 
|  | DEF_BENCH(return new RotRectBench(true,  kConstantOpaque_ColorType,                  SkXfermode::kSrc_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(true,  kConstantTransparent_ColorType,             SkXfermode::kSrc_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(true,  kChangingOpaque_ColorType,                  SkXfermode::kSrc_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(true,  kChangingTransparent_ColorType,             SkXfermode::kSrc_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(true,  kAlternatingOpaqueAndTransparent_ColorType, SkXfermode::kSrc_Mode);) | 
|  |  | 
|  | DEF_BENCH(return new RotRectBench(false, kConstantOpaque_ColorType,                  SkXfermode::kSrc_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(false, kConstantTransparent_ColorType,             SkXfermode::kSrc_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(false, kChangingOpaque_ColorType,                  SkXfermode::kSrc_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(false, kChangingTransparent_ColorType,             SkXfermode::kSrc_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(false, kAlternatingOpaqueAndTransparent_ColorType, SkXfermode::kSrc_Mode);) | 
|  |  | 
|  | DEF_BENCH(return new RotRectBench(true,  kConstantOpaque_ColorType,                  SkXfermode::kDarken_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(true,  kConstantTransparent_ColorType,             SkXfermode::kDarken_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(true,  kChangingOpaque_ColorType,                  SkXfermode::kDarken_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(true,  kChangingTransparent_ColorType,             SkXfermode::kDarken_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(true,  kAlternatingOpaqueAndTransparent_ColorType, SkXfermode::kDarken_Mode);) | 
|  |  | 
|  | DEF_BENCH(return new RotRectBench(false, kConstantOpaque_ColorType,                  SkXfermode::kDarken_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(false, kConstantTransparent_ColorType,             SkXfermode::kDarken_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(false, kChangingOpaque_ColorType,                  SkXfermode::kDarken_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(false, kChangingTransparent_ColorType,             SkXfermode::kDarken_Mode);) | 
|  | DEF_BENCH(return new RotRectBench(false, kAlternatingOpaqueAndTransparent_ColorType, SkXfermode::kDarken_Mode);) |