Allow LCD text to batch across colorchanges.  This will always use
color vertices, even when we can't batch across color changes

BUG=skia:

Review URL: https://codereview.chromium.org/1502253003
diff --git a/src/gpu/GrAtlasTextContext.cpp b/src/gpu/GrAtlasTextContext.cpp
index 5023857..fbbcdb6 100644
--- a/src/gpu/GrAtlasTextContext.cpp
+++ b/src/gpu/GrAtlasTextContext.cpp
@@ -1014,7 +1014,8 @@
     r.fRight = r.fLeft + SkIntToScalar(width);
     r.fBottom = r.fTop + SkIntToScalar(height);
     subRun->setMaskFormat(format);
-    blob->appendGlyph(&run, subRun, r, color, vertexStride, kA8_GrMaskFormat == format, glyph);
+    blob->appendGlyph(&run, subRun, r, color, vertexStride,
+                      kARGB_GrMaskFormat != format, glyph);
 }
 
 bool GrAtlasTextContext::dfAppendGlyph(GrAtlasTextBlob* blob, int runIndex,
@@ -1070,11 +1071,9 @@
     SkASSERT(glyph->fMaskFormat == kA8_GrMaskFormat);
     subRun->setMaskFormat(kA8_GrMaskFormat);
 
-    size_t vertexStride = GrAtlasTextBatch::GetVertexStrideDf(kA8_GrMaskFormat,
-                                                              subRun->hasUseLCDText());
+    size_t vertexStride = GrAtlasTextBatch::GetVertexStride(kA8_GrMaskFormat);
 
-    bool useColorVerts = !subRun->hasUseLCDText();
-    blob->appendGlyph(&run, subRun, glyphRect, color, vertexStride, useColorVerts, glyph);
+    blob->appendGlyph(&run, subRun, glyphRect, color, vertexStride, true, glyph);
     return true;
 }
 
diff --git a/src/gpu/batches/GrAtlasTextBatch.cpp b/src/gpu/batches/GrAtlasTextBatch.cpp
index b1ec1f8..685cddc 100644
--- a/src/gpu/batches/GrAtlasTextBatch.cpp
+++ b/src/gpu/batches/GrAtlasTextBatch.cpp
@@ -312,12 +312,10 @@
         return;
     }
 
-    bool usesDistanceFields = this->usesDistanceFields();
     GrMaskFormat maskFormat = this->maskFormat();
-    bool isLCD = this->isLCD();
 
     SkAutoTUnref<const GrGeometryProcessor> gp;
-    if (usesDistanceFields) {
+    if (this->usesDistanceFields()) {
         gp.reset(this->setupDfProcessor(this->viewMatrix(), fFilteredColor, this->color(),
                                         texture));
     } else {
@@ -333,9 +331,7 @@
     FlushInfo flushInfo;
     flushInfo.fGlyphsToFlush = 0;
     size_t vertexStride = gp->getVertexStride();
-    SkASSERT(vertexStride == (usesDistanceFields ?
-                              GetVertexStrideDf(maskFormat, isLCD) :
-                              GetVertexStride(maskFormat)));
+    SkASSERT(vertexStride == GetVertexStride(maskFormat));
 
     target->initDraw(gp, this->pipeline());
 
@@ -381,12 +377,8 @@
         bool regenerateGlyphs = info.strike()->isAbandoned();
         bool regenerateTextureCoords = info.atlasGeneration() != currentAtlasGen ||
                                        regenerateGlyphs;
-        bool regenerateColors;
-        if (usesDistanceFields) {
-            regenerateColors = !isLCD && run.fColor != args.fColor;
-        } else {
-            regenerateColors = kA8_GrMaskFormat == maskFormat && run.fColor != args.fColor;
-        }
+        bool regenerateColors = kARGB_GrMaskFormat != maskFormat &&
+                                run.fColor != args.fColor;
         bool regeneratePositions = args.fTransX != 0.f || args.fTransY != 0.f;
         int glyphCount = info.glyphCount();
 
@@ -459,9 +451,7 @@
     }
 
     if (!this->usesDistanceFields()) {
-        // TODO we can often batch across LCD text if we have dual source blending and don't
-        // have to use the blend constant
-        if (kGrayscaleCoverageMask_MaskType != fMaskType && this->color() != that->color()) {
+        if (kColorBitmapMask_MaskType == fMaskType && this->color() != that->color()) {
             return false;
         }
         if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
@@ -479,11 +469,6 @@
         if (fUseBGR != that->fUseBGR) {
             return false;
         }
-
-        // TODO see note above
-        if (kLCDDistanceField_MaskType == fMaskType && this->color() != that->color()) {
-            return false;
-        }
     }
 
     fBatch.fNumGlyphs += that->numGlyphs();
@@ -530,6 +515,7 @@
         flags |= kUseLCD_DistanceFieldEffectFlag;
         flags |= viewMatrix.rectStaysRect() ? kRectToRect_DistanceFieldEffectFlag : 0;
         flags |= fUseBGR ? kBGR_DistanceFieldEffectFlag : 0;
+        flags |= kColorAttr_DistanceFieldEffectFlag;
 
         GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor);
 
diff --git a/src/gpu/batches/GrAtlasTextBatch.h b/src/gpu/batches/GrAtlasTextBatch.h
index 11cd89e..95abbf4 100644
--- a/src/gpu/batches/GrAtlasTextBatch.h
+++ b/src/gpu/batches/GrAtlasTextBatch.h
@@ -15,11 +15,11 @@
 class GrAtlasTextBatch : public GrVertexBatch {
 public:
     DEFINE_BATCH_CLASS_ID
-    static const size_t kLCDTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16);
 
     // position + local coord
     static const size_t kColorTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16);
     static const size_t kGrayTextVASize = sizeof(SkPoint) + sizeof(GrColor) + sizeof(SkIPoint16);
