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