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: #ifndef GrGLVertexArray_DEFINED michael@0: #define GrGLVertexArray_DEFINED michael@0: michael@0: #include "GrResource.h" michael@0: #include "GrTypesPriv.h" michael@0: #include "gl/GrGLDefines.h" michael@0: #include "gl/GrGLFunctions.h" michael@0: michael@0: #include "SkTArray.h" michael@0: michael@0: class GrGLVertexBuffer; michael@0: class GrGLIndexBuffer; michael@0: class GrGpuGL; michael@0: michael@0: struct GrGLAttribLayout { michael@0: GrGLint fCount; michael@0: GrGLenum fType; michael@0: GrGLboolean fNormalized; michael@0: }; michael@0: michael@0: static inline const GrGLAttribLayout& GrGLAttribTypeToLayout(GrVertexAttribType type) { michael@0: SkASSERT(type >= 0 && type < kGrVertexAttribTypeCount); michael@0: static const GrGLAttribLayout kLayouts[kGrVertexAttribTypeCount] = { michael@0: {1, GR_GL_FLOAT, false}, // kFloat_GrVertexAttribType michael@0: {2, GR_GL_FLOAT, false}, // kVec2f_GrVertexAttribType michael@0: {3, GR_GL_FLOAT, false}, // kVec3f_GrVertexAttribType michael@0: {4, GR_GL_FLOAT, false}, // kVec4f_GrVertexAttribType michael@0: {4, GR_GL_UNSIGNED_BYTE, true}, // kVec4ub_GrVertexAttribType michael@0: }; michael@0: GR_STATIC_ASSERT(0 == kFloat_GrVertexAttribType); michael@0: GR_STATIC_ASSERT(1 == kVec2f_GrVertexAttribType); michael@0: GR_STATIC_ASSERT(2 == kVec3f_GrVertexAttribType); michael@0: GR_STATIC_ASSERT(3 == kVec4f_GrVertexAttribType); michael@0: GR_STATIC_ASSERT(4 == kVec4ub_GrVertexAttribType); michael@0: GR_STATIC_ASSERT(SK_ARRAY_COUNT(kLayouts) == kGrVertexAttribTypeCount); michael@0: return kLayouts[type]; michael@0: } michael@0: michael@0: /** michael@0: * This sets and tracks the vertex attribute array state. It is used internally by GrGLVertexArray michael@0: * (below) but is separate because it is also used to track the state of vertex array object 0. michael@0: */ michael@0: class GrGLAttribArrayState { michael@0: public: michael@0: explicit GrGLAttribArrayState(int arrayCount = 0) { michael@0: this->resize(arrayCount); michael@0: } michael@0: michael@0: void resize(int newCount) { michael@0: fAttribArrayStates.resize_back(newCount); michael@0: for (int i = 0; i < newCount; ++i) { michael@0: fAttribArrayStates[i].invalidate(); michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * This function enables and sets vertex attrib state for the specified attrib index. It is michael@0: * assumed that the GrGLAttribArrayState is tracking the state of the currently bound vertex michael@0: * array object. michael@0: */ michael@0: void set(const GrGpuGL*, michael@0: int index, michael@0: GrGLVertexBuffer*, michael@0: GrGLint size, michael@0: GrGLenum type, michael@0: GrGLboolean normalized, michael@0: GrGLsizei stride, michael@0: GrGLvoid* offset); michael@0: michael@0: /** michael@0: * This function disables vertex attribs not present in the mask. It is assumed that the michael@0: * GrGLAttribArrayState is tracking the state of the currently bound vertex array object. michael@0: */ michael@0: void disableUnusedArrays(const GrGpuGL*, uint64_t usedAttribArrayMask); michael@0: michael@0: void invalidate() { michael@0: int count = fAttribArrayStates.count(); michael@0: for (int i = 0; i < count; ++i) { michael@0: fAttribArrayStates[i].invalidate(); michael@0: } michael@0: } michael@0: michael@0: void notifyVertexBufferDelete(GrGLuint id) { michael@0: int count = fAttribArrayStates.count(); michael@0: for (int i = 0; i < count; ++i) { michael@0: if (fAttribArrayStates[i].fAttribPointerIsValid && michael@0: id == fAttribArrayStates[i].fVertexBufferID) { michael@0: fAttribArrayStates[i].invalidate(); michael@0: } michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * The number of attrib arrays that this object is configured to track. michael@0: */ michael@0: int count() const { return fAttribArrayStates.count(); } michael@0: michael@0: private: michael@0: /** michael@0: * Tracks the state of glVertexAttribArray for an attribute index. michael@0: */ michael@0: struct AttribArrayState { michael@0: void invalidate() { michael@0: fEnableIsValid = false; michael@0: fAttribPointerIsValid = false; michael@0: } michael@0: michael@0: bool fEnableIsValid; michael@0: bool fAttribPointerIsValid; michael@0: bool fEnabled; michael@0: GrGLuint fVertexBufferID; michael@0: GrGLint fSize; michael@0: GrGLenum fType; michael@0: GrGLboolean fNormalized; michael@0: GrGLsizei fStride; michael@0: GrGLvoid* fOffset; michael@0: }; michael@0: michael@0: SkSTArray<16, AttribArrayState, true> fAttribArrayStates; michael@0: }; michael@0: michael@0: /** michael@0: * This class represents an OpenGL vertex array object. It manages the lifetime of the vertex array michael@0: * and is used to track the state of the vertex array to avoid redundant GL calls. michael@0: */ michael@0: class GrGLVertexArray : public GrResource { michael@0: public: michael@0: GrGLVertexArray(GrGpuGL* gpu, GrGLint id, int attribCount); michael@0: michael@0: /** michael@0: * Binds this vertex array. If the ID has been deleted or abandoned then NULL is returned. michael@0: * Otherwise, the GrGLAttribArrayState that is tracking this vertex array's attrib bindings is michael@0: * returned. michael@0: */ michael@0: GrGLAttribArrayState* bind(); michael@0: michael@0: /** michael@0: * This is a version of the above function that also binds an index buffer to the vertex michael@0: * array object. michael@0: */ michael@0: GrGLAttribArrayState* bindWithIndexBuffer(const GrGLIndexBuffer* indexBuffer); michael@0: michael@0: void notifyIndexBufferDelete(GrGLuint bufferID); michael@0: michael@0: void notifyVertexBufferDelete(GrGLuint id) { michael@0: fAttribArrays.notifyVertexBufferDelete(id); michael@0: } michael@0: michael@0: GrGLuint arrayID() const { return fID; } michael@0: michael@0: void invalidateCachedState(); michael@0: michael@0: virtual size_t sizeInBytes() const SK_OVERRIDE { return 0; } michael@0: michael@0: protected: michael@0: virtual void onAbandon() SK_OVERRIDE; michael@0: michael@0: virtual void onRelease() SK_OVERRIDE; michael@0: michael@0: private: michael@0: GrGLuint fID; michael@0: GrGLAttribArrayState fAttribArrays; michael@0: GrGLuint fIndexBufferID; michael@0: bool fIndexBufferIDIsValid; michael@0: michael@0: typedef GrResource INHERITED; michael@0: }; michael@0: michael@0: #endif