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