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

#ifndef SkBlurEngine_DEFINED
#define SkBlurEngine_DEFINED

#include "include/core/SkM44.h"  // IWYU pragma: keep
#include "include/core/SkRefCnt.h"
#include "include/core/SkSize.h"
#include "include/core/SkSpan.h"
#include "include/private/base/SkFloatingPoint.h"

#include <array>

class SkColorSpace;
class SkDevice;
class SkRuntimeEffect;
class SkShader;
class SkSpecialImage;
struct SkImageInfo;
struct SkIRect;

enum class SkTileMode;
enum SkColorType : int;

/**
 * SkBlurEngine is a backend-agnostic provider of blur algorithms. Each Skia backend defines a blur
 * engine with a set of supported algorithms and/or implementations. A given implementation may be
 * optimized for a particular color type, sigma range, or available hardware. Each engine and its
 * algorithms are assumed to operate only on SkImages corresponding to its Skia backend, and will
 * produce output SkImages of the same type.
 *
 * Algorithms are allowed to specify a maximum supported sigma. If the desired sigma is higher than
 * this, the input image and output region must be downscaled by the caller before invoking the
 * algorithm. This is to provide the most flexibility for input representation (e.g. directly
 * rasterize at half resolution or apply deferred filter effects during the first downsample pass).
 *
 * skif::FilterResult::Builder::blur() is a convenient wrapper around the blur engine and
 * automatically handles resizing.
*/
class SkBlurEngine {
public:
    class Algorithm;

    virtual ~SkBlurEngine() = default;

    // Returns an Algorithm ideal for the requested 'sigma' that will support sampling an image of
    // the given 'colorType'. If the engine does not support the requested configuration, it returns
    // null. The engine maintains the lifetime of its algorithms, so the returned non-null
    // Algorithms live as long as the engine does.
    virtual const Algorithm* findAlgorithm(SkSize sigma,
                                           SkColorType colorType) const = 0;

    // TODO: Consolidate common utility functions from SkBlurMask.h into this header.

    // Any sigmas smaller than this are effectively an identity blur so can skip convolution at a
    // higher level. The value was chosen because it corresponds roughly to a radius of 1/10px, and
    // because 2*sigma^2 is slightly greater than SK_ScalarNearlyZero.
    static constexpr bool IsEffectivelyIdentity(float sigma) { return sigma <= 0.03f; }

    // Convert from a sigma Gaussian standard deviation to a pixel radius such that pixels outside
    // the radius would have an insignificant contribution to the final blurred value.
    static int SigmaToRadius(float sigma) {
        // sk_float_ceil2int is not constexpr
        return IsEffectivelyIdentity(sigma) ? 0 : sk_float_ceil2int(3.f * sigma);
    }
};

class SkBlurEngine::Algorithm {
public:
    virtual ~Algorithm() = default;

    // The maximum sigma that can be passed to blur() in the X and/or Y sigma values. Larger
    // requested sigmas must manually downscale the input image and upscale the output image.
    virtual float maxSigma() const = 0;

    // Whether or not the SkTileMode can be passed to blur() must be SkTileMode::kDecal, or if any
    // tile mode is supported. If only kDecal is supported, then callers must manually apply the
    // tilemode and account for that in the src and dst bounds passed into blur(). If this returns
    // false, then the algorithm supports all SkTileModes.
    // TODO: Once CPU blurs support all tile modes, this API can go away.
    virtual bool supportsOnlyDecalTiling() const = 0;

    // Produce a blurred image that fills 'dstRect' (their dimensions will match). 'dstRect's top
    // left corner defines the output's location relative to the 'src' image. 'srcRect' restricts
    // the pixels that are included in the blur and is also relative to 'src'. The 'tileMode'
    // applies to the boundary of 'srcRect', which must be contained within 'src's dimensions.
    //
    // 'srcRect' and 'dstRect' may be different sizes and even be disjoint.
    //
    // The returned SkImage will have the same color type and colorspace as the input image. It will
    // be an SkImage type matching the underlying Skia backend. If the 'src' SkImage is not a
    // compatible SkImage type, null is returned.
    // TODO(b/299474380): This only takes SkSpecialImage to work with skif::FilterResult and
    // SkDevice::snapSpecial(); SkImage would be ideal.
    virtual sk_sp<SkSpecialImage> blur(SkSize sigma,
                                       sk_sp<SkSpecialImage> src,
                                       const SkIRect& srcRect,
                                       SkTileMode tileMode,
                                       const SkIRect& dstRect) const = 0;
};

