diff pytouhou/ui/opengl/renderer.pyx @ 558:94725968dabb

Use vertex array objects, to be compatible with OpenGL 3.1+ core profile.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Thu, 12 Dec 2013 13:47:17 +0100
parents d6d9a711253d
children 1be60813f7cb
line wrap: on
line diff
--- a/pytouhou/ui/opengl/renderer.pyx
+++ b/pytouhou/ui/opengl/renderer.pyx
@@ -32,12 +32,14 @@ from pytouhou.lib.opengl cimport \
           GL_DEPTH_COMPONENT, GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT,
           GL_FRAMEBUFFER_COMPLETE, glClear, GL_COLOR_BUFFER_BIT,
           GL_DEPTH_BUFFER_BIT, GLuint, glDeleteTextures,
-          GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW)
+          GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW, glGenVertexArrays,
+          glDeleteVertexArrays, glBindVertexArray)
 
 from pytouhou.lib.sdl import SDLError
 
 from pytouhou.game.element cimport Element
 from .sprite cimport get_sprite_rendering_data
+from .backend cimport use_vao
 
 from pytouhou.utils.helpers import get_logger
 
@@ -95,6 +97,10 @@ cdef class Renderer:
             glDeleteBuffers(1, &self.framebuffer_vbo)
             glDeleteBuffers(1, &self.vbo)
 
+            if use_vao:
+                glDeleteVertexArrays(1, &self.vao)
+                glDeleteVertexArrays(1, &self.framebuffer_vao)
+
 
     def __init__(self, resource_loader):
         # Only used in modern GL.
@@ -119,6 +125,43 @@ cdef class Renderer:
             glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(framebuffer_indices), framebuffer_indices, GL_STATIC_DRAW)
             glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
 
+            if use_vao:
+                glGenVertexArrays(1, &self.vao)
+                glBindVertexArray(self.vao)
+                self.set_state()
+
+                glGenVertexArrays(1, &self.framebuffer_vao)
+                glBindVertexArray(self.framebuffer_vao)
+                self.set_framebuffer_state()
+                glBindVertexArray(0)
+
+
+    cdef void set_state(self) nogil:
+        glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
+
+        #TODO: find a way to use offsetof() instead of those ugly substractions.
+        glVertexAttribPointer(0, 3, GL_SHORT, False, sizeof(Vertex), <void*>0)
+        glEnableVertexAttribArray(0)
+        glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(Vertex), <void*>8)
+        glEnableVertexAttribArray(1)
+        glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, True, sizeof(Vertex), <void*>16)
+        glEnableVertexAttribArray(2)
+
+        glBindBuffer(GL_ARRAY_BUFFER, 0)
+
+
+    cdef void set_framebuffer_state(self) nogil:
+        glBindBuffer(GL_ARRAY_BUFFER, self.framebuffer_vbo)
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.framebuffer_ibo)
+
+        #TODO: find a way to use offsetof() instead of those ugly hardcoded values.
+        glVertexAttribPointer(0, 2, GL_SHORT, False, sizeof(PassthroughVertex), <void*>0)
+        glEnableVertexAttribArray(0)
+        glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(PassthroughVertex), <void*>4)
+        glEnableVertexAttribArray(1)
+
+        glBindBuffer(GL_ARRAY_BUFFER, 0)
+
 
     cdef void render_elements(self, elements):
         cdef Element element
@@ -168,14 +211,12 @@ cdef class Renderer:
         else:
             glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
             glBufferData(GL_ARRAY_BUFFER, nb_vertices * sizeof(Vertex), &self.vertex_buffer[0], GL_DYNAMIC_DRAW)
+            glBindBuffer(GL_ARRAY_BUFFER, 0)
 
