/*
 * 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 "bench/Benchmark.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkImage.h"
#include "include/effects/SkImageFilters.h"
#include "include/gpu/GrDirectContext.h"
#include "include/gpu/GrRecordingContext.h"
#include "tools/Resources.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));

        // Set up the filters once, we're not interested in measuring allocation time here
        sk_sp<SkImageFilter> blur(SkImageFilters::Blur(20.0f, 20.0f, nullptr));
        sk_sp<SkImageFilter> inputs[kNumInputs];
        for (int i = 0; i < kNumInputs; ++i) {
            inputs[i] = blur;
        }
        SkPaint paint;
        paint.setImageFilter(SkImageFilters::Merge(inputs, kNumInputs));

        // Only measure the filter computations done in drawRect()
        // TODO (michaelludwig) - This benchmark, and the ones defined below, allocate their filters
        // outside of the loop. This means that repeatedly drawing with the same filter will hit
        // the global image filter cache inside the loop. Raster backend uses this cache so will see
        // artificially improved performance. Ganesh will not because it uses a cache per filter
        // call, so only within-DAG cache hits are measured (as desired). skbug:9297 wants to move
        // raster backend to the same pattern, which will make the benchmark executions fair again.
        for (int j = 0; j < loops; j++) {
            canvas->drawRect(rect, paint);
        }
    }

private:
    static const int kNumInputs = 5;

    using INHERITED = Benchmark;
};

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

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

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

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

        auto dContext = GrAsDirectContext(canvas->recordingContext());
        // makeWithFilter will only use the GPU backend if the image is already a texture
        sk_sp<SkImage> image = fImage->makeTextureImage(dContext);
        if (!image) {
            image = fImage;
        }

        // Set up the filters once so the allocation cost isn't included per-loop
        sk_sp<SkImageFilter> blur(SkImageFilters::Blur(20.0f, 20.0f, nullptr));
        sk_sp<SkImageFilter> inputs[kNumInputs];
        for (int i = 0; i < kNumInputs; ++i) {
            inputs[i] = blur;
        }
        sk_sp<SkImageFilter> mergeFilter = SkImageFilters::Merge(inputs, kNumInputs);

        // But measure makeWithFilter() per loop since that's the focus of this benchmark
        for (int j = 0; j < loops; j++) {
            image = image->makeWithFilter(dContext, mergeFilter.get(), subset, subset,
                                          &discardSubset, &offset);
            SkASSERT(image && image->dimensions() == fImage->dimensions());
        }
    }

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

    using INHERITED = Benchmark;
};

// 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 {
        // Setup filter once
        sk_sp<SkImageFilter> blur(SkImageFilters::Blur(4.0f, 4.0f, nullptr));
        SkScalar scale = 2;

        SkPaint paint;
        paint.setImageFilter(SkImageFilters::DisplacementMap(SkColorChannel::kR, SkColorChannel::kR,
                                                             scale, blur, blur));

        SkRect rect = SkRect::Make(SkIRect::MakeWH(400, 400));

        // As before, measure just the filter computation time inside the loops
        for (int j = 0; j < loops; j++) {
            canvas->drawRect(rect, paint);
        }
    }

private:
    using INHERITED = Benchmark;
};

// 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 {
        // Allocate filters once to avoid measuring instantiation time
        auto blur = SkImageFilters::Blur(20.0f, 20.0f, nullptr);
        auto offset1 = SkImageFilters::Offset(100.0f, 100.0f, blur);
        auto offset2 = SkImageFilters::Offset(-100.0f, -100.0f, blur);
        auto xfermode =
                SkImageFilters::Blend(SkBlendMode::kSrcIn, offset1, offset2, nullptr);

        SkPaint paint;
        paint.setImageFilter(xfermode);

        // Measure only the filter time
        for (int j = 0; j < loops; j++) {
            canvas->drawRect(SkRect::MakeWH(200.0f, 200.0f), paint);
        }
    }

private:
    using INHERITED = Benchmark;
};

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