Revert "ccpr: Implement conics"

This reverts commit 98b241573e6083c4c7f0ce9e30cc214c4da1a8ba.

Reason for revert: TSAN not happy

Original change's description:
> ccpr: Implement conics
> 
> Bug: skia:
> Change-Id: I4bae8b059072af987abb7b2d9c57fe08f783d680
> Reviewed-on: https://skia-review.googlesource.com/120040
> Commit-Queue: Chris Dalton <csmartdalton@google.com>
> Reviewed-by: Greg Daniel <egdaniel@google.com>

TBR=egdaniel@google.com,bsalomon@google.com,csmartdalton@google.com

Change-Id: Ic29bf660f042c20b7e4492b03400412e378dbb8a
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:
Reviewed-on: https://skia-review.googlesource.com/121717
Reviewed-by: Chris Dalton <csmartdalton@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/ccpr/GrCCConicShader.cpp b/src/gpu/ccpr/GrCCConicShader.cpp
deleted file mode 100644
index 01568de..0000000
--- a/src/gpu/ccpr/GrCCConicShader.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrCCConicShader.h"
-
-#include "glsl/GrGLSLFragmentShaderBuilder.h"
-#include "glsl/GrGLSLVertexGeoBuilder.h"
-
-void GrCCConicShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts, const char* wind,
-                                    const char** outHull4) const {
-    // K is distance from the line P2 -> P0. L is distance from the line P0 -> P1, scaled by 2w.
-    // M is distance from the line P1 -> P2, scaled by 2w. We do this in a space where P1=0.
-    s->declareGlobal(fKLMMatrix);
-    s->codeAppendf("float x0 = %s[0].x - %s[1].x, x2 = %s[2].x - %s[1].x;", pts, pts, pts, pts);
-    s->codeAppendf("float y0 = %s[0].y - %s[1].y, y2 = %s[2].y - %s[1].y;", pts, pts, pts, pts);
-    s->codeAppendf("float w = %s[3].x;", pts);
-    s->codeAppendf("%s = float3x3(y2 - y0, x0 - x2, x2*y0 - x0*y2, "
-                                 "2*w * float2(+y0, -x0), 0, "
-                                 "2*w * float2(-y2, +x2), 0);", fKLMMatrix.c_str());
-
-    s->declareGlobal(fControlPoint);
-    s->codeAppendf("%s = %s[1];", fControlPoint.c_str(), pts);
-
-    // Scale KLM by the inverse Manhattan width of K. This allows K to double as the flat opposite
-    // edge AA. kwidth will not be 0 because we cull degenerate conics on the CPU.
-    s->codeAppendf("float kwidth = 2*bloat * %s * (abs(%s[0].x) + abs(%s[0].y));",
-                   wind, fKLMMatrix.c_str(), fKLMMatrix.c_str());
-    s->codeAppendf("%s *= 1/kwidth;", fKLMMatrix.c_str());
-
-    if (outHull4) {
-        // Clip the conic triangle by the tangent line at maximum height. Conics have the nice
-        // property that maximum height always occurs at T=.5. This is a simple application for
-        // De Casteljau's algorithm.
-        s->codeAppendf("float2 p1w = %s[1]*w;", pts);
-        s->codeAppend ("float r = 1 / (1 + w);");
-        s->codeAppendf("float2 conic_hull[4] = float2[4](%s[0], "
-                                                        "(%s[0] + p1w) * r, "
-                                                        "(p1w + %s[2]) * r, "
-                                                        "%s[2]);", pts, pts, pts, pts);
-        *outHull4 = "conic_hull";
-    }
-}
-
-void GrCCConicShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler,
-                                     GrGLSLVarying::Scope scope, SkString* code,
-                                     const char* position, const char* coverage,
-                                     const char* cornerCoverage) {
-    fKLM_fWind.reset(kFloat4_GrSLType, scope);
-    varyingHandler->addVarying("klm_and_wind", &fKLM_fWind);
-    code->appendf("float3 klm = float3(%s - %s, 1) * %s;",
-                  position, fControlPoint.c_str(), fKLMMatrix.c_str());
-    code->appendf("%s.xyz = klm;", OutName(fKLM_fWind));
-    code->appendf("%s.w = %s;", OutName(fKLM_fWind), coverage); // coverage == wind.
-
-    fGrad_fCorner.reset(cornerCoverage ? kFloat4_GrSLType : kFloat2_GrSLType, scope);
-    varyingHandler->addVarying(cornerCoverage ? "grad_and_corner" : "grad", &fGrad_fCorner);
-    code->appendf("%s.xy = 2*bloat * (float3x2(%s) * float3(2*klm[0], -klm[2], -klm[1]));",
-                  OutName(fGrad_fCorner), fKLMMatrix.c_str());
-
-    if (cornerCoverage) {
-        code->appendf("half hull_coverage;");
-        this->calcHullCoverage(code, "klm", OutName(fGrad_fCorner), "hull_coverage");
-        code->appendf("%s.zw = half2(hull_coverage, 1) * %s;",
-                      OutName(fGrad_fCorner), cornerCoverage);
-    }
-}
-
-void GrCCConicShader::onEmitFragmentCode(GrGLSLFPFragmentBuilder* f,
-                                         const char* outputCoverage) const {
-    this->calcHullCoverage(&AccessCodeString(f), fKLM_fWind.fsIn(), fGrad_fCorner.fsIn(),
-                           outputCoverage);
-    f->codeAppendf("%s *= %s.w;", outputCoverage, fKLM_fWind.fsIn()); // Wind.
-
-    if (kFloat4_GrSLType == fGrad_fCorner.type()) {
-        f->codeAppendf("%s = %s.z * %s.w + %s;", // Attenuated corner coverage.
-                       outputCoverage, fGrad_fCorner.fsIn(), fGrad_fCorner.fsIn(),
-                       outputCoverage);
-    }
-}
-
-void GrCCConicShader::calcHullCoverage(SkString* code, const char* klm, const char* grad,
-                                       const char* outputCoverage) const {
-    code->appendf("float k = %s.x, l = %s.y, m = %s.z;", klm, klm, klm);
-    code->append ("float f = k*k - l*m;");
-    code->appendf("float fwidth = abs(%s.x) + abs(%s.y);", grad, grad);
-    code->appendf("%s = min(0.5 - f/fwidth, 1);", outputCoverage); // Curve coverage.
-    code->append ("half d = min(k - 0.5, 0);"); // K doubles as the flat opposite edge's AA.
-    code->appendf("%s = max(%s + d, 0);", outputCoverage, outputCoverage); // Total hull coverage.
-}
diff --git a/src/gpu/ccpr/GrCCConicShader.h b/src/gpu/ccpr/GrCCConicShader.h
deleted file mode 100644
index 16b70e7..0000000
--- a/src/gpu/ccpr/GrCCConicShader.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrCCConicShader_DEFINED
-#define GrCCConicShader_DEFINED
-
-#include "ccpr/GrCCCoverageProcessor.h"
-
-/**
- * This class renders the coverage of closed conic curves using the techniques outlined in
- * "Resolution Independent Curve Rendering using Programmable Graphics Hardware" by Charles Loop and
- * Jim Blinn:
- *
- * https://www.microsoft.com/en-us/research/wp-content/uploads/2005/01/p1000-loop.pdf
- *
- * The provided curves must be monotonic with respect to the vector of their closing edge [P2 - P0].
- * (Use GrCCGeometry::conicTo().)
- */
-class GrCCConicShader : public GrCCCoverageProcessor::Shader {
-public:
-    void emitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, const char* wind,
-                       const char** outHull4) const override;
-
-    void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code,
-                        const char* position, const char* coverage,
-                        const char* cornerCoverage) override;
-
-    void onEmitFragmentCode(GrGLSLFPFragmentBuilder*, const char* outputCoverage) const override;
-
-private:
-    void calcHullCoverage(SkString* code, const char* klm, const char* grad,
-                          const char* outputCoverage) const;
-
-    const GrShaderVar fKLMMatrix{"klm_matrix", kFloat3x3_GrSLType};
-    const GrShaderVar fControlPoint{"control_point", kFloat2_GrSLType};
-    GrGLSLVarying fKLM_fWind;
-    GrGLSLVarying fGrad_fCorner;
-};
-
-#endif
diff --git a/src/gpu/ccpr/GrCCCoverageProcessor.cpp b/src/gpu/ccpr/GrCCCoverageProcessor.cpp
index d38db27..b94b188 100644
--- a/src/gpu/ccpr/GrCCCoverageProcessor.cpp
+++ b/src/gpu/ccpr/GrCCCoverageProcessor.cpp
@@ -10,7 +10,6 @@
 #include "GrGpuCommandBuffer.h"
 #include "GrOpFlushState.h"
 #include "SkMakeUnique.h"
