/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkBenchmark.h"
#include "SkCanvas.h"
#include "SkPaint.h"
#include "SkRandom.h"
#include "SkShader.h"
#include "SkString.h"
#include "SkBlurMask.h"

#define SMALL   SkIntToScalar(2)
#define REAL    SkFloatToScalar(1.5f)
static const SkScalar kMedium = SkIntToScalar(5);
#define BIG     SkIntToScalar(10)
static const SkScalar kMedBig = SkIntToScalar(20);
#define REALBIG SkFloatToScalar(30.5f)

class BlurRectBench: public SkBenchmark {
    int         fLoopCount;
    SkScalar    fRadius;
    SkString    fName;

public:
    BlurRectBench(SkScalar rad) {
        fRadius = rad;

        if (fRadius > SkIntToScalar(25)) {
            fLoopCount = 100;
        } else if (fRadius > SkIntToScalar(5)) {
            fLoopCount = 1000;
        } else {
            fLoopCount = 10000;
        }
    }

protected:
    virtual const char* onGetName() {
        return fName.c_str();
    }

    SkScalar radius() const {
        return fRadius;
    }

    void setName(const SkString& name) {
        fName = name;
    }

    virtual void onDraw(SkCanvas*) {
        SkPaint paint;
        this->setupPaint(&paint);

        paint.setAntiAlias(true);

        SkScalar pad = fRadius*3/2 + SK_Scalar1;
        SkRect r = SkRect::MakeWH(2 * pad + SK_Scalar1, 2 * pad + SK_Scalar1);

        preBenchSetup(r);

        for (int i = 0; i < this->getLoops(); i++) {
            makeBlurryRect(r);
        }
    }

    virtual void makeBlurryRect(const SkRect&) = 0;
    virtual void preBenchSetup(const SkRect&) {}
private:
    typedef SkBenchmark INHERITED;
};


class BlurRectDirectBench: public BlurRectBench {
 public:
    BlurRectDirectBench(SkScalar rad) : INHERITED(rad) {
        SkString name;

        if (SkScalarFraction(rad) != 0) {
            name.printf("blurrect_direct_%.2f", SkScalarToFloat(rad));
        } else {
            name.printf("blurrect_direct_%d", SkScalarRoundToInt(rad));
        }

        this->setName(name);
    }
protected:
    virtual void makeBlurryRect(const SkRect& r) SK_OVERRIDE {
        SkMask mask;
        SkBlurMask::BlurRect(SkBlurMask::ConvertRadiusToSigma(this->radius()),
                             &mask, r, SkBlurMask::kNormal_Style);
        SkMask::FreeImage(mask.fImage);
    }
private:
    typedef BlurRectBench INHERITED;
};

class BlurRectSeparableBench: public BlurRectBench {

public:
    BlurRectSeparableBench(SkScalar rad) : INHERITED(rad) {
        fSrcMask.fImage = NULL;
    }

    ~BlurRectSeparableBench() {
        SkMask::FreeImage(fSrcMask.fImage);
    }

protected:
    virtual void preBenchSetup(const SkRect& r) SK_OVERRIDE {
        SkMask::FreeImage(fSrcMask.fImage);

        r.roundOut(&fSrcMask.fBounds);
        fSrcMask.fFormat = SkMask::kA8_Format;
        fSrcMask.fRowBytes = fSrcMask.fBounds.width();
        fSrcMask.fImage = SkMask::AllocImage(fSrcMask.computeTotalImageSize());

        memset(fSrcMask.fImage, 0xff, fSrcMask.computeTotalImageSize());
    }

    SkMask fSrcMask;
private:
    typedef BlurRectBench INHERITED;
};

class BlurRectBoxFilterBench: public BlurRectSeparableBench {
public:
    BlurRectBoxFilterBench(SkScalar rad) : INHERITED(rad) {
        SkString name;

        if (SkScalarFraction(rad) != 0) {
            name.printf("blurrect_boxfilter_%.2f", SkScalarToFloat(rad));
        } else {
            name.printf("blurrect_boxfilter_%d", SkScalarRoundToInt(rad));
        }

        this->setName(name);
    }

protected:

    virtual void makeBlurryRect(const SkRect&) SK_OVERRIDE {
        SkMask mask;
        mask.fImage = NULL;
        SkBlurMask::BoxBlur(&mask, fSrcMask, SkBlurMask::ConvertRadiusToSigma(this->radius()),
                            SkBlurMask::kNormal_Style,
                            SkBlurMask::kHigh_Quality);
        SkMask::FreeImage(mask.fImage);
    }
private:
    typedef BlurRectSeparableBench INHERITED;
};

class BlurRectGaussianBench: public BlurRectSeparableBench {
public:
    BlurRectGaussianBench(SkScalar rad) : INHERITED(rad) {
        SkString name;

        if (SkScalarFraction(rad) != 0) {
            name.printf("blurrect_gaussian_%.2f", SkScalarToFloat(rad));
        } else {
            name.printf("blurrect_gaussian_%d", SkScalarRoundToInt(rad));
        }

        this->setName(name);
    }

protected:

    virtual void makeBlurryRect(const SkRect&) SK_OVERRIDE {
        SkMask mask;
        mask.fImage = NULL;
        SkBlurMask::BlurGroundTruth(SkBlurMask::ConvertRadiusToSigma(this->radius()),
                                    &mask, fSrcMask, SkBlurMask::kNormal_Style);
        SkMask::FreeImage(mask.fImage);
    }
private:
    typedef BlurRectSeparableBench INHERITED;
};

DEF_BENCH(return new BlurRectBoxFilterBench(SMALL);)
DEF_BENCH(return new BlurRectBoxFilterBench(BIG);)
DEF_BENCH(return new BlurRectBoxFilterBench(REALBIG);)
DEF_BENCH(return new BlurRectBoxFilterBench(REAL);)
DEF_BENCH(return new BlurRectGaussianBench(SMALL);)
DEF_BENCH(return new BlurRectGaussianBench(BIG);)
DEF_BENCH(return new BlurRectGaussianBench(REALBIG);)
DEF_BENCH(return new BlurRectGaussianBench(REAL);)
DEF_BENCH(return new BlurRectDirectBench(SMALL);)
DEF_BENCH(return new BlurRectDirectBench(BIG);)
DEF_BENCH(return new BlurRectDirectBench(REALBIG);)
DEF_BENCH(return new BlurRectDirectBench(REAL);)

DEF_BENCH(return new BlurRectDirectBench(kMedium);)
DEF_BENCH(return new BlurRectDirectBench(kMedBig);)

DEF_BENCH(return new BlurRectBoxFilterBench(kMedium);)
DEF_BENCH(return new BlurRectBoxFilterBench(kMedBig);)

#if 0
// disable Gaussian benchmarks; the algorithm works well enough
// and serves as a baseline for ground truth, but it's too slow
// to use in production for non-trivial radii, so no real point
// in having the bots benchmark it all the time.

DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(1));)
DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(2));)
DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(3));)
DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(4));)
DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(5));)
DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(6));)
DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(7));)
DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(8));)
DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(9));)
DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(10));)
DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(11));)
DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(12));)
DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(13));)
DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(14));)
DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(15));)
DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(16));)
DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(17));)
DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(18));)
DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(19));)
DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(20));)
#endif
