Merge latest Skia into master (3 commits)

https://skia.googlesource.com/skia.git/+log/3f142b6..652ecb5

Test: Presubmit checks will test this change.
Change-Id: I5e9d7e0dd26d3a91a6c08a1c19f2a03b9ff2699d
diff --git a/gm/texdata.cpp b/gm/texdata.cpp
index 8520d28..372ff5d 100644
--- a/gm/texdata.cpp
+++ b/gm/texdata.cpp
@@ -97,10 +97,7 @@
         } else {
             vm.reset();
         }
-        SkMatrix tm;
-        tm = vm;
-        tm.postIDiv(2*S, 2*S);
-        paint.addColorTextureProcessor(texture, nullptr, tm);
+        paint.addColorTextureProcessor(texture, nullptr, vm);
 
         renderTargetContext->drawRect(clip, GrPaint(paint), GrAA::kNo, vm,
                                       SkRect::MakeWH(2 * S, 2 * S));
diff --git a/gm/texturedomaineffect.cpp b/gm/texturedomaineffect.cpp
index 32042aa..cc3e1c9 100644
--- a/gm/texturedomaineffect.cpp
+++ b/gm/texturedomaineffect.cpp
@@ -89,11 +89,10 @@
         }
 
         SkTArray<SkMatrix> textureMatrices;
-        textureMatrices.push_back().setIDiv(texture->width(), texture->height());
-        textureMatrices.push_back() = textureMatrices[0];
-        textureMatrices.back().postScale(1.5f, 0.85f);
-        textureMatrices.push_back() = textureMatrices[0];
-        textureMatrices.back().preRotate(45.f, texture->width() / 2.f, texture->height() / 2.f);
+        textureMatrices.push_back() = SkMatrix::I();
+        textureMatrices.push_back() = SkMatrix::MakeScale(1.5f, 0.85f);
+        textureMatrices.push_back();
+        textureMatrices.back().setRotate(45.f, texture->width() / 2.f, texture->height() / 2.f);
 
         const SkIRect texelDomains[] = {
             fBmp.bounds(),
diff --git a/include/gpu/GrCoordTransform.h b/include/gpu/GrCoordTransform.h
index 1f1cac7..5c16c89 100644
--- a/include/gpu/GrCoordTransform.h
+++ b/include/gpu/GrCoordTransform.h
@@ -20,7 +20,11 @@
  */
 class GrCoordTransform : SkNoncopyable {
 public:
-    GrCoordTransform() { SkDEBUGCODE(fInProcessor = false); }
+    GrCoordTransform()
+        : fTexture(nullptr)
+        , fNormalize(false) {
+        SkDEBUGCODE(fInProcessor = false);
+    }
 
     /**
      * Create a transformation that maps [0, 1] to a texture's boundaries. The precision is inferred
@@ -30,7 +34,7 @@
     GrCoordTransform(const GrTexture* texture, GrSamplerParams::FilterMode filter) {
         SkASSERT(texture);
         SkDEBUGCODE(fInProcessor = false);
-        this->reset(texture, filter);
+        this->reset(SkMatrix::I(), texture, filter);
     }
 
     /**
@@ -52,18 +56,23 @@
         this->reset(m, precision);
     }
 
-    void reset(const GrTexture* texture, GrSamplerParams::FilterMode filter) {
-        SkASSERT(!fInProcessor);
-        SkASSERT(texture);
-        this->reset(MakeDivByTextureWHMatrix(texture), texture, filter);
-    }
+    void reset(const SkMatrix&, const GrTexture*, GrSamplerParams::FilterMode filter,
+               bool normalize = true);
 
-    void reset(const SkMatrix&, const GrTexture*, GrSamplerParams::FilterMode filter);
-    void reset(const SkMatrix& m, GrSLPrecision precision = kDefault_GrSLPrecision);
+    void reset(const SkMatrix& m, GrSLPrecision precision = kDefault_GrSLPrecision) {
+        SkASSERT(!fInProcessor);
+        fMatrix = m;
+        fTexture = nullptr;
+        fNormalize = false;
+        fReverseY = false;
+        fPrecision = precision;
+    }
 
     GrCoordTransform& operator= (const GrCoordTransform& that) {
         SkASSERT(!fInProcessor);
         fMatrix = that.fMatrix;
+        fTexture = that.fTexture;
+        fNormalize = that.fNormalize;
         fReverseY = that.fReverseY;
         fPrecision = that.fPrecision;
         return *this;
@@ -78,29 +87,38 @@
         return &fMatrix;
     }
 
-    bool operator==(const GrCoordTransform& that) const {
-        return fMatrix.cheapEqualTo(that.fMatrix) &&
-               fReverseY == that.fReverseY &&
-               fPrecision == that.fPrecision;
+    bool hasSameEffectAs(const GrCoordTransform& that) const {
+        if (fNormalize != that.fNormalize ||
+            fReverseY != that.fReverseY ||
+            fPrecision != that.fPrecision ||
+            !fMatrix.cheapEqualTo(that.fMatrix)) {
+            return false;
+        }
+
+        if (fNormalize) {
+            SkASSERT(fTexture && that.fTexture);
+            return fTexture->width() == that.fTexture->width() &&
+                   fTexture->height() == that.fTexture->height();
+        }
+
+        return true;
     }
 
-    bool operator!=(const GrCoordTransform& that) const { return !(*this == that); }
-
     const SkMatrix& getMatrix() const { return fMatrix; }
+    const GrTexture* texture() const { return fTexture; }
+    bool normalize() const { return fNormalize; }
     bool reverseY() const { return fReverseY; }
     GrSLPrecision precision() const { return fPrecision; }
 
-    /** Useful for effects that want to insert a texture matrix that is implied by the texture
-        dimensions */
-    static inline SkMatrix MakeDivByTextureWHMatrix(const GrTexture* texture) {
-        SkASSERT(texture);
-        SkMatrix mat;
-        (void)mat.setIDiv(texture->width(), texture->height());
-        return mat;
-    }
-
 private:
+    // The textures' effect is to optionally normalize the final matrix, so a blind
+    // equality check could be misleading
+    bool operator==(const GrCoordTransform& that) const;
+    bool operator!=(const GrCoordTransform& that) const;
+
     SkMatrix                fMatrix;
+    const GrTexture*        fTexture;
+    bool                    fNormalize;
     bool                    fReverseY;
     GrSLPrecision           fPrecision;
     typedef SkNoncopyable INHERITED;
diff --git a/src/core/SkGpuBlurUtils.cpp b/src/core/SkGpuBlurUtils.cpp
index b3b523a..6ac5abe 100644
--- a/src/core/SkGpuBlurUtils.cpp
+++ b/src/core/SkGpuBlurUtils.cpp
@@ -262,10 +262,6 @@
     for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
         GrPaint paint;
         paint.setGammaCorrect(dstRenderTargetContext->isGammaCorrect());
-        // TODO: this matrix relies on the final instantiated size of the texture. This
-        // will have to be deferred for TextureProxys
-        SkMatrix matrix;
-        matrix.setIDiv(srcTexture->width(), srcTexture->height());
         SkIRect dstRect(srcRect);
         if (srcBounds && i == 1) {
             SkRect domain = SkRect::Make(*srcBounds);
@@ -274,7 +270,7 @@
             sk_sp<GrFragmentProcessor> fp(GrTextureDomainEffect::Make(
                                                         srcTexture.get(),
                                                         nullptr,
-                                                        matrix,
+                                                        SkMatrix::I(),
                                                         domain,
                                                         GrTextureDomain::kDecal_Mode,
                                                         GrSamplerParams::kBilerp_FilterMode));
@@ -283,7 +279,7 @@
             srcOffset.set(0, 0);
         } else {
             GrSamplerParams params(SkShader::kClamp_TileMode, GrSamplerParams::kBilerp_FilterMode);
-            paint.addColorTextureProcessor(srcTexture.get(), nullptr, matrix, params);
+            paint.addColorTextureProcessor(srcTexture.get(), nullptr, SkMatrix::I(), params);
         }
         paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
         shrink_irect_by_2(&dstRect, i < scaleFactorX, i < scaleFactorY);
@@ -369,12 +365,7 @@
             return nullptr;
         }
 
-        // TODO: this matrix relies on the final instantiated size of the texture. This
-        // will have to be deferred for TextureProxys
-        SkMatrix matrix;
-        matrix.setIDiv(tex->width(), tex->height());
-
-        paint.addColorTextureProcessor(tex.get(), nullptr, matrix, params);
+        paint.addColorTextureProcessor(tex.get(), nullptr, SkMatrix::I(), params);
         paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
 
         SkIRect dstRect(srcRect);
diff --git a/src/core/SkMatrix.cpp b/src/core/SkMatrix.cpp
index a05ae0a..390ebe0 100644
--- a/src/core/SkMatrix.cpp
+++ b/src/core/SkMatrix.cpp
@@ -1038,7 +1038,7 @@
 
 const SkMatrix::MapPtsProc SkMatrix::gMapPtsProcs[] = {
     SkMatrix::Identity_pts, SkMatrix::Trans_pts,
-    SkMatrix::Scale_pts,   SkMatrix::Scale_pts,
+    SkMatrix::Scale_pts,    SkMatrix::Scale_pts,
     SkMatrix::Affine_vpts,  SkMatrix::Affine_vpts,
     SkMatrix::Affine_vpts,  SkMatrix::Affine_vpts,
     // repeat the persp proc 8 times
diff --git a/src/effects/GrAlphaThresholdFragmentProcessor.cpp b/src/effects/GrAlphaThresholdFragmentProcessor.cpp
index afafe08..a259607 100644
--- a/src/effects/GrAlphaThresholdFragmentProcessor.cpp
+++ b/src/effects/GrAlphaThresholdFragmentProcessor.cpp
@@ -32,12 +32,6 @@
                                                                 bounds));
 }
 
