1/*
2 * Copyright 2015 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 GrMeshDrawOp_DEFINED
9#define GrMeshDrawOp_DEFINED
10
11#include "src/core/SkArenaAlloc.h"
12#include "src/gpu/GrAppliedClip.h"
13#include "src/gpu/GrGeometryProcessor.h"
14#include "src/gpu/GrSimpleMesh.h"
15#include "src/gpu/ops/GrDrawOp.h"
16#include <type_traits>
17
18class GrAtlasManager;
19class GrCaps;
20class GrStrikeCache;
21class GrOpFlushState;
22class GrSmallPathAtlasMgr;
23
24/**
25 * Base class for mesh-drawing GrDrawOps.
26 */
27class GrMeshDrawOp : public GrDrawOp {
28public:
29 /** Abstract interface that represents a destination for a GrMeshDrawOp. */
30 class Target;
31
32 static bool CanUpgradeAAOnMerge(GrAAType aa1, GrAAType aa2) {
33 return (aa1 == GrAAType::kNone && aa2 == GrAAType::kCoverage) ||
34 (aa1 == GrAAType::kCoverage && aa2 == GrAAType::kNone);
35 }
36
37protected:
38 GrMeshDrawOp(uint32_t classID);
39
40 void createProgramInfo(const GrCaps* caps,
41 SkArenaAlloc* arena,
42 const GrSurfaceProxyView* writeView,
43 GrAppliedClip&& appliedClip,
44 const GrXferProcessor::DstProxyView& dstProxyView) {
45 this->onCreateProgramInfo(caps, arena, writeView, std::move(appliedClip), dstProxyView);
46 }
47
48 void createProgramInfo(Target* target);
49
50 /** Helper for rendering repeating meshes using a patterned index buffer. This class creates the
51 space for the vertices and flushes the draws to the GrMeshDrawOp::Target. */
52 class PatternHelper {
53 public:
54 PatternHelper(Target*, GrPrimitiveType, size_t vertexStride,
55 sk_sp<const GrBuffer> indexBuffer, int verticesPerRepetition,
56 int indicesPerRepetition, int repeatCount, int maxRepetitions);
57
58 /** Called to issue draws to the GrMeshDrawOp::Target.*/
59 void recordDraw(Target*, const GrGeometryProcessor*) const;
60 void recordDraw(Target*, const GrGeometryProcessor*,
61 const GrSurfaceProxy* const primProcProxies[]) const;
62
63 void* vertices() const { return fVertices; }
64 GrSimpleMesh* mesh() { return fMesh; }
65
66 protected:
67 PatternHelper() = default;
68 void init(Target*, GrPrimitiveType, size_t vertexStride, sk_sp<const GrBuffer> indexBuffer,
69 int verticesPerRepetition, int indicesPerRepetition, int repeatCount,
70 int maxRepetitions);
71
72 private:
73 void* fVertices = nullptr;
74 GrSimpleMesh* fMesh = nullptr;
75 GrPrimitiveType fPrimitiveType;
76 };
77
78 /** A specialization of InstanceHelper for quad rendering.
79 * It only draws non-antialiased indexed quads.
80 */
81 class QuadHelper : private PatternHelper {
82 public:
83 QuadHelper() = delete;
84 QuadHelper(Target* target, size_t vertexStride, int quadsToDraw);
85
86 using PatternHelper::mesh;
87 using PatternHelper::recordDraw;
88 using PatternHelper::vertices;
89
90 private:
91 typedef PatternHelper INHERITED;
92 };
93
94 static bool CombinedQuadCountWillOverflow(GrAAType aaType,
95 bool willBeUpgradedToAA,
96 int combinedQuadCount) {
97 bool willBeAA = (aaType == GrAAType::kCoverage) || willBeUpgradedToAA;
98
99 return combinedQuadCount > (willBeAA ? GrResourceProvider::MaxNumAAQuads()
100 : GrResourceProvider::MaxNumNonAAQuads());
101 }
102
103 virtual void onPrePrepareDraws(GrRecordingContext*,
104 const GrSurfaceProxyView* writeView,
105 GrAppliedClip*,
106 const GrXferProcessor::DstProxyView&);
107
108private:
109 virtual GrProgramInfo* programInfo() = 0;
110 // This method is responsible for creating all the programInfos required
111 // by this op.
112 virtual void onCreateProgramInfo(const GrCaps*,
113 SkArenaAlloc*,
114 const GrSurfaceProxyView* writeView,
115 GrAppliedClip&&,
116 const GrXferProcessor::DstProxyView&) = 0;
117
118 void onPrePrepare(GrRecordingContext* context,
119 const GrSurfaceProxyView* writeView,
120 GrAppliedClip* clip,
121 const GrXferProcessor::DstProxyView& dstProxyView) final {
122 this->onPrePrepareDraws(context, writeView, clip, dstProxyView);
123 }
124 void onPrepare(GrOpFlushState* state) final;
125
126 virtual void onPrepareDraws(Target*) = 0;
127 typedef GrDrawOp INHERITED;
128};
129
130class GrMeshDrawOp::Target {
131public:
132 virtual ~Target() {}
133
134 /** Adds a draw of a mesh. 'primProcProxies' must have
135 * GrPrimitiveProcessor::numTextureSamplers() entries. Can be null if no samplers.
136 */
137 virtual void recordDraw(const GrGeometryProcessor*,
138 const GrSimpleMesh[],
139 int meshCnt,
140 const GrSurfaceProxy* const primProcProxies[],
141 GrPrimitiveType) = 0;
142
143 /**
144 * Helper for drawing GrSimpleMesh(es) with zero primProc textures.
145 */
146 void recordDraw(const GrGeometryProcessor* gp,
147 const GrSimpleMesh meshes[],
148 int meshCnt,
149 GrPrimitiveType primitiveType) {
150 this->recordDraw(gp, meshes, meshCnt, nullptr, primitiveType);
151 }
152
153 /**
154 * Makes space for vertex data. The returned pointer is the location where vertex data
155 * should be written. On return the buffer that will hold the data as well as an offset into
156 * the buffer (in 'vertexSize' units) where the data will be placed.
157 */
158 virtual void* makeVertexSpace(size_t vertexSize, int vertexCount, sk_sp<const GrBuffer>*,
159 int* startVertex) = 0;
160
161 /**
162 * Makes space for index data. The returned pointer is the location where index data
163 * should be written. On return the buffer that will hold the data as well as an offset into
164 * the buffer (in uint16_t units) where the data will be placed.
165 */
166 virtual uint16_t* makeIndexSpace(int indexCount, sk_sp<const GrBuffer>*, int* startIndex) = 0;
167
168 /**
169 * This is similar to makeVertexSpace. It allows the caller to use up to 'actualVertexCount'
170 * vertices in the returned pointer, which may exceed 'minVertexCount'.
171 * 'fallbackVertexCount' is the maximum number of vertices that should be allocated if a new
172 * buffer is allocated on behalf of this request.
173 */
174 virtual void* makeVertexSpaceAtLeast(size_t vertexSize, int minVertexCount,
175 int fallbackVertexCount, sk_sp<const GrBuffer>*,
176 int* startVertex, int* actualVertexCount) = 0;
177
178 /**
179 * This is similar to makeIndexSpace. It allows the caller to use up to 'actualIndexCount'
180 * indices in the returned pointer, which may exceed 'minIndexCount'.
181 * 'fallbackIndexCount' is the maximum number of indices that should be allocated if a new
182 * buffer is allocated on behalf of this request.
183 */
184 virtual uint16_t* makeIndexSpaceAtLeast(int minIndexCount, int fallbackIndexCount,
185 sk_sp<const GrBuffer>*, int* startIndex,
186 int* actualIndexCount) = 0;
187
188 /**
189 * Makes space for elements in a draw-indirect buffer. Upon success, the returned pointer is a
190 * CPU mapping where the data should be written.
191 */
192 virtual GrDrawIndirectCommand* makeDrawIndirectSpace(int drawCount,
193 sk_sp<const GrBuffer>* buffer,
194 size_t* offsetInBytes) = 0;
195
196 /**
197 * Makes space for elements in a draw-indexed-indirect buffer. Upon success, the returned
198 * pointer is a CPU mapping where the data should be written.
199 */
200 virtual GrDrawIndexedIndirectCommand* makeDrawIndexedIndirectSpace(
201 int drawCount, sk_sp<const GrBuffer>* buffer, size_t* offsetInBytes) = 0;
202
203 /** Helpers for ops which over-allocate and then return excess data to the pool. */
204 virtual void putBackIndices(int indices) = 0;
205 virtual void putBackVertices(int vertices, size_t vertexStride) = 0;
206
207 GrSimpleMesh* allocMesh() { return this->allocator()->make<GrSimpleMesh>(); }
208 GrSimpleMesh* allocMeshes(int n) { return this->allocator()->makeArray<GrSimpleMesh>(n); }
209 const GrSurfaceProxy** allocPrimProcProxyPtrs(int n) {
210 return this->allocator()->makeArray<const GrSurfaceProxy*>(n);
211 }
212
213 virtual GrRenderTargetProxy* proxy() const = 0;
214 virtual const GrSurfaceProxyView* writeView() const = 0;
215
216 virtual const GrAppliedClip* appliedClip() const = 0;
217 virtual GrAppliedClip detachAppliedClip() = 0;
218
219 virtual const GrXferProcessor::DstProxyView& dstProxyView() const = 0;
220
221 virtual GrResourceProvider* resourceProvider() const = 0;
222 uint32_t contextUniqueID() const { return this->resourceProvider()->contextUniqueID(); }
223
224 virtual GrStrikeCache* strikeCache() const = 0;
225 virtual GrAtlasManager* atlasManager() const = 0;
226 virtual GrSmallPathAtlasMgr* smallPathAtlasManager() const = 0;
227
228 // This should be called during onPrepare of a GrOp. The caller should add any proxies to the
229 // array it will use that it did not access during a call to visitProxies. This is usually the
230 // case for atlases.
231 virtual SkTArray<GrSurfaceProxy*, true>* sampledProxyArray() = 0;
232
233 virtual const GrCaps& caps() const = 0;
234
235 virtual GrDeferredUploadTarget* deferredUploadTarget() = 0;
236
237 virtual SkArenaAlloc* allocator() = 0;
238};
239
240#endif
241