Home | History | Annotate | Download | only in ccpr
      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