Remove option to make GrCoordTransforms apply to device positions.

Adds a device space texture decal effect to use for clipping.

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2870

Change-Id: Ifcc7617ea87f5a86e301995cba9dfc30a4b0e2c5
Reviewed-on: https://skia-review.googlesource.com/2870
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/effects/GrTextureDomain.cpp b/src/gpu/effects/GrTextureDomain.cpp
index e809109..55d69bf 100644
--- a/src/gpu/effects/GrTextureDomain.cpp
+++ b/src/gpu/effects/GrTextureDomain.cpp
@@ -169,53 +169,6 @@
     }
 }
 
-
-//////////////////////////////////////////////////////////////////////////////
-
-class GrGLTextureDomainEffect : public GrGLSLFragmentProcessor {
-public:
-    void emitCode(EmitArgs&) override;
-
-    static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*);
-
-protected:
-    void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
-
-private:
-    GrTextureDomain::GLDomain         fGLDomain;
-    typedef GrGLSLFragmentProcessor INHERITED;
-};
-
-void GrGLTextureDomainEffect::emitCode(EmitArgs& args) {
-    const GrTextureDomainEffect& textureDomainEffect = args.fFp.cast<GrTextureDomainEffect>();
-    const GrTextureDomain& domain = textureDomainEffect.textureDomain();
-
-    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
-    SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
-    fGLDomain.sampleTexture(fragBuilder,
-                            args.fUniformHandler,
-                            args.fGLSLCaps,
-                            domain,
-                            args.fOutputColor,
-                            coords2D,
-                            args.fTexSamplers[0],
-                            args.fInputColor);
-}
-
-void GrGLTextureDomainEffect::onSetData(const GrGLSLProgramDataManager& pdman,
-                                        const GrProcessor& processor) {
-    const GrTextureDomainEffect& textureDomainEffect = processor.cast<GrTextureDomainEffect>();
-    const GrTextureDomain& domain = textureDomainEffect.textureDomain();
-    fGLDomain.setData(pdman, domain, processor.texture(0)->origin());
-}
-
-void GrGLTextureDomainEffect::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
-                                     GrProcessorKeyBuilder* b) {
-    const GrTextureDomain& domain = processor.cast<GrTextureDomainEffect>().textureDomain();
-    b->add32(GrTextureDomain::GLDomain::DomainKey(domain));
-}
-
-
 ///////////////////////////////////////////////////////////////////////////////
 
 sk_sp<GrFragmentProcessor> GrTextureDomainEffect::Make(GrTexture* texture,
@@ -223,8 +176,7 @@
                                                        const SkMatrix& matrix,
                                                        const SkRect& domain,
                                                        GrTextureDomain::Mode mode,
-                                                       GrTextureParams::FilterMode filterMode,
-                                                       GrCoordSet coordSet) {
+                                                       GrTextureParams::FilterMode filterMode) {
     static const SkRect kFullRect = {0, 0, SK_Scalar1, SK_Scalar1};
     if (GrTextureDomain::kIgnore_Mode == mode ||
         (GrTextureDomain::kClamp_Mode == mode && domain.contains(kFullRect))) {
@@ -232,7 +184,7 @@
     } else {
         return sk_sp<GrFragmentProcessor>(
             new GrTextureDomainEffect(texture, std::move(colorSpaceXform), matrix, domain, mode,
-                                      filterMode, coordSet));
+                                      filterMode));
     }
 }
 
@@ -241,33 +193,62 @@
                                              const SkMatrix& matrix,
                                              const SkRect& domain,
                                              GrTextureDomain::Mode mode,
-                                             GrTextureParams::FilterMode filterMode,
-                                             GrCoordSet coordSet)
-    : GrSingleTextureEffect(texture, std::move(colorSpaceXform), matrix, filterMode, coordSet)
+                                             GrTextureParams::FilterMode filterMode)
+    : GrSingleTextureEffect(texture, std::move(colorSpaceXform), matrix, filterMode)
     , fTextureDomain(domain, mode) {
     SkASSERT(mode != GrTextureDomain::kRepeat_Mode ||
             filterMode == GrTextureParams::kNone_FilterMode);
     this->initClassID<GrTextureDomainEffect>();
 }
 
