changeset 610:1b31169dc344

Move the passthrough shader to the Framebuffer class, since it isn’t used in the use_framebuffer_blit path.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Sun, 21 Dec 2014 18:52:18 +0100
parents 23b9418e4b2f
children a6a191e371c7
files pytouhou/ui/opengl/backend.pxd pytouhou/ui/opengl/backend.pyx pytouhou/ui/opengl/framebuffer.pxd pytouhou/ui/opengl/framebuffer.pyx pytouhou/ui/opengl/gamerenderer.pxd pytouhou/ui/opengl/gamerenderer.pyx
diffstat 6 files changed, 43 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/pytouhou/ui/opengl/backend.pxd
+++ b/pytouhou/ui/opengl/backend.pxd
@@ -12,4 +12,5 @@ cdef bint use_vao
 cdef bint use_framebuffer_blit
 cdef bint use_primitive_restart
 cdef bint use_pack_invert
+cdef bint use_scaled_rendering
 cdef bytes shader_header
--- a/pytouhou/ui/opengl/backend.pyx
+++ b/pytouhou/ui/opengl/backend.pyx
@@ -49,20 +49,21 @@ def init(options):
 cdef void discover_features() except *:
     '''Discover which features are supported by our context.'''
 
-    global use_debug_group, use_vao, use_primitive_restart, use_framebuffer_blit, use_pack_invert
+    global use_debug_group, use_vao, use_primitive_restart, use_framebuffer_blit, use_pack_invert, use_scaled_rendering
     global primitive_mode
     global shader_header
     global is_legacy
 
     version = epoxy_gl_version()
     is_desktop = epoxy_is_desktop_gl()
-    is_legacy = is_desktop and version < 20
+    is_legacy = is_legacy or (is_desktop and version < 20)
 
     use_debug_group = (is_desktop and version >= 43) or epoxy_has_gl_extension('GL_KHR_debug')
     use_vao = (is_desktop and version >= 30) or epoxy_has_gl_extension('GL_ARB_vertex_array_object')
     use_primitive_restart = (is_desktop and version >= 31)
     use_framebuffer_blit = (is_desktop and version >= 30)
     use_pack_invert = epoxy_has_gl_extension('GL_MESA_pack_invert')
+    use_scaled_rendering = not is_legacy  #TODO: try to use the EXT framebuffer extension.
 
     primitive_mode = GL_TRIANGLE_STRIP if use_primitive_restart else GL_TRIANGLES
 
@@ -96,6 +97,8 @@ def create_window(title, x, y, width, he
         sdl.gl_set_attribute(sdl.GL_DOUBLEBUFFER, double_buffer)
 
     flags = sdl.WINDOW_SHOWN | sdl.WINDOW_OPENGL
+
+    # Legacy contexts don’t support our required extensions for scaling.
     if not is_legacy:
         flags |= sdl.WINDOW_RESIZABLE
 
@@ -104,9 +107,9 @@ def create_window(title, x, y, width, he
 
     discover_features()
 
-    #TODO: legacy could support one of the framebuffer extensions for resize,
-    # but for now set the window to a fixed size.
-    if is_legacy and flags & sdl.WINDOW_RESIZABLE:
+    # If we can’t use scaling but have previously created a resizable window,
+    # recreate it unresizable.
+    if not use_scaled_rendering and flags & sdl.WINDOW_RESIZABLE:
         flags &= ~sdl.WINDOW_RESIZABLE
         window = Window(title, x, y, width, height, flags)
         window.gl_create_context()
--- a/pytouhou/ui/opengl/framebuffer.pxd
+++ b/pytouhou/ui/opengl/framebuffer.pxd
@@ -1,4 +1,6 @@
 from pytouhou.lib.opengl cimport GLuint
+from pytouhou.utils.matrix cimport Matrix
+from .shader cimport Shader
 
 cdef struct PassthroughVertex:
     short x, y
@@ -6,10 +8,17 @@ cdef struct PassthroughVertex:
 
 
 cdef class Framebuffer:
-    cdef GLuint fbo, texture, rbo, vbo, vao
+    cdef GLuint fbo, texture, rbo
+
+    # Used by the use_framebuffer_blit path
+    cdef int x, y, width, height
+
+    # Used by the other one.
+    cdef GLuint vbo, vao
+    cdef Shader shader
+    cdef Matrix *mvp
     cdef PassthroughVertex[4] buf
-    cdef int x, y, width, height
 
     cpdef bind(self)
     cdef void set_state(self) nogil
-    cdef void render(self, int x, int y, int width, int height) nogil
+    cdef void render(self, int x, int y, int width, int height) except *
--- a/pytouhou/ui/opengl/framebuffer.pyx
+++ b/pytouhou/ui/opengl/framebuffer.pyx
@@ -12,6 +12,8 @@
 ## GNU General Public License for more details.
 ##
 
+from libc.stdlib cimport free
+
 from pytouhou.lib.opengl cimport \
          (glPushDebugGroup, glPopDebugGroup, GL_DEBUG_SOURCE_APPLICATION,
           glGenTextures, glDeleteTextures, glBindTexture, glTexParameteri,
@@ -30,6 +32,9 @@ from pytouhou.lib.opengl cimport \
           glBlitFramebuffer, GL_READ_FRAMEBUFFER, glClear, GL_COLOR_BUFFER_BIT,
           GL_DEPTH_BUFFER_BIT, glViewport, glBlendFunc, GL_ONE, GL_ZERO)
 
+from pytouhou.utils.maths cimport ortho_2d
+
+from .shaders.eosd import PassthroughShader
 from .backend cimport use_debug_group, use_vao, use_framebuffer_blit
 
 cdef class Framebuffer:
@@ -77,13 +82,17 @@ cdef class Framebuffer:
             glBufferData(GL_ARRAY_BUFFER, sizeof(self.buf), self.buf, GL_STATIC_DRAW)
 
             # As a performance optimisation, if supported, store the rendering state into a vao.
-            if use_vao and not use_framebuffer_blit:
+            if use_vao:
                 glGenVertexArrays(1, &self.vao)
                 glBindVertexArray(self.vao)
                 self.set_state()
                 glBindVertexArray(0)
 
             glBindBuffer(GL_ARRAY_BUFFER, 0)
+
+            # And finally the shader we’ll use to display everything.
+            self.shader = PassthroughShader()
+            self.mvp = ortho_2d(0., float(width), float(height), 0.)
         else:
             self.x = x
             self.y = y
@@ -98,6 +107,8 @@ cdef class Framebuffer:
             glDeleteBuffers(1, &self.vbo)
             if use_vao:
                 glDeleteVertexArrays(1, &self.vao)
+            if self.mvp != NULL:
+                free(self.mvp)
         glDeleteTextures(1, &self.texture)
         glDeleteRenderbuffers(1, &self.rbo)
         glDeleteFramebuffers(1, &self.fbo)
@@ -114,7 +125,7 @@ cdef class Framebuffer:
         glVertexAttribPointer(1, 2, GL_FLOAT, False, sizeof(PassthroughVertex), <void*>4)
         glEnableVertexAttribArray(1)
 
-    cdef void render(self, int x, int y, int width, int height) nogil:
+    cdef void render(self, int x, int y, int width, int height) except *:
         if use_debug_group:
             glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "Framebuffer drawing")
 
@@ -127,6 +138,9 @@ cdef class Framebuffer:
                               x, y, x + width, y + height,
                               GL_COLOR_BUFFER_BIT, GL_LINEAR)
         else:
+            self.shader.bind()
+            self.shader.uniform_matrix('mvp', self.mvp)
+
             glViewport(x, y, width, height)
             glBlendFunc(GL_ONE, GL_ZERO)
 
--- a/pytouhou/ui/opengl/gamerenderer.pxd
+++ b/pytouhou/ui/opengl/gamerenderer.pxd
@@ -9,7 +9,7 @@ cdef class GameRenderer(Renderer):
     cdef Matrix *game_mvp
     cdef Matrix *interface_mvp
     cdef Matrix *proj
-    cdef Shader game_shader, background_shader, interface_shader, passthrough_shader
+    cdef Shader game_shader, background_shader, interface_shader
     cdef Framebuffer framebuffer
     cdef BackgroundRenderer background_renderer
     cdef object background
--- a/pytouhou/ui/opengl/gamerenderer.pyx
+++ b/pytouhou/ui/opengl/gamerenderer.pyx
@@ -28,9 +28,9 @@ from pytouhou.utils.matrix cimport mul, 
 from pytouhou.utils.maths cimport perspective, setup_camera, ortho_2d
 from pytouhou.game.text cimport NativeText, GlyphCollection
 from pytouhou.ui.window cimport Window
-from .shaders.eosd import GameShader, BackgroundShader, PassthroughShader
+from .shaders.eosd import GameShader, BackgroundShader
 from .renderer cimport Texture
-from .backend cimport is_legacy, use_debug_group, use_pack_invert
+from .backend cimport is_legacy, use_debug_group, use_pack_invert, use_scaled_rendering
 
 from collections import namedtuple
 Rect = namedtuple('Rect', 'x y w h')
@@ -45,8 +45,8 @@ cdef class GameRenderer(Renderer):
             self.game_shader = GameShader()
             self.background_shader = BackgroundShader()
             self.interface_shader = self.game_shader
-            self.passthrough_shader = PassthroughShader()
 
+        if use_scaled_rendering:
             self.framebuffer = Framebuffer(0, 0, window.width, window.height)
 
 
@@ -88,24 +88,16 @@ cdef class GameRenderer(Renderer):
 
 
     def render(self, Game game):
-        if not is_legacy:
+        if use_scaled_rendering:
             self.framebuffer.bind()
 
         self.render_game(game)
         self.render_text(game.texts)
         self.render_interface(game.interface, game.boss)
 
-        if not is_legacy:
-            if use_debug_group:
-                glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "Scaled rendering")
-
-            self.passthrough_shader.bind()
-            self.passthrough_shader.uniform_matrix('mvp', self.interface_mvp)
+        if use_scaled_rendering:
             self.framebuffer.render(self.x, self.y, self.width, self.height)
 
-            if use_debug_group:
-                glPopDebugGroup()
-
 
     def capture(self, filename, int width, int height):
         capture_memory = <char*>malloc(width * height * 3)