/*
 * 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 GrAARectEffect.fp; do not modify.
 **************************************************************************************************/
#include "GrAARectEffect.h"

#include "src/core/SkUtils.h"
#include "src/gpu/GrTexture.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
#include "src/sksl/SkSLCPP.h"
#include "src/sksl/SkSLUtil.h"
class GrGLSLAARectEffect : public GrGLSLFragmentProcessor {
public:
    GrGLSLAARectEffect() {}
    void emitCode(EmitArgs& args) override {
        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
        const GrAARectEffect& _outer = args.fFp.cast<GrAARectEffect>();
        (void)_outer;
        auto edgeType = _outer.edgeType;
        (void)edgeType;
        auto rect = _outer.rect;
        (void)rect;
        prevRect = float4(-1.0);
        rectUniformVar = args.fUniformHandler->addUniform(
                &_outer, kFragment_GrShaderFlag, kFloat4_GrSLType, "rectUniform");
        fragBuilder->codeAppendf(
                R"SkSL(float4 prevRect = float4(%f, %f, %f, %f);
half coverage;
@switch (%d) {
    case 0:
    case 2:
        coverage = half(all(greaterThan(float4(sk_FragCoord.xy, %s.zw), float4(%s.xy, sk_FragCoord.xy))) ? 1 : 0);
        break;
    default:
        half4 dists4 = clamp(half4(1.0, 1.0, -1.0, -1.0) * half4(sk_FragCoord.xyxy - %s), 0.0, 1.0);
        half2 dists2 = (dists4.xy + dists4.zw) - 1.0;
        coverage = dists2.x * dists2.y;
}
@if (%d == 2 || %d == 3) {
    coverage = 1.0 - coverage;
})SkSL",
                prevRect.left(),
                prevRect.top(),
                prevRect.right(),
                prevRect.bottom(),
                (int)_outer.edgeType,
                args.fUniformHandler->getUniformCStr(rectUniformVar),
                args.fUniformHandler->getUniformCStr(rectUniformVar),
                args.fUniformHandler->getUniformCStr(rectUniformVar),
                (int)_outer.edgeType,
                (int)_outer.edgeType);
        SkString _sample0 = this->invokeChild(0, args);
        fragBuilder->codeAppendf(
                R"SkSL(
return %s * coverage;
)SkSL",
                _sample0.c_str());
    }

private:
    void onSetData(const GrGLSLProgramDataManager& pdman,
                   const GrFragmentProcessor& _proc) override {
        const GrAARectEffect& _outer = _proc.cast<GrAARectEffect>();
        auto edgeType = _outer.edgeType;
        (void)edgeType;
        auto rect = _outer.rect;
        (void)rect;
        UniformHandle& rectUniform = rectUniformVar;
        (void)rectUniform;

        SkASSERT(rect.isSorted());
        // The AA math in the shader evaluates to 0 at the uploaded coordinates, so outset by 0.5
        // to interpolate from 0 at a half pixel inset and 1 at a half pixel outset of rect.
        const SkRect& newRect =
                GrProcessorEdgeTypeIsAA(edgeType) ? rect.makeOutset(.5f, .5f) : rect;
        if (newRect != prevRect) {
            pdman.set4f(rectUniform, newRect.fLeft, newRect.fTop, newRect.fRight, newRect.fBottom);
            prevRect = newRect;
        }
    }
    SkRect prevRect = float4(0);
    UniformHandle rectUniformVar;
};
std::unique_ptr<GrGLSLFragmentProcessor> GrAARectEffect::onMakeProgramImpl() const {
    return std::make_unique<GrGLSLAARectEffect>();
}
void GrAARectEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
                                           GrProcessorKeyBuilder* b) const {
    b->addBits(2, (uint32_t)edgeType, "edgeType");
}
bool GrAARectEffect::onIsEqual(const GrFragmentProcessor& other) const {
    const GrAARectEffect& that = other.cast<GrAARectEffect>();
    (void)that;
    if (edgeType != that.edgeType) return false;
    if (rect != that.rect) return false;
    return true;
}
GrAARectEffect::GrAARectEffect(const GrAARectEffect& src)
        : INHERITED(kGrAARectEffect_ClassID, src.optimizationFlags())
        , edgeType(src.edgeType)
        , rect(src.rect) {
    this->cloneAndRegisterAllChildProcessors(src);
}
std::unique_ptr<GrFragmentProcessor> GrAARectEffect::clone() const {
    return std::make_unique<GrAARectEffect>(*this);
}
#if GR_TEST_UTILS
SkString GrAARectEffect::onDumpInfo() const {
    return SkStringPrintf("(edgeType=%d, rect=float4(%f, %f, %f, %f))",
                          (int)edgeType,
                          rect.left(),
                          rect.top(),
                          rect.right(),
                          rect.bottom());
}
#endif
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrAARectEffect);
#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrAARectEffect::TestCreate(GrProcessorTestData* d) {
    SkRect rect = SkRect::MakeLTRB(d->fRandom->nextSScalar1(),
                                   d->fRandom->nextSScalar1(),
                                   d->fRandom->nextSScalar1(),
                                   d->fRandom->nextSScalar1());
    rect.sort();
    GrClipEdgeType edgeType =
            static_cast<GrClipEdgeType>(d->fRandom->nextULessThan(kGrClipEdgeTypeCnt));

    return GrAARectEffect::Make(d->inputFP(), edgeType, rect);
}
#endif
