Add effect caching to distance field text.

This also is a step towards unifying GrDistanceFieldTextureEffect and GrDistanceFieldLCDTextureEffect.

Committed: https://skia.googlesource.com/skia/+/137bac067306c5446bc4f9797bedc3bbaf302822

R=robertphillips@google.com

Author: jvanverth@google.com

Review URL: https://codereview.chromium.org/424103002
diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp
index 0ef596a..32d8f0c 100755
--- a/src/gpu/GrDistanceFieldTextContext.cpp
+++ b/src/gpu/GrDistanceFieldTextContext.cpp
@@ -66,7 +66,10 @@
     fGammaTexture = NULL;
 
     fCurrVertex = 0;
-
+    fEffectTextureUniqueID = SK_InvalidUniqueID;
+    fEffectColor = GrColor_ILLEGAL;
+    fEffectFlags = 0;
+                                                        
     fVertices = NULL;
 }
 
@@ -111,6 +114,58 @@
     return GrColorPackRGBA(r, g, b, 0xff);
 }
 
+void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColor) {
+    GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode);
+    GrTextureParams gammaParams(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode);
+    
+    GrTexture* currTexture = fStrike->getTexture();
+    SkASSERT(currTexture);
+    uint32_t textureUniqueID = currTexture->getUniqueID();
+    
+    // set up any flags
+    uint32_t flags = 0;
+    flags |= fContext->getMatrix().isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0;
+    flags |= fUseLCDText ? kUseLCD_DistanceFieldEffectFlag : 0;
+    flags |= fUseLCDText && fContext->getMatrix().rectStaysRect() ?
+    kRectToRect_DistanceFieldEffectFlag : 0;
+    bool useBGR = SkDeviceProperties::Geometry::kBGR_Layout ==
+    fDeviceProperties.fGeometry.getLayout();
+    flags |= fUseLCDText && useBGR ? kBGR_DistanceFieldEffectFlag : 0;
+    
+    // see if we need to create a new effect
+    if (textureUniqueID != fEffectTextureUniqueID ||
+        filteredColor != fEffectColor ||
+        flags != fEffectFlags) {
+        if (fUseLCDText) {
+            GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor);
+            fCachedEffect.reset(GrDistanceFieldLCDTextureEffect::Create(currTexture,
+                                                                        params,
+                                                                        fGammaTexture,
+                                                                        gammaParams,
+                                                                        colorNoPreMul,
+                                                                        flags));
+        } else {
+#ifdef SK_GAMMA_APPLY_TO_A8
+            U8CPU lum = SkColorSpaceLuminance::computeLuminance(fDeviceProperties.fGamma,
+                                                                filteredColor);
+            fCachedEffect.reset(GrDistanceFieldTextureEffect::Create(currTexture,
+                                                                     params,
+                                                                     fGammaTexture,
+                                                                     gammaParams,
+                                                                     lum/255.f,
+                                                                     flags));
+#else
+            fCachedEffect.reset(GrDistanceFieldTextureEffect::Create(currTexture,
+                                                                     params, flags));
+#endif
+        }
+        fEffectTextureUniqueID = textureUniqueID;
+        fEffectColor = filteredColor;
+        fEffectFlags = flags;
+    }
+    
+}
+
 void GrDistanceFieldTextContext::flushGlyphs() {
     if (NULL == fDrawTarget) {
         return;
@@ -123,14 +178,8 @@
     if (fCurrVertex > 0) {
         // setup our sampler state for our text texture/atlas
         SkASSERT(SkIsAlign4(fCurrVertex));
-        GrTexture* currTexture = fStrike->getTexture();
-        SkASSERT(currTexture);
-        GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode);
-        GrTextureParams gammaParams(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode);
 
-        // Effects could be stored with one of the cache objects (atlas?)
-        int coordsIdx = drawState->hasColorVertexAttribute() ? kGlyphCoordsWithColorAttributeIndex :
-                                                               kGlyphCoordsNoColorAttributeIndex;
+        // get our current color
         SkColor filteredColor;
         SkColorFilter* colorFilter = fSkPaint.getColorFilter();
         if (NULL != colorFilter) {
@@ -138,21 +187,16 @@
         } else {
             filteredColor = fSkPaint.getColor();
         }
+        this->setupCoverageEffect(filteredColor);
+       
+        // Effects could be stored with one of the cache objects (atlas?)
+        int coordsIdx = drawState->hasColorVertexAttribute() ? kGlyphCoordsWithColorAttributeIndex :
+                                                               kGlyphCoordsNoColorAttributeIndex;
+        drawState->addCoverageEffect(fCachedEffect.get(), coordsIdx);
+        
+        // Set draw state
         if (fUseLCDText) {
             GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor);
-            bool useBGR = SkDeviceProperties::Geometry::kBGR_Layout ==
-                                                            fDeviceProperties.fGeometry.getLayout();
-            drawState->addCoverageEffect(GrDistanceFieldLCDTextureEffect::Create(
-                                                            currTexture,
-                                                            params,
-                                                            fGammaTexture,
-                                                            gammaParams,
-                                                            colorNoPreMul,
-                                                            fContext->getMatrix().rectStaysRect() &&
-                                                            fContext->getMatrix().isSimilarity(),
-                                                            useBGR),
-                                         coordsIdx)->unref();
-
             if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
                 kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
                 fPaint.numColorStages()) {
@@ -170,21 +214,6 @@
             drawState->setBlendConstant(colorNoPreMul);
             drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
         } else {
-#ifdef SK_GAMMA_APPLY_TO_A8
-            U8CPU lum = SkColorSpaceLuminance::computeLuminance(fDeviceProperties.fGamma,
-                                                                filteredColor);
-            drawState->addCoverageEffect(GrDistanceFieldTextureEffect::Create(
-                                                              currTexture, params,
-                                                              fGammaTexture, gammaParams,
-                                                              lum/255.f,
-                                                              fContext->getMatrix().isSimilarity()),
-                                         coordsIdx)->unref();
-#else
-            drawState->addCoverageEffect(GrDistanceFieldTextureEffect::Create(
-                                                              currTexture, params,
-                                                              fContext->getMatrix().isSimilarity()),
-                                         coordsIdx)->unref();
-#endif
             // set back to normal in case we took LCD path previously.
             drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
             //drawState->setColor(fPaint.getColor());