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