/**
 * The default blur implementation uses internal runtime effects to evaluate either a single 2D
 * kernel within a shader, or performs two 1D blur passes. This algorithm is backend agnostic but
 * must be subclassed per backend to define the SkDevice creation function.
 */
class SkShaderBlurAlgorithm : public SkBlurEngine::Algorithm {
public:
    float maxSigma() const override { return kMaxLinearSigma; }
    bool supportsOnlyDecalTiling() const override { return false; }

    sk_sp<SkSpecialImage> blur(SkSize sigma,
                               sk_sp<SkSpecialImage> src,
                               const SkIRect& srcRect,
                               SkTileMode tileMode,
                               const SkIRect& dstRect) const override;

private:
    // Create a new surface, which can be approx-fit and have undefined contents.
    virtual sk_sp<SkDevice> makeDevice(const SkImageInfo&) const = 0;

    sk_sp<SkSpecialImage> renderBlur(sk_sp<SkShader> blurEffect,
                                     const SkIRect& dstRect,
                                     SkColorType colorType,
                                     sk_sp<SkColorSpace> colorSpace) const;
    sk_sp<SkSpecialImage> evalBlur2D(SkSize sigma,
                                     SkISize radii,
                                     sk_sp<SkSpecialImage> input,
                                     const SkIRect& srcRect,
                                     SkTileMode tileMode,
                                     const SkIRect& dstRect) const;
    sk_sp<SkSpecialImage> evalBlur1D(float sigma,
                                     int radius,
                                     SkV2 dir,
                                     sk_sp<SkSpecialImage> input,
                                     SkIRect srcRect,
                                     SkTileMode tileMode,
                                     SkIRect dstRect) const;

// TODO: These are internal details of the blur shaders, but are public for now because multiple
// backends invoke the blur shaders directly. Once everything just goes through this class, these
// can be hidden.
public:

    // The kernel width of a Gaussian blur of the given pixel radius, when all pixels are sampled.
    static constexpr int KernelWidth(int radius) { return 2 * radius + 1; }

    // The kernel width of a Gaussian blur of the given pixel radius, that relies on HW bilinear
    // filtering to combine adjacent pixels.
    static constexpr int LinearKernelWidth(int radius) { return radius + 1; }

    // The maximum sigma that can be computed without downscaling is based on the number of uniforms
    // and texture samples the effects will make in a single pass. For 1D passes, the number of
    // samples is equal to `LinearKernelWidth`; for 2D passes, it is equal to
    // `KernelWidth(radiusX)*KernelWidth(radiusY)`. This maps back to different maximum sigmas
    // depending on the approach used, as well as the ratio between the sigmas for the X and Y axes
    // if a 2D blur is performed.
    static constexpr int kMaxSamples = 28;

    // TODO(b/297393474): Update max linear sigma to 9; it had been 4 when a full 1D kernel was
    // used, but never updated after the linear filtering optimization reduced the number of
    // sample() calls required. Keep it at 4 for now to better isolate performance changes due to
    // switching to a runtime effect and constant loop structure.
    static constexpr float kMaxLinearSigma = 4.f; // -> radius = 27 -> linear kernel width = 28
    // NOTE: There is no defined kMaxBlurSigma for direct 2D blurs since it is entirely dependent on
    // the ratio between the two axes' sigmas, but generally it will be small on the order of a
    // 5x5 kernel.

    // Return a runtime effect that applies a 2D Gaussian blur in a single pass. The returned effect
    // can perform arbitrarily sized blur kernels so long as the kernel area is less than
    // kMaxSamples. An SkRuntimeEffect is returned to give flexibility for callers to convert it to
    // an SkShader or a GrFragmentProcessor. Callers are responsible for providing the uniform
    // values (using the appropriate API of the target effect type). The effect declares the
    // following uniforms:
    //
    //    uniform half4  kernel[7];
    //    uniform half4  offsets[14];
    //    uniform shader child;
    //
    // 'kernel' should be set to the output of Compute2DBlurKernel(). 'offsets' should be set to the
    // output of Compute2DBlurOffsets() with the same 'radii' passed to this function. 'child'
    // should be bound to whatever input is intended to be blurred, and can use nearest-neighbor
    // sampling (assuming it's an image).
    static const SkRuntimeEffect* GetBlur2DEffect(const SkISize& radii);

