initial changes to add local matrix to primitive processor
authorjoshualitt <joshualitt@chromium.org>
Fri, 19 Dec 2014 21:45:20 +0000 (13:45 -0800)
committerCommit bot <commit-bot@chromium.org>
Fri, 19 Dec 2014 21:45:20 +0000 (13:45 -0800)
BUG=skia:

Review URL: https://codereview.chromium.org/820523002

22 files changed:
expectations/gm/ignored-tests.txt
gm/coloremoji.cpp
include/gpu/GrFragmentProcessor.h
include/gpu/GrPaint.h
src/gpu/GrAAConvexPathRenderer.cpp
src/gpu/GrDefaultGeoProcFactory.cpp
src/gpu/GrGeometryProcessor.cpp
src/gpu/GrGeometryProcessor.h
src/gpu/GrOptDrawState.cpp
src/gpu/GrOvalRenderer.cpp
src/gpu/GrProcessor.cpp
src/gpu/GrStencilAndCoverTextContext.cpp
src/gpu/GrStencilAndCoverTextContext.h
src/gpu/effects/GrBezierEffect.cpp
src/gpu/effects/GrBezierEffect.h
src/gpu/effects/GrBitmapTextGeoProc.cpp
src/gpu/effects/GrBitmapTextGeoProc.h
src/gpu/effects/GrDashingEffect.cpp
src/gpu/effects/GrDistanceFieldTextureEffect.cpp
src/gpu/effects/GrDistanceFieldTextureEffect.h
src/gpu/gl/GrGLProgram.cpp
src/gpu/gl/GrGLProgram.h

index ac02d05..5d2fb33 100644 (file)
@@ -48,6 +48,10 @@ dropshadowimagefilter
 # quality improvements to imagemagnifier GM
 imagemagnifier
 
+#joshualitt
+textblobshader
+coloremoji
+
 #reed
 modecolorfilters
 
index 2eab864..9782dd8 100644 (file)
@@ -8,10 +8,40 @@
 #include "gm.h"
 
 #include "Resources.h"
+#include "SkBlurImageFilter.h"
+#include "SkColorFilterImageFilter.h"
+#include "SkColorMatrixFilter.h"
 #include "SkCanvas.h"
+#include "SkGradientShader.h"
 #include "SkStream.h"
 #include "SkTypeface.h"
 