-            #TODO: find a way to use offsetof() instead of those ugly hardcoded values.
-            glVertexAttribPointer(0, 3, GL_SHORT, False, sizeof(Vertex), <void*>0)
-            glEnableVertexAttribArray(0)
-            glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(Vertex), <void*>8)
-            glEnableVertexAttribArray(1)
-            glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, True, sizeof(Vertex), <void*>16)
-            glEnableVertexAttribArray(2)
+            if use_vao:
+                glBindVertexArray(self.vao)
+            else:
+                self.set_state()
 
         # Don’t change the state when it’s not needed.
         previous_blendfunc = -1
@@ -200,8 +241,8 @@ cdef class Renderer:
 
         glBindTexture(GL_TEXTURE_2D, 0)
 
-        if not self.use_fixed_pipeline:
-            glBindBuffer(GL_ARRAY_BUFFER, 0)
+        if not self.use_fixed_pipeline and use_vao:
+            glBindVertexArray(0)
 
 
     cdef void render_quads(self, rects, colors, GLuint texture):
@@ -228,22 +269,17 @@ cdef class Renderer:
         else:
             glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
             glBufferData(GL_ARRAY_BUFFER, 4 * length * sizeof(Vertex), buf, GL_DYNAMIC_DRAW)
+            glBindBuffer(GL_ARRAY_BUFFER, 0)
 
-            #TODO: find a way to use offsetof() instead of those ugly hardcoded values.
-            glVertexAttribPointer(0, 3, GL_SHORT, False, sizeof(Vertex), <void*>0)
-            glEnableVertexAttribArray(0)
-            glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(Vertex), <void*>8)
-            glEnableVertexAttribArray(1)
-            glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, True, sizeof(Vertex), <void*>16)
-            glEnableVertexAttribArray(2)
+            if use_vao:
+                glBindVertexArray(self.vao)
+            else:
+                self.set_state()
 
         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
         glBindTexture(GL_TEXTURE_2D, texture)
         glDrawElements(GL_TRIANGLES, 6 * length, GL_UNSIGNED_SHORT, indices)
 
-        if not self.use_fixed_pipeline:
-            glBindBuffer(GL_ARRAY_BUFFER, 0)
-
 
     cdef void render_framebuffer(self, Framebuffer fb):
         cdef PassthroughVertex[4] buf
@@ -255,27 +291,28 @@ cdef class Renderer:
         glBlendFunc(GL_ONE, GL_ZERO)
         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
 
-        glBindBuffer(GL_ARRAY_BUFFER, self.framebuffer_vbo)
-        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.framebuffer_ibo)
-
-        #TODO: find a way to use offsetof() instead of those ugly hardcoded values.
-        glVertexAttribPointer(0, 2, GL_SHORT, False, sizeof(PassthroughVertex), <void*>0)
-        glEnableVertexAttribArray(0)
-        glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(PassthroughVertex), <void*>4)
-        glEnableVertexAttribArray(1)
+        if use_vao:
+            glBindVertexArray(self.framebuffer_vao)
+        else:
+            self.set_framebuffer_state()
 
         buf[0] = PassthroughVertex(fb.x, fb.y, 0, 1)
         buf[1] = PassthroughVertex(fb.x + fb.width, fb.y, 1, 1)
         buf[2] = PassthroughVertex(fb.x + fb.width, fb.y + fb.height, 1, 0)
         buf[3] = PassthroughVertex(fb.x, fb.y + fb.height, 0, 0)
-        glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(PassthroughVertex), buf, GL_DYNAMIC_DRAW)
+
+        glBindBuffer(GL_ARRAY_BUFFER, self.framebuffer_vbo)
+        glBufferData(GL_ARRAY_BUFFER, sizeof(buf), buf, GL_DYNAMIC_DRAW)
+        glBindBuffer(GL_ARRAY_BUFFER, 0)
 
         glBindTexture(GL_TEXTURE_2D, fb.texture)
         glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, NULL)
         glBindTexture(GL_TEXTURE_2D, 0)
 
-        glBindBuffer(GL_ARRAY_BUFFER, 0)
-        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
+        if use_vao:
+            glBindVertexArray(0)
+        else:
+            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
 
 
 cdef class Framebuffer: