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

#include "bench/Benchmark.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkPaint.h"
#include "include/core/SkShader.h"
#include "include/core/SkString.h"
#include "include/effects/SkGradient.h"
#include "src/base/SkRandom.h"
#include "tools/flags/CommandLineFlags.h"

static DEFINE_double(strokeWidth, -1.0, "If set, use this stroke width in RectBench.");

class RectBench : public Benchmark {
public:
    int fShift, fStroke;
    enum {
        W = 640,
        H = 480,
        N = 300,
    };
    SkRect  fRects[N];
    SkColor fColors[N];
    bool    fAA;
    bool    fPerspective;

    RectBench(int shift, int stroke = 0, bool aa = true, bool perspective = false)
        : fShift(shift)
        , fStroke(stroke)
        , fAA(aa)
        , fPerspective(perspective) {}

    const char* computeName(const char root[]) {
        fBaseName.printf("%s_%d", root, fShift);
        if (fStroke > 0) {
            fBaseName.appendf("_stroke_%d", fStroke);
        }
        if (fAA) {
            fBaseName.appendf("_aa");
        } else {
            fBaseName.appendf("_bw");
        }
        if (fPerspective) {
            fBaseName.appendf("_persp");
        }
        return fBaseName.c_str();
    }

protected:

    virtual void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) {
        c->drawRect(r, p);
    }

    const char* onGetName() override { return computeName("rects"); }

    void onDelayedSetup() override {
        SkRandom rand;
        const SkScalar offset = SK_Scalar1/3;
        for (int i = 0; i < N; i++) {
            int x = rand.nextU() % W;
            int y = rand.nextU() % H;
            int w = rand.nextU() % W;
            int h = rand.nextU() % H;
            w >>= fShift;
            h >>= fShift;
            x -= w/2;
            y -= h/2;
            fRects[i].setXYWH(SkIntToScalar(x), SkIntToScalar(y),
                              SkIntToScalar(w), SkIntToScalar(h));
            fRects[i].offset(offset, offset);
            fColors[i] = rand.nextU() | 0xFF808080;
        }
    }

    void onDraw(int loops, SkCanvas* canvas) override {
        SkPaint paint;
        if (fStroke > 0) {
            paint.setStyle(SkPaint::kStroke_Style);
            paint.setStrokeWidth(SkIntToScalar(fStroke));
        }
        if (fPerspective) {
            // Apply some fixed perspective to change how ops may draw the rects
            SkMatrix perspective;
            perspective.setIdentity();
            perspective.setPerspX(1e-4f);
            perspective.setPerspY(1e-3f);
            perspective.setSkewX(0.1f);
            canvas->concat(perspective);
        }
        for (int i = 0; i < loops; i++) {
            paint.setColor(fColors[i % N]);
            this->setupPaint(&paint);
            this->drawThisRect(canvas, fRects[i % N], paint);
        }
    }

    void setupPaint(SkPaint* paint) override {
        this->INHERITED::setupPaint(paint);
        paint->setAntiAlias(fAA);
    }

private:
    SkString fBaseName;
    using INHERITED = Benchmark;
};

class SrcModeRectBench : public RectBench {
public:
    SrcModeRectBench() : INHERITED(1, 0) {
        fMode = SkBlendMode::kSrc;
    }

protected:
    void setupPaint(SkPaint* paint) override {
        this->INHERITED::setupPaint(paint);
        // srcmode is most interesting when we're not opaque
        paint->setAlpha(0x80);
        paint->setBlendMode(fMode);
    }

    const char* onGetName() override {
        fName.set(this->INHERITED::onGetName());
        fName.prepend("srcmode_");
        return fName.c_str();
    }

private:
    SkBlendMode fMode;
    SkString fName;

    using INHERITED = RectBench;
};

class TransparentRectBench : public RectBench {
public:
    TransparentRectBench() : INHERITED(1, 0) {}

protected:
    void setupPaint(SkPaint* paint) override {
        this->INHERITED::setupPaint(paint);
        // draw non opaque rect
        paint->setAlpha(0x80);
    }

    const char* onGetName() override {
        fName.set(this->INHERITED::onGetName());
        fName.prepend("transparent_");
        return fName.c_str();
    }

private:
    SkString fName;
    using INHERITED = RectBench;
};

// Adds a shader to the paint that requires local coordinates to be used
class LocalCoordsRectBench : public RectBench {
public:
    LocalCoordsRectBench(bool aa, bool perspective = false) : INHERITED(1, 0, aa, perspective) { }

protected:
    void onDelayedSetup() override {
        this->INHERITED::onDelayedSetup();
        // Create the shader once, so that isn't included in the timing
        SkPoint pts[2] = { {0.f, 0.f}, {50.f, 50.f} };
        SkColor4f colors[] = { SkColors::kWhite, SkColors::kBlue };
        fShader = SkShaders::LinearGradient(pts, {{colors, {}, SkTileMode::kClamp}, {}});
    }

