changeset 515:b3193b43a86c

Add an indirection layer for textures, to cope with drivers assigning them random names.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Fri, 06 Dec 2013 19:02:42 +0100
parents 3d4410de78e1
children 577c3a88fb67
files pytouhou/ui/opengl/background.pxd pytouhou/ui/opengl/background.pyx pytouhou/ui/opengl/gamerenderer.pyx pytouhou/ui/opengl/renderer.pxd pytouhou/ui/opengl/renderer.pyx pytouhou/ui/opengl/sprite.pyx pytouhou/ui/opengl/texture.pyx setup.py
diffstat 8 files changed, 36 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/pytouhou/ui/opengl/background.pxd
+++ b/pytouhou/ui/opengl/background.pxd
@@ -1,4 +1,5 @@
 from pytouhou.lib.opengl cimport GLuint
+from .renderer cimport Renderer
 
 cdef struct Vertex:
     float x, y, z
@@ -14,4 +15,4 @@ cdef class BackgroundRenderer:
     cdef object background
 
     cdef void render_background(self) except *
-    cdef void load(self, background) except *
+    cdef void load(self, background, Renderer renderer) except *
--- a/pytouhou/ui/opengl/background.pyx
+++ b/pytouhou/ui/opengl/background.pyx
@@ -68,7 +68,7 @@ cdef class BackgroundRenderer:
             glBindBuffer(GL_ARRAY_BUFFER, 0)
 
 
-    cdef void load(self, background):
+    cdef void load(self, background, Renderer renderer):
         cdef float ox, oy, oz, ox2, oy2, oz2
         cdef unsigned short nb_vertices = 0
         cdef Vertex* vertex_buffer
@@ -92,7 +92,7 @@ cdef class BackgroundRenderer:
 
                 nb_vertices += 4
 
-        self.texture = key >> 1
+        self.texture = renderer.textures[key >> 1]
         self.blendfunc = key & 1
         self.nb_vertices = nb_vertices
         self.vertex_buffer = <Vertex*> realloc(vertex_buffer, nb_vertices * sizeof(Vertex))
--- a/pytouhou/ui/opengl/gamerenderer.pyx
+++ b/pytouhou/ui/opengl/gamerenderer.pyx
@@ -59,7 +59,7 @@ cdef class GameRenderer(Renderer):
     def load_background(self, background):
         if background is not None:
             self.background_renderer = BackgroundRenderer(self.use_fixed_pipeline)
-            self.background_renderer.load(background)
+            self.background_renderer.load(background, self)
         else:
             self.background_renderer = None
 
--- a/pytouhou/ui/opengl/renderer.pxd
+++ b/pytouhou/ui/opengl/renderer.pxd
@@ -14,7 +14,8 @@ cdef struct PassthroughVertex:
 
 
 cdef class Texture:
-    cdef GLuint texture
+    cdef long key
+    cdef GLuint texture, *pointer
     cdef unsigned short indices[2][65536]
 
 
@@ -27,6 +28,7 @@ cdef class Renderer:
 
     cdef bint use_fixed_pipeline #XXX
 
+    cdef GLuint textures[MAX_TEXTURES]
     cdef unsigned short *indices[MAX_TEXTURES][2]
     cdef unsigned short last_indices[2 * MAX_TEXTURES]
     cdef PyObject *elements[640*3]
--- a/pytouhou/ui/opengl/renderer.pyx
+++ b/pytouhou/ui/opengl/renderer.pyx
@@ -46,11 +46,27 @@ logger = get_logger(__name__)
 cdef class Texture:
     def __cinit__(self, GLuint texture, Renderer renderer):
         self.texture = texture
+
+        # Find an unused key in the textures array.
+        for key in xrange(MAX_TEXTURES):
+            if renderer.textures[key] == 0:
+                break
+        else:
+            raise MemoryError('Too many textures currently loaded, consider increasing MAX_TEXTURES (currently %d).' % MAX_TEXTURES)
+
+        self.key = key
+        self.pointer = &renderer.textures[key]
+        self.pointer[0] = texture
         for i in xrange(2):
