| /* | |
| * 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 "GrGpuResource.h" | |
| #include "GrTypesPriv.h" | |
| #include "gl/GrGLDefines.h" | |
| #include "gl/GrGLFunctions.h" | |
| #include "SkTArray.h" | |
| class GrGLVertexBuffer; | |
| class GrGLIndexBuffer; | |
| class GrGLGpu; | |
| struct GrGLAttribLayout { | |
| GrGLint fCount; | |
| GrGLenum fType; | |
| GrGLboolean fNormalized; | |
| }; | |
| static inline const GrGLAttribLayout& GrGLAttribTypeToLayout(GrVertexAttribType type) { | |
| SkASSERT(type >= 0 && type < kGrVertexAttribTypeCount); | |
| static const GrGLAttribLayout kLayouts[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 | |
| }; | |
| 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(SK_ARRAY_COUNT(kLayouts) == kGrVertexAttribTypeCount); | |
| return kLayouts[type]; | |
| } | |
| /** | |
| * 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(const GrGLGpu*, | |
| int index, | |
| GrGLVertexBuffer*, | |
| GrGLint size, | |
| GrGLenum type, | |
| GrGLboolean normalized, | |
| 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; | |
| GrGLint fSize; | |
| GrGLenum fType; | |
| GrGLboolean fNormalized; | |
| 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 GrGpuResource { | |
| public: | |
| GrGLVertexArray(GrGLGpu* gpu, GrGLint id, int attribCount); | |
| /** | |
| * Binds this vertex array. If the ID has been deleted or abandoned then NULL is returned. | |
| * Otherwise, the GrGLAttribArrayState that is tracking this vertex array's attrib bindings is | |
| * returned. | |
| */ | |
| GrGLAttribArrayState* bind(); | |
| /** | |
| * This is a version of the above function that also binds an index buffer to the vertex | |
| * array object. | |
| */ | |
| GrGLAttribArrayState* bindWithIndexBuffer(const GrGLIndexBuffer* indexBuffer); | |
| void notifyIndexBufferDelete(GrGLuint bufferID); | |
| void notifyVertexBufferDelete(GrGLuint id) { | |
| fAttribArrays.notifyVertexBufferDelete(id); | |
| } | |
| GrGLuint arrayID() const { return fID; } | |
| void invalidateCachedState(); | |
| protected: | |
| virtual size_t onGpuMemorySize() const SK_OVERRIDE { return 0; } | |
| virtual void onAbandon() SK_OVERRIDE; | |
| virtual void onRelease() SK_OVERRIDE; | |
| private: | |
| GrGLuint fID; | |
| GrGLAttribArrayState fAttribArrays; | |
| GrGLuint fIndexBufferID; | |
| bool fIndexBufferIDIsValid; | |
| typedef GrGpuResource INHERITED; | |
| }; | |
| #endif |