-#include "ccpr/GrCCConicShader.h"
 #include "ccpr/GrCCCubicShader.h"
 #include "ccpr/GrCCQuadraticShader.h"
 #include "glsl/GrGLSLVertexGeoBuilder.h"
@@ -175,9 +174,6 @@
         case PrimitiveType::kCubics:
             shader = skstd::make_unique<GrCCCubicShader>();
             break;
-        case PrimitiveType::kConics:
-            shader = skstd::make_unique<GrCCConicShader>();
-            break;
     }
     return Impl::kGeometryShader == fImpl ? this->createGSImpl(std::move(shader))
                                           : this->createVSImpl(std::move(shader));
diff --git a/src/gpu/ccpr/GrCCCoverageProcessor.h b/src/gpu/ccpr/GrCCCoverageProcessor.h
index 454e728..6818027 100644
--- a/src/gpu/ccpr/GrCCCoverageProcessor.h
+++ b/src/gpu/ccpr/GrCCCoverageProcessor.h
@@ -40,7 +40,6 @@
         kWeightedTriangles, // Triangles (from the tessellator) whose winding magnitude > 1.
         kQuadratics,
         kCubics,
-        kConics
     };
     static const char* PrimitiveTypeName(PrimitiveType);
 
@@ -54,15 +53,14 @@
         void set(const SkPoint&, const SkPoint&, const SkPoint&, const Sk2f& trans);
     };
 
