xref: /aosp_15_r20/external/skia/bench/RotatedRectBench.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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