Add support for blending of LCD for all blend modes.
BUG=skia:

Review URL: https://codereview.chromium.org/1313623002
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
index 5f34f75..4c50e47 100644
--- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
@@ -31,6 +31,7 @@
         kNone_OutputType,        //<! 0
         kCoverage_OutputType,    //<! inputCoverage
         kModulate_OutputType,    //<! inputColor * inputCoverage
+        kSAModulate_OutputType,  //<! inputColor.a * inputCoverage
         kISAModulate_OutputType, //<! (1 - inputColor.a) * inputCoverage
         kISCModulate_OutputType, //<! (1 - inputColor) * inputCoverage
 
@@ -139,6 +140,15 @@
                        kAdd_GrBlendEquation, SRC_COEFF, DST_COEFF)
 
 /**
+ * Basic coeff formula similar to COEFF_FORMULA but we will make the src f*Sa. This is used in
+ * LCD dst-out.
+ */
+#define COEFF_FORMULA_SA_MODULATE(SRC_COEFF, DST_COEFF) \
+    INIT_BLEND_FORMULA(BlendFormula::kSAModulate_OutputType, \
+                       BlendFormula::kNone_OutputType, \
+                       kAdd_GrBlendEquation, SRC_COEFF, DST_COEFF)
+
+/**
  * When the coeffs are (Zero, Zero), we clear the dst. This formula has its own macro so we can set
  * the primary output type to none.
  */
@@ -289,6 +299,24 @@
     /* screen */     COEFF_FORMULA(   kOne_GrBlendCoeff,    kISC_GrBlendCoeff),
 }}};
 
+static const BlendFormula gLCDBlendTable[SkXfermode::kLastCoeffMode + 1] = {
+    /* clear */      COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType),
+    /* src */        COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kOne_GrBlendCoeff),
+    /* dst */        NO_DST_WRITE_FORMULA,
+    /* src-over */   COVERAGE_FORMULA(BlendFormula::kSAModulate_OutputType, kOne_GrBlendCoeff),
+    /* dst-over */   COEFF_FORMULA(   kIDA_GrBlendCoeff,    kOne_GrBlendCoeff),
+    /* src-in */     COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kDA_GrBlendCoeff),
+    /* dst-in */     COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISAModulate_OutputType),
+    /* src-out */    COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kIDA_GrBlendCoeff),
+    /* dst-out */    COEFF_FORMULA_SA_MODULATE(   kZero_GrBlendCoeff,   kISC_GrBlendCoeff),
+    /* src-atop */   COVERAGE_FORMULA(BlendFormula::kSAModulate_OutputType, kDA_GrBlendCoeff),
+    /* dst-atop */   COVERAGE_FORMULA(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff),
+    /* xor */        COVERAGE_FORMULA(BlendFormula::kSAModulate_OutputType, kIDA_GrBlendCoeff),
+    /* plus */       COEFF_FORMULA(   kOne_GrBlendCoeff,    kOne_GrBlendCoeff),
+    /* modulate */   COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_OutputType),
+    /* screen */     COEFF_FORMULA(   kOne_GrBlendCoeff,    kISC_GrBlendCoeff),
+};
+
 static BlendFormula get_blend_formula(const GrProcOptInfo& colorPOI,
                                       const GrProcOptInfo& coveragePOI,
                                       bool hasMixedSamples,
@@ -300,6 +328,14 @@
     return gBlendTable[colorPOI.isOpaque()][conflatesCoverage][xfermode];
 }
 
+static BlendFormula get_lcd_blend_formula(const GrProcOptInfo& coveragePOI,
+                                          SkXfermode::Mode xfermode) {
+    SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode);
+    SkASSERT(coveragePOI.isFourChannelOutput());
+
+    return gLCDBlendTable[xfermode];
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 class PorterDuffXferProcessor : public GrXferProcessor {
@@ -363,6 +399,13 @@
                 fsBuilder->codeAppendf("%s = %s;", output, inColor);
             }
             break;
+        case BlendFormula::kSAModulate_OutputType:
+            if (xp.readsCoverage()) {
+                fsBuilder->codeAppendf("%s = %s.a * %s;", output, inColor, inCoverage);
+            } else {
+                fsBuilder->codeAppendf("%s = %s;", output, inColor);
+            }
+            break;
         case BlendFormula::kISAModulate_OutputType:
             if (xp.readsCoverage()) {
                 fsBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", output, inColor, inCoverage);
@@ -444,7 +487,9 @@
         if (coveragePOI.isSolidWhite()) {
             optFlags |= GrXferProcessor::kIgnoreCoverage_OptFlag;
         }
-        if (colorPOI.allStagesMultiplyInput() && fBlendFormula.canTweakAlphaForCoverage()) {
+        if (colorPOI.allStagesMultiplyInput() &&
+            fBlendFormula.canTweakAlphaForCoverage() &&
+            !coveragePOI.isFourChannelOutput()) {
             optFlags |= GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag;
         }
     }
@@ -579,7 +624,6 @@
 private:
     void emitOutputsForBlendState(const EmitArgs& args) override {
         GrGLXPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
-
         fsBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, args.fInputColor,
                                args.fInputCoverage);
     }
@@ -684,12 +728,18 @@
                                              const GrProcOptInfo& covPOI,
                                              bool hasMixedSamples,
                                              const DstTexture* dstTexture) const {
+    BlendFormula blendFormula;
     if (covPOI.isFourChannelOutput()) {
-        SkASSERT(!dstTexture || !dstTexture->texture());
-        return PDLCDXferProcessor::Create(fXfermode, colorPOI);
+        if (SkXfermode::kSrcOver_Mode == fXfermode &&
+            kRGBA_GrColorComponentFlags == colorPOI.validFlags()) {
+            SkASSERT(!dstTexture || !dstTexture->texture());
+            return PDLCDXferProcessor::Create(fXfermode, colorPOI);
+        }
+        blendFormula = get_lcd_blend_formula(covPOI, fXfermode);
+    } else {
+        blendFormula = get_blend_formula(colorPOI, covPOI, hasMixedSamples, fXfermode);
     }
 
-    BlendFormula blendFormula = get_blend_formula(colorPOI, covPOI, hasMixedSamples, fXfermode);
     if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) {
         return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, fXfermode);
     }
@@ -698,15 +748,6 @@
     return new PorterDuffXferProcessor(blendFormula);
 }
 
-bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/,
-                                                uint32_t knownColorFlags) const {
-    if (SkXfermode::kSrcOver_Mode == fXfermode &&
-        kRGBA_GrColorComponentFlags == knownColorFlags) {
-        return true;
-    }
-    return false;
-}
-
 void GrPorterDuffXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
                                                      InvariantBlendedColor* blendedColor) const {
     // Find the blended color info based on the formula that does not have coverage.
@@ -745,8 +786,16 @@
     if (caps.shaderCaps()->dualSourceBlendingSupport()) {
         return false;
     }
+    
+    // When we have four channel coverage we always need to read the dst in order to correctly
+    // blend. The one exception is when we are using srcover mode and we know the input color into
+    // the XP.
     if (covPOI.isFourChannelOutput()) {
-        return false; // The LCD XP will abort rather than doing a dst read.
+        if (SkXfermode::kSrcOver_Mode == fXfermode &&
+            kRGBA_GrColorComponentFlags == colorPOI.validFlags()) {
+            return false;
+        }
+        return get_lcd_blend_formula(covPOI, fXfermode).hasSecondaryOutput();
     }
     // We fallback on the shader XP when the blend formula would use dual source blending but we
     // don't have support for it.