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 kFloat2_GrVertexAttribType: 25 return {false, 2, GR_GL_FLOAT}; 26 case kFloat3_GrVertexAttribType: 27 return {false, 3, GR_GL_FLOAT}; 28 case kFloat4_GrVertexAttribType: 29 return {false, 4, GR_GL_FLOAT}; 30 case kHalf_GrVertexAttribType: 31 return {false, 1, GR_GL_FLOAT}; 32 case kHalf2_GrVertexAttribType: 33 return {false, 2, GR_GL_FLOAT}; 34 case kHalf3_GrVertexAttribType: 35 return {false, 3, GR_GL_FLOAT}; 36 case kHalf4_GrVertexAttribType: 37 return {false, 4, GR_GL_FLOAT}; 38 case kInt2_GrVertexAttribType: 39 return {false, 2, GR_GL_INT}; 40 case kInt3_GrVertexAttribType: 41 return {false, 3, GR_GL_INT}; 42 case kInt4_GrVertexAttribType: 43 return {false, 4, GR_GL_INT}; 44 case kUByte_norm_GrVertexAttribType: 45 return {true, 1, GR_GL_UNSIGNED_BYTE}; 46 case kUByte4_norm_GrVertexAttribType: 47 return {true, 4, GR_GL_UNSIGNED_BYTE}; 48 case kShort2_GrVertexAttribType: 49 return {false, 2, GR_GL_SHORT}; 50 case kUShort2_GrVertexAttribType: 51 return {false, 2, GR_GL_UNSIGNED_SHORT}; 52 case kUShort2_norm_GrVertexAttribType: 53 return {true, 2, GR_GL_UNSIGNED_SHORT}; 54 case kInt_GrVertexAttribType: 55 return {false, 1, GR_GL_INT}; 56 case kUint_GrVertexAttribType: 57 return {false, 1, GR_GL_UNSIGNED_INT}; 58 } 59 SK_ABORT("Unknown vertex attrib type"); 60 return {false, 0, 0}; 61 }; 62 63 static bool GrVertexAttribTypeIsIntType(const GrShaderCaps* shaderCaps, 64 GrVertexAttribType type) { 65 switch (type) { 66 case kFloat_GrVertexAttribType: 67 return false; 68 case kFloat2_GrVertexAttribType: 69 return false; 70 case kFloat3_GrVertexAttribType: 71 return false; 72 case kFloat4_GrVertexAttribType: 73 return false; 74 case kHalf_GrVertexAttribType: 75 return false; 76 case kHalf2_GrVertexAttribType: 77 return false; 78 case kHalf3_GrVertexAttribType: 79 return false; 80 case kHalf4_GrVertexAttribType: 81 return false; 82 case kInt2_GrVertexAttribType: 83 return true; 84 case kInt3_GrVertexAttribType: 85 return true; 86 case kInt4_GrVertexAttribType: 87 return true; 88 case kUByte_norm_GrVertexAttribType: 89 return false; 90 case kUByte4_norm_GrVertexAttribType: 91 return false; 92 case kShort2_GrVertexAttribType: 93 return true; 94 case kUShort2_GrVertexAttribType: 95 return shaderCaps->integerSupport(); // FIXME: caller should handle this. 96 case kUShort2_norm_GrVertexAttribType: 97 return false; 98 case kInt_GrVertexAttribType: 99 return true; 100 case kUint_GrVertexAttribType: 101 return true; 102 } 103 SK_ABORT("Unexpected attribute type"); 104 return false; 105 } 106 107 void GrGLAttribArrayState::set(GrGLGpu* gpu, 108 int index, 109 const GrBuffer* vertexBuffer, 110 GrVertexAttribType type, 111 GrGLsizei stride, 112 size_t offsetInBytes, 113 int divisor) { 114 SkASSERT(index >= 0 && index < fAttribArrayStates.count()); 115 SkASSERT(0 == divisor || gpu->caps()->instanceAttribSupport()); 116 AttribArrayState* array = &fAttribArrayStates[index]; 117 if (array->fVertexBufferUniqueID != vertexBuffer->uniqueID() || 118 array->fType != type || 119 array->fStride != stride || 120 array->fOffset != offsetInBytes) { 121 gpu->bindBuffer(kVertex_GrBufferType, vertexBuffer); 122 const AttribLayout& layout = attrib_layout(type); 123 const GrGLvoid* offsetAsPtr = reinterpret_cast<const GrGLvoid*>(offsetInBytes); 124 if (!GrVertexAttribTypeIsIntType(gpu->caps()->shaderCaps(), type)) { 125 GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index, 126 layout.fCount, 127 layout.fType, 128 layout.fNormalized, 129 stride, 130 offsetAsPtr)); 131 } else { 132 SkASSERT(gpu->caps()->shaderCaps()->integerSupport()); 133 SkASSERT(!layout.fNormalized); 134 GR_GL_CALL(gpu->glInterface(), VertexAttribIPointer(index, 135 layout.fCount, 136 layout.fType, 137 stride, 138 offsetAsPtr)); 139 } 140 array->fVertexBufferUniqueID = vertexBuffer->uniqueID(); 141 array->fType = type; 142 array->fStride = stride; 143 array->fOffset = offsetInBytes; 144 } 145 if (gpu->caps()->instanceAttribSupport() && array->fDivisor != divisor) { 146 SkASSERT(0 == divisor || 1 == divisor); // not necessarily a requirement but what we expect. 147 GR_GL_CALL(gpu->glInterface(), VertexAttribDivisor(index, divisor)); 148 array->fDivisor = divisor; 149 } 150 } 151 152 void GrGLAttribArrayState::enableVertexArrays(const GrGLGpu* gpu, int enabledCount, 153 EnablePrimitiveRestart enablePrimitiveRestart) { 154 SkASSERT(enabledCount <= fAttribArrayStates.count()); 155 156 if (!fEnableStateIsValid || enabledCount != fNumEnabledArrays) { 157 int firstIdxToEnable = fEnableStateIsValid ? fNumEnabledArrays : 0; 158 for (int i = firstIdxToEnable; i < enabledCount; ++i) { 159 GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(i)); 160 } 161 162 int endIdxToDisable = fEnableStateIsValid ? fNumEnabledArrays : fAttribArrayStates.count(); 163 for (int i = enabledCount; i < endIdxToDisable; ++i) { 164 GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i)); 165 } 166 167 fNumEnabledArrays = enabledCount; 168 } 169 170 SkASSERT(EnablePrimitiveRestart::kNo == enablePrimitiveRestart || 171 gpu->caps()->usePrimitiveRestart()); 172 173 if (gpu->caps()->usePrimitiveRestart() && 174 (!fEnableStateIsValid || enablePrimitiveRestart != fPrimitiveRestartEnabled)) { 175 if (EnablePrimitiveRestart::kYes == enablePrimitiveRestart) { 176 GR_GL_CALL(gpu->glInterface(), Enable(GR_GL_PRIMITIVE_RESTART_FIXED_INDEX)); 177 } else { 178 GR_GL_CALL(gpu->glInterface(), Disable(GR_GL_PRIMITIVE_RESTART_FIXED_INDEX)); 179 } 180 181 fPrimitiveRestartEnabled = enablePrimitiveRestart; 182 } 183 184 fEnableStateIsValid = true; 185 } 186 187 /////////////////////////////////////////////////////////////////////////////////////////////////// 188 189 GrGLVertexArray::GrGLVertexArray(GrGLint id, int attribCount) 190 : fID(id) 191 , fAttribArrays(attribCount) 192 , fIndexBufferUniqueID(SK_InvalidUniqueID) { 193 } 194 195 GrGLAttribArrayState* GrGLVertexArray::bind(GrGLGpu* gpu) { 196 if (0 == fID) { 197 return nullptr; 198 } 199 gpu->bindVertexArray(fID); 200 return &fAttribArrays; 201 } 202 203 GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(GrGLGpu* gpu, const GrBuffer* ibuff) { 204 GrGLAttribArrayState* state = this->bind(gpu); 205 if (state && fIndexBufferUniqueID != ibuff->uniqueID()) { 206 if (ibuff->isCPUBacked()) { 207 GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0)); 208 } else { 209 const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(ibuff); 210 GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 211 glBuffer->bufferID())); 212 } 213 fIndexBufferUniqueID = ibuff->uniqueID(); 214 } 215 return state; 216 } 217 218 void GrGLVertexArray::invalidateCachedState() { 219 fAttribArrays.invalidate(); 220 fIndexBufferUniqueID.makeInvalid(); 221 } 222