-static SkMatrix make_div_and_translate_matrix(GrTexture* texture, int x, int y) {
-    SkMatrix matrix = GrCoordTransform::MakeDivByTextureWHMatrix(texture);
-    matrix.preTranslate(SkIntToScalar(x), SkIntToScalar(y));
-    return matrix;
-}
-
 GrAlphaThresholdFragmentProcessor::GrAlphaThresholdFragmentProcessor(
                                                            GrTexture* texture,
                                                            sk_sp<GrColorSpaceXform> colorSpaceXform,
@@ -47,11 +41,11 @@
                                                            const SkIRect& bounds)
     : fInnerThreshold(innerThreshold)
     , fOuterThreshold(outerThreshold)
-    , fImageCoordTransform(GrCoordTransform::MakeDivByTextureWHMatrix(texture), texture,
-                           GrSamplerParams::kNone_FilterMode)
+    , fImageCoordTransform(SkMatrix::I(), texture, GrSamplerParams::kNone_FilterMode)
     , fImageTextureSampler(texture)
     , fColorSpaceXform(std::move(colorSpaceXform))
-    , fMaskCoordTransform(make_div_and_translate_matrix(maskTexture, -bounds.x(), -bounds.y()),
+    , fMaskCoordTransform(SkMatrix::MakeTrans(SkIntToScalar(-bounds.x()),
+                                              SkIntToScalar(-bounds.y())),
                           maskTexture,
                           GrSamplerParams::kNone_FilterMode)
     , fMaskTextureSampler(maskTexture) {
diff --git a/src/effects/SkArithmeticImageFilter.cpp b/src/effects/SkArithmeticImageFilter.cpp
index 3e4d48f..d33a9dc 100644
--- a/src/effects/SkArithmeticImageFilter.cpp
+++ b/src/effects/SkArithmeticImageFilter.cpp
@@ -348,10 +348,8 @@
     sk_sp<GrFragmentProcessor> bgFP;
 
     if (backgroundTex) {
-        SkMatrix backgroundMatrix;
-        backgroundMatrix.setIDiv(backgroundTex->width(), backgroundTex->height());
-        backgroundMatrix.preTranslate(-SkIntToScalar(backgroundOffset.fX),
-                                      -SkIntToScalar(backgroundOffset.fY));
+        SkMatrix backgroundMatrix = SkMatrix::MakeTrans(-SkIntToScalar(backgroundOffset.fX),
+                                                        -SkIntToScalar(backgroundOffset.fY));
         sk_sp<GrColorSpaceXform> bgXform =
                 GrColorSpaceXform::Make(background->getColorSpace(), outputProperties.colorSpace());
         bgFP = GrTextureDomainEffect::Make(
@@ -364,10 +362,8 @@
     }
 
     if (foregroundTex) {
-        SkMatrix foregroundMatrix;
-        foregroundMatrix.setIDiv(foregroundTex->width(), foregroundTex->height());
-        foregroundMatrix.preTranslate(-SkIntToScalar(foregroundOffset.fX),
-                                      -SkIntToScalar(foregroundOffset.fY));
+        SkMatrix foregroundMatrix = SkMatrix::MakeTrans(-SkIntToScalar(foregroundOffset.fX),
+                                                        -SkIntToScalar(foregroundOffset.fY));
         sk_sp<GrColorSpaceXform> fgXform =
                 GrColorSpaceXform::Make(foreground->getColorSpace(), outputProperties.colorSpace());
         sk_sp<GrFragmentProcessor> foregroundFP;
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp
index fa4cb33..70afd91 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -1520,10 +1520,9 @@
 
     if (!isNormalBlur) {
         GrPaint paint;
-        SkMatrix matrix;
-        matrix.setIDiv(src->width(), src->height());
         // Blend pathTexture over blurTexture.
-        paint.addCoverageFragmentProcessor(GrSimpleTextureEffect::Make(src, nullptr, matrix));
+        paint.addCoverageFragmentProcessor(
+                                        GrSimpleTextureEffect::Make(src, nullptr, SkMatrix::I()));
         if (kInner_SkBlurStyle == fBlurStyle) {
             // inner:  dst = dst * src
             paint.setCoverageSetOpXPFactory(SkRegion::kIntersect_Op);
diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp
index 28483bd..0d39403 100644
--- a/src/effects/SkDisplacementMapEffect.cpp
+++ b/src/effects/SkDisplacementMapEffect.cpp
@@ -336,9 +336,8 @@
             return nullptr;
         }
 
-        SkMatrix offsetMatrix = GrCoordTransform::MakeDivByTextureWHMatrix(displTexture.get());
-        offsetMatrix.preTranslate(SkIntToScalar(colorOffset.fX - displOffset.fX),
-                                  SkIntToScalar(colorOffset.fY - displOffset.fY));
+        SkMatrix offsetMatrix = SkMatrix::MakeTrans(SkIntToScalar(colorOffset.fX - displOffset.fX),
+                                                    SkIntToScalar(colorOffset.fY - displOffset.fY));
         SkColorSpace* colorSpace = ctx.outputProperties().colorSpace();
         sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(color->getColorSpace(),
                                                                            colorSpace);
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index 1d710bf..67ded34 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -1707,7 +1707,7 @@
                                    const SkMatrix& matrix,
                                    BoundaryMode boundaryMode,
                                    const SkIRect* srcBounds)
-    : INHERITED(texture, nullptr, GrCoordTransform::MakeDivByTextureWHMatrix(texture))
+    : INHERITED(texture, nullptr, SkMatrix::I())
     , fLight(light)
     , fSurfaceScale(surfaceScale)
     , fFilterMatrix(matrix)
diff --git a/src/effects/SkMagnifierImageFilter.cpp b/src/effects/SkMagnifierImageFilter.cpp
index 2b04532..c8b32ae 100644
--- a/src/effects/SkMagnifierImageFilter.cpp
+++ b/src/effects/SkMagnifierImageFilter.cpp
@@ -71,8 +71,7 @@
                       float yInvZoom,
                       float xInvInset,
                       float yInvInset)
-        : INHERITED(texture, std::move(colorSpaceXform),
-                    GrCoordTransform::MakeDivByTextureWHMatrix(texture))
+        : INHERITED(texture, std::move(colorSpaceXform), SkMatrix::I())
         , fBounds(bounds)
         , fXOffset(xOffset)
         , fYOffset(yOffset)
diff --git a/src/effects/SkPerlinNoiseShader.cpp b/src/effects/SkPerlinNoiseShader.cpp
index dc3d9a6..f5a8b87 100644
--- a/src/effects/SkPerlinNoiseShader.cpp
+++ b/src/effects/SkPerlinNoiseShader.cpp
@@ -515,7 +515,6 @@
     bool stitchTiles() const { return fStitchTiles; }
     const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
     int numOctaves() const { return fNumOctaves; }
-    const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
 
 private:
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
@@ -546,6 +545,7 @@
                         GrTexture* permutationsTexture, GrTexture* noiseTexture,
                         const SkMatrix& matrix)
       : fType(type)
+      , fCoordTransform(matrix)
       , fNumOctaves(numOctaves)
       , fStitchTiles(stitchTiles)
       , fPermutationsSampler(permutationsTexture)
@@ -554,7 +554,6 @@
         this->initClassID<GrPerlinNoiseEffect>();
         this->addTextureSampler(&fPermutationsSampler);
         this->addTextureSampler(&fNoiseSampler);
-        fCoordTransform.reset(matrix);
         this->addCoordTransform(&fCoordTransform);
     }
 
diff --git a/src/effects/SkXfermodeImageFilter.cpp b/src/effects/SkXfermodeImageFilter.cpp
index 7f91df3..c52eeba 100644
--- a/src/effects/SkXfermodeImageFilter.cpp
+++ b/src/effects/SkXfermodeImageFilter.cpp
@@ -249,10 +249,8 @@
     sk_sp<GrFragmentProcessor> bgFP;
 
     if (backgroundTex) {
-        SkMatrix backgroundMatrix;
-        backgroundMatrix.setIDiv(backgroundTex->width(), backgroundTex->height());
-        backgroundMatrix.preTranslate(-SkIntToScalar(backgroundOffset.fX),
-                                      -SkIntToScalar(backgroundOffset.fY));
+        SkMatrix backgroundMatrix = SkMatrix::MakeTrans(-SkIntToScalar(backgroundOffset.fX),
+                                                        -SkIntToScalar(backgroundOffset.fY));
         sk_sp<GrColorSpaceXform> bgXform = GrColorSpaceXform::Make(background->getColorSpace(),
                                                                    outputProperties.colorSpace());
         bgFP = GrTextureDomainEffect::Make(
@@ -266,10 +264,8 @@
     }
 
     if (foregroundTex) {
-        SkMatrix foregroundMatrix;
-        foregroundMatrix.setIDiv(foregroundTex->width(), foregroundTex->height());
-        foregroundMatrix.preTranslate(-SkIntToScalar(foregroundOffset.fX),
-                                      -SkIntToScalar(foregroundOffset.fY));
+        SkMatrix foregroundMatrix = SkMatrix::MakeTrans(-SkIntToScalar(foregroundOffset.fX),
+                                                        -SkIntToScalar(foregroundOffset.fY));
         sk_sp<GrColorSpaceXform> fgXform = GrColorSpaceXform::Make(foreground->getColorSpace(),
                                                                    outputProperties.colorSpace());
         sk_sp<GrFragmentProcessor> foregroundFP;
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp
index ca64cb7..1d2c01e 100644
--- a/src/effects/gradients/SkGradientShader.cpp
+++ b/src/effects/gradients/SkGradientShader.cpp
@@ -1659,14 +1659,17 @@
             fRow = fAtlas->lockRow(bitmap);
             if (-1 != fRow) {
                 fYCoord = fAtlas->getYOffset(fRow)+SK_ScalarHalf*fAtlas->getNormalizedTexelHeight();
-                fCoordTransform.reset(*args.fMatrix, fAtlas->getTexture(), params.filterMode());
+                // This is 1/2 places where auto-normalization is disabled
+                fCoordTransform.reset(*args.fMatrix, fAtlas->getTexture(),
+                                      params.filterMode(), false);
                 fTextureSampler.reset(fAtlas->getTexture(), params);
             } else {
                 sk_sp<GrTexture> texture(GrRefCachedBitmapTexture(args.fContext, bitmap, params));
                 if (!texture) {
                     return;
                 }
-                fCoordTransform.reset(*args.fMatrix, texture.get(), params.filterMode());
+                // This is 2/2 places where auto-normalization is disabled
+                fCoordTransform.reset(*args.fMatrix, texture.get(), params.filterMode(), false);
                 fTextureSampler.reset(texture.get(), params);
                 fYCoord = SK_ScalarHalf;
             }
diff --git a/src/gpu/GrBlurUtils.cpp b/src/gpu/GrBlurUtils.cpp
index 23a3c6c..61290b0 100644
--- a/src/gpu/GrBlurUtils.cpp
+++ b/src/gpu/GrBlurUtils.cpp
@@ -46,10 +46,8 @@
         return false;
     }
 
-    SkMatrix matrix;
-    matrix.setTranslate(-SkIntToScalar(maskRect.fLeft), -SkIntToScalar(maskRect.fTop));
-    // TODO: this divide relies on the instantiated texture's size!
-    matrix.postIDiv(maskTex->width(), maskTex->height());
+    SkMatrix matrix = SkMatrix::MakeTrans(-SkIntToScalar(maskRect.fLeft),
+                                          -SkIntToScalar(maskRect.fTop));
     matrix.preConcat(viewMatrix);
     paint.addCoverageFragmentProcessor(GrSimpleTextureEffect::Make(maskTex, nullptr, matrix));
 
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 1256058..1e2bdc7 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -308,10 +308,8 @@
     SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
     if (tempTexture) {
         sk_sp<GrFragmentProcessor> fp;
-        SkMatrix textureMatrix;
-        textureMatrix.setIDiv(tempTexture->width(), tempTexture->height());
         if (applyPremulToSrc) {
-            fp = this->createUPMToPMEffect(tempTexture.get(), tempDrawInfo.fSwizzle, textureMatrix);
+            fp = this->createUPMToPMEffect(tempTexture.get(), tempDrawInfo.fSwizzle, SkMatrix::I());
             // If premultiplying was the only reason for the draw, fall back to a straight write.
             if (!fp) {
                 if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) {
@@ -325,7 +323,7 @@
             if (!fp) {
                 fp = GrConfigConversionEffect::Make(tempTexture.get(), tempDrawInfo.fSwizzle,
                                                     GrConfigConversionEffect::kNone_PMConversion,
-                                                    textureMatrix);
+                                                    SkMatrix::I());
                 if (!fp) {
                     return false;
                 }
@@ -463,9 +461,7 @@
                                                            tempDrawInfo.fTempSurfaceDesc.fSampleCnt,
                                                            tempDrawInfo.fTempSurfaceDesc.fOrigin);
         if (tempRTC) {
-            SkMatrix textureMatrix;
-            textureMatrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
-            textureMatrix.postIDiv(src->width(), src->height());
+            SkMatrix textureMatrix = SkMatrix::MakeTrans(SkIntToScalar(left), SkIntToScalar(top));
             sk_sp<GrFragmentProcessor> fp;
             if (unpremul) {
                 fp = this->createPMToUPMEffect(src->asTexture(), tempDrawInfo.fSwizzle,
diff --git a/src/gpu/GrCoordTransform.cpp b/src/gpu/GrCoordTransform.cpp
index 63d91a8..4afd0ef 100644
--- a/src/gpu/GrCoordTransform.cpp
+++ b/src/gpu/GrCoordTransform.cpp
@@ -11,11 +11,13 @@
 #include "GrGpu.h"
 
 void GrCoordTransform::reset(const SkMatrix& m, const GrTexture* texture,
-                             GrSamplerParams::FilterMode filter) {
+                             GrSamplerParams::FilterMode filter, bool normalize) {
     SkASSERT(texture);
     SkASSERT(!fInProcessor);
 
     fMatrix = m;
+    fTexture = texture;
+    fNormalize = normalize;
     fReverseY = kBottomLeft_GrSurfaceOrigin == texture->origin();
 
     // Always start at kDefault. Then if precisions differ we see if the precision needs to be
@@ -52,9 +54,3 @@
     }
 }
 
-void GrCoordTransform::reset(const SkMatrix& m, GrSLPrecision precision) {
-    SkASSERT(!fInProcessor);
-    fMatrix = m;
-    fReverseY = false;
-    fPrecision = precision;
-}
diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp
index 977974d..8a710e5 100644
--- a/src/gpu/GrFragmentProcessor.cpp
+++ b/src/gpu/GrFragmentProcessor.cpp
@@ -92,7 +92,7 @@
     }
     int count = this->numCoordTransforms();
     for (int i = 0; i < count; ++i) {
-        if (this->coordTransform(i) != that.coordTransform(i)) {
+        if (!this->coordTransform(i).hasSameEffectAs(that.coordTransform(i))) {
             return false;
         }
     }
diff --git a/src/gpu/GrPipeline.cpp b/src/gpu/GrPipeline.cpp
index ea3f0f2..96051ea 100644
--- a/src/gpu/GrPipeline.cpp
+++ b/src/gpu/GrPipeline.cpp
@@ -7,11 +7,12 @@
 
 #include "GrPipeline.h"
 
+#include "GrAppliedClip.h"
 #include "GrCaps.h"
-#include "GrRenderTargetContext.h"
 #include "GrGpu.h"
 #include "GrPipelineBuilder.h"
 #include "GrProcOptInfo.h"
+#include "GrRenderTargetContext.h"
 #include "GrRenderTargetOpList.h"
 #include "GrRenderTargetPriv.h"
 #include "GrXferProcessor.h"
@@ -30,8 +31,8 @@
     GrPipeline* pipeline = new (memory) GrPipeline;
     pipeline->fRenderTarget.reset(rt);
     SkASSERT(pipeline->fRenderTarget);
-    pipeline->fScissorState = *args.fScissor;
-    pipeline->fWindowRectsState = *args.fWindowRectsState;
+    pipeline->fScissorState = args.fAppliedClip->scissorState();
+    pipeline->fWindowRectsState = args.fAppliedClip->windowRectsState();
     pipeline->fUserStencilSettings = userStencil;
     pipeline->fDrawFace = builder.getDrawFace();
 
@@ -51,10 +52,10 @@
     if (builder.getUsesDistanceVectorField()) {
         pipeline->fFlags |= kUsesDistanceVectorField_Flag;
     }
-    if (args.fHasStencilClip) {
+    if (args.fAppliedClip->hasStencilClip()) {
         pipeline->fFlags |= kHasStencilClip_Flag;
     }
-    if (!userStencil->isDisabled(args.fHasStencilClip)) {
+    if (!userStencil->isDisabled(args.fAppliedClip->hasStencilClip())) {
         pipeline->fFlags |= kStencilEnabled_Flag;
     }
 
@@ -84,10 +85,9 @@
 
     const GrXferProcessor* xpForOpts = xferProcessor ? xferProcessor.get() :
                                                        &GrPorterDuffXPFactory::SimpleSrcOverXP();
-    optFlags = xpForOpts->getOptimizations(args.fAnalysis,
-                                           userStencil->doesWrite(args.fHasStencilClip),
-                                           &overrideColor,
-                                           *args.fCaps);
+    optFlags = xpForOpts->getOptimizations(
+            args.fAnalysis, userStencil->doesWrite(args.fAppliedClip->hasStencilClip()),
+            &overrideColor, *args.fCaps);
 
     // When path rendering the stencil settings are not always set on the GrPipelineBuilder
     // so we must check the draw type. In cases where we will skip drawing we simply return a
@@ -122,6 +122,9 @@
     pipeline->fNumColorProcessors = builder.numColorFragmentProcessors() - firstColorProcessorIdx;
     int numTotalProcessors = pipeline->fNumColorProcessors +
                              builder.numCoverageFragmentProcessors() - firstCoverageProcessorIdx;
+    if (args.fAppliedClip->clipCoverageFragmentProcessor()) {
+        ++numTotalProcessors;
+    }
     pipeline->fFragmentProcessors.reset(numTotalProcessors);
     int currFPIdx = 0;
     for (int i = firstColorProcessorIdx; i < builder.numColorFragmentProcessors();
@@ -137,6 +140,10 @@
         pipeline->fFragmentProcessors[currFPIdx].reset(fp);
         usesLocalCoords = usesLocalCoords || fp->usesLocalCoords();
     }
+    if (const GrFragmentProcessor* fp = args.fAppliedClip->clipCoverageFragmentProcessor()) {
+        pipeline->fFragmentProcessors[currFPIdx].reset(fp);
+        usesLocalCoords = usesLocalCoords || fp->usesLocalCoords();
+    }
 
     // Setup info we need to pass to GrPrimitiveProcessors that are used with this GrPipeline.
     optimizations->fFlags = 0;
diff --git a/src/gpu/GrPipeline.h b/src/gpu/GrPipeline.h
index 0013ce6..f00fbf3 100644
--- a/src/gpu/GrPipeline.h
+++ b/src/gpu/GrPipeline.h
@@ -26,6 +26,7 @@
 #include "effects/GrPorterDuffXferProcessor.h"
 #include "effects/GrSimpleTextureEffect.h"
 
+class GrAppliedClip;
 class GrDeviceCoordTexture;
 class GrOp;
 class GrPipelineBuilder;
@@ -70,12 +71,10 @@
 
     struct CreateArgs {
         const GrPipelineBuilder* fPipelineBuilder;
+        GrAppliedClip* fAppliedClip;
         GrRenderTargetContext* fRenderTargetContext;
         const GrCaps* fCaps;
         GrPipelineAnalysis fAnalysis;
-        const GrScissorState* fScissor;
-        const GrWindowRectsState* fWindowRectsState;
-        bool fHasStencilClip;
         GrXferProcessor::DstTexture fDstTexture;
     };
 
diff --git a/src/gpu/GrPipelineBuilder.cpp b/src/gpu/GrPipelineBuilder.cpp
index fc67c33..fce8aa9 100644
--- a/src/gpu/GrPipelineBuilder.cpp
+++ b/src/gpu/GrPipelineBuilder.cpp
@@ -19,8 +19,6 @@
         : fFlags(0x0)
         , fUserStencilSettings(&GrUserStencilSettings::kUnused)
         , fDrawFace(GrDrawFace::kBoth) {
-    SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
-
     for (int i = 0; i < paint.numColorFragmentProcessors(); ++i) {
         fColorFragmentProcessors.emplace_back(paint.fColorFragmentProcessors[i].release());
     }
@@ -40,8 +38,6 @@
                    paint.usesDistanceVectorField());
 }
 
-//////////////////////////////////////////////////////////////////////////////s
-
 bool GrPipelineBuilder::willXPNeedDstTexture(const GrCaps& caps,
                                              const GrPipelineAnalysis& analysis) const {
     if (this->getXPFactory()) {
@@ -49,30 +45,3 @@
     }
     return GrPorterDuffXPFactory::SrcOverWillNeedDstTexture(caps, analysis);
 }
-
-void GrPipelineBuilder::AutoRestoreFragmentProcessorState::set(
-                                                         const GrPipelineBuilder* pipelineBuilder) {
-    if (fPipelineBuilder) {
-        int m = fPipelineBuilder->numColorFragmentProcessors() - fColorEffectCnt;
-        SkASSERT(m >= 0);
-        fPipelineBuilder->fColorFragmentProcessors.pop_back_n(m);
-
-        int n = fPipelineBuilder->numCoverageFragmentProcessors() - fCoverageEffectCnt;
-        SkASSERT(n >= 0);
-        fPipelineBuilder->fCoverageFragmentProcessors.pop_back_n(n);
-
-        SkDEBUGCODE(--fPipelineBuilder->fBlockEffectRemovalCnt;)
-    }
-    fPipelineBuilder = const_cast<GrPipelineBuilder*>(pipelineBuilder);
-    if (nullptr != pipelineBuilder) {
-        fColorEffectCnt = pipelineBuilder->numColorFragmentProcessors();
-        fCoverageEffectCnt = pipelineBuilder->numCoverageFragmentProcessors();
-        SkDEBUGCODE(++pipelineBuilder->fBlockEffectRemovalCnt;)
-    }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-GrPipelineBuilder::~GrPipelineBuilder() {
-    SkASSERT(0 == fBlockEffectRemovalCnt);
-}
diff --git a/src/gpu/GrPipelineBuilder.h b/src/gpu/GrPipelineBuilder.h
index 66459ae..fcc692a 100644
--- a/src/gpu/GrPipelineBuilder.h
+++ b/src/gpu/GrPipelineBuilder.h
@@ -37,8 +37,6 @@
      */
     GrPipelineBuilder(GrPaint&&, GrAAType);
 
-    virtual ~GrPipelineBuilder();
-
     ///////////////////////////////////////////////////////////////////////////
     /// @name Fragment Processors
     ///
@@ -61,44 +59,6 @@
         return fCoverageFragmentProcessors[idx].get();
     }
 
-    /**
-     * When this object is destroyed it will remove any color/coverage FPs from the pipeline builder
-     * that were added after its constructor.
-     * This class can transiently modify its "const" GrPipelineBuilder object but will restore it
-     * when done - so it is notionally "const" correct.
-     */
-    class AutoRestoreFragmentProcessorState : public ::SkNoncopyable {
-    public:
-        AutoRestoreFragmentProcessorState()
-            : fPipelineBuilder(nullptr)
-            , fColorEffectCnt(0)
-            , fCoverageEffectCnt(0) {}
-
-        AutoRestoreFragmentProcessorState(const GrPipelineBuilder& ds)
-            : fPipelineBuilder(nullptr)
-            , fColorEffectCnt(0)
-            , fCoverageEffectCnt(0) {
-            this->set(&ds);
-        }
-
-        ~AutoRestoreFragmentProcessorState() { this->set(nullptr); }
-
-        void set(const GrPipelineBuilder* ds);
-
-        bool isSet() const { return SkToBool(fPipelineBuilder); }
-
-        void addCoverageFragmentProcessor(sk_sp<GrFragmentProcessor> processor) {
-            SkASSERT(this->isSet());
-            return fPipelineBuilder->addCoverageFragmentProcessor(std::move(processor));
-        }
-
-    private:
-        // notionally const (as marginalia)
-        GrPipelineBuilder*    fPipelineBuilder;
-        int                   fColorEffectCnt;
-        int                   fCoverageEffectCnt;
-    };
-
     /// @}
 
     ///////////////////////////////////////////////////////////////////////////
@@ -241,17 +201,6 @@
     bool usePLSDstRead(const GrDrawOp*) const;
 
 private:
-    // This exists solely for AutoRestoreFragmentProcessor, which itself exists solely to install
-    // an applied clip's FP. This will be removed soon.
-    void addCoverageFragmentProcessor(sk_sp<GrFragmentProcessor> processor) {
-        SkASSERT(processor);
-        fCoverageFragmentProcessors.push_back(std::move(processor));
-    }
-
-    // Some of the auto restore objects assume that no effects are removed during their lifetime.
-    // This is used to assert that this condition holds.
-    SkDEBUGCODE(mutable int fBlockEffectRemovalCnt;)
-
     typedef SkSTArray<4, sk_sp<GrFragmentProcessor>> FragmentProcessorArray;
 
     uint32_t                                fFlags;
diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp
index 780e13b..e4bb34e 100644
--- a/src/gpu/GrRenderTargetOpList.cpp
+++ b/src/gpu/GrRenderTargetOpList.cpp
@@ -275,13 +275,6 @@
         return;
     }
 
-    // TODO: this is the only remaining usage of the AutoRestoreFragmentProcessorState - remove it
-    GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps;
-    if (appliedClip.clipCoverageFragmentProcessor()) {
-        arfps.set(&pipelineBuilder);
-        arfps.addCoverageFragmentProcessor(sk_ref_sp(appliedClip.clipCoverageFragmentProcessor()));
-    }
-
     if (pipelineBuilder.hasUserStencilSettings() || appliedClip.hasStencilClip()) {
         if (!renderTargetContext->accessRenderTarget()) {
             return;
@@ -296,6 +289,7 @@
 
     GrPipeline::CreateArgs args;
     args.fPipelineBuilder = &pipelineBuilder;
+    args.fAppliedClip = &appliedClip;
     args.fRenderTargetContext = renderTargetContext;
     args.fCaps = this->caps();
     op->initPipelineAnalysis(&args.fAnalysis);
@@ -324,9 +318,10 @@
     args.fAnalysis.fCoveragePOI.addProcessors(
             sk_sp_address_as_pointer_address(pipelineBuilder.fCoverageFragmentProcessors.begin()),
             pipelineBuilder.numCoverageFragmentProcessors());
-    args.fScissor = &appliedClip.scissorState();
-    args.fWindowRectsState = &appliedClip.windowRectsState();
-    args.fHasStencilClip = appliedClip.hasStencilClip();
+    if (const GrFragmentProcessor* clipFP = appliedClip.clipCoverageFragmentProcessor()) {
+        args.fAnalysis.fCoveragePOI.addProcessors(&clipFP, 1);
+    }
+
     if (!renderTargetContext->accessRenderTarget()) {
         return;
     }
diff --git a/src/gpu/GrSWMaskHelper.cpp b/src/gpu/GrSWMaskHelper.cpp
index 240f9f9..5dbbaf0 100644
--- a/src/gpu/GrSWMaskHelper.cpp
+++ b/src/gpu/GrSWMaskHelper.cpp
@@ -176,10 +176,8 @@
     // We use device coords to compute the texture coordinates. We take the device coords and apply
     // a translation so that the top-left of the device bounds maps to 0,0, and then a scaling
     // matrix to normalized coords.
-    SkMatrix maskMatrix;
-    maskMatrix.setIDiv(texture->width(), texture->height());
-    maskMatrix.preTranslate(SkIntToScalar(-textureOriginInDeviceSpace.fX),
-                            SkIntToScalar(-textureOriginInDeviceSpace.fY));
+    SkMatrix maskMatrix = SkMatrix::MakeTrans(SkIntToScalar(-textureOriginInDeviceSpace.fX),
+                                              SkIntToScalar(-textureOriginInDeviceSpace.fY));
     maskMatrix.preConcat(viewMatrix);
     std::unique_ptr<GrDrawOp> op = GrRectOpFactory::MakeNonAAFill(paint.getColor(), SkMatrix::I(),
                                                                   dstRect, nullptr, &invert);
diff --git a/src/gpu/GrTextureAdjuster.cpp b/src/gpu/GrTextureAdjuster.cpp
index 7142ab9..db9bbde 100644
--- a/src/gpu/GrTextureAdjuster.cpp
+++ b/src/gpu/GrTextureAdjuster.cpp
@@ -156,7 +156,6 @@
     }
     SkASSERT(kNoDomain_DomainMode == domainMode ||
              (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom));
-    textureMatrix.postIDiv(texture->width(), texture->height());
     sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace,
                                                                        dstColorSpace);
     return CreateFragmentProcessorForDomainAndFilter(texture.get(), std::move(colorSpaceXform),
diff --git a/src/gpu/GrTextureMaker.cpp b/src/gpu/GrTextureMaker.cpp
index 37272be..cc6c703 100644
--- a/src/gpu/GrTextureMaker.cpp
+++ b/src/gpu/GrTextureMaker.cpp
@@ -87,12 +87,10 @@
                             texture->width(), texture->height(),
                             nullptr, fmForDetermineDomain, &domain);
     SkASSERT(kTightCopy_DomainMode != domainMode);
-    SkMatrix normalizedTextureMatrix = textureMatrix;
-    normalizedTextureMatrix.postIDiv(texture->width(), texture->height());
     sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(texColorSpace.get(),
                                                                        dstColorSpace);
     return CreateFragmentProcessorForDomainAndFilter(texture.get(), std::move(colorSpaceXform),
-                                                     normalizedTextureMatrix, domainMode, domain,
+                                                     textureMatrix, domainMode, domain,
                                                      filterOrNullForBicubic);
 }
 
diff --git a/src/gpu/GrTextureProducer.cpp b/src/gpu/GrTextureProducer.cpp
index 0adae8c..496dbb2 100644
--- a/src/gpu/GrTextureProducer.cpp
+++ b/src/gpu/GrTextureProducer.cpp
@@ -52,16 +52,9 @@
 
     SkRect localRect;
     if (subset) {
-        SkScalar sx = SK_Scalar1 / inputTexture->width();
-        SkScalar sy = SK_Scalar1 / inputTexture->height();
-
         localRect = SkRect::Make(*subset);
-        localRect.fLeft *= sx;
-        localRect.fTop *= sy;
-        localRect.fRight *= sx;
-        localRect.fBottom *= sy;
     } else {
-        localRect = SkRect::MakeWH(1.f, 1.f);
+        localRect = SkRect::MakeWH(inputTexture->width(), inputTexture->height());
     }
 
     SkRect dstRect = SkRect::MakeIWH(copyParams.fWidth, copyParams.fHeight);
diff --git a/src/gpu/GrTextureToYUVPlanes.cpp b/src/gpu/GrTextureToYUVPlanes.cpp
index b9252fa..132b680 100644
--- a/src/gpu/GrTextureToYUVPlanes.cpp
+++ b/src/gpu/GrTextureToYUVPlanes.cpp
@@ -22,8 +22,8 @@
 static bool convert_texture(GrTexture* src, GrRenderTargetContext* dst, int dstW, int dstH,
                             SkYUVColorSpace colorSpace, MakeFPProc proc) {
 
-    SkScalar xScale = SkIntToScalar(src->width()) / dstW / src->width();
-    SkScalar yScale = SkIntToScalar(src->height()) / dstH / src->height();
+    SkScalar xScale = SkIntToScalar(src->width()) / dstW;
+    SkScalar yScale = SkIntToScalar(src->height()) / dstH;
     GrSamplerParams::FilterMode filter;
     if (dstW == src->width() && dstW == src->height()) {
         filter = GrSamplerParams::kNone_FilterMode;
diff --git a/src/gpu/GrYUVProvider.cpp b/src/gpu/GrYUVProvider.cpp
index 1330cfe..2f75d92 100644
--- a/src/gpu/GrYUVProvider.cpp
+++ b/src/gpu/GrYUVProvider.cpp
@@ -146,7 +146,7 @@
 
     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
     const SkRect r = SkRect::MakeIWH(yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fWidth,
-            yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight);
+                                     yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight);
 
     renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), r);
 
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 1dec0f6..25ad781 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1048,13 +1048,8 @@
     sk_sp<GrColorSpaceXform> colorSpaceXform =
         GrColorSpaceXform::Make(bitmap.colorSpace(), fRenderTargetContext->getColorSpace());
 
-    SkScalar iw = 1.f / texture->width();
-    SkScalar ih = 1.f / texture->height();
-
-    SkMatrix texMatrix;
     // Compute a matrix that maps the rect we will draw to the src rect.
-    texMatrix.setRectToRect(dstRect, srcRect, SkMatrix::kFill_ScaleToFit);
-    texMatrix.postScale(iw, ih);
+    SkMatrix texMatrix = SkMatrix::MakeRectToRect(dstRect, srcRect, SkMatrix::kFill_ScaleToFit);
 
     // Construct a GrPaint by setting the bitmap texture as the first effect and then configuring
     // the rest from the SkPaint.
@@ -1200,10 +1195,7 @@
             SkMatrix::I(),
             SkRect::Make(SkIRect::MakeXYWH(
                     left + offset.fX, top + offset.fY, subset.width(), subset.height())),
-            SkRect::MakeXYWH(SkIntToScalar(subset.fLeft) / texture->width(),
-                             SkIntToScalar(subset.fTop) / texture->height(),
-                             SkIntToScalar(subset.width()) / texture->width(),
-                             SkIntToScalar(subset.height()) / texture->height()));
+            SkRect::Make(subset));
 }
 
 void SkGpuDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 3cca52f..50c7cc2 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -23,6 +23,7 @@
 #include "SkColorFilter.h"
 #include "SkConfig8888.h"
 #include "SkData.h"
+#include "SkImageInfoPriv.h"
 #include "SkMaskFilter.h"
 #include "SkMessageBus.h"
 #include "SkMipMap.h"
@@ -125,6 +126,10 @@
     SkPixmap tmpPixmap;
     SkBitmap tmpBitmap;
 
+    if (!SkImageInfoIsValid(pixmap.info())) {
+        return nullptr;
+    }
+
     const GrCaps* caps = ctx->caps();
     GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(pixmap.info(), *caps);
 
@@ -199,6 +204,10 @@
         ? SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware
         : SkDestinationSurfaceColorMode::kLegacy;
 
+    if (!SkImageInfoIsValid(bitmap.info())) {
+        return nullptr;
+    }
+
     GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap.info(), *ctx->caps());
 
     // We don't support Gray8 directly in the GL backend, so fail-over to GrUploadBitmapToTexture.
