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