C++程序  |  353行  |  10.42 KB

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