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
20class GrOnFlushResourceProvider;
21class SkMatrix;
22class SkPath;
23
24/**
25 * This class parses SkPaths into CCPR primitives in GPU buffers, then issues calls to draw their
26 * coverage counts.
27 */
28class GrCCFiller {
29public:
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
56private:
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