/*
 * Copyright 2012 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/GrTextureDomain.h"

#include "include/gpu/GrTexture.h"
#include "include/private/SkFloatingPoint.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrShaderCaps.h"
#include "src/gpu/GrSurfaceProxyPriv.h"
#include "src/gpu/effects/generated/GrSimpleTextureEffect.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
#include "src/gpu/glsl/GrGLSLShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLUniformHandler.h"

#include <utility>

GrTextureDomain::GrTextureDomain(GrSurfaceProxy* proxy, const SkRect& domain, Mode modeX,
                                 Mode modeY, int index)
    : fModeX(modeX)
    , fModeY(modeY)
    , fIndex(index) {

    if (!proxy) {
        SkASSERT(modeX == kIgnore_Mode && modeY == kIgnore_Mode);
        return;
    }

    const SkRect kFullRect = proxy->getBoundsRect();

    // We don't currently handle domains that are empty or don't intersect the texture.
    // It is OK if the domain rect is a line or point, but it should not be inverted. We do not
    // handle rects that do not intersect the [0..1]x[0..1] rect.
    SkASSERT(domain.isSorted());
    fDomain.fLeft = SkScalarPin(domain.fLeft, 0.0f, kFullRect.fRight);
    fDomain.fRight = SkScalarPin(domain.fRight, fDomain.fLeft, kFullRect.fRight);
    fDomain.fTop = SkScalarPin(domain.fTop, 0.0f, kFullRect.fBottom);
    fDomain.fBottom = SkScalarPin(domain.fBottom, fDomain.fTop, kFullRect.fBottom);
    SkASSERT(fDomain.fLeft <= fDomain.fRight);
    SkASSERT(fDomain.fTop <= fDomain.fBottom);
}

GrTextureDomain::GrTextureDomain(const SkRect& domain, Mode modeX, Mode modeY, int index)
        : fDomain(domain), fModeX(modeX), fModeY(modeY), fIndex(index) {
    // We don't currently handle domains that are empty or don't intersect the texture.
    // It is OK if the domain rect is a line or point, but it should not be inverted.
    SkASSERT(domain.isSorted());
}

//////////////////////////////////////////////////////////////////////////////

static void append_wrap(GrGLSLShaderBuilder* builder, GrTextureDomain::Mode mode,
                        const char* inCoord, const char* domainStart, const char* domainEnd,
                        bool is2D, const char* out) {
    switch(mode) {
        case GrTextureDomain::kIgnore_Mode:
            builder->codeAppendf("%s = %s;\n", out, inCoord);
            break;
        case GrTextureDomain::kDecal_Mode:
            // 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 GrTextureDomain::kClamp_Mode:
            builder->codeAppendf("%s = clamp(%s, %s, %s);", out, inCoord, domainStart, domainEnd);
            break;
        case GrTextureDomain::kRepeat_Mode:
            builder->codeAppendf("%s = mod(%s - %s, %s - %s) + %s;", out, inCoord, domainStart,
                                 domainEnd, domainStart, domainStart);
            break;
        case GrTextureDomain::kMirrorRepeat_Mode: {
            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;
        }
    }
}

void GrTextureDomain::GLDomain::sampleProcessor(const GrTextureDomain& textureDomain,
                                                const char* inColor,
                                                const char* outColor,
                                                const SkString& inCoords,
                                                GrGLSLFragmentProcessor* parent,
                                                GrGLSLFragmentProcessor::EmitArgs& args,
                                                int childIndex) {
    auto appendProcessorSample = [parent, &args, childIndex, inColor](const char* coord) {
        SkString outColor("childColor");
        parent->invokeChild(childIndex, inColor, &outColor, args, coord);
        return outColor;
    };
    this->sample(args.fFragBuilder, args.fUniformHandler, textureDomain, outColor, inCoords,
                 appendProcessorSample);
}

void GrTextureDomain::GLDomain::sampleTexture(GrGLSLShaderBuilder* builder,
                                              GrGLSLUniformHandler* uniformHandler,
                                              const GrShaderCaps* shaderCaps,
                                              const GrTextureDomain& textureDomain,
                                              const char* outColor,
                                              const SkString& inCoords,
                                              GrGLSLFragmentProcessor::SamplerHandle sampler,
                                              const char* inModulateColor) {
    auto appendTextureSample = [&sampler, inModulateColor, builder](const char* coord) {
        builder->codeAppend("half4 textureColor = ");
        builder->appendTextureLookupAndModulate(inModulateColor, sampler, coord);
        builder->codeAppend(";");
        return SkString("textureColor");
    };
    this->sample(builder, uniformHandler, textureDomain, outColor, inCoords, appendTextureSample);
}

void GrTextureDomain::GLDomain::sample(GrGLSLShaderBuilder* builder,
                                       GrGLSLUniformHandler* uniformHandler,
                                       const GrTextureDomain& textureDomain,
                                       const char* outColor,
                                       const SkString& inCoords,
                                       const std::function<AppendSample>& appendSample) {
    SkASSERT(!fHasMode || (textureDomain.modeX() == fModeX && textureDomain.modeY() == fModeY));
    SkDEBUGCODE(fModeX = textureDomain.modeX();)
    SkDEBUGCODE(fModeY = textureDomain.modeY();)
    SkDEBUGCODE(fHasMode = true;)

    if ((textureDomain.modeX() != kIgnore_Mode || textureDomain.modeY() != kIgnore_Mode) &&
        !fDomainUni.isValid()) {
        // Must include the domain uniform since at least one axis uses it
        const char* name;
        SkString uniName("TexDom");
        if (textureDomain.fIndex >= 0) {
            uniName.appendS32(textureDomain.fIndex);
        }
        fDomainUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
                                                uniName.c_str(), &name);
        fDomainName = name;
    }

    bool decalX = textureDomain.modeX() == kDecal_Mode;
    bool decalY = textureDomain.modeY() == kDecal_Mode;
    if ((decalX || decalY) && !fDecalUni.isValid()) {
        const char* name;
        SkString uniName("DecalParams");
        if (textureDomain.fIndex >= 0) {
            uniName.appendS32(textureDomain.fIndex);
        }
        // Half3 since this will hold texture width, height, and then a step function control param
        fDecalUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
                                               uniName.c_str(), &name);
        fDecalName = name;
    }

    // Add a block so that we can declare variables
    GrGLSLShaderBuilder::ShaderBlock block(builder);
    // 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
    builder->codeAppendf("float2 origCoord = %s;", inCoords.c_str());
    builder->codeAppend("float2 clampedCoord;");
    SkString start;
    SkString end;
    bool is2D = textureDomain.modeX() == textureDomain.modeY();
    if (is2D) {
        // Doing the domain setup using vectors seems to avoid shader compilation issues on
        // Chromecast, possibly due to reducing shader length.
        start.printf("%s.xy", fDomainName.c_str());
        end.printf("%s.zw", fDomainName.c_str());
        append_wrap(builder, textureDomain.modeX(), "origCoord", start.c_str(), end.c_str(),
                    true, "clampedCoord");
    } else {
        // 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", fDomainName.c_str());
        end.printf("%s.z", fDomainName.c_str());
        append_wrap(builder, textureDomain.modeX(), "origCoord.x", start.c_str(), end.c_str(),
                    false, "clampedCoord.x");
        // Repeat the same logic for y.
        start.printf("%s.y", fDomainName.c_str());
        end.printf("%s.w", fDomainName.c_str());
        append_wrap(builder, textureDomain.modeY(), "origCoord.y", start.c_str(), end.c_str(),
                    false, "clampedCoord.y");
    }
    // Sample 'appendSample' at the clamped coordinate location.
    SkString color = appendSample("clampedCoord");

    // Apply decal mode's transparency interpolation if needed
    if (decalX || decalY) {
        // The decal err is the max absoluate 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) {
            builder->codeAppendf("half err = max(half(abs(clampedCoord.x - origCoord.x) * %s.x), "
                                                "half(abs(clampedCoord.y - origCoord.y) * %s.y));",
                                 fDecalName.c_str(), fDecalName.c_str());
        } else if (decalX) {
            builder->codeAppendf("half err = half(abs(clampedCoord.x - origCoord.x) * %s.x);",
                                 fDecalName.c_str());
        } else {
            SkASSERT(decalY);
            builder->codeAppendf("half err = half(abs(clampedCoord.y - origCoord.y) * %s.y);",
                                 fDecalName.c_str());
        }

        // 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 1/2 so
        // this becomes a step function centered at .5 away from the clamped coordinate (but the
        // domain for decal is inset by .5 so the edge lines up properly). When bilerp, fSizeName.z
        // is set to 1 and it becomes a simple linear blend between texture and transparent.
        builder->codeAppendf("if (err > %s.z) { err = 1.0; } else if (%s.z < 1) { err = 0.0; }",
                             fDecalName.c_str(), fDecalName.c_str());
        builder->codeAppendf("%s = mix(%s, half4(0, 0, 0, 0), err);", outColor, color.c_str());
    } else {
        // A simple look up
        builder->codeAppendf("%s = %s;", outColor, color.c_str());
    }
}

void GrTextureDomain::GLDomain::setData(const GrGLSLProgramDataManager& pdman,
                                        const GrTextureDomain& textureDomain,
                                        const GrSurfaceProxyView& view,
                                        const GrSamplerState& state) {
    // We want a hard transition from texture content to trans-black in nearest mode.
    bool filterDecal = state.filter() != GrSamplerState::Filter::kNearest;
    this->setData(pdman, textureDomain, view.proxy(), view.origin(), filterDecal);
}

void GrTextureDomain::GLDomain::setData(const GrGLSLProgramDataManager& pdman,
                                        const GrTextureDomain& textureDomain,
                                        bool filterIfDecal) {
    // The origin we pass here doesn't matter
    this->setData(pdman, textureDomain, nullptr, kTopLeft_GrSurfaceOrigin, filterIfDecal);
}

void GrTextureDomain::GLDomain::setData(const GrGLSLProgramDataManager& pdman,
                                        const GrTextureDomain& textureDomain,
                                        const GrSurfaceProxy* proxy,
                                        GrSurfaceOrigin origin,
                                        bool filterIfDecal) {
    SkASSERT(fHasMode && textureDomain.modeX() == fModeX && textureDomain.modeY() == fModeY);
    if (kIgnore_Mode == textureDomain.modeX() && kIgnore_Mode == textureDomain.modeY()) {
        return;
    }
    // If the texture is using nearest filtering, then the decal filter weight should step from
    // 0 (texture) to 1 (transparent) one half pixel away from the domain. When doing any other
    // form of filtering, the weight should be 1.0 so that it smoothly interpolates between the
    // texture and transparent.
    // Start off assuming we're in pixel units and later adjust if we have to deal with normalized
    // texture coords.
    float decalFilterWeights[3] = {1.f, 1.f, filterIfDecal ? 1.f : 0.5f};
    bool sendDecalData = textureDomain.modeX() == kDecal_Mode ||
                         textureDomain.modeY() == kDecal_Mode;
    float tempDomainValues[4];
    const float* values;
    if (proxy) {
        SkScalar wInv, hInv, h;
        GrTexture* tex = proxy->peekTexture();
        if (proxy->backendFormat().textureType() == GrTextureType::kRectangle) {
            wInv = hInv = 1.f;
            h = tex->height();
            // Don't do any scaling by texture size for decal filter rate, it's already in
            // pixels
        } else {
            wInv = SK_Scalar1 / tex->width();
            hInv = SK_Scalar1 / tex->height();
            h = 1.f;

            // Account for texture coord normalization in decal filter weights.
            decalFilterWeights[0] = tex->width();
            decalFilterWeights[1] = tex->height();
        }

        tempDomainValues[0] = SkScalarToFloat(textureDomain.domain().fLeft * wInv);
        tempDomainValues[1] = SkScalarToFloat(textureDomain.domain().fTop * hInv);
        tempDomainValues[2] = SkScalarToFloat(textureDomain.domain().fRight * wInv);
        tempDomainValues[3] = SkScalarToFloat(textureDomain.domain().fBottom * hInv);

        if (proxy->backendFormat().textureType() == GrTextureType::kRectangle) {
            SkASSERT(tempDomainValues[0] >= 0.0f && tempDomainValues[0] <= proxy->width());
            SkASSERT(tempDomainValues[1] >= 0.0f && tempDomainValues[1] <= proxy->height());
            SkASSERT(tempDomainValues[2] >= 0.0f && tempDomainValues[2] <= proxy->width());
            SkASSERT(tempDomainValues[3] >= 0.0f && tempDomainValues[3] <= proxy->height());
        } else {
            SkASSERT(tempDomainValues[0] >= 0.0f && tempDomainValues[0] <= 1.0f);
            SkASSERT(tempDomainValues[1] >= 0.0f && tempDomainValues[1] <= 1.0f);
            SkASSERT(tempDomainValues[2] >= 0.0f && tempDomainValues[2] <= 1.0f);
            SkASSERT(tempDomainValues[3] >= 0.0f && tempDomainValues[3] <= 1.0f);
        }

        // vertical flip if necessary
        if (kBottomLeft_GrSurfaceOrigin == origin) {
            tempDomainValues[1] = h - tempDomainValues[1];
            tempDomainValues[3] = h - tempDomainValues[3];

            // The top and bottom were just flipped, so correct the ordering
            // of elements so that values = (l, t, r, b).
            using std::swap;
            swap(tempDomainValues[1], tempDomainValues[3]);
        }
        values = tempDomainValues;
    } else {
        values = textureDomain.domain().asScalars();
    }
    if (!std::equal(values, values + 4, fPrevDomain)) {
        pdman.set4fv(fDomainUni, 1, values);
        std::copy_n(values, 4, fPrevDomain);
    }
    if (sendDecalData &&
        !std::equal(decalFilterWeights, decalFilterWeights + 3, fPrevDeclFilterWeights)) {
        pdman.set3fv(fDecalUni, 1, decalFilterWeights);
        std::copy_n(decalFilterWeights, 3, fPrevDeclFilterWeights);
    }
}

///////////////////////////////////////////////////////////////////////////////

std::unique_ptr<GrFragmentProcessor> GrDomainEffect::Make(std::unique_ptr<GrFragmentProcessor> fp,
                                                          const SkRect& domain,
                                                          GrTextureDomain::Mode mode,
                                                          bool decalIsFiltered) {
    return Make(std::move(fp), domain, mode, mode, decalIsFiltered);
}

std::unique_ptr<GrFragmentProcessor> GrDomainEffect::Make(std::unique_ptr<GrFragmentProcessor> fp,
                                                          const SkRect& domain,
                                                          GrTextureDomain::Mode modeX,
                                                          GrTextureDomain::Mode modeY,
                                                          bool decalIsFiltered) {
    if (modeX == GrTextureDomain::kIgnore_Mode && modeY == GrTextureDomain::kIgnore_Mode) {
        return fp;
    }
    int count = 0;
    GrCoordTransform* coordTransform = nullptr;
    for (auto [transform, ignored] : GrFragmentProcessor::FPCoordTransformRange(*fp)) {
        ++count;
        coordTransform = &transform;
    }
    // If there are no coord transforms on the passed FP or it's children then there's no need to
    // enforce a domain.
    // We have a limitation that only one coord transform is support when overriding local coords.
    // If that limit were relaxed we would need to add a coord transform for each descendent FP
    // transform and possibly have multiple domain rects to account for different proxy
    // normalization and y-reversals.
    if (count != 1) {
        return fp;
    }
    GrCoordTransform transformCopy = *coordTransform;
    // Reset the child FP's coord transform.
    *coordTransform = {};
    // If both domain modes happen to be ignore, it would be faster to just drop the domain logic
    // entirely and return the original FP. We'd need a GrMatrixProcessor if the matrix is not
    // identity, though.
    return std::unique_ptr<GrFragmentProcessor>(new GrDomainEffect(
            std::move(fp), transformCopy, domain, modeX, modeY, decalIsFiltered));
}

std::unique_ptr<GrFragmentProcessor> GrDomainEffect::Make(std::unique_ptr<GrFragmentProcessor> fp,
                                                          const SkRect& domain,
                                                          GrTextureDomain::Mode mode,
                                                          GrSamplerState::Filter filter) {
    bool filterIfDecal = filter != GrSamplerState::Filter::kNearest;
    return Make(std::move(fp), domain, mode, filterIfDecal);
}

std::unique_ptr<GrFragmentProcessor> GrDomainEffect::Make(std::unique_ptr<GrFragmentProcessor> fp,
                                                          const SkRect& domain,
                                                          GrTextureDomain::Mode modeX,
                                                          GrTextureDomain::Mode modeY,
                                                          GrSamplerState::Filter filter) {
    bool filterIfDecal = filter != GrSamplerState::Filter::kNearest;
    return Make(std::move(fp), domain, modeX, modeY, filterIfDecal);
}
GrFragmentProcessor::OptimizationFlags GrDomainEffect::Flags(GrFragmentProcessor* fp,
                                                             GrTextureDomain::Mode modeX,
                                                             GrTextureDomain::Mode modeY) {
    auto fpFlags = GrFragmentProcessor::ProcessorOptimizationFlags(fp);
    if (modeX == GrTextureDomain::kDecal_Mode || modeY == GrTextureDomain::kDecal_Mode) {
        return fpFlags & ~kPreservesOpaqueInput_OptimizationFlag;
    }
    return fpFlags;
}

GrDomainEffect::GrDomainEffect(std::unique_ptr<GrFragmentProcessor> fp,
                               const GrCoordTransform& coordTransform,
                               const SkRect& domain,
                               GrTextureDomain::Mode modeX,
                               GrTextureDomain::Mode modeY,
                               bool decalIsFiltered)
        : INHERITED(kGrDomainEffect_ClassID, Flags(fp.get(), modeX, modeY))
        , fCoordTransform(coordTransform)
        , fDomain(domain, modeX, modeY)
        , fDecalIsFiltered(decalIsFiltered) {
    SkASSERT(fp);
    fp->setSampledWithExplicitCoords(true);
    this->registerChildProcessor(std::move(fp));
    this->addCoordTransform(&fCoordTransform);
    if (fDomain.modeX() != GrTextureDomain::kDecal_Mode &&
        fDomain.modeY() != GrTextureDomain::kDecal_Mode) {
        // Canonicalize this don't care value so we don't have to worry about it elsewhere.
        fDecalIsFiltered = false;
    }
}

GrDomainEffect::GrDomainEffect(const GrDomainEffect& that)
        : INHERITED(kGrDomainEffect_ClassID, that.optimizationFlags())
        , fCoordTransform(that.fCoordTransform)
        , fDomain(that.fDomain)
        , fDecalIsFiltered(that.fDecalIsFiltered) {
    auto child = that.childProcessor(0).clone();
    child->setSampledWithExplicitCoords(true);
    this->registerChildProcessor(std::move(child));
    this->addCoordTransform(&fCoordTransform);
}

void GrDomainEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
                                           GrProcessorKeyBuilder* b) const {
    b->add32(GrTextureDomain::GLDomain::DomainKey(fDomain));
}

GrGLSLFragmentProcessor* GrDomainEffect::onCreateGLSLInstance() const {
    class GLSLProcessor : public GrGLSLFragmentProcessor {
    public:
        void emitCode(EmitArgs& args) override {
            const GrDomainEffect& de = args.fFp.cast<GrDomainEffect>();
            const GrTextureDomain& domain = de.fDomain;

            SkString coords2D =
                    args.fFragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);

            fGLDomain.sampleProcessor(domain, args.fInputColor, args.fOutputColor, coords2D, this,
                                      args, 0);
        }

    protected:
        void onSetData(const GrGLSLProgramDataManager& pdman,
                       const GrFragmentProcessor& fp) override {
            const GrDomainEffect& de = fp.cast<GrDomainEffect>();
            const GrTextureDomain& domain = de.fDomain;
            // TODO: Update GrCoordTransform to return a view instead of proxy
            const GrSurfaceProxy* proxy = de.fCoordTransform.proxy();
            // If we don't have a proxy the value of the origin doesn't matter
            GrSurfaceOrigin origin = proxy ? proxy->origin() : kTopLeft_GrSurfaceOrigin;
            fGLDomain.setData(pdman, domain, proxy, origin, de.fDecalIsFiltered);
        }

    private:
        GrTextureDomain::GLDomain         fGLDomain;
    };

    return new GLSLProcessor;
}

bool GrDomainEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
    auto& td = sBase.cast<GrDomainEffect>();
    return fDomain == td.fDomain && fDecalIsFiltered == td.fDecalIsFiltered;
}

///////////////////////////////////////////////////////////////////////////////

GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDomainEffect);

#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrDomainEffect::TestCreate(GrProcessorTestData* d) {
    do {
        GrTextureDomain::Mode modeX =
                (GrTextureDomain::Mode)d->fRandom->nextULessThan(GrTextureDomain::kModeCount);
        GrTextureDomain::Mode modeY =
                (GrTextureDomain::Mode)d->fRandom->nextULessThan(GrTextureDomain::kModeCount);
        auto child = GrProcessorUnitTest::MakeChildFP(d);
        const auto* childPtr = child.get();
        SkRect domain;
        // We assert if the child's coord transform has a proxy and the domain rect is outside its
        // bounds.
        GrFragmentProcessor::CoordTransformIter ctIter(*child);
        if (!ctIter) {
            continue;
        }
        auto [transform, fp] = *ctIter;
        if (auto proxy = transform.proxy()) {
            auto [w, h] = proxy->backingStoreDimensions();
            domain.fLeft   = d->fRandom->nextRangeScalar(0, w);
            domain.fRight  = d->fRandom->nextRangeScalar(0, w);
            domain.fTop    = d->fRandom->nextRangeScalar(0, h);
            domain.fBottom = d->fRandom->nextRangeScalar(0, h);
        } else {
            domain.fLeft   = d->fRandom->nextRangeScalar(-100.f, 100.f);
            domain.fRight  = d->fRandom->nextRangeScalar(-100.f, 100.f);
            domain.fTop    = d->fRandom->nextRangeScalar(-100.f, 100.f);
            domain.fBottom = d->fRandom->nextRangeScalar(-100.f, 100.f);
        }
        domain.sort();
        bool filterIfDecal = d->fRandom->nextBool();
        auto result = GrDomainEffect::Make(std::move(child), domain, modeX, modeY, filterIfDecal);
        if (result && result.get() != childPtr) {
            return result;
        }
    } while (true);
}
#endif

///////////////////////////////////////////////////////////////////////////////
std::unique_ptr<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::Make(
        sk_sp<GrSurfaceProxy> proxy, const SkIRect& subset, const SkIPoint& deviceSpaceOffset) {
    return std::unique_ptr<GrFragmentProcessor>(new GrDeviceSpaceTextureDecalFragmentProcessor(
            std::move(proxy), subset, deviceSpaceOffset));
}

GrDeviceSpaceTextureDecalFragmentProcessor::GrDeviceSpaceTextureDecalFragmentProcessor(
        sk_sp<GrSurfaceProxy> proxy, const SkIRect& subset, const SkIPoint& deviceSpaceOffset)
        : INHERITED(kGrDeviceSpaceTextureDecalFragmentProcessor_ClassID,
                    kCompatibleWithCoverageAsAlpha_OptimizationFlag)
        , fTextureSampler(proxy, GrSamplerState::ClampNearest())
        , fTextureDomain(proxy.get(),
                         GrTextureDomain::MakeTexelDomain(subset, GrTextureDomain::kDecal_Mode),
                         GrTextureDomain::kDecal_Mode, GrTextureDomain::kDecal_Mode) {
    this->setTextureSamplerCnt(1);
    fDeviceSpaceOffset.fX = deviceSpaceOffset.fX - subset.fLeft;
    fDeviceSpaceOffset.fY = deviceSpaceOffset.fY - subset.fTop;
}

GrDeviceSpaceTextureDecalFragmentProcessor::GrDeviceSpaceTextureDecalFragmentProcessor(
        const GrDeviceSpaceTextureDecalFragmentProcessor& that)
        : INHERITED(kGrDeviceSpaceTextureDecalFragmentProcessor_ClassID,
                    kCompatibleWithCoverageAsAlpha_OptimizationFlag)
        , fTextureSampler(that.fTextureSampler)
        , fTextureDomain(that.fTextureDomain)
        , fDeviceSpaceOffset(that.fDeviceSpaceOffset) {
    this->setTextureSamplerCnt(1);
}

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

GrGLSLFragmentProcessor* GrDeviceSpaceTextureDecalFragmentProcessor::onCreateGLSLInstance() const  {
    class GLSLProcessor : public GrGLSLFragmentProcessor {
    public:
        void emitCode(EmitArgs& args) override {
            const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
                    args.fFp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
            const char* scaleAndTranslateName;
            fScaleAndTranslateUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
                                                                     kHalf4_GrSLType,
                                                                     "scaleAndTranslate",
                                                                     &scaleAndTranslateName);
            args.fFragBuilder->codeAppendf("half2 coords = half2(sk_FragCoord.xy * %s.xy + %s.zw);",
                                           scaleAndTranslateName, scaleAndTranslateName);
            fGLDomain.sampleTexture(args.fFragBuilder,
                                    args.fUniformHandler,
                                    args.fShaderCaps,
                                    dstdfp.fTextureDomain,
                                    args.fOutputColor,
                                    SkString("coords"),
                                    args.fTexSamplers[0],
                                    args.fInputColor);
        }

    protected:
        void onSetData(const GrGLSLProgramDataManager& pdman,
                       const GrFragmentProcessor& fp) override {
            const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
                    fp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
            const auto& view = dstdfp.textureSampler(0).view();
            SkISize textureDims = view.proxy()->backingStoreDimensions();

            fGLDomain.setData(pdman, dstdfp.fTextureDomain, view,
                              dstdfp.textureSampler(0).samplerState());
            float iw = 1.f / textureDims.width();
            float ih = 1.f / textureDims.height();
            float scaleAndTransData[4] = {
                iw, ih,
                -dstdfp.fDeviceSpaceOffset.fX * iw, -dstdfp.fDeviceSpaceOffset.fY * ih
            };
            if (view.origin() == kBottomLeft_GrSurfaceOrigin) {
                scaleAndTransData[1] = -scaleAndTransData[1];
                scaleAndTransData[3] = 1 - scaleAndTransData[3];
            }
            pdman.set4fv(fScaleAndTranslateUni, 1, scaleAndTransData);
        }

    private:
        GrTextureDomain::GLDomain   fGLDomain;
        UniformHandle               fScaleAndTranslateUni;
    };

    return new GLSLProcessor;
}

bool GrDeviceSpaceTextureDecalFragmentProcessor::onIsEqual(const GrFragmentProcessor& fp) const {
    const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
            fp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
    return dstdfp.fTextureSampler.view().proxy()->underlyingUniqueID() ==
                   fTextureSampler.view().proxy()->underlyingUniqueID() &&
           dstdfp.fDeviceSpaceOffset == fDeviceSpaceOffset &&
           dstdfp.fTextureDomain == fTextureDomain;
}

///////////////////////////////////////////////////////////////////////////////

GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDeviceSpaceTextureDecalFragmentProcessor);

#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::TestCreate(
        GrProcessorTestData* d) {
    int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
                                        : GrProcessorUnitTest::kAlphaTextureIdx;
    sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
    SkIRect subset;
    subset.fLeft = d->fRandom->nextULessThan(proxy->width() - 1);
    subset.fRight = d->fRandom->nextRangeU(subset.fLeft, proxy->width());
    subset.fTop = d->fRandom->nextULessThan(proxy->height() - 1);
    subset.fBottom = d->fRandom->nextRangeU(subset.fTop, proxy->height());
    SkIPoint pt;
    pt.fX = d->fRandom->nextULessThan(2048);
    pt.fY = d->fRandom->nextULessThan(2048);
    return GrDeviceSpaceTextureDecalFragmentProcessor::Make(std::move(proxy), subset, pt);
}
#endif
