change drawAtlas to behave like drawVertices

Bug: skia:6571
Change-Id: If60c30755ec0548df0e9bdeca2f3af0bc87764ca
Reviewed-on: https://skia-review.googlesource.com/14642
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Mike Reed <reed@google.com>
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 9d38e16..f608134 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -24,6 +24,7 @@
 #include "SkTLazy.h"
 #include "SkTextBlobRunIterator.h"
 #include "SkTextToPathIter.h"
+#include "SkUtils.h"
 #include "SkVertices.h"
 
 SkBaseDevice::SkBaseDevice(const SkImageInfo& info, const SkSurfaceProps& surfaceProps)
@@ -235,36 +236,48 @@
     }
 }
 
+static SkPoint* quad_to_tris(SkPoint tris[6], const SkPoint quad[4]) {
+    tris[0] = quad[0];
+    tris[1] = quad[1];
+    tris[2] = quad[2];
+
+    tris[3] = quad[0];
+    tris[4] = quad[2];
+    tris[5] = quad[3];
+
+    return tris + 6;
+}
+
 void SkBaseDevice::drawAtlas(const SkImage* atlas, const SkRSXform xform[],
-                             const SkRect tex[], const SkColor colors[], int count,
+                             const SkRect tex[], const SkColor colors[], int quadCount,
                              SkBlendMode mode, const SkPaint& paint) {
-    SkPath path;
-    path.setIsVolatile(true);
+    const int triCount = quadCount << 1;
+    const int vertexCount = triCount * 3;
+    uint32_t flags = SkVertices::kHasTexCoords_BuilderFlag;
+    if (colors) {
+        flags |= SkVertices::kHasColors_BuilderFlag;
+    }
+    SkVertices::Builder builder(SkVertices::kTriangles_VertexMode, vertexCount, 0, flags);
 
-    for (int i = 0; i < count; ++i) {
-        SkPoint quad[4];
-        xform[i].toQuad(tex[i].width(), tex[i].height(), quad);
+    SkPoint* vPos = builder.positions();
+    SkPoint* vTex = builder.texCoords();
+    SkColor* vCol = builder.colors();
+    for (int i = 0; i < quadCount; ++i) {
+        SkPoint tmp[4];
+        xform[i].toQuad(tex[i].width(), tex[i].height(), tmp);
+        vPos = quad_to_tris(vPos, tmp);
 
-        SkMatrix localM;
-        localM.setRSXform(xform[i]);
-        localM.preTranslate(-tex[i].left(), -tex[i].top());
-
-        SkPaint pnt(paint);
-        sk_sp<SkShader> shader = atlas->makeShader(&localM);
-        if (!shader) {
-            break;
-        }
-        pnt.setShader(std::move(shader));
+        tex[i].toQuad(tmp);
+        vTex = quad_to_tris(vTex, tmp);
 
         if (colors) {
-            pnt.setColorFilter(SkColorFilter::MakeModeFilter(colors[i], (SkBlendMode)mode));
+            sk_memset32(vCol, colors[i], 6);
+            vCol += 6;
         }
-
-        path.rewind();
-        path.addPoly(quad, 4, true);
-        path.setConvexity(SkPath::kConvex_Convexity);
-        this->drawPath(path, pnt, nullptr, true);
     }
+    SkPaint p(paint);
+    p.setShader(atlas->makeShader());
+    this->drawVertices(builder.detach().get(), mode, p);
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 5d996c8..2d3178c 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1561,8 +1561,7 @@
     if (hasTexs && skPaint.getShader()) {
         if (hasColors) {
             // When there are texs and colors the shader and colors are combined using bmode.
-            return SkPaintToGrPaintWithXfermode(context, rtc, skPaint, matrix, bmode, false,
-                                                grPaint);
+            return SkPaintToGrPaintWithXfermode(context, rtc, skPaint, matrix, bmode, grPaint);
         } else {
             // We have a shader, but no colors to blend it against.
             return SkPaintToGrPaint(context, rtc, skPaint, matrix, grPaint);
@@ -1681,7 +1680,7 @@
     GrPaint grPaint;
     if (colors) {
         if (!SkPaintToGrPaintWithXfermode(this->context(), fRenderTargetContext.get(), p,
-                                          this->ctm(), (SkBlendMode)mode, true, &grPaint)) {
+                                          this->ctm(), (SkBlendMode)mode, &grPaint)) {
             return;
         }
     } else {
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 3503028..5401a10 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -428,12 +428,8 @@
 
 ////////////////////////////////////////////////////////////////////////////////////////////////
 
-static inline bool blend_requires_shader(const SkBlendMode mode, bool primitiveIsSrc) {
-    if (primitiveIsSrc) {
-        return SkBlendMode::kSrc != mode;
-    } else {
-        return SkBlendMode::kDst != mode;
-    }
+static inline bool blend_requires_shader(const SkBlendMode mode) {
+    return SkBlendMode::kDst != mode;
 }
 
 static inline bool skpaint_to_grpaint_impl(GrContext* context,
@@ -442,7 +438,6 @@
                                            const SkMatrix& viewM,
                                            sk_sp<GrFragmentProcessor>* shaderProcessor,
                                            SkBlendMode* primColorMode,
-                                           bool primitiveIsSrc,
                                            GrPaint* grPaint) {
     grPaint->setAllowSRGBInputs(rtc->isGammaCorrect());
 
@@ -453,7 +448,7 @@
     // Setup the initial color considering the shader, the SkPaint color, and the presence or not
     // of per-vertex colors.
     sk_sp<GrFragmentProcessor> shaderFP;
-    if (!primColorMode || blend_requires_shader(*primColorMode, primitiveIsSrc)) {
+    if (!primColorMode || blend_requires_shader(*primColorMode)) {
         if (shaderProcessor) {
             shaderFP = *shaderProcessor;
         } else if (const SkShader* shader = skPaint.getShader()) {
@@ -481,13 +476,9 @@
 
             GrColor4f shaderInput = origColor.opaque();
             shaderFP = GrFragmentProcessor::OverrideInput(shaderFP, shaderInput);
-            if (primitiveIsSrc) {
-                shaderFP = GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(shaderFP),
-                                                                             *primColorMode);
-            } else {
-                shaderFP = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(shaderFP),
-                                                                             *primColorMode);
-            }
+            shaderFP = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(shaderFP),
+                                                                         *primColorMode);
+
             // The above may return null if compose results in a pass through of the prim color.
             if (shaderFP) {
                 grPaint->addColorFragmentProcessor(shaderFP);
@@ -514,13 +505,8 @@
             sk_sp<GrFragmentProcessor> processor(
                 GrConstColorProcessor::Make(origColor.opaque(),
                                             GrConstColorProcessor::kIgnore_InputMode));
-            if (primitiveIsSrc) {
-                processor = GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(processor),
-                                                                              *primColorMode);
-            } else {
-                processor = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(processor),
-                                                                              *primColorMode);
-            }
+            processor = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(processor),
+                                                                          *primColorMode);
             if (processor) {
                 grPaint->addColorFragmentProcessor(std::move(processor));
             }
@@ -591,7 +577,7 @@
 
 bool SkPaintToGrPaint(GrContext* context, GrRenderTargetContext* rtc, const SkPaint& skPaint,
                       const SkMatrix& viewM, GrPaint* grPaint) {
-    return skpaint_to_grpaint_impl(context, rtc, skPaint, viewM, nullptr, nullptr, false, grPaint);
+    return skpaint_to_grpaint_impl(context, rtc, skPaint, viewM, nullptr, nullptr, grPaint);
 }
 
 /** Replaces the SkShader (if any) on skPaint with the passed in GrFragmentProcessor. */
@@ -603,7 +589,7 @@
     if (!shaderFP) {
         return false;
     }
-    return skpaint_to_grpaint_impl(context, rtc, skPaint, SkMatrix::I(), &shaderFP, nullptr, false,
+    return skpaint_to_grpaint_impl(context, rtc, skPaint, SkMatrix::I(), &shaderFP, nullptr,
                                    grPaint);
 }
 
@@ -616,7 +602,7 @@
     static sk_sp<GrFragmentProcessor> kNullShaderFP(nullptr);
     static sk_sp<GrFragmentProcessor>* kIgnoreShader = &kNullShaderFP;
     return skpaint_to_grpaint_impl(context, rtc, skPaint, SkMatrix::I(), kIgnoreShader, nullptr,
-                                   false, grPaint);
+                                   grPaint);
 }
 
 /** Blends the SkPaint's shader (or color if no shader) with a per-primitive color which must
@@ -626,10 +612,9 @@
                                   const SkPaint& skPaint,
                                   const SkMatrix& viewM,
                                   SkBlendMode primColorMode,
-                                  bool primitiveIsSrc,
                                   GrPaint* grPaint) {
     return skpaint_to_grpaint_impl(context, rtc, skPaint, viewM, nullptr, &primColorMode,
-                                   primitiveIsSrc, grPaint);
+                                   grPaint);
 }
 
 bool SkPaintToGrPaintWithTexture(GrContext* context,
diff --git a/src/gpu/SkGr.h b/src/gpu/SkGr.h
index 144a477..450f6ff 100644
--- a/src/gpu/SkGr.h
+++ b/src/gpu/SkGr.h
@@ -119,15 +119,12 @@
                                    GrPaint* grPaint);
 
 /** Blends the SkPaint's shader (or color if no shader) with the color which specified via a
-    GrOp'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. */
+    GrOp's GrPrimitiveProcesssor. */
 bool SkPaintToGrPaintWithXfermode(GrContext* context,
                                   GrRenderTargetContext* rtc,
                                   const SkPaint& skPaint,
                                   const SkMatrix& viewM,
                                   SkBlendMode primColorMode,
-                                  bool primitiveIsSrc,
                                   GrPaint* grPaint);
 
 /** This is used when there is a primitive color, but the shader should be ignored. Currently,
@@ -137,7 +134,7 @@
 inline bool SkPaintToGrPaintWithPrimitiveColor(GrContext* context, GrRenderTargetContext* rtc,
                                                const SkPaint& skPaint, GrPaint* grPaint) {
     return SkPaintToGrPaintWithXfermode(context, rtc, skPaint, SkMatrix::I(), SkBlendMode::kDst,
-                                        false, grPaint);
+                                        grPaint);
 }
 
 /** This is used when there may or may not be a shader, and the caller wants to plugin a texture