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