-GrTextureDomainEffect::~GrTextureDomainEffect() {}
-
 void GrTextureDomainEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
                                                   GrProcessorKeyBuilder* b) const {
-    GrGLTextureDomainEffect::GenKey(*this, caps, b);
+    b->add32(GrTextureDomain::GLDomain::DomainKey(fTextureDomain));
 }
 
 GrGLSLFragmentProcessor* GrTextureDomainEffect::onCreateGLSLInstance() const  {
-    return new GrGLTextureDomainEffect;
+    class GLSLProcessor : public GrGLSLFragmentProcessor {
+    public:
+        void emitCode(EmitArgs& args) override {
+            const GrTextureDomainEffect& tde = args.fFp.cast<GrTextureDomainEffect>();
+            const GrTextureDomain& domain = tde.fTextureDomain;
+
+            GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
+            SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
+            fGLDomain.sampleTexture(fragBuilder,
+                                    args.fUniformHandler,
+                                    args.fGLSLCaps,
+                                    domain,
+                                    args.fOutputColor,
+                                    coords2D,
+                                    args.fTexSamplers[0],
+                                    args.fInputColor);
+        }
+
+    protected:
+        void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& fp) override {
+            const GrTextureDomainEffect& tde = fp.cast<GrTextureDomainEffect>();
+            const GrTextureDomain& domain = tde.fTextureDomain;
+            fGLDomain.setData(pdman, domain, tde.texture(0)->origin());
+        }
+
+    private:
+        GrTextureDomain::GLDomain         fGLDomain;
+
+    };
+
+    return new GLSLProcessor;
 }
 
 bool GrTextureDomainEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
     const GrTextureDomainEffect& s = sBase.cast<GrTextureDomainEffect>();
-    return this->fTextureDomain == s.fTextureDomain;
+    return this->fTextureDomain == s.fTextureDomain && s.texture(0) == this->texture(0) &&
+           s.textureAccess(0).getParams().filterMode() ==
+                this->textureAccess(0).getParams().filterMode();
 }
 
 void GrTextureDomainEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
