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

#include "src/gpu/effects/GrTextureEffect.h"

#include "include/gpu/GrTexture.h"
#include "src/gpu/GrTexturePriv.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"

namespace {
struct Span {
    float fA = 0.f, fB = 0.f;

    Span makeInset(float o) const {
        Span r = {fA + o, fB - o};
        if (r.fA > r.fB) {
            r.fA = r.fB = (r.fA + r.fB) / 2;
        }
        return r;
    }

    bool contains(Span r) const { return fA <= r.fA && fB >= r.fB; }
};
}  // anonymous namespace

GrTextureEffect::Sampling::Sampling(GrSamplerState sampler, SkISize size, const GrCaps& caps)
        : fHWSampler(sampler) {
    if (!caps.clampToBorderSupport()) {
        if (fHWSampler.wrapModeX() == GrSamplerState::WrapMode::kClampToBorder) {
            fHWSampler.setWrapModeX(GrSamplerState::WrapMode::kClamp);
            fShaderModes[0] = ShaderMode::kDecal;
            Span span{0, (float)size.width()};
            if (sampler.filter() != GrSamplerState::Filter::kNearest) {
                span = span.makeInset(0.5f);
            }
            fShaderSubset.fLeft  = span.fA;
            fShaderSubset.fRight = span.fB;
        }
        if (fHWSampler.wrapModeY() == GrSamplerState::WrapMode::kClampToBorder) {
            fHWSampler.setWrapModeY(GrSamplerState::WrapMode::kClamp);
            fShaderModes[1] = ShaderMode::kDecal;
            Span span{0, (float)size.height()};
            if (sampler.filter() != GrSamplerState::Filter::kNearest) {
                span = span.makeInset(0.5f);
            }
            fShaderSubset.fTop    = span.fA;
            fShaderSubset.fBottom = span.fB;
        }
    }
    if (!caps.npotTextureTileSupport()) {
        if (fHWSampler.wrapModeX() != GrSamplerState::WrapMode::kClamp && !SkIsPow2(size.width())) {
            fShaderModes[0] = static_cast<ShaderMode>(fHWSampler.wrapModeX());
            fHWSampler.setWrapModeX(GrSamplerState::WrapMode::kClamp);
            // We don't yet support shader based Mirror or Repeat with filtering.
            fHWSampler.setFilterMode(GrSamplerState::Filter::kNearest);
            fShaderSubset.fLeft  = 0;
            fShaderSubset.fRight = size.width();
        }
        if (fHWSampler.wrapModeY() != GrSamplerState::WrapMode::kClamp &&
            !SkIsPow2(size.height())) {
            fShaderModes[1] = static_cast<ShaderMode>(fHWSampler.wrapModeY());
            fHWSampler.setWrapModeY(GrSamplerState::WrapMode::kClamp);
            fHWSampler.setFilterMode(GrSamplerState::Filter::kNearest);
            fShaderSubset.fTop    = 0;
            fShaderSubset.fBottom = size.height();
        }
    }
}

