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 "GrGpuResourceRef.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: 24 GrMesh(GrPrimitiveType primitiveType) 25 : fPrimitiveType(primitiveType) 26 , fBaseVertex(0) { 27 SkDEBUGCODE(fNonIndexNonInstanceData.fVertexCount = -1;) 28 } 29 30 GrPrimitiveType primitiveType() const { return fPrimitiveType; } 31 bool isIndexed() const { return SkToBool(fIndexBuffer.get()); } 32 bool isInstanced() const { return SkToBool(fInstanceBuffer.get()); } 33 bool hasVertexData() const { return SkToBool(fVertexBuffer.get()); } 34 35 void setNonIndexedNonInstanced(int vertexCount); 36 37 void setIndexed(const GrBuffer* indexBuffer, int indexCount, int baseIndex, 38 uint16_t minIndexValue, uint16_t maxIndexValue); 39 void setIndexedPatterned(const GrBuffer* indexBuffer, int indexCount, int vertexCount, 40 int patternRepeatCount, int maxPatternRepetitionsInIndexBuffer); 41 42 void setInstanced(const GrBuffer* instanceBuffer, int instanceCount, int baseInstance, 43 int vertexCount); 44 void setIndexedInstanced(const GrBuffer* indexBuffer, int indexCount, 45 const GrBuffer* instanceBuffer, int instanceCount, int baseInstance=0); 46 47 void setVertexData(const GrBuffer* vertexBuffer, int baseVertex = 0); 48 49 class SendToGpuImpl { 50 public: 51 virtual void sendMeshToGpu(const GrPrimitiveProcessor&, GrPrimitiveType, 52 const GrBuffer* vertexBuffer, int vertexCount, 53 int baseVertex) = 0; 54 55 virtual void sendIndexedMeshToGpu(const GrPrimitiveProcessor&, GrPrimitiveType, 56 const GrBuffer* indexBuffer, int indexCount, 57 int baseIndex, uint16_t minIndexValue, 58 uint16_t maxIndexValue, const GrBuffer* vertexBuffer, 59 int baseVertex) = 0; 60 61 virtual void sendInstancedMeshToGpu(const GrPrimitiveProcessor&, GrPrimitiveType, 62 const GrBuffer* vertexBuffer, int vertexCount, 63 int baseVertex, const GrBuffer* instanceBuffer, 64 int instanceCount, int baseInstance) = 0; 65 66 virtual void sendIndexedInstancedMeshToGpu(const GrPrimitiveProcessor&, GrPrimitiveType, 67 const GrBuffer* indexBuffer, int indexCount, 68 int baseIndex, const GrBuffer* vertexBuffer, 69 int baseVertex, const GrBuffer* instanceBuffer, 70 int instanceCount, int baseInstance) = 0; 71 72 virtual ~SendToGpuImpl() {} 73 }; 74 75 void sendToGpu(const GrPrimitiveProcessor&, SendToGpuImpl*) const; 76 77 struct PatternBatch; 78 79 private: 80 using PendingBuffer = GrPendingIOResource<const GrBuffer, kRead_GrIOType>; 81 82 GrPrimitiveType fPrimitiveType; 83 PendingBuffer fIndexBuffer; 84 PendingBuffer fInstanceBuffer; 85 PendingBuffer fVertexBuffer; 86 int fBaseVertex; 87 88 union { 89 struct { // When fIndexBuffer == nullptr and fInstanceBuffer == nullptr. 90 int fVertexCount; 91 } fNonIndexNonInstanceData; 92 93 struct { // When fIndexBuffer != nullptr and fInstanceBuffer == nullptr. 94 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 }; 112 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 }; 129 }; 130 }; 131 132 inline void GrMesh::setNonIndexedNonInstanced(int vertexCount) { 133 fIndexBuffer.reset(nullptr); 134 fInstanceBuffer.reset(nullptr); 135 fNonIndexNonInstanceData.fVertexCount = vertexCount; 136 } 137 138 inline void GrMesh::setIndexed(const GrBuffer* indexBuffer, int indexCount, int baseIndex, 139 uint16_t minIndexValue, uint16_t maxIndexValue) { 140 SkASSERT(indexBuffer); 141 SkASSERT(indexCount >= 1); 142 SkASSERT(baseIndex >= 0); 143 SkASSERT(maxIndexValue >= minIndexValue); 144 fIndexBuffer.reset(indexBuffer); 145 fInstanceBuffer.reset(nullptr); 146 fIndexData.fIndexCount = indexCount; 147 fIndexData.fPatternRepeatCount = 0; 148 fNonPatternIndexData.fBaseIndex = baseIndex; 149 fNonPatternIndexData.fMinIndexValue = minIndexValue; 150 fNonPatternIndexData.fMaxIndexValue = maxIndexValue; 151 } 152 153 inline void GrMesh::setIndexedPatterned(const GrBuffer* indexBuffer, int indexCount, 154 int vertexCount, int patternRepeatCount, 155 int maxPatternRepetitionsInIndexBuffer) { 156 SkASSERT(indexBuffer); 157 SkASSERT(indexCount >= 1); 158 SkASSERT(vertexCount >= 1); 159 SkASSERT(patternRepeatCount >= 1); 160 SkASSERT(maxPatternRepetitionsInIndexBuffer >= 1); 161 fIndexBuffer.reset(indexBuffer); 162 fInstanceBuffer.reset(nullptr); 163 fIndexData.fIndexCount = indexCount; 164 fIndexData.fPatternRepeatCount = patternRepeatCount; 165 fPatternData.fVertexCount = vertexCount; 166 fPatternData.fMaxPatternRepetitionsInIndexBuffer = maxPatternRepetitionsInIndexBuffer; 167 } 168 169 inline void GrMesh::setInstanced(const GrBuffer* instanceBuffer, int instanceCount, 170 int baseInstance, int vertexCount) { 171 SkASSERT(instanceBuffer); 172 SkASSERT(instanceCount >= 1); 173 SkASSERT(baseInstance >= 0); 174 fIndexBuffer.reset(nullptr); 175 fInstanceBuffer.reset(instanceBuffer); 176 fInstanceData.fInstanceCount = instanceCount; 177 fInstanceData.fBaseInstance = baseInstance; 178 fInstanceNonIndexData.fVertexCount = vertexCount; 179 } 180 181 inline void GrMesh::setIndexedInstanced(const GrBuffer* indexBuffer, int indexCount, 182 const GrBuffer* instanceBuffer, int instanceCount, 183 int baseInstance) { 184 SkASSERT(indexBuffer); 185 SkASSERT(indexCount >= 1); 186 SkASSERT(instanceBuffer); 187 SkASSERT(instanceCount >= 1); 188 SkASSERT(baseInstance >= 0); 189 fIndexBuffer.reset(indexBuffer); 190 fInstanceBuffer.reset(instanceBuffer); 191 fInstanceData.fInstanceCount = instanceCount; 192 fInstanceData.fBaseInstance = baseInstance; 193 fInstanceIndexData.fIndexCount = indexCount; 194 } 195 196 inline void GrMesh::setVertexData(const GrBuffer* vertexBuffer, int baseVertex) { 197 SkASSERT(baseVertex >= 0); 198 fVertexBuffer.reset(vertexBuffer); 199 fBaseVertex = baseVertex; 200 } 201 202 inline void GrMesh::sendToGpu(const GrPrimitiveProcessor& primProc, SendToGpuImpl* impl) const { 203 if (this->isInstanced()) { 204 if (!this->isIndexed()) { 205 impl->sendInstancedMeshToGpu(primProc, fPrimitiveType, fVertexBuffer.get(), 206 fInstanceNonIndexData.fVertexCount, fBaseVertex, 207 fInstanceBuffer.get(), fInstanceData.fInstanceCount, 208 fInstanceData.fBaseInstance); 209 } else { 210 impl->sendIndexedInstancedMeshToGpu(primProc, fPrimitiveType, fIndexBuffer.get(), 211 fInstanceIndexData.fIndexCount, 0, 212 fVertexBuffer.get(), fBaseVertex, 213 fInstanceBuffer.get(), fInstanceData.fInstanceCount, 214 fInstanceData.fBaseInstance); 215 } 216 return; 217 } 218 219 if (!this->isIndexed()) { 220 SkASSERT(fNonIndexNonInstanceData.fVertexCount > 0); 221 impl->sendMeshToGpu(primProc, fPrimitiveType, fVertexBuffer.get(), 222 fNonIndexNonInstanceData.fVertexCount, fBaseVertex); 223 return; 224 } 225 226 if (0 == fIndexData.fPatternRepeatCount) { 227 impl->sendIndexedMeshToGpu(primProc, fPrimitiveType, fIndexBuffer.get(), 228 fIndexData.fIndexCount, fNonPatternIndexData.fBaseIndex, 229 fNonPatternIndexData.fMinIndexValue, 230 fNonPatternIndexData.fMaxIndexValue, fVertexBuffer.get(), 231 fBaseVertex); 232 return; 233 } 234 235 SkASSERT(fIndexData.fPatternRepeatCount > 0); 236 int baseRepetition = 0; 237 do { 238 int repeatCount = SkTMin(fPatternData.fMaxPatternRepetitionsInIndexBuffer, 239 fIndexData.fPatternRepeatCount - baseRepetition); 240 // A patterned index buffer must contain indices in the range [0..vertexCount]. 241 int minIndexValue = 0; 242 int maxIndexValue = fPatternData.fVertexCount * repeatCount - 1; 243 impl->sendIndexedMeshToGpu(primProc, fPrimitiveType, fIndexBuffer.get(), 244 fIndexData.fIndexCount * repeatCount, 0, minIndexValue, 245 maxIndexValue, fVertexBuffer.get(), 246 fBaseVertex + fPatternData.fVertexCount * baseRepetition); 247 baseRepetition += repeatCount; 248 } while (baseRepetition < fIndexData.fPatternRepeatCount); 249 } 250 251 #endif 252