# HG changeset patch # User Emmanuel Gil Peyrot # Date 1386352962 -3600 # Node ID b3193b43a86c0c224857ded605458c54304e71d7 # Parent 3d4410de78e1c74d2fee77d740ef32b6caf17fc7 Add an indirection layer for textures, to cope with drivers assigning them random names. diff --git a/pytouhou/ui/opengl/background.pxd b/pytouhou/ui/opengl/background.pxd --- 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 * diff --git a/pytouhou/ui/opengl/background.pyx b/pytouhou/ui/opengl/background.pyx --- 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 = realloc(vertex_buffer, nb_vertices * sizeof(Vertex)) 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 @@ -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 diff --git a/pytouhou/ui/opengl/renderer.pxd b/pytouhou/ui/opengl/renderer.pxd --- 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] diff --git a/pytouhou/ui/opengl/renderer.pyx b/pytouhou/ui/opengl/renderer.pyx --- 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 diff --git a/pytouhou/ui/opengl/sprite.pyx b/pytouhou/ui/opengl/sprite.pyx --- 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 = ((sprite.anm.texture).texture << 1) | sprite.blendfunc + key = ((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 diff --git a/pytouhou/ui/opengl/texture.pyx b/pytouhou/ui/opengl/texture.pyx --- 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 diff --git a/setup.py b/setup.py --- 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,