blob: 7d457fef33adb76dabc06cd45b9b247a4d4bc88f [file] [log] [blame]
Chris Daltonc1e59632017-09-05 00:30:07 -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 GrCCPRCoverageOp_DEFINED
9#define GrCCPRCoverageOp_DEFINED
10
11#include "GrMesh.h"
12#include "SkRect.h"
13#include "SkRefCnt.h"
14#include "ccpr/GrCCPRCoverageProcessor.h"
15#include "ccpr/GrCCPRGeometry.h"
16#include "ops/GrDrawOp.h"
17
18class GrCCPRCoverageOp;
19class GrOnFlushResourceProvider;
20class SkMatrix;
21class SkPath;
22
23/**
24 * This class produces GrCCPRCoverageOps that render coverage count masks and atlases. A path is
25 * added to the current op in two steps:
26 *
27 * 1) parsePath(ScissorMode, viewMatrix, path, &devBounds, &devBounds45);
28 *
29 * <client decides where to put the mask within an atlas, if wanted>
30 *
31 * 2) saveParsedPath(offsetX, offsetY, clipBounds);
32 *
33 * The client can flush the currently saved paths to a GrCCPRCoverageOp by calling emitOp, and
34 * retrieve all emitted ops after calling finalize().
35 */
36class GrCCPRCoverageOpsBuilder {
37public:
38 // Indicates whether a path should enforce a scissor clip when rendering its mask. (Specified
39 // as an int because these values get used directly as indices into arrays.)
40 enum class ScissorMode : int {
41 kNonScissored = 0,
42 kScissored = 1
43 };
44 static constexpr int kNumScissorModes = 2;
45
46 GrCCPRCoverageOpsBuilder(int maxTotalPaths, int numSkPoints, int numSkVerbs)
47 : fPathsInfo(maxTotalPaths)
48 , fGeometry(numSkPoints, numSkVerbs)
49 , fTallies{PrimitiveTallies(), PrimitiveTallies()}
50 , fScissorBatches(maxTotalPaths) {}
51
52 ~GrCCPRCoverageOpsBuilder() {
53 // Enforce the contract that the client always calls saveParsedPath or discardParsedPath.
54 SkASSERT(!fParsingPath);
55 }
56
57 // Parses an SkPath into a temporary staging area. The path will not yet be included in the next
58 // Op unless there is a matching call to saveParsedPath. The user must complement this with a
59 // following call to either saveParsedPath or discardParsedPath.
60 //
61 // Returns two tight bounding boxes: device space and "45 degree" (| 1 -1 | * devCoords) space.
62 // | 1 1 |
63 void parsePath(const SkMatrix&, const SkPath&, SkRect* devBounds, SkRect* devBounds45);
64
65 // Commits the currently-parsed path from staging to the next Op, and specifies whether the mask
66 // should be rendered with a scissor clip in effect. Accepts an optional post-device-space
67 // translate for placement in an atlas.
68 void saveParsedPath(ScissorMode, const SkIRect& clippedDevIBounds,
69 int16_t atlasOffsetX, int16_t atlasOffsetY);
70 void discardParsedPath();
71
72 // Flushes all currently-saved paths internally to a GrCCPRCoverageOp.
73 //
74 // NOTE: if there is a parsed path in the staging area, it will not be included. But the client
75 // may still call saveParsedPath to include it in a future Op.
76 void emitOp(SkISize drawBounds);
77
78 // Builds GPU buffers and returns the list of GrCCPRCoverageOps as specified by calls to emitOp.
79 bool finalize(GrOnFlushResourceProvider*, SkTArray<std::unique_ptr<GrCCPRCoverageOp>>*);
80
81private:
82 using PrimitiveTallies = GrCCPRGeometry::PrimitiveTallies;
83
84 // Every kBeginPath verb has a corresponding PathInfo entry.
85 struct PathInfo {
86 ScissorMode fScissorMode;
87 int32_t fPackedAtlasOffset; // (offsetY << 16) | (offsetX & 0xffff)
88 std::unique_ptr<GrCCPRCoverageOp> fTerminatingOp;
89 };
90
91 // Every PathInfo with a mode of kScissored has a corresponding ScissorBatch.
92 struct ScissorBatch {
93 PrimitiveTallies fInstanceCounts;
94 SkIRect fScissor;
95 };
96
97 void endContourIfNeeded(bool insideContour);
98
99 // Staging area for the path being parsed.
100 SkDEBUGCODE(int fParsingPath = false);
101 int fCurrPathPointsIdx;
102 int fCurrPathVerbsIdx;
103 PrimitiveTallies fCurrPathTallies;
104
105 SkSTArray<32, PathInfo, true> fPathsInfo;
106
107 GrCCPRGeometry fGeometry;
108
109 PrimitiveTallies fTallies[kNumScissorModes];
110 SkTArray<ScissorBatch, true> fScissorBatches;
111
112 std::unique_ptr<GrCCPRCoverageOp> fTerminatingOp;
113
114 friend class GrCCPRCoverageOp; // For ScissorBatch.
115};
116
117/**
118 * This Op renders coverage count masks and atlases. Create it using GrCCPRCoverageOpsBuilder.
119 */
120class GrCCPRCoverageOp : public GrDrawOp {
121public:
122 DEFINE_OP_CLASS_ID
123
124 // GrDrawOp interface.
125 const char* name() const override { return "GrCCPRCoverageOp"; }
126 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
Brian Osman9a725dd2017-09-20 09:53:22 -0400127 RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*,
128 GrPixelConfigIsClamped) override {
Chris Daltonc1e59632017-09-05 00:30:07 -0600129 return RequiresDstTexture::kNo;
130 }
131 bool onCombineIfPossible(GrOp* other, const GrCaps& caps) override { return false; }
132 void onPrepare(GrOpFlushState*) override {}
133 void onExecute(GrOpFlushState*) override;
134
135private:
136 static constexpr int kNumScissorModes = GrCCPRCoverageOpsBuilder::kNumScissorModes;
137 using PrimitiveTallies = GrCCPRGeometry::PrimitiveTallies;
138 using ScissorBatch = GrCCPRCoverageOpsBuilder::ScissorBatch;
139
140 GrCCPRCoverageOp(SkTArray<ScissorBatch, true>&& scissorBatches, const SkISize& drawBounds)
141 : INHERITED(ClassID())
142 , fScissorBatches(std::move(scissorBatches))
143 , fDrawBounds(drawBounds) {
144 this->setBounds(SkRect::MakeIWH(fDrawBounds.width(), fDrawBounds.height()),
145 GrOp::HasAABloat::kNo, GrOp::IsZeroArea::kNo);
146 }
147
148 void setBuffers(sk_sp<GrBuffer> pointsBuffer, sk_sp<GrBuffer> instanceBuffer,
149 const PrimitiveTallies baseInstances[kNumScissorModes],
150 const PrimitiveTallies endInstances[kNumScissorModes]);
151
152 void drawMaskPrimitives(GrOpFlushState*, const GrPipeline&, const GrCCPRCoverageProcessor::Mode,
153 GrPrimitiveType, int vertexCount,
154 int PrimitiveTallies::* instanceType) const;
155
156 sk_sp<GrBuffer> fPointsBuffer;
157 sk_sp<GrBuffer> fInstanceBuffer;
158 PrimitiveTallies fBaseInstances[kNumScissorModes];
159 PrimitiveTallies fInstanceCounts[kNumScissorModes];
160 const SkTArray<ScissorBatch, true> fScissorBatches;
161 const SkISize fDrawBounds;
162
163 mutable SkTArray<GrMesh> fMeshesScratchBuffer;
164 mutable SkTArray<GrPipeline::DynamicState> fDynamicStatesScratchBuffer;
165
166 friend class GrCCPRCoverageOpsBuilder;
167
168 typedef GrDrawOp INHERITED;
169};
170
171#endif