1 /*
2  * Copyright 2016 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include <memory>
9 #include "Benchmark.h"
10 
11 #include "SkArenaAlloc.h"
12 #include "SkBitmapProcShader.h"
13 #include "SkColor.h"
14 #include "SkArenaAlloc.h"
15 #include "SkImage.h"
16 #include "SkLinearBitmapPipeline.h"
17 #include "SkPM4f.h"
18 #include "SkShader.h"
19 
20 struct CommonBitmapFPBenchmark : public Benchmark {
CommonBitmapFPBenchmarkCommonBitmapFPBenchmark21     CommonBitmapFPBenchmark(
22         SkISize srcSize,
23         bool isSRGB,
24         SkMatrix m,
25         bool useBilerp,
26         SkShader::TileMode xTile,
27         SkShader::TileMode yTile)
28         : fIsSRGB(isSRGB)
29         , fM{m}
30         , fUseBilerp{useBilerp}
31         , fXTile{xTile}
32         , fYTile{yTile} {
33         fSrcSize = srcSize;
34     }
35 
tileNameCommonBitmapFPBenchmark36     static SkString tileName(const char* pre, SkShader::TileMode mode) {
37         SkString name{pre};
38         switch (mode) {
39             case SkShader::kClamp_TileMode:
40                 name.append("Clamp");
41                 return name;
42             case SkShader::kRepeat_TileMode:
43                 name.append("Repeat");
44                 return name;
45             case SkShader::kMirror_TileMode:
46                 name.append("Mirror");
47                 return name;
48             default:
49                 name.append("Unknown");
50                 return name;
51         }
52     }
53 
onGetNameCommonBitmapFPBenchmark54     const char* onGetName() override {
55         fName.set("SkBitmapFP");
56         if (fM.getType() & SkMatrix::kPerspective_Mask) {
57             fName.append("Perspective");
58         } else if (fM.getType() & SkMatrix::kAffine_Mask) {
59             fName.append("Affine");
60         } else if (fM.getType() & SkMatrix::kScale_Mask) {
61             fName.append("Scale");
62         } else if (fM.getType() & SkMatrix::kTranslate_Mask) {
63             fName.append("Translate");
64         } else {
65             fName.append("Identity");
66         }
67 
68         fName.append(tileName("X", fXTile));
69         fName.append(tileName("Y", fYTile));
70 
71         if (fUseBilerp) {
72             fName.append("Filter");
73         } else {
74             fName.append("Nearest");
75         }
76 
77         fName.appendf("%s", BaseName().c_str());
78 
79         return fName.c_str();
80     }
81 
onPreDrawCommonBitmapFPBenchmark82     void onPreDraw(SkCanvas*) override {
83         int width = fSrcSize.fWidth;
84         int height = fSrcSize.fHeight;
85         fBitmap.reset(new uint32_t[width * height]);
86         for (int y = 0; y < height; y++) {
87             for (int x = 0; x < width; x++) {
88                 fBitmap[y * width + x] = (y << 8) + x + (128<<24);
89             }
90         }
91 
92         bool trash = fM.invert(&fInvert);
93         sk_ignore_unused_variable(trash);
94 
95         fInfo = SkImageInfo::MakeN32Premul(width, height, fIsSRGB ?
96                                       SkColorSpace::MakeSRGB() : nullptr);
97     }
98 
isSuitableForCommonBitmapFPBenchmark99     bool isSuitableFor(Backend backend) override {
100         return backend == kNonRendering_Backend;
101     }
102 
103     virtual SkString BaseName() = 0;
104 
105     SkString fName;
106     SkISize fSrcSize;
107     bool fIsSRGB;
108     SkMatrix fM;
109     SkMatrix fInvert;
110     bool fUseBilerp;
111     SkShader::TileMode fXTile;
112     SkShader::TileMode fYTile;
113     SkImageInfo fInfo;
114     std::unique_ptr<uint32_t[]> fBitmap;
115 };
116 
117 struct SkBitmapFPGeneral final : public CommonBitmapFPBenchmark {
SkBitmapFPGeneralSkBitmapFPGeneral118     SkBitmapFPGeneral(
119         SkISize srcSize,
120         bool isSRGB,
121         SkMatrix m,
122         bool useBilerp,
123         SkShader::TileMode xTile,
124         SkShader::TileMode yTile)
125             : CommonBitmapFPBenchmark(srcSize, isSRGB, m, useBilerp, xTile, yTile) { }
126 
BaseNameSkBitmapFPGeneral127     SkString BaseName() override {
128         SkString name;
129         if (fInfo.gammaCloseToSRGB()) {
130             name.set("sRGB");
131         } else {
132             name.set("Linr");
133         }
134         return name;
135     }
136 
onDrawSkBitmapFPGeneral137     void onDraw(int loops, SkCanvas*) override {
138         int width = fSrcSize.fWidth;
139         int height = fSrcSize.fHeight;
140 
141         SkAutoTMalloc<SkPM4f> FPbuffer(width*height);
142 
143         SkFilterQuality filterQuality;
144         if (fUseBilerp) {
145             filterQuality = SkFilterQuality::kLow_SkFilterQuality;
146         } else {
147             filterQuality = SkFilterQuality::kNone_SkFilterQuality;
148         }
149 
150         SkPixmap srcPixmap{fInfo, fBitmap.get(), static_cast<size_t>(4 * width)};
151 
152 
153         char storage[600];
154         SkArenaAlloc allocator{storage, sizeof(storage), 512};
155         SkLinearBitmapPipeline pipeline{
156             fInvert, filterQuality, fXTile, fYTile, SK_ColorBLACK, srcPixmap, &allocator};
157 
158         int count = 100;
159 
160         for (int n = 0; n < 1000*loops; n++) {
161             pipeline.shadeSpan4f(3, 6, FPbuffer, count);
162         }
163     }
164 };
165 
166 struct SkBitmapFPOrigShader : public CommonBitmapFPBenchmark {
SkBitmapFPOrigShaderSkBitmapFPOrigShader167     SkBitmapFPOrigShader(
168         SkISize srcSize,
169         bool isSRGB,
170         SkMatrix m,
171         bool useBilerp,
172         SkShader::TileMode xTile,
173         SkShader::TileMode yTile)
174             : CommonBitmapFPBenchmark(srcSize, isSRGB, m, useBilerp, xTile, yTile) { }
175 
BaseNameSkBitmapFPOrigShader176     SkString BaseName() override {
177         SkString name{"Orig"};
178         return name;
179     }
180 
onPreDrawSkBitmapFPOrigShader181     void onPreDraw(SkCanvas* c) override {
182         CommonBitmapFPBenchmark::onPreDraw(c);
183 
184         fImage = SkImage::MakeRasterCopy(
185             SkPixmap(fInfo, fBitmap.get(), sizeof(SkPMColor) * fSrcSize.fWidth));
186         fPaint.setShader(fImage->makeShader(fXTile, fYTile));
187         if (fUseBilerp) {
188             fPaint.setFilterQuality(SkFilterQuality::kLow_SkFilterQuality);
189         } else {
190             fPaint.setFilterQuality(SkFilterQuality::kNone_SkFilterQuality);
191         }
192     }
193 
onPostDrawSkBitmapFPOrigShader194     void onPostDraw(SkCanvas*) override {
195 
196     }
197 
onDrawSkBitmapFPOrigShader198     void onDraw(int loops, SkCanvas*) override {
199         int width = fSrcSize.fWidth;
200         int height = fSrcSize.fHeight;
201 
202         SkAutoTMalloc<SkPMColor> buffer4b(width*height);
203 
204         SkArenaAlloc alloc{0};
205         const SkShader::ContextRec rec(fPaint, fM, nullptr,
206                                        SkShader::ContextRec::kPMColor_DstType,
207                                        nullptr);
208         SkShader::Context* ctx = fPaint.getShader()->makeContext(rec, &alloc);
209 
210         int count = 100;
211 
212         for (int n = 0; n < 1000*loops; n++) {
213             ctx->shadeSpan(3, 6, buffer4b, count);
214         }
215     }
216     SkPaint fPaint;
217     sk_sp<SkImage> fImage;
218 };
219 
220 const bool gSRGB = true;
221 const bool gLinearRGB = false;
222 static SkISize srcSize = SkISize::Make(120, 100);
223 static SkMatrix mI = SkMatrix::I();
224 DEF_BENCH(return new SkBitmapFPGeneral(
225     srcSize, gSRGB, mI, false,
226     SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);)
227 
228 DEF_BENCH(return new SkBitmapFPGeneral(
229     srcSize, gLinearRGB, mI, false,
230     SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);)
231 
232 DEF_BENCH(return new SkBitmapFPOrigShader(
233     srcSize, gLinearRGB, mI, false,
234     SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);)
235 
236 DEF_BENCH(return new SkBitmapFPGeneral(
237     srcSize, gSRGB, mI, true,
238     SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);)
239 
240 DEF_BENCH(return new SkBitmapFPGeneral(
241     srcSize, gLinearRGB, mI, true,
242     SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);)
243 
244 DEF_BENCH(return new SkBitmapFPOrigShader(
245     srcSize, gLinearRGB, mI, true,
246     SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);)
247 
248 static SkMatrix mS = SkMatrix::MakeScale(2.7f, 2.7f);
249 DEF_BENCH(return new SkBitmapFPGeneral(
250     srcSize, gSRGB, mS, false,
251     SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);)
252 
DEF_BENCH(return new SkBitmapFPGeneral (srcSize,gLinearRGB,mS,false,SkShader::kClamp_TileMode,SkShader::kClamp_TileMode);)253 DEF_BENCH(return new SkBitmapFPGeneral(
254     srcSize, gLinearRGB, mS, false,
255     SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);)
256 
257 DEF_BENCH(return new SkBitmapFPOrigShader(
258     srcSize, gLinearRGB, mS, false,
259     SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);)
260 
261 DEF_BENCH(return new SkBitmapFPGeneral(
262     srcSize, gSRGB, mS, true,
263     SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);)
264 
265 DEF_BENCH(return new SkBitmapFPGeneral(
266     srcSize, gLinearRGB, mS, true,
267     SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);)
268 
269 DEF_BENCH(return new SkBitmapFPOrigShader(
270     srcSize, gLinearRGB, mS, true,
271     SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);)
272 
273 // Repeat
274 DEF_BENCH(return new SkBitmapFPGeneral(
275     srcSize, gSRGB, mS, false,
276     SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);)
277 
278 DEF_BENCH(return new SkBitmapFPGeneral(
279     srcSize, gLinearRGB, mS, false,
280     SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);)
281 
282 DEF_BENCH(return new SkBitmapFPOrigShader(
283     srcSize, gLinearRGB, mS, false,
284     SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);)
285 
286 DEF_BENCH(return new SkBitmapFPGeneral(
287     srcSize, gSRGB, mS, true,
288     SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);)
289 
290 DEF_BENCH(return new SkBitmapFPGeneral(
291     srcSize, gLinearRGB, mS, true,
292     SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);)
293 
294 DEF_BENCH(return new SkBitmapFPOrigShader(
295     srcSize, gLinearRGB, mS, true,
296     SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);)
297 
298 static SkMatrix rotate(SkScalar r) {
299     SkMatrix m;
300     m.setRotate(30);
301     return m;
302 }
303 
304 static SkMatrix mR = rotate(30);
305 DEF_BENCH(return new SkBitmapFPGeneral(
306     srcSize, gSRGB, mR, false,
307     SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);)
308 
309 DEF_BENCH(return new SkBitmapFPGeneral(
310     srcSize, gLinearRGB, mR, false,
311     SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);)
312 
313 DEF_BENCH(return new SkBitmapFPOrigShader(
314     srcSize, gLinearRGB, mR, false,
315     SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);)
316 
317 DEF_BENCH(return new SkBitmapFPGeneral(
318     srcSize, gSRGB, mR, true,
319     SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);)
320 
321 DEF_BENCH(return new SkBitmapFPGeneral(
322     srcSize, gLinearRGB, mR, true,
323     SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);)
324 
325 DEF_BENCH(return new SkBitmapFPOrigShader(
326     srcSize, gLinearRGB, mR, true,
327     SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);)
328 
329 // Repeat
330 DEF_BENCH(return new SkBitmapFPGeneral(
331     srcSize, gSRGB, mR, false,
332     SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);)
333 
334 DEF_BENCH(return new SkBitmapFPGeneral(
335     srcSize, gLinearRGB, mR, false,
336     SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);)
337 
338 DEF_BENCH(return new SkBitmapFPOrigShader(
339     srcSize, gLinearRGB, mR, false,
340     SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);)
341 
342 DEF_BENCH(return new SkBitmapFPGeneral(
343     srcSize, gSRGB, mR, true,
344     SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);)
345 
346 DEF_BENCH(return new SkBitmapFPGeneral(
347     srcSize, gLinearRGB, mR, true,
348     SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);)
349 
350 DEF_BENCH(return new SkBitmapFPOrigShader(
351     srcSize, gLinearRGB, mR, true,
352     SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);)
353