1/* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#ifndef GrGLVertexArray_DEFINED 9#define GrGLVertexArray_DEFINED 10 11#include "GrResource.h" 12#include "GrTypesPriv.h" 13#include "gl/GrGLDefines.h" 14#include "gl/GrGLFunctions.h" 15 16#include "SkTArray.h" 17 18class GrGLVertexBuffer; 19class GrGLIndexBuffer; 20class GrGpuGL; 21 22struct GrGLAttribLayout { 23 GrGLint fCount; 24 GrGLenum fType; 25 GrGLboolean fNormalized; 26}; 27 28static inline const GrGLAttribLayout& GrGLAttribTypeToLayout(GrVertexAttribType type) { 29 SkASSERT(type >= 0 && type < kGrVertexAttribTypeCount); 30 static const GrGLAttribLayout kLayouts[kGrVertexAttribTypeCount] = { 31 {1, GR_GL_FLOAT, false}, // kFloat_GrVertexAttribType 32 {2, GR_GL_FLOAT, false}, // kVec2f_GrVertexAttribType 33 {3, GR_GL_FLOAT, false}, // kVec3f_GrVertexAttribType 34 {4, GR_GL_FLOAT, false}, // kVec4f_GrVertexAttribType 35 {4, GR_GL_UNSIGNED_BYTE, true}, // kVec4ub_GrVertexAttribType 36 }; 37 GR_STATIC_ASSERT(0 == kFloat_GrVertexAttribType); 38 GR_STATIC_ASSERT(1 == kVec2f_GrVertexAttribType); 39 GR_STATIC_ASSERT(2 == kVec3f_GrVertexAttribType); 40 GR_STATIC_ASSERT(3 == kVec4f_GrVertexAttribType); 41 GR_STATIC_ASSERT(4 == kVec4ub_GrVertexAttribType); 42 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kLayouts) == kGrVertexAttribTypeCount); 43 return kLayouts[type]; 44} 45 46/** 47 * This sets and tracks the vertex attribute array state. It is used internally by GrGLVertexArray 48 * (below) but is separate because it is also used to track the state of vertex array object 0. 49 */ 50class GrGLAttribArrayState { 51public: 52 explicit GrGLAttribArrayState(int arrayCount = 0) { 53 this->resize(arrayCount); 54 // glVertexPointer doesn't have a normalization param. 55 fFixedFunctionVertexArray.fNormalized = false; 56 fUnusedFixedFunctionArraysDisabled = false; 57 } 58 59 void resize(int newCount) { 60 fAttribArrayStates.resize_back(newCount); 61 for (int i = 0; i < newCount; ++i) { 62 fAttribArrayStates[i].invalidate(); 63 } 64 } 65 66 /** 67 * This function enables and sets vertex attrib state for the specified attrib index. It is 68 * assumed that the GrGLAttribArrayState is tracking the state of the currently bound vertex 69 * array object. 70 */ 71 void set(const GrGpuGL*, 72 int index, 73 GrGLVertexBuffer*, 74 GrGLint size, 75 GrGLenum type, 76 GrGLboolean normalized, 77 GrGLsizei stride, 78 GrGLvoid* offset); 79 80 void setFixedFunctionVertexArray(const GrGpuGL*, 81 GrGLVertexBuffer*, 82 GrGLint size, 83 GrGLenum type, 84 GrGLsizei stride, 85 GrGLvoid* offset); 86 87 /** 88 * This function disables vertex attribs not present in the mask. It is assumed that the 89 * GrGLAttribArrayState is tracking the state of the currently bound vertex array object. 90 */ 91 void disableUnusedArrays(const GrGpuGL*, uint64_t usedAttribArrayMask, bool usingFFVertexArray); 92 93 void invalidate() { 94 int count = fAttribArrayStates.count(); 95 for (int i = 0; i < count; ++i) { 96 fAttribArrayStates[i].invalidate(); 97 } 98 fFixedFunctionVertexArray.invalidate(); 99 fUnusedFixedFunctionArraysDisabled = false; 100 } 101 102 void notifyVertexBufferDelete(GrGLuint id) { 103 int count = fAttribArrayStates.count(); 104 for (int i = 0; i < count; ++i) { 105 if (fAttribArrayStates[i].fAttribPointerIsValid && 106 id == fAttribArrayStates[i].fVertexBufferID) { 107 fAttribArrayStates[i].invalidate(); 108 } 109 } 110 if (fFixedFunctionVertexArray.fAttribPointerIsValid && 111 id == fFixedFunctionVertexArray.fVertexBufferID) { 112 fFixedFunctionVertexArray.invalidate(); 113 } 114 } 115 116 /** 117 * The number of attrib arrays that this object is configured to track. 118 */ 119 int count() const { return fAttribArrayStates.count(); } 120 121private: 122 /** 123 * Tracks the state of glVertexAttribArray for an attribute index. 124 */ 125 struct AttribArrayState { 126 void invalidate() { 127 fEnableIsValid = false; 128 fAttribPointerIsValid = false; 129 } 130 131 bool fEnableIsValid; 132 bool fAttribPointerIsValid; 133 bool fEnabled; 134 GrGLuint fVertexBufferID; 135 GrGLint fSize; 136 GrGLenum fType; 137 GrGLboolean fNormalized; 138 GrGLsizei fStride; 139 GrGLvoid* fOffset; 140 }; 141 142 SkSTArray<16, AttribArrayState, true> fAttribArrayStates; 143 144 // Tracks the array specified by glVertexPointer. 145 AttribArrayState fFixedFunctionVertexArray; 146 147 // Tracks whether we've disabled the other fixed function arrays that we don't 148 // use (e.g. glNormalPointer). 149 bool fUnusedFixedFunctionArraysDisabled; 150}; 151 152/** 153 * This class represents an OpenGL vertex array object. It manages the lifetime of the vertex array 154 * and is used to track the state of the vertex array to avoid redundant GL calls. 155 */ 156class GrGLVertexArray : public GrResource { 157public: 158 GrGLVertexArray(GrGpuGL* gpu, GrGLint id, int attribCount); 159 160 /** 161 * Binds this vertex array. If the ID has been deleted or abandoned then NULL is returned. 162 * Otherwise, the GrGLAttribArrayState that is tracking this vertex array's attrib bindings is 163 * returned. 164 */ 165 GrGLAttribArrayState* bind(); 166 167 /** 168 * This is a version of the above function that also binds an index buffer to the vertex 169 * array object. 170 */ 171 GrGLAttribArrayState* bindWithIndexBuffer(const GrGLIndexBuffer* indexBuffer); 172 173 void notifyIndexBufferDelete(GrGLuint bufferID); 174 175 void notifyVertexBufferDelete(GrGLuint id) { 176 fAttribArrays.notifyVertexBufferDelete(id); 177 } 178 179 GrGLuint arrayID() const { return fID; } 180 181 void invalidateCachedState(); 182 183 virtual size_t sizeInBytes() const SK_OVERRIDE { return 0; } 184 185protected: 186 virtual void onAbandon() SK_OVERRIDE; 187 188 virtual void onRelease() SK_OVERRIDE; 189 190private: 191 GrGLuint fID; 192 GrGLAttribArrayState fAttribArrays; 193 GrGLuint fIndexBufferID; 194 bool fIndexBufferIDIsValid; 195 196 typedef GrResource INHERITED; 197}; 198 199#endif 200