/*
 * Copyright 2020 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm/gm.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkData.h"
#include "include/core/SkPaint.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkSurface.h"
#include "include/effects/SkRuntimeEffect.h"
#include "tools/Resources.h"

class KawaseBlurFilter {
public:
    // Downsample scale factor used to improve performance
    static constexpr float kInputScale = 0.25f;
    // Downsample scale factor used to improve performance
    static constexpr float kInverseInputScale = 1.0f / kInputScale;
    // Maximum number of render passes
    static constexpr uint32_t kMaxPasses = 4;
    // To avoid downscaling artifacts, we interpolate the blurred fbo with the full composited
    // image, up to this radius.
    static constexpr float kMaxCrossFadeRadius = 30.0f;

    KawaseBlurFilter() {
        SkString blurString(R"(
            uniform shader src;
            uniform float in_inverseScale;
            uniform float2 in_blurOffset;

            half4 main(float2 xy) {
                float2 scaled_xy = float2(xy.x * in_inverseScale, xy.y * in_inverseScale);

                half4 c = src.eval(scaled_xy);
                c += src.eval(scaled_xy + float2( in_blurOffset.x,  in_blurOffset.y));
                c += src.eval(scaled_xy + float2( in_blurOffset.x, -in_blurOffset.y));
                c += src.eval(scaled_xy + float2(-in_blurOffset.x,  in_blurOffset.y));
                c += src.eval(scaled_xy + float2(-in_blurOffset.x, -in_blurOffset.y));

                return half4(c.rgb * 0.2, 1.0);
            }
        )");

        SkString mixString(R"(
            uniform shader in_blur;
            uniform shader in_original;
            uniform float in_inverseScale;
            uniform float in_mix;

            half4 main(float2 xy) {
                float2 scaled_xy = float2(xy.x * in_inverseScale, xy.y * in_inverseScale);

                half4 blurred = in_blur.eval(scaled_xy);
                half4 composition = in_original.eval(xy);
                return mix(composition, blurred, in_mix);
            }
        )");

        auto [blurEffect, error] = SkRuntimeEffect::MakeForShader(blurString);
        if (!blurEffect) {
            SkDEBUGFAILF("RuntimeShader error: %s\n", error.c_str());
        }
        fBlurEffect = std::move(blurEffect);

        auto [mixEffect, error2] = SkRuntimeEffect::MakeForShader(mixString);
        if (!mixEffect) {
            SkDEBUGFAILF("RuntimeShader error: %s\n", error2.c_str());
        }
        fMixEffect = std::move(mixEffect);
    }

    static sk_sp<SkSurface> MakeSurface(SkCanvas* canvas, const SkImageInfo& info) {
        if (sk_sp<SkSurface> surface = canvas->makeSurface(info)) {
            return surface;
        }
        // serialize-8888 returns null from makeSurface; fallback to a raster surface.
        return SkSurface::MakeRaster(info);
    }

    void draw(SkCanvas* canvas, sk_sp<SkImage> input, int blurRadius) {
        // NOTE: this is only experimental and the current blur params cause points to be sampled
        // beyond the input blur radius.

        // Kawase is an approximation of Gaussian, but it behaves differently from it.
        // A radius transformation is required for approximating them, and also to introduce
        // non-integer steps, necessary to smoothly interpolate large radii.
        float tmpRadius = (float)blurRadius / 6.0f;
        float numberOfPasses = std::min(kMaxPasses, (uint32_t)ceil(tmpRadius));
        float radiusByPasses = tmpRadius / (float)numberOfPasses;

        SkImageInfo scaledInfo = SkImageInfo::MakeN32Premul((float)input->width() * kInputScale,
                                                            (float)input->height() * kInputScale);
        auto drawSurface = MakeSurface(canvas, scaledInfo);

        const float stepX = radiusByPasses;
        const float stepY = radiusByPasses;

        // start by drawing and downscaling and doing the first blur pass
        SkRuntimeShaderBuilder blurBuilder(fBlurEffect);
        blurBuilder.child("src") = input->makeShader(SkSamplingOptions(SkFilterMode::kLinear));
        blurBuilder.uniform("in_inverseScale") = kInverseInputScale;
        blurBuilder.uniform("in_blurOffset") = SkV2{stepX * kInverseInputScale,
                                                    stepY * kInverseInputScale};
        SkPaint paint;
        paint.setShader(blurBuilder.makeShader());
        drawSurface->getCanvas()->drawIRect(scaledInfo.bounds(), paint);

        // DEBUG draw each of the stages
        canvas->save();
        canvas->drawImage(drawSurface->makeImageSnapshot(), input->width() / 4, 0,
                          SkSamplingOptions());
        canvas->translate(input->width() / 4, input->height() * 0.75);
        drawSurface->flush();

        // And now we'll ping pong between our surfaces, to accumulate the result of various
        // offsets.
        auto lastDrawTarget = drawSurface;
        if (numberOfPasses > 1) {
            auto readSurface = drawSurface;
            drawSurface = MakeSurface(canvas, scaledInfo);

            for (auto i = 1; i < numberOfPasses; i++) {
                const float stepScale = (float)i * kInputScale;

                blurBuilder.child("src") = readSurface->makeImageSnapshot()->makeShader(
                        SkSamplingOptions(SkFilterMode::kLinear));
                blurBuilder.uniform("in_inverseScale") = 1.0f;
                blurBuilder.uniform("in_blurOffset") = SkV2{stepX * stepScale , stepY * stepScale};

                paint.setShader(blurBuilder.makeShader());
                drawSurface->getCanvas()->drawIRect(scaledInfo.bounds(), paint);

                // DEBUG draw each of the stages
                canvas->drawImage(drawSurface->makeImageSnapshot(), 0, 0, SkSamplingOptions());
                canvas->translate(0, input->height() * 0.75);

                // Swap buffers for next iteration
                auto tmp = drawSurface;
                drawSurface = readSurface;
                readSurface = tmp;
            }
            lastDrawTarget = readSurface;
        }

        // restore translations done for debug and offset
        canvas->restore();
        SkAutoCanvasRestore acr(canvas, true);
        canvas->translate(input->width(), 0);

        // do the final composition and when we scale our blur up. It will be interpolated
        // with the larger composited texture to hide downscaling artifacts.
        SkRuntimeShaderBuilder mixBuilder(fMixEffect);
        mixBuilder.child("in_blur") = lastDrawTarget->makeImageSnapshot()->makeShader(
                SkSamplingOptions(SkFilterMode::kLinear));
        mixBuilder.child("in_original") =
                input->makeShader(SkSamplingOptions(SkFilterMode::kLinear));
        mixBuilder.uniform("in_inverseScale") = kInputScale;
        mixBuilder.uniform("in_mix") = std::min(1.0f, (float)blurRadius / kMaxCrossFadeRadius);

        paint.setShader(mixBuilder.makeShader());
        canvas->drawIRect(input->bounds(), paint);
    }

private:
    sk_sp<SkRuntimeEffect> fBlurEffect;
    sk_sp<SkRuntimeEffect> fMixEffect;
};

class KawaseBlurRT : public skiagm::GM {
public:
    KawaseBlurRT() {}
    SkString onShortName() override { return SkString("kawase_blur_rt"); }
    SkISize onISize() override { return {1280, 768}; }

    void onOnceBeforeDraw() override {
        fMandrill = GetResourceAsImage("images/mandrill_256.png");
    }

    void onDraw(SkCanvas* canvas) override {
        canvas->drawImage(fMandrill, 0, 0);
        canvas->translate(256, 0);
        KawaseBlurFilter blurFilter;
        blurFilter.draw(canvas, fMandrill, 45);
        canvas->translate(512, 0);
        blurFilter.draw(canvas, fMandrill, 55);
    }

private:
    sk_sp<SkImage> fMandrill;
};
DEF_GM(return new KawaseBlurRT;)