-    // Defines a single primitive shape with 4 input points, or 3 input points plus a "weight"
-    // parameter duplicated in both lanes of the 4th input (i.e. Cubics, Conics, and Triangles with
-    // a weighted winding number). X,Y point values are transposed.
+    // Defines a single primitive shape with 4 input points, or 3 input points plus a W parameter
+    // duplicated in both 4th components (i.e. Cubics or Triangles with a custom winding number).
+    // X,Y point values are transposed.
     struct QuadPointInstance {
         float fX[4];
         float fY[4];
 
         void set(const SkPoint[4], float dx, float dy);
-        void setW(const SkPoint[3], const Sk2f& trans, float w);
         void setW(const SkPoint&, const SkPoint&, const SkPoint&, const Sk2f& trans, float w);
     };
 
@@ -207,11 +205,6 @@
     // Number of bezier points for curves, or 3 for triangles.
     int numInputPoints() const { return PrimitiveType::kCubics == fPrimitiveType ? 4 : 3; }
 
-    int hasInputWeight() const {
-        return PrimitiveType::kWeightedTriangles == fPrimitiveType ||
-               PrimitiveType::kConics == fPrimitiveType;
-    }
-
     enum class Impl : bool {
         kGeometryShader,
         kVertexShader
@@ -266,7 +259,6 @@
         case PrimitiveType::kWeightedTriangles: return "kWeightedTriangles";
         case PrimitiveType::kQuadratics: return "kQuadratics";
         case PrimitiveType::kCubics: return "kCubics";
-        case PrimitiveType::kConics: return "kConics";
     }
     SK_ABORT("Invalid PrimitiveType");
     return "";
@@ -291,11 +283,6 @@
     (Y + dy).store(&fY);
 }
 
-inline void GrCCCoverageProcessor::QuadPointInstance::setW(const SkPoint p[3], const Sk2f& trans,
-                                                           float w) {
-    this->setW(p[0], p[1], p[2], trans, w);
-}
-
 inline void GrCCCoverageProcessor::QuadPointInstance::setW(const SkPoint& p0, const SkPoint& p1,
                                                            const SkPoint& p2, const Sk2f& trans,
                                                            float w) {
diff --git a/src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp b/src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp
index b1d886c..f933030 100644
--- a/src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp
+++ b/src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp
@@ -52,10 +52,9 @@
         int numInputPoints = proc.numInputPoints();
         SkASSERT(3 == numInputPoints || 4 == numInputPoints);
 
-        int inputWidth = (4 == numInputPoints || proc.hasInputWeight()) ? 4 : 3;
-        const char* posValues = (4 == inputWidth) ? "sk_Position" : "sk_Position.xyz";
+        const char* posValues = (4 == numInputPoints) ? "sk_Position" : "sk_Position.xyz";
         g->codeAppendf("float%ix2 pts = transpose(float2x%i(sk_in[0].%s, sk_in[1].%s));",
-                       inputWidth, inputWidth, posValues, posValues);
+                       numInputPoints, numInputPoints, posValues, posValues);
 
         GrShaderVar wind("wind", kHalf_GrSLType);
         g->declareGlobal(wind);
