blob: e8a3f5cec309683723358e8a4ad1d5b16d52cd74 [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"
Brian Salomonae5f9532018-07-31 11:03:40 -040012#include "GrPendingIOResource.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:
Brian Salomon7eae3e02018-08-07 14:02:38 +000024 GrMesh(GrPrimitiveType primitiveType = GrPrimitiveType::kTriangles)
25 : fPrimitiveType(primitiveType), fBaseVertex(0) {
Chris Dalton1d616352017-05-31 12:51:23 -060026 SkDEBUGCODE(fNonIndexNonInstanceData.fVertexCount = -1;)
Chris Daltonbca46e22017-05-15 11:03:26 -060027 }
28
Brian Salomon7eae3e02018-08-07 14:02:38 +000029 void setPrimitiveType(GrPrimitiveType type) { fPrimitiveType = type; }
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
Chris Daltonbca46e22017-05-15 11:03:26 -060078private:
Chris Daltonff926502017-05-03 14:36:54 -040079 using PendingBuffer = GrPendingIOResource<const GrBuffer, kRead_GrIOType>;
80
Brian Salomon802cb312018-06-08 18:05:20 -040081 GrPrimitiveType fPrimitiveType;
82 PendingBuffer fIndexBuffer;
83 PendingBuffer fInstanceBuffer;
84 PendingBuffer fVertexBuffer;
85 int fBaseVertex;
86 GrPrimitiveRestart fPrimitiveRestart;
Chris Daltonff926502017-05-03 14:36:54 -040087
Chris Dalton114a3c02017-05-26 15:17:19 -060088 union {
Chris Dalton1d616352017-05-31 12:51:23 -060089 struct { // When fIndexBuffer == nullptr and fInstanceBuffer == nullptr.
Chris Dalton114a3c02017-05-26 15:17:19 -060090 int fVertexCount;
Chris Dalton1d616352017-05-31 12:51:23 -060091 } fNonIndexNonInstanceData;
Chris Dalton114a3c02017-05-26 15:17:19 -060092
Chris Dalton1d616352017-05-31 12:51:23 -060093 struct { // When fIndexBuffer != nullptr and fInstanceBuffer == nullptr.
Chris Dalton114a3c02017-05-26 15:17:19 -060094 struct {
95 int fIndexCount;
96 int fPatternRepeatCount;
97 } fIndexData;
98
99 union {
100 struct { // When fPatternRepeatCount == 0.
101 int fBaseIndex;
102 uint16_t fMinIndexValue;
103 uint16_t fMaxIndexValue;
104 } fNonPatternIndexData;
105
106 struct { // When fPatternRepeatCount != 0.
107 int fVertexCount;
108 int fMaxPatternRepetitionsInIndexBuffer;
109 } fPatternData;
110 };
111 };
Chris Dalton1d616352017-05-31 12:51:23 -0600112
113 struct { // When fInstanceBuffer != nullptr.
114 struct {
115 int fInstanceCount;
116 int fBaseInstance;
117 } fInstanceData;
118
119 union { // When fIndexBuffer == nullptr.
120 struct {
121 int fVertexCount;
122 } fInstanceNonIndexData;
123
124 struct { // When fIndexBuffer != nullptr.
125 int fIndexCount;
126 } fInstanceIndexData;
127 };
128 };
Chris Dalton114a3c02017-05-26 15:17:19 -0600129 };
Chris Daltonff926502017-05-03 14:36:54 -0400130};
131
Chris Dalton1d616352017-05-31 12:51:23 -0600132inline void GrMesh::setNonIndexedNonInstanced(int vertexCount) {
Chris Daltonbca46e22017-05-15 11:03:26 -0600133 fIndexBuffer.reset(nullptr);
Chris Dalton1d616352017-05-31 12:51:23 -0600134 fInstanceBuffer.reset(nullptr);
135 fNonIndexNonInstanceData.fVertexCount = vertexCount;
Brian Salomon802cb312018-06-08 18:05:20 -0400136 fPrimitiveRestart = GrPrimitiveRestart::kNo;
Chris Daltonbca46e22017-05-15 11:03:26 -0600137}
138
Chris Dalton114a3c02017-05-26 15:17:19 -0600139inline void GrMesh::setIndexed(const GrBuffer* indexBuffer, int indexCount, int baseIndex,
Brian Salomon802cb312018-06-08 18:05:20 -0400140 uint16_t minIndexValue, uint16_t maxIndexValue,
141 GrPrimitiveRestart primitiveRestart) {
Chris Daltonbca46e22017-05-15 11:03:26 -0600142 SkASSERT(indexBuffer);
143 SkASSERT(indexCount >= 1);
144 SkASSERT(baseIndex >= 0);
Chris Daltona88da482017-06-06 12:25:28 -0600145 SkASSERT(maxIndexValue >= minIndexValue);
Chris Daltonbca46e22017-05-15 11:03:26 -0600146 fIndexBuffer.reset(indexBuffer);
Chris Dalton1d616352017-05-31 12:51:23 -0600147 fInstanceBuffer.reset(nullptr);
Chris Dalton114a3c02017-05-26 15:17:19 -0600148 fIndexData.fIndexCount = indexCount;
149 fIndexData.fPatternRepeatCount = 0;
150 fNonPatternIndexData.fBaseIndex = baseIndex;
151 fNonPatternIndexData.fMinIndexValue = minIndexValue;
152 fNonPatternIndexData.fMaxIndexValue = maxIndexValue;
Brian Salomon802cb312018-06-08 18:05:20 -0400153 fPrimitiveRestart = primitiveRestart;
Chris Daltonbca46e22017-05-15 11:03:26 -0600154}
155
156inline void GrMesh::setIndexedPatterned(const GrBuffer* indexBuffer, int indexCount,
Chris Dalton114a3c02017-05-26 15:17:19 -0600157 int vertexCount, int patternRepeatCount,
Chris Daltonbca46e22017-05-15 11:03:26 -0600158 int maxPatternRepetitionsInIndexBuffer) {
159 SkASSERT(indexBuffer);
160 SkASSERT(indexCount >= 1);
Chris Dalton114a3c02017-05-26 15:17:19 -0600161 SkASSERT(vertexCount >= 1);
Chris Daltonbca46e22017-05-15 11:03:26 -0600162 SkASSERT(patternRepeatCount >= 1);
163 SkASSERT(maxPatternRepetitionsInIndexBuffer >= 1);
164 fIndexBuffer.reset(indexBuffer);
Chris Dalton1d616352017-05-31 12:51:23 -0600165 fInstanceBuffer.reset(nullptr);
Chris Dalton114a3c02017-05-26 15:17:19 -0600166 fIndexData.fIndexCount = indexCount;
167 fIndexData.fPatternRepeatCount = patternRepeatCount;
168 fPatternData.fVertexCount = vertexCount;
169 fPatternData.fMaxPatternRepetitionsInIndexBuffer = maxPatternRepetitionsInIndexBuffer;
Brian Salomon802cb312018-06-08 18:05:20 -0400170 fPrimitiveRestart = GrPrimitiveRestart::kNo;
Chris Daltonbca46e22017-05-15 11:03:26 -0600171}
172
Chris Dalton1d616352017-05-31 12:51:23 -0600173inline void GrMesh::setInstanced(const GrBuffer* instanceBuffer, int instanceCount,
174 int baseInstance, int vertexCount) {
175 SkASSERT(instanceBuffer);
176 SkASSERT(instanceCount >= 1);
177 SkASSERT(baseInstance >= 0);
178 fIndexBuffer.reset(nullptr);
179 fInstanceBuffer.reset(instanceBuffer);
180 fInstanceData.fInstanceCount = instanceCount;
181 fInstanceData.fBaseInstance = baseInstance;
182 fInstanceNonIndexData.fVertexCount = vertexCount;
Brian Salomon802cb312018-06-08 18:05:20 -0400183 fPrimitiveRestart = GrPrimitiveRestart::kNo;
Chris Dalton1d616352017-05-31 12:51:23 -0600184}
185
186inline void GrMesh::setIndexedInstanced(const GrBuffer* indexBuffer, int indexCount,
187 const GrBuffer* instanceBuffer, int instanceCount,
Brian Salomon802cb312018-06-08 18:05:20 -0400188 int baseInstance, GrPrimitiveRestart primitiveRestart) {
Chris Dalton1d616352017-05-31 12:51:23 -0600189 SkASSERT(indexBuffer);
190 SkASSERT(indexCount >= 1);
191 SkASSERT(instanceBuffer);
192 SkASSERT(instanceCount >= 1);
193 SkASSERT(baseInstance >= 0);
194 fIndexBuffer.reset(indexBuffer);
195 fInstanceBuffer.reset(instanceBuffer);
196 fInstanceData.fInstanceCount = instanceCount;
197 fInstanceData.fBaseInstance = baseInstance;
198 fInstanceIndexData.fIndexCount = indexCount;
Brian Salomon802cb312018-06-08 18:05:20 -0400199 fPrimitiveRestart = primitiveRestart;
Chris Dalton1d616352017-05-31 12:51:23 -0600200}
201
Chris Dalton114a3c02017-05-26 15:17:19 -0600202inline void GrMesh::setVertexData(const GrBuffer* vertexBuffer, int baseVertex) {
203 SkASSERT(baseVertex >= 0);
Chris Daltonbca46e22017-05-15 11:03:26 -0600204 fVertexBuffer.reset(vertexBuffer);
Chris Daltonbca46e22017-05-15 11:03:26 -0600205 fBaseVertex = baseVertex;
206}
207
Brian Salomon802cb312018-06-08 18:05:20 -0400208inline void GrMesh::sendToGpu(SendToGpuImpl* impl) const {
Chris Dalton1d616352017-05-31 12:51:23 -0600209 if (this->isInstanced()) {
210 if (!this->isIndexed()) {
Brian Salomon802cb312018-06-08 18:05:20 -0400211 impl->sendInstancedMeshToGpu(fPrimitiveType, fVertexBuffer.get(),
Chris Dalton1d616352017-05-31 12:51:23 -0600212 fInstanceNonIndexData.fVertexCount, fBaseVertex,
213 fInstanceBuffer.get(), fInstanceData.fInstanceCount,
214 fInstanceData.fBaseInstance);
215 } else {
Brian Salomon802cb312018-06-08 18:05:20 -0400216 impl->sendIndexedInstancedMeshToGpu(
217 fPrimitiveType, fIndexBuffer.get(), fInstanceIndexData.fIndexCount, 0,
218 fVertexBuffer.get(), fBaseVertex, fInstanceBuffer.get(),
219 fInstanceData.fInstanceCount, fInstanceData.fBaseInstance, fPrimitiveRestart);
Chris Dalton1d616352017-05-31 12:51:23 -0600220 }
221 return;
222 }
223
Chris Dalton114a3c02017-05-26 15:17:19 -0600224 if (!this->isIndexed()) {
Chris Dalton1d616352017-05-31 12:51:23 -0600225 SkASSERT(fNonIndexNonInstanceData.fVertexCount > 0);
Brian Salomon802cb312018-06-08 18:05:20 -0400226 impl->sendMeshToGpu(fPrimitiveType, fVertexBuffer.get(),
Chris Dalton1d616352017-05-31 12:51:23 -0600227 fNonIndexNonInstanceData.fVertexCount, fBaseVertex);
Chris Dalton114a3c02017-05-26 15:17:19 -0600228 return;
bsalomoncb8979d2015-05-05 09:51:38 -0700229 }
230
Chris Dalton114a3c02017-05-26 15:17:19 -0600231 if (0 == fIndexData.fPatternRepeatCount) {
Brian Salomon802cb312018-06-08 18:05:20 -0400232 impl->sendIndexedMeshToGpu(fPrimitiveType, fIndexBuffer.get(), fIndexData.fIndexCount,
233 fNonPatternIndexData.fBaseIndex,
Chris Dalton114a3c02017-05-26 15:17:19 -0600234 fNonPatternIndexData.fMinIndexValue,
235 fNonPatternIndexData.fMaxIndexValue, fVertexBuffer.get(),
Brian Salomon802cb312018-06-08 18:05:20 -0400236 fBaseVertex, fPrimitiveRestart);
Chris Dalton114a3c02017-05-26 15:17:19 -0600237 return;
bsalomoncb8979d2015-05-05 09:51:38 -0700238 }
239
Chris Dalton114a3c02017-05-26 15:17:19 -0600240 SkASSERT(fIndexData.fPatternRepeatCount > 0);
241 int baseRepetition = 0;
242 do {
243 int repeatCount = SkTMin(fPatternData.fMaxPatternRepetitionsInIndexBuffer,
244 fIndexData.fPatternRepeatCount - baseRepetition);
245 // A patterned index buffer must contain indices in the range [0..vertexCount].
246 int minIndexValue = 0;
247 int maxIndexValue = fPatternData.fVertexCount * repeatCount - 1;
Brian Salomon802cb312018-06-08 18:05:20 -0400248 SkASSERT(fPrimitiveRestart == GrPrimitiveRestart::kNo);
249 impl->sendIndexedMeshToGpu(
250 fPrimitiveType, fIndexBuffer.get(), fIndexData.fIndexCount * repeatCount, 0,
251 minIndexValue, maxIndexValue, fVertexBuffer.get(),
252 fBaseVertex + fPatternData.fVertexCount * baseRepetition, GrPrimitiveRestart::kNo);
Chris Dalton114a3c02017-05-26 15:17:19 -0600253 baseRepetition += repeatCount;
254 } while (baseRepetition < fIndexData.fPatternRepeatCount);
Chris Daltonff926502017-05-03 14:36:54 -0400255}
256
bsalomoncb8979d2015-05-05 09:51:38 -0700257#endif