/*
 * 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 "Resources.h"
#include "SkBlurImageFilter.h"
#include "SkCanvas.h"
#include "SkDisplacementMapEffect.h"
#include "SkImage.h"
#include "SkMergeImageFilter.h"
#include "SkOffsetImageFilter.h"
#include "SkXfermodeImageFilter.h"

// Exercise a blur filter connected to 5 inputs of the same merge filter.
// This bench shows an improvement in performance once cacheing of re-used
// nodes is implemented, since the DAG is no longer flattened to a tree.
class ImageFilterDAGBench : public Benchmark {
public:
    ImageFilterDAGBench() {}

protected:
    const char* onGetName() override {
        return "image_filter_dag";
    }

    void onDraw(int loops, SkCanvas* canvas) override {
        const SkRect rect = SkRect::Make(SkIRect::MakeWH(400, 400));

        for (int j = 0; j < loops; j++) {
            sk_sp<SkImageFilter> blur(SkBlurImageFilter::Make(20.0f, 20.0f, nullptr));
            sk_sp<SkImageFilter> inputs[kNumInputs];
            for (int i = 0; i < kNumInputs; ++i) {
                inputs[i] = blur;
            }
            SkPaint paint;
            paint.setImageFilter(SkMergeImageFilter::Make(inputs, kNumInputs));
            canvas->drawRect(rect, paint);
        }
    }

private:
    static const int kNumInputs = 5;

    typedef Benchmark INHERITED;
};

class ImageMakeWithFilterDAGBench : public Benchmark {
public:
    ImageMakeWithFilterDAGBench() {}

protected:
    const char* onGetName() override {
        return "image_make_with_filter_dag";
    }

    void onDelayedSetup() override {
        fImage = GetResourceAsImage("mandrill_512.png");
    }

    void onDraw(int loops, SkCanvas* canvas) override {
        SkIRect subset = SkIRect::MakeSize(fImage->dimensions());
        SkIPoint offset = SkIPoint::Make(0, 0);
        SkIRect discardSubset;
        sk_sp<SkImage> image = fImage;

        for (int j = 0; j < loops; j++) {
            sk_sp<SkImageFilter> blur(SkBlurImageFilter::Make(20.0f, 20.0f, nullptr));
            sk_sp<SkImageFilter> inputs[kNumInputs];
            for (int i = 0; i < kNumInputs; ++i) {
                inputs[i] = blur;
            }
            sk_sp<SkImageFilter> mergeFilter = SkMergeImageFilter::Make(inputs, kNumInputs);
            image = image->makeWithFilter(mergeFilter.get(), subset, subset, &discardSubset,
                                          &offset);
            SkASSERT(image && image->dimensions() == fImage->dimensions());
        }
    }

private:
    static const int kNumInputs = 5;
    sk_sp<SkImage> fImage;

    typedef Benchmark INHERITED;
};

// Exercise a blur filter connected to both inputs of an SkDisplacementMapEffect.

class ImageFilterDisplacedBlur : public Benchmark {
public:
    ImageFilterDisplacedBlur() {}

protected:
    const char* onGetName() override {
        return "image_filter_displaced_blur";
    }

    void onDraw(int loops, SkCanvas* canvas) override {
        for (int j = 0; j < loops; j++) {
            sk_sp<SkImageFilter> blur(SkBlurImageFilter::Make(4.0f, 4.0f, nullptr));
            auto xSelector = SkDisplacementMapEffect::kR_ChannelSelectorType;
            auto ySelector = SkDisplacementMapEffect::kB_ChannelSelectorType;
            SkScalar scale = 2;

            SkPaint paint;
            paint.setImageFilter(SkDisplacementMapEffect::Make(xSelector, ySelector, scale,
                                                               blur, blur));

            SkRect rect = SkRect::Make(SkIRect::MakeWH(400, 400));
            canvas->drawRect(rect, paint);
        }
    }

private:
    typedef Benchmark INHERITED;
};

// Exercise an Xfermode kSrcIn filter compositing two inputs which have a small intersection.
class ImageFilterXfermodeIn : public Benchmark {
public:
    ImageFilterXfermodeIn() {}

protected:
    const char* onGetName() override { return "image_filter_xfermode_in"; }

    void onDraw(int loops, SkCanvas* canvas) override {
        for (int j = 0; j < loops; j++) {
            auto blur = SkBlurImageFilter::Make(20.0f, 20.0f, nullptr);
            auto offset1 = SkOffsetImageFilter::Make(100.0f, 100.0f, blur);
            auto offset2 = SkOffsetImageFilter::Make(-100.0f, -100.0f, blur);
            auto xfermode =
                    SkXfermodeImageFilter::Make(SkBlendMode::kSrcIn, offset1, offset2, nullptr);

            SkPaint paint;
            paint.setImageFilter(xfermode);
            canvas->drawRect(SkRect::MakeWH(200.0f, 200.0f), paint);
        }
    }

private:
    typedef Benchmark INHERITED;
};

DEF_BENCH(return new ImageFilterDAGBench;)
DEF_BENCH(return new ImageMakeWithFilterDAGBench;)
DEF_BENCH(return new ImageFilterDisplacedBlur;)
DEF_BENCH(return new ImageFilterXfermodeIn;)
