use rasterpipeline for images if matrix is >= scale+translate

Bug: skia:
Change-Id: I36112fe54c6f2d0965d0b88f0291d7ffe0902715
Reviewed-on: https://skia-review.googlesource.com/30480
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Mike Klein <mtklein@chromium.org>
Reviewed-by: Florin Malita <fmalita@chromium.org>
diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp
index 6bd48be..a1a1db6 100644
--- a/src/core/SkBlitter.cpp
+++ b/src/core/SkBlitter.cpp
@@ -913,7 +913,7 @@
         return true;
     }
     // ... or unless the shader is raster pipeline-only.
-    if (paint.getShader() && as_SB(paint.getShader())->isRasterPipelineOnly()) {
+    if (paint.getShader() && as_SB(paint.getShader())->isRasterPipelineOnly(matrix)) {
         return true;
     }
 
diff --git a/src/shaders/SkColorFilterShader.h b/src/shaders/SkColorFilterShader.h
index 001f3cc..3a1878f 100644
--- a/src/shaders/SkColorFilterShader.h
+++ b/src/shaders/SkColorFilterShader.h
@@ -29,7 +29,7 @@
     sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override;
     bool onAppendStages(SkRasterPipeline*, SkColorSpace* dstCS, SkArenaAlloc*,
                         const SkMatrix&, const SkPaint&, const SkMatrix* localM) const override;
-    bool onIsRasterPipelineOnly() const override { return true; }
+    bool onIsRasterPipelineOnly(const SkMatrix&) const override { return true; }
 
 private:
     sk_sp<SkShader>      fShader;
diff --git a/src/shaders/SkComposeShader.h b/src/shaders/SkComposeShader.h
index 432915d..1389742 100644
--- a/src/shaders/SkComposeShader.h
+++ b/src/shaders/SkComposeShader.h
@@ -45,7 +45,7 @@
     bool onAppendStages(SkRasterPipeline*, SkColorSpace* dstCS, SkArenaAlloc*,
                         const SkMatrix&, const SkPaint&, const SkMatrix* localM) const override;
 
-    bool onIsRasterPipelineOnly() const override { return true; }
+    bool onIsRasterPipelineOnly(const SkMatrix&) const override { return true; }
 
 private:
     sk_sp<SkShader>     fDst;
diff --git a/src/shaders/SkImageShader.cpp b/src/shaders/SkImageShader.cpp
index 6657743..609ad4b 100644
--- a/src/shaders/SkImageShader.cpp
+++ b/src/shaders/SkImageShader.cpp
@@ -61,7 +61,7 @@
     return fImage->isOpaque();
 }
 
