More shader preliminaries / refactoring

    - thread through ctm
    - make blitter handle paint modulation instead of each shader

TBR=herb@google.com

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4830
CQ_INCLUDE_TRYBOTS=master.client.skia:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD-Trybot

Change-Id: I8161e6b3864c4e48e4d47d5ad40a56a13c02fee8
Reviewed-on: https://skia-review.googlesource.com/4830
Reviewed-by: Mike Klein <mtklein@chromium.org>
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Mike Klein <mtklein@chromium.org>
diff --git a/src/core/SkRasterPipelineBlitter.cpp b/src/core/SkRasterPipelineBlitter.cpp
index 71267a8..0adf33a 100644
--- a/src/core/SkRasterPipelineBlitter.cpp
+++ b/src/core/SkRasterPipelineBlitter.cpp
@@ -20,7 +20,8 @@
 
 class SkRasterPipelineBlitter : public SkBlitter {
 public:
-    static SkBlitter* Create(const SkPixmap&, const SkPaint&, SkTBlitterAllocator*);
+    static SkBlitter* Create(const SkPixmap&, const SkPaint&, const SkMatrix& ctm,
+                             SkTBlitterAllocator*);
 
     SkRasterPipelineBlitter(SkPixmap dst, SkBlendMode blend, SkPM4f paintColor)
         : fDst(dst)
@@ -71,8 +72,9 @@
 
 SkBlitter* SkCreateRasterPipelineBlitter(const SkPixmap& dst,
                                          const SkPaint& paint,
+                                         const SkMatrix& ctm,
                                          SkTBlitterAllocator* alloc) {
-    return SkRasterPipelineBlitter::Create(dst, paint, alloc);
+    return SkRasterPipelineBlitter::Create(dst, paint, ctm, alloc);
 }
 
 static bool supported(const SkImageInfo& info) {
@@ -86,6 +88,7 @@
 
 SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst,
                                            const SkPaint& paint,
+                                           const SkMatrix& ctm,
                                            SkTBlitterAllocator* alloc) {
     auto blitter = alloc->createT<SkRasterPipelineBlitter>(
             dst,
@@ -114,11 +117,17 @@
     pipeline->append(SkRasterPipeline::constant_color, paintColor);
 
     if (shader) {
-        is_opaque   = is_opaque && shader->isOpaque();
-        is_constant = shader->isConstant();
-        if (!shader->appendStages(pipeline, dst.colorSpace(), &blitter->fScratchFallback)) {
+        // Shaders start with the paint color in (r,g,b,a) and dst-space (x,y) in (dr,dg).
+        // Before the shader runs, move the paint color to (dr,dg,db,da), and put (x,y) in (r,g).
+        pipeline->append(SkRasterPipeline::swap_src_dst);
+        if (!shader->appendStages(pipeline, dst.colorSpace(), &blitter->fScratchFallback, ctm)) {
             return earlyOut();
         }
+        // srcin, s' = s * da, i.e. modulate the output of the shader by the paint alpha.
+        pipeline->append(SkRasterPipeline::srcin);
+
+        is_opaque   = is_opaque && shader->isOpaque();
+        is_constant = shader->isConstant();
     }
 
     if (colorFilter) {