/*
* 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);)