| /* |
| * 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; |
| } |