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 #include "GrGLVertexArray.h" 9 #include "GrGpuGL.h" 10 11 #define GPUGL static_cast<GrGpuGL*>(this->getGpu()) 12 #define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X); 13 14 void GrGLAttribArrayState::set(const GrGpuGL* gpu, 15 int index, 16 GrGLVertexBuffer* buffer, 17 GrGLint size, 18 GrGLenum type, 19 GrGLboolean normalized, 20 GrGLsizei stride, 21 GrGLvoid* offset) { 22 SkASSERT(index >= 0 && index < fAttribArrayStates.count()); 23 AttribArrayState* array = &fAttribArrayStates[index]; 24 if (!array->fEnableIsValid || !array->fEnabled) { 25 GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(index)); 26 array->fEnableIsValid = true; 27 array->fEnabled = true; 28 } 29 if (!array->fAttribPointerIsValid || 30 array->fVertexBufferID != buffer->bufferID() || 31 array->fSize != size || 32 array->fNormalized != normalized || 33 array->fStride != stride || 34 array->fOffset != offset) { 35 36 buffer->bind(); 37 GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index, 38 size, 39 type, 40 normalized, 41 stride, 42 offset)); 43 array->fAttribPointerIsValid = true; 44 array->fVertexBufferID = buffer->bufferID(); 45 array->fSize = size; 46 array->fNormalized = normalized; 47 array->fStride = stride; 48 array->fOffset = offset; 49 } 50 } 51 52 void GrGLAttribArrayState::setFixedFunctionVertexArray(const GrGpuGL* gpu, 53 GrGLVertexBuffer* buffer, 54 GrGLint size, 55 GrGLenum type, 56 GrGLsizei stride, 57 GrGLvoid* offset) { 58 SkASSERT(gpu->glCaps().fixedFunctionSupport()); 59 AttribArrayState* array = &fFixedFunctionVertexArray; 60 if (!array->fEnableIsValid || !array->fEnabled) { 61 GR_GL_CALL(gpu->glInterface(), EnableClientState(GR_GL_VERTEX_ARRAY)); 62 array->fEnableIsValid = true; 63 array->fEnabled = true; 64 } 65 if (!array->fAttribPointerIsValid || 66 array->fVertexBufferID != buffer->bufferID() || 67 array->fSize != size || 68 array->fStride != stride || 69 array->fOffset != offset) { 70 71 buffer->bind(); 72 GR_GL_CALL(gpu->glInterface(), VertexPointer(size, 73 type, 74 stride, 75 offset)); 76 array->fAttribPointerIsValid = true; 77 array->fVertexBufferID = buffer->bufferID(); 78 array->fSize = size; 79 array->fStride = stride; 80 array->fOffset = offset; 81 } 82 } 83 84 void GrGLAttribArrayState::disableUnusedArrays(const GrGpuGL* gpu, uint64_t usedMask, bool usingFFVertexArray) { 85 int count = fAttribArrayStates.count(); 86 for (int i = 0; i < count; ++i) { 87 if (!(usedMask & 0x1)) { 88 if (!fAttribArrayStates[i].fEnableIsValid || fAttribArrayStates[i].fEnabled) { 89 GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i)); 90 fAttribArrayStates[i].fEnableIsValid = true; 91 fAttribArrayStates[i].fEnabled = false; 92 } 93 } else { 94 SkASSERT(fAttribArrayStates[i].fEnableIsValid && fAttribArrayStates[i].fEnabled); 95 } 96 // if the count is greater than 64 then this will become 0 and we will disable arrays 64+. 97 usedMask >>= 1; 98 } 99 100 // Deal with fixed-function vertex arrays. 101 if (gpu->glCaps().fixedFunctionSupport()) { 102 if (!usingFFVertexArray) { 103 if (!fFixedFunctionVertexArray.fEnableIsValid || fFixedFunctionVertexArray.fEnabled) { 104 GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_VERTEX_ARRAY)); 105 fFixedFunctionVertexArray.fEnableIsValid = true; 106 fFixedFunctionVertexArray.fEnabled = false; 107 } 108 } else { 109 SkASSERT(fFixedFunctionVertexArray.fEnableIsValid && fFixedFunctionVertexArray.fEnabled); 110 } 111 // When we use fixed function vertex processing we always use the vertex array and none of 112 // the other arrays. 113 if (!fUnusedFixedFunctionArraysDisabled) { 114 GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_NORMAL_ARRAY)); 115 GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_COLOR_ARRAY)); 116 GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_SECONDARY_COLOR_ARRAY)); 117 GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_INDEX_ARRAY)); 118 GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_EDGE_FLAG_ARRAY)); 119 for (int i = 0; i < gpu->glCaps().maxFixedFunctionTextureCoords(); ++i) { 120 GR_GL_CALL(gpu->glInterface(), ClientActiveTexture(GR_GL_TEXTURE0 + i)); 121 GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_TEXTURE_COORD_ARRAY)); 122 } 123 fUnusedFixedFunctionArraysDisabled = true; 124 } 125 } else { 126 SkASSERT(!usingFFVertexArray); 127 } 128 } 129 130 /////////////////////////////////////////////////////////////////////////////////////////////////// 131 132 GrGLVertexArray::GrGLVertexArray(GrGpuGL* gpu, GrGLint id, int attribCount) 133 : GrResource(gpu, false) 134 , fID(id) 135 , fAttribArrays(attribCount) 136 , fIndexBufferIDIsValid(false) { 137 } 138 139 void GrGLVertexArray::onAbandon() { 140 fID = 0; 141 INHERITED::onAbandon(); 142 } 143 144 void GrGLVertexArray::onRelease() { 145 if (0 != fID) { 146 GL_CALL(DeleteVertexArrays(1, &fID)); 147 GPUGL->notifyVertexArrayDelete(fID); 148 fID = 0; 149 } 150 INHERITED::onRelease(); 151 } 152 153 GrGLAttribArrayState* GrGLVertexArray::bind() { 154 if (0 == fID) { 155 return NULL; 156 } 157 GPUGL->bindVertexArray(fID); 158 return &fAttribArrays; 159 } 160 161 GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(const GrGLIndexBuffer* buffer) { 162 GrGLAttribArrayState* state = this->bind(); 163 if (NULL != state && NULL != buffer) { 164 GrGLuint bufferID = buffer->bufferID(); 165 if (!fIndexBufferIDIsValid || bufferID != fIndexBufferID) { 166 GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, bufferID)); 167 fIndexBufferIDIsValid = true; 168 fIndexBufferID = bufferID; 169 } 170 } 171 return state; 172 } 173 174 void GrGLVertexArray::notifyIndexBufferDelete(GrGLuint bufferID) { 175 if (fIndexBufferIDIsValid && bufferID == fIndexBufferID) { 176 fIndexBufferID = 0; 177 } 178 } 179 180 void GrGLVertexArray::invalidateCachedState() { 181 fAttribArrays.invalidate(); 182 fIndexBufferIDIsValid = false; 183 } 184