fold params into StageRec

pre-CL before trying to add a hint-rect field to allow shaders to "optimize"
their stages for a given restriction in device space
- e.g. if the shader's intrinsic domain is contained, it won't need to tile/clamp


Bug: skia:
Change-Id: Ia2da557691da25f31e4b9e3f53c3bc6709b89083
Reviewed-on: https://skia-review.googlesource.com/40224
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: Mike Reed <reed@google.com>
diff --git a/src/core/SkDraw_vertices.cpp b/src/core/SkDraw_vertices.cpp
index 8df9946..c7d439d 100644
--- a/src/core/SkDraw_vertices.cpp
+++ b/src/core/SkDraw_vertices.cpp
@@ -86,16 +86,15 @@
     Context* onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const override {
         return nullptr;
     }
-    bool onAppendStages(SkRasterPipeline* pipeline, SkColorSpace* dstCS, SkArenaAlloc* alloc,
-                        const SkMatrix&, const SkPaint&, const SkMatrix*) const override {
-        pipeline->append(SkRasterPipeline::seed_shader);
-        pipeline->append(SkRasterPipeline::matrix_4x3, &fM43);
+    bool onAppendStages(const StageRec& rec) const override {
+        rec.fPipeline->append(SkRasterPipeline::seed_shader);
+        rec.fPipeline->append(SkRasterPipeline::matrix_4x3, &fM43);
         // In theory we should never need to clamp. However, either due to imprecision in our
         // matrix43, or the scan converter passing us pixel centers that in fact are not within
         // the triangle, we do see occasional (slightly) out-of-range values, so we add these
         // clamp stages. It would be nice to find a way to detect when these are not needed.
-        pipeline->append(SkRasterPipeline::clamp_0);
-        pipeline->append(SkRasterPipeline::clamp_a);
+        rec.fPipeline->append(SkRasterPipeline::clamp_0);
+        rec.fPipeline->append(SkRasterPipeline::clamp_a);
         return true;
     }
 
diff --git a/src/core/SkRasterPipelineBlitter.cpp b/src/core/SkRasterPipelineBlitter.cpp
index 863fb92..1444b8f 100644
--- a/src/core/SkRasterPipelineBlitter.cpp
+++ b/src/core/SkRasterPipelineBlitter.cpp
@@ -119,7 +119,7 @@
                                                is_opaque, is_constant);
     }
 
