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