1 /* 2 * Copyright 2013 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 #include "GrGLVertexArray.h" 9 #include "GrGLBuffer.h" 10 #include "GrGLGpu.h" 11 12 struct AttribLayout { 13 bool fNormalized; // Only used by floating point types. 14 uint8_t fCount; 15 uint16_t fType; 16 }; 17 18 GR_STATIC_ASSERT(4 == sizeof(AttribLayout)); 19 20 static AttribLayout attrib_layout(GrVertexAttribType type) { 21 switch (type) { 22 case kFloat_GrVertexAttribType: 23 return {false, 1, GR_GL_FLOAT}; 24 case kVec2f_GrVertexAttribType: 25 return {false, 2, GR_GL_FLOAT}; 26 case kVec3f_GrVertexAttribType: 27 return {false, 3, GR_GL_FLOAT}; 28 case kVec4f_GrVertexAttribType: 29 return {false, 4, GR_GL_FLOAT}; 30 case kVec2i_GrVertexAttribType: 31 return {false, 2, GR_GL_INT}; 32 case kVec3i_GrVertexAttribType: 33 return {false, 3, GR_GL_INT}; 34 case kVec4i_GrVertexAttribType: 35 return {false, 4, GR_GL_INT}; 36 case kUByte_GrVertexAttribType: 37 return {true, 1, GR_GL_UNSIGNED_BYTE}; 38 case kVec4ub_GrVertexAttribType: 39 return {true, 4, GR_GL_UNSIGNED_BYTE}; 40 case kVec2us_GrVertexAttribType: 41 return {true, 2, GR_GL_UNSIGNED_SHORT}; 42 case kInt_GrVertexAttribType: 43 return {false, 1, GR_GL_INT}; 44 case kUint_GrVertexAttribType: 45 return {false, 1, GR_GL_UNSIGNED_INT}; 46 } 47 SkFAIL("Unknown vertex attrib type"); 48 return {false, 0, 0}; 49 }; 50 51 void GrGLAttribArrayState::set(GrGLGpu* gpu, 52 int index, 53 const GrBuffer* vertexBuffer, 54 GrVertexAttribType type, 55 GrGLsizei stride, 56 GrGLvoid* offset) { 57 SkASSERT(index >= 0 && index < fAttribArrayStates.count()); 58 AttribArrayState* array = &fAttribArrayStates[index]; 59 if (!array->fEnableIsValid || !array->fEnabled) { 60 GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(index)); 61 array->fEnableIsValid = true; 62 array->fEnabled = true; 63 } 64 if (array->fVertexBufferUniqueID != vertexBuffer->uniqueID() || 65 array->fType != type || 66 array->fStride != stride || 67 array->fOffset != offset) { 68 gpu->bindBuffer(kVertex_GrBufferType, vertexBuffer); 69 const AttribLayout& layout = attrib_layout(type); 70 if (!GrVertexAttribTypeIsIntType(type)) { 71 GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index, 72 layout.fCount, 73 layout.fType, 74 layout.fNormalized, 75 stride, 76 offset)); 77 } else { 78 SkASSERT(gpu->caps()->shaderCaps()->integerSupport()); 79 SkASSERT(!layout.fNormalized); 80 GR_GL_CALL(gpu->glInterface(), VertexAttribIPointer(index, 81 layout.fCount, 82 layout.fType, 83 stride, 84 offset)); 85 } 86 array->fVertexBufferUniqueID = vertexBuffer->uniqueID(); 87 array->fType = type; 88 array->fStride = stride; 89 array->fOffset = offset; 90 } 91 } 92 93 void GrGLAttribArrayState::disableUnusedArrays(const GrGLGpu* gpu, uint64_t usedMask) { 94 int count = fAttribArrayStates.count(); 95 for (int i = 0; i < count; ++i) { 96 if (!(usedMask & 0x1)) { 97 if (!fAttribArrayStates[i].fEnableIsValid || fAttribArrayStates[i].fEnabled) { 98 GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i)); 99 fAttribArrayStates[i].fEnableIsValid = true; 100 fAttribArrayStates[i].fEnabled = false; 101 } 102 } else { 103 SkASSERT(fAttribArrayStates[i].fEnableIsValid && fAttribArrayStates[i].fEnabled); 104 } 105 // if the count is greater than 64 then this will become 0 and we will disable arrays 64+. 106 usedMask >>= 1; 107 } 108 } 109 110 /////////////////////////////////////////////////////////////////////////////////////////////////// 111 112 GrGLVertexArray::GrGLVertexArray(GrGLint id, int attribCount) 113 : fID(id) 114 , fAttribArrays(attribCount) 115 , fIndexBufferUniqueID(SK_InvalidUniqueID) { 116 } 117 118 GrGLAttribArrayState* GrGLVertexArray::bind(GrGLGpu* gpu) { 119 if (0 == fID) { 120 return nullptr; 121 } 122 gpu->bindVertexArray(fID); 123 return &fAttribArrays; 124 } 125 126 GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(GrGLGpu* gpu, const GrBuffer* ibuff) { 127 GrGLAttribArrayState* state = this->bind(gpu); 128 if (state && fIndexBufferUniqueID != ibuff->uniqueID()) { 129 if (ibuff->isCPUBacked()) { 130 GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0)); 131 } else { 132 const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(ibuff); 133 GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 134 glBuffer->bufferID())); 135 } 136 fIndexBufferUniqueID = ibuff->uniqueID(); 137 } 138 return state; 139 } 140 141 void GrGLVertexArray::invalidateCachedState() { 142 fAttribArrays.invalidate(); 143 fIndexBufferUniqueID.makeInvalid(); 144 } 145