michael@0: /* michael@0: * Copyright 2013 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #include "GrGLVertexArray.h" michael@0: #include "GrGpuGL.h" michael@0: michael@0: #define GPUGL static_cast(this->getGpu()) michael@0: #define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X); michael@0: michael@0: void GrGLAttribArrayState::set(const GrGpuGL* gpu, michael@0: int index, michael@0: GrGLVertexBuffer* buffer, michael@0: GrGLint size, michael@0: GrGLenum type, michael@0: GrGLboolean normalized, michael@0: GrGLsizei stride, michael@0: GrGLvoid* offset) { michael@0: SkASSERT(index >= 0 && index < fAttribArrayStates.count()); michael@0: AttribArrayState* array = &fAttribArrayStates[index]; michael@0: if (!array->fEnableIsValid || !array->fEnabled) { michael@0: GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(index)); michael@0: array->fEnableIsValid = true; michael@0: array->fEnabled = true; michael@0: } michael@0: if (!array->fAttribPointerIsValid || michael@0: array->fVertexBufferID != buffer->bufferID() || michael@0: array->fSize != size || michael@0: array->fNormalized != normalized || michael@0: array->fStride != stride || michael@0: array->fOffset != offset) { michael@0: michael@0: buffer->bind(); michael@0: GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index, michael@0: size, michael@0: type, michael@0: normalized, michael@0: stride, michael@0: offset)); michael@0: array->fAttribPointerIsValid = true; michael@0: array->fVertexBufferID = buffer->bufferID(); michael@0: array->fSize = size; michael@0: array->fNormalized = normalized; michael@0: array->fStride = stride; michael@0: array->fOffset = offset; michael@0: } michael@0: } michael@0: michael@0: void GrGLAttribArrayState::disableUnusedArrays(const GrGpuGL* gpu, uint64_t usedMask) { michael@0: int count = fAttribArrayStates.count(); michael@0: for (int i = 0; i < count; ++i) { michael@0: if (!(usedMask & 0x1)) { michael@0: if (!fAttribArrayStates[i].fEnableIsValid || fAttribArrayStates[i].fEnabled) { michael@0: GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i)); michael@0: fAttribArrayStates[i].fEnableIsValid = true; michael@0: fAttribArrayStates[i].fEnabled = false; michael@0: } michael@0: } else { michael@0: SkASSERT(fAttribArrayStates[i].fEnableIsValid && fAttribArrayStates[i].fEnabled); michael@0: } michael@0: // if the count is greater than 64 then this will become 0 and we will disable arrays 64+. michael@0: usedMask >>= 1; michael@0: } michael@0: } michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: GrGLVertexArray::GrGLVertexArray(GrGpuGL* gpu, GrGLint id, int attribCount) michael@0: : GrResource(gpu, false) michael@0: , fID(id) michael@0: , fAttribArrays(attribCount) michael@0: , fIndexBufferIDIsValid(false) { michael@0: } michael@0: michael@0: void GrGLVertexArray::onAbandon() { michael@0: fID = 0; michael@0: INHERITED::onAbandon(); michael@0: } michael@0: michael@0: void GrGLVertexArray::onRelease() { michael@0: if (0 != fID) { michael@0: GL_CALL(DeleteVertexArrays(1, &fID)); michael@0: GPUGL->notifyVertexArrayDelete(fID); michael@0: fID = 0; michael@0: } michael@0: INHERITED::onRelease(); michael@0: } michael@0: michael@0: GrGLAttribArrayState* GrGLVertexArray::bind() { michael@0: if (0 == fID) { michael@0: return NULL; michael@0: } michael@0: GPUGL->bindVertexArray(fID); michael@0: return &fAttribArrays; michael@0: } michael@0: michael@0: GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(const GrGLIndexBuffer* buffer) { michael@0: GrGLAttribArrayState* state = this->bind(); michael@0: if (NULL != state && NULL != buffer) { michael@0: GrGLuint bufferID = buffer->bufferID(); michael@0: if (!fIndexBufferIDIsValid || bufferID != fIndexBufferID) { michael@0: GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, bufferID)); michael@0: fIndexBufferIDIsValid = true; michael@0: fIndexBufferID = bufferID; michael@0: } michael@0: } michael@0: return state; michael@0: } michael@0: michael@0: void GrGLVertexArray::notifyIndexBufferDelete(GrGLuint bufferID) { michael@0: if (fIndexBufferIDIsValid && bufferID == fIndexBufferID) { michael@0: fIndexBufferID = 0; michael@0: } michael@0: } michael@0: michael@0: void GrGLVertexArray::invalidateCachedState() { michael@0: fAttribArrays.invalidate(); michael@0: fIndexBufferIDIsValid = false; michael@0: }