/*
 * 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/SkMatrix.h"
#include "include/core/SkString.h"
#include "include/utils/SkRandom.h"
#include "src/core/SkMatrixUtils.h"

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

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

    virtual void performTest() = 0;

protected:
    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 EqualsMatrixBench : public MatrixBench {
public:
    EqualsMatrixBench() : INHERITED("equals") {}
protected:
    void performTest() override {
        SkMatrix m0, m1, m2;

        m0.reset();
        m1.reset();
        m2.reset();

        // xor into a volatile prevents these comparisons from being optimized away.
        [[maybe_unused]] volatile bool junk = false;
        junk ^= (m0 == m1);
        junk ^= (m1 == m2);
        junk ^= (m2 == m0);
    }
private:
    using INHERITED = MatrixBench;
};

class ScaleMatrixBench : public MatrixBench {
public:
    ScaleMatrixBench() : INHERITED("scale") {
        fSX = fSY = 1.5f;
        fM0.reset();
        fM1.setScale(fSX, fSY);
        fM2.setTranslate(fSX, fSY);
    }
protected:
    void performTest() override {
        SkMatrix m;
        m = fM0; m.preScale(fSX, fSY);
        m = fM1; m.preScale(fSX, fSY);
        m = fM2; m.preScale(fSX, fSY);
    }
private:
    SkMatrix fM0, fM1, fM2;
    SkScalar fSX, fSY;
    using INHERITED = MatrixBench;
};

// having unknown values in our arrays can throw off the timing a lot, perhaps
// handling NaN values is a lot slower. Anyway, this is just meant to put
// reasonable values in our arrays.
template <typename T> void init9(T array[9]) {
    SkRandom rand;
    for (int i = 0; i < 9; i++) {
        array[i] = rand.nextSScalar1();
    }
}

class GetTypeMatrixBench : public MatrixBench {
public:
    GetTypeMatrixBench()
        : INHERITED("gettype") {
        fArray[0] = (float) fRnd.nextS();
        fArray[1] = (float) fRnd.nextS();
        fArray[2] = (float) fRnd.nextS();
        fArray[3] = (float) fRnd.nextS();
        fArray[4] = (float) fRnd.nextS();
        fArray[5] = (float) fRnd.nextS();
        fArray[6] = (float) fRnd.nextS();
        fArray[7] = (float) fRnd.nextS();
        fArray[8] = (float) fRnd.nextS();
    }
protected:
    // Putting random generation of the matrix inside performTest()
    // would help us avoid anomalous runs, but takes up 25% or
    // more of the function time.
    void performTest() override {
        fMatrix.setAll(fArray[0], fArray[1], fArray[2],
                       fArray[3], fArray[4], fArray[5],
                       fArray[6], fArray[7], fArray[8]);
        // xoring into a volatile prevents the compiler from optimizing these away
        [[maybe_unused]] volatile int junk = 0;
        junk ^= (fMatrix.getType());
        fMatrix.dirtyMatrixTypeCache();
        junk ^= (fMatrix.getType());
        fMatrix.dirtyMatrixTypeCache();
        junk ^= (fMatrix.getType());
        fMatrix.dirtyMatrixTypeCache();
        junk ^= (fMatrix.getType());
        fMatrix.dirtyMatrixTypeCache();
        junk ^= (fMatrix.getType());
        fMatrix.dirtyMatrixTypeCache();
        junk ^= (fMatrix.getType());
        fMatrix.dirtyMatrixTypeCache();
        junk ^= (fMatrix.getType());
        fMatrix.dirtyMatrixTypeCache();
        junk ^= (fMatrix.getType());
    }
private:
    SkMatrix fMatrix;
    float fArray[9];
    SkRandom fRnd;
    using INHERITED = MatrixBench;
};

class DecomposeMatrixBench : public MatrixBench {
public:
    DecomposeMatrixBench() : INHERITED("decompose") {}

protected:
    void onDelayedSetup() override {
        for (int i = 0; i < 10; ++i) {
            SkScalar rot0 = (fRandom.nextBool()) ? fRandom.nextRangeF(-180, 180) : 0.0f;
            SkScalar sx = fRandom.nextRangeF(-3000.f, 3000.f);
            SkScalar sy = (fRandom.nextBool()) ? fRandom.nextRangeF(-3000.f, 3000.f) : sx;
            SkScalar rot1 = fRandom.nextRangeF(-180, 180);
            fMatrix[i].setRotate(rot0);
            fMatrix[i].postScale(sx, sy);
            fMatrix[i].postRotate(rot1);
        }
    }
    void performTest() override {
        SkPoint rotation1, scale, rotation2;
        for (int i = 0; i < 10; ++i) {
            (void) SkDecomposeUpper2x2(fMatrix[i], &rotation1, &scale, &rotation2);
        }
    }
private:
    SkMatrix fMatrix[10];
    SkRandom fRandom;
    using INHERITED = MatrixBench;
};

class InvertMapRectMatrixBench : public MatrixBench {
public:
    InvertMapRectMatrixBench(const char* name, int flags)
        : INHERITED(name)
        , fFlags(flags) {
        fMatrix.reset();
        fIteration = 0;
        if (flags & kScale_Flag) {
            fMatrix.postScale(1.5f, 2.5f);
        }
        if (flags & kTranslate_Flag) {
            fMatrix.postTranslate(1.5f, 2.5f);
        }
        if (flags & kRotate_Flag) {
            fMatrix.postRotate(45.0f);
        }
        if (flags & kPerspective_Flag) {
            fMatrix.setPerspX(1.5f);
            fMatrix.setPerspY(2.5f);
        }
        if (0 == (flags & kUncachedTypeMask_Flag)) {
            fMatrix.getType();
        }
    }
    enum Flag {
        kScale_Flag             = 0x01,
        kTranslate_Flag         = 0x02,
        kRotate_Flag            = 0x04,
        kPerspective_Flag       = 0x08,
        kUncachedTypeMask_Flag  = 0x10,
    };
protected:
    void performTest() override {
        if (fFlags & kUncachedTypeMask_Flag) {
            // This will invalidate the typemask without
            // changing the matrix.
            fMatrix.setPerspX(fMatrix.getPerspX());
        }
        SkMatrix inv;
        bool invertible = fMatrix.invert(&inv);
        SkASSERT(invertible);
        SkRect transformedRect;
        // an arbitrary, small, non-zero rect to transform
        SkRect srcRect = SkRect::MakeWH(SkIntToScalar(10), SkIntToScalar(10));
        if (invertible) {
            inv.mapRect(&transformedRect, srcRect);
        }
    }
private:
    SkMatrix fMatrix;
    int fFlags;
    unsigned fIteration;
    using INHERITED = MatrixBench;
};

///////////////////////////////////////////////////////////////////////////////

DEF_BENCH( return new EqualsMatrixBench(); )
DEF_BENCH( return new ScaleMatrixBench(); )
DEF_BENCH( return new GetTypeMatrixBench(); )
DEF_BENCH( return new DecomposeMatrixBench(); )

DEF_BENCH( return new InvertMapRectMatrixBench("invert_maprect_identity", 0); )

DEF_BENCH(return new InvertMapRectMatrixBench(
                                  "invert_maprect_rectstaysrect",
                                  InvertMapRectMatrixBench::kScale_Flag |
                                  InvertMapRectMatrixBench::kTranslate_Flag); )

DEF_BENCH(return new InvertMapRectMatrixBench(
                                  "invert_maprect_translate",
                                  InvertMapRectMatrixBench::kTranslate_Flag); )

DEF_BENCH(return new InvertMapRectMatrixBench(
                                  "invert_maprect_nonpersp",
                                  InvertMapRectMatrixBench::kScale_Flag |
                                  InvertMapRectMatrixBench::kRotate_Flag |
                                  InvertMapRectMatrixBench::kTranslate_Flag); )

DEF_BENCH( return new InvertMapRectMatrixBench(
                               "invert_maprect_persp",
                               InvertMapRectMatrixBench::kPerspective_Flag); )

DEF_BENCH( return new InvertMapRectMatrixBench(
                           "invert_maprect_typemask_rectstaysrect",
                           InvertMapRectMatrixBench::kUncachedTypeMask_Flag |
                           InvertMapRectMatrixBench::kScale_Flag |
                           InvertMapRectMatrixBench::kTranslate_Flag); )

DEF_BENCH( return new InvertMapRectMatrixBench(
                           "invert_maprect_typemask_nonpersp",
                           InvertMapRectMatrixBench::kUncachedTypeMask_Flag |
                           InvertMapRectMatrixBench::kScale_Flag |
                           InvertMapRectMatrixBench::kRotate_Flag |
                           InvertMapRectMatrixBench::kTranslate_Flag); )

///////////////////////////////////////////////////////////////////////////////

static SkMatrix make_trans() { return SkMatrix::Translate(2, 3); }
static SkMatrix make_scale() { SkMatrix m(make_trans()); m.postScale(1.5f, 0.5f); return m; }
static SkMatrix make_afine() { SkMatrix m(make_trans()); m.postRotate(15); return m; }

class MapPointsMatrixBench : public MatrixBench {
protected:
    SkMatrix fM;
    enum {
        N = 32
    };
    SkPoint fSrc[N], fDst[N];
public:
    MapPointsMatrixBench(const char name[], const SkMatrix& m)
        : MatrixBench(name), fM(m)
    {
        SkRandom rand;
        for (int i = 0; i < N; ++i) {
            fSrc[i].set(rand.nextSScalar1(), rand.nextSScalar1());
        }
    }

    void performTest() override {
        for (int i = 0; i < 1000000; ++i) {
            fM.mapPoints(fDst, fSrc, N);
        }
    }
};
DEF_BENCH( return new MapPointsMatrixBench("mappoints_identity", SkMatrix::I()); )
DEF_BENCH( return new MapPointsMatrixBench("mappoints_trans", make_trans()); )
DEF_BENCH( return new MapPointsMatrixBench("mappoints_scale", make_scale()); )
DEF_BENCH( return new MapPointsMatrixBench("mappoints_affine", make_afine()); )

///////////////////////////////////////////////////////////////////////////////

class MapRectMatrixBench : public MatrixBench {
    SkMatrix fM;
    SkRect   fR;
    bool     fScaleTrans;

    enum { MEGA_LOOP = 1000 * 1000 };
public:
    MapRectMatrixBench(const char name[], bool scale_trans)
        : MatrixBench(name), fScaleTrans(scale_trans)
    {
        fM.setScale(2, 3);
        fM.postTranslate(1, 2);

        fR.setLTRB(10, 10, 100, 200);
    }

    void performTest() override {
        SkRect dst;
        if (fScaleTrans) {
            for (int i = 0; i < MEGA_LOOP; ++i) {
                fM.mapRectScaleTranslate(&dst, fR);
            }
        } else {
            for (int i = 0; i < MEGA_LOOP; ++i) {
                fM.mapRect(&dst, fR);
            }
        }
    }
};
DEF_BENCH( return new MapRectMatrixBench("maprect", false); )
DEF_BENCH( return new MapRectMatrixBench("maprectscaletrans", true); )
