blob: 92d0203e8fa6b0bb2612edbb36b2879f163646e7 [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;
98 class AccumulatingViewMatrix;
99
100private:
101 using PrimitiveInstance = GrCCPRCoverageProcessor::PrimitiveInstance;
102
103 struct PrimitiveTallies {
104 int fTriangles;
105 int fQuadratics;
106 int fSerpentines;
107 int fLoops;
108
109 PrimitiveTallies operator+(const PrimitiveTallies&) const;
110 PrimitiveTallies operator-(const PrimitiveTallies&) const;
111 int sum() const;
112 };
113
114 struct ScissorBatch {
115 PrimitiveTallies fInstanceCounts;
116 SkIRect fScissor;
117 };
118
119 void startContour(AccumulatingViewMatrix&, const SkPoint& anchorPoint);
120 void fanTo(AccumulatingViewMatrix&, const SkPoint& pt);
121 void quadraticTo(AccumulatingViewMatrix&, const SkPoint P[3]);
122 void cubicTo(AccumulatingViewMatrix&, const SkPoint P[4]);
123 void emitCubicSegment(AccumulatingViewMatrix&, SkCubicType, const SkDCubic&,
124 const SkPoint& ts0, const SkPoint& ts1);
125 void closeContour();
126 void emitHierarchicalFan(int32_t indices[], int count);
127 SkDEBUGCODE(void validate();)
128
129 ScissorMode fCurrScissorMode;
130 PrimitiveTallies fCurrPathIndices;
131 int32_t fCurrContourStartIdx;
132 SkPoint fCurrPathSpaceAnchorPoint;
133
134 sk_sp<GrBuffer> fPointsBuffer;
135 SkPoint* fPointsData;
136 int32_t fFanPtsIdx;
137 int32_t fControlPtsIdx;
138 SkDEBUGCODE(int fMaxFanPoints;)
139 SkDEBUGCODE(int fMaxControlPoints;)
140
141 sk_sp<GrBuffer> fInstanceBuffer;
142 PrimitiveInstance* fInstanceData;
143 PrimitiveTallies fBaseInstances[kNumScissorModes];
144 PrimitiveTallies fInstanceIndices[kNumScissorModes];
145
146 SkTArray<ScissorBatch> fScissorBatches;
147};
148
149inline void GrCCPRCoverageOpsBuilder::MaxBufferItems::operator+=(const MaxBufferItems& b) {
150 fMaxFanPoints += b.fMaxFanPoints;
151 fMaxControlPoints += b.fMaxControlPoints;
152 fMaxPrimitives[0] += b.fMaxPrimitives[0];
153 fMaxPrimitives[1] += b.fMaxPrimitives[1];
154 fMaxPaths += b.fMaxPaths;
155}
156
157inline void GrCCPRCoverageOpsBuilder::MaxPrimitives::operator+=(const MaxPrimitives& b) {
158 fMaxTriangles += b.fMaxTriangles;
159 fMaxQuadratics += b.fMaxQuadratics;
160 fMaxCubics += b.fMaxCubics;
161}
162
163inline int GrCCPRCoverageOpsBuilder::MaxPrimitives::sum() const {
164 return fMaxTriangles + fMaxQuadratics + fMaxCubics;
165}
166
167#endif