@@ -390,7 +389,8 @@
 
 void GrCCCoverageProcessor::initGS() {
     SkASSERT(Impl::kGeometryShader == fImpl);
-    if (4 == this->numInputPoints() || this->hasInputWeight()) {
+    if (PrimitiveType::kCubics == fPrimitiveType ||
+        PrimitiveType::kWeightedTriangles == fPrimitiveType) {
         this->addVertexAttrib("x_or_y_values", kFloat4_GrVertexAttribType);
         SkASSERT(sizeof(QuadPointInstance) == this->getVertexStride() * 2);
         SkASSERT(offsetof(QuadPointInstance, fY) == this->getVertexStride());
diff --git a/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp b/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp
index dd8da96..a1f180b 100644
--- a/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp
+++ b/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp
@@ -257,10 +257,9 @@
     GrGLSLVertexBuilder* v = args.fVertBuilder;
     int numInputPoints = proc.numInputPoints();
 
-    int inputWidth = (4 == numInputPoints || proc.hasInputWeight()) ? 4 : 3;
-    const char* swizzle = (4 == inputWidth) ? "xyzw" : "xyz";
+    const char* swizzle = (4 == numInputPoints) ? "xyzw" : "xyz";
     v->codeAppendf("float%ix2 pts = transpose(float2x%i(%s.%s, %s.%s));",
-                   inputWidth, inputWidth, proc.getAttrib(kAttribIdx_X).fName, swizzle,
+                   numInputPoints, numInputPoints, proc.getAttrib(kAttribIdx_X).fName, swizzle,
                    proc.getAttrib(kAttribIdx_Y).fName, swizzle);
 
     if (PrimitiveType::kWeightedTriangles != proc.fPrimitiveType) {
@@ -477,8 +476,7 @@
         }
 
         case PrimitiveType::kQuadratics:
-        case PrimitiveType::kCubics:
-        case PrimitiveType::kConics: {
+        case PrimitiveType::kCubics: {
             GR_DEFINE_STATIC_UNIQUE_KEY(gCurveVertexBufferKey);
             fVSVertexBuffer = rp->findOrMakeStaticBuffer(kVertex_GrBufferType,
                                                          sizeof(kCurveVertices), kCurveVertices,
@@ -501,7 +499,8 @@
         }
     }
 
-    if (4 == this->numInputPoints() || this->hasInputWeight()) {
+    if (PrimitiveType::kCubics == fPrimitiveType ||
+        PrimitiveType::kWeightedTriangles == fPrimitiveType) {
         SkASSERT(kAttribIdx_X == this->numAttribs());
         this->addInstanceAttrib("X", kFloat4_GrVertexAttribType);
 
@@ -551,7 +550,6 @@
             return new VSImpl(std::move(shadr), 3);
         case PrimitiveType::kQuadratics:
         case PrimitiveType::kCubics:
-        case PrimitiveType::kConics:
             return new VSImpl(std::move(shadr), 4);
     }
     SK_ABORT("Invalid RenderPass");
diff --git a/src/gpu/ccpr/GrCCGeometry.cpp b/src/gpu/ccpr/GrCCGeometry.cpp
index 302cfe2..5d7fc69 100644
--- a/src/gpu/ccpr/GrCCGeometry.cpp
+++ b/src/gpu/ccpr/GrCCGeometry.cpp
@@ -27,7 +27,7 @@
     SkASSERT(!fBuildingContour);
     // Store the current verb count in the fTriangles field for now. When we close the contour we
     // will use this value to calculate the actual number of triangles in its fan.
-    fCurrContourTallies = {fVerbs.count(), 0, 0, 0, 0};
+    fCurrContourTallies = {fVerbs.count(), 0, 0, 0};
 
     fPoints.push_back(pt);
     fVerbs.push_back(Verb::kBeginContour);
@@ -125,8 +125,7 @@
     return dot0 >= tolerance && dot1 >= tolerance;
 }
 
-template<int N> static inline SkNx<N,float> lerp(const SkNx<N,float>& a, const SkNx<N,float>& b,
-                                                 const SkNx<N,float>& t) {
+static inline Sk2f lerp(const Sk2f& a, const Sk2f& b, const Sk2f& t) {
     return SkNx_fma(t, b - a, a);
 }
 
@@ -329,54 +328,6 @@
     return ((c1 - c2).abs() <= 1).allTrue();
 }
 
-// Given a convex curve segment with the following order-2 tangent function:
-//
-//                                                       |C2x  C2y|
-//     tan = some_scale * |dx/dt  dy/dt| = |t^2  t  1| * |C1x  C1y|
-//                                                       |C0x  C0y|
-//
-// This function finds the T value whose tangent angle is halfway between the tangents at T=0 and
-// T=1 (tan0 and tan1).
-static inline float find_midtangent(const Sk2f& tan0, const Sk2f& tan1,
-                                    float scale2, const Sk2f& C2,
-                                    float scale1, const Sk2f& C1,
-                                    float scale0, const Sk2f& C0) {
-    // Tangents point in the direction of increasing T, so tan0 and -tan1 both point toward the
-    // midtangent. 'n' will therefore bisect tan0 and -tan1, giving us the normal to the midtangent.
-    //
-    //     n dot midtangent = 0
-    //
-    Sk2f n = normalize(tan0) - normalize(tan1);
-
-    // Find the T value at the midtangent. This is a simple quadratic equation:
-    //
-    //     midtangent dot n = 0
-    //
-    //     (|t^2  t  1| * C) dot n = 0
-    //
-    //     |t^2  t  1| dot C*n = 0
-    //
-    // First find coeffs = C*n.
-    Sk4f C[2];
-    Sk2f::Store4(C, C2, C1, C0, 0);
-    Sk4f coeffs = C[0]*n[0] + C[1]*n[1];
-    if (1 != scale2 || 1 != scale1 || 1 != scale0) {
-        coeffs *= Sk4f(scale2, scale1, scale0, 0);
-    }
-
-    // Now solve the quadratic.
-    float a = coeffs[0], b = coeffs[1], c = coeffs[2];
-    float discr = b*b - 4*a*c;
-    if (discr < 0) {
-        return 0; // This will only happen if the curve is a line.
-    }
-
-    // The roots are q/a and c/q. Pick the one closer to T=.5.
-    float q = -.5f * (b + copysignf(std::sqrt(discr), b));
-    float r = .5f*q*a;
-    return std::abs(q*q - r) < std::abs(a*c - r) ? q/a : c/q;
-}
-
 void GrCCGeometry::cubicTo(const SkPoint P[4], float inflectPad, float loopIntersectPad) {
     SkASSERT(fBuildingContour);
     SkASSERT(P[0] == fPoints.back());
@@ -535,7 +486,7 @@
         this->appendMonotonicCubics(p0, ab2, abc2, abcd2);
     } else if (T2 > T1) {
         // Section 3 (middle section).
-        Sk2f midp2 = lerp(abc2, abcd2, Sk2f(T1/T2));
+        Sk2f midp2 = lerp(abc2, abcd2, T1/T2);
         this->appendMonotonicCubics(midp0, midp1, midp2, abcd2);
     }
 
@@ -548,18 +499,25 @@
 inline void GrCCGeometry::chopCubicAtMidTangent(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2,
                                                 const Sk2f& p3, const Sk2f& tan0,
                                                 const Sk2f& tan1, int maxFutureSubdivisions) {
-    float midT = find_midtangent(tan0, tan1, 3, p3 + (p1 - p2)*3 - p0,
-                                             6, p0 - p1*2 + p2,
-                                             3, p1 - p0);
-    // Use positive logic since NaN fails comparisons. (However midT should not be NaN since we cull
-    // near-flat cubics in cubicTo().)
-    if (!(midT > 0 && midT < 1)) {
-        // The cubic is flat. Otherwise there would be a real midtangent inside T=0..1.
-        this->appendLine(p3);
+    // Find the T value whose tangent is perpendicular to the vector that bisects tan0 and -tan1.
+    Sk2f n = normalize(tan0) - normalize(tan1);
+
+    float a = 3 * dot(p3 + (p1 - p2)*3 - p0, n);
+    float b = 6 * dot(p0 - p1*2 + p2, n);
+    float c = 3 * dot(p1 - p0, n);
+
+    float discr = b*b - 4*a*c;
+    if (discr < 0) {
+        // If this is the case then the cubic must be nearly flat.
+        (this->*AppendLeftRight)(p0, p1, p2, p3, maxFutureSubdivisions);
         return;
     }
 
-    this->chopCubic<AppendLeftRight, AppendLeftRight>(p0, p1, p2, p3, midT, maxFutureSubdivisions);
+    float q = -.5f * (b + copysignf(std::sqrt(discr), b));
+    float m = .5f*q*a;
+    float T = std::abs(q*q - m) < std::abs(a*c - m) ? q/a : c/q;
+
+    this->chopCubic<AppendLeftRight, AppendLeftRight>(p0, p1, p2, p3, T, maxFutureSubdivisions);
 }
 
 template<GrCCGeometry::AppendCubicFn AppendLeft, GrCCGeometry::AppendCubicFn AppendRight>
@@ -652,87 +610,6 @@
     }
 }
 
-void GrCCGeometry::conicTo(const SkPoint P[3], float w) {
-    SkASSERT(fBuildingContour);
-    SkASSERT(P[0] == fPoints.back());
-    Sk2f p0 = Sk2f::Load(P);
-    Sk2f p1 = Sk2f::Load(P+1);
-    Sk2f p2 = Sk2f::Load(P+2);
-
-    // Don't crunch on the curve if it is nearly flat (or just very small). Collinear control points
-    // can break the midtangent-finding math below.
-    if (are_collinear(p0, p1, p2)) {
-        this->appendLine(p2);
-        return;
-    }
-
-    Sk2f tan0 = p1 - p0;
-    Sk2f tan1 = p2 - p1;
-    // The derivative of a conic has a cumbersome order-4 denominator. However, this isn't necessary
-    // if we are only interested in a vector in the same *direction* as a given tangent line. Since
-    // the denominator scales dx and dy uniformly, we can throw it out completely after evaluating
-    // the derivative with the standard quotient rule. This leaves us with a simpler quadratic
-    // function that we use to find the midtangent.
-    float midT = find_midtangent(tan0, tan1, 1, (w - 1) * (p2 - p0),
-                                             1, (p2 - p0) - 2*w*(p1 - p0),
-                                             1, w*(p1 - p0));
-    // Use positive logic since NaN fails comparisons. (However midT should not be NaN since we cull
-    // near-linear conics above. And while w=0 is flat, it's not a line and has valid midtangents.)
-    if (!(midT > 0 && midT < 1)) {
-        // The conic is flat. Otherwise there would be a real midtangent inside T=0..1.
-        this->appendLine(p2);
-        return;
-    }
-
-    // Evaluate the conic at midT.
-    Sk4f p3d0 = Sk4f(p0[0], p0[1], 1, 0);
-    Sk4f p3d1 = Sk4f(p1[0], p1[1], 1, 0) * w;
-    Sk4f p3d2 = Sk4f(p2[0], p2[1], 1, 0);
-    Sk4f midT4 = midT;
-
-    Sk4f p3d01 = lerp(p3d0, p3d1, midT4);
-    Sk4f p3d12 = lerp(p3d1, p3d2, midT4);
-    Sk4f p3d012 = lerp(p3d01, p3d12, midT4);
-
-    Sk2f midpoint = Sk2f(p3d012[0], p3d012[1]) / p3d012[2];
-
-    if (are_collinear(p0, midpoint, p2, 1) || // Check if the curve is within one pixel of flat.
-        ((midpoint - p1).abs() < 1).allTrue()) { // Check if the curve is almost a triangle.
-        // Draw the conic as a triangle instead. Our AA approximation won't do well if the curve
-        // gets wrapped too tightly, and if we get too close to p1 we will pick up artifacts from
-        // the implicit function's reflection.
-        this->appendLine(midpoint);
-        this->appendLine(p2);
-        return;
-    }
-
-    if (!is_convex_curve_monotonic(p0, tan0, p2, tan1)) {
-        // Chop the conic at midtangent to produce two monotonic segments.
-        Sk2f ww = Sk2f(p3d01[2], p3d12[2]) * Sk2f(p3d012[2]).rsqrt();
-        this->appendMonotonicConic(p0, Sk2f(p3d01[0], p3d01[1]) / p3d01[2], midpoint, ww[0]);
-        this->appendMonotonicConic(midpoint, Sk2f(p3d12[0], p3d12[1]) / p3d12[2], p2, ww[1]);
-        return;
-    }
-
-    this->appendMonotonicConic(p0, p1, p2, w);
-}
-
-void GrCCGeometry::appendMonotonicConic(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2, float w) {
-    SkASSERT(fPoints.back() == SkPoint::Make(p0[0], p0[1]));
-
-    // Don't send curves to the GPU if we know they are nearly flat (or just very small).
-    if (are_collinear(p0, p1, p2)) {
-        this->appendLine(p2);
-        return;
-    }
-
-    p1.store(&fPoints.push_back());
-    p2.store(&fPoints.push_back());
-    fConicWeights.push_back(w);
-    fVerbs.push_back(Verb::kMonotonicConicTo);
-    ++fCurrContourTallies.fConics;
-}
-
 GrCCGeometry::PrimitiveTallies GrCCGeometry::endContour() {
     SkASSERT(fBuildingContour);
     SkASSERT(fVerbs.count() >= fCurrContourTallies.fTriangles);
diff --git a/src/gpu/ccpr/GrCCGeometry.h b/src/gpu/ccpr/GrCCGeometry.h
index 7f098f9..01cf16c 100644
--- a/src/gpu/ccpr/GrCCGeometry.h
+++ b/src/gpu/ccpr/GrCCGeometry.h
@@ -31,7 +31,6 @@
         kLineTo,
         kMonotonicQuadraticTo, // Monotonic relative to the vector between its endpoints [P2 - P0].
         kMonotonicCubicTo,
-        kMonotonicConicTo,
         kEndClosedContour, // endPt == startPt.
         kEndOpenContour // endPt != startPt.
     };
@@ -42,7 +41,6 @@
         int fWeightedTriangles; // Triangles (from the tessellator) whose winding magnitude > 1.
         int fQuadratics;
         int fCubics;
-        int fConics;
 
         void operator+=(const PrimitiveTallies&);
         PrimitiveTallies operator-(const PrimitiveTallies&) const;
@@ -55,7 +53,6 @@
 
     const SkTArray<SkPoint, true>& points() const { SkASSERT(!fBuildingContour); return fPoints; }
     const SkTArray<Verb, true>& verbs() const { SkASSERT(!fBuildingContour); return fVerbs; }
-    float getConicWeight(int idx) const { SkASSERT(!fBuildingContour); return fConicWeights[idx]; }
 
     void reset() {
         SkASSERT(!fBuildingContour);
@@ -92,8 +89,6 @@
     //       intersection vs. 1.489 on the tiger).
     void cubicTo(const SkPoint[4], float inflectPad = 0.55f, float loopIntersectPad = 2);
 
-    void conicTo(const SkPoint[3], float w);
-
     PrimitiveTallies endContour(); // Returns the numbers of primitives needed to draw the contour.
 
 private:
@@ -121,17 +116,15 @@
     void appendCubicApproximation(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2, const Sk2f& p3,
                                   int maxSubdivisions = kMaxSubdivionsPerCubicSection);
 
-    void appendMonotonicConic(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2, float w);
-
     // Transient state used while building a contour.
     SkPoint fCurrAnchorPoint;
     PrimitiveTallies fCurrContourTallies;
     SkCubicType fCurrCubicType;
     SkDEBUGCODE(bool fBuildingContour = false);
 
-    SkSTArray<128, SkPoint, true> fPoints;
-    SkSTArray<32, float, true> fConicWeights;
-    SkSTArray<128, Verb, true> fVerbs;
+    // TODO: These points could eventually be written directly to block-allocated GPU buffers.
+    SkSTArray<128, SkPoint, true>   fPoints;
+    SkSTArray<128, Verb, true>      fVerbs;
 };
 
 inline void GrCCGeometry::PrimitiveTallies::operator+=(const PrimitiveTallies& b) {
@@ -139,7 +132,6 @@
     fWeightedTriangles += b.fWeightedTriangles;
     fQuadratics += b.fQuadratics;
     fCubics += b.fCubics;
-    fConics += b.fConics;
 }
 
 GrCCGeometry::PrimitiveTallies
@@ -147,13 +139,12 @@
     return {fTriangles - b.fTriangles,
             fWeightedTriangles - b.fWeightedTriangles,
             fQuadratics - b.fQuadratics,
-            fCubics - b.fCubics,
-            fConics - b.fConics};
+            fCubics - b.fCubics};
 }
 
 inline bool GrCCGeometry::PrimitiveTallies::operator==(const PrimitiveTallies& b) {
     return fTriangles == b.fTriangles && fWeightedTriangles == b.fWeightedTriangles &&
-           fQuadratics == b.fQuadratics && fCubics == b.fCubics && fConics == b.fConics;
+           fQuadratics == b.fQuadratics && fCubics == b.fCubics;
 }
 
 #endif
diff --git a/src/gpu/ccpr/GrCCPathParser.cpp b/src/gpu/ccpr/GrCCPathParser.cpp
index 2740569..f77c52e 100644
--- a/src/gpu/ccpr/GrCCPathParser.cpp
+++ b/src/gpu/ccpr/GrCCPathParser.cpp
@@ -114,9 +114,7 @@
         return;
     }
 
