diff pytouhou/ui/texture.pyx @ 426:5d7bb2fd74f7

Never keep texture on the host when it has been uploaded, and prevent them from being decoded again.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Tue, 16 Jul 2013 21:11:35 +0200
parents d8630c086926
children 40d5f3083ebc
line wrap: on
line diff
--- a/pytouhou/ui/texture.pyx
+++ b/pytouhou/ui/texture.pyx
@@ -16,7 +16,8 @@ from pytouhou.lib.opengl cimport \
          (glTexParameteri, GL_TEXTURE_MIN_FILTER, GL_TEXTURE_MAG_FILTER,
           GL_LINEAR, GL_BGRA, GL_RGBA, GL_RGB, GL_LUMINANCE, GL_UNSIGNED_BYTE,
           GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_4_4_4_4_REV,
-          glGenTextures, glBindTexture, glTexImage2D, GL_TEXTURE_2D, GLuint)
+          glGenTextures, glBindTexture, glTexImage2D, GL_TEXTURE_2D, GLuint,
+          glDeleteTextures)
 
 from pytouhou.lib.sdl import load_png, create_rgb_surface
 from pytouhou.formats.thtx import Texture #TODO: perhaps define that elsewhere?
@@ -24,85 +25,81 @@ from pytouhou.formats.thtx import Textur
 import os
 
 
-cdef class TextureManager:
-    def __init__(self, loader=None):
-        self.loader = loader
-        self.textures = {}
+class TextureId(int):
+    def __del__(self):
+        cdef GLuint texture = self
+        glDeleteTextures(1, &texture)
 
 
-    def __getitem__(self, key):
-        if not key in self.textures:
-            self.textures[key] = self.load_texture(key)
-        return self.textures[key]
+class TextureManager(object):
+    def __init__(self, loader=None):
+        self.loader = loader
 
 
-    def preload(self, anm_wrapper):
-        for anm in anm_wrapper:
-            anm.texture = self.load_png_texture(anm.first_name, anm.secondary_name)
+    def load(self, anm_list):
+        for anm in anm_list:
+            if not hasattr(anm, 'texture'):
+                texture = decode_png(self.loader, anm.first_name, anm.secondary_name)
+                anm.texture = load_texture(texture)
 
 
-    def load_png_texture(self, first_name, secondary_name):
-        image_file = load_png(self.loader.get_file(os.path.basename(first_name)))
-        width, height = image_file.width, image_file.height
+cdef decode_png(loader, first_name, secondary_name):
+    image_file = load_png(loader.get_file(os.path.basename(first_name)))
+    width, height = image_file.width, image_file.height
 
-        # Support only 32 bits RGBA. Paletted surfaces are awful to work with.
-        #TODO: verify it doesn’t blow up on big-endian systems.
-        new_image = create_rgb_surface(width, height, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000)
-        new_image.blit(image_file)
+    # Support only 32 bits RGBA. Paletted surfaces are awful to work with.
+    #TODO: verify it doesn’t blow up on big-endian systems.
+    new_image = create_rgb_surface(width, height, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000)
+    new_image.blit(image_file)
 
-        if secondary_name:
-            alpha_file = load_png(self.loader.get_file(os.path.basename(secondary_name)))
-            assert (width == alpha_file.width and
-                    height == alpha_file.height)
+    if secondary_name:
+        alpha_file = load_png(loader.get_file(os.path.basename(secondary_name)))
+        assert (width == alpha_file.width and height == alpha_file.height)
 
-            new_alpha_file = create_rgb_surface(width, height, 24)
-            new_alpha_file.blit(alpha_file)
+        new_alpha_file = create_rgb_surface(width, height, 24)
+        new_alpha_file.blit(alpha_file)
 
-            new_image.set_alpha(new_alpha_file)
+        new_image.set_alpha(new_alpha_file)
 
-        return Texture(width, height, -4, new_image.pixels)
+    return Texture(width, height, -4, new_image.pixels)
 
 
-    def load_texture(self, key):
-        cdef GLuint id_
-
-        if not isinstance(key, Texture):
-            first_name, secondary_name = key
-            key = self.load_png_texture(first_name, secondary_name)
+cdef load_texture(thtx):
+    cdef GLuint texture
 
-        if key.fmt == 1:
-            format_ = GL_BGRA
-            type_ = GL_UNSIGNED_BYTE
-            composants = GL_RGBA
-        elif key.fmt == 3:
-            format_ = GL_RGB
-            type_ = GL_UNSIGNED_SHORT_5_6_5
-            composants = GL_RGB
-        elif key.fmt == 5:
-            format_ = GL_BGRA
-            type_ = GL_UNSIGNED_SHORT_4_4_4_4_REV
-            composants = GL_RGBA
-        elif key.fmt == 7:
-            format_ = GL_LUMINANCE
-            type_ = GL_UNSIGNED_BYTE
-            composants = GL_LUMINANCE
-        elif key.fmt == -4: #XXX: non-standard
-            format_ = GL_RGBA
-            type_ = GL_UNSIGNED_BYTE
-            composants = GL_RGBA
-        else:
-            raise Exception('Unknown texture type')
+    if thtx.fmt == 1:
+        format_ = GL_BGRA
+        type_ = GL_UNSIGNED_BYTE
+        composants = GL_RGBA
+    elif thtx.fmt == 3:
+        format_ = GL_RGB
+        type_ = GL_UNSIGNED_SHORT_5_6_5
+        composants = GL_RGB
+    elif thtx.fmt == 5:
+        format_ = GL_BGRA
+        type_ = GL_UNSIGNED_SHORT_4_4_4_4_REV
+        composants = GL_RGBA
+    elif thtx.fmt == 7:
+        format_ = GL_LUMINANCE
+        type_ = GL_UNSIGNED_BYTE
+        composants = GL_LUMINANCE
+    elif thtx.fmt == -4: #XXX: non-standard
+        format_ = GL_RGBA
+        type_ = GL_UNSIGNED_BYTE
+        composants = GL_RGBA
+    else:
+        raise Exception('Unknown texture type')
 
-        glGenTextures(1, &id_)
-        glBindTexture(GL_TEXTURE_2D, id_)
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
+    glGenTextures(1, &texture)
+    glBindTexture(GL_TEXTURE_2D, texture)
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
 
-        glTexImage2D(GL_TEXTURE_2D, 0,
-                     composants,
-                     key.width, key.height,
-                     0,
-                     format_, type_,
-                     <char*>key.data)
+    glTexImage2D(GL_TEXTURE_2D, 0,
+                 composants,
+                 thtx.width, thtx.height,
+                 0,
+                 format_, type_,
+                 <char*>thtx.data)
 
-        return id_
+    return TextureId(texture)