/*
 * Copyright 2013 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 "SkColorFilterImageFilter.h"
#include "SkColorMatrixFilter.h"
#include "SkLumaColorFilter.h"
#include "SkTableColorFilter.h"

#define FILTER_WIDTH_SMALL  SkIntToScalar(32)
#define FILTER_HEIGHT_SMALL SkIntToScalar(32)
#define FILTER_WIDTH_LARGE  SkIntToScalar(256)
#define FILTER_HEIGHT_LARGE SkIntToScalar(256)

class ColorFilterBaseBench : public Benchmark {

public:
    ColorFilterBaseBench(bool small) : fIsSmall(small) { }

protected:
    SkRect getFilterRect() const {
        return isSmall() ? SkRect::MakeWH(FILTER_WIDTH_SMALL, FILTER_HEIGHT_SMALL) :
                           SkRect::MakeWH(FILTER_WIDTH_LARGE, FILTER_HEIGHT_LARGE);
    }

    static SkImageFilter* make_brightness(float amount, SkImageFilter* input = NULL) {
        SkScalar amount255 = SkScalarMul(amount, SkIntToScalar(255));
        SkScalar matrix[20] = { 1, 0, 0, 0, amount255,
                                0, 1, 0, 0, amount255,
                                0, 0, 1, 0, amount255,
                                0, 0, 0, 1, 0 };
        SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix));
        return SkColorFilterImageFilter::Create(filter, input);
    }

    static SkImageFilter* make_grayscale(SkImageFilter* input = NULL) {
        SkScalar matrix[20];
        memset(matrix, 0, 20 * sizeof(SkScalar));
        matrix[0] = matrix[5] = matrix[10] = 0.2126f;
        matrix[1] = matrix[6] = matrix[11] = 0.7152f;
        matrix[2] = matrix[7] = matrix[12] = 0.0722f;
        matrix[18] = 1.0f;
        SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix));
        return SkColorFilterImageFilter::Create(filter, input);
    }

    static SkImageFilter* make_mode_blue(SkImageFilter* input = NULL) {
        SkAutoTUnref<SkColorFilter> filter(
            SkColorFilter::CreateModeFilter(SK_ColorBLUE, SkXfermode::kSrcIn_Mode));
        return SkColorFilterImageFilter::Create(filter, input);
    }

    inline bool isSmall() const { return fIsSmall; }
private:
    bool fIsSmall;

    typedef Benchmark INHERITED;
};

class ColorFilterDimBrightBench : public ColorFilterBaseBench {

public:
    ColorFilterDimBrightBench(bool small) : INHERITED(small) {
    }

protected:
    const char* onGetName() override {
        return isSmall() ? "colorfilter_dim_bright_small" : "colorfilter_dim_bright_large";
    }

    void onDraw(const int loops, SkCanvas* canvas) override {
        SkRect r = getFilterRect();
        SkPaint paint;
        paint.setColor(SK_ColorRED);

        for (int i = 0; i < loops; i++) {
            for (float brightness = -1.0f; brightness <= 1.0f; brightness += 0.4f) {
                SkAutoTUnref<SkImageFilter> dim(make_brightness(-brightness));
                SkAutoTUnref<SkImageFilter> bright(make_brightness(brightness, dim));
                paint.setImageFilter(bright);
                canvas->drawRect(r, paint);
            }
        }
    }

private:
    typedef ColorFilterBaseBench INHERITED;
};

class ColorFilterBrightGrayBench : public ColorFilterBaseBench {

public:
    ColorFilterBrightGrayBench(bool small) : INHERITED(small) {
    }

protected:
    const char* onGetName() override {
        return isSmall() ? "colorfilter_bright_gray_small" : "colorfilter_bright_gray_large";
    }

    void onDraw(const int loops, SkCanvas* canvas) override {
        SkRect r = getFilterRect();
        SkPaint paint;
        paint.setColor(SK_ColorRED);
        for (int i = 0; i < loops; i++) {
            SkAutoTUnref<SkImageFilter> brightness(make_brightness(0.9f));
            SkAutoTUnref<SkImageFilter> grayscale(make_grayscale(brightness));
            paint.setImageFilter(grayscale);
            canvas->drawRect(r, paint);
        }
    }

private:
    typedef ColorFilterBaseBench INHERITED;
};

class ColorFilterGrayBrightBench : public ColorFilterBaseBench {

public:
    ColorFilterGrayBrightBench(bool small) : INHERITED(small) {
    }

protected:
    const char* onGetName() override {
        return isSmall() ? "colorfilter_gray_bright_small" : "colorfilter_gray_bright_large";
    }

    void onDraw(const int loops, SkCanvas* canvas) override {
        SkRect r = getFilterRect();
        SkPaint paint;
        paint.setColor(SK_ColorRED);
        for (int i = 0; i < loops; i++) {
            SkAutoTUnref<SkImageFilter> grayscale(make_grayscale());
            SkAutoTUnref<SkImageFilter> brightness(make_brightness(0.9f, grayscale));
            paint.setImageFilter(brightness);
            canvas->drawRect(r, paint);
        }
    }

private:
    typedef ColorFilterBaseBench INHERITED;
};

class ColorFilterBlueBrightBench : public ColorFilterBaseBench {

public:
    ColorFilterBlueBrightBench(bool small) : INHERITED(small) {
    }

protected:
    const char* onGetName() override {
        return isSmall() ? "colorfilter_blue_bright_small" : "colorfilter_blue_bright_large";
    }

    void onDraw(const int loops, SkCanvas* canvas) override {
        SkRect r = getFilterRect();
        SkPaint paint;
        paint.setColor(SK_ColorRED);
        for (int i = 0; i < loops; i++) {
            SkAutoTUnref<SkImageFilter> blue(make_mode_blue());
            SkAutoTUnref<SkImageFilter> brightness(make_brightness(1.0f, blue));
            paint.setImageFilter(brightness);
            canvas->drawRect(r, paint);
        }
    }

private:
    typedef ColorFilterBaseBench INHERITED;
};

class ColorFilterBrightBlueBench : public ColorFilterBaseBench {

public:
    ColorFilterBrightBlueBench(bool small) : INHERITED(small) {
    }

protected:
    const char* onGetName() override {
        return isSmall() ? "colorfilter_bright_blue_small" : "colorfilter_bright_blue_large";
    }

    void onDraw(const int loops, SkCanvas* canvas) override {
        SkRect r = getFilterRect();
        SkPaint paint;
        paint.setColor(SK_ColorRED);
        for (int i = 0; i < loops; i++) {
            SkAutoTUnref<SkImageFilter> brightness(make_brightness(1.0f));
            SkAutoTUnref<SkImageFilter> blue(make_mode_blue(brightness));
            paint.setImageFilter(blue);
            canvas->drawRect(r, paint);
        }
    }

private:
    typedef ColorFilterBaseBench INHERITED;
};

class ColorFilterBrightBench : public ColorFilterBaseBench {

public:
    ColorFilterBrightBench(bool small) : INHERITED(small) {
    }

protected:
    const char* onGetName() override {
        return isSmall() ? "colorfilter_bright_small" : "colorfilter_bright_large";
    }

    void onDraw(const int loops, SkCanvas* canvas) override {
        SkRect r = getFilterRect();
        SkPaint paint;
        paint.setColor(SK_ColorRED);
        for (int i = 0; i < loops; i++) {
            SkAutoTUnref<SkImageFilter> brightness(make_brightness(1.0f));
            paint.setImageFilter(brightness);
            canvas->drawRect(r, paint);
        }
    }

private:
    typedef ColorFilterBaseBench INHERITED;
};

class ColorFilterBlueBench : public ColorFilterBaseBench {

public:
    ColorFilterBlueBench(bool small) : INHERITED(small) {
    }

protected:
    const char* onGetName() override {
        return isSmall() ? "colorfilter_blue_small" : "colorfilter_blue_large";
    }

    void onDraw(const int loops, SkCanvas* canvas) override {
        SkRect r = getFilterRect();
        SkPaint paint;
        paint.setColor(SK_ColorRED);
        for (int i = 0; i < loops; i++) {
            SkAutoTUnref<SkImageFilter> blue(make_mode_blue());
            paint.setImageFilter(blue);
            canvas->drawRect(r, paint);
        }
    }

private:
    typedef ColorFilterBaseBench INHERITED;
};

class ColorFilterGrayBench : public ColorFilterBaseBench {

public:
    ColorFilterGrayBench(bool small) : INHERITED(small) {
    }

protected:
    const char* onGetName() override {
        return isSmall() ? "colorfilter_gray_small" : "colorfilter_gray_large";
    }

    void onDraw(const int loops, SkCanvas* canvas) override {
        SkRect r = getFilterRect();
        SkPaint paint;
        paint.setColor(SK_ColorRED);
        for (int i = 0; i < loops; i++) {
            SkAutoTUnref<SkImageFilter> grayscale(make_grayscale());
            paint.setImageFilter(grayscale);
            canvas->drawRect(r, paint);
        }
    }

private:
    typedef ColorFilterBaseBench INHERITED;
};

class TableColorFilterBench : public ColorFilterBaseBench {

public:
    TableColorFilterBench(bool small) : INHERITED(small) {
    }

protected:
    const char* onGetName() override {
        return isSmall() ? "table_colorfilter_small" : "table_colorfilter_large";
    }

    void onDraw(const int loops, SkCanvas* canvas) override {
        SkRect r = getFilterRect();
        SkPaint paint;
        paint.setColor(SK_ColorRED);
        for (int i = 0; i < loops; i++) {
            SkAutoTUnref<SkColorFilter> table_filter(make_table_filter());
            paint.setColorFilter(table_filter);
            canvas->drawRect(r, paint);
        }
    }

private:
    static void fill_table_data(uint8_t table[]) {
        for (int i = 0; i < 256; ++i) {
            int n = i >> 5;
            table[i] = (n << 5) | (n << 2) | (n >> 1);
        }
    }

    static SkColorFilter* make_table_filter() {
        uint8_t table[256]; fill_table_data(table);
        return SkTableColorFilter::Create(table);
    }

    typedef ColorFilterBaseBench INHERITED;
};

class LumaColorFilterBench : public ColorFilterBaseBench {

public:
    LumaColorFilterBench(bool small) : INHERITED(small) {
    }

protected:
    const char* onGetName() override {
        return isSmall() ? "luma_colorfilter_small" : "luma_colorfilter_large";
    }

    void onDraw(const int loops, SkCanvas* canvas) override {
        SkRect r = getFilterRect();
        SkPaint paint;
        paint.setColor(SK_ColorRED);

        for (int i = 0; i < loops; i++) {
            SkAutoTUnref<SkColorFilter> luma_filter(SkLumaColorFilter::Create());
            paint.setColorFilter(luma_filter);
            canvas->drawRect(r, paint);
        }
    }

private:
    typedef ColorFilterBaseBench INHERITED;
};

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

DEF_BENCH( return new ColorFilterDimBrightBench(true); )
DEF_BENCH( return new ColorFilterBrightGrayBench(true); )
DEF_BENCH( return new ColorFilterGrayBrightBench(true); )
DEF_BENCH( return new ColorFilterBlueBrightBench(true); )
DEF_BENCH( return new ColorFilterBrightBlueBench(true); )
DEF_BENCH( return new ColorFilterBrightBench(true); )
DEF_BENCH( return new ColorFilterBlueBench(true); )
DEF_BENCH( return new ColorFilterGrayBench(true); )
DEF_BENCH( return new TableColorFilterBench(true); )
DEF_BENCH( return new LumaColorFilterBench(true); )

DEF_BENCH( return new ColorFilterDimBrightBench(false); )
DEF_BENCH( return new ColorFilterBrightGrayBench(false); )
DEF_BENCH( return new ColorFilterGrayBrightBench(false); )
DEF_BENCH( return new ColorFilterBlueBrightBench(false); )
DEF_BENCH( return new ColorFilterBrightBlueBench(false); )
DEF_BENCH( return new ColorFilterBrightBench(false); )
DEF_BENCH( return new ColorFilterBlueBench(false); )
DEF_BENCH( return new ColorFilterGrayBench(false); )
DEF_BENCH( return new TableColorFilterBench(false); )
DEF_BENCH( return new LumaColorFilterBench(false); )