-    const float* conicWeights = SkPathPriv::ConicWeightData(path);
     int ptsIdx = 0;
-    int conicWeightsIdx = 0;
     bool insideContour = false;
 
     for (SkPath::Verb verb : SkPathPriv::Verbs(path)) {
@@ -144,16 +142,11 @@
                 ptsIdx += 3;
                 continue;
             case SkPath::kConic_Verb:
-                fGeometry.conicTo(&deviceSpacePts[ptsIdx - 1], conicWeights[conicWeightsIdx]);
-                ptsIdx += 2;
-                ++conicWeightsIdx;
-                continue;
+                SK_ABORT("Conics are not supported.");
             default:
                 SK_ABORT("Unexpected path verb.");
         }
     }
-    SkASSERT(ptsIdx == path.countPoints());
-    SkASSERT(conicWeightsIdx == SkPathPriv::ConicWeightCnt(path));
 
     this->endContourIfNeeded(insideContour);
 }
@@ -203,7 +196,6 @@
                     continue;
 
                 case GrCCGeometry::Verb::kMonotonicQuadraticTo:
-                case GrCCGeometry::Verb::kMonotonicConicTo:
                     fan.lineTo(pts[ptsIdx + 1]);
                     ptsIdx += 2;
                     continue;
@@ -385,9 +377,7 @@
     fBaseInstances[0].fCubics = fBaseInstances[1].fWeightedTriangles +
                                 fTotalPrimitiveCounts[1].fWeightedTriangles;
     fBaseInstances[1].fCubics = fBaseInstances[0].fCubics + fTotalPrimitiveCounts[0].fCubics;
