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 GrMesh_DEFINED
9 #define GrMesh_DEFINED
10
11 #include "GrBuffer.h"
12 #include "GrPendingIOResource.h"
13
14 class GrPrimitiveProcessor;
15
16 /**
17 * Used to communicate index and vertex buffers, counts, and offsets for a draw from GrOp to
18 * GrGpu. It also holds the primitive type for the draw. TODO: Consider moving ownership of this
19 * and draw-issuing responsibility to GrPrimitiveProcessor. The rest of the vertex info lives there
20 * already (stride, attribute mappings).
21 */
22 class GrMesh {
23 public:
24 GrMesh(GrPrimitiveType primitiveType = GrPrimitiveType::kTriangles)
fPrimitiveType(primitiveType)25 : fPrimitiveType(primitiveType), fBaseVertex(0) {
26 SkDEBUGCODE(fNonIndexNonInstanceData.fVertexCount = -1;)
27 }
28
setPrimitiveType(GrPrimitiveType type)29 void setPrimitiveType(GrPrimitiveType type) { fPrimitiveType = type; }
primitiveType()30 GrPrimitiveType primitiveType() const { return fPrimitiveType; }
31
isIndexed()32 bool isIndexed() const { return SkToBool(fIndexBuffer.get()); }
isInstanced()33 bool isInstanced() const { return SkToBool(fInstanceBuffer.get()); }
hasVertexData()34 bool hasVertexData() const { return SkToBool(fVertexBuffer.get()); }
35
36 void setNonIndexedNonInstanced(int vertexCount);
37
38 void setIndexed(sk_sp<const GrBuffer> indexBuffer, int indexCount, int baseIndex,
39 uint16_t minIndexValue, uint16_t maxIndexValue, GrPrimitiveRestart);
40 void setIndexedPatterned(sk_sp<const GrBuffer> indexBuffer, int indexCount, int vertexCount,
41 int patternRepeatCount, int maxPatternRepetitionsInIndexBuffer);
42
43 void setInstanced(sk_sp<const GrBuffer> instanceBuffer, int instanceCount, int baseInstance,
44 int vertexCount);
45 void setIndexedInstanced(sk_sp<const GrBuffer>, int indexCount, sk_sp<const GrBuffer>,
46 int instanceCount, int baseInstance, GrPrimitiveRestart);
47
48 void setVertexData(sk_sp<const GrBuffer> vertexBuffer, int baseVertex = 0);
49
50 class SendToGpuImpl {
51 public:
52 virtual void sendMeshToGpu(GrPrimitiveType, const GrBuffer* vertexBuffer, int vertexCount,
53 int baseVertex) = 0;
54
55 virtual void sendIndexedMeshToGpu(GrPrimitiveType, const GrBuffer* indexBuffer,
56 int indexCount, int baseIndex, uint16_t minIndexValue,
57 uint16_t maxIndexValue, const GrBuffer* vertexBuffer,
58 int baseVertex, GrPrimitiveRestart) = 0;
59
60 virtual void sendInstancedMeshToGpu(GrPrimitiveType, const GrBuffer* vertexBuffer,
61 int vertexCount, int baseVertex,
62 const GrBuffer* instanceBuffer, int instanceCount,
63 int baseInstance) = 0;
64
65 virtual void sendIndexedInstancedMeshToGpu(GrPrimitiveType, const GrBuffer* indexBuffer,
66 int indexCount, int baseIndex,
67 const GrBuffer* vertexBuffer, int baseVertex,
68 const GrBuffer* instanceBuffer,
69 int instanceCount, int baseInstance,
70 GrPrimitiveRestart) = 0;
71
~SendToGpuImpl()72 virtual ~SendToGpuImpl() {}
73 };
74
75 void sendToGpu(SendToGpuImpl*) const;
76
77 private:
78 GrPrimitiveType fPrimitiveType;
79 sk_sp<const GrBuffer> fIndexBuffer;
80 sk_sp<const GrBuffer> fInstanceBuffer;
81 sk_sp<const GrBuffer> fVertexBuffer;
82 int fBaseVertex;
83 GrPrimitiveRestart fPrimitiveRestart;
84
85 union {
86 struct { // When fIndexBuffer == nullptr and fInstanceBuffer == nullptr.
87 int fVertexCount;
88 } fNonIndexNonInstanceData;
89
90 struct { // When fIndexBuffer != nullptr and fInstanceBuffer == nullptr.
91 struct {
92 int fIndexCount;
93 int fPatternRepeatCount;
94 } fIndexData;
95
96 union {
97 struct { // When fPatternRepeatCount == 0.
98 int fBaseIndex;
99 uint16_t fMinIndexValue;
100 uint16_t fMaxIndexValue;
101 } fNonPatternIndexData;
102
103 struct { // When fPatternRepeatCount != 0.
104 int fVertexCount;
105 int fMaxPatternRepetitionsInIndexBuffer;
106 } fPatternData;
107 };
108 };
109
110 struct { // When fInstanceBuffer != nullptr.
111 struct {
112 int fInstanceCount;
113 int fBaseInstance;
114 } fInstanceData;
115
116 union { // When fIndexBuffer == nullptr.
117 struct {
118 int fVertexCount;
119 } fInstanceNonIndexData;
120
121 struct { // When fIndexBuffer != nullptr.
122 int fIndexCount;
123 } fInstanceIndexData;
124 };
125 };
126 };
127 };
128
setNonIndexedNonInstanced(int vertexCount)129 inline void GrMesh::setNonIndexedNonInstanced(int vertexCount) {
130 fIndexBuffer.reset(nullptr);
131 fInstanceBuffer.reset(nullptr);
132 fNonIndexNonInstanceData.fVertexCount = vertexCount;
133 fPrimitiveRestart = GrPrimitiveRestart::kNo;
134 }
135
setIndexed(sk_sp<const GrBuffer> indexBuffer,int indexCount,int baseIndex,uint16_t minIndexValue,uint16_t maxIndexValue,GrPrimitiveRestart primitiveRestart)136 inline void GrMesh::setIndexed(sk_sp<const GrBuffer> indexBuffer, int indexCount, int baseIndex,
137 uint16_t minIndexValue, uint16_t maxIndexValue,
138 GrPrimitiveRestart primitiveRestart) {
139 SkASSERT(indexBuffer);
140 SkASSERT(indexCount >= 1);
141 SkASSERT(baseIndex >= 0);
142 SkASSERT(maxIndexValue >= minIndexValue);
143 fIndexBuffer = std::move(indexBuffer);
144 fInstanceBuffer.reset();
145 fIndexData.fIndexCount = indexCount;
146 fIndexData.fPatternRepeatCount = 0;
147 fNonPatternIndexData.fBaseIndex = baseIndex;
148 fNonPatternIndexData.fMinIndexValue = minIndexValue;
149 fNonPatternIndexData.fMaxIndexValue = maxIndexValue;
150 fPrimitiveRestart = primitiveRestart;
151 }
152
setIndexedPatterned(sk_sp<const GrBuffer> indexBuffer,int indexCount,int vertexCount,int patternRepeatCount,int maxPatternRepetitionsInIndexBuffer)153 inline void GrMesh::setIndexedPatterned(sk_sp<const GrBuffer> indexBuffer, int indexCount,
154 int vertexCount, int patternRepeatCount,
155 int maxPatternRepetitionsInIndexBuffer) {
156 SkASSERT(indexBuffer);
157 SkASSERT(indexCount >= 1);
158 SkASSERT(vertexCount >= 1);
159 SkASSERT(patternRepeatCount >= 1);
160 SkASSERT(maxPatternRepetitionsInIndexBuffer >= 1);
161 fIndexBuffer = std::move(indexBuffer);
162 fInstanceBuffer.reset();
163 fIndexData.fIndexCount = indexCount;
164 fIndexData.fPatternRepeatCount = patternRepeatCount;
165 fPatternData.fVertexCount = vertexCount;
166 fPatternData.fMaxPatternRepetitionsInIndexBuffer = maxPatternRepetitionsInIndexBuffer;
167 fPrimitiveRestart = GrPrimitiveRestart::kNo;
168 }
169
setInstanced(sk_sp<const GrBuffer> instanceBuffer,int instanceCount,int baseInstance,int vertexCount)170 inline void GrMesh::setInstanced(sk_sp<const GrBuffer> instanceBuffer, int instanceCount,
171 int baseInstance, int vertexCount) {
172 SkASSERT(instanceBuffer);
173 SkASSERT(instanceCount >= 1);
174 SkASSERT(baseInstance >= 0);
175 fIndexBuffer.reset();
176 fInstanceBuffer = std::move(instanceBuffer);
177 fInstanceData.fInstanceCount = instanceCount;
178 fInstanceData.fBaseInstance = baseInstance;
179 fInstanceNonIndexData.fVertexCount = vertexCount;
180 fPrimitiveRestart = GrPrimitiveRestart::kNo;
181 }
182
setIndexedInstanced(sk_sp<const GrBuffer> indexBuffer,int indexCount,sk_sp<const GrBuffer> instanceBuffer,int instanceCount,int baseInstance,GrPrimitiveRestart primitiveRestart)183 inline void GrMesh::setIndexedInstanced(sk_sp<const GrBuffer> indexBuffer, int indexCount,
184 sk_sp<const GrBuffer> instanceBuffer, int instanceCount,
185 int baseInstance, GrPrimitiveRestart primitiveRestart) {
186 SkASSERT(indexBuffer);
187 SkASSERT(indexCount >= 1);
188 SkASSERT(instanceBuffer);
189 SkASSERT(instanceCount >= 1);
190 SkASSERT(baseInstance >= 0);
191 fIndexBuffer = std::move(indexBuffer);
192 fInstanceBuffer = std::move(instanceBuffer);
193 fInstanceData.fInstanceCount = instanceCount;
194 fInstanceData.fBaseInstance = baseInstance;
195 fInstanceIndexData.fIndexCount = indexCount;
196 fPrimitiveRestart = primitiveRestart;
197 }
198
setVertexData(sk_sp<const GrBuffer> vertexBuffer,int baseVertex)199 inline void GrMesh::setVertexData(sk_sp<const GrBuffer> vertexBuffer, int baseVertex) {
200 SkASSERT(baseVertex >= 0);
201 fVertexBuffer = std::move(vertexBuffer);
202 fBaseVertex = baseVertex;
203 }
204
sendToGpu(SendToGpuImpl * impl)205 inline void GrMesh::sendToGpu(SendToGpuImpl* impl) const {
206 if (this->isInstanced()) {
207 if (!this->isIndexed()) {
208 impl->sendInstancedMeshToGpu(fPrimitiveType, fVertexBuffer.get(),
209 fInstanceNonIndexData.fVertexCount, fBaseVertex,
210 fInstanceBuffer.get(), fInstanceData.fInstanceCount,
211 fInstanceData.fBaseInstance);
212 } else {
213 impl->sendIndexedInstancedMeshToGpu(
214 fPrimitiveType, fIndexBuffer.get(), fInstanceIndexData.fIndexCount, 0,
215 fVertexBuffer.get(), fBaseVertex, fInstanceBuffer.get(),
216 fInstanceData.fInstanceCount, fInstanceData.fBaseInstance, fPrimitiveRestart);
217 }
218 return;
219 }
220
221 if (!this->isIndexed()) {
222 SkASSERT(fNonIndexNonInstanceData.fVertexCount > 0);
223 impl->sendMeshToGpu(fPrimitiveType, fVertexBuffer.get(),
224 fNonIndexNonInstanceData.fVertexCount, fBaseVertex);
225 return;
226 }
227
228 if (0 == fIndexData.fPatternRepeatCount) {
229 impl->sendIndexedMeshToGpu(fPrimitiveType, fIndexBuffer.get(), fIndexData.fIndexCount,
230 fNonPatternIndexData.fBaseIndex,
231 fNonPatternIndexData.fMinIndexValue,
232 fNonPatternIndexData.fMaxIndexValue, fVertexBuffer.get(),
233 fBaseVertex, fPrimitiveRestart);
234 return;
235 }
236
237 SkASSERT(fIndexData.fPatternRepeatCount > 0);
238 int baseRepetition = 0;
239 do {
240 int repeatCount = SkTMin(fPatternData.fMaxPatternRepetitionsInIndexBuffer,
241 fIndexData.fPatternRepeatCount - baseRepetition);
242 // A patterned index buffer must contain indices in the range [0..vertexCount].
243 int minIndexValue = 0;
244 int maxIndexValue = fPatternData.fVertexCount * repeatCount - 1;
245 SkASSERT(fPrimitiveRestart == GrPrimitiveRestart::kNo);
246 impl->sendIndexedMeshToGpu(
247 fPrimitiveType, fIndexBuffer.get(), fIndexData.fIndexCount * repeatCount, 0,
248 minIndexValue, maxIndexValue, fVertexBuffer.get(),
249 fBaseVertex + fPatternData.fVertexCount * baseRepetition, GrPrimitiveRestart::kNo);
250 baseRepetition += repeatCount;
251 } while (baseRepetition < fIndexData.fPatternRepeatCount);
252 }
253
254 #endif
255