blob: 1c9fac4425a8d28aaf0f83aa3ec03d28b9c51ea8 [file] [log] [blame]
bsalomoncb8979d2015-05-05 09:51:38 -07001/*
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
egdaniel0e1853c2016-03-17 11:35:45 -07008#ifndef GrMesh_DEFINED
9#define GrMesh_DEFINED
bsalomoncb8979d2015-05-05 09:51:38 -070010
cdalton397536c2016-03-25 12:15:03 -070011#include "GrBuffer.h"
Hal Canary466c7d62017-07-03 15:11:49 -040012#include "GrGpuResourceRef.h"
bsalomoncb8979d2015-05-05 09:51:38 -070013
Chris Dalton114a3c02017-05-26 15:17:19 -060014class GrPrimitiveProcessor;
15
bsalomoncb8979d2015-05-05 09:51:38 -070016/**
Brian Salomon25a88092016-12-01 09:36:50 -050017 * Used to communicate index and vertex buffers, counts, and offsets for a draw from GrOp to
bsalomoncb8979d2015-05-05 09:51:38 -070018 * 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 */
Chris Daltonbca46e22017-05-15 11:03:26 -060022class GrMesh {
23public:
24 GrMesh(GrPrimitiveType primitiveType)
Chris Dalton114a3c02017-05-26 15:17:19 -060025 : fPrimitiveType(primitiveType)
26 , fBaseVertex(0) {
Chris Dalton1d616352017-05-31 12:51:23 -060027 SkDEBUGCODE(fNonIndexNonInstanceData.fVertexCount = -1;)
Chris Daltonbca46e22017-05-15 11:03:26 -060028 }
29
Chris Dalton114a3c02017-05-26 15:17:19 -060030 GrPrimitiveType primitiveType() const { return fPrimitiveType; }
Brian Salomon802cb312018-06-08 18:05:20 -040031
Chris Dalton114a3c02017-05-26 15:17:19 -060032 bool isIndexed() const { return SkToBool(fIndexBuffer.get()); }
Chris Dalton1d616352017-05-31 12:51:23 -060033 bool isInstanced() const { return SkToBool(fInstanceBuffer.get()); }
Chris Dalton114a3c02017-05-26 15:17:19 -060034 bool hasVertexData() const { return SkToBool(fVertexBuffer.get()); }
35
Chris Dalton1d616352017-05-31 12:51:23 -060036 void setNonIndexedNonInstanced(int vertexCount);
37
Chris Dalton114a3c02017-05-26 15:17:19 -060038 void setIndexed(const GrBuffer* indexBuffer, int indexCount, int baseIndex,
Brian Salomon802cb312018-06-08 18:05:20 -040039 uint16_t minIndexValue, uint16_t maxIndexValue, GrPrimitiveRestart);
Chris Dalton114a3c02017-05-26 15:17:19 -060040 void setIndexedPatterned(const GrBuffer* indexBuffer, int indexCount, int vertexCount,
Chris Daltonbca46e22017-05-15 11:03:26 -060041 int patternRepeatCount, int maxPatternRepetitionsInIndexBuffer);
42
Chris Dalton1d616352017-05-31 12:51:23 -060043 void setInstanced(const GrBuffer* instanceBuffer, int instanceCount, int baseInstance,
44 int vertexCount);
45 void setIndexedInstanced(const GrBuffer* indexBuffer, int indexCount,
Brian Salomon802cb312018-06-08 18:05:20 -040046 const GrBuffer* instanceBuffer, int instanceCount, int baseInstance,
47 GrPrimitiveRestart);
Chris Dalton1d616352017-05-31 12:51:23 -060048
Chris Dalton114a3c02017-05-26 15:17:19 -060049 void setVertexData(const GrBuffer* vertexBuffer, int baseVertex = 0);
Chris Daltonbca46e22017-05-15 11:03:26 -060050
Chris Dalton114a3c02017-05-26 15:17:19 -060051 class SendToGpuImpl {
52 public:
Brian Salomon802cb312018-06-08 18:05:20 -040053 virtual void sendMeshToGpu(GrPrimitiveType, const GrBuffer* vertexBuffer, int vertexCount,
Chris Dalton114a3c02017-05-26 15:17:19 -060054 int baseVertex) = 0;
Chris Daltonbca46e22017-05-15 11:03:26 -060055
Brian Salomon802cb312018-06-08 18:05:20 -040056 virtual void sendIndexedMeshToGpu(GrPrimitiveType, const GrBuffer* indexBuffer,
57 int indexCount, int baseIndex, uint16_t minIndexValue,
Chris Dalton114a3c02017-05-26 15:17:19 -060058 uint16_t maxIndexValue, const GrBuffer* vertexBuffer,
Brian Salomon802cb312018-06-08 18:05:20 -040059 int baseVertex, GrPrimitiveRestart) = 0;
Chris Daltonbca46e22017-05-15 11:03:26 -060060
Brian Salomon802cb312018-06-08 18:05:20 -040061 virtual void sendInstancedMeshToGpu(GrPrimitiveType, const GrBuffer* vertexBuffer,
62 int vertexCount, int baseVertex,
63 const GrBuffer* instanceBuffer, int instanceCount,
64 int baseInstance) = 0;
Chris Dalton1d616352017-05-31 12:51:23 -060065
Brian Salomon802cb312018-06-08 18:05:20 -040066 virtual void sendIndexedInstancedMeshToGpu(GrPrimitiveType, const GrBuffer* indexBuffer,
67 int indexCount, int baseIndex,
68 const GrBuffer* vertexBuffer, int baseVertex,
69 const GrBuffer* instanceBuffer,
70 int instanceCount, int baseInstance,
71 GrPrimitiveRestart) = 0;
Chris Dalton1d616352017-05-31 12:51:23 -060072
Chris Dalton114a3c02017-05-26 15:17:19 -060073 virtual ~SendToGpuImpl() {}
74 };
75
Brian Salomon802cb312018-06-08 18:05:20 -040076 void sendToGpu(SendToGpuImpl*) const;
Chris Daltonbca46e22017-05-15 11:03:26 -060077
78 struct PatternBatch;
79
80private:
Chris Daltonff926502017-05-03 14:36:54 -040081 using PendingBuffer = GrPendingIOResource<const GrBuffer, kRead_GrIOType>;
82
Brian Salomon802cb312018-06-08 18:05:20 -040083 GrPrimitiveType fPrimitiveType;
84 PendingBuffer fIndexBuffer;
85 PendingBuffer fInstanceBuffer;
86 PendingBuffer fVertexBuffer;
87 int fBaseVertex;
88 GrPrimitiveRestart fPrimitiveRestart;
Chris Daltonff926502017-05-03 14:36:54 -040089
Chris Dalton114a3c02017-05-26 15:17:19 -060090 union {
Chris Dalton1d616352017-05-31 12:51:23 -060091 struct { // When fIndexBuffer == nullptr and fInstanceBuffer == nullptr.
Chris Dalton114a3c02017-05-26 15:17:19 -060092 int fVertexCount;
Chris Dalton1d616352017-05-31 12:51:23 -060093 } fNonIndexNonInstanceData;
Chris Dalton114a3c02017-05-26 15:17:19 -060094
Chris Dalton1d616352017-05-31 12:51:23 -060095 struct { // When fIndexBuffer != nullptr and fInstanceBuffer == nullptr.
Chris Dalton114a3c02017-05-26 15:17:19 -060096 struct {
97 int fIndexCount;
98 int fPatternRepeatCount;
99 } fIndexData;
100
101 union {
102 struct { // When fPatternRepeatCount == 0.
103 int fBaseIndex;
104 uint16_t fMinIndexValue;
105 uint16_t fMaxIndexValue;
106 } fNonPatternIndexData;
107
108 struct { // When fPatternRepeatCount != 0.
109 int fVertexCount;
110 int fMaxPatternRepetitionsInIndexBuffer;
111 } fPatternData;
112 };
113 };
Chris Dalton1d616352017-05-31 12:51:23 -0600114
115 struct { // When fInstanceBuffer != nullptr.
116 struct {
117 int fInstanceCount;
118 int fBaseInstance;
119 } fInstanceData;
120
121 union { // When fIndexBuffer == nullptr.
122 struct {
123 int fVertexCount;
124 } fInstanceNonIndexData;
125
126 struct { // When fIndexBuffer != nullptr.
127 int fIndexCount;
128 } fInstanceIndexData;
129 };
130 };
Chris Dalton114a3c02017-05-26 15:17:19 -0600131 };
Chris Daltonff926502017-05-03 14:36:54 -0400132};
133
Chris Dalton1d616352017-05-31 12:51:23 -0600134inline void GrMesh::setNonIndexedNonInstanced(int vertexCount) {
Chris Daltonbca46e22017-05-15 11:03:26 -0600135 fIndexBuffer.reset(nullptr);
Chris Dalton1d616352017-05-31 12:51:23 -0600136 fInstanceBuffer.reset(nullptr);
137 fNonIndexNonInstanceData.fVertexCount = vertexCount;
Brian Salomon802cb312018-06-08 18:05:20 -0400138 fPrimitiveRestart = GrPrimitiveRestart::kNo;
Chris Daltonbca46e22017-05-15 11:03:26 -0600139}
140
Chris Dalton114a3c02017-05-26 15:17:19 -0600141inline void GrMesh::setIndexed(const GrBuffer* indexBuffer, int indexCount, int baseIndex,
Brian Salomon802cb312018-06-08 18:05:20 -0400142 uint16_t minIndexValue, uint16_t maxIndexValue,
143 GrPrimitiveRestart primitiveRestart) {
Chris Daltonbca46e22017-05-15 11:03:26 -0600144 SkASSERT(indexBuffer);
145 SkASSERT(indexCount >= 1);
146 SkASSERT(baseIndex >= 0);
Chris Daltona88da482017-06-06 12:25:28 -0600147 SkASSERT(maxIndexValue >= minIndexValue);
Chris Daltonbca46e22017-05-15 11:03:26 -0600148 fIndexBuffer.reset(indexBuffer);
Chris Dalton1d616352017-05-31 12:51:23 -0600149 fInstanceBuffer.reset(nullptr);
Chris Dalton114a3c02017-05-26 15:17:19 -0600150 fIndexData.fIndexCount = indexCount;
151 fIndexData.fPatternRepeatCount = 0;
152 fNonPatternIndexData.fBaseIndex = baseIndex;
153 fNonPatternIndexData.fMinIndexValue = minIndexValue;
154 fNonPatternIndexData.fMaxIndexValue = maxIndexValue;
Brian Salomon802cb312018-06-08 18:05:20 -0400155 fPrimitiveRestart = primitiveRestart;
Chris Daltonbca46e22017-05-15 11:03:26 -0600156}
157
158inline void GrMesh::setIndexedPatterned(const GrBuffer* indexBuffer, int indexCount,
Chris Dalton114a3c02017-05-26 15:17:19 -0600159 int vertexCount, int patternRepeatCount,
Chris Daltonbca46e22017-05-15 11:03:26 -0600160 int maxPatternRepetitionsInIndexBuffer) {
161 SkASSERT(indexBuffer);
162 SkASSERT(indexCount >= 1);
Chris Dalton114a3c02017-05-26 15:17:19 -0600163 SkASSERT(vertexCount >= 1);
Chris Daltonbca46e22017-05-15 11:03:26 -0600164 SkASSERT(patternRepeatCount >= 1);
165 SkASSERT(maxPatternRepetitionsInIndexBuffer >= 1);
166 fIndexBuffer.reset(indexBuffer);
Chris Dalton1d616352017-05-31 12:51:23 -0600167 fInstanceBuffer.reset(nullptr);
Chris Dalton114a3c02017-05-26 15:17:19 -0600168 fIndexData.fIndexCount = indexCount;
169 fIndexData.fPatternRepeatCount = patternRepeatCount;
170 fPatternData.fVertexCount = vertexCount;
171 fPatternData.fMaxPatternRepetitionsInIndexBuffer = maxPatternRepetitionsInIndexBuffer;
Brian Salomon802cb312018-06-08 18:05:20 -0400172 fPrimitiveRestart = GrPrimitiveRestart::kNo;
Chris Daltonbca46e22017-05-15 11:03:26 -0600173}
174
Chris Dalton1d616352017-05-31 12:51:23 -0600175inline void GrMesh::setInstanced(const GrBuffer* instanceBuffer, int instanceCount,
176 int baseInstance, int vertexCount) {
177 SkASSERT(instanceBuffer);
178 SkASSERT(instanceCount >= 1);
179 SkASSERT(baseInstance >= 0);
180 fIndexBuffer.reset(nullptr);
181 fInstanceBuffer.reset(instanceBuffer);
182 fInstanceData.fInstanceCount = instanceCount;
183 fInstanceData.fBaseInstance = baseInstance;
184 fInstanceNonIndexData.fVertexCount = vertexCount;
Brian Salomon802cb312018-06-08 18:05:20 -0400185 fPrimitiveRestart = GrPrimitiveRestart::kNo;
Chris Dalton1d616352017-05-31 12:51:23 -0600186}
187
188inline void GrMesh::setIndexedInstanced(const GrBuffer* indexBuffer, int indexCount,
189 const GrBuffer* instanceBuffer, int instanceCount,
Brian Salomon802cb312018-06-08 18:05:20 -0400190 int baseInstance, GrPrimitiveRestart primitiveRestart) {
Chris Dalton1d616352017-05-31 12:51:23 -0600191 SkASSERT(indexBuffer);
192 SkASSERT(indexCount >= 1);
193 SkASSERT(instanceBuffer);
194 SkASSERT(instanceCount >= 1);
195 SkASSERT(baseInstance >= 0);
196 fIndexBuffer.reset(indexBuffer);
197 fInstanceBuffer.reset(instanceBuffer);
198 fInstanceData.fInstanceCount = instanceCount;
199 fInstanceData.fBaseInstance = baseInstance;
200 fInstanceIndexData.fIndexCount = indexCount;
Brian Salomon802cb312018-06-08 18:05:20 -0400201 fPrimitiveRestart = primitiveRestart;
Chris Dalton1d616352017-05-31 12:51:23 -0600202}
203
Chris Dalton114a3c02017-05-26 15:17:19 -0600204inline void GrMesh::setVertexData(const GrBuffer* vertexBuffer, int baseVertex) {
205 SkASSERT(baseVertex >= 0);
Chris Daltonbca46e22017-05-15 11:03:26 -0600206 fVertexBuffer.reset(vertexBuffer);
Chris Daltonbca46e22017-05-15 11:03:26 -0600207 fBaseVertex = baseVertex;
208}
209
Brian Salomon802cb312018-06-08 18:05:20 -0400210inline void GrMesh::sendToGpu(SendToGpuImpl* impl) const {
Chris Dalton1d616352017-05-31 12:51:23 -0600211 if (this->isInstanced()) {
212 if (!this->isIndexed()) {
Brian Salomon802cb312018-06-08 18:05:20 -0400213 impl->sendInstancedMeshToGpu(fPrimitiveType, fVertexBuffer.get(),
Chris Dalton1d616352017-05-31 12:51:23 -0600214 fInstanceNonIndexData.fVertexCount, fBaseVertex,
215 fInstanceBuffer.get(), fInstanceData.fInstanceCount,
216 fInstanceData.fBaseInstance);
217 } else {
Brian Salomon802cb312018-06-08 18:05:20 -0400218 impl->sendIndexedInstancedMeshToGpu(
219 fPrimitiveType, fIndexBuffer.get(), fInstanceIndexData.fIndexCount, 0,
220 fVertexBuffer.get(), fBaseVertex, fInstanceBuffer.get(),
221 fInstanceData.fInstanceCount, fInstanceData.fBaseInstance, fPrimitiveRestart);
Chris Dalton1d616352017-05-31 12:51:23 -0600222 }
223 return;
224 }
225
Chris Dalton114a3c02017-05-26 15:17:19 -0600226 if (!this->isIndexed()) {
Chris Dalton1d616352017-05-31 12:51:23 -0600227 SkASSERT(fNonIndexNonInstanceData.fVertexCount > 0);
Brian Salomon802cb312018-06-08 18:05:20 -0400228 impl->sendMeshToGpu(fPrimitiveType, fVertexBuffer.get(),
Chris Dalton1d616352017-05-31 12:51:23 -0600229 fNonIndexNonInstanceData.fVertexCount, fBaseVertex);
Chris Dalton114a3c02017-05-26 15:17:19 -0600230 return;
bsalomoncb8979d2015-05-05 09:51:38 -0700231 }
232
Chris Dalton114a3c02017-05-26 15:17:19 -0600233 if (0 == fIndexData.fPatternRepeatCount) {
Brian Salomon802cb312018-06-08 18:05:20 -0400234 impl->sendIndexedMeshToGpu(fPrimitiveType, fIndexBuffer.get(), fIndexData.fIndexCount,
235 fNonPatternIndexData.fBaseIndex,
Chris Dalton114a3c02017-05-26 15:17:19 -0600236 fNonPatternIndexData.fMinIndexValue,
237 fNonPatternIndexData.fMaxIndexValue, fVertexBuffer.get(),
Brian Salomon802cb312018-06-08 18:05:20 -0400238 fBaseVertex, fPrimitiveRestart);
Chris Dalton114a3c02017-05-26 15:17:19 -0600239 return;
bsalomoncb8979d2015-05-05 09:51:38 -0700240 }
241
Chris Dalton114a3c02017-05-26 15:17:19 -0600242 SkASSERT(fIndexData.fPatternRepeatCount > 0);
243 int baseRepetition = 0;
244 do {
245 int repeatCount = SkTMin(fPatternData.fMaxPatternRepetitionsInIndexBuffer,
246 fIndexData.fPatternRepeatCount - baseRepetition);
247 // A patterned index buffer must contain indices in the range [0..vertexCount].
248 int minIndexValue = 0;
249 int maxIndexValue = fPatternData.fVertexCount * repeatCount - 1;
Brian Salomon802cb312018-06-08 18:05:20 -0400250 SkASSERT(fPrimitiveRestart == GrPrimitiveRestart::kNo);
251 impl->sendIndexedMeshToGpu(
252 fPrimitiveType, fIndexBuffer.get(), fIndexData.fIndexCount * repeatCount, 0,
253 minIndexValue, maxIndexValue, fVertexBuffer.get(),
254 fBaseVertex + fPatternData.fVertexCount * baseRepetition, GrPrimitiveRestart::kNo);
Chris Dalton114a3c02017-05-26 15:17:19 -0600255 baseRepetition += repeatCount;
256 } while (baseRepetition < fIndexData.fPatternRepeatCount);
Chris Daltonff926502017-05-03 14:36:54 -0400257}
258
bsalomoncb8979d2015-05-05 09:51:38 -0700259#endif