• 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 GrCoverageCountingPathRenderer_DEFINED
9 #define GrCoverageCountingPathRenderer_DEFINED
10 
11 #include <map>
12 #include "GrAllocator.h"
13 #include "GrOnFlushResourceProvider.h"
14 #include "GrPathRenderer.h"
15 #include "SkTInternalLList.h"
16 #include "ccpr/GrCCAtlas.h"
17 #include "ccpr/GrCCPathParser.h"
18 #include "ccpr/GrCCPathProcessor.h"
19 #include "ops/GrDrawOp.h"
20 
21 /**
22  * This is a path renderer that draws antialiased paths by counting coverage in an offscreen
23  * buffer. (See GrCCCoverageProcessor, GrCCPathProcessor)
24  *
25  * It also serves as the per-render-target tracker for pending path draws, and at the start of
26  * flush, it compiles GPU buffers and renders a "coverage count atlas" for the upcoming paths.
27  */
28 class GrCoverageCountingPathRenderer : public GrPathRenderer, public GrOnFlushCallbackObject {
29     struct RTPendingPaths;
30 
31 public:
32     static bool IsSupported(const GrCaps&);
33     static sk_sp<GrCoverageCountingPathRenderer> CreateIfSupported(const GrCaps&,
34                                                                    bool drawCachablePaths);
35 
~GrCoverageCountingPathRenderer()36     ~GrCoverageCountingPathRenderer() override {
37         // Ensure no Ops exist that could have a dangling pointer back into this class.
38         SkASSERT(fRTPendingPathsMap.empty());
39         SkASSERT(0 == fPendingDrawOpsCount);
40     }
41 
42     // This is the Op that ultimately draws a path into its final destination, using the atlas we
43     // generate at flush time.
44     class DrawPathsOp : public GrDrawOp {
45     public:
46         DEFINE_OP_CLASS_ID
47         SK_DECLARE_INTERNAL_LLIST_INTERFACE(DrawPathsOp);
48 
49         DrawPathsOp(GrCoverageCountingPathRenderer*, const DrawPathArgs&, GrColor);
50         ~DrawPathsOp() override;
51 
52         struct SingleDraw {
53             SkIRect fClipIBounds;
54             SkMatrix fMatrix;
55             SkPath fPath;
56             GrColor fColor;
57             SingleDraw* fNext = nullptr;
58         };
59 
head()60         const SingleDraw* head() const {
61             SkASSERT(fInstanceCount >= 1);
62             return &fHeadDraw;
63         }
64 
SkDEBUGCODE(int numSkippedInstances_debugOnly ()const{ return fNumSkippedInstances; })65         SkDEBUGCODE(int numSkippedInstances_debugOnly() const { return fNumSkippedInstances; })
66 
67         // GrDrawOp overrides.
68         const char* name() const override { return "GrCoverageCountingPathRenderer::DrawPathsOp"; }
fixedFunctionFlags()69         FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
70         RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*,
71                                     GrPixelConfigIsClamped) override;
72         void wasRecorded(GrRenderTargetOpList*) override;
73         bool onCombineIfPossible(GrOp* other, const GrCaps& caps) override;
visitProxies(const VisitProxyFunc & func)74         void visitProxies(const VisitProxyFunc& func) const override {
75             fProcessors.visitProxies(func);
76         }
onPrepare(GrOpFlushState *)77         void onPrepare(GrOpFlushState*) override {}
78         void onExecute(GrOpFlushState*) override;
79 
80         int setupResources(GrOnFlushResourceProvider*,
81                            GrCCPathProcessor::Instance* pathInstanceData, int pathInstanceIdx);
82 
83     private:
getFillType()84         SkPath::FillType getFillType() const {
85             SkASSERT(fInstanceCount >= 1);
86             return fHeadDraw.fPath.getFillType();
87         }
88 
89         struct AtlasBatch {
90             const GrCCAtlas* fAtlas;
91             int fEndInstanceIdx;
92         };
93 
addAtlasBatch(const GrCCAtlas * atlas,int endInstanceIdx)94         void addAtlasBatch(const GrCCAtlas* atlas, int endInstanceIdx) {
95             SkASSERT(endInstanceIdx > fBaseInstance);
96             SkASSERT(fAtlasBatches.empty() ||
97                      endInstanceIdx > fAtlasBatches.back().fEndInstanceIdx);
98             fAtlasBatches.push_back() = {atlas, endInstanceIdx};
99         }
100 
101         GrCoverageCountingPathRenderer* const fCCPR;
102         const uint32_t fSRGBFlags;
103         GrProcessorSet fProcessors;
104         SingleDraw fHeadDraw;
105         SingleDraw* fTailDraw;
106         RTPendingPaths* fOwningRTPendingPaths;
107         int fBaseInstance;
108         SkDEBUGCODE(int fInstanceCount);
109         SkDEBUGCODE(int fNumSkippedInstances);
110         SkSTArray<1, AtlasBatch, true> fAtlasBatches;
111 
112         typedef GrDrawOp INHERITED;
113     };
114 
115     // GrPathRenderer overrides.
onGetStencilSupport(const GrShape &)116     StencilSupport onGetStencilSupport(const GrShape&) const override {
117         return GrPathRenderer::kNoSupport_StencilSupport;
118     }
119     CanDrawPath onCanDrawPath(const CanDrawPathArgs& args) const override;
120     bool onDrawPath(const DrawPathArgs&) final;
121 
122     // These are keyed by SkPath generation ID, and store which device-space paths are accessed and
123     // where by clip FPs in a given opList. A single ClipPath can be referenced by multiple FPs. At
124     // flush time their coverage count masks are packed into atlas(es) alongside normal DrawPathOps.
125     class ClipPath {
126     public:
127         ClipPath() = default;
128         ClipPath(const ClipPath&) = delete;
129 
~ClipPath()130         ~ClipPath() {
131             // Ensure no clip FPs exist with a dangling pointer back into this class.
132             SkASSERT(!fAtlasLazyProxy || fAtlasLazyProxy->isUnique_debugOnly());
133             // Ensure no lazy proxy callbacks exist with a dangling pointer back into this class.
134             SkASSERT(fHasAtlasTransform);
135         }
136 
isUninitialized()137         bool isUninitialized() const { return !fAtlasLazyProxy; }
138         void init(GrProxyProvider* proxyProvider,
139                   const SkPath& deviceSpacePath, const SkIRect& accessRect,
140                   int rtWidth, int rtHeight);
addAccess(const SkIRect & accessRect)141         void addAccess(const SkIRect& accessRect) {
142             SkASSERT(!this->isUninitialized());
143             fAccessRect.join(accessRect);
144         }
145 
atlasLazyProxy()146         GrTextureProxy* atlasLazyProxy() const {
147             SkASSERT(!this->isUninitialized());
148             return fAtlasLazyProxy.get();
149         }
deviceSpacePath()150         const SkPath& deviceSpacePath() const {
151             SkASSERT(!this->isUninitialized());
152             return fDeviceSpacePath;
153         }
pathDevIBounds()154         const SkIRect& pathDevIBounds() const {
155             SkASSERT(!this->isUninitialized());
156             return fPathDevIBounds;
157         }
158         void placePathInAtlas(GrCoverageCountingPathRenderer*, GrOnFlushResourceProvider*,
159                               GrCCPathParser*);
160 
atlasScale()161         const SkVector& atlasScale() const {
162             SkASSERT(fHasAtlasTransform);
163             return fAtlasScale;
164         }
atlasTranslate()165         const SkVector& atlasTranslate() const {
166             SkASSERT(fHasAtlasTransform);
167             return fAtlasTranslate;
168         }
169 
170     private:
171         sk_sp<GrTextureProxy> fAtlasLazyProxy;
172         SkPath fDeviceSpacePath;
173         SkIRect fPathDevIBounds;
174         SkIRect fAccessRect;
175 
176         const GrCCAtlas* fAtlas = nullptr;
177         int16_t fAtlasOffsetX;
178         int16_t fAtlasOffsetY;
179         SkDEBUGCODE(bool fHasAtlas = false);
180 
181         SkVector fAtlasScale;
182         SkVector fAtlasTranslate;
183         SkDEBUGCODE(bool fHasAtlasTransform = false);
184     };
185 
186     bool canMakeClipProcessor(const SkPath& deviceSpacePath) const;
187 
188     std::unique_ptr<GrFragmentProcessor> makeClipProcessor(GrProxyProvider*, uint32_t oplistID,
189                                                            const SkPath& deviceSpacePath,
190                                                            const SkIRect& accessRect,
191                                                            int rtWidth, int rtHeight);
192 
193     // GrOnFlushCallbackObject overrides.
194     void preFlush(GrOnFlushResourceProvider*, const uint32_t* opListIDs, int numOpListIDs,
195                   SkTArray<sk_sp<GrRenderTargetContext>>* results) override;
196     void postFlush(GrDeferredUploadToken, const uint32_t* opListIDs, int numOpListIDs) override;
197 
198 private:
GrCoverageCountingPathRenderer(bool drawCachablePaths)199     GrCoverageCountingPathRenderer(bool drawCachablePaths)
200             : fDrawCachablePaths(drawCachablePaths) {}
201 
202     GrCCAtlas* placeParsedPathInAtlas(GrOnFlushResourceProvider*, const SkIRect& accessRect,
203                                       const SkIRect& pathIBounds, int16_t* atlasOffsetX,
204                                       int16_t* atlasOffsetY);
205 
206     struct RTPendingPaths {
~RTPendingPathsRTPendingPaths207         ~RTPendingPaths() {
208             // Ensure all DrawPathsOps in this opList have been deleted.
209             SkASSERT(fDrawOps.isEmpty());
210         }
211 
212         SkTInternalLList<DrawPathsOp> fDrawOps;
213         std::map<uint32_t, ClipPath> fClipPaths;
214         GrSTAllocator<256, DrawPathsOp::SingleDraw> fDrawsAllocator;
215     };
216 
217     // A map from render target ID to the individual render target's pending paths.
218     std::map<uint32_t, RTPendingPaths> fRTPendingPathsMap;
219     SkDEBUGCODE(int fPendingDrawOpsCount = 0);
220 
221     sk_sp<const GrBuffer> fPerFlushIndexBuffer;
222     sk_sp<const GrBuffer> fPerFlushVertexBuffer;
223     sk_sp<GrBuffer> fPerFlushInstanceBuffer;
224     sk_sp<GrCCPathParser> fPerFlushPathParser;
225     GrSTAllocator<4, GrCCAtlas> fPerFlushAtlases;
226     bool fPerFlushResourcesAreValid;
227     SkDEBUGCODE(bool fFlushing = false);
228 
229     const bool fDrawCachablePaths;
230 };
231 
232 #endif
233