    // Return a runtime effect that applies a 1D Gaussian blur, taking advantage of HW linear
    // interpolation to accumulate adjacent pixels with fewer samples. The returned effect can be
    // used for both X and Y axes by changing the 'dir' uniform value (see below). It can be used
    // for all 1D blurs such that BlurLinearKernelWidth(radius) is less than or equal to
    // kMaxSamples. Like GetBlur2DEffect(), the caller is free to convert this to an SkShader or a
    // GrFragmentProcessor and is responsible for assigning uniforms with the appropriate API. Its
    // uniforms are declared as:
    //
    //     uniform half4  offsetsAndKernel[14];
    //     uniform half2  dir;
    //     uniform int    radius;
    //     uniform shader child;
    //
    // 'offsetsAndKernel' should be set to the output of Compute1DBlurLinearKernel(). 'radius'
    // should match the radius passed to that function. 'dir' should either be the vector {1,0} or
    // {0,1} for X and Y axis passes, respectively. 'child' should be bound to whatever input is
    // intended to be blurred and must use linear sampling in order for the outer blur effect to
    // function correctly.
    static const SkRuntimeEffect* GetLinearBlur1DEffect(int radius);

    // Calculates a set of weights for a 2D Gaussian blur of the given sigma and radius. It is
    // assumed that the radius was from prior calls to BlurSigmaRadius(sigma.width()|height()) and
    // is passed in to avoid redundant calculations.
    //
    // The provided span is fully written. The kernel is stored in row-major order based on the
    // provided radius. Any remaining indices in the span are zero initialized. The span must have
    // at least KernelWidth(radius.width())*KernelWidth(radius.height()) elements.
    //
    // NOTE: These take spans because it can be useful to compute full kernels that are larger than
    // what is supported in the GPU effects.
    static void Compute2DBlurKernel(SkSize sigma,
                                    SkISize radius,
                                    SkSpan<float> kernel);

    // A convenience function that packs the kMaxBlurSample scalars into SkV4's to match the
    // required type of the uniforms in GetBlur2DEffect().
    static void Compute2DBlurKernel(SkSize sigma,
                                    SkISize radius,
                                    std::array<SkV4, kMaxSamples/4>& kernel);

    // A convenience for the 2D case where one dimension has a sigma of 0.
    static  void Compute1DBlurKernel(float sigma, int radius, SkSpan<float> kernel) {
        Compute2DBlurKernel(SkSize{sigma, 0.f}, SkISize{radius, 0}, kernel);
    }

    // Utility function to fill in 'offsets' for the effect returned by GetBlur2DEffect(). It
    // automatically fills in the elements beyond the kernel size with the last real offset to
    // maximize texture cache hits. Each offset is really an SkV2 but are packed into SkV4's to
    // match the uniform declaration, and are otherwise ordered row-major.
    static void Compute2DBlurOffsets(SkISize radius, std::array<SkV4, kMaxSamples/2>& offsets);

    // Calculates a set of weights and sampling offsets for a 1D blur that uses GPU hardware to
    // linearly combine two logical source pixel values. This assumes that 'radius' was from a prior
    // call to BlurSigmaRadius() and is passed in to avoid redundant calculations. To match std140
    // uniform packing, the offset and kernel weight for adjacent samples are packed into a single
    // SkV4 as {offset[2*i], kernel[2*i], offset[2*i+1], kernel[2*i+1]}
    //
    // The provided array is fully written to. The calculated values are written to indices 0
    // through LinearKernelWidth(radius), with any remaining indices zero initialized.
    //
    // NOTE: This takes an array of a constrained size because its main use is calculating uniforms
    // for an effect with a matching constraint. Knowing the size of the linear kernel means the
    // full kernel can be stored on the stack internally.
    static void Compute1DBlurLinearKernel(float sigma,
                                          int radius,
                                          std::array<SkV4, kMaxSamples/2>& offsetsAndKernel);

};

#endif // SkBlurEngine_DEFINED