+/*
+ * Spits out a dummy gradient to test blur with shader on paint
+ */
+static SkShader* MakeLinear() {
+    static const SkPoint     kPts[] = { { 0, 0 }, { 32, 32 } };
+    static const SkScalar    kPos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
+    static const SkColor kColors[] = {0x80F00080, 0xF0F08000, 0x800080F0 };
+    return SkGradientShader::CreateLinear(kPts, kColors, kPos,
+                                          SK_ARRAY_COUNT(kColors), SkShader::kClamp_TileMode);
+}
+
+static SkImageFilter* make_grayscale(SkImageFilter* input = NULL) {
+    SkScalar matrix[20];
+    memset(matrix, 0, 20 * sizeof(SkScalar));
+    matrix[0] = matrix[5] = matrix[10] = 0.2126f;
+    matrix[1] = matrix[6] = matrix[11] = 0.7152f;
+    matrix[2] = matrix[7] = matrix[12] = 0.0722f;
+    matrix[18] = 1.0f;
+    SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix));
+    return SkColorFilterImageFilter::Create(filter, input);
+}
+
+static SkImageFilter* make_blur(float amount, SkImageFilter* input = NULL) {
+    return SkBlurImageFilter::Create(amount, amount, input);
+}
+
 namespace skiagm {
 
 class ColorEmojiGM : public GM {
@@ -40,7 +70,7 @@ protected:
     }
 
     virtual SkISize onISize() {
-        return SkISize::Make(640, 480);
+        return SkISize::Make(650, 480);
     }
 
     virtual void onDraw(SkCanvas* canvas) {
@@ -53,12 +83,42 @@ protected:
         const char* text = "hamburgerfons";
 
         // draw text at different point sizes
-        const int textSize[] = { 10, 30, 50 };
-        const int textYOffset[] = { 10, 40, 100};
+        const int textSize[] = { 10, 30, 50, };
+        const int textYOffset[] = { 10, 40, 100};
         SkASSERT(sizeof(textSize) == sizeof(textYOffset));
-        for (size_t y = 0; y < sizeof(textSize) / sizeof(int); ++y) {
+        size_t y_offset = 0;
+        for (size_t y = 0; y < sizeof(textSize) / sizeof(int); y++) {
             paint.setTextSize(SkIntToScalar(textSize[y]));
             canvas->drawText(text, strlen(text), 10, SkIntToScalar(textYOffset[y]), paint);
+            y_offset += textYOffset[y];
+        }
+
+        // draw with shaders and image filters
+        for (int i = 0; i < 2; i++) {
+            for (int j = 0; j < 2; j++) {
+                for (int k = 0; k < 2; k++) {
+                    SkPaint shaderPaint;
+                    shaderPaint.setTypeface(fTypeface);
+                    if (SkToBool(i)) {
+                        shaderPaint.setShader(MakeLinear());
+                    }
+
+                    if (SkToBool(j) && SkToBool(k)) {
+                        SkAutoTUnref<SkImageFilter> grayScale(make_grayscale(NULL));
+                        SkAutoTUnref<SkImageFilter> blur(make_blur(3.0f, grayScale));
+                        shaderPaint.setImageFilter(blur);
+                    } else if (SkToBool(j)) {
+                        SkAutoTUnref<SkImageFilter> blur(make_blur(3.0f, NULL));
+                        shaderPaint.setImageFilter(blur);
+                    } else if (SkToBool(k)) {
+                        SkAutoTUnref<SkImageFilter> grayScale(make_grayscale(NULL));
+                        shaderPaint.setImageFilter(grayScale);
+                    }
+                    shaderPaint.setTextSize(30);
+                    canvas->drawText(text, strlen(text), 380, SkIntToScalar(y_offset), shaderPaint);
+                    y_offset += 32;
+                }
+            }
         }
 
         // setup work needed to draw text with different clips
index 0c15599..fe6e6fa 100644 (file)
@@ -25,7 +25,8 @@ public:
     GrFragmentProcessor()
         : INHERITED()
         , fWillReadDstColor(false)
-        , fWillUseInputColor(true) {}
+        , fWillUseInputColor(true)
+        , fUsesLocalCoords(false) {}
 
     /** Implemented using GLFragmentProcessor::GenKey as described in this class's comment. */
     virtual void getGLProcessorKey(const GrGLCaps& caps,
@@ -52,6 +53,9 @@ public:
     /** Will this prceossor read the source color value? */
     bool willUseInputColor() const { return fWillUseInputColor; }
 
+    /** Do any of the coordtransforms for this processor require local coords? */
+    bool usesLocalCoords() const { return fUsesLocalCoords; }
+
     /** Returns true if this and other processor conservatively draw identically. It can only return
         true when the two processor are of the same subclass (i.e. they return the same object from
         from getFactory()).
@@ -130,6 +134,7 @@ private:
     SkSTArray<4, const GrCoordTransform*, true>  fCoordTransforms;
     bool                                         fWillReadDstColor;
     bool                                         fWillUseInputColor;
+    bool                                         fUsesLocalCoords;
 
     typedef GrProcessor INHERITED;
 };
index 41b838c..d60b47f 100644 (file)
@@ -151,15 +151,6 @@ public:
      * DO NOT USE THESE
      * TODO Remove remaining use cases and delete these
      */
-    void localCoordChange(const SkMatrix& oldToNew) {
-        for (int i = 0; i < fColorStages.count(); ++i) {
-            fColorStages[i].localCoordChange(oldToNew);
-        }
-        for (int i = 0; i < fCoverageStages.count(); ++i) {
-            fCoverageStages[i].localCoordChange(oldToNew);
-        }
-    }
-
     bool localCoordChangeInverse(const SkMatrix& newToOld) {
         SkMatrix oldToNew;
         bool computed = false;
index 93e2b37..311010f 100644 (file)
@@ -610,12 +610,17 @@ public:
     void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE {
         BatchTracker* local = bt->cast<BatchTracker>();
         local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+        local->fUsesLocalCoords = init.fUsesLocalCoords;
     }
 
-    bool onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const SK_OVERRIDE {
+    bool onCanMakeEqual(const GrBatchTracker& m,
+                        const GrGeometryProcessor& that,
+                        const GrBatchTracker& t) const SK_OVERRIDE {
         const BatchTracker& mine = m.cast<BatchTracker>();
         const BatchTracker& theirs = t.cast<BatchTracker>();
-        return CanCombineOutput(mine.fInputColorType, mine.fColor,
+        return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+                                       that, theirs.fUsesLocalCoords) &&
+               CanCombineOutput(mine.fInputColorType, mine.fColor,
                                 theirs.fInputColorType, theirs.fColor);
     }
 
@@ -637,6 +642,7 @@ private:
     struct BatchTracker {
         GrGPInput fInputColorType;
         GrColor fColor;
+        bool fUsesLocalCoords;
     };
 
     const GrAttribute* fInPosition;
index f7b85ee..a74565c 100644 (file)
@@ -52,12 +52,18 @@ public:
         } else {
             local->fInputCoverageType = kIgnored_GrGPInput;
         }
+
+        local->fUsesLocalCoords = init.fUsesLocalCoords;
     }
 
-    bool onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const SK_OVERRIDE {
+    bool onCanMakeEqual(const GrBatchTracker& m,
+                        const GrGeometryProcessor& that,
+                        const GrBatchTracker& t) const SK_OVERRIDE {
         const BatchTracker& mine = m.cast<BatchTracker>();
         const BatchTracker& theirs = t.cast<BatchTracker>();
-        return CanCombineOutput(mine.fInputColorType, mine.fColor,
+        return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+                                       that, theirs.fUsesLocalCoords) &&
+               CanCombineOutput(mine.fInputColorType, mine.fColor,
                                 theirs.fInputColorType, theirs.fColor) &&
                CanCombineOutput(mine.fInputCoverageType, mine.fCoverage,
                                 theirs.fInputCoverageType, theirs.fCoverage);
@@ -205,6 +211,7 @@ private:
         GrGPInput fInputCoverageType;
         GrColor  fColor;
         GrColor  fCoverage;
+        bool fUsesLocalCoords;
     };
 
     const GrAttribute* fInPosition;
index 5d9cdaf..d47f687 100644 (file)
@@ -62,6 +62,7 @@ struct PathBatchTracker {
     GrGPInput fInputColorType;
     GrGPInput fInputCoverageType;
     GrColor fColor;
+    bool fUsesLocalCoords;
 };
 
 class GrGLPathProcessor : public GrGLGeometryProcessor {
@@ -118,7 +119,9 @@ private:
     typedef GrGLGeometryProcessor INHERITED;
 };
 
-GrPathProcessor::GrPathProcessor(GrColor color) : fColor(color) {
+GrPathProcessor::GrPathProcessor(GrColor color, const SkMatrix& localMatrix)
+    : INHERITED(localMatrix)
+    , fColor(color) {
     this->initClassID<GrPathProcessor>();
 }
 
@@ -142,6 +145,7 @@ void GrPathProcessor::initBatchTracker(GrBatchTracker* bt, const InitBT& init) c
     }
 
     local->fInputCoverageType = init.fCoverageIgnored ? kIgnored_GrGPInput : kAllOnes_GrGPInput;
+    local->fUsesLocalCoords = init.fUsesLocalCoords;
 }
 
 bool GrPathProcessor::canMakeEqual(const GrBatchTracker& m,
@@ -153,7 +157,9 @@ bool GrPathProcessor::canMakeEqual(const GrBatchTracker& m,
 
     const PathBatchTracker& mine = m.cast<PathBatchTracker>();
     const PathBatchTracker& theirs = t.cast<PathBatchTracker>();
-    return CanCombineOutput(mine.fInputColorType, mine.fColor,
+    return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+                                   that, theirs.fUsesLocalCoords) &&
+           CanCombineOutput(mine.fInputColorType, mine.fColor,
                             theirs.fInputColorType, theirs.fColor) &&
            CanCombineOutput(mine.fInputCoverageType, 0xff,
                             theirs.fInputCoverageType, 0xff);
index f3ec0b5..fb2300e 100644 (file)
@@ -90,6 +90,10 @@ enum GrGPInput {
  */
 class GrPrimitiveProcessor : public GrProcessor {
 public:
+    // TODO let the PrimProc itself set this in its setData call, this should really live on the
+    // bundle of primitive data
+    const SkMatrix& localMatrix() const { return fLocalMatrix; }
+
     /*
      * This struct allows the optstate to communicate requirements to the GrPrimitiveProcessor.
      */
@@ -97,6 +101,7 @@ public:
         bool fColorIgnored;
         bool fCoverageIgnored;
         GrColor fOverrideColor;
+        bool fUsesLocalCoords;
     };
 
     virtual void initBatchTracker(GrBatchTracker*, const InitBT&) const = 0;
@@ -130,6 +135,8 @@ public:
     virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const = 0;
 
 protected:
+    GrPrimitiveProcessor(const SkMatrix& localMatrix) : fLocalMatrix(localMatrix) {}
+
     /*
      * CanCombineOutput will return true if two draws are 'batchable' from a color perspective.
      * TODO remove this when GPs can upgrade to attribute color
@@ -146,7 +153,23 @@ protected:
         return true;
     }
 
+    static bool CanCombineLocalMatrices(const GrPrimitiveProcessor& left,
+                                        bool leftUsesLocalCoords,
+                                        const GrPrimitiveProcessor& right,
+                                        bool rightUsesLocalCoords) {
+        if (leftUsesLocalCoords != rightUsesLocalCoords) {
+            return false;
+        }
+
+        if (leftUsesLocalCoords && !left.localMatrix().cheapEqualTo(right.localMatrix())) {
+            return false;
+        }
+        return true;
+    }
+
 private:
+    SkMatrix fLocalMatrix;
+
     typedef GrProcessor INHERITED;
 };
 
@@ -161,8 +184,11 @@ class GrGeometryProcessor : public GrPrimitiveProcessor {
 public:
     // TODO the Hint can be handled in a much more clean way when we have deferred geometry or
     // atleast bundles
-    GrGeometryProcessor(GrColor color, bool opaqueVertexColors = false)
-        : fVertexStride(0)
+    GrGeometryProcessor(GrColor color,
+                        bool opaqueVertexColors = false,
+                        const SkMatrix& localMatrix = SkMatrix::I())
+        : INHERITED(localMatrix)
+        , fVertexStride(0)
         , fColor(color)
         , fOpaqueVertexColors(opaqueVertexColors)
         , fWillUseGeoShader(false)
@@ -223,7 +249,7 @@ public:
             return false;
         }
 
-        return this->onCanMakeEqual(mine, theirs);
+        return this->onCanMakeEqual(mine, other, theirs);
     }
 
     
@@ -293,7 +319,9 @@ protected:
     virtual void onGetInvariantOutputCoverage(GrInitInvariantOutput*) const = 0;
 
 private:
-    virtual bool onCanMakeEqual(const GrBatchTracker& mine, const GrBatchTracker& theirs) const = 0;
+    virtual bool onCanMakeEqual(const GrBatchTracker& mine,
+                                const GrGeometryProcessor& that,
+                                const GrBatchTracker& theirs) const = 0;
     // TODO delete this when we have more advanced equality testing via bundles and the BT
     virtual bool onIsEqual(const GrGeometryProcessor&) const = 0;
 
@@ -305,7 +333,7 @@ private:
     bool fHasVertexColor;
     bool fHasLocalCoords;
 
-    typedef GrProcessor INHERITED;
+    typedef GrPrimitiveProcessor INHERITED;
 };
 
 /*
@@ -314,8 +342,8 @@ private:
  */
 class GrPathProcessor : public GrPrimitiveProcessor {
 public:
-    static GrPathProcessor* Create(GrColor color) {
-        return SkNEW_ARGS(GrPathProcessor, (color));
+    static GrPathProcessor* Create(GrColor color, const SkMatrix& localMatrix = SkMatrix::I()) {
+        return SkNEW_ARGS(GrPathProcessor, (color, localMatrix));
     }
     
     void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
@@ -338,9 +366,9 @@ public:
     virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
 
 private:
-    GrPathProcessor(GrColor color);
+    GrPathProcessor(GrColor color, const SkMatrix& localMatrix);
     GrColor fColor;
 
-    typedef GrProcessor INHERITED;
+    typedef GrPrimitiveProcessor INHERITED;
 };
 #endif
index d12cf0c..95d5984 100644 (file)
@@ -110,11 +110,15 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
 
     fDescInfo.fRequiresLocalCoordAttrib = hasLocalCoords;
 
+    bool usesLocalCoords = false;
+
     // Copy Stages from DS to ODS
     for (int i = firstColorStageIdx; i < drawState.numColorStages(); ++i) {
         SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
                                GrPendingFragmentStage,
                                (drawState.fColorStages[i], hasLocalCoords));
+        usesLocalCoords = usesLocalCoords ||
+                          drawState.fColorStages[i].getProcessor()->usesLocalCoords();
     }
 
     fNumColorStages = fFragmentStages.count();
@@ -122,6 +126,8 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
         SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
                                GrPendingFragmentStage,
                                (drawState.fCoverageStages[i], hasLocalCoords));
+        usesLocalCoords = usesLocalCoords ||
+                          drawState.fCoverageStages[i].getProcessor()->usesLocalCoords();
     }
 
     // let the GP init the batch tracker
@@ -129,6 +135,7 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
     init.fColorIgnored = SkToBool(optFlags & GrXferProcessor::kIgnoreColor_OptFlag);
     init.fOverrideColor = init.fColorIgnored ? GrColor_ILLEGAL : overrideColor;
     init.fCoverageIgnored = SkToBool(optFlags & GrXferProcessor::kIgnoreCoverage_OptFlag);
+    init.fUsesLocalCoords = usesLocalCoords;
     fPrimitiveProcessor->initBatchTracker(&fBatchTracker, init);
 }
 
index 4e0fed9..304d6d6 100644 (file)
@@ -157,13 +157,17 @@ public:
     void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE {
         BatchTracker* local = bt->cast<BatchTracker>();
         local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
-
+        local->fUsesLocalCoords = init.fUsesLocalCoords;
     }
 
-    bool onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const SK_OVERRIDE {
+    bool onCanMakeEqual(const GrBatchTracker& m,
+                        const GrGeometryProcessor& that,
+                        const GrBatchTracker& t) const SK_OVERRIDE {
         const BatchTracker& mine = m.cast<BatchTracker>();
         const BatchTracker& theirs = t.cast<BatchTracker>();
-        return CanCombineOutput(mine.fInputColorType, mine.fColor,
+        return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+                                       that, theirs.fUsesLocalCoords) &&
+               CanCombineOutput(mine.fInputColorType, mine.fColor,
                                 theirs.fInputColorType, theirs.fColor);
     }
 
@@ -188,6 +192,7 @@ private:
     struct BatchTracker {
         GrGPInput fInputColorType;
         GrColor fColor;
+        bool fUsesLocalCoords;
     };
 
     const GrAttribute* fInPosition;
@@ -336,12 +341,17 @@ public:
     void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE {
         BatchTracker* local = bt->cast<BatchTracker>();
         local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+        local->fUsesLocalCoords = init.fUsesLocalCoords;
     }
 
-    bool onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const SK_OVERRIDE {
+    bool onCanMakeEqual(const GrBatchTracker& m,
+                        const GrGeometryProcessor& that,
+                        const GrBatchTracker& t) const SK_OVERRIDE {
         const BatchTracker& mine = m.cast<BatchTracker>();
         const BatchTracker& theirs = t.cast<BatchTracker>();
-        return CanCombineOutput(mine.fInputColorType, mine.fColor,
+        return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+                                       that, theirs.fUsesLocalCoords) &&
+               CanCombineOutput(mine.fInputColorType, mine.fColor,
                                 theirs.fInputColorType, theirs.fColor);
     }
 
@@ -368,6 +378,7 @@ private:
     struct BatchTracker {
         GrGPInput fInputColorType;
         GrColor fColor;
+        bool fUsesLocalCoords;
     };
 
     const GrAttribute* fInPosition;
@@ -534,12 +545,17 @@ public:
     void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE {
         BatchTracker* local = bt->cast<BatchTracker>();
         local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+        local->fUsesLocalCoords = init.fUsesLocalCoords;
     }
 
-    bool onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const SK_OVERRIDE {
+    bool onCanMakeEqual(const GrBatchTracker& m,
+                        const GrGeometryProcessor& that,
+                        const GrBatchTracker& t) const SK_OVERRIDE {
         const BatchTracker& mine = m.cast<BatchTracker>();
         const BatchTracker& theirs = t.cast<BatchTracker>();
-        return CanCombineOutput(mine.fInputColorType, mine.fColor,
+        return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+                                       that, theirs.fUsesLocalCoords) &&
+               CanCombineOutput(mine.fInputColorType, mine.fColor,
                                 theirs.fInputColorType, theirs.fColor);
     }
 
@@ -566,6 +582,7 @@ private:
     struct BatchTracker {
         GrGPInput fInputColorType;
         GrColor fColor;
+        bool fUsesLocalCoords;
     };
 
     const GrAttribute* fInPosition;
index 4f27404..6699b52 100644 (file)
@@ -149,6 +149,7 @@ bool GrProcessor::hasSameTextureAccesses(const GrProcessor& that) const {
 
 void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) {
     fCoordTransforms.push_back(transform);
+    fUsesLocalCoords = fUsesLocalCoords || transform->sourceCoords() == kLocal_GrCoordSet;
     SkDEBUGCODE(transform->setInProcessor();)
 }
 
index 7cda4f9..b5ab523 100644 (file)
@@ -234,6 +234,7 @@ void GrStencilAndCoverTextContext::init(const GrPaint& paint,
 
     fContextInitialMatrix = viewMatrix;
     fViewMatrix = viewMatrix;
+    fLocalMatrix = SkMatrix::I();
 
     const bool otherBackendsWillDrawAsPaths =
         SkDraw::ShouldDrawTextAsPaths(skPaint, fContextInitialMatrix);
@@ -262,7 +263,10 @@ void GrStencilAndCoverTextContext::init(const GrPaint& paint,
         // the paint preConcats the inverse.
         m = fContextInitialMatrix;
         m.postScale(1, -1);
-        fPaint.localCoordChangeInverse(m);
+        if (!m.invert(&fLocalMatrix)) {
+            SkDebugf("Not invertible!\n");
+            return;
+        }
 
         fGlyphCache = fSkPaint.detachCache(&fDeviceProperties, &fContextInitialMatrix,
                                            true /*ignoreGamma*/);
@@ -331,8 +335,8 @@ void GrStencilAndCoverTextContext::init(const GrPaint& paint,
         SkMatrix textMatrix;
         // Glyphs loaded by GPU path rendering have an inverted y-direction.
         textMatrix.setScale(fTextRatio, -fTextRatio);
-        fPaint.localCoordChange(textMatrix);
         fViewMatrix.preConcat(textMatrix);
+        fLocalMatrix = textMatrix;
 
         fGlyphCache = fSkPaint.detachCache(&fDeviceProperties, NULL, true /*ignoreGamma*/);
         fGlyphs = canUseRawPaths ?
@@ -402,7 +406,7 @@ static const SkScalar* get_xy_scalar_array(const SkPoint* pointArray) {
 
 void GrStencilAndCoverTextContext::flush() {
     if (fQueuedGlyphCount > 0) {
-        SkAutoTUnref<GrPathProcessor> pp(GrPathProcessor::Create(fPaint.getColor()));
+        SkAutoTUnref<GrPathProcessor> pp(GrPathProcessor::Create(fPaint.getColor(), fLocalMatrix));
         fDrawTarget->drawPaths(&fDrawState, pp, fGlyphs,
                                fGlyphIndices, GrPathRange::kU16_PathIndexType,
                                get_xy_scalar_array(fGlyphPositions),
@@ -426,7 +430,6 @@ void GrStencilAndCoverTextContext::flush() {
 
         SkMatrix inverse;
         if (this->mapToFallbackContext(&inverse)) {
-            paintFallback.localCoordChangeInverse(inverse);
             inverse.mapPoints(&fGlyphPositions[fFallbackGlyphsIdx], fallbackGlyphCount);
         }
 
index f053e2e..89c94eb 100644 (file)
@@ -64,6 +64,7 @@ private:
     int                             fFallbackGlyphsIdx;
     SkMatrix                        fContextInitialMatrix;
     SkMatrix                        fViewMatrix;
+    SkMatrix                        fLocalMatrix;
     bool                            fUsingDeviceSpaceGlyphs;
 
     GrStencilAndCoverTextContext(GrContext*, const SkDeviceProperties&);
index be1fef7..2a4ef36 100644 (file)
@@ -16,6 +16,7 @@ struct ConicBatchTracker {
     GrGPInput fInputColorType;
     GrColor fColor;
     uint8_t fCoverageScale;
+    bool fUsesLocalCoords;
 };
 
 class GrGLConicEffect : public GrGLGeometryProcessor {
@@ -198,12 +199,17 @@ void GrConicEffect::initBatchTracker(GrBatchTracker* bt, const InitBT& init) con
     ConicBatchTracker* local = bt->cast<ConicBatchTracker>();
     local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
     local->fCoverageScale = fCoverageScale;
+    local->fUsesLocalCoords = init.fUsesLocalCoords;
 }
 
-bool GrConicEffect::onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const {
+bool GrConicEffect::onCanMakeEqual(const GrBatchTracker& m,
+                                   const GrGeometryProcessor& that,
+                                   const GrBatchTracker& t) const {
     const ConicBatchTracker& mine = m.cast<ConicBatchTracker>();
     const ConicBatchTracker& theirs = t.cast<ConicBatchTracker>();
-    return CanCombineOutput(mine.fInputColorType, mine.fColor,
+    return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+                                   that, theirs.fUsesLocalCoords) &&
+           CanCombineOutput(mine.fInputColorType, mine.fColor,
                             theirs.fInputColorType, theirs.fColor) &&
            mine.fCoverageScale == theirs.fCoverageScale;
 }
@@ -233,6 +239,7 @@ struct QuadBatchTracker {
     GrGPInput fInputColorType;
     GrColor fColor;
     uint8_t fCoverageScale;
+    bool fUsesLocalCoords;
 };
 
 class GrGLQuadEffect : public GrGLGeometryProcessor {
@@ -401,12 +408,17 @@ void GrQuadEffect::initBatchTracker(GrBatchTracker* bt, const InitBT& init) cons
     QuadBatchTracker* local = bt->cast<QuadBatchTracker>();
     local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
     local->fCoverageScale = fCoverageScale;
+    local->fUsesLocalCoords = init.fUsesLocalCoords;
 }
 
-bool GrQuadEffect::onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const {
+bool GrQuadEffect::onCanMakeEqual(const GrBatchTracker& m,
+                                  const GrGeometryProcessor& that,
+                                  const GrBatchTracker& t) const {
     const QuadBatchTracker& mine = m.cast<QuadBatchTracker>();
     const QuadBatchTracker& theirs = t.cast<QuadBatchTracker>();
-    return CanCombineOutput(mine.fInputColorType, mine.fColor,
+    return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+                                   that, theirs.fUsesLocalCoords) &&
+           CanCombineOutput(mine.fInputColorType, mine.fColor,
                             theirs.fInputColorType, theirs.fColor) &&
            mine.fCoverageScale == theirs.fCoverageScale;
 }
@@ -435,6 +447,7 @@ GrGeometryProcessor* GrQuadEffect::TestCreate(SkRandom* random,
 struct CubicBatchTracker {
     GrGPInput fInputColorType;
     GrColor fColor;
+    bool fUsesLocalCoords;
 };
 
 class GrGLCubicEffect : public GrGLGeometryProcessor {
@@ -625,12 +638,17 @@ bool GrCubicEffect::onIsEqual(const GrGeometryProcessor& other) const {
 void GrCubicEffect::initBatchTracker(GrBatchTracker* bt, const InitBT& init) const {
     CubicBatchTracker* local = bt->cast<CubicBatchTracker>();
     local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+    local->fUsesLocalCoords = init.fUsesLocalCoords;
 }
 
-bool GrCubicEffect::onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const {
+bool GrCubicEffect::onCanMakeEqual(const GrBatchTracker& m,
+                                   const GrGeometryProcessor& that,
+                                   const GrBatchTracker& t) const {
     const CubicBatchTracker& mine = m.cast<CubicBatchTracker>();
     const CubicBatchTracker& theirs = t.cast<CubicBatchTracker>();
-    return CanCombineOutput(mine.fInputColorType, mine.fColor,
+    return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+                                   that, theirs.fUsesLocalCoords) &&
+           CanCombineOutput(mine.fInputColorType, mine.fColor,
                             theirs.fInputColorType, theirs.fColor);
 }
 
index a58211b..5954ee3 100644 (file)
@@ -98,7 +98,9 @@ public:
     virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
 
     void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
-    bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+    bool onCanMakeEqual(const GrBatchTracker&,
+                        const GrGeometryProcessor&,
+                        const GrBatchTracker&) const SK_OVERRIDE;
 
 private:
     GrConicEffect(GrColor, uint8_t coverage, GrPrimitiveEdgeType);
@@ -171,7 +173,9 @@ public:
     virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
 
     void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
-    bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+    bool onCanMakeEqual(const GrBatchTracker&,
+                        const GrGeometryProcessor&,
+                        const GrBatchTracker&) const SK_OVERRIDE;
 
 private:
     GrQuadEffect(GrColor, uint8_t coverage, GrPrimitiveEdgeType);
@@ -245,7 +249,9 @@ public:
     virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
 
     void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
-    bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+    bool onCanMakeEqual(const GrBatchTracker&,
+                        const GrGeometryProcessor&,
+                        const GrBatchTracker&) const SK_OVERRIDE;
 
 private:
     GrCubicEffect(GrColor, GrPrimitiveEdgeType);
index 1b393f3..09eee1c 100644 (file)
@@ -17,6 +17,7 @@
 struct BitmapTextBatchTracker {
     GrGPInput fInputColorType;
     GrColor fColor;
+    bool fUsesLocalCoords;
 };
 
 class GrGLBitmapTextGeoProc : public GrGLGeometryProcessor {
@@ -134,12 +135,17 @@ void GrBitmapTextGeoProc::initBatchTracker(GrBatchTracker* bt, const InitBT& ini
     BitmapTextBatchTracker* local = bt->cast<BitmapTextBatchTracker>();
     local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init,
                                                SkToBool(fInColor));
+    local->fUsesLocalCoords = init.fUsesLocalCoords;
 }
 
-bool GrBitmapTextGeoProc::onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const {
+bool GrBitmapTextGeoProc::onCanMakeEqual(const GrBatchTracker& m,
+                                         const GrGeometryProcessor& that,
+                                         const GrBatchTracker& t) const {
     const BitmapTextBatchTracker& mine = m.cast<BitmapTextBatchTracker>();
     const BitmapTextBatchTracker& theirs = t.cast<BitmapTextBatchTracker>();
-    return CanCombineOutput(mine.fInputColorType, mine.fColor,
+    return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+                                   that, theirs.fUsesLocalCoords) &&
+           CanCombineOutput(mine.fInputColorType, mine.fColor,
                             theirs.fInputColorType, theirs.fColor);
 }
 
index 4234570..507515b 100644 (file)
@@ -41,7 +41,9 @@ public:
     virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
 
     void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
-    bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+    bool onCanMakeEqual(const GrBatchTracker&,
+                        const GrGeometryProcessor&,
+                        const GrBatchTracker&) const SK_OVERRIDE;
 
 private:
     GrBitmapTextGeoProc(GrColor, GrTexture* texture, const GrTextureParams& params,
index 69e40eb..35b7637 100644 (file)
@@ -445,6 +445,7 @@ class GLDashingCircleEffect;
 struct DashingCircleBatchTracker {
     GrGPInput fInputColorType;
     GrColor fColor;
+    bool fUsesLocalCoords;
 };
 
 /*
@@ -489,7 +490,9 @@ public:
 
     void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE;
 
-    bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+    bool onCanMakeEqual(const GrBatchTracker&,
+                        const GrGeometryProcessor&,
+                        const GrBatchTracker&) const SK_OVERRIDE;
 
 private:
     DashingCircleEffect(GrColor, GrPrimitiveEdgeType edgeType, const DashInfo& info,
@@ -679,12 +682,17 @@ bool DashingCircleEffect::onIsEqual(const GrGeometryProcessor& other) const {
 void DashingCircleEffect::initBatchTracker(GrBatchTracker* bt, const InitBT& init) const {
     DashingCircleBatchTracker* local = bt->cast<DashingCircleBatchTracker>();
     local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+    local->fUsesLocalCoords = init.fUsesLocalCoords;
 }
 
-bool DashingCircleEffect::onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const {
+bool DashingCircleEffect::onCanMakeEqual(const GrBatchTracker& m,
+                                         const GrGeometryProcessor& that,
+                                         const GrBatchTracker& t) const {
     const DashingCircleBatchTracker& mine = m.cast<DashingCircleBatchTracker>();
     const DashingCircleBatchTracker& theirs = t.cast<DashingCircleBatchTracker>();
-    return CanCombineOutput(mine.fInputColorType, mine.fColor,
+    return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+                                   that, theirs.fUsesLocalCoords) &&
+           CanCombineOutput(mine.fInputColorType, mine.fColor,
                             theirs.fInputColorType, theirs.fColor);
 }
 
@@ -715,6 +723,7 @@ class GLDashingLineEffect;
 struct DashingLineBatchTracker {
     GrGPInput fInputColorType;
     GrColor  fColor;
+    bool fUsesLocalCoords;
 };
 
 /*
@@ -757,7 +766,9 @@ public:
 
     void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE;
 
-    bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+    bool onCanMakeEqual(const GrBatchTracker&,
+                        const GrGeometryProcessor&,
+                        const GrBatchTracker&) const SK_OVERRIDE;
 
 private:
     DashingLineEffect(GrColor, GrPrimitiveEdgeType edgeType, const DashInfo& info,
@@ -960,12 +971,17 @@ bool DashingLineEffect::onIsEqual(const GrGeometryProcessor& other) const {
 void DashingLineEffect::initBatchTracker(GrBatchTracker* bt, const InitBT& init) const {
     DashingLineBatchTracker* local = bt->cast<DashingLineBatchTracker>();
     local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+    local->fUsesLocalCoords = init.fUsesLocalCoords;
 }
 
-bool DashingLineEffect::onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const {
+bool DashingLineEffect::onCanMakeEqual(const GrBatchTracker& m,
+                                       const GrGeometryProcessor& that,
+                                       const GrBatchTracker& t) const {
     const DashingLineBatchTracker& mine = m.cast<DashingLineBatchTracker>();
     const DashingLineBatchTracker& theirs = t.cast<DashingLineBatchTracker>();
-    return CanCombineOutput(mine.fInputColorType, mine.fColor,
+    return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+                                  that, theirs.fUsesLocalCoords) &&
+           CanCombineOutput(mine.fInputColorType, mine.fColor,
                             theirs.fInputColorType, theirs.fColor);
 }
 
index cc0a800..0f930af 100755 (executable)
@@ -21,6 +21,7 @@
 struct DistanceFieldBatchTracker {
     GrGPInput fInputColorType;
     GrColor fColor;
+    bool fUsesLocalCoords;
 };
 
 class GrGLDistanceFieldTextureEffect : public GrGLGeometryProcessor {
@@ -242,13 +243,17 @@ void GrDistanceFieldTextureEffect::initBatchTracker(GrBatchTracker* bt, const In
     DistanceFieldBatchTracker* local = bt->cast<DistanceFieldBatchTracker>();
     local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init,
                                                SkToBool(fInColor));
+    local->fUsesLocalCoords = init.fUsesLocalCoords;
 }
 
 bool GrDistanceFieldTextureEffect::onCanMakeEqual(const GrBatchTracker& m,
+                                                  const GrGeometryProcessor& that,
                                                   const GrBatchTracker& t) const {
     const DistanceFieldBatchTracker& mine = m.cast<DistanceFieldBatchTracker>();
     const DistanceFieldBatchTracker& theirs = t.cast<DistanceFieldBatchTracker>();
-    return CanCombineOutput(mine.fInputColorType, mine.fColor,
+    return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+                                   that, theirs.fUsesLocalCoords) &&
+           CanCombineOutput(mine.fInputColorType, mine.fColor,
                             theirs.fInputColorType, theirs.fColor);
 }
 
@@ -297,6 +302,7 @@ GrGeometryProcessor* GrDistanceFieldTextureEffect::TestCreate(SkRandom* random,
 struct DistanceFieldNoGammaBatchTracker {
     GrGPInput fInputColorType;
     GrColor fColor;
+    bool fUsesLocalCoords;
 };
 
 class GrGLDistanceFieldNoGammaTextureEffect : public GrGLGeometryProcessor {
@@ -479,13 +485,17 @@ void GrDistanceFieldNoGammaTextureEffect::initBatchTracker(GrBatchTracker* bt,
     DistanceFieldNoGammaBatchTracker* local = bt->cast<DistanceFieldNoGammaBatchTracker>();
     local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init,
                                                SkToBool(fInColor));
+    local->fUsesLocalCoords = init.fUsesLocalCoords;
 }
 
 bool GrDistanceFieldNoGammaTextureEffect::onCanMakeEqual(const GrBatchTracker& m,
+                                                         const GrGeometryProcessor& that,
                                                          const GrBatchTracker& t) const {
     const DistanceFieldNoGammaBatchTracker& mine = m.cast<DistanceFieldNoGammaBatchTracker>();
     const DistanceFieldNoGammaBatchTracker& theirs = t.cast<DistanceFieldNoGammaBatchTracker>();
-    return CanCombineOutput(mine.fInputColorType, mine.fColor,
+    return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+                                   that, theirs.fUsesLocalCoords) &&
+           CanCombineOutput(mine.fInputColorType, mine.fColor,
                             theirs.fInputColorType, theirs.fColor);
 }
 
@@ -521,6 +531,7 @@ GrGeometryProcessor* GrDistanceFieldNoGammaTextureEffect::TestCreate(SkRandom* r
 struct DistanceFieldLCDBatchTracker {
     GrGPInput fInputColorType;
     GrColor fColor;
+    bool fUsesLocalCoords;
 };
 
 class GrGLDistanceFieldLCDTextureEffect : public GrGLGeometryProcessor {
@@ -776,13 +787,17 @@ void GrDistanceFieldLCDTextureEffect::initBatchTracker(GrBatchTracker* bt,
                                                        const InitBT& init) const {
     DistanceFieldLCDBatchTracker* local = bt->cast<DistanceFieldLCDBatchTracker>();
     local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+    local->fUsesLocalCoords = init.fUsesLocalCoords;
 }
 
 bool GrDistanceFieldLCDTextureEffect::onCanMakeEqual(const GrBatchTracker& m,
+                                                     const GrGeometryProcessor& that,
                                                      const GrBatchTracker& t) const {
     const DistanceFieldLCDBatchTracker& mine = m.cast<DistanceFieldLCDBatchTracker>();
     const DistanceFieldLCDBatchTracker& theirs = t.cast<DistanceFieldLCDBatchTracker>();
-    return CanCombineOutput(mine.fInputColorType, mine.fColor,
+    return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
+                                   that, theirs.fUsesLocalCoords) &&
+           CanCombineOutput(mine.fInputColorType, mine.fColor,
                             theirs.fInputColorType, theirs.fColor);
 }
 
index 5650cfc..7acd279 100644 (file)
@@ -81,7 +81,9 @@ public:
 
     void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE;
 
-    bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+    bool onCanMakeEqual(const GrBatchTracker&,
+                        const GrGeometryProcessor&,
+                        const GrBatchTracker&) const SK_OVERRIDE;
 
 private:
     GrDistanceFieldTextureEffect(GrColor, GrTexture* texture, const GrTextureParams& params,
@@ -141,7 +143,9 @@ public:
 
     void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE;
 
-    bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+    bool onCanMakeEqual(const GrBatchTracker&,
+                        const GrGeometryProcessor&,
+                        const GrBatchTracker&) const SK_OVERRIDE;
 
 private:
     GrDistanceFieldNoGammaTextureEffect(GrColor, GrTexture* texture, const GrTextureParams& params,
@@ -194,7 +198,9 @@ public:
 
     void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE;
 
-    bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+    bool onCanMakeEqual(const GrBatchTracker&,
+                        const GrGeometryProcessor&,
+                        const GrBatchTracker&) const SK_OVERRIDE;
 
 private:
     GrDistanceFieldLCDTextureEffect(GrColor, GrTexture* texture, const GrTextureParams& params,
index f8770b3..9bf91fc 100644 (file)
 /**
  * Retrieves the final matrix that a transform needs to apply to its source coords.
  */
-static SkMatrix get_transform_matrix(const GrPendingFragmentStage& stage, int transformIdx) {
+static SkMatrix get_transform_matrix(const GrPendingFragmentStage& stage,
+                                     int transformIdx,
+                                     const SkMatrix& localMatrix) {
     const GrCoordTransform& coordTransform = stage.getProcessor()->coordTransform(transformIdx);
     SkMatrix combined;
 
     if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
         // If we have explicit local coords or are in device coords then we shouldn't need a coord
         // change.
-        const SkMatrix& ccm = stage.getCoordChangeMatrix();
-        combined.setConcat(coordTransform.getMatrix(), ccm);
+        // TODO shortly we will get rid of coord change matrices entirely, and the PrimProc will
+        // always have a local matrix, often Identity, which can be used to transform coord
+        // transforms.  Until we actually do this, we need some way for a PrimProc to say 'use my
+        // matrix' instead of the coord change mechanism.  Temporarily, we have overloaded
+        // The identity matrix to be this value, ie if a primproc has an identity matrix for a
+        // local matrix then use the coord change matrix, otherwise use the matrix on the primproc
+        if (localMatrix.isIdentity()) {
+            const SkMatrix& ccm = stage.getCoordChangeMatrix();
+            combined.setConcat(coordTransform.getMatrix(), ccm);
+        } else {
+            combined.setConcat(coordTransform.getMatrix(), localMatrix);
+        }
     } else {
         combined = coordTransform.getMatrix();
     }
@@ -180,18 +192,20 @@ void GrGLProgram::setFragmentData(const GrOptDrawState& optState) {
         const GrPendingFragmentStage& stage = optState.getFragmentStage(e);
         const GrProcessor& processor = *stage.getProcessor();
         fFragmentProcessors->fProcs[e]->fGLProc->setData(fProgramDataManager, processor);
-        this->setTransformData(stage, fFragmentProcessors->fProcs[e]);
+        const SkMatrix& localMatrix = optState.getPrimitiveProcessor()->localMatrix();
+        this->setTransformData(stage, localMatrix, fFragmentProcessors->fProcs[e]);
         this->bindTextures(fFragmentProcessors->fProcs[e], processor);
     }
 }
 void GrGLProgram::setTransformData(const GrPendingFragmentStage& processor,
+                                   const SkMatrix& localMatrix,
                                    GrGLInstalledFragProc* ip) {
     SkTArray<GrGLInstalledFragProc::Transform, true>& transforms = ip->fTransforms;
     int numTransforms = transforms.count();
     SkASSERT(numTransforms == processor.getProcessor()->numTransforms());
     for (int t = 0; t < numTransforms; ++t) {
         SkASSERT(transforms[t].fHandle.isValid());
-        const SkMatrix& matrix = get_transform_matrix(processor, t);
+        const SkMatrix& matrix = get_transform_matrix(processor, t, localMatrix);
         if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
             fProgramDataManager.setSkMatrix(transforms[t].fHandle.convertToUniformHandle(), matrix);
             transforms[t].fCurrentValue = matrix;
@@ -291,13 +305,14 @@ void GrGLNvprProgram::didSetData(GrGpu::DrawType drawType) {
 }
 
 void GrGLNvprProgram::setTransformData(const GrPendingFragmentStage& proc,
+                                       const SkMatrix& localMatrix,
                                        GrGLInstalledFragProc* ip) {
     SkTArray<GrGLInstalledFragProc::Transform, true>& transforms = ip->fTransforms;
     int numTransforms = transforms.count();
     SkASSERT(numTransforms == proc.getProcessor()->numTransforms());
     for (int t = 0; t < numTransforms; ++t) {
         SkASSERT(transforms[t].fHandle.isValid());
-        const SkMatrix& transform = get_transform_matrix(proc, t);
+        const SkMatrix& transform = get_transform_matrix(proc, t, localMatrix);
         if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
             continue;
         }
@@ -335,12 +350,13 @@ void GrGLLegacyNvprProgram::didSetData(GrGpu::DrawType drawType) {
 
 void
 GrGLLegacyNvprProgram::setTransformData(const GrPendingFragmentStage& proc,
+                                        const SkMatrix& localMatrix,
                                         GrGLInstalledFragProc* ip) {
     // We've hidden the texcoord index in the first entry of the transforms array for each effect
     int texCoordIndex = ip->fTransforms[0].fHandle.handle();
     int numTransforms = proc.getProcessor()->numTransforms();
     for (int t = 0; t < numTransforms; ++t) {
-        const SkMatrix& transform = get_transform_matrix(proc, t);
+        const SkMatrix& transform = get_transform_matrix(proc, t, localMatrix);
         GrGLPathRendering::PathTexGenComponents components =
                 GrGLPathRendering::kST_PathTexGenComponents;
         if (proc.isPerspectiveCoordTransform(t)) {
index 09dd4aa..3ee71b8 100644 (file)
@@ -150,7 +150,9 @@ protected:
 
     // A templated helper to loop over effects, set the transforms(via subclass) and bind textures
     void setFragmentData(const GrOptDrawState&);
-    virtual void setTransformData(const GrPendingFragmentStage&, GrGLInstalledFragProc*);
+    virtual void setTransformData(const GrPendingFragmentStage&,
+                                  const SkMatrix& localMatrix,
+                                  GrGLInstalledFragProc*);
     void bindTextures(const GrGLInstalledProc*, const GrProcessor&);
 
     /*
@@ -225,6 +227,7 @@ private:
                     const SeparableVaryingInfoArray& separableVaryings);
     virtual void didSetData(GrGpu::DrawType) SK_OVERRIDE;
     virtual void setTransformData(const GrPendingFragmentStage&,
+                                  const SkMatrix& localMatrix,
                                   GrGLInstalledFragProc*) SK_OVERRIDE;
 
     struct Varying {
@@ -256,6 +259,7 @@ private:
                           int texCoordSetCnt);
     virtual void didSetData(GrGpu::DrawType) SK_OVERRIDE;
     virtual void setTransformData(const GrPendingFragmentStage&,
+                                  const SkMatrix& localMatrix,
                                   GrGLInstalledFragProc*) SK_OVERRIDE;
 
     int fTexCoordSetCnt;