@@ -210,11 +219,6 @@
         return nullptr;
     }
 
-    SkASSERT(sizeof(int) <= sizeof(uint32_t));
-    if (bitmap.width() < 0 || bitmap.height() < 0) {
-        return nullptr;
-    }
-
     SkAutoPixmapUnlock srcUnlocker;
     if (!bitmap.requestLock(&srcUnlocker)) {
         return nullptr;
@@ -264,6 +268,10 @@
 
 GrTexture* GrUploadMipMapToTexture(GrContext* ctx, const SkImageInfo& info,
                                    const GrMipLevel* texels, int mipLevelCount) {
+    if (!SkImageInfoIsValid(info)) {
+        return nullptr;
+    }
+
     const GrCaps* caps = ctx->caps();
     return ctx->textureProvider()->createMipMappedTexture(GrImageInfoToSurfaceDesc(info, *caps),
                                                           SkBudgeted::kYes, texels,
diff --git a/src/gpu/effects/Gr1DKernelEffect.h b/src/gpu/effects/Gr1DKernelEffect.h
index d7402e8..29e0e5d 100644
--- a/src/gpu/effects/Gr1DKernelEffect.h
+++ b/src/gpu/effects/Gr1DKernelEffect.h
@@ -31,7 +31,7 @@
     Gr1DKernelEffect(GrTexture* texture,
                      Direction direction,
                      int radius)
-        : INHERITED(texture, nullptr, GrCoordTransform::MakeDivByTextureWHMatrix(texture))
+        : INHERITED(texture, nullptr, SkMatrix::I())
         , fDirection(direction)
         , fRadius(radius) {}
 
diff --git a/src/gpu/effects/GrBicubicEffect.cpp b/src/gpu/effects/GrBicubicEffect.cpp
index 50a2a5d..07d1c53 100644
--- a/src/gpu/effects/GrBicubicEffect.cpp
+++ b/src/gpu/effects/GrBicubicEffect.cpp
@@ -181,8 +181,7 @@
     static const SkShader::TileMode kClampClamp[] =
         { SkShader::kClamp_TileMode, SkShader::kClamp_TileMode };
     return GrBicubicEffect::Make(d->fTextures[texIdx], colorSpaceXform,
-                                 GrCoordTransform::MakeDivByTextureWHMatrix(d->fTextures[texIdx]),
-                                 kClampClamp);
+                                 SkMatrix::I(), kClampClamp);
 }
 
 //////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/effects/GrConfigConversionEffect.cpp b/src/gpu/effects/GrConfigConversionEffect.cpp
index 8405fcb..e6b3b28 100644
--- a/src/gpu/effects/GrConfigConversionEffect.cpp
+++ b/src/gpu/effects/GrConfigConversionEffect.cpp
@@ -216,7 +216,7 @@
         *upmToPMRule = kConversionRules[i][1];
 
         static const SkRect kDstRect = SkRect::MakeIWH(kSize, kSize);
-        static const SkRect kSrcRect = SkRect::MakeIWH(1, 1);
+        static const SkRect kSrcRect = SkRect::MakeIWH(kSize, kSize);
         // We do a PM->UPM draw from dataTex to readTex and read the data. Then we do a UPM->PM draw
         // from readTex to tempTex followed by a PM->UPM draw to readTex and finally read the data.
         // We then verify that two reads produced the same values.
diff --git a/src/gpu/effects/GrMatrixConvolutionEffect.cpp b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
index 8b98d0b..01fc6ce 100644
--- a/src/gpu/effects/GrMatrixConvolutionEffect.cpp
+++ b/src/gpu/effects/GrMatrixConvolutionEffect.cpp
@@ -156,7 +156,7 @@
                                                      const SkIPoint& kernelOffset,
                                                      GrTextureDomain::Mode tileMode,
                                                      bool convolveAlpha)
