Write GPU buffers directly from GrStrokeGeometry

Removes the intermediate stroke representation that GrStrokeGeometry
used to generate. Uses GrOpFlushState::makeVertexStateAtLeast instead
and writes patches directly to a vertex buffer as we iterate the path.
If the vertex buffer runs out of room we simply allocate a new one and
draw the stroke in chunks.

Bug: skia:10419
Bug: skia:10460
Change-Id: Ic743158366e43d4d3f5a4ff97b039d48c9c9c65b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/305380
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
diff --git a/samplecode/SampleCCPRGeometry.cpp b/samplecode/SampleCCPRGeometry.cpp
index 0aa8100..758c076 100644
--- a/samplecode/SampleCCPRGeometry.cpp
+++ b/samplecode/SampleCCPRGeometry.cpp
@@ -26,7 +26,6 @@
 #include "src/gpu/GrResourceProvider.h"
 #include "src/gpu/ccpr/GrCCCoverageProcessor.h"
 #include "src/gpu/ccpr/GrCCFillGeometry.h"
-#include "src/gpu/ccpr/GrCCStroker.h"
 #include "src/gpu/ccpr/GrGSCoverageProcessor.h"
 #include "src/gpu/ccpr/GrVSCoverageProcessor.h"
 #include "src/gpu/geometry/GrPathUtils.h"
@@ -66,7 +65,7 @@
 
     void updateGpuData();
 
-    PrimitiveType fPrimitiveType = PrimitiveType::kTriangles;
+    PrimitiveType fPrimitiveType = PrimitiveType::kCubics;
     SkCubicType fCubicType;
     SkMatrix fCubicKLM;
 
@@ -75,7 +74,9 @@
 
     float fConicWeight = .5;
     float fStrokeWidth = 40;
-    bool fDoStroke = false;
+    SkPaint::Join fStrokeJoin = SkPaint::kMiter_Join;
+    SkPaint::Cap fStrokeCap = SkPaint::kButt_Cap;
+    bool fDoStroke = true;
 
     SkTArray<TriPointInstance> fTriPointInstances;
     SkTArray<QuadPointInstance> fQuadPointInstances;
