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 GrNonInstancedMesh { 15 public: primitiveType()16 GrPrimitiveType primitiveType() const { return fPrimitiveType; } startVertex()17 int startVertex() const { return fStartVertex; } startIndex()18 int startIndex() const { return fStartIndex; } vertexCount()19 int vertexCount() const { return fVertexCount; } indexCount()20 int indexCount() const { return fIndexCount; } isIndexed()21 bool isIndexed() const { return fIndexCount > 0; } 22 vertexBuffer()23 const GrBuffer* vertexBuffer() const { return fVertexBuffer.get(); } indexBuffer()24 const GrBuffer* indexBuffer() const { return fIndexBuffer.get(); } 25 26 protected: 27 GrPrimitiveType fPrimitiveType; 28 int fStartVertex; 29 int fStartIndex; 30 int fVertexCount; 31 int fIndexCount; 32 GrPendingIOResource<const GrBuffer, kRead_GrIOType> fVertexBuffer; 33 GrPendingIOResource<const GrBuffer, kRead_GrIOType> fIndexBuffer; 34 friend class GrMesh; 35 }; 36 37 /** 38 * Used to communicate index and vertex buffers, counts, and offsets for a draw from GrOp to 39 * GrGpu. It also holds the primitive type for the draw. TODO: Consider moving ownership of this 40 * and draw-issuing responsibility to GrPrimitiveProcessor. The rest of the vertex info lives there 41 * already (stride, attribute mappings). 42 */ 43 class GrMesh : public GrNonInstancedMesh { 44 public: GrMesh()45 GrMesh() {} GrMesh(const GrMesh & di)46 GrMesh(const GrMesh& di) { (*this) = di; } 47 GrMesh& operator =(const GrMesh& di); 48 init(GrPrimitiveType primType,const GrBuffer * vertexBuffer,int startVertex,int vertexCount)49 void init(GrPrimitiveType primType, const GrBuffer* vertexBuffer, int startVertex, 50 int vertexCount) { 51 SkASSERT(vertexBuffer); 52 SkASSERT(vertexCount); 53 SkASSERT(startVertex >= 0); 54 fPrimitiveType = primType; 55 fVertexBuffer.reset(vertexBuffer); 56 fIndexBuffer.reset(nullptr); 57 fStartVertex = startVertex; 58 fStartIndex = 0; 59 fVertexCount = vertexCount; 60 fIndexCount = 0; 61 fInstanceCount = 0; 62 fVerticesPerInstance = 0; 63 fIndicesPerInstance = 0; 64 fMaxInstancesPerDraw = 0; 65 } 66 initIndexed(GrPrimitiveType primType,const GrBuffer * vertexBuffer,const GrBuffer * indexBuffer,int startVertex,int startIndex,int vertexCount,int indexCount)67 void initIndexed(GrPrimitiveType primType, 68 const GrBuffer* vertexBuffer, 69 const GrBuffer* indexBuffer, 70 int startVertex, 71 int startIndex, 72 int vertexCount, 73 int indexCount) { 74 SkASSERT(indexBuffer); 75 SkASSERT(vertexBuffer); 76 SkASSERT(indexCount); 77 SkASSERT(vertexCount); 78 SkASSERT(startIndex >= 0); 79 SkASSERT(startVertex >= 0); 80 fPrimitiveType = primType; 81 fVertexBuffer.reset(vertexBuffer); 82 fIndexBuffer.reset(indexBuffer); 83 fStartVertex = startVertex; 84 fStartIndex = startIndex; 85 fVertexCount = vertexCount; 86 fIndexCount = indexCount; 87 fInstanceCount = 0; 88 fVerticesPerInstance = 0; 89 fIndicesPerInstance = 0; 90 fMaxInstancesPerDraw = 0; 91 } 92 93 94 /** Variation of the above that may be used when the total number of instances may exceed 95 the number of instances supported by the index buffer. To be used with 96 nextInstances() to draw in max-sized batches.*/ initInstanced(GrPrimitiveType primType,const GrBuffer * vertexBuffer,const GrBuffer * indexBuffer,int startVertex,int verticesPerInstance,int indicesPerInstance,int instanceCount,int maxInstancesPerDraw)97 void initInstanced(GrPrimitiveType primType, 98 const GrBuffer* vertexBuffer, 99 const GrBuffer* indexBuffer, 100 int startVertex, 101 int verticesPerInstance, 102 int indicesPerInstance, 103 int instanceCount, 104 int maxInstancesPerDraw) { 105 SkASSERT(vertexBuffer); 106 SkASSERT(indexBuffer); 107 SkASSERT(instanceCount); 108 SkASSERT(verticesPerInstance); 109 SkASSERT(indicesPerInstance); 110 SkASSERT(startVertex >= 0); 111 fPrimitiveType = primType; 112 fVertexBuffer.reset(vertexBuffer); 113 fIndexBuffer.reset(indexBuffer); 114 fStartVertex = startVertex; 115 fStartIndex = 0; 116 fVerticesPerInstance = verticesPerInstance; 117 fIndicesPerInstance = indicesPerInstance; 118 fInstanceCount = instanceCount; 119 fVertexCount = instanceCount * fVerticesPerInstance; 120 fIndexCount = instanceCount * fIndicesPerInstance; 121 fMaxInstancesPerDraw = maxInstancesPerDraw; 122 } 123 124 125 /** These return 0 if initInstanced was not used to initialize the GrVertices. */ verticesPerInstance()126 int verticesPerInstance() const { return fVerticesPerInstance; } indicesPerInstance()127 int indicesPerInstance() const { return fIndicesPerInstance; } instanceCount()128 int instanceCount() const { return fInstanceCount; } 129 isInstanced()130 bool isInstanced() const { return fInstanceCount > 0; } 131 132 class Iterator { 133 public: init(const GrMesh & mesh)134 const GrNonInstancedMesh* init(const GrMesh& mesh) { 135 fMesh = &mesh; 136 if (mesh.fInstanceCount <= mesh.fMaxInstancesPerDraw) { 137 fInstancesRemaining = 0; 138 // Note, this also covers the non-instanced case! 139 return &mesh; 140 } 141 SkASSERT(mesh.isInstanced()); 142 fInstanceBatch.fIndexBuffer.reset(mesh.fIndexBuffer.get()); 143 fInstanceBatch.fVertexBuffer.reset(mesh.fVertexBuffer.get()); 144 fInstanceBatch.fIndexCount = mesh.fMaxInstancesPerDraw * 145 mesh.fIndicesPerInstance; 146 fInstanceBatch.fVertexCount = mesh.fMaxInstancesPerDraw * 147 mesh.fVerticesPerInstance; 148 fInstanceBatch.fPrimitiveType = mesh.fPrimitiveType; 149 fInstanceBatch.fStartIndex = mesh.fStartIndex; 150 fInstanceBatch.fStartVertex = mesh.fStartVertex; 151 fInstancesRemaining = mesh.fInstanceCount - mesh.fMaxInstancesPerDraw; 152 return &fInstanceBatch; 153 } 154 next()155 const GrNonInstancedMesh* next() { 156 if (!fInstancesRemaining) { 157 return nullptr; 158 } 159 fInstanceBatch.fStartVertex += fInstanceBatch.fVertexCount; 160 int instances = SkTMin(fInstancesRemaining, fMesh->fMaxInstancesPerDraw); 161 fInstanceBatch.fIndexCount = instances * fMesh->fIndicesPerInstance; 162 fInstanceBatch.fVertexCount = instances * fMesh->fVerticesPerInstance; 163 fInstancesRemaining -= instances; 164 return &fInstanceBatch; 165 } 166 private: 167 GrNonInstancedMesh fInstanceBatch; 168 const GrMesh* fMesh; 169 int fInstancesRemaining; 170 }; 171 172 private: 173 int fInstanceCount; 174 int fVerticesPerInstance; 175 int fIndicesPerInstance; 176 int fMaxInstancesPerDraw; 177 }; 178 179 #endif 180