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