Enable wide color support in CCPR

Unlike other ops, always use half-float colors. The logic around the
Instance struct makes dynamically switching color size tricky.
CCPR stores color in a per-instance attribute though, so the cost of
always using FP16 is much lower.

Bug: skia:
Change-Id: I9c0c64940f74f915a18417a5830030558e065d28
Reviewed-on: https://skia-review.googlesource.com/c/182760
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/ccpr/GrCCDrawPathsOp.cpp b/src/gpu/ccpr/GrCCDrawPathsOp.cpp
index fe1365b..13b21d0 100644
--- a/src/gpu/ccpr/GrCCDrawPathsOp.cpp
+++ b/src/gpu/ccpr/GrCCDrawPathsOp.cpp
@@ -174,7 +174,6 @@
         fShape = GrShape(path, GrStyle(hairlineStroke, nullptr));
         fStrokeDevWidth = 1;
 
-        // TODO4F: Preserve float colors
         // fShapeConservativeIBounds already accounted for this possibility of inflating the stroke.
         fColor = fColor * coverage;
     }
@@ -350,9 +349,8 @@
 #endif
             op->recordInstance(fCacheEntry->cachedAtlas()->getOnFlushProxy(),
                                resources->nextPathInstanceIdx());
-            // TODO4F: Preserve float colors
             resources->appendDrawPathInstance().set(*fCacheEntry, fCachedMaskShift,
-                                                    fColor.toBytes_RGBA());
+                                                    SkPMColor4f_toFP16(fColor));
             return;
         }
     }
@@ -368,9 +366,8 @@
                 fMaskDevIBounds, fMatrix, fShape, fStrokeDevWidth, &devBounds, &devBounds45,
                 &devIBounds, &devToAtlasOffset)) {
         op->recordInstance(atlas->textureProxy(), resources->nextPathInstanceIdx());
-        // TODO4F: Preserve float colors
         resources->appendDrawPathInstance().set(devBounds, devBounds45, devToAtlasOffset,
-                                                fColor.toBytes_RGBA(), doEvenOddFill);
+                                                SkPMColor4f_toFP16(fColor), doEvenOddFill);
 
         if (fDoCachePathMask) {
             SkASSERT(fCacheEntry);
diff --git a/src/gpu/ccpr/GrCCPathCache.h b/src/gpu/ccpr/GrCCPathCache.h
index 5fa5d4d..688521b 100644
--- a/src/gpu/ccpr/GrCCPathCache.h
+++ b/src/gpu/ccpr/GrCCPathCache.h
@@ -268,7 +268,7 @@
 
     friend class GrCCPathCache;
     friend void GrCCPathProcessor::Instance::set(const GrCCPathCacheEntry&, const SkIVector&,
-                                                 GrColor, DoEvenOddFill);  // To access data.
+                                                 uint64_t color, DoEvenOddFill);  // To access data.
 
 public:
     int testingOnly_peekOnFlushRefCnt() const;
@@ -360,7 +360,7 @@
 }
 
 inline void GrCCPathProcessor::Instance::set(const GrCCPathCacheEntry& entry,
-                                             const SkIVector& shift, GrColor color,
+                                             const SkIVector& shift, uint64_t color,
                                              DoEvenOddFill doEvenOddFill) {
     float dx = (float)shift.fX, dy = (float)shift.fY;
     this->set(entry.fDevBounds.makeOffset(dx, dy), MakeOffset45(entry.fDevBounds45, dx, dy),
diff --git a/src/gpu/ccpr/GrCCPathProcessor.h b/src/gpu/ccpr/GrCCPathProcessor.h
index bd544bb..2f54d67 100644
--- a/src/gpu/ccpr/GrCCPathProcessor.h
+++ b/src/gpu/ccpr/GrCCPathProcessor.h
@@ -56,15 +56,15 @@
         SkRect fDevBounds45;  // Bounding box in "| 1  -1 | * devCoords" space.
                               //                  | 1   1 |
         SkIVector fDevToAtlasOffset;  // Translation from device space to location in atlas.
-        GrColor fColor;
+        uint64_t fColor;  // Color always stored as 4 x fp16
 
         void set(const SkRect& devBounds, const SkRect& devBounds45,
-                 const SkIVector& devToAtlasOffset, GrColor, DoEvenOddFill = DoEvenOddFill::kNo);
-        void set(const GrCCPathCacheEntry&, const SkIVector& shift, GrColor,
+                 const SkIVector& devToAtlasOffset, uint64_t, DoEvenOddFill = DoEvenOddFill::kNo);
+        void set(const GrCCPathCacheEntry&, const SkIVector& shift, uint64_t,
                  DoEvenOddFill = DoEvenOddFill::kNo);
     };
 
-    GR_STATIC_ASSERT(4 * 11 == sizeof(Instance));
+    GR_STATIC_ASSERT(4 * 12 == sizeof(Instance));
 
     static sk_sp<const GrBuffer> FindVertexBuffer(GrOnFlushResourceProvider*);
     static sk_sp<const GrBuffer> FindIndexBuffer(GrOnFlushResourceProvider*);
@@ -102,7 +102,7 @@
             {"devbounds", kFloat4_GrVertexAttribType, kFloat4_GrSLType},
             {"devbounds45", kFloat4_GrVertexAttribType, kFloat4_GrSLType},
             {"dev_to_atlas_offset", kInt2_GrVertexAttribType, kInt2_GrSLType},
-            {"color", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType}
+            {"color", kHalf4_GrVertexAttribType, kHalf4_GrSLType}
     };
     static constexpr Attribute kEdgeNormsAttrib = {"edge_norms", kFloat4_GrVertexAttribType,
                                                                  kFloat4_GrSLType};
