blob: 5cfc5fbd3292e874e6c6da489757dc7af095a3ad [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"
Brian Salomondbf70722019-02-07 11:31:24 -050013#include "GrGpuBuffer.h"
bsalomoncb8979d2015-05-05 09:51:38 -070014
Chris Dalton114a3c02017-05-26 15:17:19 -060015class GrPrimitiveProcessor;
16
bsalomoncb8979d2015-05-05 09:51:38 -070017/**
Brian Salomon25a88092016-12-01 09:36:50 -050018 * Used to communicate index and vertex buffers, counts, and offsets for a draw from GrOp to
bsalomoncb8979d2015-05-05 09:51:38 -070019 * GrGpu. It also holds the primitive type for the draw. TODO: Consider moving ownership of this
20 * and draw-issuing responsibility to GrPrimitiveProcessor. The rest of the vertex info lives there
21 * already (stride, attribute mappings).
22 */
Chris Daltonbca46e22017-05-15 11:03:26 -060023class GrMesh {
24public:
Brian Salomon7eae3e02018-08-07 14:02:38 +000025 GrMesh(GrPrimitiveType primitiveType = GrPrimitiveType::kTriangles)
26 : fPrimitiveType(primitiveType), fBaseVertex(0) {
Chris Dalton1d616352017-05-31 12:51:23 -060027 SkDEBUGCODE(fNonIndexNonInstanceData.fVertexCount = -1;)
Chris Daltonbca46e22017-05-15 11:03:26 -060028 }
29
Brian Salomon7eae3e02018-08-07 14:02:38 +000030 void setPrimitiveType(GrPrimitiveType type) { fPrimitiveType = type; }
Chris Dalton114a3c02017-05-26 15:17:19 -060031 GrPrimitiveType primitiveType() const { return fPrimitiveType; }
Brian Salomon802cb312018-06-08 18:05:20 -040032
Chris Dalton114a3c02017-05-26 15:17:19 -060033 bool isIndexed() const { return SkToBool(fIndexBuffer.get()); }
Chris Dalton906430d2019-02-27 18:16:59 -070034 GrPrimitiveRestart primitiveRestart() const {
35 return GrPrimitiveRestart(fFlags & Flags::kUsePrimitiveRestart);
36 }
37 bool isInstanced() const { return fFlags & Flags::kIsInstanced; }
38 bool hasInstanceData() const { return SkToBool(fInstanceBuffer.get()); }
Chris Dalton114a3c02017-05-26 15:17:19 -060039 bool hasVertexData() const { return SkToBool(fVertexBuffer.get()); }
40
Chris Dalton1d616352017-05-31 12:51:23 -060041 void setNonIndexedNonInstanced(int vertexCount);
42
Brian Salomon12d22642019-01-29 14:38:50 -050043 void setIndexed(sk_sp<const GrBuffer> indexBuffer, int indexCount, int baseIndex,
Brian Salomon802cb312018-06-08 18:05:20 -040044 uint16_t minIndexValue, uint16_t maxIndexValue, GrPrimitiveRestart);
Brian Salomon12d22642019-01-29 14:38:50 -050045 void setIndexedPatterned(sk_sp<const GrBuffer> indexBuffer, int indexCount, int vertexCount,
Chris Daltonbca46e22017-05-15 11:03:26 -060046 int patternRepeatCount, int maxPatternRepetitionsInIndexBuffer);
47
Brian Salomon12d22642019-01-29 14:38:50 -050048 void setInstanced(sk_sp<const GrBuffer> instanceBuffer, int instanceCount, int baseInstance,
Chris Dalton1d616352017-05-31 12:51:23 -060049 int vertexCount);
Brian Salomondbf70722019-02-07 11:31:24 -050050 void setIndexedInstanced(sk_sp<const GrBuffer> indexBuffer, int indexCount,
51 sk_sp<const GrBuffer> instanceBuffer, int instanceCount,
52 int baseInstance, GrPrimitiveRestart);
Chris Dalton1d616352017-05-31 12:51:23 -060053
Brian Salomon12d22642019-01-29 14:38:50 -050054 void setVertexData(sk_sp<const GrBuffer> vertexBuffer, int baseVertex = 0);
Chris Daltonbca46e22017-05-15 11:03:26 -060055
Chris Dalton114a3c02017-05-26 15:17:19 -060056 class SendToGpuImpl {
57 public:
Brian Salomon802cb312018-06-08 18:05:20 -040058 virtual void sendMeshToGpu(GrPrimitiveType, const GrBuffer* vertexBuffer, int vertexCount,
Chris Dalton114a3c02017-05-26 15:17:19 -060059 int baseVertex) = 0;
Chris Daltonbca46e22017-05-15 11:03:26 -060060
Brian Salomon802cb312018-06-08 18:05:20 -040061 virtual void sendIndexedMeshToGpu(GrPrimitiveType, const GrBuffer* indexBuffer,
62 int indexCount, int baseIndex, uint16_t minIndexValue,
Chris Dalton114a3c02017-05-26 15:17:19 -060063 uint16_t maxIndexValue, const GrBuffer* vertexBuffer,
Brian Salomon802cb312018-06-08 18:05:20 -040064 int baseVertex, GrPrimitiveRestart) = 0;
Chris Daltonbca46e22017-05-15 11:03:26 -060065
Brian Salomon802cb312018-06-08 18:05:20 -040066 virtual void sendInstancedMeshToGpu(GrPrimitiveType, const GrBuffer* vertexBuffer,
67 int vertexCount, int baseVertex,
68 const GrBuffer* instanceBuffer, int instanceCount,
69 int baseInstance) = 0;
Chris Dalton1d616352017-05-31 12:51:23 -060070
Brian Salomon802cb312018-06-08 18:05:20 -040071 virtual void sendIndexedInstancedMeshToGpu(GrPrimitiveType, const GrBuffer* indexBuffer,
72 int indexCount, int baseIndex,
73 const GrBuffer* vertexBuffer, int baseVertex,
74 const GrBuffer* instanceBuffer,
75 int instanceCount, int baseInstance,
76 GrPrimitiveRestart) = 0;
Chris Dalton1d616352017-05-31 12:51:23 -060077
Chris Dalton114a3c02017-05-26 15:17:19 -060078 virtual ~SendToGpuImpl() {}
79 };
80
Brian Salomon802cb312018-06-08 18:05:20 -040081 void sendToGpu(SendToGpuImpl*) const;
Chris Daltonbca46e22017-05-15 11:03:26 -060082
Chris Daltonbca46e22017-05-15 11:03:26 -060083private:
Chris Dalton906430d2019-02-27 18:16:59 -070084 enum class Flags {
85 kNone = 0,
86 kUsePrimitiveRestart = 1 << 0,
87 kIsInstanced = 1 << 1,
88 };
89
90 GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(Flags);
91 GR_STATIC_ASSERT(Flags(GrPrimitiveRestart::kNo) == Flags::kNone);
92 GR_STATIC_ASSERT(Flags(GrPrimitiveRestart::kYes) == Flags::kUsePrimitiveRestart);
93
Brian Salomon802cb312018-06-08 18:05:20 -040094 GrPrimitiveType fPrimitiveType;
Brian Salomon924a10e2019-02-01 12:15:18 -050095 sk_sp<const GrBuffer> fIndexBuffer;
96 sk_sp<const GrBuffer> fInstanceBuffer;
97 sk_sp<const GrBuffer> fVertexBuffer;
Brian Salomon802cb312018-06-08 18:05:20 -040098 int fBaseVertex;
Chris Dalton906430d2019-02-27 18:16:59 -070099 Flags fFlags;
Chris Daltonff926502017-05-03 14:36:54 -0400100
Chris Dalton114a3c02017-05-26 15:17:19 -0600101 union {
Chris Dalton906430d2019-02-27 18:16:59 -0700102 struct { // When fIndexBuffer == nullptr and isInstanced() == false.
Chris Dalton114a3c02017-05-26 15:17:19 -0600103 int fVertexCount;
Chris Dalton1d616352017-05-31 12:51:23 -0600104 } fNonIndexNonInstanceData;
Chris Dalton114a3c02017-05-26 15:17:19 -0600105
Chris Dalton906430d2019-02-27 18:16:59 -0700106 struct { // When fIndexBuffer != nullptr and isInstanced() == false.
Chris Dalton114a3c02017-05-26 15:17:19 -0600107 struct {
108 int fIndexCount;
109 int fPatternRepeatCount;
110 } fIndexData;
111
112 union {
113 struct { // When fPatternRepeatCount == 0.
114 int fBaseIndex;
115 uint16_t fMinIndexValue;
116 uint16_t fMaxIndexValue;
117 } fNonPatternIndexData;
118
119 struct { // When fPatternRepeatCount != 0.
120 int fVertexCount;
121 int fMaxPatternRepetitionsInIndexBuffer;
122 } fPatternData;
123 };
124 };
Chris Dalton1d616352017-05-31 12:51:23 -0600125
Chris Dalton906430d2019-02-27 18:16:59 -0700126 struct { // When isInstanced() != false.
Chris Dalton1d616352017-05-31 12:51:23 -0600127 struct {
128 int fInstanceCount;
129 int fBaseInstance;
130 } fInstanceData;
131
132 union { // When fIndexBuffer == nullptr.
133 struct {
134 int fVertexCount;
135 } fInstanceNonIndexData;
136
137 struct { // When fIndexBuffer != nullptr.
138 int fIndexCount;
139 } fInstanceIndexData;
140 };
141 };
Chris Dalton114a3c02017-05-26 15:17:19 -0600142 };
Chris Daltonff926502017-05-03 14:36:54 -0400143};
144
Chris Dalton906430d2019-02-27 18:16:59 -0700145GR_MAKE_BITFIELD_CLASS_OPS(GrMesh::Flags);
146
Chris Dalton1d616352017-05-31 12:51:23 -0600147inline void GrMesh::setNonIndexedNonInstanced(int vertexCount) {
Brian Salomondbf70722019-02-07 11:31:24 -0500148 fIndexBuffer.reset();
149 fInstanceBuffer.reset();
Chris Dalton1d616352017-05-31 12:51:23 -0600150 fNonIndexNonInstanceData.fVertexCount = vertexCount;
Chris Dalton906430d2019-02-27 18:16:59 -0700151 fFlags = Flags::kNone;
Chris Daltonbca46e22017-05-15 11:03:26 -0600152}
153
Brian Salomon12d22642019-01-29 14:38:50 -0500154inline void GrMesh::setIndexed(sk_sp<const GrBuffer> indexBuffer, int indexCount, int baseIndex,
Brian Salomon802cb312018-06-08 18:05:20 -0400155 uint16_t minIndexValue, uint16_t maxIndexValue,
156 GrPrimitiveRestart primitiveRestart) {
Chris Daltonbca46e22017-05-15 11:03:26 -0600157 SkASSERT(indexBuffer);
158 SkASSERT(indexCount >= 1);
159 SkASSERT(baseIndex >= 0);
Chris Daltona88da482017-06-06 12:25:28 -0600160 SkASSERT(maxIndexValue >= minIndexValue);
Brian Salomon12d22642019-01-29 14:38:50 -0500161 fIndexBuffer = std::move(indexBuffer);
162 fInstanceBuffer.reset();
Chris Dalton114a3c02017-05-26 15:17:19 -0600163 fIndexData.fIndexCount = indexCount;
164 fIndexData.fPatternRepeatCount = 0;
165 fNonPatternIndexData.fBaseIndex = baseIndex;
166 fNonPatternIndexData.fMinIndexValue = minIndexValue;
167 fNonPatternIndexData.fMaxIndexValue = maxIndexValue;
Chris Dalton906430d2019-02-27 18:16:59 -0700168 fFlags = Flags(primitiveRestart);
Chris Daltonbca46e22017-05-15 11:03:26 -0600169}
170
Brian Salomon12d22642019-01-29 14:38:50 -0500171inline void GrMesh::setIndexedPatterned(sk_sp<const GrBuffer> indexBuffer, int indexCount,
Chris Dalton114a3c02017-05-26 15:17:19 -0600172 int vertexCount, int patternRepeatCount,
Chris Daltonbca46e22017-05-15 11:03:26 -0600173 int maxPatternRepetitionsInIndexBuffer) {
174 SkASSERT(indexBuffer);
175 SkASSERT(indexCount >= 1);
Chris Dalton114a3c02017-05-26 15:17:19 -0600176 SkASSERT(vertexCount >= 1);
Chris Daltonbca46e22017-05-15 11:03:26 -0600177 SkASSERT(patternRepeatCount >= 1);
178 SkASSERT(maxPatternRepetitionsInIndexBuffer >= 1);
Brian Salomon12d22642019-01-29 14:38:50 -0500179 fIndexBuffer = std::move(indexBuffer);
180 fInstanceBuffer.reset();
Chris Dalton114a3c02017-05-26 15:17:19 -0600181 fIndexData.fIndexCount = indexCount;
182 fIndexData.fPatternRepeatCount = patternRepeatCount;
183 fPatternData.fVertexCount = vertexCount;
184 fPatternData.fMaxPatternRepetitionsInIndexBuffer = maxPatternRepetitionsInIndexBuffer;
Chris Dalton906430d2019-02-27 18:16:59 -0700185 fFlags = Flags::kNone;
Chris Daltonbca46e22017-05-15 11:03:26 -0600186}
187
Brian Salomon12d22642019-01-29 14:38:50 -0500188inline void GrMesh::setInstanced(sk_sp<const GrBuffer> instanceBuffer, int instanceCount,
Chris Dalton1d616352017-05-31 12:51:23 -0600189 int baseInstance, int vertexCount) {
Chris Dalton1d616352017-05-31 12:51:23 -0600190 SkASSERT(instanceCount >= 1);
191 SkASSERT(baseInstance >= 0);
Brian Salomon12d22642019-01-29 14:38:50 -0500192 fIndexBuffer.reset();
193 fInstanceBuffer = std::move(instanceBuffer);
Chris Dalton1d616352017-05-31 12:51:23 -0600194 fInstanceData.fInstanceCount = instanceCount;
195 fInstanceData.fBaseInstance = baseInstance;
196 fInstanceNonIndexData.fVertexCount = vertexCount;
Chris Dalton906430d2019-02-27 18:16:59 -0700197 fFlags = Flags::kIsInstanced;
Chris Dalton1d616352017-05-31 12:51:23 -0600198}
199
Brian Salomon12d22642019-01-29 14:38:50 -0500200inline void GrMesh::setIndexedInstanced(sk_sp<const GrBuffer> indexBuffer, int indexCount,
201 sk_sp<const GrBuffer> instanceBuffer, int instanceCount,
Brian Salomon802cb312018-06-08 18:05:20 -0400202 int baseInstance, GrPrimitiveRestart primitiveRestart) {
Chris Dalton1d616352017-05-31 12:51:23 -0600203 SkASSERT(indexBuffer);
204 SkASSERT(indexCount >= 1);
Chris Dalton1d616352017-05-31 12:51:23 -0600205 SkASSERT(instanceCount >= 1);
206 SkASSERT(baseInstance >= 0);
Brian Salomon12d22642019-01-29 14:38:50 -0500207 fIndexBuffer = std::move(indexBuffer);
208 fInstanceBuffer = std::move(instanceBuffer);
Chris Dalton1d616352017-05-31 12:51:23 -0600209 fInstanceData.fInstanceCount = instanceCount;
210 fInstanceData.fBaseInstance = baseInstance;
211 fInstanceIndexData.fIndexCount = indexCount;
Chris Dalton906430d2019-02-27 18:16:59 -0700212 fFlags = Flags::kIsInstanced | Flags(primitiveRestart);
Chris Dalton1d616352017-05-31 12:51:23 -0600213}
214
Brian Salomon12d22642019-01-29 14:38:50 -0500215inline void GrMesh::setVertexData(sk_sp<const GrBuffer> vertexBuffer, int baseVertex) {
Chris Dalton114a3c02017-05-26 15:17:19 -0600216 SkASSERT(baseVertex >= 0);
Brian Salomon12d22642019-01-29 14:38:50 -0500217 fVertexBuffer = std::move(vertexBuffer);
Chris Daltonbca46e22017-05-15 11:03:26 -0600218 fBaseVertex = baseVertex;
219}
220
Brian Salomon802cb312018-06-08 18:05:20 -0400221inline void GrMesh::sendToGpu(SendToGpuImpl* impl) const {
Chris Dalton1d616352017-05-31 12:51:23 -0600222 if (this->isInstanced()) {
223 if (!this->isIndexed()) {
Brian Salomon802cb312018-06-08 18:05:20 -0400224 impl->sendInstancedMeshToGpu(fPrimitiveType, fVertexBuffer.get(),
Chris Dalton1d616352017-05-31 12:51:23 -0600225 fInstanceNonIndexData.fVertexCount, fBaseVertex,
226 fInstanceBuffer.get(), fInstanceData.fInstanceCount,
227 fInstanceData.fBaseInstance);
228 } else {
Brian Salomon802cb312018-06-08 18:05:20 -0400229 impl->sendIndexedInstancedMeshToGpu(
230 fPrimitiveType, fIndexBuffer.get(), fInstanceIndexData.fIndexCount, 0,
231 fVertexBuffer.get(), fBaseVertex, fInstanceBuffer.get(),
Chris Dalton906430d2019-02-27 18:16:59 -0700232 fInstanceData.fInstanceCount, fInstanceData.fBaseInstance,
233 this->primitiveRestart());
Chris Dalton1d616352017-05-31 12:51:23 -0600234 }
235 return;
236 }
237
Chris Dalton114a3c02017-05-26 15:17:19 -0600238 if (!this->isIndexed()) {
Chris Dalton1d616352017-05-31 12:51:23 -0600239 SkASSERT(fNonIndexNonInstanceData.fVertexCount > 0);
Brian Salomon802cb312018-06-08 18:05:20 -0400240 impl->sendMeshToGpu(fPrimitiveType, fVertexBuffer.get(),
Chris Dalton1d616352017-05-31 12:51:23 -0600241 fNonIndexNonInstanceData.fVertexCount, fBaseVertex);
Chris Dalton114a3c02017-05-26 15:17:19 -0600242 return;
bsalomoncb8979d2015-05-05 09:51:38 -0700243 }
244
Chris Dalton114a3c02017-05-26 15:17:19 -0600245 if (0 == fIndexData.fPatternRepeatCount) {
Chris Dalton906430d2019-02-27 18:16:59 -0700246 impl->sendIndexedMeshToGpu(
247 fPrimitiveType, fIndexBuffer.get(), fIndexData.fIndexCount,
248 fNonPatternIndexData.fBaseIndex, fNonPatternIndexData.fMinIndexValue,
249 fNonPatternIndexData.fMaxIndexValue, fVertexBuffer.get(), fBaseVertex,
250 this->primitiveRestart());
Chris Dalton114a3c02017-05-26 15:17:19 -0600251 return;
bsalomoncb8979d2015-05-05 09:51:38 -0700252 }
253
Chris Dalton114a3c02017-05-26 15:17:19 -0600254 SkASSERT(fIndexData.fPatternRepeatCount > 0);
255 int baseRepetition = 0;
256 do {
257 int repeatCount = SkTMin(fPatternData.fMaxPatternRepetitionsInIndexBuffer,
258 fIndexData.fPatternRepeatCount - baseRepetition);
259 // A patterned index buffer must contain indices in the range [0..vertexCount].
260 int minIndexValue = 0;
261 int maxIndexValue = fPatternData.fVertexCount * repeatCount - 1;
Chris Dalton906430d2019-02-27 18:16:59 -0700262 SkASSERT(!(fFlags & Flags::kUsePrimitiveRestart));
Brian Salomon802cb312018-06-08 18:05:20 -0400263 impl->sendIndexedMeshToGpu(
264 fPrimitiveType, fIndexBuffer.get(), fIndexData.fIndexCount * repeatCount, 0,
265 minIndexValue, maxIndexValue, fVertexBuffer.get(),
266 fBaseVertex + fPatternData.fVertexCount * baseRepetition, GrPrimitiveRestart::kNo);
Chris Dalton114a3c02017-05-26 15:17:19 -0600267 baseRepetition += repeatCount;
268 } while (baseRepetition < fIndexData.fPatternRepeatCount);
Chris Daltonff926502017-05-03 14:36:54 -0400269}
270
bsalomoncb8979d2015-05-05 09:51:38 -0700271#endif