GrTextureEffect::Sampling::Sampling(const GrSurfaceProxy& proxy,
                                    GrSamplerState sampler,
                                    const SkRect& subset,
                                    const SkRect* domain,
                                    const GrCaps& caps) {
    using Mode = GrSamplerState::WrapMode;
    using Filter = GrSamplerState::Filter;

    struct Result1D {
        ShaderMode fShaderMode;
        Span fShaderSubset;
        Mode fHWMode;
        Filter fFilter;
    };

    auto resolve = [filter = sampler.filter(), &caps](int size, Mode mode, Span subset,
                                                      Span domain) {
        Result1D r;
        r.fFilter = filter;
        bool canDoHW = (mode != Mode::kClampToBorder || caps.clampToBorderSupport()) &&
                       (mode == Mode::kClamp || caps.npotTextureTileSupport() || SkIsPow2(size));
        if (canDoHW && size > 0 && subset.fA <= 0 && subset.fB >= size) {
            r.fShaderMode = ShaderMode::kNone;
            r.fHWMode = mode;
            return r;
        }

        bool domainIsSafe = false;
        Span insetSubset;
        if (filter == Filter::kNearest) {
            Span isubset{sk_float_floor(subset.fA), sk_float_ceil(subset.fB)};
            if (domain.fA > isubset.fA && domain.fB < isubset.fB) {
                domainIsSafe = true;
            }
            if (mode == Mode::kClamp) {
                // This inset prevents sampling neighboring texels that could occur when
                // texture coords fall exactly at texel boundaries (depending on precision
                // and GPU-specific snapping at the boundary).
                insetSubset = isubset.makeInset(0.5f);
            } else {
                // TODO: Handle other modes properly in this case.
                insetSubset = subset;
            }
        } else {
            insetSubset = subset.makeInset(0.5f);
            domainIsSafe = insetSubset.contains(domain);
        }
        if (canDoHW && domainIsSafe) {
            r.fShaderMode = ShaderMode::kNone;
            r.fHWMode = mode;
            return r;
        }

        if (mode == Mode::kRepeat || mode == Mode::kMirrorRepeat) {
            r.fFilter = Filter::kNearest;
            r.fShaderSubset = subset;
        } else {
            r.fShaderSubset = insetSubset;
        }
        r.fShaderMode = static_cast<ShaderMode>(mode);
        r.fHWMode = Mode::kClamp;
        return r;
    };

    SkISize dim = proxy.isFullyLazy() ? SkISize{-1, -1} : proxy.backingStoreDimensions();

    Span subsetX{subset.fLeft, subset.fRight};
    auto domainX = domain ? Span{domain->fLeft, domain->fRight}
                          : Span{SK_FloatNegativeInfinity, SK_FloatInfinity};
    auto x = resolve(dim.width(), sampler.wrapModeX(), subsetX, domainX);

    Span subsetY{subset.fTop, subset.fBottom};
    auto domainY = domain ? Span{domain->fTop, domain->fBottom}
                          : Span{SK_FloatNegativeInfinity, SK_FloatInfinity};
    auto y = resolve(dim.height(), sampler.wrapModeY(), subsetY, domainY);

    fHWSampler = {x.fHWMode, y.fHWMode, std::min(x.fFilter, y.fFilter)};
    fShaderModes[0] = x.fShaderMode;
    fShaderModes[1] = y.fShaderMode;
    fShaderSubset = {x.fShaderSubset.fA, y.fShaderSubset.fA,
                     x.fShaderSubset.fB, y.fShaderSubset.fB};
}

bool GrTextureEffect::Sampling::usesDecal() const {
    return fShaderModes[0] == ShaderMode::kDecal || fShaderModes[1] == ShaderMode::kDecal ||
           fHWSampler.wrapModeX() == GrSamplerState::WrapMode::kClampToBorder ||
           fHWSampler.wrapModeY() == GrSamplerState::WrapMode::kClampToBorder;
}

std::unique_ptr<GrFragmentProcessor> GrTextureEffect::Make(GrSurfaceProxyView view,
                                                           SkAlphaType alphaType,
                                                           const SkMatrix& matrix,
                                                           GrSamplerState::Filter filter) {
    return std::unique_ptr<GrFragmentProcessor>(
            new GrTextureEffect(std::move(view), alphaType, matrix, Sampling(filter)));
}

std::unique_ptr<GrFragmentProcessor> GrTextureEffect::Make(GrSurfaceProxyView view,
                                                           SkAlphaType alphaType,
                                                           const SkMatrix& matrix,
                                                           GrSamplerState sampler,
                                                           const GrCaps& caps) {
    Sampling sampling(sampler, view.proxy()->dimensions(), caps);
    return std::unique_ptr<GrFragmentProcessor>(
            new GrTextureEffect(std::move(view), alphaType, matrix, sampling));
}

std::unique_ptr<GrFragmentProcessor> GrTextureEffect::MakeTexelSubset(GrSurfaceProxyView view,
                                                                      SkAlphaType alphaType,
                                                                      const SkMatrix& matrix,
                                                                      GrSamplerState sampler,
                                                                      const SkIRect& subset,
                                                                      const GrCaps& caps) {
    Sampling sampling(*view.proxy(), sampler, SkRect::Make(subset), nullptr, caps);
    return std::unique_ptr<GrFragmentProcessor>(
            new GrTextureEffect(std::move(view), alphaType, matrix, sampling));
}

std::unique_ptr<GrFragmentProcessor> GrTextureEffect::MakeTexelSubset(GrSurfaceProxyView view,
                                                                      SkAlphaType alphaType,
                                                                      const SkMatrix& matrix,
                                                                      GrSamplerState sampler,
                                                                      const SkIRect& subset,
                                                                      const SkRect& domain,
                                                                      const GrCaps& caps) {
    Sampling sampling(*view.proxy(), sampler, SkRect::Make(subset), &domain, caps);
    return std::unique_ptr<GrFragmentProcessor>(
            new GrTextureEffect(std::move(view), alphaType, matrix, sampling));
}

