/*
 * 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:
    virtual const char* onGetName() SK_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;
            }
        }
    }

    virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
        SkPaint paint;
        paint.setAntiAlias(false);
        paint.setFilterLevel(SkPaint::kLow_FilterLevel);

        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)); )

