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

/**************************************************************************************************
 *** This file was autogenerated from GrRectBlurEffect.fp; do not modify.
 **************************************************************************************************/
#ifndef GrRectBlurEffect_DEFINED
#define GrRectBlurEffect_DEFINED
#include "include/core/SkTypes.h"

#include <cmath>
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "src/core/SkBlurMask.h"
#include "src/core/SkMathPriv.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrShaderCaps.h"

#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
class GrRectBlurEffect : public GrFragmentProcessor {
public:
    static sk_sp<GrTextureProxy> CreateIntegralTexture(GrProxyProvider* proxyProvider,
                                                       float sixSigma) {
        // The texture we're producing represents the integral of a normal distribution over a
        // six-sigma range centered at zero. We want enough resolution so that the linear
        // interpolation done in texture lookup doesn't introduce noticeable artifacts. We
        // conservatively choose to have 2 texels for each dst pixel.
        int minWidth = 2 * sk_float_ceil2int(sixSigma);
        // Bin by powers of 2 with a minimum so we get good profile reuse.
        int width = SkTMax(SkNextPow2(minWidth), 32);

        static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
        GrUniqueKey key;
        GrUniqueKey::Builder builder(&key, kDomain, 1, "Rect Blur Mask");
        builder[0] = width;
        builder.finish();

        sk_sp<GrTextureProxy> proxy(proxyProvider->findOrCreateProxyByUniqueKey(
                key, GrColorType::kAlpha_8, kTopLeft_GrSurfaceOrigin));
        if (!proxy) {
            SkBitmap bitmap;
            if (!bitmap.tryAllocPixels(SkImageInfo::MakeA8(width, 1))) {
                return nullptr;
            }
            *bitmap.getAddr8(0, 0) = 255;
            const float invWidth = 1.f / width;
            for (int i = 1; i < width - 1; ++i) {
                float x = (i + 0.5f) * invWidth;
                x = (-6 * x + 3) * SK_ScalarRoot2Over2;
                float integral = 0.5f * (std::erf(x) + 1.f);
                *bitmap.getAddr8(i, 0) = SkToU8(sk_float_round2int(255.f * integral));
            }
            *bitmap.getAddr8(width - 1, 0) = 0;
            bitmap.setImmutable();
            proxy = proxyProvider->createProxyFromBitmap(bitmap, GrMipMapped::kNo);
            if (!proxy) {
                return nullptr;
            }
            SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
            proxyProvider->assignUniqueKeyToProxy(key, proxy.get());
        }
        return proxy;
    }

    static std::unique_ptr<GrFragmentProcessor> Make(GrProxyProvider* proxyProvider,
                                                     const GrShaderCaps& caps, const SkRect& rect,
                                                     float sigma) {
        SkASSERT(rect.isSorted());
        if (!caps.floatIs32Bits()) {
            // We promote the math that gets us into the Gaussian space to full float when the rect
            // coords are large. If we don't have full float then fail. We could probably clip the
            // rect to an outset device bounds instead.
            if (SkScalarAbs(rect.fLeft) > 16000.f || SkScalarAbs(rect.fTop) > 16000.f ||
                SkScalarAbs(rect.fRight) > 16000.f || SkScalarAbs(rect.fBottom) > 16000.f) {
                return nullptr;
            }
        }

        const float sixSigma = 6 * sigma;
        auto integral = CreateIntegralTexture(proxyProvider, sixSigma);
        if (!integral) {
            return nullptr;
        }

        // In the fast variant we think of the midpoint of the integral texture as aligning
        // with the closest rect edge both in x and y. To simplify texture coord calculation we
        // inset the rect so that the edge of the inset rect corresponds to t = 0 in the texture.
        // It actually simplifies things a bit in the !isFast case, too.
        float threeSigma = sixSigma / 2;
        SkRect insetRect = {rect.fLeft + threeSigma, rect.fTop + threeSigma,
                            rect.fRight - threeSigma, rect.fBottom - threeSigma};

        // In our fast variant we find the nearest horizontal and vertical edges and for each
        // do a lookup in the integral texture for each and multiply them. When the rect is
        // less than 6 sigma wide then things aren't so simple and we have to consider both the
        // left and right edge of the rectangle (and similar in y).
        bool isFast = insetRect.isSorted();
        // 1 / (6 * sigma) is the domain of the integral texture. We use the inverse to produce
        // normalized texture coords from frag coord distances.
        float invSixSigma = 1.f / sixSigma;
        return std::unique_ptr<GrFragmentProcessor>(
                new GrRectBlurEffect(insetRect, std::move(integral), invSixSigma, isFast,
                                     GrSamplerState::ClampBilerp()));
    }
    GrRectBlurEffect(const GrRectBlurEffect& src);
    std::unique_ptr<GrFragmentProcessor> clone() const override;
    const char* name() const override { return "RectBlurEffect"; }
    SkRect rect;
    TextureSampler integral;
    float invSixSigma;
    bool isFast;

private:
    GrRectBlurEffect(SkRect rect, sk_sp<GrTextureProxy> integral, float invSixSigma, bool isFast,
                     GrSamplerState samplerParams)
            : INHERITED(kGrRectBlurEffect_ClassID,
                        (OptimizationFlags)kCompatibleWithCoverageAsAlpha_OptimizationFlag)
            , rect(rect)
            , integral(std::move(integral), samplerParams)
            , invSixSigma(invSixSigma)
            , isFast(isFast) {
        this->setTextureSamplerCnt(1);
    }
    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
    void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
    bool onIsEqual(const GrFragmentProcessor&) const override;
    const TextureSampler& onTextureSampler(int) const override;
    GR_DECLARE_FRAGMENT_PROCESSOR_TEST
    typedef GrFragmentProcessor INHERITED;
};
#endif