std::unique_ptr<GrFragmentProcessor> GrTextureEffect::MakeSubset(GrSurfaceProxyView view,
                                                                 SkAlphaType alphaType,
                                                                 const SkMatrix& matrix,
                                                                 GrSamplerState sampler,
                                                                 const SkRect& subset,
                                                                 const GrCaps& caps) {
    Sampling sampling(*view.proxy(), sampler, subset, nullptr, caps);
    return std::unique_ptr<GrFragmentProcessor>(
            new GrTextureEffect(std::move(view), alphaType, matrix, sampling));
}

std::unique_ptr<GrFragmentProcessor> GrTextureEffect::MakeSubset(GrSurfaceProxyView view,
                                                                 SkAlphaType alphaType,
                                                                 const SkMatrix& matrix,
                                                                 GrSamplerState sampler,
                                                                 const SkRect& subset,
                                                                 const SkRect& domain,
                                                                 const GrCaps& caps) {
    Sampling sampling(*view.proxy(), sampler, subset, &domain, caps);
    return std::unique_ptr<GrFragmentProcessor>(
            new GrTextureEffect(std::move(view), alphaType, matrix, sampling));
}

GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const {
    class Impl : public GrGLSLFragmentProcessor {
        UniformHandle fSubsetUni;
        UniformHandle fDecalUni;

    public:
        void emitCode(EmitArgs& args) override {
            auto appendWrap = [](GrGLSLShaderBuilder* builder, ShaderMode mode, const char* inCoord,
                                 const char* domainStart, const char* domainEnd, bool is2D,
                                 const char* out) {
                switch (mode) {
                    case ShaderMode::kNone:
                        builder->codeAppendf("%s = %s;\n", out, inCoord);
                        break;
                    case ShaderMode::kDecal:
                        // The lookup coordinate to use for decal will be clamped just like
                        // kClamp_Mode, it's just that the post-processing will be different, so
                        // fall through
                    case ShaderMode::kClamp:
                        builder->codeAppendf("%s = clamp(%s, %s, %s);", out, inCoord, domainStart,
                                             domainEnd);
                        break;
                    case ShaderMode::kRepeat:
                        builder->codeAppendf("%s = mod(%s - %s, %s - %s) + %s;", out, inCoord,
                                             domainStart, domainEnd, domainStart, domainStart);
                        break;
                    case ShaderMode::kMirrorRepeat: {
                        const char* type = is2D ? "float2" : "float";
                        builder->codeAppend("{");
                        builder->codeAppendf("%s w = %s - %s;", type, domainEnd, domainStart);
                        builder->codeAppendf("%s w2 = 2 * w;", type);
                        builder->codeAppendf("%s m = mod(%s - %s, w2);", type, inCoord,
                                             domainStart);
                        builder->codeAppendf("%s = mix(m, w2 - m, step(w, m)) + %s;", out,
                                             domainStart);
                        builder->codeAppend("}");
                        break;
                    }
                }
            };
            auto te = args.fFp.cast<GrTextureEffect>();
            const char* coords;
            if (args.fFp.coordTransformsApplyToLocalCoords()) {
                coords = args.fTransformedCoords[0].fVaryingPoint.c_str();
            } else {
                coords = "_coords";
            }
            auto* fb = args.fFragBuilder;
            if (te.fShaderModes[0] == ShaderMode::kNone &&
                te.fShaderModes[1] == ShaderMode::kNone) {
                fb->codeAppendf("%s = ", args.fOutputColor);
                fb->appendTextureLookupAndBlend(args.fInputColor, SkBlendMode::kModulate,
                                                args.fTexSamplers[0], coords);
                fb->codeAppendf(";");
            } else {
                const char* subsetName;
                SkString uniName("TexDom");
                fSubsetUni = args.fUniformHandler->addUniform(
                        kFragment_GrShaderFlag, kHalf4_GrSLType, "subset", &subsetName);

                // Always use a local variable for the input coordinates; often callers pass in an
                // expression and we want to cache it across all of its references in the code below
                auto inCoords = fb->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
                fb->codeAppend("float2 clampedCoord;");
                SkString start;
                SkString end;
                if (te.fShaderModes[0] == te.fShaderModes[1]) {
                    // Doing the domain setup using vectors seems to avoid shader compilation issues
                    // on Chromecast, possibly due to reducing shader length.
                    start.printf("%s.xy", subsetName);
                    end.printf("%s.zw", subsetName);
                    appendWrap(fb, te.fShaderModes[0], inCoords.c_str(), start.c_str(), end.c_str(),
                               true, "clampedCoord");
                } else {
                    SkString origX, origY;
                    // Apply x mode to the x coordinate using the left and right edges of the domain
                    // rect (stored as the x and z components of the domain uniform).
                    start.printf("%s.x", subsetName);
                    end.printf("%s.z", subsetName);
                    origX.printf("%s.x", inCoords.c_str());
                    appendWrap(fb, te.fShaderModes[0], origX.c_str(), start.c_str(), end.c_str(),
                               false, "clampedCoord.x");
                    // Repeat the same logic for y.
                    start.printf("%s.y", subsetName);
                    end.printf("%s.w", subsetName);
                    origY.printf("%s.y", inCoords.c_str());
                    appendWrap(fb, te.fShaderModes[1], origY.c_str(), start.c_str(), end.c_str(),
                               false, "clampedCoord.y");
                }
                SkString textureLookup;
                fb->appendTextureLookup(&textureLookup, args.fTexSamplers[0], "clampedCoord");
                fb->codeAppendf("half4 textureColor = %s;", textureLookup.c_str());

                // Apply decal mode's transparency interpolation if needed
                bool decalX = te.fShaderModes[0] == ShaderMode::kDecal;
                bool decalY = te.fShaderModes[1] == ShaderMode::kDecal;
                if (decalX || decalY) {
                    const char* decalName;
                    // Half3 since this will hold texture width, height, and then a step function
                    // control param
                    fDecalUni = args.fUniformHandler->addUniform(
                            kFragment_GrShaderFlag, kHalf3_GrSLType, uniName.c_str(), &decalName);
                    // The decal err is the max absolute value between the clamped coordinate and
                    // the original pixel coordinate. This will then be clamped to 1.f if it's
                    // greater than the control parameter, which simulates kNearest and kBilerp
                    // behavior depending on if it's 0 or 1.
                    if (decalX && decalY) {
                        fb->codeAppendf(
                                "half err = max(half(abs(clampedCoord.x - %s.x) * %s.x), "
                                "               half(abs(clampedCoord.y - %s.y) * %s.y));",
                                inCoords.c_str(), decalName, inCoords.c_str(), decalName);
                    } else if (decalX) {
                        fb->codeAppendf("half err = half(abs(clampedCoord.x - %s.x) * %s.x);",
                                        inCoords.c_str(), decalName);
                    } else {
                        SkASSERT(decalY);
                        fb->codeAppendf("half err = half(abs(clampedCoord.y - %s.y) * %s.y);",
                                        inCoords.c_str(), decalName);
                    }

                    // Apply a transform to the error rate, which let's us simulate nearest or
                    // bilerp filtering in the same shader. When the texture is nearest filtered,
                    // fSizeName.z is set to 0 so this becomes a step function centered at the
                    // clamped coordinate. When bilerp, fSizeName.z is set to 1 and it becomes
                    // a simple linear blend between texture and transparent.
                    fb->codeAppendf(
                            "if (err > %s.z) { err = 1.0; } else if (%s.z < 1) { err = 0.0; }",
                            decalName, decalName);
                    fb->codeAppend("textureColor = mix(textureColor, half4(0), err);");
                }
                fb->codeAppendf("%s = textureColor * %s;", args.fOutputColor, args.fInputColor);
            }
        }

    protected:
        void onSetData(const GrGLSLProgramDataManager& pdm,
                       const GrFragmentProcessor& fp) override {
            const auto& te = fp.cast<GrTextureEffect>();
            if (fSubsetUni.isValid()) {
                const float w = te.fSampler.peekTexture()->width();
                const float h = te.fSampler.peekTexture()->height();

                const auto& s = te.fSubset;
                float rect[] = {s.fLeft, s.fTop, s.fRight, s.fBottom};
                float decalW[3];

                if (te.fSampler.view().origin() == kBottomLeft_GrSurfaceOrigin) {
                    rect[1] = h - rect[1];
                    rect[3] = h - rect[3];
                    std::swap(rect[1], rect[3]);
                }

                if (te.fSampler.peekTexture()->texturePriv().textureType() !=
                    GrTextureType::kRectangle) {
                    float iw = 1.f / w;
                    float ih = 1.f / h;
                    rect[0] *= iw;
                    rect[2] *= iw;
                    rect[1] *= ih;
                    rect[3] *= ih;
                    decalW[0] = w;
                    decalW[1] = h;
                } else {
                    decalW[0] = 1;
                    decalW[1] = 1;
                }
                pdm.set4fv(fSubsetUni, 1, rect);

                if (fDecalUni.isValid()) {
                    bool filter = te.textureSampler(0).samplerState().filter() !=
                                  GrSamplerState::Filter::kNearest;
                    decalW[2] = filter ? 1.f : 0.f;
                    pdm.set3fv(fDecalUni, 1, decalW);
                }
            }
        }
    };
    return new Impl;
}

