/*
 * 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 "Benchmark.h"
#include "SkMatrix44.h"
#include "SkRandom.h"
#include "SkString.h"

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

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

    virtual void performTest() = 0;

protected:
    virtual int mulLoopCount() const { return 1; }

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

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

private:
    typedef Benchmark INHERITED;
};

class EqualsMatrix44Bench : public Matrix44Bench {
public:
    EqualsMatrix44Bench()
        : INHERITED("equals")
        , fM0(SkMatrix44::kIdentity_Constructor)
        , fM1(SkMatrix44::kIdentity_Constructor)
        , fM2(SkMatrix44::kIdentity_Constructor)
    {
        fM1.set(0, 0, 0);
        fM2.set(3, 3, 0);
    }
protected:
    virtual void performTest() {
        for (int i = 0; i < 10; ++i) {
            (void) (fM0 == fM1);
            (void) (fM1 == fM2);
            (void) (fM2 == fM0);
        }
    }
private:
    SkMatrix44 fM0, fM1, fM2;
    typedef Matrix44Bench INHERITED;
};

class SetIdentityMatrix44Bench : public Matrix44Bench {
public:
    SetIdentityMatrix44Bench()
        : INHERITED("setidentity")
        , mat(SkMatrix44::kIdentity_Constructor)
    {
        double rowMajor[16] =
                { 1, 2, 3, 4,
                  5, 6, 7, 8,
                  9, 10, 11, 12,
                  13, 14, 15, 16};
        mat.setRowMajord(rowMajor);
    }
protected:
    virtual void performTest() {
        for (int i = 0; i < 10; ++i) {
            mat.setIdentity();
        }
    }
private:
    SkMatrix44 mat;
    typedef Matrix44Bench INHERITED;
};

class PreScaleMatrix44Bench : public Matrix44Bench {
public:
    PreScaleMatrix44Bench()
        : INHERITED("prescale")
        , fM0(SkMatrix44::kUninitialized_Constructor)
    {
        fX = fY = fZ = SkDoubleToMScalar(1.5);
    }
protected:
    virtual void performTest() {
        fM0.reset();
        for (int i = 0; i < 10; ++i) {
            fM0.preScale(fX, fY, fZ);
        }
    }
private:
    SkMatrix44 fM0;
    SkMScalar  fX, fY, fZ;
    typedef Matrix44Bench INHERITED;
};

class InvertMatrix44Bench : public Matrix44Bench {
public:
    InvertMatrix44Bench()
        : INHERITED("invert")
        , fM0(SkMatrix44::kUninitialized_Constructor)
        , fM1(SkMatrix44::kUninitialized_Constructor)
    {
        fM0.set(0, 0, -1.1);
        fM0.set(0, 1, 2.1);
        fM0.set(0, 2, -3.1);
        fM0.set(0, 3, 4.1);
        fM0.set(1, 0, 5.1);
        fM0.set(1, 1, -6.1);
        fM0.set(1, 2, 7.1);
        fM0.set(1, 3, 8.1);
        fM0.set(2, 0, -9.1);
        fM0.set(2, 1, 10.1);
        fM0.set(2, 2, 11.1);
        fM0.set(2, 3, -12.1);
        fM0.set(3, 0, -13.1);
        fM0.set(3, 1, 14.1);
        fM0.set(3, 2, -15.1);
        fM0.set(3, 3, 16.1);
    }
protected:
    virtual void performTest() {
        for (int i = 0; i < 10; ++i) {
            fM0.invert(&fM1);
        }
    }
private:
    SkMatrix44 fM0, fM1;
    typedef Matrix44Bench INHERITED;
};

class InvertAffineMatrix44Bench : public Matrix44Bench {
public:
    InvertAffineMatrix44Bench()
        : INHERITED("invertaffine")
        , fM0(SkMatrix44::kIdentity_Constructor)
        , fM1(SkMatrix44::kUninitialized_Constructor)
    {
        fM0.set(0, 0, -1.1);
        fM0.set(0, 1, 2.1);
        fM0.set(0, 2, -3.1);
        fM0.set(0, 3, 4.1);
        fM0.set(1, 0, 5.1);
        fM0.set(1, 1, -6.1);
        fM0.set(1, 2, 7.1);
        fM0.set(1, 3, 8.1);
        fM0.set(2, 0, -9.1);
        fM0.set(2, 1, 10.1);
        fM0.set(2, 2, 11.1);
        fM0.set(2, 3, -12.1);
        // bottom row (perspective component) remains (0, 0, 0, 1).
    }
protected:
    virtual void performTest() {
        for (int i = 0; i < 10; ++i) {
            fM0.invert(&fM1);
        }
    }
private:
    SkMatrix44 fM0, fM1;
    typedef Matrix44Bench INHERITED;
};

class InvertScaleTranslateMatrix44Bench : public Matrix44Bench {
public:
    InvertScaleTranslateMatrix44Bench()
        : INHERITED("invertscaletranslate")
        , fM0(SkMatrix44::kIdentity_Constructor)
        , fM1(SkMatrix44::kUninitialized_Constructor)
    {
        fM0.set(0, 0, -1.1);
        fM0.set(0, 3, 4.1);

        fM0.set(1, 1, -6.1);
        fM0.set(1, 3, 8.1);

        fM0.set(2, 2, 11.1);
        fM0.set(2, 3, -12.1);
    }
protected:
    virtual void performTest() {
        for (int i = 0; i < 10; ++i) {
            fM0.invert(&fM1);
        }
    }
private:
    SkMatrix44 fM0, fM1;
    typedef Matrix44Bench INHERITED;
};

class InvertTranslateMatrix44Bench : public Matrix44Bench {
public:
    InvertTranslateMatrix44Bench()
        : INHERITED("inverttranslate")
        , fM0(SkMatrix44::kIdentity_Constructor)
        , fM1(SkMatrix44::kUninitialized_Constructor)
    {
        fM0.set(0, 3, 4.1);
        fM0.set(1, 3, 8.1);
        fM0.set(2, 3, -12.1);
    }
protected:
    virtual void performTest() {
        for (int i = 0; i < 10; ++i) {
            fM0.invert(&fM1);
        }
    }
private:
    SkMatrix44 fM0, fM1;
    typedef Matrix44Bench INHERITED;
};

class PostScaleMatrix44Bench : public Matrix44Bench {
public:
    PostScaleMatrix44Bench()
        : INHERITED("postscale")
        , fM0(SkMatrix44::kUninitialized_Constructor)
    {
        fX = fY = fZ = SkDoubleToMScalar(1.5);
    }
protected:
    virtual void performTest() {
        fM0.reset();
        for (int i = 0; i < 10; ++i) {
            fM0.postScale(fX, fY, fZ);
        }
    }
private:
    SkMatrix44 fM0;
    SkMScalar  fX, fY, fZ;
    typedef Matrix44Bench INHERITED;
};

class SetConcatMatrix44Bench : public Matrix44Bench {
public:
    SetConcatMatrix44Bench()
        : INHERITED("setconcat")
        , fM0(SkMatrix44::kUninitialized_Constructor)
        , fM1(SkMatrix44::kUninitialized_Constructor)
        , fM2(SkMatrix44::kUninitialized_Constructor)
{
        fX = fY = fZ = SkDoubleToMScalar(1.5);
        fM1.setScale(fX, fY, fZ);
        fM2.setTranslate(fX, fY, fZ);
    }
protected:
    virtual void performTest() {
        fM0.reset();    // just to normalize this test with prescale/postscale
        for (int i = 0; i < 10; ++i) {
            fM0.setConcat(fM1, fM2);
        }
    }
private:
    SkMatrix44 fM0, fM1, fM2;
    SkMScalar  fX, fY, fZ;
    typedef Matrix44Bench INHERITED;
};

class GetTypeMatrix44Bench : public Matrix44Bench {
public:
    GetTypeMatrix44Bench()
        : INHERITED("gettype")
        , fMatrix(SkMatrix44::kIdentity_Constructor)
    {}
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.
    virtual void performTest() {
        for (int i = 0; i < 20; ++i) {
            fMatrix.set(1, 2, 1);   // to invalidate the type-cache
            fMatrix.getType();
        }
    }
private:
    SkMatrix44 fMatrix;
    typedef Matrix44Bench INHERITED;
};

DEF_BENCH( return new SetIdentityMatrix44Bench(); )
DEF_BENCH( return new EqualsMatrix44Bench(); )
DEF_BENCH( return new PreScaleMatrix44Bench(); )
DEF_BENCH( return new PostScaleMatrix44Bench(); )
DEF_BENCH( return new InvertMatrix44Bench(); )
DEF_BENCH( return new InvertAffineMatrix44Bench(); )
DEF_BENCH( return new InvertScaleTranslateMatrix44Bench(); )
DEF_BENCH( return new InvertTranslateMatrix44Bench(); )
DEF_BENCH( return new SetConcatMatrix44Bench(); )
DEF_BENCH( return new GetTypeMatrix44Bench(); )
