comparison 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
comparison
equal deleted inserted replaced
425:1104dc2553ee 426:5d7bb2fd74f7
14 14
15 from pytouhou.lib.opengl cimport \ 15 from pytouhou.lib.opengl cimport \
16 (glTexParameteri, GL_TEXTURE_MIN_FILTER, GL_TEXTURE_MAG_FILTER, 16 (glTexParameteri, GL_TEXTURE_MIN_FILTER, GL_TEXTURE_MAG_FILTER,
17 GL_LINEAR, GL_BGRA, GL_RGBA, GL_RGB, GL_LUMINANCE, GL_UNSIGNED_BYTE, 17 GL_LINEAR, GL_BGRA, GL_RGBA, GL_RGB, GL_LUMINANCE, GL_UNSIGNED_BYTE,
18 GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_4_4_4_4_REV, 18 GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_4_4_4_4_REV,
19 glGenTextures, glBindTexture, glTexImage2D, GL_TEXTURE_2D, GLuint) 19 glGenTextures, glBindTexture, glTexImage2D, GL_TEXTURE_2D, GLuint,
20 glDeleteTextures)
20 21
21 from pytouhou.lib.sdl import load_png, create_rgb_surface 22 from pytouhou.lib.sdl import load_png, create_rgb_surface
22 from pytouhou.formats.thtx import Texture #TODO: perhaps define that elsewhere? 23 from pytouhou.formats.thtx import Texture #TODO: perhaps define that elsewhere?
23 24
24 import os 25 import os
25 26
26 27
27 cdef class TextureManager: 28 class TextureId(int):
29 def __del__(self):
30 cdef GLuint texture = self
31 glDeleteTextures(1, &texture)
32
33
34 class TextureManager(object):
28 def __init__(self, loader=None): 35 def __init__(self, loader=None):
29 self.loader = loader 36 self.loader = loader
30 self.textures = {}
31 37
32 38
33 def __getitem__(self, key): 39 def load(self, anm_list):
34 if not key in self.textures: 40 for anm in anm_list:
35 self.textures[key] = self.load_texture(key) 41 if not hasattr(anm, 'texture'):
36 return self.textures[key] 42 texture = decode_png(self.loader, anm.first_name, anm.secondary_name)
43 anm.texture = load_texture(texture)
37 44
38 45
39 def preload(self, anm_wrapper): 46 cdef decode_png(loader, first_name, secondary_name):
40 for anm in anm_wrapper: 47 image_file = load_png(loader.get_file(os.path.basename(first_name)))
41 anm.texture = self.load_png_texture(anm.first_name, anm.secondary_name) 48 width, height = image_file.width, image_file.height
49
50 # Support only 32 bits RGBA. Paletted surfaces are awful to work with.
51 #TODO: verify it doesn’t blow up on big-endian systems.
52 new_image = create_rgb_surface(width, height, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000)
53 new_image.blit(image_file)
54
55 if secondary_name:
56 alpha_file = load_png(loader.get_file(os.path.basename(secondary_name)))
57 assert (width == alpha_file.width and height == alpha_file.height)
58
59 new_alpha_file = create_rgb_surface(width, height, 24)
60 new_alpha_file.blit(alpha_file)
61
62 new_image.set_alpha(new_alpha_file)
63
64 return Texture(width, height, -4, new_image.pixels)
42 65
43 66
44 def load_png_texture(self, first_name, secondary_name): 67 cdef load_texture(thtx):
45 image_file = load_png(self.loader.get_file(os.path.basename(first_name))) 68 cdef GLuint texture
46 width, height = image_file.width, image_file.height
47 69
48 # Support only 32 bits RGBA. Paletted surfaces are awful to work with. 70 if thtx.fmt == 1:
49 #TODO: verify it doesn’t blow up on big-endian systems. 71 format_ = GL_BGRA
50 new_image = create_rgb_surface(width, height, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000) 72 type_ = GL_UNSIGNED_BYTE
51 new_image.blit(image_file) 73 composants = GL_RGBA
74 elif thtx.fmt == 3:
75 format_ = GL_RGB
76 type_ = GL_UNSIGNED_SHORT_5_6_5
77 composants = GL_RGB
78 elif thtx.fmt == 5:
79 format_ = GL_BGRA
80 type_ = GL_UNSIGNED_SHORT_4_4_4_4_REV
81 composants = GL_RGBA
82 elif thtx.fmt == 7:
83 format_ = GL_LUMINANCE
84 type_ = GL_UNSIGNED_BYTE
85 composants = GL_LUMINANCE
86 elif thtx.fmt == -4: #XXX: non-standard
87 format_ = GL_RGBA
88 type_ = GL_UNSIGNED_BYTE
89 composants = GL_RGBA
90 else:
91 raise Exception('Unknown texture type')
52 92
53 if secondary_name: 93 glGenTextures(1, &texture)
54 alpha_file = load_png(self.loader.get_file(os.path.basename(secondary_name))) 94 glBindTexture(GL_TEXTURE_2D, texture)
55 assert (width == alpha_file.width and 95 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
56 height == alpha_file.height) 96 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
57 97
58 new_alpha_file = create_rgb_surface(width, height, 24) 98 glTexImage2D(GL_TEXTURE_2D, 0,
59 new_alpha_file.blit(alpha_file) 99 composants,
100 thtx.width, thtx.height,
101 0,
102 format_, type_,
103 <char*>thtx.data)
60 104
61 new_image.set_alpha(new_alpha_file) 105 return TextureId(texture)
62
63 return Texture(width, height, -4, new_image.pixels)
64
65
66 def load_texture(self, key):
67 cdef GLuint id_
68
69 if not isinstance(key, Texture):
70 first_name, secondary_name = key
71 key = self.load_png_texture(first_name, secondary_name)
72
73 if key.fmt == 1:
74 format_ = GL_BGRA
75 type_ = GL_UNSIGNED_BYTE
76 composants = GL_RGBA
77 elif key.fmt == 3:
78 format_ = GL_RGB
79 type_ = GL_UNSIGNED_SHORT_5_6_5
80 composants = GL_RGB
81 elif key.fmt == 5:
82 format_ = GL_BGRA
83 type_ = GL_UNSIGNED_SHORT_4_4_4_4_REV
84 composants = GL_RGBA
85 elif key.fmt == 7:
86 format_ = GL_LUMINANCE
87 type_ = GL_UNSIGNED_BYTE
88 composants = GL_LUMINANCE
89 elif key.fmt == -4: #XXX: non-standard
90 format_ = GL_RGBA
91 type_ = GL_UNSIGNED_BYTE
92 composants = GL_RGBA
93 else:
94 raise Exception('Unknown texture type')
95
96 glGenTextures(1, &id_)
97 glBindTexture(GL_TEXTURE_2D, id_)
98 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
99 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
100
101 glTexImage2D(GL_TEXTURE_2D, 0,
102 composants,
103 key.width, key.height,
104 0,
105 format_, type_,
106 <char*>key.data)
107
108 return id_