/* * Copyright 2013 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef GrGLVertexArray_DEFINED #define GrGLVertexArray_DEFINED #include "GrTypesPriv.h" #include "gl/GrGLDefines.h" #include "gl/GrGLTypes.h" #include "SkTArray.h" class GrGLVertexBuffer; class GrGLIndexBuffer; class GrGLGpu; /** * This sets and tracks the vertex attribute array state. It is used internally by GrGLVertexArray * (below) but is separate because it is also used to track the state of vertex array object 0. */ class GrGLAttribArrayState { public: explicit GrGLAttribArrayState(int arrayCount = 0) { this->resize(arrayCount); } void resize(int newCount) { fAttribArrayStates.resize_back(newCount); for (int i = 0; i < newCount; ++i) { fAttribArrayStates[i].invalidate(); } } /** * This function enables and sets vertex attrib state for the specified attrib index. It is * assumed that the GrGLAttribArrayState is tracking the state of the currently bound vertex * array object. */ void set(GrGLGpu*, int attribIndex, GrGLuint vertexBufferID, GrVertexAttribType type, GrGLsizei stride, GrGLvoid* offset); /** * This function disables vertex attribs not present in the mask. It is assumed that the * GrGLAttribArrayState is tracking the state of the currently bound vertex array object. */ void disableUnusedArrays(const GrGLGpu*, uint64_t usedAttribArrayMask); void invalidate() { int count = fAttribArrayStates.count(); for (int i = 0; i < count; ++i) { fAttribArrayStates[i].invalidate(); } } void notifyVertexBufferDelete(GrGLuint id) { int count = fAttribArrayStates.count(); for (int i = 0; i < count; ++i) { if (fAttribArrayStates[i].fAttribPointerIsValid && id == fAttribArrayStates[i].fVertexBufferID) { fAttribArrayStates[i].invalidate(); } } } /** * The number of attrib arrays that this object is configured to track. */ int count() const { return fAttribArrayStates.count(); } private: /** * Tracks the state of glVertexAttribArray for an attribute index. */ struct AttribArrayState { void invalidate() { fEnableIsValid = false; fAttribPointerIsValid = false; } bool fEnableIsValid; bool fAttribPointerIsValid; bool fEnabled; GrGLuint fVertexBufferID; GrVertexAttribType fType; GrGLsizei fStride; GrGLvoid* fOffset; }; SkSTArray<16, AttribArrayState, true> fAttribArrayStates; }; /** * This class represents an OpenGL vertex array object. It manages the lifetime of the vertex array * and is used to track the state of the vertex array to avoid redundant GL calls. */ class GrGLVertexArray { public: GrGLVertexArray(GrGLint id, int attribCount); /** * Binds this vertex array. If the ID has been deleted or abandoned then nullptr is returned. * Otherwise, the GrGLAttribArrayState that is tracking this vertex array's attrib bindings is * returned. */ GrGLAttribArrayState* bind(GrGLGpu*); /** * This is a version of the above function that also binds an index buffer to the vertex * array object. */ GrGLAttribArrayState* bindWithIndexBuffer(GrGLGpu* gpu, GrGLuint indexBufferID); void notifyIndexBufferDelete(GrGLuint bufferID); void notifyVertexBufferDelete(GrGLuint id) { fAttribArrays.notifyVertexBufferDelete(id); } GrGLuint arrayID() const { return fID; } void invalidateCachedState(); private: GrGLuint fID; GrGLAttribArrayState fAttribArrays; GrGLuint fIndexBufferID; bool fIndexBufferIDIsValid; }; #endif