/*
 * 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/SkCanvas.h"
#include "include/core/SkPaint.h"
#include "include/core/SkShader.h"
#include "include/core/SkString.h"
#include "include/core/SkVertices.h"
#include "include/utils/SkRandom.h"
#include "tools/Resources.h"

// Just want to trigger perspective handling, not dramatically change size
static void tiny_persp_effect(SkCanvas* canvas) {
    SkMatrix m;
    m.reset();
    m[7] = 0.000001f;
    canvas->concat(m);
}

enum VertFlags {
    kColors_VertFlag  = 1 << 0,
    kTexture_VertFlag = 1 << 1,
    kPersp_VertFlag   = 1 << 2,
};

class VertBench : public Benchmark {
    SkString fName;
    enum {
        W = 64*2,
        H = 48*2,
        ROW = 20,
        COL = 20,
        PTS = (ROW + 1) * (COL + 1),
        IDX = ROW * COL * 6,
    };

    sk_sp<SkShader> fShader;
    SkPoint fPts[PTS];
    SkColor fColors[PTS];
    uint16_t fIdx[IDX];
    unsigned fFlags;

    static void load_2_tris(uint16_t idx[], int x, int y, int rb) {
        int n = y * rb + x;
        idx[0] = n; idx[1] = n + 1; idx[2] = rb + n + 1;
        idx[3] = n; idx[4] = rb + n + 1; idx[5] = n + rb;
    }

    void onDelayedSetup() override {
        auto img = GetResourceAsImage("images/mandrill_256.png");
        if (img) {
            fShader = img->makeShader(SkSamplingOptions());
        }
    }

public:
    VertBench(unsigned flags) : fFlags(flags) {
        const SkScalar dx = SkIntToScalar(W) / COL;
        const SkScalar dy = SkIntToScalar(H) / COL;

        SkPoint* pts = fPts;
        uint16_t* idx = fIdx;

        SkScalar yy = 0;
        for (int y = 0; y <= ROW; y++) {
            SkScalar xx = 0;
            for (int x = 0; x <= COL; ++x) {
                pts->set(xx, yy);
                pts += 1;
                xx += dx;

                if (x < COL && y < ROW) {
                    load_2_tris(idx, x, y, COL + 1);
                    for (int i = 0; i < 6; i++) {
                        SkASSERT(idx[i] < PTS);
                    }
                    idx += 6;
                }
            }
            yy += dy;
        }
        SkASSERT(PTS == pts - fPts);
        SkASSERT(IDX == idx - fIdx);

        SkRandom rand;
        for (int i = 0; i < PTS; ++i) {
            fColors[i] = rand.nextU() | (0xFF << 24);
        }

        fName.set("verts");
        if (fFlags & kTexture_VertFlag) {
            fName.append("_textures");
        }
        if (fFlags & kColors_VertFlag) {
            fName.append("_colors");
        }
        if (fFlags & kPersp_VertFlag) {
            fName.append("_persp");
        }
    }

protected:
    const char* onGetName() override { return fName.c_str(); }
    void onDraw(int loops, SkCanvas* canvas) override {
        SkPaint paint;
        this->setupPaint(&paint);
        paint.setShader(fShader);

        if (fFlags & kPersp_VertFlag) {
            tiny_persp_effect(canvas);
        }

        const SkPoint* texs = (fFlags & kTexture_VertFlag) ? fPts    : nullptr;
        const SkColor* cols = (fFlags & kColors_VertFlag)  ? fColors : nullptr;
        auto verts = SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode, PTS,
                                          fPts, texs, cols, IDX, fIdx);
        for (int i = 0; i < loops; i++) {
            canvas->drawVertices(verts, SkBlendMode::kModulate, paint);
        }
    }
private:
    using INHERITED = Benchmark;
};
DEF_BENCH(return new VertBench(kTexture_VertFlag | kPersp_VertFlag);)
DEF_BENCH(return new VertBench(kColors_VertFlag  | kPersp_VertFlag);)
DEF_BENCH(return new VertBench(kTexture_VertFlag);)
DEF_BENCH(return new VertBench(kColors_VertFlag);)
DEF_BENCH(return new VertBench(kColors_VertFlag | kTexture_VertFlag);)

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

#include "include/core/SkRSXform.h"
#include "include/utils/SkRandom.h"
#include "tools/Resources.h"

enum AtlasFlags {
    kColors_Flag = 1 << 0,
    kRotate_Flag = 1 << 1,
    kPersp_Flag  = 1 << 2,
};

class AtlasBench : public Benchmark {
    unsigned fFlags;
    SkString fName;
    enum {
        W = 640,
        H = 480,
        N = 10*1000,
    };

    sk_sp<SkImage>  fAtlas;
    SkRSXform       fXforms[N];
    SkRect          fRects[N];
    SkColor         fColors[N];

public:
    AtlasBench(unsigned flags) : fFlags(flags) {
        fName.printf("drawAtlas");
        if (flags & kColors_Flag) {
            fName.append("_colors");
        }
        if (flags & kRotate_Flag) {
            fName.append("_rotated");
        }
        if (flags & kPersp_Flag) {
            fName.append("_persp");
        }
    }
    ~AtlasBench() override {}

protected:
    const char* onGetName() override { return fName.c_str(); }
    void onDelayedSetup() override {
        fAtlas = GetResourceAsImage("images/mandrill_256.png");
        if (fAtlas) {
            fAtlas = fAtlas->makeRasterImage();
        }

        const SkScalar imageW = fAtlas->width();
        const SkScalar imageH = fAtlas->height();
        SkScalar scos = 1;
        SkScalar ssin = 0;
        if (fFlags & kRotate_Flag) {
            scos = 0.866025403784439f;  // sqrt(3)/2
            ssin = 0.5f;
        }

        SkRandom rand;
        for (int i = 0; i < N; ++i) {
            fRects[i] = SkRect::MakeXYWH(rand.nextF() * (imageW - 8),
                                         rand.nextF() * (imageH - 8), 8, 8);
            fColors[i] = rand.nextU() | 0xFF000000;
            fXforms[i] = SkRSXform::Make(scos, ssin, rand.nextF() * W, rand.nextF() * H);
        }
    }
    void onDraw(int loops, SkCanvas* canvas) override {
        const SkRect* cullRect = nullptr;
        const SkPaint* paintPtr = nullptr;
        const SkColor* colors = nullptr;
        if (fFlags & kColors_Flag) {
            colors = fColors;
        }
        if (fFlags & kPersp_Flag) {
            tiny_persp_effect(canvas);
        }
        for (int i = 0; i < loops; i++) {
            canvas->drawAtlas(fAtlas.get(), fXforms, fRects, colors, N, SkBlendMode::kModulate,
                              SkSamplingOptions(), cullRect, paintPtr);
        }
    }
private:
    using INHERITED = Benchmark;
};
//DEF_BENCH(return new AtlasBench(0);)
//DEF_BENCH(return new AtlasBench(kColors_Flag);)
DEF_BENCH(return new AtlasBench(0);)
DEF_BENCH(return new AtlasBench(kRotate_Flag);)
DEF_BENCH(return new AtlasBench(kPersp_Flag);)
DEF_BENCH(return new AtlasBench(kColors_Flag);)
DEF_BENCH(return new AtlasBench(kColors_Flag | kRotate_Flag);)

