/* * Copyright 2016 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include <memory> #include "Benchmark.h" #include "SkArenaAlloc.h" #include "SkBitmapProcShader.h" #include "SkColor.h" #include "SkArenaAlloc.h" #include "SkImage.h" #include "SkLinearBitmapPipeline.h" #include "SkPM4f.h" #include "SkShader.h" struct CommonBitmapFPBenchmark : public Benchmark { CommonBitmapFPBenchmark( SkISize srcSize, bool isSRGB, SkMatrix m, bool useBilerp, SkShader::TileMode xTile, SkShader::TileMode yTile) : fIsSRGB(isSRGB) , fM{m} , fUseBilerp{useBilerp} , fXTile{xTile} , fYTile{yTile} { fSrcSize = srcSize; } static SkString tileName(const char* pre, SkShader::TileMode mode) { SkString name{pre}; switch (mode) { case SkShader::kClamp_TileMode: name.append("Clamp"); return name; case SkShader::kRepeat_TileMode: name.append("Repeat"); return name; case SkShader::kMirror_TileMode: name.append("Mirror"); return name; default: name.append("Unknown"); return name; } } const char* onGetName() override { fName.set("SkBitmapFP"); if (fM.getType() & SkMatrix::kPerspective_Mask) { fName.append("Perspective"); } else if (fM.getType() & SkMatrix::kAffine_Mask) { fName.append("Affine"); } else if (fM.getType() & SkMatrix::kScale_Mask) { fName.append("Scale"); } else if (fM.getType() & SkMatrix::kTranslate_Mask) { fName.append("Translate"); } else { fName.append("Identity"); } fName.append(tileName("X", fXTile)); fName.append(tileName("Y", fYTile)); if (fUseBilerp) { fName.append("Filter"); } else { fName.append("Nearest"); } fName.appendf("%s", BaseName().c_str()); return fName.c_str(); } void onPreDraw(SkCanvas*) override { int width = fSrcSize.fWidth; int height = fSrcSize.fHeight; fBitmap.reset(new uint32_t[width * height]); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { fBitmap[y * width + x] = (y << 8) + x + (128<<24); } } bool trash = fM.invert(&fInvert); sk_ignore_unused_variable(trash); fInfo = SkImageInfo::MakeN32Premul(width, height, fIsSRGB ? SkColorSpace::MakeSRGB() : nullptr); } bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; } virtual SkString BaseName() = 0; SkString fName; SkISize fSrcSize; bool fIsSRGB; SkMatrix fM; SkMatrix fInvert; bool fUseBilerp; SkShader::TileMode fXTile; SkShader::TileMode fYTile; SkImageInfo fInfo; std::unique_ptr<uint32_t[]> fBitmap; }; struct SkBitmapFPGeneral final : public CommonBitmapFPBenchmark { SkBitmapFPGeneral( SkISize srcSize, bool isSRGB, SkMatrix m, bool useBilerp, SkShader::TileMode xTile, SkShader::TileMode yTile) : CommonBitmapFPBenchmark(srcSize, isSRGB, m, useBilerp, xTile, yTile) { } SkString BaseName() override { SkString name; if (fInfo.gammaCloseToSRGB()) { name.set("sRGB"); } else { name.set("Linr"); } return name; } void onDraw(int loops, SkCanvas*) override { int width = fSrcSize.fWidth; int height = fSrcSize.fHeight; SkAutoTMalloc<SkPM4f> FPbuffer(width*height); SkFilterQuality filterQuality; if (fUseBilerp) { filterQuality = SkFilterQuality::kLow_SkFilterQuality; } else { filterQuality = SkFilterQuality::kNone_SkFilterQuality; } SkPixmap srcPixmap{fInfo, fBitmap.get(), static_cast<size_t>(4 * width)}; char storage[600]; SkArenaAlloc allocator{storage, sizeof(storage), 512}; SkLinearBitmapPipeline pipeline{ fInvert, filterQuality, fXTile, fYTile, SK_ColorBLACK, srcPixmap, &allocator}; int count = 100; for (int n = 0; n < 1000*loops; n++) { pipeline.shadeSpan4f(3, 6, FPbuffer, count); } } }; struct SkBitmapFPOrigShader : public CommonBitmapFPBenchmark { SkBitmapFPOrigShader( SkISize srcSize, bool isSRGB, SkMatrix m, bool useBilerp, SkShader::TileMode xTile, SkShader::TileMode yTile) : CommonBitmapFPBenchmark(srcSize, isSRGB, m, useBilerp, xTile, yTile) { } SkString BaseName() override { SkString name{"Orig"}; return name; } void onPreDraw(SkCanvas* c) override { CommonBitmapFPBenchmark::onPreDraw(c); fImage = SkImage::MakeRasterCopy( SkPixmap(fInfo, fBitmap.get(), sizeof(SkPMColor) * fSrcSize.fWidth)); fPaint.setShader(fImage->makeShader(fXTile, fYTile)); if (fUseBilerp) { fPaint.setFilterQuality(SkFilterQuality::kLow_SkFilterQuality); } else { fPaint.setFilterQuality(SkFilterQuality::kNone_SkFilterQuality); } } void onPostDraw(SkCanvas*) override { } void onDraw(int loops, SkCanvas*) override { int width = fSrcSize.fWidth; int height = fSrcSize.fHeight; SkAutoTMalloc<SkPMColor> buffer4b(width*height); SkArenaAlloc alloc{0}; const SkShader::ContextRec rec(fPaint, fM, nullptr, SkShader::ContextRec::kPMColor_DstType, nullptr); SkShader::Context* ctx = fPaint.getShader()->makeContext(rec, &alloc); int count = 100; for (int n = 0; n < 1000*loops; n++) { ctx->shadeSpan(3, 6, buffer4b, count); } } SkPaint fPaint; sk_sp<SkImage> fImage; }; const bool gSRGB = true; const bool gLinearRGB = false; static SkISize srcSize = SkISize::Make(120, 100); static SkMatrix mI = SkMatrix::I(); DEF_BENCH(return new SkBitmapFPGeneral( srcSize, gSRGB, mI, false, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) DEF_BENCH(return new SkBitmapFPGeneral( srcSize, gLinearRGB, mI, false, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) DEF_BENCH(return new SkBitmapFPOrigShader( srcSize, gLinearRGB, mI, false, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) DEF_BENCH(return new SkBitmapFPGeneral( srcSize, gSRGB, mI, true, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) DEF_BENCH(return new SkBitmapFPGeneral( srcSize, gLinearRGB, mI, true, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) DEF_BENCH(return new SkBitmapFPOrigShader( srcSize, gLinearRGB, mI, true, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) static SkMatrix mS = SkMatrix::MakeScale(2.7f, 2.7f); DEF_BENCH(return new SkBitmapFPGeneral( srcSize, gSRGB, mS, false, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) DEF_BENCH(return new SkBitmapFPGeneral( srcSize, gLinearRGB, mS, false, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) DEF_BENCH(return new SkBitmapFPOrigShader( srcSize, gLinearRGB, mS, false, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) DEF_BENCH(return new SkBitmapFPGeneral( srcSize, gSRGB, mS, true, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) DEF_BENCH(return new SkBitmapFPGeneral( srcSize, gLinearRGB, mS, true, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) DEF_BENCH(return new SkBitmapFPOrigShader( srcSize, gLinearRGB, mS, true, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) // Repeat DEF_BENCH(return new SkBitmapFPGeneral( srcSize, gSRGB, mS, false, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);) DEF_BENCH(return new SkBitmapFPGeneral( srcSize, gLinearRGB, mS, false, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);) DEF_BENCH(return new SkBitmapFPOrigShader( srcSize, gLinearRGB, mS, false, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);) DEF_BENCH(return new SkBitmapFPGeneral( srcSize, gSRGB, mS, true, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);) DEF_BENCH(return new SkBitmapFPGeneral( srcSize, gLinearRGB, mS, true, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);) DEF_BENCH(return new SkBitmapFPOrigShader( srcSize, gLinearRGB, mS, true, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);) static SkMatrix rotate(SkScalar r) { SkMatrix m; m.setRotate(30); return m; } static SkMatrix mR = rotate(30); DEF_BENCH(return new SkBitmapFPGeneral( srcSize, gSRGB, mR, false, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) DEF_BENCH(return new SkBitmapFPGeneral( srcSize, gLinearRGB, mR, false, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) DEF_BENCH(return new SkBitmapFPOrigShader( srcSize, gLinearRGB, mR, false, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) DEF_BENCH(return new SkBitmapFPGeneral( srcSize, gSRGB, mR, true, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) DEF_BENCH(return new SkBitmapFPGeneral( srcSize, gLinearRGB, mR, true, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) DEF_BENCH(return new SkBitmapFPOrigShader( srcSize, gLinearRGB, mR, true, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);) // Repeat DEF_BENCH(return new SkBitmapFPGeneral( srcSize, gSRGB, mR, false, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);) DEF_BENCH(return new SkBitmapFPGeneral( srcSize, gLinearRGB, mR, false, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);) DEF_BENCH(return new SkBitmapFPOrigShader( srcSize, gLinearRGB, mR, false, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);) DEF_BENCH(return new SkBitmapFPGeneral( srcSize, gSRGB, mR, true, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);) DEF_BENCH(return new SkBitmapFPGeneral( srcSize, gLinearRGB, mR, true, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);) DEF_BENCH(return new SkBitmapFPOrigShader( srcSize, gLinearRGB, mR, true, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);)