/*
 * Copyright 2014 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 "SkCanvas.h"
#include "SkGradientShader.h"
#include "SkPaint.h"
#include "SkString.h"

enum ColorPattern {
    kWhite_ColorPattern,
    kBlue_ColorPattern,
    kOpaqueBitmap_ColorPattern,
    kAlphaBitmap_ColorPattern,
};

static const struct ColorPatternData{
    SkColor         fColor;
    bool            fIsBitmap;
    const char*     fName;
} gColorPatterns[] = {
    // Keep this in same order as ColorPattern enum
    { SK_ColorWHITE, false,  "white"        }, // kWhite_ColorPattern
    { SK_ColorBLUE,  false,  "blue"         }, // kBlue_ColorPattern
    { SK_ColorWHITE, true,   "obaqueBitMap" }, // kOpaqueBitmap_ColorPattern
    { 0x10000000,    true,   "alphaBitmap"  }, // kAlphaBitmap_ColorPattern
};

enum DrawType {
    kRect_DrawType,
    kPath_DrawType,
};

static void makebm(SkBitmap* bm, int w, int h) {
    bm->allocN32Pixels(w, h);
    bm->eraseColor(SK_ColorTRANSPARENT);

    SkCanvas    canvas(*bm);
    SkScalar    s = SkIntToScalar(SkMin32(w, h));
    static const SkPoint     kPts0[] = { { 0, 0 }, { s, s } };
    static const SkPoint     kPts1[] = { { s/2, 0 }, { s/2, s } };
    static const SkScalar    kPos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
    static const SkColor kColors0[] = {0x80F00080, 0xF0F08000, 0x800080F0 };
    static const SkColor kColors1[] = {0xF08000F0, 0x8080F000, 0xF000F080 };


    SkPaint     paint;

    paint.setShader(SkGradientShader::CreateLinear(kPts0, kColors0, kPos,
                    SK_ARRAY_COUNT(kColors0), SkShader::kClamp_TileMode))->unref();
    canvas.drawPaint(paint);
    paint.setShader(SkGradientShader::CreateLinear(kPts1, kColors1, kPos,
                    SK_ARRAY_COUNT(kColors1), SkShader::kClamp_TileMode))->unref();
    canvas.drawPaint(paint);
}

/**
 * This bench draws a grid of either rects or filled paths, with two alternating color patterns.
 * This color patterns are passed in as enums to the class. The options are:
 *   1) solid white color
 *   2) solid blue color
 *   3) opaque bitmap
 *   4) partial alpha bitmap
 * The same color pattern can be set for both arguments to create a uniform pattern on all draws.
 *
 * The bench is used to test a few things. First it can test any optimizations made for a specific
 * color pattern (for example drawing an opaque bitmap versus one with partial alpha). Also it can
 * be used to test the cost of program switching and/or batching when alternating between different
 * patterns when on the gpu.
 */
class AlternatingColorPatternBench : public Benchmark {
public:
    enum {
        NX = 5,
        NY = 5,
        NUM_DRAWS = NX * NY,
    };
    SkShader* fBmShader;

    SkPath  fPaths[NUM_DRAWS];
    SkRect  fRects[NUM_DRAWS];
    SkColor fColors[NUM_DRAWS];
    SkShader* fShaders[NUM_DRAWS];

    SkString        fName;
    ColorPatternData    fPattern1;
    ColorPatternData    fPattern2;
    DrawType fDrawType;
    SkBitmap fBmp;


    AlternatingColorPatternBench(ColorPattern pattern1, ColorPattern pattern2, DrawType drawType)
        : fBmShader(NULL) {
        fPattern1 = gColorPatterns[pattern1];
        fPattern2 = gColorPatterns[pattern2];
        fName.printf("colorPattern_%s_%s_%s",
                     fPattern1.fName, fPattern2.fName,
                     kRect_DrawType == drawType ? "rect" : "path");
        fDrawType = drawType;
    }

    virtual ~AlternatingColorPatternBench() {
        SkSafeUnref(fBmShader);
    }

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

