Make SkGpuDevice::drawVertices perform color byte order swap and premul step using vertex shader.

Change-Id: I8153ba8c6bb48d8b15d524fbfafbe3c6d83f39c5
Reviewed-on: https://skia-review.googlesource.com/7727
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/ops/GrAAConvexPathRenderer.cpp b/src/gpu/ops/GrAAConvexPathRenderer.cpp
index a279a8c..f39902f 100644
--- a/src/gpu/ops/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAAConvexPathRenderer.cpp
@@ -717,7 +717,8 @@
     }
     LocalCoords::Type localCoordsType =
             usesLocalCoords ? LocalCoords::kUsePosition_Type : LocalCoords::kUnused_Type;
-    return MakeForDeviceSpace(Color::kAttribute_Type, coverageType, localCoordsType, viewMatrix);
+    return MakeForDeviceSpace(Color::kPremulGrColorAttribute_Type, coverageType, localCoordsType,
+                              viewMatrix);
 }
 
 class AAConvexPathOp final : public GrMeshDrawOp {
diff --git a/src/gpu/ops/GrAAFillRectOp.cpp b/src/gpu/ops/GrAAFillRectOp.cpp
index 5c585bf..a0fc9f0 100644
--- a/src/gpu/ops/GrAAFillRectOp.cpp
+++ b/src/gpu/ops/GrAAFillRectOp.cpp
@@ -211,7 +211,7 @@
     void onPrepareDraws(Target* target) const override {
         using namespace GrDefaultGeoProcFactory;
 
-        Color color(Color::kAttribute_Type);
+        Color color(Color::kPremulGrColorAttribute_Type);
         Coverage::Type coverageType;
         if (fCanTweakAlphaForCoverage) {
             coverageType = Coverage::kSolid_Type;
diff --git a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
index caa086e..fd09d91 100644
--- a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
@@ -114,7 +114,8 @@
     }
     LocalCoords::Type localCoordsType =
             usesLocalCoords ? LocalCoords::kUsePosition_Type : LocalCoords::kUnused_Type;
-    return MakeForDeviceSpace(Color::kAttribute_Type, coverageType, localCoordsType, viewMatrix);
+    return MakeForDeviceSpace(Color::kPremulGrColorAttribute_Type, coverageType, localCoordsType,
+                              viewMatrix);
 }
 
 class AAFlatteningConvexPathOp final : public GrMeshDrawOp {
diff --git a/src/gpu/ops/GrAAStrokeRectOp.cpp b/src/gpu/ops/GrAAStrokeRectOp.cpp
index 8a5fec1..b05e722 100644
--- a/src/gpu/ops/GrAAStrokeRectOp.cpp
+++ b/src/gpu/ops/GrAAStrokeRectOp.cpp
@@ -105,7 +105,8 @@
     }
     LocalCoords::Type localCoordsType =
             usesLocalCoords ? LocalCoords::kUsePosition_Type : LocalCoords::kUnused_Type;
-    return MakeForDeviceSpace(Color::kAttribute_Type, coverageType, localCoordsType, viewMatrix);
+    return MakeForDeviceSpace(Color::kPremulGrColorAttribute_Type, coverageType, localCoordsType,
+                              viewMatrix);
 }
 
 class AAStrokeRectOp final : public GrMeshDrawOp {
diff --git a/src/gpu/ops/GrDrawAtlasOp.cpp b/src/gpu/ops/GrDrawAtlasOp.cpp
index c9dffe6..4d78a7d 100644
--- a/src/gpu/ops/GrDrawAtlasOp.cpp
+++ b/src/gpu/ops/GrDrawAtlasOp.cpp
@@ -35,7 +35,7 @@
     using namespace GrDefaultGeoProcFactory;
     Color gpColor(color);
     if (hasColors) {
-        gpColor.fType = Color::kAttribute_Type;
+        gpColor.fType = Color::kPremulGrColorAttribute_Type;
     }
 
     return GrDefaultGeoProcFactory::Make(gpColor, Coverage::kSolid_Type,
diff --git a/src/gpu/ops/GrDrawVerticesOp.cpp b/src/gpu/ops/GrDrawVerticesOp.cpp
index ed2c072..3448249 100644
--- a/src/gpu/ops/GrDrawVerticesOp.cpp
+++ b/src/gpu/ops/GrDrawVerticesOp.cpp
@@ -11,10 +11,12 @@
 #include "GrInvariantOutput.h"
 #include "GrOpFlushState.h"
 
-static sk_sp<GrGeometryProcessor> set_vertex_attributes(bool hasLocalCoords,
-                                                        int* colorOffset,
-                                                        int* texOffset,
-                                                        const SkMatrix& viewMatrix) {
+static sk_sp<GrGeometryProcessor> set_vertex_attributes(
+        bool hasLocalCoords,
+        int* colorOffset,
+        GrRenderTargetContext::ColorArrayType colorArrayType,
+        int* texOffset,
+        const SkMatrix& viewMatrix) {
     using namespace GrDefaultGeoProcFactory;
     *texOffset = -1;
     *colorOffset = -1;
@@ -23,17 +25,22 @@
             hasLocalCoords ? LocalCoords::kHasExplicit_Type : LocalCoords::kUsePosition_Type;
     *colorOffset = sizeof(SkPoint);
     if (hasLocalCoords) {
-        *texOffset = sizeof(SkPoint) + sizeof(GrColor);
+        *texOffset = sizeof(SkPoint) + sizeof(uint32_t);
     }
-    return GrDefaultGeoProcFactory::Make(Color::kAttribute_Type, Coverage::kSolid_Type,
-                                         localCoordsType, viewMatrix);
+    Color::Type colorType =
+            (colorArrayType == GrRenderTargetContext::ColorArrayType::kPremulGrColor)
+                    ? Color::kPremulGrColorAttribute_Type
+                    : Color::kUnpremulSkColorAttribute_Type;
+    return GrDefaultGeoProcFactory::Make(colorType, Coverage::kSolid_Type, localCoordsType,
+                                         viewMatrix);
 }
 
 GrDrawVerticesOp::GrDrawVerticesOp(GrColor color, GrPrimitiveType primitiveType,
                                    const SkMatrix& viewMatrix, const SkPoint* positions,
                                    int vertexCount, const uint16_t* indices, int indexCount,
-                                   const GrColor* colors, const SkPoint* localCoords,
-                                   const SkRect& bounds)
+                                   const uint32_t* colors, const SkPoint* localCoords,
+                                   const SkRect& bounds,
+                                   GrRenderTargetContext::ColorArrayType colorArrayType)
         : INHERITED(ClassID()) {
     SkASSERT(positions);
 
@@ -49,8 +56,12 @@
     if (colors) {
         fVariableColor = true;
         mesh.fColors.append(vertexCount, colors);
+        fColorArrayType = colorArrayType;
     } else {
         fVariableColor = false;
+        // When we tessellate we will fill a color array with the GrColor value passed above as
+        // 'color'.
+        fColorArrayType = GrRenderTargetContext::ColorArrayType::kPremulGrColor;
     }
 
     if (localCoords) {
@@ -85,6 +96,7 @@
         fMeshes[0].fColor = overrideColor;
         fMeshes[0].fColors.reset();
         fVariableColor = false;
+        fColorArrayType = GrRenderTargetContext::ColorArrayType::kPremulGrColor;
     }
     if (!optimizations.readsLocalCoords()) {
         fMeshes[0].fLocalCoords.reset();
@@ -94,12 +106,12 @@
 void GrDrawVerticesOp::onPrepareDraws(Target* target) const {
     bool hasLocalCoords = !fMeshes[0].fLocalCoords.isEmpty();
     int colorOffset = -1, texOffset = -1;
-    sk_sp<GrGeometryProcessor> gp(
-            set_vertex_attributes(hasLocalCoords, &colorOffset, &texOffset, fViewMatrix));
+    sk_sp<GrGeometryProcessor> gp(set_vertex_attributes(hasLocalCoords, &colorOffset,
+                                                        fColorArrayType, &texOffset, fViewMatrix));
     size_t vertexStride = gp->getVertexStride();
 
     SkASSERT(vertexStride ==
-             sizeof(SkPoint) + (hasLocalCoords ? sizeof(SkPoint) : 0) + sizeof(GrColor));
+             sizeof(SkPoint) + (hasLocalCoords ? sizeof(SkPoint) : 0) + sizeof(uint32_t));
 
     int instanceCount = fMeshes.count();
 
@@ -141,9 +153,9 @@
         for (int j = 0; j < mesh.fPositions.count(); ++j) {
             *((SkPoint*)verts) = mesh.fPositions[j];
             if (mesh.fColors.isEmpty()) {
-                *(GrColor*)((intptr_t)verts + colorOffset) = mesh.fColor;
+                *(uint32_t*)((intptr_t)verts + colorOffset) = mesh.fColor;
             } else {
-                *(GrColor*)((intptr_t)verts + colorOffset) = mesh.fColors[j];
+                *(uint32_t*)((intptr_t)verts + colorOffset) = mesh.fColors[j];
             }
             if (hasLocalCoords) {
                 *(SkPoint*)((intptr_t)verts + texOffset) = mesh.fLocalCoords[j];
@@ -189,6 +201,10 @@
         return false;
     }
 
+    if (fColorArrayType != that->fColorArrayType) {
+        return false;
+    }
+
     if (!fVariableColor) {
         if (that->fVariableColor || that->fMeshes[0].fColor != fMeshes[0].fColor) {
             fVariableColor = true;
@@ -251,8 +267,8 @@
 static void randomize_params(size_t count, size_t maxVertex, SkScalar min, SkScalar max,
                              SkRandom* random, SkTArray<SkPoint>* positions,
                              SkTArray<SkPoint>* texCoords, bool hasTexCoords,
-                             SkTArray<GrColor>* colors, bool hasColors, SkTArray<uint16_t>* indices,
-                             bool hasIndices) {
+                             SkTArray<uint32_t>* colors, bool hasColors,
+                             SkTArray<uint16_t>* indices, bool hasIndices) {
     for (uint32_t v = 0; v < count; v++) {
         positions->push_back(random_point(random, min, max));
         if (hasTexCoords) {
@@ -275,7 +291,7 @@
     // TODO make 'sensible' indexbuffers
     SkTArray<SkPoint> positions;
     SkTArray<SkPoint> texCoords;
-    SkTArray<GrColor> colors;
+    SkTArray<uint32_t> colors;
     SkTArray<uint16_t> indices;
 
     bool hasTexCoords = random->nextBool();
@@ -296,6 +312,9 @@
                          hasIndices);
     }
 
+    GrRenderTargetContext::ColorArrayType colorArrayType =
+            random->nextBool() ? GrRenderTargetContext::ColorArrayType::kPremulGrColor
+                               : GrRenderTargetContext::ColorArrayType::kSkColor;
     SkMatrix viewMatrix = GrTest::TestMatrix(random);
     SkRect bounds;
     SkDEBUGCODE(bool result =) bounds.setBoundsCheck(positions.begin(), vertexCount);
@@ -306,7 +325,7 @@
     GrColor color = GrRandomColor(random);
     return GrDrawVerticesOp::Make(color, type, viewMatrix, positions.begin(), vertexCount,
                                   indices.begin(), hasIndices ? vertexCount : 0, colors.begin(),
-                                  texCoords.begin(), bounds);
+                                  texCoords.begin(), bounds, colorArrayType);
 }
 
 #endif
diff --git a/src/gpu/ops/GrDrawVerticesOp.h b/src/gpu/ops/GrDrawVerticesOp.h
index 680b41f..38b1a47 100644
--- a/src/gpu/ops/GrDrawVerticesOp.h
+++ b/src/gpu/ops/GrDrawVerticesOp.h
@@ -10,6 +10,7 @@
 
 #include "GrColor.h"
 #include "GrMeshDrawOp.h"
+#include "GrRenderTargetContext.h"
 #include "GrTypes.h"
 #include "SkMatrix.h"
 #include "SkRect.h"
@@ -25,11 +26,12 @@
     static std::unique_ptr<GrDrawOp> Make(GrColor color, GrPrimitiveType primitiveType,
                                           const SkMatrix& viewMatrix, const SkPoint* positions,
                                           int vertexCount, const uint16_t* indices, int indexCount,
-                                          const GrColor* colors, const SkPoint* localCoords,
-                                          const SkRect& bounds) {
-        return std::unique_ptr<GrDrawOp>(
-                new GrDrawVerticesOp(color, primitiveType, viewMatrix, positions, vertexCount,
-                                     indices, indexCount, colors, localCoords, bounds));
+                                          const uint32_t* colors, const SkPoint* localCoords,
+                                          const SkRect& bounds,
+                                          GrRenderTargetContext::ColorArrayType colorArrayType) {
+        return std::unique_ptr<GrDrawOp>(new GrDrawVerticesOp(
+                color, primitiveType, viewMatrix, positions, vertexCount, indices, indexCount,
+                colors, localCoords, bounds, colorArrayType));
     }
 
     const char* name() const override { return "DrawVerticesOp"; }
@@ -46,8 +48,8 @@
 private:
     GrDrawVerticesOp(GrColor color, GrPrimitiveType primitiveType, const SkMatrix& viewMatrix,
                      const SkPoint* positions, int vertexCount, const uint16_t* indices,
-                     int indexCount, const GrColor* colors, const SkPoint* localCoords,
-                     const SkRect& bounds);
+                     int indexCount, const uint32_t* colors, const SkPoint* localCoords,
+                     const SkRect& bounds, GrRenderTargetContext::ColorArrayType colorArrayType);
 
     void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override;
     void applyPipelineOptimizations(const GrPipelineOptimizations&) override;
@@ -66,7 +68,7 @@
         GrColor fColor;  // Only used if there are no per-vertex colors
         SkTDArray<SkPoint> fPositions;
         SkTDArray<uint16_t> fIndices;
-        SkTDArray<GrColor> fColors;
+        SkTDArray<uint32_t> fColors;
         SkTDArray<SkPoint> fLocalCoords;
     };
 
@@ -75,6 +77,7 @@
     bool fVariableColor;
     int fVertexCount;
     int fIndexCount;
+    GrRenderTargetContext::ColorArrayType fColorArrayType;
 
     SkSTArray<1, Mesh, true> fMeshes;
 
diff --git a/src/gpu/ops/GrLatticeOp.cpp b/src/gpu/ops/GrLatticeOp.cpp
index 93c6f0f..319e505 100644
--- a/src/gpu/ops/GrLatticeOp.cpp
+++ b/src/gpu/ops/GrLatticeOp.cpp
@@ -17,7 +17,7 @@
 
 static sk_sp<GrGeometryProcessor> create_gp() {
     using namespace GrDefaultGeoProcFactory;
-    return GrDefaultGeoProcFactory::Make(Color::kAttribute_Type, Coverage::kSolid_Type,
+    return GrDefaultGeoProcFactory::Make(Color::kPremulGrColorAttribute_Type, Coverage::kSolid_Type,
                                          LocalCoords::kHasExplicit_Type, SkMatrix::I());
 }
 
diff --git a/src/gpu/ops/GrMSAAPathRenderer.cpp b/src/gpu/ops/GrMSAAPathRenderer.cpp
index 26fdf5d..62dc49b 100644
--- a/src/gpu/ops/GrMSAAPathRenderer.cpp
+++ b/src/gpu/ops/GrMSAAPathRenderer.cpp
@@ -401,7 +401,7 @@
             sk_sp<GrGeometryProcessor> lineGP;
             {
                 using namespace GrDefaultGeoProcFactory;
-                lineGP = GrDefaultGeoProcFactory::Make(Color(Color::kAttribute_Type),
+                lineGP = GrDefaultGeoProcFactory::Make(Color(Color::kPremulGrColorAttribute_Type),
                                                        Coverage::kSolid_Type,
                                                        LocalCoords(LocalCoords::kUnused_Type),
                                                        fViewMatrix);
diff --git a/src/gpu/ops/GrNonAAFillRectOp.cpp b/src/gpu/ops/GrNonAAFillRectOp.cpp
index eb2143d..7ef6cad 100644
--- a/src/gpu/ops/GrNonAAFillRectOp.cpp
+++ b/src/gpu/ops/GrNonAAFillRectOp.cpp
@@ -30,7 +30,7 @@
  */
 static sk_sp<GrGeometryProcessor> make_gp() {
     using namespace GrDefaultGeoProcFactory;
-    return GrDefaultGeoProcFactory::Make(Color::kAttribute_Type, Coverage::kSolid_Type,
+    return GrDefaultGeoProcFactory::Make(Color::kPremulGrColorAttribute_Type, Coverage::kSolid_Type,
                                          LocalCoords::kHasExplicit_Type, SkMatrix::I());
 }
 
diff --git a/src/gpu/ops/GrNonAAFillRectPerspectiveOp.cpp b/src/gpu/ops/GrNonAAFillRectPerspectiveOp.cpp
index b919a0d..cec1cfc 100644
--- a/src/gpu/ops/GrNonAAFillRectPerspectiveOp.cpp
+++ b/src/gpu/ops/GrNonAAFillRectPerspectiveOp.cpp
@@ -41,16 +41,17 @@
         LocalCoords localCoords(hasExplicitLocalCoords ? LocalCoords::kHasExplicit_Type
                                                        : LocalCoords::kUsePosition_Type,
                                 localMatrix);
-        return GrDefaultGeoProcFactory::Make(Color::kAttribute_Type, Coverage::kSolid_Type,
-                                             localCoords, viewMatrix);
+        return GrDefaultGeoProcFactory::Make(Color::kPremulGrColorAttribute_Type,
+                                             Coverage::kSolid_Type, localCoords, viewMatrix);
     } else if (hasExplicitLocalCoords) {
         LocalCoords localCoords(LocalCoords::kHasExplicit_Type, localMatrix);
-        return GrDefaultGeoProcFactory::Make(Color::kAttribute_Type, Coverage::kSolid_Type,
-                                             localCoords, SkMatrix::I());
+        return GrDefaultGeoProcFactory::Make(Color::kPremulGrColorAttribute_Type,
+                                             Coverage::kSolid_Type, localCoords, SkMatrix::I());
     } else {
         LocalCoords localCoords(LocalCoords::kUsePosition_Type, localMatrix);
-        return GrDefaultGeoProcFactory::MakeForDeviceSpace(
-                Color::kAttribute_Type, Coverage::kSolid_Type, localCoords, viewMatrix);
+        return GrDefaultGeoProcFactory::MakeForDeviceSpace(Color::kPremulGrColorAttribute_Type,
+                                                           Coverage::kSolid_Type, localCoords,
+                                                           viewMatrix);
     }
 }
 
diff --git a/src/gpu/ops/GrRegionOp.cpp b/src/gpu/ops/GrRegionOp.cpp
index 32a8150..fae79d0 100644
--- a/src/gpu/ops/GrRegionOp.cpp
+++ b/src/gpu/ops/GrRegionOp.cpp
@@ -19,7 +19,7 @@
 
 static sk_sp<GrGeometryProcessor> make_gp(const SkMatrix& viewMatrix) {
     using namespace GrDefaultGeoProcFactory;
-    return GrDefaultGeoProcFactory::Make(Color::kAttribute_Type, Coverage::kSolid_Type,
+    return GrDefaultGeoProcFactory::Make(Color::kPremulGrColorAttribute_Type, Coverage::kSolid_Type,
                                          LocalCoords::kUsePosition_Type, viewMatrix);
 }
 
diff --git a/src/gpu/ops/GrTessellatingPathRenderer.cpp b/src/gpu/ops/GrTessellatingPathRenderer.cpp
index bd474a2..509ac9f 100644
--- a/src/gpu/ops/GrTessellatingPathRenderer.cpp
+++ b/src/gpu/ops/GrTessellatingPathRenderer.cpp
@@ -280,7 +280,7 @@
                                                         : LocalCoords::kUnused_Type;
             Coverage::Type coverageType;
             if (fAntiAlias) {
-                color = Color(Color::kAttribute_Type);
+                color = Color(Color::kPremulGrColorAttribute_Type);
                 if (fCanTweakAlphaForCoverage) {
                     coverageType = Coverage::kSolid_Type;
                 } else {