| /* | |
| * Copyright 2013 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "GrGLVertexArray.h" | |
| #include "GrGLBuffer.h" | |
| #include "GrGLGpu.h" | |
| struct AttribLayout { | |
| GrGLint fCount; | |
| GrGLenum fType; | |
| GrGLboolean fNormalized; // Only used by floating point types. | |
| }; | |
| static const AttribLayout gLayouts[kGrVertexAttribTypeCount] = { | |
| {1, GR_GL_FLOAT, false}, // kFloat_GrVertexAttribType | |
| {2, GR_GL_FLOAT, false}, // kVec2f_GrVertexAttribType | |
| {3, GR_GL_FLOAT, false}, // kVec3f_GrVertexAttribType | |
| {4, GR_GL_FLOAT, false}, // kVec4f_GrVertexAttribType | |
| {1, GR_GL_UNSIGNED_BYTE, true}, // kUByte_GrVertexAttribType | |
| {4, GR_GL_UNSIGNED_BYTE, true}, // kVec4ub_GrVertexAttribType | |
| {2, GR_GL_UNSIGNED_SHORT, true}, // kVec2s_GrVertexAttribType | |
| {1, GR_GL_INT, false}, // kInt_GrVertexAttribType | |
| {1, GR_GL_UNSIGNED_INT, false}, // kUint_GrVertexAttribType | |
| }; | |
| GR_STATIC_ASSERT(0 == kFloat_GrVertexAttribType); | |
| GR_STATIC_ASSERT(1 == kVec2f_GrVertexAttribType); | |
| GR_STATIC_ASSERT(2 == kVec3f_GrVertexAttribType); | |
| GR_STATIC_ASSERT(3 == kVec4f_GrVertexAttribType); | |
| GR_STATIC_ASSERT(4 == kUByte_GrVertexAttribType); | |
| GR_STATIC_ASSERT(5 == kVec4ub_GrVertexAttribType); | |
| GR_STATIC_ASSERT(6 == kVec2us_GrVertexAttribType); | |
| GR_STATIC_ASSERT(7 == kInt_GrVertexAttribType); | |
| GR_STATIC_ASSERT(8 == kUint_GrVertexAttribType); | |
| void GrGLAttribArrayState::set(GrGLGpu* gpu, | |
| int index, | |
| const GrBuffer* vertexBuffer, | |
| GrVertexAttribType type, | |
| GrGLsizei stride, | |
| GrGLvoid* offset) { | |
| SkASSERT(index >= 0 && index < fAttribArrayStates.count()); | |
| AttribArrayState* array = &fAttribArrayStates[index]; | |
| if (!array->fEnableIsValid || !array->fEnabled) { | |
| GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(index)); | |
| array->fEnableIsValid = true; | |
| array->fEnabled = true; | |
| } | |
| if (array->fVertexBufferUniqueID != vertexBuffer->uniqueID() || | |
| array->fType != type || | |
| array->fStride != stride || | |
| array->fOffset != offset) { | |
| gpu->bindBuffer(kVertex_GrBufferType, vertexBuffer); | |
| const AttribLayout& layout = gLayouts[type]; | |
| if (!GrVertexAttribTypeIsIntType(type)) { | |
| GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index, | |
| layout.fCount, | |
| layout.fType, | |
| layout.fNormalized, | |
| stride, | |
| offset)); | |
| } else { | |
| SkASSERT(gpu->caps()->shaderCaps()->integerSupport()); | |
| SkASSERT(!layout.fNormalized); | |
| GR_GL_CALL(gpu->glInterface(), VertexAttribIPointer(index, | |
| layout.fCount, | |
| layout.fType, | |
| stride, | |
| offset)); | |
| } | |
| array->fVertexBufferUniqueID = vertexBuffer->uniqueID(); | |
| array->fType = type; | |
| array->fStride = stride; | |
| array->fOffset = offset; | |
| } | |
| } | |
| void GrGLAttribArrayState::disableUnusedArrays(const GrGLGpu* gpu, uint64_t usedMask) { | |
| int count = fAttribArrayStates.count(); | |
| for (int i = 0; i < count; ++i) { | |
| if (!(usedMask & 0x1)) { | |
| if (!fAttribArrayStates[i].fEnableIsValid || fAttribArrayStates[i].fEnabled) { | |
| GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i)); | |
| fAttribArrayStates[i].fEnableIsValid = true; | |
| fAttribArrayStates[i].fEnabled = false; | |
| } | |
| } else { | |
| SkASSERT(fAttribArrayStates[i].fEnableIsValid && fAttribArrayStates[i].fEnabled); | |
| } | |
| // if the count is greater than 64 then this will become 0 and we will disable arrays 64+. | |
| usedMask >>= 1; | |
| } | |
| } | |
| /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| GrGLVertexArray::GrGLVertexArray(GrGLint id, int attribCount) | |
| : fID(id) | |
| , fAttribArrays(attribCount) | |
| , fIndexBufferUniqueID(SK_InvalidUniqueID) { | |
| } | |
| GrGLAttribArrayState* GrGLVertexArray::bind(GrGLGpu* gpu) { | |
| if (0 == fID) { | |
| return nullptr; | |
| } | |
| gpu->bindVertexArray(fID); | |
| return &fAttribArrays; | |
| } | |
| GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(GrGLGpu* gpu, const GrBuffer* ibuff) { | |
| GrGLAttribArrayState* state = this->bind(gpu); | |
| if (state && fIndexBufferUniqueID != ibuff->uniqueID()) { | |
| if (ibuff->isCPUBacked()) { | |
| GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0)); | |
| } else { | |
| const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(ibuff); | |
| GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, | |
| glBuffer->bufferID())); | |
| } | |
| fIndexBufferUniqueID = ibuff->uniqueID(); | |
| } | |
| return state; | |
| } | |
| void GrGLVertexArray::invalidateCachedState() { | |
| fAttribArrays.invalidate(); | |
| fIndexBufferUniqueID = SK_InvalidUniqueID; | |
| } |