PrivateVertexBuffer::render () was enabling vertex attrib arrays as needed, but never disabling them, leaking GL state.
If one call to render () used a VBO for colors, and the next did not, the latter call would still have color VBO enabled. This may cause the GL to fetch color data needlessly or out-of-bounds (even if not really used in the shader). This patch fixes a theoretical problem. Signed-off-by: Pekka Paalanen <[email protected]> --- plugins/opengl/src/vertexbuffer.cpp | 43 ++++++++++++++++++++++++---------- 1 files changed, 30 insertions(+), 13 deletions(-) diff --git a/plugins/opengl/src/vertexbuffer.cpp b/plugins/opengl/src/vertexbuffer.cpp index 03e0a25..2255f7f 100644 --- a/plugins/opengl/src/vertexbuffer.cpp +++ b/plugins/opengl/src/vertexbuffer.cpp @@ -244,7 +244,10 @@ int PrivateVertexBuffer::render (const GLMatrix &projection, { GLfloat params[4] = {0, 0, 0, 0}; GLfloat attribs[3] = {1, 1, 1}; - GLint index = 0; + GLint positionIndex = -1; + GLint normalIndex = -1; + GLint colorIndex = -1; + GLint texCoordIndex[4] = {-1, -1, -1, -1}; if (program == NULL) { @@ -261,10 +264,10 @@ int PrivateVertexBuffer::render (const GLMatrix &projection, program->setUniform ("projection", projection); program->setUniform ("modelview", modelview); - index = program->attributeLocation ("position"); - (*GL::enableVertexAttribArray) (index); + positionIndex = program->attributeLocation ("position"); + (*GL::enableVertexAttribArray) (positionIndex); (*GL::bindBuffer) (GL_ARRAY_BUFFER, vertexBuffer); - (*GL::vertexAttribPointer) (index, 3, GL_FLOAT, GL_FALSE, 0, 0); + (*GL::vertexAttribPointer) (positionIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); //use default normal if (normalData.size () == 0) @@ -279,10 +282,10 @@ int PrivateVertexBuffer::render (const GLMatrix &projection, } else if (normalData.size () > 3) { - index = program->attributeLocation ("normal"); - (*GL::enableVertexAttribArray) (index); + normalIndex = program->attributeLocation ("normal"); + (*GL::enableVertexAttribArray) (normalIndex); (*GL::bindBuffer) (GL_ARRAY_BUFFER, normalBuffer); - (*GL::vertexAttribPointer) (index, 3, GL_FLOAT, GL_FALSE, 0, 0); + (*GL::vertexAttribPointer) (normalIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); } // special case a single color and apply it to the entire operation @@ -294,10 +297,10 @@ int PrivateVertexBuffer::render (const GLMatrix &projection, } else if (colorData.size () > 4) { - index = program->attributeLocation ("color"); - (*GL::enableVertexAttribArray) (index); + colorIndex = program->attributeLocation ("color"); + (*GL::enableVertexAttribArray) (colorIndex); (*GL::bindBuffer) (GL_ARRAY_BUFFER, colorBuffer); - (*GL::vertexAttribPointer) (index, 4, GL_FLOAT, GL_FALSE, 0, 0); + (*GL::vertexAttribPointer) (colorIndex, 4, GL_FLOAT, GL_FALSE, 0, 0); params[1] = 1.0; } @@ -309,11 +312,11 @@ int PrivateVertexBuffer::render (const GLMatrix &projection, char name[10]; snprintf (name, 10, "texCoord%d", i); - index = program->attributeLocation (name); + texCoordIndex[i] = program->attributeLocation (name); - (*GL::enableVertexAttribArray) (index); + (*GL::enableVertexAttribArray) (texCoordIndex[i]); (*GL::bindBuffer) (GL_ARRAY_BUFFER, textureBuffers[i]); - (*GL::vertexAttribPointer) (index, 2, GL_FLOAT, GL_FALSE, 0, 0); + (*GL::vertexAttribPointer) (texCoordIndex[i], 2, GL_FLOAT, GL_FALSE, 0, 0); snprintf (name, 9, "texture%d", i); program->setUniform (name, i); @@ -328,6 +331,20 @@ int PrivateVertexBuffer::render (const GLMatrix &projection, program->setUniform4f ("params", params[0], params[1], params[2], params[3]); glDrawArrays (primitiveType, 0, vertexData.size () / 3); + for (int i = 0; i < 4; ++i) + { + if (texCoordIndex[i] != -1) + (*GL::disableVertexAttribArray) (texCoordIndex[i]); + } + + if (colorIndex != -1) + (*GL::disableVertexAttribArray) (colorIndex); + + if (normalIndex != -1) + (*GL::disableVertexAttribArray) (normalIndex); + + (*GL::disableVertexAttribArray) (positionIndex); + GL::bindBuffer (GL_ARRAY_BUFFER, 0); program->unbind (); -- 1.7.3.4 _______________________________________________ dev mailing list [email protected] http://lists.compiz.org/mailman/listinfo/dev
