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