-    if (shader->appendStages(&shaderPipeline, dstCS, alloc, ctm, paint)) {
+    if (shader->appendStages({&shaderPipeline, alloc, dstCS, paint, nullptr, ctm})) {
         if (paintColor.a() != 1.0f) {
             shaderPipeline.append(SkRasterPipeline::scale_1_float,
                                   alloc->make<float>(paintColor.a()));
diff --git a/src/shaders/SkColorFilterShader.cpp b/src/shaders/SkColorFilterShader.cpp
index bacfc37..d19b8ec 100644
--- a/src/shaders/SkColorFilterShader.cpp
+++ b/src/shaders/SkColorFilterShader.cpp
@@ -39,13 +39,11 @@
     buffer.writeFlattenable(fFilter.get());
 }
 
-bool SkColorFilterShader::onAppendStages(SkRasterPipeline* pipeline, SkColorSpace* dstCS,
-                                         SkArenaAlloc* alloc, const SkMatrix& ctm,
-                                         const SkPaint& paint, const SkMatrix* localM) const {
-    if (!as_SB(fShader)->appendStages(pipeline, dstCS, alloc, ctm, paint, localM)) {
+bool SkColorFilterShader::onAppendStages(const StageRec& rec) const {
+    if (!as_SB(fShader)->appendStages(rec)) {
         return false;
     }
-    fFilter->appendStages(pipeline, dstCS, alloc, fShader->isOpaque());
+    fFilter->appendStages(rec.fPipeline, rec.fDstCS, rec.fAlloc, fShader->isOpaque());
     return true;
 }
 
diff --git a/src/shaders/SkColorFilterShader.h b/src/shaders/SkColorFilterShader.h
index 9cd199e..f69aa0d 100644
--- a/src/shaders/SkColorFilterShader.h
+++ b/src/shaders/SkColorFilterShader.h
@@ -27,8 +27,7 @@
 protected:
     void flatten(SkWriteBuffer&) const override;
     sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override;
-    bool onAppendStages(SkRasterPipeline*, SkColorSpace* dstCS, SkArenaAlloc*,
-                        const SkMatrix&, const SkPaint&, const SkMatrix* localM) const override;
+    bool onAppendStages(const StageRec&) const override;
     bool onIsRasterPipelineOnly(const SkMatrix&) const override { return true; }
 
 private:
diff --git a/src/shaders/SkColorShader.cpp b/src/shaders/SkColorShader.cpp
index 33ebc53..53bc94e 100644
--- a/src/shaders/SkColorShader.cpp
+++ b/src/shaders/SkColorShader.cpp
@@ -245,22 +245,13 @@
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-bool SkColorShader::onAppendStages(SkRasterPipeline* p,
-                                   SkColorSpace* dst,
-                                   SkArenaAlloc* scratch,
-                                   const SkMatrix&,
-                                   const SkPaint&,
-                                   const SkMatrix*) const {
-    p->append_constant_color(scratch, SkPM4f_from_SkColor(fColor, dst));
+bool SkColorShader::onAppendStages(const StageRec& rec) const {
+    rec.fPipeline->append_constant_color(rec.fAlloc, SkPM4f_from_SkColor(fColor, rec.fDstCS));
     return true;
 }
 
-bool SkColor4Shader::onAppendStages(SkRasterPipeline* p,
-                                    SkColorSpace* dst,
-                                    SkArenaAlloc* scratch,
-                                    const SkMatrix&,
-                                    const SkPaint&,
-                                    const SkMatrix*) const {
-    p->append_constant_color(scratch, to_colorspace(fColor4, fColorSpace.get(), dst).premul());
+bool SkColor4Shader::onAppendStages(const StageRec& rec) const {
+    rec.fPipeline->append_constant_color(
+                     rec.fAlloc, to_colorspace(fColor4, fColorSpace.get(), rec.fDstCS).premul());
     return true;
 }
diff --git a/src/shaders/SkColorShader.h b/src/shaders/SkColorShader.h
index 7d035f5..e545514 100644
--- a/src/shaders/SkColorShader.h
+++ b/src/shaders/SkColorShader.h
@@ -63,8 +63,7 @@
         return true;
     }
 
-    bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*,
-                        const SkMatrix& ctm, const SkPaint&, const SkMatrix*) const override;
+    bool onAppendStages(const StageRec&) const override;
 
     sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override {
         return SkShader::MakeColorShader(xformer->apply(fColor));
@@ -118,8 +117,7 @@
         *lum = fCachedByteColor;
         return true;
     }
-    bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*,
-                        const SkMatrix& ctm, const SkPaint&, const SkMatrix*) const override;
+    bool onAppendStages(const StageRec&) const override;
 
     sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override;
 
diff --git a/src/shaders/SkComposeShader.cpp b/src/shaders/SkComposeShader.cpp
index 9799a1c..0bc8c8c 100644
--- a/src/shaders/SkComposeShader.cpp
+++ b/src/shaders/SkComposeShader.cpp
@@ -84,36 +84,34 @@
 }
 #endif
 
-bool SkComposeShader::onAppendStages(SkRasterPipeline* pipeline, SkColorSpace* dstCS,
-                                     SkArenaAlloc* alloc, const SkMatrix& ctm,
-                                     const SkPaint& paint, const SkMatrix* localM) const {
+bool SkComposeShader::onAppendStages(const StageRec& rec) const {
     struct Storage {
         float   fRGBA[4 * SkJumper_kMaxStride];
         float   fAlpha;
     };
-    auto storage = alloc->make<Storage>();
+    auto storage = rec.fAlloc->make<Storage>();
 
-    if (!as_SB(fSrc)->appendStages(pipeline, dstCS, alloc, ctm, paint, localM)) {
+    if (!as_SB(fSrc)->appendStages(rec)) {
         return false;
     }
     // This outputs r,g,b,a, which we'll need later when we apply the mode, but we save it off now
     // since fShaderB will overwrite them.
-    pipeline->append(SkRasterPipeline::store_rgba, storage->fRGBA);
+    rec.fPipeline->append(SkRasterPipeline::store_rgba, storage->fRGBA);
 
-    if (!as_SB(fDst)->appendStages(pipeline, dstCS, alloc, ctm, paint, localM)) {
+    if (!as_SB(fDst)->appendStages(rec)) {
         return false;
     }
     // We now have our logical 'dst' in r,g,b,a, but we need it in dr,dg,db,da for the mode/lerp
     // so we have to shuttle them. If we had a stage the would load_into_dst, then we could
     // reverse the two shader invocations, and avoid this move...
-    pipeline->append(SkRasterPipeline::move_src_dst);
-    pipeline->append(SkRasterPipeline::load_rgba, storage->fRGBA);
+    rec.fPipeline->append(SkRasterPipeline::move_src_dst);
+    rec.fPipeline->append(SkRasterPipeline::load_rgba, storage->fRGBA);
 
     if (!this->isJustLerp()) {
-        SkBlendMode_AppendStages(fMode, pipeline);
+        SkBlendMode_AppendStages(fMode, rec.fPipeline);
     }
     if (!this->isJustMode()) {
-        pipeline->append(SkRasterPipeline::lerp_1_float, &fLerpT);
+        rec.fPipeline->append(SkRasterPipeline::lerp_1_float, &fLerpT);
     }
     return true;
 }
diff --git a/src/shaders/SkComposeShader.h b/src/shaders/SkComposeShader.h
index 34abf62..85d56cc 100644
--- a/src/shaders/SkComposeShader.h
+++ b/src/shaders/SkComposeShader.h
@@ -42,8 +42,7 @@
     SkComposeShader(SkReadBuffer&);
     void flatten(SkWriteBuffer&) const override;
     sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override;
-    bool onAppendStages(SkRasterPipeline*, SkColorSpace* dstCS, SkArenaAlloc*,
-                        const SkMatrix&, const SkPaint&, const SkMatrix* localM) const override;
+    bool onAppendStages(const StageRec&) const override;
 
     bool onIsRasterPipelineOnly(const SkMatrix&) const override { return true; }
 
diff --git a/src/shaders/SkEmptyShader.h b/src/shaders/SkEmptyShader.h
index d4809e0..b44e9a0 100644
--- a/src/shaders/SkEmptyShader.h
+++ b/src/shaders/SkEmptyShader.h
@@ -34,8 +34,7 @@
         // which will write data we don't care to serialize or decode.
     }
 
-    bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, const SkMatrix&,
-                        const SkPaint&, const SkMatrix*) const override {
+    bool onAppendStages(const StageRec&) const override {
         return false;
     }
 
diff --git a/src/shaders/SkImageShader.cpp b/src/shaders/SkImageShader.cpp
index ba6c9fa..f5756fe 100644
--- a/src/shaders/SkImageShader.cpp
+++ b/src/shaders/SkImageShader.cpp
@@ -253,20 +253,21 @@
 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
 
 
-bool SkImageShader::onAppendStages(SkRasterPipeline* p, SkColorSpace* dstCS, SkArenaAlloc* alloc,
-                                   const SkMatrix& ctm, const SkPaint& paint,
-                                   const SkMatrix* localM) const {
-    auto matrix = SkMatrix::Concat(ctm, this->getLocalMatrix());
-    if (localM) {
-        matrix.preConcat(*localM);
+bool SkImageShader::onAppendStages(const StageRec& rec) const {
+    SkRasterPipeline* p = rec.fPipeline;
+    SkArenaAlloc* alloc = rec.fAlloc;
+
+    auto matrix = SkMatrix::Concat(rec.fCTM, this->getLocalMatrix());
+    if (rec.fLocalM) {
+        matrix.preConcat(*rec.fLocalM);
     }
 
     if (!matrix.invert(&matrix)) {
         return false;
     }
-    auto quality = paint.getFilterQuality();
+    auto quality = rec.fPaint.getFilterQuality();
 
-    SkBitmapProvider provider(fImage.get(), dstCS);
+    SkBitmapProvider provider(fImage.get(), rec.fDstCS);
     SkDefaultBitmapController controller;
     std::unique_ptr<SkBitmapController::State> state {
         controller.requestBitmap(provider, matrix, quality)
@@ -308,7 +309,7 @@
     };
     auto misc = alloc->make<MiscCtx>();
     misc->state       = std::move(state);  // Extend lifetime to match the pipeline's.
-    misc->paint_color = SkColor4f_from_SkColor(paint.getColor(), dstCS);
+    misc->paint_color = SkColor4f_from_SkColor(rec.fPaint.getColor(), rec.fDstCS);
     p->append_matrix(alloc, matrix);
 
     auto gather = alloc->make<SkJumper_MemoryCtx>();
@@ -343,7 +344,7 @@
             case kRGBA_F16_SkColorType:  p->append(SkRasterPipeline::gather_f16,  gather); break;
             default: SkASSERT(false);
         }
-        if (dstCS && (!info.colorSpace() || info.gammaCloseToSRGB())) {
+        if (rec.fDstCS && (!info.colorSpace() || info.gammaCloseToSRGB())) {
             p->append_from_srgb(info.alphaType());
         }
     };
@@ -409,6 +410,6 @@
         p->append(SkRasterPipeline::clamp_0);
         p->append(SkRasterPipeline::clamp_a);
     }
-    append_gamut_transform(p, alloc, info.colorSpace(), dstCS, kPremul_SkAlphaType);
+    append_gamut_transform(p, alloc, info.colorSpace(), rec.fDstCS, kPremul_SkAlphaType);
     return true;
 }
diff --git a/src/shaders/SkImageShader.h b/src/shaders/SkImageShader.h
index 98856c9..c981b5c 100644
--- a/src/shaders/SkImageShader.h
+++ b/src/shaders/SkImageShader.h
@@ -43,8 +43,7 @@
 
     bool onIsRasterPipelineOnly(const SkMatrix& ctm) const override;
 
-    bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*,
-                        const SkMatrix& ctm, const SkPaint&, const SkMatrix*) const override;
+    bool onAppendStages(const StageRec&) const override;
 
     sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override {
         return xformer->apply(fImage.get())->makeShader(fTileModeX, fTileModeY,
diff --git a/src/shaders/SkLocalMatrixShader.cpp b/src/shaders/SkLocalMatrixShader.cpp
index 254092d..377e6f6 100644
--- a/src/shaders/SkLocalMatrixShader.cpp
+++ b/src/shaders/SkLocalMatrixShader.cpp
@@ -63,18 +63,14 @@
     return image;
 }
 
-bool SkLocalMatrixShader::onAppendStages(SkRasterPipeline* p,
-                                         SkColorSpace* dst,
-                                         SkArenaAlloc* scratch,
-                                         const SkMatrix& ctm,
-                                         const SkPaint& paint,
-                                         const SkMatrix* localM) const {
+bool SkLocalMatrixShader::onAppendStages(const StageRec& rec) const {
     SkMatrix tmp;
-    if (localM) {
-        tmp.setConcat(*localM, this->getLocalMatrix());
+    if (rec.fLocalM) {
+        tmp.setConcat(*rec.fLocalM, this->getLocalMatrix());
     }
-    return as_SB(fProxyShader)->appendStages(p, dst, scratch, ctm, paint,
-                                             localM ? &tmp : &this->getLocalMatrix());
+    StageRec newRec = rec;
+    newRec.fLocalM = rec.fLocalM ? &tmp : &this->getLocalMatrix();
+    return as_SB(fProxyShader)->appendStages(newRec);
 }
 
 #ifndef SK_IGNORE_TO_STRING
diff --git a/src/shaders/SkLocalMatrixShader.h b/src/shaders/SkLocalMatrixShader.h
index 8c8edf1..b16b243 100644
--- a/src/shaders/SkLocalMatrixShader.h
+++ b/src/shaders/SkLocalMatrixShader.h
@@ -48,8 +48,7 @@
 
     SkImage* onIsAImage(SkMatrix* matrix, TileMode* mode) const override;
 
-    bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*,
-                        const SkMatrix&, const SkPaint&, const SkMatrix*) const override;
+    bool onAppendStages(const StageRec&) const override;
 
     sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override {
         return as_SB(fProxyShader)->makeColorSpace(xformer)->makeWithLocalMatrix(
diff --git a/src/shaders/SkPictureShader.cpp b/src/shaders/SkPictureShader.cpp
index 16f5767..00985a7 100644
--- a/src/shaders/SkPictureShader.cpp
+++ b/src/shaders/SkPictureShader.cpp
@@ -296,13 +296,11 @@
                                                fTmx, fTmy, this->getLocalMatrix());
 }
 
-bool SkPictureShader::onAppendStages(SkRasterPipeline* p, SkColorSpace* cs, SkArenaAlloc* alloc,
-                                     const SkMatrix& ctm, const SkPaint& paint,
-                                     const SkMatrix* localMatrix) const {
+bool SkPictureShader::onAppendStages(const StageRec& rec) const {
     // Keep bitmapShader alive by using alloc instead of stack memory
-    auto& bitmapShader = *alloc->make<sk_sp<SkShader>>();
-    bitmapShader = this->refBitmapShader(ctm, localMatrix, cs);
-    return bitmapShader && as_SB(bitmapShader)->appendStages(p, cs, alloc, ctm, paint);
+    auto& bitmapShader = *rec.fAlloc->make<sk_sp<SkShader>>();
+    bitmapShader = this->refBitmapShader(rec.fCTM, rec.fLocalM, rec.fDstCS);
+    return bitmapShader && as_SB(bitmapShader)->appendStages(rec);
 }
 
 /////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/shaders/SkPictureShader.h b/src/shaders/SkPictureShader.h
index ee1ffb5..6b23fa3 100644
--- a/src/shaders/SkPictureShader.h
+++ b/src/shaders/SkPictureShader.h
@@ -38,8 +38,7 @@
 protected:
     SkPictureShader(SkReadBuffer&);
     void flatten(SkWriteBuffer&) const override;
-    bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*,
-                        const SkMatrix&, const SkPaint&, const SkMatrix*) const override;
+    bool onAppendStages(const StageRec&) const override;
     Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override;
     sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override;
     bool onIsRasterPipelineOnly(const SkMatrix&) const override;
diff --git a/src/shaders/SkShader.cpp b/src/shaders/SkShader.cpp
index d288054..8964388 100644
--- a/src/shaders/SkShader.cpp
+++ b/src/shaders/SkShader.cpp
@@ -201,39 +201,29 @@
 }
 #endif
 
-bool SkShaderBase::appendStages(SkRasterPipeline* p,
-                                SkColorSpace* dstCS,
-                                SkArenaAlloc* alloc,
-                                const SkMatrix& ctm,
-                                const SkPaint& paint,
-                                const SkMatrix* localM) const {
-    return this->onAppendStages(p, dstCS, alloc, ctm, paint, localM);
+bool SkShaderBase::appendStages(const StageRec& rec) const {
+    return this->onAppendStages(rec);
 }
 
-bool SkShaderBase::onAppendStages(SkRasterPipeline* p,
-                                  SkColorSpace* dstCS,
-                                  SkArenaAlloc* alloc,
-                                  const SkMatrix& ctm,
-                                  const SkPaint& paint,
-                                  const SkMatrix* localM) const {
+bool SkShaderBase::onAppendStages(const StageRec& rec) const {
     // SkShader::Context::shadeSpan4f() handles the paint opacity internally,
     // but SkRasterPipelineBlitter applies it as a separate stage.
     // We skip the internal shadeSpan4f() step by forcing the paint opaque.
-    SkTCopyOnFirstWrite<SkPaint> opaquePaint(paint);
-    if (paint.getAlpha() != SK_AlphaOPAQUE) {
+    SkTCopyOnFirstWrite<SkPaint> opaquePaint(rec.fPaint);
+    if (rec.fPaint.getAlpha() != SK_AlphaOPAQUE) {
         opaquePaint.writable()->setAlpha(SK_AlphaOPAQUE);
     }
 
-    ContextRec rec(*opaquePaint, ctm, localM, ContextRec::kPM4f_DstType, dstCS);
+    ContextRec cr(*opaquePaint, rec.fCTM, rec.fLocalM, ContextRec::kPM4f_DstType, rec.fDstCS);
 
     struct CallbackCtx : SkJumper_CallbackCtx {
         sk_sp<SkShader> shader;
         Context*        ctx;
     };
-    auto cb = alloc->make<CallbackCtx>();
-    cb->shader = dstCS ? SkColorSpaceXformer::Make(sk_ref_sp(dstCS))->apply(this)
-                       : sk_ref_sp((SkShader*)this);
-    cb->ctx = as_SB(cb->shader)->makeContext(rec, alloc);
+    auto cb = rec.fAlloc->make<CallbackCtx>();
+    cb->shader = rec.fDstCS ? SkColorSpaceXformer::Make(sk_ref_sp(rec.fDstCS))->apply(this)
+                            : sk_ref_sp((SkShader*)this);
+    cb->ctx = as_SB(cb->shader)->makeContext(cr, rec.fAlloc);
     cb->fn  = [](SkJumper_CallbackCtx* self, int active_pixels) {
         auto c = (CallbackCtx*)self;
         int x = (int)c->rgba[0],
@@ -242,8 +232,8 @@
     };
 
     if (cb->ctx) {
-        p->append(SkRasterPipeline::seed_shader);
-        p->append(SkRasterPipeline::callback, cb);
+        rec.fPipeline->append(SkRasterPipeline::seed_shader);
+        rec.fPipeline->append(SkRasterPipeline::callback, cb);
         return true;
     }
     return false;
diff --git a/src/shaders/SkShaderBase.h b/src/shaders/SkShaderBase.h
index 8f64efe..d63813c 100644
--- a/src/shaders/SkShaderBase.h
+++ b/src/shaders/SkShaderBase.h
@@ -193,9 +193,17 @@
                                     || this->onIsRasterPipelineOnly(ctm);
     }
 
+    struct StageRec {
+        SkRasterPipeline*   fPipeline;
+        SkArenaAlloc*       fAlloc;
+        SkColorSpace*       fDstCS;         // may be nullptr
+        const SkPaint&      fPaint;
+        const SkMatrix*     fLocalM;        // may be nullptr
+        SkMatrix            fCTM;
+    };
+
     // If this returns false, then we draw nothing (do not fall back to shader context)
-    bool appendStages(SkRasterPipeline*, SkColorSpace* dstCS, SkArenaAlloc*,
-                      const SkMatrix& ctm, const SkPaint&, const SkMatrix* localM=nullptr) const;
+    bool appendStages(const StageRec&) const;
 
     bool computeTotalInverse(const SkMatrix& ctm,
                              const SkMatrix* outerLocalMatrix,
@@ -245,8 +253,7 @@
     }
 
     // Default impl creates shadercontext and calls that (not very efficient)
-    virtual bool onAppendStages(SkRasterPipeline*, SkColorSpace* dstCS, SkArenaAlloc*,
-                                const SkMatrix&, const SkPaint&, const SkMatrix* localM) const;
+    virtual bool onAppendStages(const StageRec&) const;
 
     virtual bool onIsRasterPipelineOnly(const SkMatrix& ctm) const { return false; }
 
diff --git a/src/shaders/gradients/SkGradientShader.cpp b/src/shaders/gradients/SkGradientShader.cpp
index 1b24ef9..4eb68c9 100644
--- a/src/shaders/gradients/SkGradientShader.cpp
+++ b/src/shaders/gradients/SkGradientShader.cpp
@@ -364,14 +364,13 @@
     add_stop_color(ctx, stop, Fs, Bs);
 }
 
-bool SkGradientShaderBase::onAppendStages(SkRasterPipeline* p,
-                                          SkColorSpace* dstCS,
-                                          SkArenaAlloc* alloc,
-                                          const SkMatrix& ctm,
-                                          const SkPaint& paint,
-                                          const SkMatrix* localM) const {
+bool SkGradientShaderBase::onAppendStages(const StageRec& rec) const {
+    SkRasterPipeline* p = rec.fPipeline;
+    SkArenaAlloc* alloc = rec.fAlloc;
+    SkColorSpace* dstCS = rec.fDstCS;
+
     SkMatrix matrix;
-    if (!this->computeTotalInverse(ctm, localM, &matrix)) {
+    if (!this->computeTotalInverse(rec.fCTM, rec.fLocalM, &matrix)) {
         return false;
     }
     matrix.postConcat(fPtsToUnit);
@@ -405,7 +404,7 @@
     // The two-stop case with stops at 0 and 1.
     if (fColorCount == 2 && fOrigPos == nullptr) {
         const SkPM4f c_l = prepareColor(0),
-            c_r = prepareColor(1);
+                     c_r = prepareColor(1);
 
         // See F and B below.
         auto* f_and_b = alloc->makeArrayDefault<SkPM4f>(2);
diff --git a/src/shaders/gradients/SkGradientShaderPriv.h b/src/shaders/gradients/SkGradientShaderPriv.h
index 437e830..6d7c1b8 100644
--- a/src/shaders/gradients/SkGradientShaderPriv.h
+++ b/src/shaders/gradients/SkGradientShaderPriv.h
@@ -229,9 +229,7 @@
                                    SkColor* colorSrc, Rec* recSrc,
                                    int count);
 
-    bool onAppendStages(SkRasterPipeline* pipeline, SkColorSpace* dstCS, SkArenaAlloc* alloc,
-                        const SkMatrix& ctm, const SkPaint& paint,
-                        const SkMatrix* localM) const override;
+    bool onAppendStages(const StageRec&) const override;
 
     virtual void appendGradientStages(SkArenaAlloc* alloc, SkRasterPipeline* tPipeline,
                                       SkRasterPipeline* postPipeline) const = 0;