-    fBaseInstances[0].fConics = fBaseInstances[1].fCubics + fTotalPrimitiveCounts[1].fCubics;
-    fBaseInstances[1].fConics = fBaseInstances[0].fConics + fTotalPrimitiveCounts[0].fConics;
-    int quadEndIdx = fBaseInstances[1].fConics + fTotalPrimitiveCounts[1].fConics;
+    int quadEndIdx = fBaseInstances[1].fCubics + fTotalPrimitiveCounts[1].fCubics;
 
     fInstanceBuffer = onFlushRP->makeBuffer(kVertex_GrBufferType,
                                             quadEndIdx * sizeof(QuadPointInstance));
@@ -410,7 +400,6 @@
 
     const SkTArray<SkPoint, true>& pts = fGeometry.points();
     int ptsIdx = -1;
-    int nextConicWeightIdx = 0;
 
     // Expand the ccpr verbs into GPU instance buffers.
     for (GrCCGeometry::Verb verb : fGeometry.verbs()) {
@@ -465,17 +454,6 @@
                 }
                 continue;
 
-            case GrCCGeometry::Verb::kMonotonicConicTo:
-                quadPointInstanceData[currIndices->fConics++].setW(
-                        &pts[ptsIdx], atlasOffset, fGeometry.getConicWeight(nextConicWeightIdx));
-                ptsIdx += 2;
-                ++nextConicWeightIdx;
-                if (!currFanIsTessellated) {
-                    SkASSERT(!currFan.empty());
-                    currFan.push_back(ptsIdx);
-                }
-                continue;
-
             case GrCCGeometry::Verb::kEndClosedContour:  // endPt == startPt.
                 if (!currFanIsTessellated) {
                     SkASSERT(!currFan.empty());
@@ -511,9 +489,7 @@
     SkASSERT(instanceIndices[0].fWeightedTriangles == fBaseInstances[1].fWeightedTriangles);
     SkASSERT(instanceIndices[1].fWeightedTriangles == fBaseInstances[0].fCubics);
     SkASSERT(instanceIndices[0].fCubics == fBaseInstances[1].fCubics);
-    SkASSERT(instanceIndices[1].fCubics == fBaseInstances[0].fConics);
-    SkASSERT(instanceIndices[0].fConics == fBaseInstances[1].fConics);
-    SkASSERT(instanceIndices[1].fConics == quadEndIdx);
+    SkASSERT(instanceIndices[1].fCubics == quadEndIdx);
 
     fMeshesScratchBuffer.reserve(fMaxMeshesPerDraw);
     fDynamicStatesScratchBuffer.reserve(fMaxMeshesPerDraw);
@@ -551,11 +527,6 @@
         this->drawPrimitives(flushState, pipeline, batchID, PrimitiveType::kCubics,
                              &PrimitiveTallies::fCubics, drawBounds);
     }
-
-    if (batchTotalCounts.fConics) {
-        this->drawPrimitives(flushState, pipeline, batchID, PrimitiveType::kConics,
-                             &PrimitiveTallies::fConics, drawBounds);
-    }
 }
 
 void GrCCPathParser::drawPrimitives(GrOpFlushState* flushState, const GrPipeline& pipeline,
diff --git a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
index b6f5770..90d89de 100644
--- a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
+++ b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
@@ -65,6 +65,10 @@
 
     SkPath path;
     args.fShape->asPath(&path);
+    if (SkPathPriv::ConicWeightCnt(path)) {
+        return CanDrawPath::kNo;
+    }
+
     SkRect devBounds;
     SkIRect devIBounds;
     args.fViewMatrix->mapRect(&devBounds, path.getBounds());
@@ -189,6 +193,11 @@
     if (!fDrawCachablePaths && !deviceSpacePath.isVolatile()) {
         return false;
     }
+
+    if (SkPathPriv::ConicWeightCnt(deviceSpacePath)) {
+        return false;
+    }
+
     return true;
 }