Half float vertex colors (when necessary) in small path renderer

Bug: skia:
Change-Id: I34fa12e8d7dbf003d4776df779967dd273228502
Reviewed-on: https://skia-review.googlesource.com/c/174302
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/src/gpu/GrGeometryProcessor.h b/src/gpu/GrGeometryProcessor.h
index a12ab00..f6d3ef5 100644
--- a/src/gpu/GrGeometryProcessor.h
+++ b/src/gpu/GrGeometryProcessor.h
@@ -39,6 +39,14 @@
         fSampleShading = sampleShading;
     }
 
+    // GPs that need to use either half-float or ubyte colors can just call this to get a correctly
+    // configured Attribute struct
+    static Attribute MakeColorAttribute(const char* name, bool wideColor) {
+        return { name,
+                 wideColor ? kHalf4_GrVertexAttribType : kUByte4_norm_GrVertexAttribType,
+                 kHalf4_GrSLType };
+    }
+
 private:
     bool fWillUseGeoShader;
     float fSampleShading;
diff --git a/src/gpu/effects/GrBitmapTextGeoProc.cpp b/src/gpu/effects/GrBitmapTextGeoProc.cpp
index 0b83c7b..cd98f1d 100644
--- a/src/gpu/effects/GrBitmapTextGeoProc.cpp
+++ b/src/gpu/effects/GrBitmapTextGeoProc.cpp
@@ -120,6 +120,7 @@
 
 GrBitmapTextGeoProc::GrBitmapTextGeoProc(const GrShaderCaps& caps,
                                          const SkPMColor4f& color,
+                                         bool wideColor,
                                          const sk_sp<GrTextureProxy>* proxies,
                                          int numActiveProxies,
                                          const GrSamplerState& params, GrMaskFormat format,
@@ -140,7 +141,7 @@
     bool hasVertexColor = kA8_GrMaskFormat == fMaskFormat ||
                           kA565_GrMaskFormat == fMaskFormat;
     if (hasVertexColor) {
-        fInColor = {"inColor", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType};
+        fInColor = MakeColorAttribute("inColor", wideColor);
     }
 
     fInTextureCoords = {"inTextureCoords", kUShort2_GrVertexAttribType,
@@ -224,6 +225,7 @@
 
     return GrBitmapTextGeoProc::Make(*d->caps()->shaderCaps(),
                                      SkPMColor4f::FromBytes_RGBA(GrRandomColor(d->fRandom)),
+                                     d->fRandom->nextBool(),
                                      proxies, 1, samplerState, format,
                                      GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool());
 }
diff --git a/src/gpu/effects/GrBitmapTextGeoProc.h b/src/gpu/effects/GrBitmapTextGeoProc.h
index ca9b796..30cd38e 100644
--- a/src/gpu/effects/GrBitmapTextGeoProc.h
+++ b/src/gpu/effects/GrBitmapTextGeoProc.h
@@ -23,13 +23,14 @@
 public:
     static constexpr int kMaxTextures = 4;
 
-    static sk_sp<GrGeometryProcessor> Make(const GrShaderCaps& caps, const SkPMColor4f& color,
+    static sk_sp<GrGeometryProcessor> Make(const GrShaderCaps& caps,
+                                           const SkPMColor4f& color, bool wideColor,
                                            const sk_sp<GrTextureProxy>* proxies,
                                            int numActiveProxies,
                                            const GrSamplerState& p, GrMaskFormat format,
                                            const SkMatrix& localMatrix, bool usesW) {
         return sk_sp<GrGeometryProcessor>(
-            new GrBitmapTextGeoProc(caps, color, proxies, numActiveProxies, p, format,
+            new GrBitmapTextGeoProc(caps, color, wideColor, proxies, numActiveProxies, p, format,
                                     localMatrix, usesW));
     }
 
@@ -54,7 +55,7 @@
     GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps& caps) const override;
 
 private:
-    GrBitmapTextGeoProc(const GrShaderCaps&, const SkPMColor4f&,
+    GrBitmapTextGeoProc(const GrShaderCaps&, const SkPMColor4f&, bool wideColor,
                         const sk_sp<GrTextureProxy>* proxies, int numProxies,
                         const GrSamplerState& params, GrMaskFormat format,
                         const SkMatrix& localMatrix, bool usesW);
diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.cpp b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
index 29c7c47..314a984 100644
--- a/src/gpu/effects/GrDistanceFieldGeoProc.cpp
+++ b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
@@ -509,6 +509,7 @@
 
 GrDistanceFieldPathGeoProc::GrDistanceFieldPathGeoProc(const GrShaderCaps& caps,
                                                        const SkMatrix& matrix,
+                                                       bool wideColor,
                                                        const sk_sp<GrTextureProxy>* proxies,
                                                        int numProxies,
                                                        const GrSamplerState& params,
@@ -520,7 +521,7 @@
     SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
 
     fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
-    fInColor = {"inColor", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType};
+    fInColor = MakeColorAttribute("inColor", wideColor);
     fInTextureCoords = {"inTextureCoords", kUShort2_GrVertexAttribType,
                         caps.integerSupport() ? kUShort2_GrSLType : kFloat2_GrSLType};
     this->setVertexAttributes(&fInPosition, 3);
@@ -596,6 +597,7 @@
 
     return GrDistanceFieldPathGeoProc::Make(*d->caps()->shaderCaps(),
                                             GrTest::TestMatrix(d->fRandom),
+                                            d->fRandom->nextBool(),
                                             proxies, 1,
                                             samplerState,
                                             flags);
diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.h b/src/gpu/effects/GrDistanceFieldGeoProc.h
index 3529fe0..386b38a 100644
--- a/src/gpu/effects/GrDistanceFieldGeoProc.h
+++ b/src/gpu/effects/GrDistanceFieldGeoProc.h
@@ -137,11 +137,13 @@
     /** The local matrix should be identity if local coords are not required by the GrPipeline. */
     static sk_sp<GrGeometryProcessor> Make(const GrShaderCaps& caps,
                                            const SkMatrix& matrix,
+                                           bool wideColor,
                                            const sk_sp<GrTextureProxy>* proxies,
                                            int numActiveProxies,
                                            const GrSamplerState& params, uint32_t flags) {
         return sk_sp<GrGeometryProcessor>(
-            new GrDistanceFieldPathGeoProc(caps, matrix, proxies, numActiveProxies, params, flags));
+            new GrDistanceFieldPathGeoProc(caps, matrix, wideColor, proxies, numActiveProxies,
+                                           params, flags));
     }
 
     ~GrDistanceFieldPathGeoProc() override {}
@@ -164,6 +166,7 @@
 private:
     GrDistanceFieldPathGeoProc(const GrShaderCaps& caps,
                                const SkMatrix& matrix,
+                               bool wideColor,
                                const sk_sp<GrTextureProxy>* proxies,
                                int numActiveProxies,
                                const GrSamplerState&, uint32_t flags);
diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp
index 7263dfb..368c625 100644
--- a/src/gpu/ops/GrAtlasTextOp.cpp
+++ b/src/gpu/ops/GrAtlasTextOp.cpp
@@ -321,8 +321,8 @@
         GrSamplerState samplerState = fNeedsGlyphTransform ? GrSamplerState::ClampBilerp()
                                                            : GrSamplerState::ClampNearest();
         flushInfo.fGeometryProcessor = GrBitmapTextGeoProc::Make(
-            *target->caps().shaderCaps(), this->color(), proxies, numActiveProxies, samplerState,
-            maskFormat, localMatrix, vmPerspective);
+            *target->caps().shaderCaps(), this->color(), false, proxies, numActiveProxies,
+            samplerState, maskFormat, localMatrix, vmPerspective);
     }
 
     flushInfo.fGlyphsToFlush = 0;
diff --git a/src/gpu/ops/GrOvalOpFactory.cpp b/src/gpu/ops/GrOvalOpFactory.cpp
index 0c2946c..5752c81 100644
--- a/src/gpu/ops/GrOvalOpFactory.cpp
+++ b/src/gpu/ops/GrOvalOpFactory.cpp
@@ -32,12 +32,6 @@
 
 static inline bool circle_stays_circle(const SkMatrix& m) { return m.isSimilarity(); }
 
-static inline GrPrimitiveProcessor::Attribute color_attribute(bool wideColor) {
-    return { "inColor",
-             wideColor ? kHalf4_GrVertexAttribType : kUByte4_norm_GrVertexAttribType,
-             kHalf4_GrSLType };
-}
-
 // Produces TriStrip vertex data for an origin-centered rectangle from [-x, -y] to [x, y]
 static inline GrVertexWriter::TriStrip<float> origin_centered_tri_strip(float x, float y) {
     return GrVertexWriter::TriStrip<float>{ -x, -y, x, y };
@@ -74,7 +68,7 @@
             , fLocalMatrix(localMatrix)
             , fStroke(stroke) {
         fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
-        fInColor = color_attribute(wideColor);
+        fInColor = MakeColorAttribute("inColor", wideColor);
         fInCircleEdge = {"inCircleEdge", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
 
         if (clipPlane) {
@@ -266,7 +260,7 @@
     ButtCapDashedCircleGeometryProcessor(bool wideColor, const SkMatrix& localMatrix)
             : INHERITED(kButtCapStrokedCircleGeometryProcessor_ClassID), fLocalMatrix(localMatrix) {
         fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
-        fInColor = color_attribute(wideColor);
+        fInColor = MakeColorAttribute("inColor", wideColor);
         fInCircleEdge = {"inCircleEdge", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
         fInDashParams = {"inDashParams", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
         this->setVertexAttributes(&fInPosition, 4);
@@ -513,7 +507,7 @@
     : INHERITED(kEllipseGeometryProcessor_ClassID)
     , fLocalMatrix(localMatrix) {
         fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
-        fInColor = color_attribute(wideColor);
+        fInColor = MakeColorAttribute("inColor", wideColor);
         fInEllipseOffset = {"inEllipseOffset", kFloat2_GrVertexAttribType, kHalf2_GrSLType};
         fInEllipseRadii = {"inEllipseRadii", kFloat4_GrVertexAttribType, kHalf4_GrSLType};
         this->setVertexAttributes(&fInPosition, 4);
@@ -665,7 +659,7 @@
             , fViewMatrix(viewMatrix) {
         fStyle = style;
         fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
-        fInColor = color_attribute(wideColor);
+        fInColor = MakeColorAttribute("inColor", wideColor);
         fInEllipseOffsets0 = {"inEllipseOffsets0", kFloat2_GrVertexAttribType, kHalf2_GrSLType};
         fInEllipseOffsets1 = {"inEllipseOffsets1", kFloat2_GrVertexAttribType, kHalf2_GrSLType};
         this->setVertexAttributes(&fInPosition, 4);
diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp
index 4f902e0..154d845 100644
--- a/src/gpu/ops/GrSmallPathRenderer.cpp
+++ b/src/gpu/ops/GrSmallPathRenderer.cpp
@@ -267,6 +267,7 @@
         fShapeCache = shapeCache;
         fShapeList = shapeList;
         fGammaCorrect = gammaCorrect;
+        fWideColor = !SkPMColor4fFitsInBytes(color);
 
     }
 
@@ -351,7 +352,7 @@
                 matrix = &SkMatrix::I();
             }
             flushInfo.fGeometryProcessor = GrDistanceFieldPathGeoProc::Make(
-                    *target->caps().shaderCaps(), *matrix, fAtlas->getProxies(),
+                    *target->caps().shaderCaps(), *matrix, fWideColor, fAtlas->getProxies(),
                     fAtlas->numActivePages(), GrSamplerState::ClampBilerp(), flags);
         } else {
             SkMatrix invert;
@@ -362,7 +363,7 @@
             }
 
             flushInfo.fGeometryProcessor = GrBitmapTextGeoProc::Make(
-                    *target->caps().shaderCaps(), this->color(), fAtlas->getProxies(),
+                    *target->caps().shaderCaps(), this->color(), fWideColor, fAtlas->getProxies(),
                     fAtlas->numActivePages(), GrSamplerState::ClampNearest(), kA8_GrMaskFormat,
                     invert, false);
         }
@@ -489,9 +490,8 @@
             auto uploadTarget = target->deferredUploadTarget();
             fAtlas->setLastUseToken(shapeData->fID, uploadTarget->tokenTracker()->nextDrawToken());
 
-            // TODO4F: Preserve float colors
-            this->writePathVertices(fAtlas, vertices, args.fColor.toBytes_RGBA(), args.fViewMatrix,
-                                    shapeData);
+            this->writePathVertices(fAtlas, vertices, GrVertexColor(args.fColor, fWideColor),
+                                    args.fViewMatrix, shapeData);
             flushInfo.fInstancesToFlush++;
         }
 
@@ -745,7 +745,7 @@
 
     void writePathVertices(GrDrawOpAtlas* atlas,
                            GrVertexWriter& vertices,
-                           GrColor color,
+                           const GrVertexColor& color,
                            const SkMatrix& ctm,
                            const ShapeData* shapeData) const {
         SkRect translatedBounds(shapeData->fBounds);
@@ -844,6 +844,7 @@
         }
 
         fShapes.push_back_n(that->fShapes.count(), that->fShapes.begin());
+        fWideColor |= that->fWideColor;
         return CombineResult::kMerged;
     }
 
@@ -861,6 +862,7 @@
     ShapeCache* fShapeCache;
     ShapeDataList* fShapeList;
     bool fGammaCorrect;
+    bool fWideColor;
 
     typedef GrMeshDrawOp INHERITED;
 };