blob: 710ee8820647282d003e49e92f72f5c8da93901f [file] [log] [blame]
Chris Dalton1a325d22017-07-14 15:17:41 -06001/*
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 GrCCPRCoverageOpsBuilder_DEFINED
9#define GrCCPRCoverageOpsBuilder_DEFINED
10
11#include "GrBuffer.h"
12#include "SkRefCnt.h"
13#include "SkRect.h"
14#include "ccpr/GrCCPRCoverageProcessor.h"
15
16class GrCCPRCoverageOp;
17class GrDrawOp;
18class GrOnFlushResourceProvider;
19class GrResourceProvider;
20class SkMatrix;
21class SkPath;
22struct SkDCubic;
23enum class SkCubicType;
24
25/**
26 * This class produces GrDrawOps that render coverage count masks and atlases. A path is added to
27 * the current op in two steps:
28 *
29 * 1) parsePath(ScissorMode, viewMatrix, path, &devBounds, &devBounds45);
30 *
31 * <client decides where to put the mask within an atlas, if wanted>
32 *
33 * 2) saveParsedPath(offsetX, offsetY, clipBounds);
34 *
35 * The client can then produce a GrDrawOp for all currently saved paths by calling either
36 * createIntermediateOp() or finalize().
37 */
38class GrCCPRCoverageOpsBuilder {
39public:
40 // Indicates whether a path should enforce a scissor clip when rendering its mask. (Specified
41 // as an int because these values get used directly as indices into arrays.)
42 enum class ScissorMode : int {
43 kNonScissored = 0,
44 kScissored = 1
45 };
46 static constexpr int kNumScissorModes = 2;
47
48 struct MaxPrimitives {
49 int fMaxTriangles = 0;
50 int fMaxQuadratics = 0;
51 int fMaxCubics = 0;
52
53 void operator+=(const MaxPrimitives&);
54 int sum() const;
55 };
56
57 struct MaxBufferItems {
58 int fMaxFanPoints = 0;
59 int fMaxControlPoints = 0;
60 MaxPrimitives fMaxPrimitives[kNumScissorModes];
61 int fMaxPaths = 0;
62
63 void operator+=(const MaxBufferItems&);
64 void countPathItems(ScissorMode, const SkPath&);
65 };
66
67 GrCCPRCoverageOpsBuilder() : fScissorBatches(512) {
68 SkDEBUGCODE(fPointsData = nullptr;)
69 SkDEBUGCODE(fInstanceData = nullptr;)
70 }
71
72 bool init(GrOnFlushResourceProvider*, const MaxBufferItems&);
73
74 // Parses an SkPath into a temporary staging area. The path will not yet be included in the next
75 // Op until there is a matching call to saveParsedPath.
76 //
77 // Returns two tight bounding boxes: device space and "45 degree" (| 1 -1 | * devCoords) space.
78 // | 1 1 |
79 void parsePath(ScissorMode, const SkMatrix&, const SkPath&, SkRect* devBounds,
80 SkRect* devBounds45);
81
82 // Commits the currently-parsed path from the staging area to the GPU buffers and next Op.
83 // Accepts an optional post-device-space translate for placement in an atlas.
84 void saveParsedPath(const SkIRect& clippedDevIBounds,
85 int16_t atlasOffsetX, int16_t atlasOffsetY);
86
87 // Flushes all currently-saved paths to a GrDrawOp and leaves the GPU buffers open to accept
88 // new paths (e.g. for when an atlas runs out of space).
89 // NOTE: if there is a parsed path in the staging area, it will not be included. But the client
90 // may still call saveParsedPath to include it in a future Op.
91 std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT createIntermediateOp(SkISize drawBounds);
92
93 // Flushes the remaining saved paths to a final GrDrawOp and closes off the GPU buffers. This
94 // must be called before attempting to draw any Ops produced by this class.
95 std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT finalize(SkISize drawBounds);
96
97 class CoverageOp;
Chris Dalton1a325d22017-07-14 15:17:41 -060098
99private:
100 using PrimitiveInstance = GrCCPRCoverageProcessor::PrimitiveInstance;
101
102 struct PrimitiveTallies {
103 int fTriangles;
104 int fQuadratics;
105 int fSerpentines;
106 int fLoops;
107
108 PrimitiveTallies operator+(const PrimitiveTallies&) const;
109 PrimitiveTallies operator-(const PrimitiveTallies&) const;
110 int sum() const;
111 };
112
113 struct ScissorBatch {
114 PrimitiveTallies fInstanceCounts;
115 SkIRect fScissor;
116 };
117
Chris Dalton21171e52017-08-01 15:36:01 -0600118 void startContour(const SkPoint& anchorPoint);
119 void fanTo(const SkPoint& pt);
120 void quadraticTo(SkPoint controlPt, SkPoint endPt);
121 void cubicTo(SkPoint controlPt1, SkPoint controlPt2, SkPoint endPt);
122 void emitCubicSegment(SkCubicType, const SkDCubic&, const SkPoint& ts0, const SkPoint& ts1);
Chris Dalton1a325d22017-07-14 15:17:41 -0600123 void closeContour();
124 void emitHierarchicalFan(int32_t indices[], int count);
125 SkDEBUGCODE(void validate();)
126
127 ScissorMode fCurrScissorMode;
128 PrimitiveTallies fCurrPathIndices;
129 int32_t fCurrContourStartIdx;
Chris Dalton21171e52017-08-01 15:36:01 -0600130 SkPoint fCurrAnchorPoint;
131 SkPoint fCurrFanPoint;
Chris Dalton1a325d22017-07-14 15:17:41 -0600132
133 sk_sp<GrBuffer> fPointsBuffer;
134 SkPoint* fPointsData;
135 int32_t fFanPtsIdx;
136 int32_t fControlPtsIdx;
137 SkDEBUGCODE(int fMaxFanPoints;)
138 SkDEBUGCODE(int fMaxControlPoints;)
139
140 sk_sp<GrBuffer> fInstanceBuffer;
141 PrimitiveInstance* fInstanceData;
142 PrimitiveTallies fBaseInstances[kNumScissorModes];
143 PrimitiveTallies fInstanceIndices[kNumScissorModes];
144
145 SkTArray<ScissorBatch> fScissorBatches;
146};
147
148inline void GrCCPRCoverageOpsBuilder::MaxBufferItems::operator+=(const MaxBufferItems& b) {
149 fMaxFanPoints += b.fMaxFanPoints;
150 fMaxControlPoints += b.fMaxControlPoints;
151 fMaxPrimitives[0] += b.fMaxPrimitives[0];
152 fMaxPrimitives[1] += b.fMaxPrimitives[1];
153 fMaxPaths += b.fMaxPaths;
154}
155
156inline void GrCCPRCoverageOpsBuilder::MaxPrimitives::operator+=(const MaxPrimitives& b) {
157 fMaxTriangles += b.fMaxTriangles;
158 fMaxQuadratics += b.fMaxQuadratics;
159 fMaxCubics += b.fMaxCubics;
160}
161
162inline int GrCCPRCoverageOpsBuilder::MaxPrimitives::sum() const {
163 return fMaxTriangles + fMaxQuadratics + fMaxCubics;
164}
165
166#endif