void GrTextureEffect::onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const {
    bool shaderFilter = (fShaderModes[0] == ShaderMode::kDecal ||
                         fShaderModes[1] == ShaderMode::kDecal) &&
                        fSampler.samplerState().filter() != GrSamplerState::Filter::kNearest;
    auto m0 = static_cast<uint32_t>(fShaderModes[0]);
    auto m1 = static_cast<uint32_t>(fShaderModes[1]);
    b->add32(shaderFilter << 31 | (m0 << 16) | m1);
}

bool GrTextureEffect::onIsEqual(const GrFragmentProcessor& other) const {
    auto that = other.cast<GrTextureEffect>();
    return fShaderModes[0] == that.fShaderModes[1] && fShaderModes[1] == that.fShaderModes[1] &&
           fSubset == that.fSubset;
}

GrTextureEffect::GrTextureEffect(GrSurfaceProxyView view, SkAlphaType alphaType,
                                 const SkMatrix& matrix, const Sampling& sampling)
        : GrFragmentProcessor(kGrTextureEffect_ClassID,
                              ModulateForSamplerOptFlags(alphaType, sampling.usesDecal()))
        , fCoordTransform(matrix, view.proxy())
        , fSampler(std::move(view), sampling.fHWSampler)
        , fSubset(sampling.fShaderSubset)
        , fShaderModes{sampling.fShaderModes[0], sampling.fShaderModes[1]} {
    // We always compare the range even when it isn't used so assert we have canonical don't care
    // values.
    SkASSERT(fShaderModes[0] != ShaderMode::kNone || (fSubset.fLeft == 0 && fSubset.fRight == 0));
    SkASSERT(fShaderModes[1] != ShaderMode::kNone || (fSubset.fTop == 0 && fSubset.fBottom == 0));
    this->setTextureSamplerCnt(1);
    this->addCoordTransform(&fCoordTransform);
}