    void setupPaint(SkPaint* paint) override {
        this->INHERITED::setupPaint(paint);
        paint->setShader(fShader);
    }

    const char* onGetName() override {
        fName.set(this->INHERITED::onGetName());
        fName.append("_localcoords");
        return fName.c_str();
    }

private:
    SkString fName;
    sk_sp<SkShader> fShader;

    using INHERITED = RectBench;
};


class OvalBench : public RectBench {
public:
    OvalBench(int shift, int stroke = 0) : RectBench(shift, stroke) {}
protected:
    void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) override {
        c->drawOval(r, p);
    }
    const char* onGetName() override { return computeName("ovals"); }
};

class RRectBench : public RectBench {
public:
    RRectBench(int shift, int stroke = 0) : RectBench(shift, stroke) {}
protected:
    void drawThisRect(SkCanvas* c, const SkRect& r, const SkPaint& p) override {
        c->drawRoundRect(r, r.width() / 4, r.height() / 4, p);
    }
    const char* onGetName() override { return computeName("rrects"); }
};

class PointsBench : public RectBench {
public:
    SkCanvas::PointMode fMode;

    PointsBench(SkCanvas::PointMode mode, const char* name)
        : RectBench(2)
        , fMode(mode) {
        fName = name;
    }

protected:
    void onDraw(int loops, SkCanvas* canvas) override {
        SkScalar gSizes[] = {
            SkIntToScalar(7), 0
        };
        size_t sizes = std::size(gSizes);

        if (FLAGS_strokeWidth >= 0) {
            gSizes[0] = (SkScalar)FLAGS_strokeWidth;
            sizes = 1;
        }

        SkPaint paint;
        paint.setStrokeCap(SkPaint::kRound_Cap);

        for (int loop = 0; loop < loops; loop++) {
            for (size_t i = 0; i < sizes; i++) {
                paint.setStrokeWidth(gSizes[i]);
                this->setupPaint(&paint);
                canvas->drawPoints(fMode, {reinterpret_cast<SkPoint*>(fRects), N*2}, paint);
                paint.setColor(fColors[i % N]);
            }
        }
    }
    const char* onGetName() override { return fName.c_str(); }

private:
    SkString fName;

};

class HairPointsBench : public Benchmark {
    static constexpr float W = 640;
    static constexpr float H = 480;
    static constexpr int   N = 300;

    const SkBlendMode      fBM;
    const float            fAlpha;
    std::array<SkPoint, N> fPts;
    SkString               fName;

public:
    HairPointsBench(SkBlendMode bm, float alpha) : fBM(bm), fAlpha(alpha) {

        fName.printf("hair_points_mode_%s_alpha_%g",
                     SkBlendMode_Name(bm), alpha);
    }

protected:
    bool isSuitableFor(Backend backend) override {
        if (backend == Backend::kNonRendering) {
            return false;
        }

        // seems to be a bug on graphic (mali) + src_mode
        auto showsBug = fBM == SkBlendMode::kSrc && backend == Backend::kGraphite;
        return !showsBug;
    }

    const char* onGetName() override { return fName.c_str(); }

    void onDelayedSetup() override {
        SkRandom rand;
        for (auto& p : fPts) {
            const auto x = rand.nextF() * W;
            const auto y = rand.nextF() * H;
            p.set(x, y);
        }
    }

    void onDraw(int loops, SkCanvas* canvas) override {
        SkPaint paint;
        paint.setBlendMode(fBM);
        paint.setAlphaf(fAlpha);
        paint.setStrokeWidth(0);    // we're hairpoints

        for (int loop = 0; loop < loops; loop++) {
            for (int i = 0; i < 1000; ++i)
            canvas->drawPoints(SkCanvas::kPoints_PointMode, fPts, paint);
        }
    }
};


/*******************************************************************************
 * to bench BlitMask [Opaque, Black, color, shader]
 *******************************************************************************/

class BlitMaskBench : public RectBench {
public:
    enum kMaskType {
        kMaskOpaque = 0,
        kMaskBlack,
        kMaskColor,
        KMaskShader
    };
    SkCanvas::PointMode fMode;