+    static const size_t kLCDTextVASize = kGrayTextVASize;
     static const int kVerticesPerGlyph = GrAtlasTextBlob::kVerticesPerGlyph;
     static const int kIndicesPerGlyph = 6;
 
@@ -113,15 +113,6 @@
         }
     }
 
-    static size_t GetVertexStrideDf(GrMaskFormat maskFormat, bool useLCDText) {
-        SkASSERT(maskFormat == kA8_GrMaskFormat);
-        if (useLCDText) {
-            return kLCDTextVASize;
-        } else {
-            return kGrayTextVASize;
-        }
-    }
-
 protected:
     void computePipelineOptimizations(GrInitInvariantOutput* color, 
                                       GrInitInvariantOutput* coverage,
diff --git a/src/gpu/effects/GrBitmapTextGeoProc.cpp b/src/gpu/effects/GrBitmapTextGeoProc.cpp
index a8643b0..6fd3538 100644
--- a/src/gpu/effects/GrBitmapTextGeoProc.cpp
+++ b/src/gpu/effects/GrBitmapTextGeoProc.cpp
@@ -144,9 +144,8 @@
     this->initClassID<GrBitmapTextGeoProc>();
     fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType));
 
-    // TODO we could think about removing this attribute if color is ignored, but unfortunately
-    // we don't do text positioning in batch, so we can't quite do that yet.
-    bool hasVertexColor = kA8_GrMaskFormat == fMaskFormat;
+    bool hasVertexColor = kA8_GrMaskFormat == fMaskFormat ||
+                          kA565_GrMaskFormat == fMaskFormat;
     if (hasVertexColor) {
         fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType));
     }
diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.cpp b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
index fab9369..f6c41cb 100644
--- a/src/gpu/effects/GrDistanceFieldGeoProc.cpp
+++ b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
@@ -416,7 +416,7 @@
             pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
         }
 
-        if (dfpgp.color() != fColor) {
+        if (dfpgp.color() != fColor && !dfpgp.hasVertexColor()) {
             float c[4];
             GrColorToRGBAFloat(dfpgp.color(), c);
             pdman.set4fv(fColorUniform, 1, c);
@@ -535,7 +535,12 @@
 
         // setup pass through color
         if (!dfTexEffect.colorIgnored()) {
-            this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);
+            if (dfTexEffect.hasVertexColor()) {
+                varyingHandler->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor);
+            } else {
+                this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor,
+                                        &fColorUniform);
+            }
         }
 
         // Setup position
@@ -696,7 +701,7 @@
             pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
         }
 
-        if (dflcd.color() != fColor) {
+        if (dflcd.color() != fColor && !dflcd.hasVertexColor()) {
             float c[4];
             GrColorToRGBAFloat(dflcd.color(), c);
             pdman.set4fv(fColorUniform, 1, c);
@@ -750,6 +755,9 @@
     this->initClassID<GrDistanceFieldLCDTextGeoProc>();
     fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType,
                                                    kHigh_GrSLPrecision));
+    if (flags & kColorAttr_DistanceFieldEffectFlag) {
+        fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType));
+    }
     fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords",
                                                         kVec2s_GrVertexAttribType));
     this->addTextureAccess(&fTextureAccess);
diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.h b/src/gpu/effects/GrDistanceFieldGeoProc.h
index e17a0ce..ad14c51 100644
--- a/src/gpu/effects/GrDistanceFieldGeoProc.h
+++ b/src/gpu/effects/GrDistanceFieldGeoProc.h
@@ -35,7 +35,8 @@
     kLCD_DistanceFieldEffectMask          = kSimilarity_DistanceFieldEffectFlag |
                                             kRectToRect_DistanceFieldEffectFlag |
                                             kUseLCD_DistanceFieldEffectFlag |
-                                            kBGR_DistanceFieldEffectFlag,
+                                            kBGR_DistanceFieldEffectFlag |
+                                            kColorAttr_DistanceFieldEffectFlag,
 };
 
 /**
@@ -197,10 +198,12 @@
     const char* name() const override { return "DistanceFieldLCDTexture"; }
 
     const Attribute* inPosition() const { return fInPosition; }
+    const Attribute* inColor() const { return fInColor; }
     const Attribute* inTextureCoords() const { return fInTextureCoords; }
     DistanceAdjust getDistanceAdjust() const { return fDistanceAdjust; }
     GrColor color() const { return fColor; }
     bool colorIgnored() const { return GrColor_ILLEGAL == fColor; }
+    bool hasVertexColor() const { return SkToBool(fInColor); }
     const SkMatrix& viewMatrix() const { return fViewMatrix; }
     uint32_t getFlags() const { return fFlags; }
     bool usesLocalCoords() const { return fUsesLocalCoords; }
@@ -221,6 +224,7 @@
     DistanceAdjust   fDistanceAdjust;
     uint32_t         fFlags;
     const Attribute* fInPosition;
+    const Attribute* fInColor;
     const Attribute* fInTextureCoords;
     bool             fUsesLocalCoords;