1 /* 2 * Copyright 2018 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef GrCCStroker_DEFINED 9 #define GrCCStroker_DEFINED 10 11 #include "include/private/SkNx.h" 12 #include "src/gpu/GrAllocator.h" 13 #include "src/gpu/GrMesh.h" 14 #include "src/gpu/ccpr/GrCCStrokeGeometry.h" 15 16 class GrGpuBuffer; 17 class GrCCCoverageProcessor; 18 class GrOnFlushResourceProvider; 19 class GrOpFlushState; 20 class GrPipeline; 21 class GrPrimitiveProcessor; 22 class SkMatrix; 23 class SkPath; 24 class SkStrokeRec; 25 26 /** 27 * This class parses stroked SkPaths into a GPU instance buffer, then issues calls to draw their 28 * coverage counts. 29 */ 30 class GrCCStroker { 31 public: GrCCStroker(int numPaths,int numSkPoints,int numSkVerbs)32 GrCCStroker(int numPaths, int numSkPoints, int numSkVerbs) 33 : fGeometry(numSkPoints, numSkVerbs), fPathInfos(numPaths) {} 34 35 // Parses a device-space SkPath into the current batch, using the SkPath's original verbs with 36 // 'deviceSpacePts', and the SkStrokeRec's original settings with 'strokeDevWidth'. Accepts an 37 // optional post-device-space translate for placement in an atlas. 38 // 39 // Strokes intended as hairlines must have a strokeDevWidth of 1. Non-hairline strokes can only 40 // be drawn with rigid body transforms; affine transformation of the stroke lines themselves is 41 // not yet supported. 42 void parseDeviceSpaceStroke(const SkPath&, const SkPoint* deviceSpacePts, const SkStrokeRec&, 43 float strokeDevWidth, GrScissorTest, 44 const SkIRect& clippedDevIBounds, 45 const SkIVector& devToAtlasOffset); 46 47 using BatchID = int; 48 49 // Compiles the outstanding parsed paths into a batch, and returns an ID that can be used to 50 // draw their strokes in the future. 51 BatchID closeCurrentBatch(); 52 53 // Builds an internal GPU buffer and prepares for calls to drawStrokes(). Caller must close the 54 // current batch before calling this method, and cannot parse new paths afer. 55 bool prepareToDraw(GrOnFlushResourceProvider*); 56 57 // Called after prepareToDraw(). Draws the given batch of path strokes. 58 void drawStrokes( 59 GrOpFlushState*, GrCCCoverageProcessor*, BatchID, const SkIRect& drawBounds) const; 60 61 private: 62 static constexpr int kNumScissorModes = 2; 63 static constexpr BatchID kEmptyBatchID = -1; 64 using Verb = GrCCStrokeGeometry::Verb; 65 using InstanceTallies = GrCCStrokeGeometry::InstanceTallies; 66 67 // Every kBeginPath verb has a corresponding PathInfo entry. 68 struct PathInfo { 69 SkIVector fDevToAtlasOffset; 70 float fStrokeRadius; 71 GrScissorTest fScissorTest; 72 }; 73 74 // Defines a sub-batch of stroke instances that have a scissor test and the same scissor rect. 75 // Start indices are deduced by looking at the previous ScissorSubBatch. 76 struct ScissorSubBatch { ScissorSubBatchScissorSubBatch77 ScissorSubBatch(GrTAllocator<InstanceTallies>* alloc, const InstanceTallies& startIndices, 78 const SkIRect& scissor) 79 : fEndInstances(&alloc->emplace_back(startIndices)), fScissor(scissor) {} 80 InstanceTallies* fEndInstances; 81 SkIRect fScissor; 82 }; 83 84 // Defines a batch of stroke instances that can be drawn with drawStrokes(). Start indices are 85 // deduced by looking at the previous Batch in the list. 86 struct Batch { BatchBatch87 Batch(GrTAllocator<InstanceTallies>* alloc, const InstanceTallies& startNonScissorIndices, 88 int startScissorSubBatch) 89 : fNonScissorEndInstances(&alloc->emplace_back(startNonScissorIndices)) 90 , fEndScissorSubBatch(startScissorSubBatch) {} 91 InstanceTallies* fNonScissorEndInstances; 92 int fEndScissorSubBatch; 93 }; 94 95 class InstanceBufferBuilder; 96 97 void appendStrokeMeshesToBuffers(int numSegmentsLog2, const Batch&, 98 const InstanceTallies* startIndices[2], 99 int startScissorSubBatch, const SkIRect& drawBounds) const; 100 void flushBufferedMeshesAsStrokes(const GrPrimitiveProcessor&, GrOpFlushState*, const 101 GrPipeline&, const SkIRect& drawBounds) const; 102 103 template<int GrCCStrokeGeometry::InstanceTallies::* InstanceType> 104 void drawConnectingGeometry(GrOpFlushState*, const GrPipeline&, 105 const GrCCCoverageProcessor&, const Batch&, 106 const InstanceTallies* startIndices[2], int startScissorSubBatch, 107 const SkIRect& drawBounds) const; 108 109 GrCCStrokeGeometry fGeometry; 110 SkSTArray<32, PathInfo> fPathInfos; 111 SkSTArray<32, Batch> fBatches; 112 SkSTArray<32, ScissorSubBatch> fScissorSubBatches; 113 int fMaxNumScissorSubBatches = 0; 114 bool fHasOpenBatch = false; 115 116 const InstanceTallies fZeroTallies = InstanceTallies(); 117 GrSTAllocator<128, InstanceTallies> fTalliesAllocator; 118 const InstanceTallies* fInstanceCounts[kNumScissorModes] = {&fZeroTallies, &fZeroTallies}; 119 120 sk_sp<GrGpuBuffer> fInstanceBuffer; 121 // The indices stored in batches are relative to these base instances. 122 InstanceTallies fBaseInstances[kNumScissorModes]; 123 124 mutable SkSTArray<32, GrMesh> fMeshesBuffer; 125 mutable SkSTArray<32, SkIRect> fScissorsBuffer; 126 }; 127 128 #endif 129