    BlitMaskBench(SkCanvas::PointMode mode,
                  BlitMaskBench::kMaskType type, const char* name) :
        RectBench(2), fMode(mode), _type(type) {
        fName = name;
    }

protected:
    void onDraw(int loops, SkCanvas* canvas) override {
        SkScalar gSizes[] = {
            SkIntToScalar(13), SkIntToScalar(24)
        };
        size_t sizes = std::size(gSizes);

        if (FLAGS_strokeWidth >= 0) {
            gSizes[0] = (SkScalar)FLAGS_strokeWidth;
            sizes = 1;
        }
        SkRandom rand;
        SkColor color = 0xFF000000;
        U8CPU alpha = 0xFF;
        SkPaint paint;
        paint.setStrokeCap(SkPaint::kRound_Cap);
        if (_type == KMaskShader) {
            SkBitmap srcBM;
            srcBM.allocN32Pixels(10, 1);
            srcBM.eraseColor(0xFF00FF00);

            paint.setShader(srcBM.makeShader(SkSamplingOptions()));
        }
        for (int loop = 0; loop < loops; loop++) {
            for (size_t i = 0; i < sizes; i++) {
                switch (_type) {
                    case kMaskOpaque:
                        color = fColors[i];
                        alpha = 0xFF;
                        break;
                    case kMaskBlack:
                        alpha = 0xFF;
                        color = 0xFF000000;
                        break;
                    case kMaskColor:
                        color = fColors[i];
                        alpha = rand.nextU() & 255;
                        break;
                    case KMaskShader:
                        break;
                }
                paint.setStrokeWidth(gSizes[i]);
                this->setupPaint(&paint);
                paint.setColor(color);
                paint.setAlpha(alpha);
                canvas->drawPoints(fMode, {reinterpret_cast<SkPoint*>(fRects), N*2}, paint);
           }
        }
    }
    const char* onGetName() override { return fName.c_str(); }

private:
    using INHERITED = RectBench;
    kMaskType _type;
    SkString fName;
};

// AA rects
DEF_BENCH(return new RectBench(1, 0, true);)
DEF_BENCH(return new RectBench(1, 4, true);)
DEF_BENCH(return new RectBench(3, 0, true);)
DEF_BENCH(return new RectBench(3, 4, true);)
// Non-AA rects
DEF_BENCH(return new RectBench(1, 0, false);)
DEF_BENCH(return new RectBench(1, 4, false);)
DEF_BENCH(return new RectBench(3, 0, false);)
DEF_BENCH(return new RectBench(3, 4, false);)

DEF_BENCH(return new OvalBench(1);)
DEF_BENCH(return new OvalBench(3);)
DEF_BENCH(return new OvalBench(1, 4);)
DEF_BENCH(return new OvalBench(3, 4);)
DEF_BENCH(return new RRectBench(1);)
DEF_BENCH(return new RRectBench(1, 4);)
DEF_BENCH(return new RRectBench(3);)
DEF_BENCH(return new RRectBench(3, 4);)

DEF_BENCH(return new HairPointsBench(SkBlendMode::kSrcOver, 0.5f);)
DEF_BENCH(return new HairPointsBench(SkBlendMode::kSrcOver, 1);)
DEF_BENCH(return new HairPointsBench(SkBlendMode::kSrc, 0.5f);)
DEF_BENCH(return new HairPointsBench(SkBlendMode::kSrc, 1);)

DEF_BENCH(return new PointsBench(SkCanvas::kPoints_PointMode, "points");)
DEF_BENCH(return new PointsBench(SkCanvas::kLines_PointMode, "lines");)
DEF_BENCH(return new PointsBench(SkCanvas::kPolygon_PointMode, "polygon");)

DEF_BENCH(return new SrcModeRectBench();)

DEF_BENCH(return new TransparentRectBench();)

DEF_BENCH(return new LocalCoordsRectBench(true);)
DEF_BENCH(return new LocalCoordsRectBench(false);)

// Perspective rects
DEF_BENCH(return new RectBench(1, 0, true, true);)
DEF_BENCH(return new RectBench(1, 0, false, true);)
DEF_BENCH(return new LocalCoordsRectBench(true, true);)
DEF_BENCH(return new LocalCoordsRectBench(false, true);)

/* init the blitmask bench
 */
DEF_BENCH(return new BlitMaskBench(SkCanvas::kPoints_PointMode,
                                   BlitMaskBench::kMaskOpaque,
                                   "maskopaque");)
DEF_BENCH(return new BlitMaskBench(SkCanvas::kPoints_PointMode,
                                   BlitMaskBench::kMaskBlack,
                                   "maskblack");)
DEF_BENCH(return new BlitMaskBench(SkCanvas::kPoints_PointMode,
                                   BlitMaskBench::kMaskColor,
                                   "maskcolor");)
DEF_BENCH(return new BlitMaskBench(SkCanvas::kPoints_PointMode,
                                   BlitMaskBench::KMaskShader,
                                   "maskshader");)

class RectBoundsBench : public Benchmark {
    SkString             fName;
    std::vector<SkPoint> fPoints;

public:
    RectBoundsBench(size_t count)
        : fName(SkStringPrintf("rect_bounds_%zu", count))
        , fPoints(count)
    {}

protected:

    const char* onGetName() override {
        return fName.c_str();
    }

    void onDelayedSetup() override {
        SkRandom rand;
        for (auto& p : fPoints) {
            float x = rand.nextF();
            float y = rand.nextF();
            p = {x, y};
        }
    }

    bool isSuitableFor(Backend backend) override {
        return backend == Backend::kNonRendering;
    }

    void onDraw(int loops, SkCanvas*) override {
        for (int i = 0; i < loops; ++i) {
            (void)SkRect::Bounds(fPoints);
        }
    }
};

DEF_BENCH(return new RectBoundsBench(4);)
DEF_BENCH(return new RectBoundsBench(400);)