-    if (GrTextureDomain::kDecal_Mode == fTextureDomain.mode()) { // TODO: helper
+    if (GrTextureDomain::kDecal_Mode == fTextureDomain.mode()) {
         if (GrPixelConfigIsAlphaOnly(this->texture(0)->config())) {
             inout->mulByUnknownSingleComponent();
         } else {
@@ -294,7 +275,6 @@
         (GrTextureDomain::Mode) d->fRandom->nextULessThan(GrTextureDomain::kModeCount);
     const SkMatrix& matrix = GrTest::TestMatrix(d->fRandom);
     bool bilerp = mode != GrTextureDomain::kRepeat_Mode ? d->fRandom->nextBool() : false;
-    GrCoordSet coords = d->fRandom->nextBool() ? kLocal_GrCoordSet : kDevice_GrCoordSet;
     auto colorSpaceXform = GrTest::TestColorXform(d->fRandom);
     return GrTextureDomainEffect::Make(
         d->fTextures[texIdx],
@@ -302,6 +282,112 @@
         matrix,
         domain,
         mode,
-        bilerp ? GrTextureParams::kBilerp_FilterMode : GrTextureParams::kNone_FilterMode,
-        coords);
+        bilerp ? GrTextureParams::kBilerp_FilterMode : GrTextureParams::kNone_FilterMode);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+sk_sp<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::Make(GrTexture* texture,
+        const SkIRect& subset, const SkIPoint& deviceSpaceOffset) {
+    return sk_sp<GrFragmentProcessor>(new GrDeviceSpaceTextureDecalFragmentProcessor(
+            texture, subset, deviceSpaceOffset));
+}
+
+GrDeviceSpaceTextureDecalFragmentProcessor::GrDeviceSpaceTextureDecalFragmentProcessor(
+        GrTexture* texture, const SkIRect& subset, const SkIPoint& deviceSpaceOffset)
+        : fTextureAccess(texture, GrTextureParams::ClampNoFilter())
+        , fTextureDomain(GrTextureDomain::MakeTexelDomain(texture, subset),
+                         GrTextureDomain::kDecal_Mode) {
+    this->addTextureAccess(&fTextureAccess);
+    fDeviceSpaceOffset.fX = deviceSpaceOffset.fX - subset.fLeft;
+    fDeviceSpaceOffset.fY = deviceSpaceOffset.fY - subset.fTop;
+    this->initClassID<GrDeviceSpaceTextureDecalFragmentProcessor>();
+    this->setWillReadFragmentPosition();
+}
+
+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,
+                                                                     kVec4f_GrSLType,
+                                                                     kDefault_GrSLPrecision,
+                                                                     "scaleAndTranslate",
+                                                                     &scaleAndTranslateName);
+            args.fFragBuilder->codeAppendf("vec2 coords = %s.xy * %s.xy + %s.zw;",
+                                           args.fFragBuilder->fragmentPosition(),
+                                           scaleAndTranslateName, scaleAndTranslateName);
+            fGLDomain.sampleTexture(args.fFragBuilder,
+                                    args.fUniformHandler,
+                                    args.fGLSLCaps,
+                                    dstdfp.fTextureDomain,
+                                    args.fOutputColor,
+                                    SkString("coords"),
+                                    args.fTexSamplers[0],
+                                    args.fInputColor);
+        }
+
+    protected:
+        void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& fp) override {
+            const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
+                    fp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
+            fGLDomain.setData(pdman, dstdfp.fTextureDomain, dstdfp.texture(0)->origin());
+            float iw = 1.f / dstdfp.texture(0)->width();
+            float ih = 1.f / dstdfp.texture(0)->height();
+            float scaleAndTransData[4] = {
+                iw, ih,
+                -dstdfp.fDeviceSpaceOffset.fX * iw, -dstdfp.fDeviceSpaceOffset.fY * ih
+            };
+            if (dstdfp.texture(0)->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.fTextureAccess.getTexture() == fTextureAccess.getTexture() &&
+           dstdfp.fDeviceSpaceOffset == fDeviceSpaceOffset &&
+           dstdfp.fTextureDomain == fTextureDomain;
+}
+
+void GrDeviceSpaceTextureDecalFragmentProcessor::onComputeInvariantOutput(
+        GrInvariantOutput* inout) const {
+    if (GrPixelConfigIsAlphaOnly(this->texture(0)->config())) {
+        inout->mulByUnknownSingleComponent();
+    } else {
+        inout->mulByUnknownFourComponents();
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDeviceSpaceTextureDecalFragmentProcessor);
+
+sk_sp<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::TestCreate(
+        GrProcessorTestData* d) {
+    int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
+                                        : GrProcessorUnitTest::kAlphaTextureIdx;
+    SkIRect subset;
+    subset.fLeft = d->fRandom->nextULessThan(d->fTextures[texIdx]->width() - 1);
+    subset.fRight = d->fRandom->nextRangeU(subset.fLeft, d->fTextures[texIdx]->width());
+    subset.fTop = d->fRandom->nextULessThan(d->fTextures[texIdx]->height() - 1);
+    subset.fBottom = d->fRandom->nextRangeU(subset.fTop, d->fTextures[texIdx]->height());
+    SkIPoint pt;
+    pt.fX = d->fRandom->nextULessThan(2048);
+    pt.fY = d->fRandom->nextULessThan(2048);
+    return GrDeviceSpaceTextureDecalFragmentProcessor::Make(d->fTextures[texIdx], subset, pt);
 }