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

Reply via email to