Don't use AA convex path renderer if direction can't be determined

Without the changes to GrShape and GrAAConvexPathRenderer, this new GM
would not draw the red circle at the center when using Ganesh. Raster
drew the red circle. The difference came about because they checked
convexity after transforming by the view matrix, and Ganesh checked
before.

With this particular path construction and the very large scale factor
on the CTM, the convexity calculator in local space computed small
enough edge vectors that it thought the contour backtracked on itself
instead of winding in a consistent direction.

The GrAAConvexPathRenderer would claim it could draw the convex path,
but later when actually preparing to draw, it would do nothing if it
turned out the convex path didn't have a direction. This CL updates it
so that the convex path renderer's canDraw() function matches what it
is actually able to draw.

There is the separate issue of the convexity/direction checking
precision.

Bug: chromium:996140
Change-Id: I6f2af2d9ba6752663d97c8573deb2d767a3f1245
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/238121
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Chris Dalton <csmartdalton@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/gpu/ops/GrAAConvexPathRenderer.cpp b/src/gpu/ops/GrAAConvexPathRenderer.cpp
index 5021aa7..4aa860f 100644
--- a/src/gpu/ops/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAAConvexPathRenderer.cpp
@@ -219,19 +219,21 @@
     }
 }
 
-static inline bool get_direction(const SkPath& path, const SkMatrix& m,
-                                 SkPathPriv::FirstDirection* dir) {
-    if (!SkPathPriv::CheapComputeFirstDirection(path, dir)) {
-        return false;
-    }
+static inline SkPathPriv::FirstDirection get_direction(const SkPath& path, const SkMatrix& m) {
+    // At this point, we've already returned true from canDraw(), which checked that the path's
+    // direction could be determined, so this should just be fetching the cached direction.
+    SkPathPriv::FirstDirection dir;
+    SkAssertResult(SkPathPriv::CheapComputeFirstDirection(path, &dir));
+
     // check whether m reverses the orientation
     SkASSERT(!m.hasPerspective());
     SkScalar det2x2 = m.get(SkMatrix::kMScaleX) * m.get(SkMatrix::kMScaleY) -
                       m.get(SkMatrix::kMSkewX)  * m.get(SkMatrix::kMSkewY);
     if (det2x2 < 0) {
-        *dir = SkPathPriv::OppositeFirstDirection(*dir);
+        dir = SkPathPriv::OppositeFirstDirection(dir);
     }
-    return true;
+
+    return dir;
 }
 
 static inline void add_line_to_segment(const SkPoint& pt,
@@ -281,11 +283,7 @@
     // line paths. We detect paths that are very close to a line (zero area) and
     // draw nothing.
     DegenerateTestData degenerateData;
-    SkPathPriv::FirstDirection dir;
-    // get_direction can fail for some degenerate paths.
-    if (!get_direction(path, m, &dir)) {
-        return false;
-    }
+    SkPathPriv::FirstDirection dir = get_direction(path, m);
 
     for (;;) {
         SkPoint pts[4];
@@ -661,9 +659,12 @@
 
 GrPathRenderer::CanDrawPath
 GrAAConvexPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
+    // This check requires convexity and known direction, since the direction is used to build
+    // the geometry segments. Degenerate convex paths will fall through to some other path renderer.
     if (args.fCaps->shaderCaps()->shaderDerivativeSupport() &&
         (GrAAType::kCoverage == args.fAAType) && args.fShape->style().isSimpleFill() &&
-        !args.fShape->inverseFilled() && args.fShape->knownToBeConvex()) {
+        !args.fShape->inverseFilled() && args.fShape->knownToBeConvex() &&
+        args.fShape->knownDirection()) {
         return CanDrawPath::kYes;
     }
     return CanDrawPath::kNo;