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 "SkColor.h" 10#include "SkLinearBitmapPipeline.h" 11#include "SkPM4f.h" 12#include "Benchmark.h" 13#include "SkShader.h" 14#include "SkImage.h" 15 16struct CommonBitmapFPBenchmark : public Benchmark { 17 CommonBitmapFPBenchmark( 18 SkISize srcSize, 19 SkColorProfileType colorProfile, 20 SkMatrix m, 21 bool useBilerp, 22 SkShader::TileMode xTile, 23 SkShader::TileMode yTile) 24 : fColorProfile(colorProfile) 25 , fM{m} 26 , fUseBilerp{useBilerp} 27 , fXTile{xTile} 28 , fYTile{yTile} { 29 fSrcSize = srcSize; 30 } 31 32 static SkString tileName(const char* pre, SkShader::TileMode mode) { 33 SkString name{pre}; 34 switch (mode) { 35 case SkShader::kClamp_TileMode: 36 name.append("Clamp"); 37 return name; 38 case SkShader::kRepeat_TileMode: 39 name.append("Repeat"); 40 return name; 41 case SkShader::kMirror_TileMode: 42 name.append("Mirror"); 43 return name; 44 default: 45 name.append("Unknown"); 46 return name; 47 } 48 } 49 50 const char* onGetName() override { 51 fName.set("SkBitmapFP"); 52 if (fM.getType() & SkMatrix::kPerspective_Mask) { 53 fName.append("Perspective"); 54 } else if (fM.getType() & SkMatrix::kAffine_Mask) { 55 fName.append("Affine"); 56 } else if (fM.getType() & SkMatrix::kScale_Mask) { 57 fName.append("Scale"); 58 } else if (fM.getType() & SkMatrix::kTranslate_Mask) { 59 fName.append("Translate"); 60 } else { 61 fName.append("Identity"); 62 } 63 64 fName.append(tileName("X", fXTile)); 65 fName.append(tileName("Y", fYTile)); 66 67 if (fUseBilerp) { 68 fName.append("Filter"); 69 } else { 70 fName.append("Nearest"); 71 } 72 73 fName.appendf("%s", BaseName().c_str()); 74 75 return fName.c_str(); 76 } 77 78 void onPreDraw(SkCanvas*) override { 79 int width = fSrcSize.fWidth; 80 int height = fSrcSize.fHeight; 81 fBitmap.reset(new uint32_t[width * height]); 82 for (int y = 0; y < height; y++) { 83 for (int x = 0; x < width; x++) { 84 fBitmap[y * width + x] = (y << 8) + x + (128<<24); 85 } 86 } 87 88 bool trash = fM.invert(&fInvert); 89 sk_ignore_unused_variable(trash); 90 91 fInfo = SkImageInfo::MakeN32Premul(width, height, fColorProfile); 92 } 93 94 bool isSuitableFor(Backend backend) override { 95 return backend == kNonRendering_Backend; 96 } 97 98 virtual SkString BaseName() = 0; 99 100 SkString fName; 101 SkISize fSrcSize; 102 SkColorProfileType fColorProfile; 103 SkMatrix fM; 104 SkMatrix fInvert; 105 bool fUseBilerp; 106 SkShader::TileMode fXTile; 107 SkShader::TileMode fYTile; 108 SkImageInfo fInfo; 109 std::unique_ptr<uint32_t[]> fBitmap; 110}; 111 112struct SkBitmapFPGeneral final : public CommonBitmapFPBenchmark { 113 SkBitmapFPGeneral( 114 SkISize srcSize, 115 SkColorProfileType colorProfile, 116 SkMatrix m, 117 bool useBilerp, 118 SkShader::TileMode xTile, 119 SkShader::TileMode yTile) 120 : CommonBitmapFPBenchmark(srcSize, colorProfile, m, useBilerp, xTile, yTile) { } 121 122 SkString BaseName() override { 123 SkString name; 124 if (fInfo.isSRGB()) { 125 name.set("sRGB"); 126 } else { 127 name.set("Linr"); 128 } 129 return name; 130 } 131 132 void onDraw(int loops, SkCanvas*) override { 133 int width = fSrcSize.fWidth; 134 int height = fSrcSize.fHeight; 135 136 SkAutoTMalloc<SkPM4f> FPbuffer(width*height); 137 138 SkFilterQuality filterQuality; 139 if (fUseBilerp) { 140 filterQuality = SkFilterQuality::kLow_SkFilterQuality; 141 } else { 142 filterQuality = SkFilterQuality::kNone_SkFilterQuality; 143 } 144 145 SkPixmap srcPixmap{fInfo, fBitmap.get(), static_cast<size_t>(4 * width)}; 146 147 SkLinearBitmapPipeline pipeline{ 148 fInvert, filterQuality, fXTile, fYTile, srcPixmap}; 149 150 int count = 100; 151 152 for (int n = 0; n < 1000*loops; n++) { 153 pipeline.shadeSpan4f(3, 6, FPbuffer, count); 154 } 155 } 156}; 157 158struct SkBitmapFPOrigShader : public CommonBitmapFPBenchmark { 159 SkBitmapFPOrigShader( 160 SkISize srcSize, 161 SkColorProfileType colorProfile, 162 SkMatrix m, 163 bool useBilerp, 164 SkShader::TileMode xTile, 165 SkShader::TileMode yTile) 166 : CommonBitmapFPBenchmark(srcSize, colorProfile, m, useBilerp, xTile, yTile) { } 167 168 SkString BaseName() override { 169 SkString name{"Orig"}; 170 return name; 171 } 172 173 void onPreDraw(SkCanvas* c) override { 174 CommonBitmapFPBenchmark::onPreDraw(c); 175 176 SkImage* image = SkImage::NewRasterCopy( 177 fInfo, fBitmap.get(), sizeof(SkPMColor) * fSrcSize.fWidth); 178 fImage.reset(image); 179 SkShader* shader = fImage->newShader(fXTile, fYTile); 180 if (fUseBilerp) { 181 fPaint.setFilterQuality(SkFilterQuality::kLow_SkFilterQuality); 182 } else { 183 fPaint.setFilterQuality(SkFilterQuality::kNone_SkFilterQuality); 184 } 185 fPaint.setShader(shader)->unref(); 186 } 187 188 void onPostDraw(SkCanvas*) override { 189 190 } 191 192 void onDraw(int loops, SkCanvas*) override { 193 int width = fSrcSize.fWidth; 194 int height = fSrcSize.fHeight; 195 196 SkAutoTMalloc<SkPMColor> buffer4b(width*height); 197 198 uint32_t storage[200]; 199 const SkShader::ContextRec rec(fPaint, fM, nullptr, 200 SkShader::ContextRec::kPMColor_DstType); 201 SkASSERT(fPaint.getShader()->contextSize(rec) <= sizeof(storage)); 202 SkShader::Context* ctx = fPaint.getShader()->createContext(rec, storage); 203 204 int count = 100; 205 206 for (int n = 0; n < 1000*loops; n++) { 207 ctx->shadeSpan(3, 6, buffer4b, count); 208 } 209 210 ctx->~Context(); 211 } 212 SkPaint fPaint; 213 SkAutoTUnref<SkImage> fImage; 214}; 215 216static SkISize srcSize = SkISize::Make(120, 100); 217static SkMatrix mI = SkMatrix::I(); 218DEF_BENCH(return new SkBitmapFPGeneral( 219 srcSize, kSRGB_SkColorProfileType, mI, false, 220 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) 221 222DEF_BENCH(return new SkBitmapFPGeneral( 223 srcSize, kLinear_SkColorProfileType, mI, false, 224 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) 225 226DEF_BENCH(return new SkBitmapFPOrigShader( 227 srcSize, kLinear_SkColorProfileType, mI, false, 228 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) 229 230DEF_BENCH(return new SkBitmapFPGeneral( 231 srcSize, kSRGB_SkColorProfileType, mI, true, 232 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) 233 234DEF_BENCH(return new SkBitmapFPGeneral( 235 srcSize, kLinear_SkColorProfileType, mI, true, 236 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) 237 238DEF_BENCH(return new SkBitmapFPOrigShader( 239 srcSize, kLinear_SkColorProfileType, mI, true, 240 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) 241 242static SkMatrix mS = SkMatrix::MakeScale(2.7f, 2.7f); 243DEF_BENCH(return new SkBitmapFPGeneral( 244 srcSize, kSRGB_SkColorProfileType, mS, false, 245 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) 246 247DEF_BENCH(return new SkBitmapFPGeneral( 248 srcSize, kLinear_SkColorProfileType, mS, false, 249 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) 250 251DEF_BENCH(return new SkBitmapFPOrigShader( 252 srcSize, kLinear_SkColorProfileType, mS, false, 253 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) 254 255DEF_BENCH(return new SkBitmapFPGeneral( 256 srcSize, kSRGB_SkColorProfileType, mS, true, 257 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) 258 259DEF_BENCH(return new SkBitmapFPGeneral( 260 srcSize, kLinear_SkColorProfileType, mS, true, 261 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) 262 263DEF_BENCH(return new SkBitmapFPOrigShader( 264 srcSize, kLinear_SkColorProfileType, mS, true, 265 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) 266 267static SkMatrix rotate(SkScalar r) { 268 SkMatrix m; 269 m.setRotate(30); 270 return m; 271} 272 273static SkMatrix mR = rotate(30); 274DEF_BENCH(return new SkBitmapFPGeneral( 275 srcSize, kSRGB_SkColorProfileType, mR, false, 276 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) 277 278DEF_BENCH(return new SkBitmapFPGeneral( 279 srcSize, kLinear_SkColorProfileType, mR, false, 280 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) 281 282DEF_BENCH(return new SkBitmapFPOrigShader( 283 srcSize, kLinear_SkColorProfileType, mR, false, 284 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) 285 286DEF_BENCH(return new SkBitmapFPGeneral( 287 srcSize, kSRGB_SkColorProfileType, mR, true, 288 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) 289 290DEF_BENCH(return new SkBitmapFPGeneral( 291 srcSize, kLinear_SkColorProfileType, mR, true, 292 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) 293 294DEF_BENCH(return new SkBitmapFPOrigShader( 295 srcSize, kLinear_SkColorProfileType, mR, true, 296 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) 297 298