    virtual void onPreDraw() {
        int w = 40;
        int h = 40;
        makebm(&fBmp, w, h);
        fBmShader = SkShader::CreateBitmapShader(fBmp,
                                                 SkShader::kRepeat_TileMode,
                                                 SkShader::kRepeat_TileMode);
        int offset = 2;
        int count = 0;
        for (int j = 0; j < NY; ++j) {
            for (int i = 0; i < NX; ++i) {
                int x = (w + offset) * i;
                int y = (h * offset) * j;
                if (kRect_DrawType == fDrawType) {
                    fRects[count].set(SkIntToScalar(x), SkIntToScalar(y),
                                      SkIntToScalar(x + w), SkIntToScalar(y + h));
                } else {
                    fPaths[count].moveTo(SkIntToScalar(x), SkIntToScalar(y));
                    fPaths[count].rLineTo(SkIntToScalar(w), 0);
                    fPaths[count].rLineTo(0, SkIntToScalar(h));
                    fPaths[count].rLineTo(SkIntToScalar(-w + 1), 0);
                }
                if (0 == count % 2) {
                    fColors[count]  = fPattern1.fColor;
                    fShaders[count] = fPattern1.fIsBitmap ? fBmShader : NULL;
                } else {
                    fColors[count]  = fPattern2.fColor;
                    fShaders[count] = fPattern2.fIsBitmap ? fBmShader : NULL;
                }
                ++count;
            }
        }
    }

    void onDraw(const int loops, SkCanvas* canvas) override {
        SkPaint paint;
        paint.setAntiAlias(false);
        paint.setFilterQuality(kLow_SkFilterQuality);

        for (int i = 0; i < loops; ++i) {
            for (int j = 0; j < NUM_DRAWS; ++j) {
                paint.setColor(fColors[j]);
                paint.setShader(fShaders[j]);
                if (kRect_DrawType == fDrawType) {
                    canvas->drawRect(fRects[j], paint);
                } else {
                    canvas->drawPath(fPaths[j], paint);
                }
            }
        }
    }

private:
    typedef Benchmark INHERITED;
};

DEF_BENCH( return SkNEW_ARGS(AlternatingColorPatternBench,
                             (kWhite_ColorPattern, kWhite_ColorPattern,
                              kPath_DrawType)); )
DEF_BENCH( return SkNEW_ARGS(AlternatingColorPatternBench,
                             (kBlue_ColorPattern, kBlue_ColorPattern,
                              kPath_DrawType)); )
DEF_BENCH( return SkNEW_ARGS(AlternatingColorPatternBench,
                             (kWhite_ColorPattern, kBlue_ColorPattern,
                              kPath_DrawType)); )

DEF_BENCH( return SkNEW_ARGS(AlternatingColorPatternBench,
                             (kOpaqueBitmap_ColorPattern, kOpaqueBitmap_ColorPattern,
                              kPath_DrawType)); )
DEF_BENCH( return SkNEW_ARGS(AlternatingColorPatternBench,
                             (kAlphaBitmap_ColorPattern, kAlphaBitmap_ColorPattern,
                              kPath_DrawType)); )
DEF_BENCH( return SkNEW_ARGS(AlternatingColorPatternBench,
                             (kOpaqueBitmap_ColorPattern, kAlphaBitmap_ColorPattern,
                              kPath_DrawType)); )

DEF_BENCH( return SkNEW_ARGS(AlternatingColorPatternBench,
                             (kOpaqueBitmap_ColorPattern, kOpaqueBitmap_ColorPattern,
                              kRect_DrawType)); )
DEF_BENCH( return SkNEW_ARGS(AlternatingColorPatternBench,
                             (kAlphaBitmap_ColorPattern, kAlphaBitmap_ColorPattern,
                              kRect_DrawType)); )
DEF_BENCH( return SkNEW_ARGS(AlternatingColorPatternBench,
                             (kOpaqueBitmap_ColorPattern, kAlphaBitmap_ColorPattern,
                              kRect_DrawType)); )