@@ -176,14 +177,18 @@
 void CCPRGeometryView::onDrawContent(SkCanvas* canvas) {
     canvas->clear(SK_ColorBLACK);
 
-    if (!fDoStroke) {
-        SkPaint outlinePaint;
-        outlinePaint.setColor(0x80ffffff);
-        outlinePaint.setStyle(SkPaint::kStroke_Style);
+    SkPaint outlinePaint;
+    outlinePaint.setColor(0xff808080);
+    outlinePaint.setStyle(SkPaint::kStroke_Style);
+    if (fDoStroke) {
+        outlinePaint.setStrokeWidth(fStrokeWidth);
+    } else {
         outlinePaint.setStrokeWidth(0);
-        outlinePaint.setAntiAlias(true);
-        canvas->drawPath(fPath, outlinePaint);
     }
+    outlinePaint.setStrokeJoin(fStrokeJoin);
+    outlinePaint.setStrokeCap(fStrokeCap);
+    outlinePaint.setAntiAlias(true);
+    canvas->drawPath(fPath, outlinePaint);
 
 #if 0
     SkPaint gridPaint;
@@ -200,7 +205,18 @@
 #endif
 
     SkString caption;
-    if (GrRenderTargetContext* rtc = canvas->internal_private_accessTopLayerRenderTargetContext()) {
+    caption.appendf("PrimitiveType_%s",
+                    GrCCCoverageProcessor::PrimitiveTypeName(fPrimitiveType));
+    if (PrimitiveType::kCubics == fPrimitiveType) {
+        caption.appendf(" (%s)", SkCubicTypeName(fCubicType));
+    } else if (PrimitiveType::kConics == fPrimitiveType) {
+        caption.appendf(" (w=%f)", fConicWeight);
+    }
+
+    if (fDoStroke) {
+        caption.appendf(" (stroke_width=%f)", fStrokeWidth);
+    } else if (GrRenderTargetContext* rtc =
+            canvas->internal_private_accessTopLayerRenderTargetContext()) {
         // Render coverage count.
         auto ctx = canvas->recordingContext();
         SkASSERT(ctx);
@@ -222,18 +238,6 @@
         paint.setPorterDuffXPFactory(SkBlendMode::kSrcOver);
         rtc->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
                       SkRect::MakeIWH(this->width(), this->height()));
-
-        // Add label.
-        caption.appendf("PrimitiveType_%s",
-                        GrCCCoverageProcessor::PrimitiveTypeName(fPrimitiveType));
-        if (PrimitiveType::kCubics == fPrimitiveType) {
-            caption.appendf(" (%s)", SkCubicTypeName(fCubicType));
-        } else if (PrimitiveType::kConics == fPrimitiveType) {
-            caption.appendf(" (w=%f)", fConicWeight);
-        }
-        if (fDoStroke) {
-            caption.appendf(" (stroke_width=%f)", fStrokeWidth);
-        }
     } else {
         caption = "Use GPU backend to visualize geometry.";
     }
@@ -345,8 +349,8 @@
 void CCPRGeometryView::DrawCoverageCountOp::onExecute(GrOpFlushState* state,
                                                       const SkRect& chainBounds) {
     GrResourceProvider* rp = state->resourceProvider();
-    auto direct = state->gpu()->getContext();
 #ifdef SK_GL
+    auto direct = state->gpu()->getContext();
     GrGLGpu* glGpu = GrBackendApi::kOpenGL == direct->backend()
                              ? static_cast<GrGLGpu*>(state->gpu())
                              : nullptr;
@@ -370,52 +374,30 @@
 
     GrOpsRenderPass* renderPass = state->opsRenderPass();
 
-    if (!fView->fDoStroke) {
-        for (int i = 0; i < proc->numSubpasses(); ++i) {
-            proc->reset(fView->fPrimitiveType, i, rp);
-            proc->bindPipeline(state, pipeline, this->bounds());
+    for (int i = 0; i < proc->numSubpasses(); ++i) {
+        proc->reset(fView->fPrimitiveType, i, rp);
+        proc->bindPipeline(state, pipeline, this->bounds());
 
-            if (PrimitiveType::kCubics == fView->fPrimitiveType ||
-                PrimitiveType::kConics == fView->fPrimitiveType) {
-                sk_sp<GrGpuBuffer> instBuff(rp->createBuffer(
-                        fView->fQuadPointInstances.count() * sizeof(QuadPointInstance),
-                        GrGpuBufferType::kVertex, kDynamic_GrAccessPattern,
-                        fView->fQuadPointInstances.begin()));
-                if (!fView->fQuadPointInstances.empty() && instBuff) {
-                    proc->bindBuffers(renderPass, std::move(instBuff));
-                    proc->drawInstances(renderPass, fView->fQuadPointInstances.count(), 0);
-                }
-            } else {
-                sk_sp<GrGpuBuffer> instBuff(rp->createBuffer(
-                        fView->fTriPointInstances.count() * sizeof(TriPointInstance),
-                        GrGpuBufferType::kVertex, kDynamic_GrAccessPattern,
-                        fView->fTriPointInstances.begin()));
-                if (!fView->fTriPointInstances.empty() && instBuff) {
-                    proc->bindBuffers(renderPass, std::move(instBuff));
-                    proc->drawInstances(renderPass, fView->fTriPointInstances.count(), 0);
-                }
+        if (PrimitiveType::kCubics == fView->fPrimitiveType ||
+            PrimitiveType::kConics == fView->fPrimitiveType) {
+            sk_sp<GrGpuBuffer> instBuff(rp->createBuffer(
+                    fView->fQuadPointInstances.count() * sizeof(QuadPointInstance),
+                    GrGpuBufferType::kVertex, kDynamic_GrAccessPattern,
+                    fView->fQuadPointInstances.begin()));
+            if (!fView->fQuadPointInstances.empty() && instBuff) {
+                proc->bindBuffers(renderPass, std::move(instBuff));
+                proc->drawInstances(renderPass, fView->fQuadPointInstances.count(), 0);
+            }
+        } else {
+            sk_sp<GrGpuBuffer> instBuff(rp->createBuffer(
+                    fView->fTriPointInstances.count() * sizeof(TriPointInstance),
+                    GrGpuBufferType::kVertex, kDynamic_GrAccessPattern,
+                    fView->fTriPointInstances.begin()));
+            if (!fView->fTriPointInstances.empty() && instBuff) {
+                proc->bindBuffers(renderPass, std::move(instBuff));
+                proc->drawInstances(renderPass, fView->fTriPointInstances.count(), 0);
             }
         }
-    } else if (PrimitiveType::kConics != fView->fPrimitiveType) {  // No conic stroke support yet.
-        GrCCStroker stroker(0,0,0);
-
-        SkPaint p;
-        p.setStyle(SkPaint::kStroke_Style);
-        p.setStrokeWidth(fView->fStrokeWidth);
-        p.setStrokeJoin(SkPaint::kMiter_Join);
-        p.setStrokeMiter(4);
-        // p.setStrokeCap(SkPaint::kRound_Cap);
-        stroker.parseDeviceSpaceStroke(fView->fPath, SkPathPriv::PointData(fView->fPath),
-                                       SkStrokeRec(p), p.getStrokeWidth(), GrScissorTest::kDisabled,
-                                       SkIRect::MakeWH(fView->width(), fView->height()), {0, 0});
-        GrCCStroker::BatchID batchID = stroker.closeCurrentBatch();
-
-        GrOnFlushResourceProvider onFlushRP(direct->priv().drawingManager());
-        stroker.prepareToDraw(&onFlushRP);
-
-        SkIRect ibounds;
-        this->bounds().roundOut(&ibounds);
-        stroker.drawStrokes(state, proc.get(), batchID, ibounds);
     }
 
 #ifdef SK_GL
@@ -511,6 +493,17 @@
         if (unichar == 'S') {
             fDoStroke = !fDoStroke;
             this->updateAndInval();
+            return true;
+        }
+        if (unichar == 'J') {
+            fStrokeJoin = (SkPaint::Join)((fStrokeJoin + 1) % 3);
+            this->updateAndInval();
+            return true;
+        }
+        if (unichar == 'C') {
+            fStrokeCap = (SkPaint::Cap)((fStrokeCap + 1) % 3);
+            this->updateAndInval();
+            return true;
         }
         return false;
 }