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 "src/gpu/GrCpuBuffer.h" 9#include "src/gpu/gl/GrGLBuffer.h" 10#include "src/gpu/gl/GrGLGpu.h" 11#include "src/gpu/gl/GrGLVertexArray.h" 12 13struct AttribLayout { 14 bool fNormalized; // Only used by floating point types. 15 uint8_t fCount; 16 uint16_t fType; 17}; 18 19static_assert(4 == sizeof(AttribLayout)); 20 21static AttribLayout attrib_layout(GrVertexAttribType type) { 22 switch (type) { 23 case kFloat_GrVertexAttribType: 24 return {false, 1, GR_GL_FLOAT}; 25 case kFloat2_GrVertexAttribType: 26 return {false, 2, GR_GL_FLOAT}; 27 case kFloat3_GrVertexAttribType: 28 return {false, 3, GR_GL_FLOAT}; 29 case kFloat4_GrVertexAttribType: 30 return {false, 4, GR_GL_FLOAT}; 31 case kHalf_GrVertexAttribType: 32 return {false, 1, GR_GL_HALF_FLOAT}; 33 case kHalf2_GrVertexAttribType: 34 return {false, 2, GR_GL_HALF_FLOAT}; 35 case kHalf4_GrVertexAttribType: 36 return {false, 4, GR_GL_HALF_FLOAT}; 37 case kInt2_GrVertexAttribType: 38 return {false, 2, GR_GL_INT}; 39 case kInt3_GrVertexAttribType: 40 return {false, 3, GR_GL_INT}; 41 case kInt4_GrVertexAttribType: 42 return {false, 4, GR_GL_INT}; 43 case kByte_GrVertexAttribType: 44 return {false, 1, GR_GL_BYTE}; 45 case kByte2_GrVertexAttribType: 46 return {false, 2, GR_GL_BYTE}; 47 case kByte4_GrVertexAttribType: 48 return {false, 4, GR_GL_BYTE}; 49 case kUByte_GrVertexAttribType: 50 return {false, 1, GR_GL_UNSIGNED_BYTE}; 51 case kUByte2_GrVertexAttribType: 52 return {false, 2, GR_GL_UNSIGNED_BYTE}; 53 case kUByte4_GrVertexAttribType: 54 return {false, 4, GR_GL_UNSIGNED_BYTE}; 55 case kUByte_norm_GrVertexAttribType: 56 return {true, 1, GR_GL_UNSIGNED_BYTE}; 57 case kUByte4_norm_GrVertexAttribType: 58 return {true, 4, GR_GL_UNSIGNED_BYTE}; 59 case kShort2_GrVertexAttribType: 60 return {false, 2, GR_GL_SHORT}; 61 case kShort4_GrVertexAttribType: 62 return {false, 4, GR_GL_SHORT}; 63 case kUShort2_GrVertexAttribType: 64 return {false, 2, GR_GL_UNSIGNED_SHORT}; 65 case kUShort2_norm_GrVertexAttribType: 66 return {true, 2, GR_GL_UNSIGNED_SHORT}; 67 case kInt_GrVertexAttribType: 68 return {false, 1, GR_GL_INT}; 69 case kUInt_GrVertexAttribType: 70 return {false, 1, GR_GL_UNSIGNED_INT}; 71 case kUShort_norm_GrVertexAttribType: 72 return {true, 1, GR_GL_UNSIGNED_SHORT}; 73 case kUShort4_norm_GrVertexAttribType: 74 return {true, 4, GR_GL_UNSIGNED_SHORT}; 75 } 76 SK_ABORT("Unknown vertex attrib type"); 77}; 78 79void GrGLAttribArrayState::set(GrGLGpu* gpu, 80 int index, 81 const GrBuffer* vertexBuffer, 82 GrVertexAttribType cpuType, 83 GrSLType gpuType, 84 GrGLsizei stride, 85 size_t offsetInBytes, 86 int divisor) { 87 SkASSERT(index >= 0 && index < fAttribArrayStates.count()); 88 SkASSERT(0 == divisor || gpu->caps()->drawInstancedSupport()); 89 AttribArrayState* array = &fAttribArrayStates[index]; 90 const char* offsetAsPtr; 91 bool bufferChanged = false; 92 if (vertexBuffer->isCpuBuffer()) { 93 if (!array->fUsingCpuBuffer) { 94 bufferChanged = true; 95 array->fUsingCpuBuffer = true; 96 } 97 offsetAsPtr = static_cast<const GrCpuBuffer*>(vertexBuffer)->data() + offsetInBytes; 98 } else { 99 auto gpuBuffer = static_cast<const GrGpuBuffer*>(vertexBuffer); 100 if (array->fUsingCpuBuffer || array->fVertexBufferUniqueID != gpuBuffer->uniqueID()) { 101 bufferChanged = true; 102 array->fVertexBufferUniqueID = gpuBuffer->uniqueID(); 103 } 104 offsetAsPtr = reinterpret_cast<const char*>(offsetInBytes); 105 } 106 if (bufferChanged || 107 array->fCPUType != cpuType || 108 array->fGPUType != gpuType || 109 array->fStride != stride || 110 array->fOffset != offsetAsPtr) { 111 // We always have to call this if we're going to change the array pointer. 'array' is 112 // tracking the last buffer used to setup attrib pointers, not the last buffer bound. 113 // GrGLGpu will avoid redundant binds. 114 gpu->bindBuffer(GrGpuBufferType::kVertex, vertexBuffer); 115 const AttribLayout& layout = attrib_layout(cpuType); 116 if (GrSLTypeIsFloatType(gpuType)) { 117 GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index, 118 layout.fCount, 119 layout.fType, 120 layout.fNormalized, 121 stride, 122 offsetAsPtr)); 123 } else { 124 SkASSERT(gpu->caps()->shaderCaps()->integerSupport()); 125 SkASSERT(!layout.fNormalized); 126 GR_GL_CALL(gpu->glInterface(), VertexAttribIPointer(index, 127 layout.fCount, 128 layout.fType, 129 stride, 130 offsetAsPtr)); 131 } 132 array->fCPUType = cpuType; 133 array->fGPUType = gpuType; 134 array->fStride = stride; 135 array->fOffset = offsetAsPtr; 136 } 137 if (gpu->caps()->drawInstancedSupport() && array->fDivisor != divisor) { 138 SkASSERT(0 == divisor || 1 == divisor); // not necessarily a requirement but what we expect. 139 GR_GL_CALL(gpu->glInterface(), VertexAttribDivisor(index, divisor)); 140 array->fDivisor = divisor; 141 } 142} 143 144void GrGLAttribArrayState::enableVertexArrays(const GrGLGpu* gpu, int enabledCount, 145 GrPrimitiveRestart enablePrimitiveRestart) { 146 SkASSERT(enabledCount <= fAttribArrayStates.count()); 147 148 if (!fEnableStateIsValid || enabledCount != fNumEnabledArrays) { 149 int firstIdxToEnable = fEnableStateIsValid ? fNumEnabledArrays : 0; 150 for (int i = firstIdxToEnable; i < enabledCount; ++i) { 151 GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(i)); 152 } 153 154 int endIdxToDisable = fEnableStateIsValid ? fNumEnabledArrays : fAttribArrayStates.count(); 155 for (int i = enabledCount; i < endIdxToDisable; ++i) { 156 GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i)); 157 } 158 159 fNumEnabledArrays = enabledCount; 160 } 161 162 SkASSERT(GrPrimitiveRestart::kNo == enablePrimitiveRestart || 163 gpu->caps()->usePrimitiveRestart()); 164 165 if (gpu->caps()->usePrimitiveRestart() && 166 (!fEnableStateIsValid || enablePrimitiveRestart != fPrimitiveRestartEnabled)) { 167 if (GrPrimitiveRestart::kYes == enablePrimitiveRestart) { 168 GR_GL_CALL(gpu->glInterface(), Enable(GR_GL_PRIMITIVE_RESTART_FIXED_INDEX)); 169 } else { 170 GR_GL_CALL(gpu->glInterface(), Disable(GR_GL_PRIMITIVE_RESTART_FIXED_INDEX)); 171 } 172 173 fPrimitiveRestartEnabled = enablePrimitiveRestart; 174 } 175 176 fEnableStateIsValid = true; 177} 178 179/////////////////////////////////////////////////////////////////////////////////////////////////// 180 181GrGLVertexArray::GrGLVertexArray(GrGLint id, int attribCount) 182 : fID(id) 183 , fAttribArrays(attribCount) 184 , fIndexBufferUniqueID(SK_InvalidUniqueID) { 185} 186 187GrGLAttribArrayState* GrGLVertexArray::bind(GrGLGpu* gpu) { 188 if (0 == fID) { 189 return nullptr; 190 } 191 gpu->bindVertexArray(fID); 192 return &fAttribArrays; 193} 194 195GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(GrGLGpu* gpu, const GrBuffer* ibuff) { 196 GrGLAttribArrayState* state = this->bind(gpu); 197 if (!state) { 198 return nullptr; 199 } 200 if (ibuff->isCpuBuffer()) { 201 GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0)); 202 } else { 203 const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(ibuff); 204 if (fIndexBufferUniqueID != glBuffer->uniqueID()) { 205 GR_GL_CALL(gpu->glInterface(), 206 BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, glBuffer->bufferID())); 207 fIndexBufferUniqueID = glBuffer->uniqueID(); 208 } 209 } 210 return state; 211} 212 213void GrGLVertexArray::invalidateCachedState() { 214 fAttribArrays.invalidate(); 215 fIndexBufferUniqueID.makeInvalid(); 216} 217