• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "GrMesh.h"
12 #include "GrNonAtomicRef.h"
13 #include "SkRect.h"
14 #include "SkRefCnt.h"
15 #include "ccpr/GrCCCoverageProcessor.h"
16 #include "ccpr/GrCCGeometry.h"
17 #include "ops/GrDrawOp.h"
18 
19 class GrOnFlushResourceProvider;
20 class SkMatrix;
21 class SkPath;
22 
23 /**
24  * This class parses SkPaths into CCPR primitives in GPU buffers, then issues calls to draw their
25  * coverage counts.
26  */
27 class GrCCPathParser : public GrNonAtomicRef<GrCCPathParser> {
28 public:
29     // Indicates whether a path should enforce a scissor clip when rendering its mask. (Specified
30     // as an int because these values get used directly as indices into arrays.)
31     enum class ScissorMode : int { kNonScissored = 0, kScissored = 1 };
32     static constexpr int kNumScissorModes = 2;
33 
34     GrCCPathParser(int maxTotalPaths, int maxPathPoints, int numSkPoints, int numSkVerbs);
35 
~GrCCPathParser()36     ~GrCCPathParser() {
37         // Enforce the contract that the client always calls saveParsedPath or discardParsedPath.
38         SkASSERT(!fParsingPath);
39     }
40 
41     using CoverageCountBatchID = int;
42 
43     // Parses an SkPath into a temporary staging area. The path will not be included in the current
44     // batch until there is a matching call to saveParsedPath. The user must complement this with a
45     // following call to either saveParsedPath or discardParsedPath.
46     //
47     // Returns two tight bounding boxes: device space and "45 degree" (| 1 -1 | * devCoords) space.
48     //                                                                 | 1  1 |
49     void parsePath(const SkMatrix&, const SkPath&, SkRect* devBounds, SkRect* devBounds45);
50 
51     // Parses a device-space SkPath into a temporary staging area. The path will not be included in
52     // the current batch until there is a matching call to saveParsedPath. The user must complement
53     // this with a following call to either saveParsedPath or discardParsedPath.
54     void parseDeviceSpacePath(const SkPath&);
55 
56     // Commits the currently-parsed path from staging to the current batch, and specifies whether
57     // the mask should be rendered with a scissor in effect. Accepts an optional post-device-space
58     // translate for placement in an atlas.
59     void saveParsedPath(ScissorMode, const SkIRect& clippedDevIBounds, int16_t atlasOffsetX,
60                         int16_t atlasOffsetY);
61     void discardParsedPath();
62 
63     // Compiles the outstanding saved paths into a batch, and returns an ID that can be used to draw
64     // their coverage counts in the future.
65     CoverageCountBatchID closeCurrentBatch();
66 
67     // Builds internal GPU buffers and prepares for calls to drawCoverageCount. Caller must close
68     // the current batch before calling this method, and cannot parse new paths afer.
69     bool finalize(GrOnFlushResourceProvider*);
70 
71     // Called after finalize. Draws the given batch of parsed paths.
72     void drawCoverageCount(GrOpFlushState*, CoverageCountBatchID, const SkIRect& drawBounds) const;
73 
74 private:
75     using PrimitiveTallies = GrCCGeometry::PrimitiveTallies;
76 
77     // Every kBeginPath verb has a corresponding PathInfo entry.
78     struct PathInfo {
79         ScissorMode fScissorMode;
80         int16_t fAtlasOffsetX, fAtlasOffsetY;
81     };
82 
83     // Defines a batch of CCPR primitives. Start indices are deduced by looking at the previous
84     // CoverageCountBatch in the list.
85     struct CoverageCountBatch {
86         PrimitiveTallies fEndNonScissorIndices;
87         int fEndScissorSubBatchIdx;
88     };
89 
90     // Defines a sub-batch from CoverageCountBatch that will be drawn with the given scissor rect.
91     // Start indices are deduced by looking at the previous ScissorSubBatch in the list.
92     struct ScissorSubBatch {
93         PrimitiveTallies fEndPrimitiveIndices;
94         SkIRect fScissor;
95     };
96 
97     void parsePath(const SkPath&, const SkPoint* deviceSpacePts);
98     void endContourIfNeeded(bool insideContour);
99 
100     void drawRenderPass(GrOpFlushState*, const GrPipeline&, CoverageCountBatchID,
101                         GrCCCoverageProcessor::RenderPass, int PrimitiveTallies::*instanceType,
102                         const SkIRect& drawBounds) const;
103 
104     // Staging area for the path being parsed.
105     SkDEBUGCODE(int fParsingPath = false);
106     const SkAutoSTArray<32, SkPoint> fLocalDevPtsBuffer;
107     int fCurrPathPointsIdx;
108     int fCurrPathVerbsIdx;
109     PrimitiveTallies fCurrPathPrimitiveCounts;
110 
111     GrCCGeometry fGeometry;
112     SkSTArray<32, PathInfo, true> fPathsInfo;
113     SkSTArray<32, CoverageCountBatch, true> fCoverageCountBatches;
114     SkSTArray<32, ScissorSubBatch, true> fScissorSubBatches;
115     PrimitiveTallies fTotalPrimitiveCounts[kNumScissorModes];
116     int fMaxMeshesPerDraw = 0;
117 
118     sk_sp<GrBuffer> fInstanceBuffer;
119     PrimitiveTallies fBaseInstances[kNumScissorModes];
120     mutable SkSTArray<32, GrMesh> fMeshesScratchBuffer;
121     mutable SkSTArray<32, GrPipeline::DynamicState> fDynamicStatesScratchBuffer;
122 };
123 
124 #endif
125