-bool SkImageShader::IsRasterPipelineOnly(SkColorType ct, SkAlphaType at,
+bool SkImageShader::IsRasterPipelineOnly(const SkMatrix& ctm, SkColorType ct, SkAlphaType at,
                                          SkShader::TileMode tx, SkShader::TileMode ty) {
     if (ct != kN32_SkColorType) {
         return true;
@@ -72,12 +72,17 @@
     if (tx != ty) {
         return true;
     }
+#ifndef SK_SUPPORT_LEGACY_ROTATED_SHADERS
+    if (!ctm.isScaleTranslate()) {
+        return true;
+    }
+#endif
     return false;
 }
 
-bool SkImageShader::onIsRasterPipelineOnly() const {
+bool SkImageShader::onIsRasterPipelineOnly(const SkMatrix& ctm) const {
     SkBitmapProvider provider(fImage.get(), nullptr);
-    return IsRasterPipelineOnly(provider.info().colorType(), provider.info().alphaType(),
+    return IsRasterPipelineOnly(ctm, provider.info().colorType(), provider.info().alphaType(),
                                 fTileModeX, fTileModeY);
 }
 
diff --git a/src/shaders/SkImageShader.h b/src/shaders/SkImageShader.h
index b74c315..b499b92 100644
--- a/src/shaders/SkImageShader.h
+++ b/src/shaders/SkImageShader.h
@@ -29,7 +29,7 @@
 
     SkImageShader(sk_sp<SkImage>, TileMode tx, TileMode ty, const SkMatrix* localMatrix);
 
-    static bool IsRasterPipelineOnly(SkColorType, SkAlphaType,
+    static bool IsRasterPipelineOnly(const SkMatrix& ctm, SkColorType, SkAlphaType,
                                      SkShader::TileMode tx, SkShader::TileMode ty);
 
 protected:
@@ -40,7 +40,7 @@
 #endif
     SkImage* onIsAImage(SkMatrix*, TileMode*) const override;
 
-    bool onIsRasterPipelineOnly() const override;
+    bool onIsRasterPipelineOnly(const SkMatrix& ctm) const override;
 
     bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*,
                         const SkMatrix& ctm, const SkPaint&, const SkMatrix*) const override;
diff --git a/src/shaders/SkLocalMatrixShader.h b/src/shaders/SkLocalMatrixShader.h
index 5ae8e03..3ae44cf 100644
--- a/src/shaders/SkLocalMatrixShader.h
+++ b/src/shaders/SkLocalMatrixShader.h
@@ -62,8 +62,8 @@
     }
 #endif
 
-    bool onIsRasterPipelineOnly() const override {
-        return as_SB(fProxyShader)->isRasterPipelineOnly();
+    bool onIsRasterPipelineOnly(const SkMatrix& ctm) const override {
+        return as_SB(fProxyShader)->isRasterPipelineOnly(ctm);
     }
 
 private:
diff --git a/src/shaders/SkPictureShader.cpp b/src/shaders/SkPictureShader.cpp
index 95a128e..4c746ee 100644
--- a/src/shaders/SkPictureShader.cpp
+++ b/src/shaders/SkPictureShader.cpp
@@ -291,8 +291,9 @@
     return tileShader;
 }
 
-bool SkPictureShader::onIsRasterPipelineOnly() const {
-    return SkImageShader::IsRasterPipelineOnly(kN32_SkColorType, kPremul_SkAlphaType, fTmx, fTmy);
+bool SkPictureShader::onIsRasterPipelineOnly(const SkMatrix& ctm) const {
+    return SkImageShader::IsRasterPipelineOnly(ctm, kN32_SkColorType, kPremul_SkAlphaType,
+                                               fTmx, fTmy);
 }
 
 bool SkPictureShader::onAppendStages(SkRasterPipeline* p, SkColorSpace* cs, SkArenaAlloc* alloc,
diff --git a/src/shaders/SkPictureShader.h b/src/shaders/SkPictureShader.h
index ee89f88..3d58d6d 100644
--- a/src/shaders/SkPictureShader.h
+++ b/src/shaders/SkPictureShader.h
@@ -42,7 +42,7 @@
                         const SkMatrix&, const SkPaint&, const SkMatrix*) const override;
     Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override;
     sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override;
-    bool onIsRasterPipelineOnly() const override;
+    bool onIsRasterPipelineOnly(const SkMatrix&) const override;
 
 private:
     SkPictureShader(sk_sp<SkPicture>, TileMode, TileMode, const SkMatrix*, const SkRect*,
diff --git a/src/shaders/SkShader.cpp b/src/shaders/SkShader.cpp
index cc0d6b1..5540b2d 100644
--- a/src/shaders/SkShader.cpp
+++ b/src/shaders/SkShader.cpp
@@ -91,8 +91,6 @@
 }
 
 SkShaderBase::Context* SkShaderBase::makeContext(const ContextRec& rec, SkArenaAlloc* alloc) const {
-    SkASSERT(!this->isRasterPipelineOnly());
-
     return this->computeTotalInverse(*rec.fMatrix, rec.fLocalMatrix, nullptr)
         ? this->onMakeContext(rec, alloc)
         : nullptr;
@@ -117,7 +115,7 @@
     : fShader(shader), fCTM(*rec.fMatrix)
 {
     // We should never use a context for RP-only shaders.
-    SkASSERT(!shader.isRasterPipelineOnly());
+    SkASSERT(!shader.isRasterPipelineOnly(*rec.fMatrix));
     // ... or for perspective.
     SkASSERT(!rec.fMatrix->hasPerspective());
     SkASSERT(!rec.fLocalMatrix || !rec.fLocalMatrix->hasPerspective());
diff --git a/src/shaders/SkShaderBase.h b/src/shaders/SkShaderBase.h
index 783fff4..99cace2 100644
--- a/src/shaders/SkShaderBase.h
+++ b/src/shaders/SkShaderBase.h
@@ -187,9 +187,10 @@
         return this->onMakeColorSpace(xformer);
     }
 
-    bool isRasterPipelineOnly() const {
+    bool isRasterPipelineOnly(const SkMatrix& ctm) const {
         // We always use RP when perspective is present.
-        return fLocalMatrix.hasPerspective() || this->onIsRasterPipelineOnly();
+        return ctm.hasPerspective() || fLocalMatrix.hasPerspective()
+                                    || this->onIsRasterPipelineOnly(ctm);
     }
 
     // If this returns false, then we draw nothing (do not fall back to shader context)
@@ -247,7 +248,7 @@
     virtual bool onAppendStages(SkRasterPipeline*, SkColorSpace* dstCS, SkArenaAlloc*,
                                 const SkMatrix&, const SkPaint&, const SkMatrix* localM) const;
 
-    virtual bool onIsRasterPipelineOnly() const { return false; }
+    virtual bool onIsRasterPipelineOnly(const SkMatrix& ctm) const { return false; }
 
 private:
     // This is essentially const, but not officially so it can be modified in constructors.
diff --git a/src/shaders/gradients/SkRadialGradient.h b/src/shaders/gradients/SkRadialGradient.h
index 5becf0a..8cd7df2 100644
--- a/src/shaders/gradients/SkRadialGradient.h
+++ b/src/shaders/gradients/SkRadialGradient.h
@@ -30,7 +30,7 @@
     void appendGradientStages(SkArenaAlloc* alloc, SkRasterPipeline* tPipeline,
                               SkRasterPipeline* postPipeline) const override;
 
-    bool onIsRasterPipelineOnly() const override { return true; }
+    bool onIsRasterPipelineOnly(const SkMatrix&) const override { return true; }
 
 private:
     const SkPoint fCenter;
diff --git a/src/shaders/gradients/SkSweepGradient.h b/src/shaders/gradients/SkSweepGradient.h
index 92d3411..b42f270 100644
--- a/src/shaders/gradients/SkSweepGradient.h
+++ b/src/shaders/gradients/SkSweepGradient.h
@@ -30,7 +30,7 @@
     void appendGradientStages(SkArenaAlloc* alloc, SkRasterPipeline* tPipeline,
                               SkRasterPipeline* postPipeline) const override;
 
-    bool onIsRasterPipelineOnly() const override { return true; }
+    bool onIsRasterPipelineOnly(const SkMatrix&) const override { return true; }
 
 private:
     const SkPoint  fCenter;
diff --git a/src/shaders/gradients/SkTwoPointConicalGradient.h b/src/shaders/gradients/SkTwoPointConicalGradient.h
index 81b3b20..408f31d 100644
--- a/src/shaders/gradients/SkTwoPointConicalGradient.h
+++ b/src/shaders/gradients/SkTwoPointConicalGradient.h
@@ -41,7 +41,7 @@
     void appendGradientStages(SkArenaAlloc* alloc, SkRasterPipeline* tPipeline,
                               SkRasterPipeline* postPipeline) const override;
 
-    bool onIsRasterPipelineOnly() const override { return true; }
+    bool onIsRasterPipelineOnly(const SkMatrix&) const override { return true; }
 
 private:
     enum class Type {