/*
 * Copyright 2012 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/SkM44.h"
#include "include/core/SkString.h"
#include "src/base/SkRandom.h"
#include "src/core/SkMatrixPriv.h"

class M4Bench : public Benchmark {
    SkString    fName;
public:
    M4Bench(const char name[]) {
        fName.printf("m4_%s", name);

        SkRandom rand;
        float value[32];
        for (auto& v : value) {
            v = rand.nextF();
        }
        fM1 = SkM44::ColMajor(value + 0);
        fM2 = SkM44::ColMajor(value + 16);
    }

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

    virtual void performTest() = 0;

protected:
    SkM44 fM0, fM1, fM2;

    virtual int mulLoopCount() const { return 1; }

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

    void onDraw(int loops, SkCanvas*) override {
        for (int i = 0; i < loops; i++) {
            this->performTest();
        }
    }

private:
    using INHERITED = Benchmark;
};

class M4NEQ : public M4Bench {
public:
    M4NEQ() : INHERITED("neq") {}
protected:
    void performTest() override {
        for (int i = 0; i < 10000; ++i) {
            fEQ = (fM2 == fM1); // should always be false
        }
    }
private:
    bool fEQ;
    using INHERITED = M4Bench;
};

class M4EQ : public M4Bench {
public:
    M4EQ() : INHERITED("eq") {}
protected:
    void performTest() override {
        fM2 = fM1;
        for (int i = 0; i < 10000; ++i) {
            fEQ = (fM2 == fM1); // should always be true
        }
    }
private:
    bool fEQ;
    using INHERITED = M4Bench;
};

class M4Concat : public M4Bench {
public:
    M4Concat() : INHERITED("op_concat") {}
protected:
    void performTest() override {
        for (int i = 0; i < 10000; ++i) {
            fM0 = SkM44(fM1, fM2);
        }
    }
private:
    using INHERITED = M4Bench;
};

class M4SetConcat : public M4Bench {
public:
    M4SetConcat() : INHERITED("set_concat") {}
protected:
    void performTest() override {
        for (int i = 0; i < 10000; ++i) {
            fM0.setConcat(fM1, fM2);
        }
    }
private:
    using INHERITED = M4Bench;
};

DEF_BENCH( return new M4EQ(); )
DEF_BENCH( return new M4NEQ(); )
DEF_BENCH( return new M4Concat(); )
DEF_BENCH( return new M4SetConcat(); )

class M4_map4 : public M4Bench {
public:
    M4_map4() : INHERITED("map4") {}
protected:
    void performTest() override {
        SkV4 v = {1, 2, 3, 4};
        for (int i = 0; i < 100000; ++i) {
            fV = fM0 * v;
        }
    }
private:
    SkV4 fV;
    using INHERITED = M4Bench;
};
DEF_BENCH( return new M4_map4(); )

class M4_map2 : public M4Bench {
public:
    M4_map2() : INHERITED("map2") {}
protected:
    void performTest() override {
        SkMatrix m;
        m.setRotate(1);
        for (int i = 0; i < 100000; ++i) {
            fV = m.mapXY(5, 6);
        }
    }
private:
    SkPoint fV;
    using INHERITED = M4Bench;
};
DEF_BENCH( return new M4_map2(); )


enum class MapMatrixType {
    kTranslateOnly,
    kScaleTranslate,
    kRotate,
    kPerspective,
    kPerspectiveClipped
};
class MapRectBench : public Benchmark {
    SkString fName;

public:
    MapRectBench(MapMatrixType type, const char name[]) {
        SkRandom rand;
        const char* typeName;
        switch(type) {
            case MapMatrixType::kTranslateOnly:
                typeName = "t";
                fM = SkM44::Translate(rand.nextF(), rand.nextF());
                break;
            case MapMatrixType::kScaleTranslate:
                typeName = "s+t";
                fM = SkM44::Scale(rand.nextF(), rand.nextF());
                fM.postTranslate(rand.nextF(), rand.nextF());
                break;
            case MapMatrixType::kRotate:
                typeName = "r";
                fM = SkM44::Rotate({0.f, 0.f, 1.f}, SkDegreesToRadians(45.f));
                break;
            case MapMatrixType::kPerspective:
                typeName = "p";
                // Hand chosen to have all corners with w > 0 and w != 1
                fM = SkM44::Perspective(0.01f, 10.f, SK_ScalarPI / 3.f);
                fM.preTranslate(0.f, 5.f, -0.1f);
                fM.preConcat(SkM44::Rotate({0.f, 1.f, 0.f}, 0.008f /* radians */));
                break;
            case MapMatrixType::kPerspectiveClipped:
                typeName = "pc";
                // Hand chosen to have some corners with w > 0 and some with w < 0
                fM = SkM44();
                fM.setRow(3, {-.2f, -.6f, 0.f, 8.f});
                break;
        }
        fS = SkRect::MakeXYWH(10.f * rand.nextF(), 10.f * rand.nextF(),
                              150.f * rand.nextF(), 150.f * rand.nextF());

        fName.printf("mapRect_%s_%s", name, typeName);
    }

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

    virtual void performTest() = 0;

protected:
    SkM44 fM;
    SkRect fS, fD;

    virtual int mulLoopCount() const { return 1; }

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

    void onDraw(int loops, SkCanvas*) override {
        for (int i = 0; i < loops; i++) {
            this->performTest();
        }
    }

private:
    using INHERITED = Benchmark;
};

class M4_mapRectBench : public MapRectBench {
public:
    M4_mapRectBench(MapMatrixType type) : INHERITED(type, "m4") {}

protected:
    void performTest() override {
        for (int i = 0; i < 100000; ++i) {
            fD = SkMatrixPriv::MapRect(fM, fS);
        }
    }

private:
    using INHERITED = MapRectBench;
};
DEF_BENCH(return new M4_mapRectBench(MapMatrixType::kTranslateOnly);)
DEF_BENCH(return new M4_mapRectBench(MapMatrixType::kScaleTranslate);)
DEF_BENCH(return new M4_mapRectBench(MapMatrixType::kRotate);)
DEF_BENCH(return new M4_mapRectBench(MapMatrixType::kPerspective);)
DEF_BENCH(return new M4_mapRectBench(MapMatrixType::kPerspectiveClipped);)

class M33_mapRectBench : public MapRectBench {
public:
    M33_mapRectBench(MapMatrixType type) : INHERITED(type, "m33") {
        fM33 = fM.asM33();
    }

protected:
    void performTest() override {
        for (int i = 0; i < 100000; ++i) {
            fD = fM33.mapRect(fS);
        }
    }
private:
    SkMatrix fM33;
    using INHERITED = MapRectBench;
};

DEF_BENCH(return new M33_mapRectBench(MapMatrixType::kTranslateOnly);)
DEF_BENCH(return new M33_mapRectBench(MapMatrixType::kScaleTranslate);)
DEF_BENCH(return new M33_mapRectBench(MapMatrixType::kRotate);)
DEF_BENCH(return new M33_mapRectBench(MapMatrixType::kPerspective);)
DEF_BENCH(return new M33_mapRectBench(MapMatrixType::kPerspectiveClipped);)