GrTextureEffect::GrTextureEffect(const GrTextureEffect& src)
        : INHERITED(kGrTextureEffect_ClassID, src.optimizationFlags())
        , fCoordTransform(src.fCoordTransform)
        , fSampler(src.fSampler)
        , fSubset(src.fSubset)
        , fShaderModes{src.fShaderModes[0], src.fShaderModes[1]} {
    this->setTextureSamplerCnt(1);
    this->addCoordTransform(&fCoordTransform);
}

std::unique_ptr<GrFragmentProcessor> GrTextureEffect::clone() const {
    return std::unique_ptr<GrFragmentProcessor>(new GrTextureEffect(*this));
}

const GrFragmentProcessor::TextureSampler& GrTextureEffect::onTextureSampler(int) const {
    return fSampler;
}

GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrTextureEffect);
#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrTextureEffect::TestCreate(GrProcessorTestData* testData) {
    auto [view, ct, at] = testData->randomView();
    GrSamplerState::WrapMode wrapModes[2];
    GrTest::TestWrapModes(testData->fRandom, wrapModes);
    if (!testData->caps()->npotTextureTileSupport()) {
        // Performing repeat sampling on npot textures will cause asserts on HW
        // that lacks support.
        wrapModes[0] = GrSamplerState::WrapMode::kClamp;
        wrapModes[1] = GrSamplerState::WrapMode::kClamp;
    }

    GrSamplerState params(wrapModes, testData->fRandom->nextBool()
                                             ? GrSamplerState::Filter::kBilerp
                                             : GrSamplerState::Filter::kNearest);

    const SkMatrix& matrix = GrTest::TestMatrix(testData->fRandom);
    return GrTextureEffect::Make(std::move(view), at, matrix, params, *testData->caps());
}
#endif
