1 /* 2 * Copyright 2020 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 GrStrokeIndirectTessellator_DEFINED 9 #define GrStrokeIndirectTessellator_DEFINED 10 11 #include "src/gpu/tessellate/GrStrokeTessellator.h" 12 13 struct GrVertexWriter; 14 struct SkPoint; 15 namespace skiatest { class Reporter; } 16 17 // This class bins strokes into indirect draws for consumption by GrStrokeTessellateShader. 18 class GrStrokeIndirectTessellator : public GrStrokeTessellator { 19 public: 20 // Don't allow more than 2^15 stroke edges in a triangle strip. GrTessellationPathRenderer 21 // already crops paths that require more than 2^10 parametric segments, so this should only 22 // become an issue if we try to draw a stroke with an astronomically wide width. 23 constexpr static int8_t kMaxResolveLevel = 15; 24 25 GrStrokeIndirectTessellator(ShaderFlags, const SkMatrix& viewMatrix, PathStrokeList*, 26 int totalCombinedVerbCnt, SkArenaAlloc*); 27 28 // Adds the given tessellator to our chain. The chained tessellators all append to a shared 29 // indirect draw list during prepare(). 30 void addToChain(GrStrokeIndirectTessellator*); 31 32 void prepare(GrMeshDrawOp::Target*, int totalCombinedVerbCnt) override; 33 34 void draw(GrOpFlushState*) const override; 35 36 private: 37 // Called during prepare(). Appends our indirect-draw commands and instance data onto the 38 // provided writers. 39 void writeBuffers(GrDrawIndirectWriter*, GrVertexWriter*, const SkMatrix&, 40 size_t instanceStride, int baseInstance, int numExtraEdgesInJoin); 41 42 int fResolveLevelCounts[kMaxResolveLevel + 1] = {0}; // # of instances at each resolve level. 43 int fTotalInstanceCount = 0; // Total number of stroke instances we will draw. 44 // Total number of indirect draw commands in the chain, or zero if we are not the chain head. 45 int fChainedDrawIndirectCount = 0; 46 // Total number of stroke instances in the entire chain, or zero if we are not the chain head. 47 int fChainedInstanceCount = 0; 48 49 // This array holds a resolveLevel for each stroke in the path, stored in the iteration order of 50 // GrStrokeIterator. If a stroke needs to be chopped, the array will contain a negative number 51 // whose absolute value is the number of chops required, followed by a resolveLevel for each 52 // resulting stroke after the chop(s). 53 int8_t* fResolveLevels = nullptr; 54 // fResolveLevelArrayCount != fTotalInstanceCount because we don't always need to write out 55 // resolve levels for line instances. (If they don't have round caps then their resolve level is 56 // just 0.) 57 SkDEBUGCODE(int fResolveLevelArrayCount = 0;) 58 59 // Stores the in-order chop locations for all chops indicated by fResolveLevels. 60 float* fChopTs = nullptr; 61 SkDEBUGCODE(int fChopTsArrayCount = 0;) 62 63 // Bevel, miter, and round joins require us to add different numbers of additional edges onto 64 // their triangle strips. When using dynamic stroke, we just append the maximum required number 65 // of additional edges to every instance. 66 int fMaxNumExtraEdgesInJoin = 0; 67 68 // Chained tessellators. These all append to our shared indirect draw list during prepare(). 69 GrStrokeIndirectTessellator* fNextInChain = nullptr; 70 GrStrokeIndirectTessellator** fChainTail = &fNextInChain; // Null if we are not the chain head. 71 72 // GPU buffers for drawing. 73 sk_sp<const GrBuffer> fDrawIndirectBuffer; 74 sk_sp<const GrBuffer> fInstanceBuffer; 75 size_t fDrawIndirectOffset; 76 77 friend class GrOp; // For ctor. 78 79 #if GR_TEST_UTILS 80 public: 81 void verifyResolveLevels(skiatest::Reporter*, class GrMockOpTarget*, const SkMatrix&, 82 const SkPath&, const SkStrokeRec&); 83 void verifyBuffers(skiatest::Reporter*, class GrMockOpTarget*, const SkMatrix&, 84 const SkStrokeRec&); 85 class Benchmark; 86 #endif 87 }; 88 89 #endif 90