# HG changeset patch # User Emmanuel Gil Peyrot # Date 1419184338 -3600 # Node ID 1b31169dc34436a9caef5a7a0998988db722657f # Parent 23b9418e4b2f54b3cb423ea0ef0bc98fcdf17428 Move the passthrough shader to the Framebuffer class, since it isn’t used in the use_framebuffer_blit path. diff --git a/pytouhou/ui/opengl/backend.pxd b/pytouhou/ui/opengl/backend.pxd --- 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 diff --git a/pytouhou/ui/opengl/backend.pyx b/pytouhou/ui/opengl/backend.pyx --- 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() diff --git a/pytouhou/ui/opengl/framebuffer.pxd b/pytouhou/ui/opengl/framebuffer.pxd --- 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 * diff --git a/pytouhou/ui/opengl/framebuffer.pyx b/pytouhou/ui/opengl/framebuffer.pyx --- 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), 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) diff --git a/pytouhou/ui/opengl/gamerenderer.pxd b/pytouhou/ui/opengl/gamerenderer.pxd --- 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 diff --git a/pytouhou/ui/opengl/gamerenderer.pyx b/pytouhou/ui/opengl/gamerenderer.pyx --- 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 = malloc(width * height * 3)