1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2014 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "bench/Benchmark.h" 9cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h" 10cb93a386Sopenharmony_ci#include "include/core/SkPaint.h" 11cb93a386Sopenharmony_ci#include "include/effects/SkGradientShader.h" 12cb93a386Sopenharmony_ci#include "src/core/SkBlendModePriv.h" 13cb93a386Sopenharmony_ci 14cb93a386Sopenharmony_ci#include <ctype.h> 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_ci/** This benchmark tests rendering rotated rectangles. It can optionally apply AA and/or change the 17cb93a386Sopenharmony_ci paint color between each rect in different ways using the ColorType enum. The xfermode used can 18cb93a386Sopenharmony_ci be specified as well. 19cb93a386Sopenharmony_ci */ 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_cienum ColorType { 22cb93a386Sopenharmony_ci kConstantOpaque_ColorType, 23cb93a386Sopenharmony_ci kConstantTransparent_ColorType, 24cb93a386Sopenharmony_ci kChangingOpaque_ColorType, 25cb93a386Sopenharmony_ci kChangingTransparent_ColorType, 26cb93a386Sopenharmony_ci kAlternatingOpaqueAndTransparent_ColorType, 27cb93a386Sopenharmony_ci kShaderOpaque_ColorType 28cb93a386Sopenharmony_ci}; 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_cistatic inline SkColor start_color(ColorType ct) { 31cb93a386Sopenharmony_ci switch (ct) { 32cb93a386Sopenharmony_ci case kConstantOpaque_ColorType: 33cb93a386Sopenharmony_ci case kChangingOpaque_ColorType: 34cb93a386Sopenharmony_ci case kAlternatingOpaqueAndTransparent_ColorType: 35cb93a386Sopenharmony_ci return 0xFFA07040; 36cb93a386Sopenharmony_ci case kConstantTransparent_ColorType: 37cb93a386Sopenharmony_ci case kChangingTransparent_ColorType: 38cb93a386Sopenharmony_ci return 0x80A07040; 39cb93a386Sopenharmony_ci case kShaderOpaque_ColorType: 40cb93a386Sopenharmony_ci return SK_ColorWHITE; 41cb93a386Sopenharmony_ci } 42cb93a386Sopenharmony_ci SK_ABORT("Shouldn't reach here."); 43cb93a386Sopenharmony_ci} 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_cistatic inline SkColor advance_color(SkColor old, ColorType ct, int step) { 46cb93a386Sopenharmony_ci if (kAlternatingOpaqueAndTransparent_ColorType == ct) { 47cb93a386Sopenharmony_ci ct = (step & 0x1) ? kChangingOpaque_ColorType : kChangingTransparent_ColorType ; 48cb93a386Sopenharmony_ci } 49cb93a386Sopenharmony_ci switch (ct) { 50cb93a386Sopenharmony_ci case kConstantOpaque_ColorType: 51cb93a386Sopenharmony_ci case kConstantTransparent_ColorType: 52cb93a386Sopenharmony_ci case kShaderOpaque_ColorType: 53cb93a386Sopenharmony_ci return old; 54cb93a386Sopenharmony_ci case kChangingOpaque_ColorType: 55cb93a386Sopenharmony_ci return 0xFF000000 | (old + 0x00010307); 56cb93a386Sopenharmony_ci case kChangingTransparent_ColorType: 57cb93a386Sopenharmony_ci return (0x00FFFFFF & (old + 0x00010307)) | 0x80000000; 58cb93a386Sopenharmony_ci case kAlternatingOpaqueAndTransparent_ColorType: 59cb93a386Sopenharmony_ci SK_ABORT("Can't get here"); 60cb93a386Sopenharmony_ci } 61cb93a386Sopenharmony_ci SK_ABORT("Shouldn't reach here."); 62cb93a386Sopenharmony_ci} 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_cistatic SkString to_lower(const char* str) { 65cb93a386Sopenharmony_ci SkString lower(str); 66cb93a386Sopenharmony_ci for (size_t i = 0; i < lower.size(); i++) { 67cb93a386Sopenharmony_ci lower[i] = tolower(lower[i]); 68cb93a386Sopenharmony_ci } 69cb93a386Sopenharmony_ci return lower; 70cb93a386Sopenharmony_ci} 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_ciclass RotRectBench: public Benchmark { 73cb93a386Sopenharmony_cipublic: 74cb93a386Sopenharmony_ci RotRectBench(bool aa, ColorType ct, SkBlendMode mode, bool perspective = false) 75cb93a386Sopenharmony_ci : fAA(aa) 76cb93a386Sopenharmony_ci , fPerspective(perspective) 77cb93a386Sopenharmony_ci , fColorType(ct) 78cb93a386Sopenharmony_ci , fMode(mode) { 79cb93a386Sopenharmony_ci this->makeName(); 80cb93a386Sopenharmony_ci } 81cb93a386Sopenharmony_ci 82cb93a386Sopenharmony_ciprotected: 83cb93a386Sopenharmony_ci const char* onGetName() override { return fName.c_str(); } 84cb93a386Sopenharmony_ci 85cb93a386Sopenharmony_ci void onDraw(int loops, SkCanvas* canvas) override { 86cb93a386Sopenharmony_ci SkPaint paint; 87cb93a386Sopenharmony_ci paint.setAntiAlias(fAA); 88cb93a386Sopenharmony_ci paint.setBlendMode(fMode); 89cb93a386Sopenharmony_ci SkColor color = start_color(fColorType); 90cb93a386Sopenharmony_ci 91cb93a386Sopenharmony_ci int w = this->getSize().x(); 92cb93a386Sopenharmony_ci int h = this->getSize().y(); 93cb93a386Sopenharmony_ci 94cb93a386Sopenharmony_ci static const SkScalar kRectW = 25.1f; 95cb93a386Sopenharmony_ci static const SkScalar kRectH = 25.9f; 96cb93a386Sopenharmony_ci 97cb93a386Sopenharmony_ci if (fColorType == kShaderOpaque_ColorType) { 98cb93a386Sopenharmony_ci // The only requirement for the shader is that it requires local coordinates 99cb93a386Sopenharmony_ci SkPoint pts[2] = { {0.0f, 0.0f}, {kRectW, kRectH} }; 100cb93a386Sopenharmony_ci SkColor colors[] = { color, SK_ColorBLUE }; 101cb93a386Sopenharmony_ci paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, 2, 102cb93a386Sopenharmony_ci SkTileMode::kClamp)); 103cb93a386Sopenharmony_ci } 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_ci SkMatrix rotate; 106cb93a386Sopenharmony_ci // This value was chosen so that we frequently hit the axis-aligned case. 107cb93a386Sopenharmony_ci rotate.setRotate(30.f, kRectW / 2, kRectH / 2); 108cb93a386Sopenharmony_ci SkMatrix m = rotate; 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_ci SkScalar tx = 0, ty = 0; 111cb93a386Sopenharmony_ci 112cb93a386Sopenharmony_ci if (fPerspective) { 113cb93a386Sopenharmony_ci // Apply some fixed perspective to change how ops may draw the rects 114cb93a386Sopenharmony_ci SkMatrix perspective; 115cb93a386Sopenharmony_ci perspective.setIdentity(); 116cb93a386Sopenharmony_ci perspective.setPerspX(1e-4f); 117cb93a386Sopenharmony_ci perspective.setPerspY(1e-3f); 118cb93a386Sopenharmony_ci perspective.setSkewX(0.1f); 119cb93a386Sopenharmony_ci canvas->concat(perspective); 120cb93a386Sopenharmony_ci } 121cb93a386Sopenharmony_ci 122cb93a386Sopenharmony_ci for (int i = 0; i < loops; ++i) { 123cb93a386Sopenharmony_ci canvas->save(); 124cb93a386Sopenharmony_ci canvas->translate(tx, ty); 125cb93a386Sopenharmony_ci canvas->concat(m); 126cb93a386Sopenharmony_ci paint.setColor(color); 127cb93a386Sopenharmony_ci color = advance_color(color, fColorType, i); 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_ci canvas->drawRect(SkRect::MakeWH(kRectW, kRectH), paint); 130cb93a386Sopenharmony_ci canvas->restore(); 131cb93a386Sopenharmony_ci 132cb93a386Sopenharmony_ci tx += kRectW + 2; 133cb93a386Sopenharmony_ci if (tx > w) { 134cb93a386Sopenharmony_ci tx = 0; 135cb93a386Sopenharmony_ci ty += kRectH + 2; 136cb93a386Sopenharmony_ci if (ty > h) { 137cb93a386Sopenharmony_ci ty = 0; 138cb93a386Sopenharmony_ci } 139cb93a386Sopenharmony_ci } 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_ci m.postConcat(rotate); 142cb93a386Sopenharmony_ci } 143cb93a386Sopenharmony_ci } 144cb93a386Sopenharmony_ci 145cb93a386Sopenharmony_ciprivate: 146cb93a386Sopenharmony_ci void makeName() { 147cb93a386Sopenharmony_ci fName = "rotated_rects"; 148cb93a386Sopenharmony_ci if (fAA) { 149cb93a386Sopenharmony_ci fName.append("_aa"); 150cb93a386Sopenharmony_ci } else { 151cb93a386Sopenharmony_ci fName.append("_bw"); 152cb93a386Sopenharmony_ci } 153cb93a386Sopenharmony_ci if (fPerspective) { 154cb93a386Sopenharmony_ci fName.append("_persp"); 155cb93a386Sopenharmony_ci } 156cb93a386Sopenharmony_ci switch (fColorType) { 157cb93a386Sopenharmony_ci case kConstantOpaque_ColorType: 158cb93a386Sopenharmony_ci fName.append("_same_opaque"); 159cb93a386Sopenharmony_ci break; 160cb93a386Sopenharmony_ci case kConstantTransparent_ColorType: 161cb93a386Sopenharmony_ci fName.append("_same_transparent"); 162cb93a386Sopenharmony_ci break; 163cb93a386Sopenharmony_ci case kChangingOpaque_ColorType: 164cb93a386Sopenharmony_ci fName.append("_changing_opaque"); 165cb93a386Sopenharmony_ci break; 166cb93a386Sopenharmony_ci case kChangingTransparent_ColorType: 167cb93a386Sopenharmony_ci fName.append("_changing_transparent"); 168cb93a386Sopenharmony_ci break; 169cb93a386Sopenharmony_ci case kAlternatingOpaqueAndTransparent_ColorType: 170cb93a386Sopenharmony_ci fName.append("_alternating_transparent_and_opaque"); 171cb93a386Sopenharmony_ci break; 172cb93a386Sopenharmony_ci case kShaderOpaque_ColorType: 173cb93a386Sopenharmony_ci fName.append("_shader_opaque"); 174cb93a386Sopenharmony_ci break; 175cb93a386Sopenharmony_ci } 176cb93a386Sopenharmony_ci fName.appendf("_%s", to_lower(SkBlendMode_Name(fMode)).c_str()); 177cb93a386Sopenharmony_ci } 178cb93a386Sopenharmony_ci 179cb93a386Sopenharmony_ci bool fAA; 180cb93a386Sopenharmony_ci bool fPerspective; 181cb93a386Sopenharmony_ci ColorType fColorType; 182cb93a386Sopenharmony_ci SkBlendMode fMode; 183cb93a386Sopenharmony_ci SkString fName; 184cb93a386Sopenharmony_ci 185cb93a386Sopenharmony_ci using INHERITED = Benchmark; 186cb93a386Sopenharmony_ci}; 187cb93a386Sopenharmony_ci 188cb93a386Sopenharmony_ci#define DEF_FOR_COLOR_TYPES(aa, blend) \ 189cb93a386Sopenharmony_ci DEF_BENCH(return new RotRectBench(aa, kConstantOpaque_ColorType, blend);) \ 190cb93a386Sopenharmony_ci DEF_BENCH(return new RotRectBench(aa, kConstantTransparent_ColorType, blend);) \ 191cb93a386Sopenharmony_ci DEF_BENCH(return new RotRectBench(aa, kChangingOpaque_ColorType, blend);) \ 192cb93a386Sopenharmony_ci DEF_BENCH(return new RotRectBench(aa, kChangingTransparent_ColorType, blend);) \ 193cb93a386Sopenharmony_ci DEF_BENCH(return new RotRectBench(aa, kAlternatingOpaqueAndTransparent_ColorType, blend);) \ 194cb93a386Sopenharmony_ci DEF_BENCH(return new RotRectBench(aa, kShaderOpaque_ColorType, blend);) 195cb93a386Sopenharmony_ci#define DEF_FOR_AA_MODES(blend) \ 196cb93a386Sopenharmony_ci DEF_FOR_COLOR_TYPES(true, blend) \ 197cb93a386Sopenharmony_ci DEF_FOR_COLOR_TYPES(false, blend) 198cb93a386Sopenharmony_ci 199cb93a386Sopenharmony_ci// Choose kSrcOver because it always allows coverage and alpha to be conflated. kSrc only allows 200cb93a386Sopenharmony_ci// conflation when opaque, and kDarken because it isn't possilbe with standard GL blending. 201cb93a386Sopenharmony_ciDEF_FOR_AA_MODES(SkBlendMode::kSrcOver) 202cb93a386Sopenharmony_ciDEF_FOR_AA_MODES(SkBlendMode::kSrc) 203cb93a386Sopenharmony_ciDEF_FOR_AA_MODES(SkBlendMode::kDarken) 204cb93a386Sopenharmony_ci 205cb93a386Sopenharmony_ci// Only do a limited run of perspective tests 206cb93a386Sopenharmony_ci#define DEF_FOR_PERSP_MODES(aa) \ 207cb93a386Sopenharmony_ci DEF_BENCH(return new RotRectBench(aa, kConstantOpaque_ColorType, SkBlendMode::kSrcOver, true);)\ 208cb93a386Sopenharmony_ci DEF_BENCH(return new RotRectBench(aa, kShaderOpaque_ColorType, SkBlendMode::kSrcOver, true);) 209cb93a386Sopenharmony_ciDEF_FOR_PERSP_MODES(true) 210cb93a386Sopenharmony_ciDEF_FOR_PERSP_MODES(false) 211