-            renderer.indices[texture][i] = self.indices[i]
+            renderer.indices[key][i] = self.indices[i]
 
     def __dealloc__(self):
-        glDeleteTextures(1, &self.texture)
+        if self.texture:
+            glDeleteTextures(1, &self.texture)
+        if self.pointer != NULL:
+            self.pointer[0] = 0
+        # The dangling pointers in renderer.indices doesn’t matter, since we
+        # won’t use them if no texture is loaded in that slot.
 
 
 cdef long find_objects(Renderer self, object elements) except -1:
@@ -166,7 +182,7 @@ cdef class Renderer:
             if blendfunc != previous_blendfunc:
                 glBlendFunc(GL_SRC_ALPHA, (GL_ONE_MINUS_SRC_ALPHA, GL_ONE)[blendfunc])
             if texture != previous_texture:
-                glBindTexture(GL_TEXTURE_2D, texture)
+                glBindTexture(GL_TEXTURE_2D, self.textures[texture])
             glDrawElements(GL_TRIANGLES, nb_indices, GL_UNSIGNED_SHORT, self.indices[texture][blendfunc])
 
             previous_blendfunc = blendfunc
--- a/pytouhou/ui/opengl/sprite.pyx
+++ b/pytouhou/ui/opengl/sprite.pyx
@@ -65,7 +65,7 @@ cpdef tuple get_sprite_rendering_data(Sp
            ty * y_1 + toy,
            (ty + th) * y_1 + toy)
 
-    key = ((<Texture>sprite.anm.texture).texture << 1) | sprite.blendfunc
+    key = ((<Texture>sprite.anm.texture).key << 1) | sprite.blendfunc
     r, g, b = sprite.color
     values = tuple([x for x in vertmat.data[:12]]), uvs, (r, g, b, sprite.alpha)
     sprite._rendering_data = key, values
--- a/pytouhou/ui/opengl/texture.pyx
+++ b/pytouhou/ui/opengl/texture.pyx
@@ -94,26 +94,27 @@ cdef decode_png(loader, first_name, seco
     return Texture(width, height, -4, new_image.pixels)
 
 
-cdef GLuint load_texture(thtx):
+cdef GLuint load_texture(thtx) except? 65535:
     cdef GLuint texture
+    cdef long fmt = thtx.fmt
 
-    if thtx.fmt == 1:
+    if fmt == 1:
         format_ = GL_BGRA
         type_ = GL_UNSIGNED_BYTE
         composants = GL_RGBA
-    elif thtx.fmt == 3:
+    elif fmt == 3:
         format_ = GL_RGB
         type_ = GL_UNSIGNED_SHORT_5_6_5
         composants = GL_RGB
-    elif thtx.fmt == 5:
+    elif fmt == 5:
         format_ = GL_BGRA
         type_ = GL_UNSIGNED_SHORT_4_4_4_4_REV
         composants = GL_RGBA
-    elif thtx.fmt == 7:
+    elif fmt == 7:
         format_ = GL_LUMINANCE
         type_ = GL_UNSIGNED_BYTE
         composants = GL_LUMINANCE
-    elif thtx.fmt == -4: #XXX: non-standard
+    elif fmt == -4: #XXX: non-standard
         format_ = GL_RGBA
         type_ = GL_UNSIGNED_BYTE
         composants = GL_RGBA
--- a/setup.py
+++ b/setup.py
@@ -115,7 +115,7 @@ setup(name='PyTouhou',
       ext_modules=cythonize(extensions, nthreads=4,
                             compiler_directives={'infer_types': True,
                                                  'infer_types.verbose': True},
-                            compile_time_env={'MAX_TEXTURES': 1024,
+                            compile_time_env={'MAX_TEXTURES': 128,
                                               'MAX_ELEMENTS': 640 * 4 * 3,
                                               'MAX_CHANNELS': 26,
                                               'USE_OPENGL': use_opengl,