1 | /* |
2 | * Copyright 2017 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 GrCCPathParser_DEFINED |
9 | #define GrCCPathParser_DEFINED |
10 | |
11 | #include "include/core/SkRect.h" |
12 | #include "include/core/SkRefCnt.h" |
13 | #include "src/core/SkPathPriv.h" |
14 | #include "src/gpu/GrTriangulator.h" |
15 | #include "src/gpu/ccpr/GrAutoMapVertexBuffer.h" |
16 | #include "src/gpu/ccpr/GrCCCoverageProcessor.h" |
17 | #include "src/gpu/ccpr/GrCCFillGeometry.h" |
18 | #include "src/gpu/ops/GrDrawOp.h" |
19 | |
20 | class GrOnFlushResourceProvider; |
21 | class SkMatrix; |
22 | class SkPath; |
23 | |
24 | /** |
25 | * This class parses SkPaths into CCPR primitives in GPU buffers, then issues calls to draw their |
26 | * coverage counts. |
27 | */ |
28 | class GrCCFiller { |
29 | public: |
30 | enum class Algorithm : bool { |
31 | kCoverageCount, |
32 | kStencilWindingCount |
33 | }; |
34 | |
35 | GrCCFiller(Algorithm, int numPaths, int numSkPoints, int numSkVerbs, int numConicWeights); |
36 | |
37 | // Parses a device-space SkPath into the current batch, using the SkPath's original verbs and |
38 | // 'deviceSpacePts'. Accepts an optional post-device-space translate for placement in an atlas. |
39 | void parseDeviceSpaceFill(const SkPath&, const SkPoint* deviceSpacePts, GrScissorTest, |
40 | const SkIRect& clippedDevIBounds, const SkIVector& devToAtlasOffset); |
41 | |
42 | using BatchID = int; |
43 | |
44 | // Compiles the outstanding parsed paths into a batch, and returns an ID that can be used to |
45 | // draw their fills in the future. |
46 | BatchID closeCurrentBatch(); |
47 | |
48 | // Builds internal GPU buffers and prepares for calls to drawFills(). Caller must close the |
49 | // current batch before calling this method, and cannot parse new paths afer. |
50 | bool prepareToDraw(GrOnFlushResourceProvider*); |
51 | |
52 | // Called after prepareToDraw(). Draws the given batch of path fills. |
53 | void drawFills(GrOpFlushState*, GrCCCoverageProcessor*, const GrPipeline&, BatchID, |
54 | const SkIRect& drawBounds) const; |
55 | |
56 | private: |
57 | static constexpr int kNumScissorModes = 2; |
58 | using PrimitiveTallies = GrCCFillGeometry::PrimitiveTallies; |
59 | |
60 | // Every kBeginPath verb has a corresponding PathInfo entry. |
61 | class PathInfo { |
62 | public: |
63 | PathInfo(GrScissorTest scissorTest, const SkIVector& devToAtlasOffset) |
64 | : fScissorTest(scissorTest), fDevToAtlasOffset(devToAtlasOffset) {} |
65 | |
66 | GrScissorTest scissorTest() const { return fScissorTest; } |
67 | const SkIVector& devToAtlasOffset() const { return fDevToAtlasOffset; } |
68 | |
69 | // An empty tessellation fan is also valid; we use negative count to denote not tessellated. |
70 | bool hasFanTessellation() const { return fFanTessellationCount >= 0; } |
71 | int fanTessellationCount() const { |
72 | SkASSERT(this->hasFanTessellation()); |
73 | return fFanTessellationCount; |
74 | } |
75 | const GrTriangulator::WindingVertex* fanTessellation() const { |
76 | SkASSERT(this->hasFanTessellation()); |
77 | return fFanTessellation.get(); |
78 | } |
79 | void tessellateFan( |
80 | Algorithm, const SkPath& originalPath, const GrCCFillGeometry&, int verbsIdx, |
81 | int ptsIdx, const SkIRect& clippedDevIBounds, PrimitiveTallies* newTriangleCounts); |
82 | |
83 | private: |
84 | GrScissorTest fScissorTest; |
85 | SkIVector fDevToAtlasOffset; // Translation from device space to location in atlas. |
86 | int fFanTessellationCount = -1; |
87 | std::unique_ptr<const GrTriangulator::WindingVertex[]> fFanTessellation; |
88 | }; |
89 | |
90 | // Defines a batch of CCPR primitives. Start indices are deduced by looking at the previous |
91 | // Batch in the list. |
92 | struct Batch { |
93 | PrimitiveTallies fEndNonScissorIndices; |
94 | int fEndScissorSubBatchIdx; |
95 | PrimitiveTallies fTotalPrimitiveCounts; |
96 | }; |
97 | |
98 | // Defines a sub-batch that will be drawn with the given scissor rect. Start indices are deduced |
99 | // by looking at the previous ScissorSubBatch in the list. |
100 | struct ScissorSubBatch { |
101 | PrimitiveTallies fEndPrimitiveIndices; |
102 | SkIRect fScissor; |
103 | }; |
104 | |
105 | void emitTessellatedFan( |
106 | const GrTriangulator::WindingVertex*, int numVertices, const Sk2f& devToAtlasOffset, |
107 | GrCCCoverageProcessor::TriPointInstance::Ordering, |
108 | GrCCCoverageProcessor::TriPointInstance*, GrCCCoverageProcessor::QuadPointInstance*, |
109 | GrCCFillGeometry::PrimitiveTallies*); |
110 | void drawPrimitives(GrOpFlushState*, const GrCCCoverageProcessor&, const GrPipeline&, BatchID, |
111 | int PrimitiveTallies::*instanceType, const SkIRect& drawBounds) const; |
112 | |
113 | const Algorithm fAlgorithm; |
114 | GrCCFillGeometry fGeometry; |
115 | SkSTArray<32, PathInfo, true> fPathInfos; |
116 | SkSTArray<32, Batch, true> fBatches; |
117 | SkSTArray<32, ScissorSubBatch, true> fScissorSubBatches; |
118 | PrimitiveTallies fTotalPrimitiveCounts[kNumScissorModes]; |
119 | int fMaxMeshesPerDraw = 0; |
120 | |
121 | GrAutoMapVertexBuffer fInstanceBuffer; |
122 | PrimitiveTallies fBaseInstances[kNumScissorModes]; |
123 | }; |
124 | |
125 | #endif |
126 | |