Fix drawVertices when there is a paint alpha

Review URL: https://codereview.chromium.org/1382753002
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 5289019..e2feefc 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1742,42 +1742,50 @@
 
     SkAutoSTMalloc<128, GrColor> convertedColors(0);
     if (colors) {
-        // need to convert byte order and from non-PM to PM
+        // need to convert byte order and from non-PM to PM. TODO: Keep unpremul until after
+        // interpolation.
         convertedColors.reset(vertexCount);
-        SkColor color;
         for (int i = 0; i < vertexCount; ++i) {
-            color = colors[i];
-            if (paint.getAlpha() != 255) {
-                color = SkColorSetA(color, SkMulDiv255Round(SkColorGetA(color), paint.getAlpha()));
-            }
-            /// TODO: Perform the premul after interpolating
-            convertedColors[i] = SkColorToPremulGrColor(color);
+            convertedColors[i] = SkColorToPremulGrColor(colors[i]);
         }
         colors = convertedColors.get();
     }
     GrPaint grPaint;
-    if (texs && colors && paint.getShader()) {
-        // When there are texs and colors the shader and colors are combined using xmode. A null
-        // xmode is defined to mean modulate.
-        SkXfermode::Mode colorMode;
-        if (xmode) {
-            if (!xmode->asMode(&colorMode)) {
+    if (texs && paint.getShader()) {
+        if (colors) {
+            // When there are texs and colors the shader and colors are combined using xmode. A null
+            // xmode is defined to mean modulate.
+            SkXfermode::Mode colorMode;
+            if (xmode) {
+                if (!xmode->asMode(&colorMode)) {
+                    return;
+                }
+            } else {
+                colorMode = SkXfermode::kModulate_Mode;
+            }
+            if (!SkPaintToGrPaintWithXfermode(this->context(), paint, *draw.fMatrix, colorMode,
+                                              false, &grPaint)) {
                 return;
             }
         } else {
-            colorMode = SkXfermode::kModulate_Mode;
+            // We have a shader, but no colors to blend it against.
+            if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
+                return;
+            }
         }
-        if (!SkPaintToGrPaintWithXfermode(this->context(), paint, *draw.fMatrix, colorMode, false,
-                                          &grPaint)) {
-            return;
+    } else {
+        if (colors) {
+            // We have colors, but either have no shader or no texture coords (which implies that
+            // we should ignore the shader).
+            if (!SkPaintToGrPaintWithPrimitiveColor(this->context(), paint, &grPaint)) {
+                return;
+            }
+        } else {
+            // No colors and no shaders. Just draw with the paint color.
+            if (!SkPaintToGrPaintNoShader(this->context(), paint, &grPaint)) {
+                return;
+            }
         }
-    } else if (!texs) {
-        // Defined to ignore the shader unless texs is provided.
-        if (!SkPaintToGrPaintNoShader(this->context(), paint, &grPaint)) {
-            return;
-        }
-    } else if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) {
-        return;
     }
 
     fDrawContext->drawVertices(fRenderTarget,
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index a726939..ce1ce32 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -677,6 +677,14 @@
 
 ////////////////////////////////////////////////////////////////////////////////////////////////
 
+static inline bool blend_requires_shader(const SkXfermode::Mode mode, bool primitiveIsSrc) {
+    if (primitiveIsSrc) {
+        return SkXfermode::kSrc_Mode != mode;
+    } else {
+        return SkXfermode::kDst_Mode != mode;
+    }
+}
+
 static inline bool skpaint_to_grpaint_impl(GrContext* context,
                                            const SkPaint& skPaint,
                                            const SkMatrix& viewM,
@@ -689,15 +697,18 @@
     // Setup the initial color considering the shader, the SkPaint color, and the presence or not
     // of per-vertex colors.
     SkAutoTUnref<const GrFragmentProcessor> aufp;
-    const GrFragmentProcessor* shaderFP = NULL;
-    if (shaderProcessor) {
-        shaderFP = *shaderProcessor;
-    } else if (const SkShader* shader = skPaint.getShader()) {
-        aufp.reset(shader->asFragmentProcessor(context, viewM, NULL, skPaint.getFilterQuality(),
-                                               grPaint->getProcessorDataManager()));
-        shaderFP = aufp;
-        if (!shaderFP) {
-            return false;
+    const GrFragmentProcessor* shaderFP = nullptr;
+    if (!primColorMode || blend_requires_shader(*primColorMode, primitiveIsSrc)) {
+        if (shaderProcessor) {
+            shaderFP = *shaderProcessor;
+        } else if (const SkShader* shader = skPaint.getShader()) {
+            aufp.reset(shader->asFragmentProcessor(context, viewM, nullptr,
+                                                   skPaint.getFilterQuality(),
+                                                   grPaint->getProcessorDataManager()));
+            shaderFP = aufp;
+            if (!shaderFP) {
+                return false;
+            }
         }
     }
 
@@ -761,11 +772,13 @@
                 grPaint->addColorFragmentProcessor(processor);
             }
 
-            grPaint->setColor(SkColorToUnpremulGrColor(skPaint.getColor()) | 0xFF000000);
+            grPaint->setColor(SkColorToOpaqueGrColor(skPaint.getColor()));
 
             GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
-            grPaint->addColorFragmentProcessor(GrConstColorProcessor::Create(
-                paintAlpha, GrConstColorProcessor::kModulateRGBA_InputMode))->unref();
+            if (GrColor_WHITE != paintAlpha) {
+                grPaint->addColorFragmentProcessor(GrConstColorProcessor::Create(
+                    paintAlpha, GrConstColorProcessor::kModulateRGBA_InputMode))->unref();
+            }
         } else {
             // No shader, no primitive color.
             grPaint->setColor(SkColorToPremulGrColor(skPaint.getColor()));
diff --git a/src/gpu/SkGrPriv.h b/src/gpu/SkGrPriv.h
index 25fda57..36601fc 100644
--- a/src/gpu/SkGrPriv.h
+++ b/src/gpu/SkGrPriv.h
@@ -54,19 +54,20 @@
 bool GrMakeStretchedKey(const GrUniqueKey& origKey, const SkGrStretch&, GrUniqueKey* stretchedKey);
 
 /** Converts an SkPaint to a GrPaint for a given GrContext. The matrix is required in order
-    to convert the SkShader (if any) on the SkPaint. */
+    to convert the SkShader (if any) on the SkPaint. The primitive itself has no color. */
 bool SkPaintToGrPaint(GrContext*,
                       const SkPaint& skPaint,
                       const SkMatrix& viewM,
                       GrPaint* grPaint);
 
-/** Ignores the SkShader (if any) on skPaint. */
+/** Same as above but ignores the SkShader (if any) on skPaint. */
 bool SkPaintToGrPaintNoShader(GrContext* context,
                               const SkPaint& skPaint,
                               GrPaint* grPaint);
 
 /** Replaces the SkShader (if any) on skPaint with the passed in GrFragmentProcessor. The processor
-    should expect an unpremul input color and produce a premultiplied output color. */
+    should expect an unpremul input color and produce a premultiplied output color. There is
+    no primitive color. */
 bool SkPaintToGrPaintReplaceShader(GrContext*,
                                    const SkPaint& skPaint,
                                    const GrFragmentProcessor* shaderFP,
@@ -75,8 +76,7 @@
 /** Blends the SkPaint's shader (or color if no shader) with the color which specified via a
     GrBatch's GrPrimitiveProcesssor. Currently there is a bool param to indicate whether the
     primitive color is the dst or src color to the blend in order to work around differences between
-    drawVertices and drawAtlas.
- */
+    drawVertices and drawAtlas. */
 bool SkPaintToGrPaintWithXfermode(GrContext* context,
                                   const SkPaint& skPaint,
                                   const SkMatrix& viewM,
@@ -84,6 +84,16 @@
                                   bool primitiveIsSrc,
                                   GrPaint* grPaint);
 
+/** This is used when there is a primitive color, but the shader should be ignored. Currently,
+    the expectation is that the primitive color will be premultiplied, though it really should be
+    unpremultiplied so that interpolation is done in unpremul space. The paint's alpha will be
+    applied to the primitive color after interpolation. */
+inline bool SkPaintToGrPaintWithPrimitiveColor(GrContext* context, const SkPaint& skPaint,
+                                               GrPaint* grPaint) {
+    return SkPaintToGrPaintWithXfermode(context, skPaint, SkMatrix::I(), SkXfermode::kDst_Mode,
+                                        false, grPaint);
+}
+
 bool GrTextureUsageSupported(const GrCaps&, int width, int height, SkImageUsageType);
 
 #endif