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