@@ -111,7 +111,7 @@
 };
 
 inline void GrCCPathProcessor::Instance::set(const SkRect& devBounds, const SkRect& devBounds45,
-                                             const SkIVector& devToAtlasOffset, GrColor color,
+                                             const SkIVector& devToAtlasOffset, uint64_t color,
                                              DoEvenOddFill doEvenOddFill) {
     if (DoEvenOddFill::kYes == doEvenOddFill) {
         // "right < left" indicates even-odd fill type.
diff --git a/src/gpu/ccpr/GrCCPerFlushResources.cpp b/src/gpu/ccpr/GrCCPerFlushResources.cpp
index e6cf8bb..5d4ca94 100644
--- a/src/gpu/ccpr/GrCCPerFlushResources.cpp
+++ b/src/gpu/ccpr/GrCCPerFlushResources.cpp
@@ -251,7 +251,11 @@
 
     // Write the instance at the back of the array.
     int currentInstanceIdx = fNextCopyInstanceIdx++;
-    fPathInstanceData[currentInstanceIdx].set(entry, newAtlasOffset, GrColor_WHITE, evenOdd);
+    constexpr uint64_t kWhite = (((uint64_t) SK_Half1) <<  0) |
+                                (((uint64_t) SK_Half1) << 16) |
+                                (((uint64_t) SK_Half1) << 32) |
+                                (((uint64_t) SK_Half1) << 48);
+    fPathInstanceData[currentInstanceIdx].set(entry, newAtlasOffset, kWhite, evenOdd);
 
     // Percolate the instance forward until it's contiguous with other instances that share the same
     // proxy.
diff --git a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
index 901ca38..077b0ec 100644
--- a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
+++ b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
@@ -26,6 +26,7 @@
            caps.isConfigRenderable(kAlpha_half_GrPixelConfig) &&
            caps.isConfigTexturable(kAlpha_8_GrPixelConfig) &&
            caps.isConfigRenderable(kAlpha_8_GrPixelConfig) &&
+           caps.halfFloatVertexAttributeSupport() &&
            !caps.blacklistCoverageCounting();
 }
 
diff --git a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
index 19c0d1b..e207e15 100644
--- a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
+++ b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
@@ -502,7 +502,7 @@
 // that these factories could simply return the input FP. However, that doesn't have quite
 // the same effect as the returned compose FP will replace the FP's input with solid white and
 // ignore the original input. This could be implemented as:
-// RunInSeries(ConstColor(GrColor_WHITE, kIgnoreInput), inputFP).
+// RunInSeries(ConstColor(WHITE, kIgnoreInput), inputFP).
 
 std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromDstProcessor(
         std::unique_ptr<GrFragmentProcessor> dst, SkBlendMode mode) {
diff --git a/src/gpu/mock/GrMockCaps.h b/src/gpu/mock/GrMockCaps.h
index c58b9bb..65aee42 100644
--- a/src/gpu/mock/GrMockCaps.h
+++ b/src/gpu/mock/GrMockCaps.h
@@ -17,6 +17,7 @@
     GrMockCaps(const GrContextOptions& contextOptions, const GrMockOptions& options)
             : INHERITED(contextOptions), fOptions(options) {
         fInstanceAttribSupport = options.fInstanceAttribSupport;
+        fHalfFloatVertexAttributeSupport = options.fHalfFloatVertexAttributeSupport;
         fMapBufferFlags = options.fMapBufferFlags;
         fBufferMapThreshold = SK_MaxS32; // Overridable in GrContextOptions.
         fMaxTextureSize = options.fMaxTextureSize;