-  : INHERITED(texture, nullptr, GrCoordTransform::MakeDivByTextureWHMatrix(texture)),
+  : INHERITED(texture, nullptr, SkMatrix::I()),
     fKernelSize(kernelSize),
     fGain(SkScalarToFloat(gain)),
     fBias(SkScalarToFloat(bias) / 255.0f),
diff --git a/src/gpu/effects/GrYUVEffect.cpp b/src/gpu/effects/GrYUVEffect.cpp
index 6d1fac2..41bab18 100644
--- a/src/gpu/effects/GrYUVEffect.cpp
+++ b/src/gpu/effects/GrYUVEffect.cpp
@@ -66,18 +66,17 @@
                                            GrTexture* vTexture, const SkISize sizes[3],
                                            SkYUVColorSpace colorSpace, bool nv12) {
         SkScalar w[3], h[3];
-        w[0] = SkIntToScalar(sizes[0].fWidth)  / SkIntToScalar(yTexture->width());
-        h[0] = SkIntToScalar(sizes[0].fHeight) / SkIntToScalar(yTexture->height());
-        w[1] = SkIntToScalar(sizes[1].fWidth)  / SkIntToScalar(uTexture->width());
-        h[1] = SkIntToScalar(sizes[1].fHeight) / SkIntToScalar(uTexture->height());
-        w[2] = SkIntToScalar(sizes[2].fWidth)  / SkIntToScalar(vTexture->width());
-        h[2] = SkIntToScalar(sizes[2].fHeight) / SkIntToScalar(vTexture->height());
-        SkMatrix yuvMatrix[3];
-        yuvMatrix[0] = GrCoordTransform::MakeDivByTextureWHMatrix(yTexture);
-        yuvMatrix[1] = yuvMatrix[0];
-        yuvMatrix[1].preScale(w[1] / w[0], h[1] / h[0]);
-        yuvMatrix[2] = yuvMatrix[0];
-        yuvMatrix[2].preScale(w[2] / w[0], h[2] / h[0]);
+        w[0] = SkIntToScalar(sizes[0].fWidth);
+        h[0] = SkIntToScalar(sizes[0].fHeight);
+        w[1] = SkIntToScalar(sizes[1].fWidth);
+        h[1] = SkIntToScalar(sizes[1].fHeight);
+        w[2] = SkIntToScalar(sizes[2].fWidth);
+        h[2] = SkIntToScalar(sizes[2].fHeight);
+        const SkMatrix yuvMatrix[3] = {
+            SkMatrix::I(),
+            SkMatrix::MakeScale(w[1] / w[0], h[1] / h[0]),
+            SkMatrix::MakeScale(w[2] / w[0], h[2] / h[0])
+        };
         GrSamplerParams::FilterMode uvFilterMode =
             ((sizes[1].fWidth  != sizes[0].fWidth) ||
              (sizes[1].fHeight != sizes[0].fHeight) ||
diff --git a/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp b/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp
index 24f21ff..f39fff2 100644
--- a/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp
@@ -16,6 +16,11 @@
                                                       const GrCoordTransform& coordTransform) {
     SkMatrix combined;
     combined.setConcat(coordTransform.getMatrix(), localMatrix);
+    if (coordTransform.normalize()) {
+        SkASSERT(coordTransform.texture());
+        combined.postIDiv(coordTransform.texture()->width(), coordTransform.texture()->height());
+    }
+
     if (coordTransform.reverseY()) {
         // combined.postScale(1,-1);
         // combined.postTranslate(0,1);
diff --git a/src/image/SkImageShader.cpp b/src/image/SkImageShader.cpp
index 5b79fb1..50cc3c4 100644
--- a/src/image/SkImageShader.cpp
+++ b/src/image/SkImageShader.cpp
@@ -144,8 +144,6 @@
 #include "effects/GrSimpleTextureEffect.h"
 
 sk_sp<GrFragmentProcessor> SkImageShader::asFragmentProcessor(const AsFPArgs& args) const {
-    SkMatrix matrix;
-    matrix.setIDiv(fImage->width(), fImage->height());
 
     SkMatrix lmInverse;
     if (!this->getLocalMatrix().invert(&lmInverse)) {
@@ -158,7 +156,6 @@
         }
         lmInverse.postConcat(inv);
     }
-    matrix.preConcat(lmInverse);
 
     SkShader::TileMode tm[] = { fTileModeX, fTileModeY };
 
@@ -182,10 +179,10 @@
                                                                        args.fDstColorSpace);
     sk_sp<GrFragmentProcessor> inner;
     if (doBicubic) {
-        inner = GrBicubicEffect::Make(texture.get(), std::move(colorSpaceXform), matrix, tm);
+        inner = GrBicubicEffect::Make(texture.get(), std::move(colorSpaceXform), lmInverse, tm);
     } else {
         inner = GrSimpleTextureEffect::Make(texture.get(), std::move(colorSpaceXform),
-                                            matrix, params);
+                                            lmInverse, params);
     }
 
     if (GrPixelConfigIsAlphaOnly(texture->config())) {
diff --git a/tests/GpuSampleLocationsTest.cpp b/tests/GpuSampleLocationsTest.cpp
index 094a3fc..b4c4fe5 100644
--- a/tests/GpuSampleLocationsTest.cpp
+++ b/tests/GpuSampleLocationsTest.cpp
@@ -12,10 +12,11 @@
 
 #if SK_SUPPORT_GPU
 
+#include "GrAppliedClip.h"
+#include "GrPipelineBuilder.h"
 #include "GrRenderTargetContext.h"
 #include "GrRenderTargetPriv.h"
 #include "GrTypesPriv.h"
-#include "GrPipelineBuilder.h"
 #include "gl/GrGLGpu.h"
 #include "gl/debug/DebugGLTestContext.h"
 
@@ -96,13 +97,12 @@
     GrWindowRectsState dummyWindows;
     GrPipelineOptimizations dummyOverrides;
 
+    GrAppliedClip dummyAppliedClip(SkRect::MakeLargest());
     GrPipeline::CreateArgs args;
     args.fPipelineBuilder = &dummyBuilder;
     args.fRenderTargetContext = dc;
     args.fCaps = dc->caps();
-    args.fScissor = &dummyScissor;
-    args.fWindowRectsState = &dummyWindows;
-    args.fHasStencilClip = false;
+    args.fAppliedClip = &dummyAppliedClip;
     args.fDstTexture = GrXferProcessor::DstTexture();
 
     GrPipeline::CreateAt(storage, args, &dummyOverrides);
diff --git a/tests/IntTextureTest.cpp b/tests/IntTextureTest.cpp
index a3e17bf..3edd4cc 100644
--- a/tests/IntTextureTest.cpp
+++ b/tests/IntTextureTest.cpp
@@ -207,9 +207,8 @@
     };
 
     for (auto filter : kNamedFilters) {
-        SkMatrix m;
-        m.setIDiv(kS, kS);
-        sk_sp<GrFragmentProcessor> fp(GrSimpleTextureEffect::Make(texture.get(), nullptr, m,
+        sk_sp<GrFragmentProcessor> fp(GrSimpleTextureEffect::Make(texture.get(), nullptr,
+                                                                  SkMatrix::I(),
                                                                   filter.fMode));
         REPORTER_ASSERT(reporter, fp);
         if (!fp) {
diff --git a/tests/RectangleTextureTest.cpp b/tests/RectangleTextureTest.cpp
index a0c5409..6d075df 100644
--- a/tests/RectangleTextureTest.cpp
+++ b/tests/RectangleTextureTest.cpp
@@ -107,14 +107,12 @@
             context->makeRenderTargetContext(SkBackingFit::kExact, rectangleTexture->width(),
                                              rectangleTexture->height(), rectangleTexture->config(),
                                              nullptr));
-    SkMatrix m;
-    m.setIDiv(rectangleTexture->width(), rectangleTexture->height());
     for (auto filter : {GrSamplerParams::kNone_FilterMode,
                         GrSamplerParams::kBilerp_FilterMode,
                         GrSamplerParams::kMipMap_FilterMode}) {
         rtContext->clear(nullptr, 0xDDCCBBAA, true);
-        sk_sp<GrFragmentProcessor> fp(GrSimpleTextureEffect::Make(rectangleTexture,
-                                                                  nullptr, m, filter));
+        sk_sp<GrFragmentProcessor> fp(GrSimpleTextureEffect::Make(rectangleTexture, nullptr,
+                                                                  SkMatrix::I(), filter));
         GrPaint paint;
         paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
         paint.addColorFragmentProcessor(std::move(fp));
diff --git a/tests/SRGBMipMapTest.cpp b/tests/SRGBMipMapTest.cpp
index 79d8691..22d6890 100644
--- a/tests/SRGBMipMapTest.cpp
+++ b/tests/SRGBMipMapTest.cpp
@@ -132,7 +132,7 @@
     GrPaint paint;
     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
     GrSamplerParams mipMapParams(SkShader::kRepeat_TileMode, GrSamplerParams::kMipMap_FilterMode);
-    paint.addColorTextureProcessor(texture.get(), nullptr, SkMatrix::MakeScale(0.5f), mipMapParams);
+    paint.addColorTextureProcessor(texture.get(), nullptr, SkMatrix::MakeScale(rtS), mipMapParams);
 
     // 1) Draw texture to S32 surface (should generate/use sRGB mips)
     paint.setGammaCorrect(true);