• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "GrGpuBuffer.h"
14 
15 class GrPrimitiveProcessor;
16 
17 /**
18  * Used to communicate index and vertex buffers, counts, and offsets for a draw from GrOp to
19  * 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  */
23 class GrMesh {
24 public:
25     GrMesh(GrPrimitiveType primitiveType = GrPrimitiveType::kTriangles)
fPrimitiveType(primitiveType)26             : fPrimitiveType(primitiveType), fBaseVertex(0) {
27         SkDEBUGCODE(fNonIndexNonInstanceData.fVertexCount = -1;)
28     }
29 
setPrimitiveType(GrPrimitiveType type)30     void setPrimitiveType(GrPrimitiveType type) { fPrimitiveType = type; }
primitiveType()31     GrPrimitiveType primitiveType() const { return fPrimitiveType; }
32 
isIndexed()33     bool isIndexed() const { return SkToBool(fIndexBuffer.get()); }
primitiveRestart()34     GrPrimitiveRestart primitiveRestart() const {
35         return GrPrimitiveRestart(fFlags & Flags::kUsePrimitiveRestart);
36     }
isInstanced()37     bool isInstanced() const { return fFlags & Flags::kIsInstanced; }
hasInstanceData()38     bool hasInstanceData() const { return SkToBool(fInstanceBuffer.get()); }
hasVertexData()39     bool hasVertexData() const { return SkToBool(fVertexBuffer.get()); }
40 
41     void setNonIndexedNonInstanced(int vertexCount);
42 
43     void setIndexed(sk_sp<const GrBuffer> indexBuffer, int indexCount, int baseIndex,
44                     uint16_t minIndexValue, uint16_t maxIndexValue, GrPrimitiveRestart);
45     void setIndexedPatterned(sk_sp<const GrBuffer> indexBuffer, int indexCount, int vertexCount,
46                              int patternRepeatCount, int maxPatternRepetitionsInIndexBuffer);
47 
48     void setInstanced(sk_sp<const GrBuffer> instanceBuffer, int instanceCount, int baseInstance,
49                       int vertexCount);
50     void setIndexedInstanced(sk_sp<const GrBuffer> indexBuffer, int indexCount,
51                              sk_sp<const GrBuffer> instanceBuffer, int instanceCount,
52                              int baseInstance, GrPrimitiveRestart);
53 
54     void setVertexData(sk_sp<const GrBuffer> vertexBuffer, int baseVertex = 0);
55 
56     class SendToGpuImpl {
57     public:
58         virtual void sendMeshToGpu(GrPrimitiveType, const GrBuffer* vertexBuffer, int vertexCount,
59                                    int baseVertex) = 0;
60 
61         virtual void sendIndexedMeshToGpu(GrPrimitiveType, const GrBuffer* indexBuffer,
62                                           int indexCount, int baseIndex, uint16_t minIndexValue,
63                                           uint16_t maxIndexValue, const GrBuffer* vertexBuffer,
64                                           int baseVertex, GrPrimitiveRestart) = 0;
65 
66         virtual void sendInstancedMeshToGpu(GrPrimitiveType, const GrBuffer* vertexBuffer,
67                                             int vertexCount, int baseVertex,
68                                             const GrBuffer* instanceBuffer, int instanceCount,
69                                             int baseInstance) = 0;
70 
71         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;
77 
~SendToGpuImpl()78         virtual ~SendToGpuImpl() {}
79     };
80 
81     void sendToGpu(SendToGpuImpl*) const;
82 
83 private:
84     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 
94     GrPrimitiveType fPrimitiveType;
95     sk_sp<const GrBuffer> fIndexBuffer;
96     sk_sp<const GrBuffer> fInstanceBuffer;
97     sk_sp<const GrBuffer> fVertexBuffer;
98     int fBaseVertex;
99     Flags fFlags;
100 
101     union {
102         struct { // When fIndexBuffer == nullptr and isInstanced() == false.
103             int   fVertexCount;
104         } fNonIndexNonInstanceData;
105 
106         struct { // When fIndexBuffer != nullptr and isInstanced() == false.
107             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         };
125 
126         struct { // When isInstanced() != false.
127             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         };
142     };
143 };
144 
145 GR_MAKE_BITFIELD_CLASS_OPS(GrMesh::Flags);
146 
setNonIndexedNonInstanced(int vertexCount)147 inline void GrMesh::setNonIndexedNonInstanced(int vertexCount) {
148     fIndexBuffer.reset();
149     fInstanceBuffer.reset();
150     fNonIndexNonInstanceData.fVertexCount = vertexCount;
151     fFlags = Flags::kNone;
152 }
153 
setIndexed(sk_sp<const GrBuffer> indexBuffer,int indexCount,int baseIndex,uint16_t minIndexValue,uint16_t maxIndexValue,GrPrimitiveRestart primitiveRestart)154 inline void GrMesh::setIndexed(sk_sp<const GrBuffer> indexBuffer, int indexCount, int baseIndex,
155                                uint16_t minIndexValue, uint16_t maxIndexValue,
156                                GrPrimitiveRestart primitiveRestart) {
157     SkASSERT(indexBuffer);
158     SkASSERT(indexCount >= 1);
159     SkASSERT(baseIndex >= 0);
160     SkASSERT(maxIndexValue >= minIndexValue);
161     fIndexBuffer = std::move(indexBuffer);
162     fInstanceBuffer.reset();
163     fIndexData.fIndexCount = indexCount;
164     fIndexData.fPatternRepeatCount = 0;
165     fNonPatternIndexData.fBaseIndex = baseIndex;
166     fNonPatternIndexData.fMinIndexValue = minIndexValue;
167     fNonPatternIndexData.fMaxIndexValue = maxIndexValue;
168     fFlags = Flags(primitiveRestart);
169 }
170 
setIndexedPatterned(sk_sp<const GrBuffer> indexBuffer,int indexCount,int vertexCount,int patternRepeatCount,int maxPatternRepetitionsInIndexBuffer)171 inline void GrMesh::setIndexedPatterned(sk_sp<const GrBuffer> indexBuffer, int indexCount,
172                                         int vertexCount, int patternRepeatCount,
173                                         int maxPatternRepetitionsInIndexBuffer) {
174     SkASSERT(indexBuffer);
175     SkASSERT(indexCount >= 1);
176     SkASSERT(vertexCount >= 1);
177     SkASSERT(patternRepeatCount >= 1);
178     SkASSERT(maxPatternRepetitionsInIndexBuffer >= 1);
179     fIndexBuffer = std::move(indexBuffer);
180     fInstanceBuffer.reset();
181     fIndexData.fIndexCount = indexCount;
182     fIndexData.fPatternRepeatCount = patternRepeatCount;
183     fPatternData.fVertexCount = vertexCount;
184     fPatternData.fMaxPatternRepetitionsInIndexBuffer = maxPatternRepetitionsInIndexBuffer;
185     fFlags = Flags::kNone;
186 }
187 
setInstanced(sk_sp<const GrBuffer> instanceBuffer,int instanceCount,int baseInstance,int vertexCount)188 inline void GrMesh::setInstanced(sk_sp<const GrBuffer> instanceBuffer, int instanceCount,
189                                  int baseInstance, int vertexCount) {
190     SkASSERT(instanceCount >= 1);
191     SkASSERT(baseInstance >= 0);
192     fIndexBuffer.reset();
193     fInstanceBuffer = std::move(instanceBuffer);
194     fInstanceData.fInstanceCount = instanceCount;
195     fInstanceData.fBaseInstance = baseInstance;
196     fInstanceNonIndexData.fVertexCount = vertexCount;
197     fFlags = Flags::kIsInstanced;
198 }
199 
setIndexedInstanced(sk_sp<const GrBuffer> indexBuffer,int indexCount,sk_sp<const GrBuffer> instanceBuffer,int instanceCount,int baseInstance,GrPrimitiveRestart primitiveRestart)200 inline void GrMesh::setIndexedInstanced(sk_sp<const GrBuffer> indexBuffer, int indexCount,
201                                         sk_sp<const GrBuffer> instanceBuffer, int instanceCount,
202                                         int baseInstance, GrPrimitiveRestart primitiveRestart) {
203     SkASSERT(indexBuffer);
204     SkASSERT(indexCount >= 1);
205     SkASSERT(instanceCount >= 1);
206     SkASSERT(baseInstance >= 0);
207     fIndexBuffer = std::move(indexBuffer);
208     fInstanceBuffer = std::move(instanceBuffer);
209     fInstanceData.fInstanceCount = instanceCount;
210     fInstanceData.fBaseInstance = baseInstance;
211     fInstanceIndexData.fIndexCount = indexCount;
212     fFlags = Flags::kIsInstanced | Flags(primitiveRestart);
213 }
214 
setVertexData(sk_sp<const GrBuffer> vertexBuffer,int baseVertex)215 inline void GrMesh::setVertexData(sk_sp<const GrBuffer> vertexBuffer, int baseVertex) {
216     SkASSERT(baseVertex >= 0);
217     fVertexBuffer = std::move(vertexBuffer);
218     fBaseVertex = baseVertex;
219 }
220 
sendToGpu(SendToGpuImpl * impl)221 inline void GrMesh::sendToGpu(SendToGpuImpl* impl) const {
222     if (this->isInstanced()) {
223         if (!this->isIndexed()) {
224             impl->sendInstancedMeshToGpu(fPrimitiveType, fVertexBuffer.get(),
225                                          fInstanceNonIndexData.fVertexCount, fBaseVertex,
226                                          fInstanceBuffer.get(), fInstanceData.fInstanceCount,
227                                          fInstanceData.fBaseInstance);
228         } else {
229             impl->sendIndexedInstancedMeshToGpu(
230                     fPrimitiveType, fIndexBuffer.get(), fInstanceIndexData.fIndexCount, 0,
231                     fVertexBuffer.get(), fBaseVertex, fInstanceBuffer.get(),
232                     fInstanceData.fInstanceCount, fInstanceData.fBaseInstance,
233                     this->primitiveRestart());
234         }
235         return;
236     }
237 
238     if (!this->isIndexed()) {
239         SkASSERT(fNonIndexNonInstanceData.fVertexCount > 0);
240         impl->sendMeshToGpu(fPrimitiveType, fVertexBuffer.get(),
241                             fNonIndexNonInstanceData.fVertexCount, fBaseVertex);
242         return;
243     }
244 
245     if (0 == fIndexData.fPatternRepeatCount) {
246         impl->sendIndexedMeshToGpu(
247                 fPrimitiveType, fIndexBuffer.get(), fIndexData.fIndexCount,
248                 fNonPatternIndexData.fBaseIndex, fNonPatternIndexData.fMinIndexValue,
249                 fNonPatternIndexData.fMaxIndexValue, fVertexBuffer.get(), fBaseVertex,
250                 this->primitiveRestart());
251         return;
252     }
253 
254     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;
262         SkASSERT(!(fFlags & Flags::kUsePrimitiveRestart));
263         impl->sendIndexedMeshToGpu(
264                 fPrimitiveType, fIndexBuffer.get(), fIndexData.fIndexCount * repeatCount, 0,
265                 minIndexValue, maxIndexValue, fVertexBuffer.get(),
266                 fBaseVertex + fPatternData.fVertexCount * baseRepetition, GrPrimitiveRestart::kNo);
267         baseRepetition += repeatCount;
268     } while (baseRepetition < fIndexData.fPatternRepeatCount);
269 }
270 
271 #endif
272