Guard default path renderer against buffer allocation failure

Apparently the guarantee of buffer space has been refactored out from
underneath this class.

Bug: 1223365
Change-Id: I9beb9566a641933322bd946a5067eeafb9c4c013
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/422636
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/gpu/ops/GrDefaultPathRenderer.cpp b/src/gpu/ops/GrDefaultPathRenderer.cpp
index f9ced05..a1c122a 100644
--- a/src/gpu/ops/GrDefaultPathRenderer.cpp
+++ b/src/gpu/ops/GrDefaultPathRenderer.cpp
@@ -88,7 +88,9 @@
      *  Path verbs
      */
     void moveTo(const SkPoint& p) {
-        this->needSpace(1);
+        if (!this->ensureSpace(1)) {
+            return;
+        }
 
         if (!this->isHairline()) {
             fSubpathIndexStart = this->currentIndex();
@@ -98,7 +100,9 @@
     }
 
     void addLine(const SkPoint pts[]) {
-        this->needSpace(1, this->indexScale(), &pts[0]);
+        if (!this->ensureSpace(1, this->indexScale(), &pts[0])) {
+            return;
+        }
 
         if (this->isIndexed()) {
             uint16_t prevIdx = this->currentIndex() - 1;
@@ -108,9 +112,11 @@
     }
 
     void addQuad(const SkPoint pts[], SkScalar srcSpaceTolSqd, SkScalar srcSpaceTol) {
-        this->needSpace(GrPathUtils::kMaxPointsPerCurve,
-                        GrPathUtils::kMaxPointsPerCurve * this->indexScale(),
-                        &pts[0]);
+        if (!this->ensureSpace(GrPathUtils::kMaxPointsPerCurve,
+                             GrPathUtils::kMaxPointsPerCurve * this->indexScale(),
+                             &pts[0])) {
+            return;
+        }
 
         // First pt of quad is the pt we ended on in previous step
         uint16_t firstQPtIdx = this->currentIndex() - 1;
@@ -134,9 +140,11 @@
     }
 
     void addCubic(const SkPoint pts[], SkScalar srcSpaceTolSqd, SkScalar srcSpaceTol) {
-        this->needSpace(GrPathUtils::kMaxPointsPerCurve,
-                        GrPathUtils::kMaxPointsPerCurve * this->indexScale(),
-                        &pts[0]);
+        if (!this->ensureSpace(GrPathUtils::kMaxPointsPerCurve,
+                             GrPathUtils::kMaxPointsPerCurve * this->indexScale(),
+                             &pts[0])) {
+            return;
+        }
 
         // First pt of cubic is the pt we ended on in previous step
         uint16_t firstCPtIdx = this->currentIndex() - 1;
@@ -227,6 +235,8 @@
 
     // Allocate vertex and (possibly) index buffers
     void allocNewBuffers() {
+        SkASSERT(fValid);
+
         // Ensure that we always get enough verts for a worst-case quad/cubic, plus leftover points
         // from previous mesh piece (up to two verts to continue fanning). If we can't get that
         // many, ask for a much larger number. This needs to be fairly big to handle  quads/cubics,
@@ -240,6 +250,14 @@
                                                                           &fVertexBuffer,
                                                                           &fFirstVertex,
                                                                           &fVerticesInChunk));
+        if (!fVertices) {
+            SkDebugf("WARNING: Failed to allocate vertex buffer for GrDefaultPathRenderer.\n");
+            fCurVert = nullptr;
+            fCurIdx = fIndices = nullptr;
+            fSubpathIndexStart = 0;
+            fValid = false;
+            return;
+        }
 
         if (this->isIndexed()) {
             // Similar to above: Ensure we get enough indices for one worst-case quad/cubic.
@@ -251,6 +269,11 @@
             fIndices = fTarget->makeIndexSpaceAtLeast(kMinIndicesPerChunk, kFallbackIndicesPerChunk,
                                                       &fIndexBuffer, &fFirstIndex,
                                                       &fIndicesInChunk);
+            if (!fIndices) {
+                SkDebugf("WARNING: Failed to allocate index buffer for GrDefaultPathRenderer.\n");
+                fVertices = nullptr;
+                fValid = false;
+            }
         }
 
         fCurVert = fVertices;
@@ -259,6 +282,8 @@
     }
 
     void appendCountourEdgeIndices(uint16_t edgeV0Idx) {
+        SkASSERT(fCurIdx);
+
         // When drawing lines we're appending line segments along the countour. When applying the
         // other fill rules we're drawing triangle fans around the start of the current (sub)path.
         if (!this->isHairline()) {
@@ -270,6 +295,10 @@
 
     // Emits a single draw with all accumulated vertex/index data
     void createMeshAndPutBackReserve() {
+        if (!fValid) {
+            return;
+        }
+
         int vertexCount = fCurVert - fVertices;
         int indexCount = fCurIdx - fIndices;
         SkASSERT(vertexCount <= fVerticesInChunk);
@@ -295,7 +324,11 @@
         }
     }
 
-    void needSpace(int vertsNeeded, int indicesNeeded = 0, const SkPoint* lastPoint = nullptr) {
+    bool ensureSpace(int vertsNeeded, int indicesNeeded = 0, const SkPoint* lastPoint = nullptr) {
+        if (!fValid) {
+            return false;
+        }
+
         if (fCurVert + vertsNeeded > fVertices + fVerticesInChunk ||
             fCurIdx + indicesNeeded > fIndices + fIndicesInChunk) {
             // We are about to run out of space (possibly)
@@ -320,6 +353,9 @@
 
             // Get new buffers
             this->allocNewBuffers();
+            if (!fValid) {
+                return false;
+            }
 
             // On moves we don't need to copy over any points to the new buffer and we pass in a
             // null lastPoint.
@@ -331,6 +367,8 @@
                 *(fCurVert++) = *lastPoint;
             }
         }
+
+        return true;
     }
 
     GrPrimitiveType fPrimitiveType;
@@ -351,6 +389,7 @@
     uint16_t fSubpathIndexStart;
     SkPoint fSubpathStartPoint;
 
+    bool fValid = true;
     SkTDArray<GrSimpleMesh*>* fMeshes;
 };