| 29 #include "ascension/texture.h" |
29 #include "ascension/texture.h" |
| 30 #include "ascension/error.h" |
30 #include "ascension/error.h" |
| 31 #include "ascension/filesystem.h" |
31 #include "ascension/filesystem.h" |
| 32 |
32 |
| 33 #include <assert.h> |
33 #include <assert.h> |
| |
34 #include <cx/utils.h> |
| 34 #include <GL/glew.h> |
35 #include <GL/glew.h> |
| 35 #include <SDL2/SDL_image.h> |
36 #include <SDL2/SDL_image.h> |
| 36 |
37 |
| 37 void asc_texture_bind(AscTexture const *tex, int uniform_location, int unit) { |
38 void asc_texture_bind(AscTexture const *tex, int uniform_location, int unit) { |
| 38 glActiveTexture(GL_TEXTURE0 + unit); |
39 glActiveTexture(GL_TEXTURE0 + unit); |
| 44 glUniform1i(uniform_location, unit); |
45 glUniform1i(uniform_location, unit); |
| 45 asc_error_catch_all_gl(); |
46 asc_error_catch_all_gl(); |
| 46 } |
47 } |
| 47 |
48 |
| 48 void asc_texture_from_surface(AscTexture *tex, SDL_Surface const *surface) { |
49 void asc_texture_from_surface(AscTexture *tex, SDL_Surface const *surface) { |
| 49 if (asc_texture_uninitialized(tex)) { |
50 if (tex->tex_id == 0) { |
| 50 asc_error("Tried to use uninitialized texture."); |
51 asc_error("Tried to use uninitialized texture."); |
| 51 asc_dprintf("Texture address: %"PRIxPTR, (uintptr_t) tex); |
52 asc_dprintf("Texture address: %"PRIxPTR, (uintptr_t) tex); |
| 52 return; |
53 return; |
| 53 } |
54 } |
| 54 tex->width = surface->w; |
55 tex->width = surface->w; |
| 107 SDL_FreeSurface(image); |
108 SDL_FreeSurface(image); |
| 108 } |
109 } |
| 109 |
110 |
| 110 void asc_texture_init( |
111 void asc_texture_init( |
| 111 AscTexture *tex, |
112 AscTexture *tex, |
| |
113 unsigned count, |
| 112 enum asc_texture_target target, |
114 enum asc_texture_target target, |
| 113 enum asc_texture_min_filter min_filter, |
115 enum asc_texture_min_filter min_filter, |
| 114 enum asc_texture_mag_filter mag_filter |
116 enum asc_texture_mag_filter mag_filter |
| 115 ) { |
117 ) { |
| 116 static const GLenum texture_targets[] = { |
118 static const GLenum texture_targets[] = { |
| 126 GL_LINEAR_MIPMAP_LINEAR |
128 GL_LINEAR_MIPMAP_LINEAR |
| 127 }; |
129 }; |
| 128 assert(target < sizeof(texture_targets) / sizeof(GLenum)); |
130 assert(target < sizeof(texture_targets) / sizeof(GLenum)); |
| 129 assert(min_filter < sizeof(texture_filters) / sizeof(GLint)); |
131 assert(min_filter < sizeof(texture_filters) / sizeof(GLint)); |
| 130 assert(mag_filter < 2); // mag filter only supports nearest/linear |
132 assert(mag_filter < 2); // mag filter only supports nearest/linear |
| 131 tex->target = texture_targets[target]; |
133 |
| 132 glGenTextures(1, &tex->tex_id); |
134 GLuint textures[count]; |
| 133 glBindTexture(tex->target, tex->tex_id); |
135 glGenTextures(count, textures); |
| 134 glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, |
136 |
| 135 texture_filters[min_filter]); |
137 for (unsigned i = 0; i < count; ++i) { |
| 136 glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, |
138 memset(&tex[i], 0, sizeof(AscTexture)); |
| 137 texture_filters[mag_filter]); |
139 tex[i].tex_id = textures[i]; |
| 138 asc_dprintf("Initialized texture: %u", tex->tex_id); |
140 tex[i].target = texture_targets[target]; |
| |
141 glBindTexture(tex[i].target, tex[i].tex_id); |
| |
142 glTexParameteri(tex[i].target, GL_TEXTURE_MIN_FILTER, |
| |
143 texture_filters[min_filter]); |
| |
144 glTexParameteri(tex[i].target, GL_TEXTURE_MAG_FILTER, |
| |
145 texture_filters[mag_filter]); |
| |
146 asc_dprintf("Initialized texture: %u", tex[i].tex_id); |
| |
147 } |
| |
148 |
| |
149 // TODO: proper error handling for each gl call |
| 139 asc_error_catch_all_gl(); |
150 asc_error_catch_all_gl(); |
| 140 } |
151 } |
| 141 |
152 |
| 142 void asc_texture_destroy(AscTexture *tex) { |
153 void asc_texture_destroy(AscTexture *tex, unsigned count) { |
| 143 asc_dprintf("Destroy texture: %u", tex->tex_id); |
154 GLuint textures[count]; |
| 144 glDeleteTextures(1, &tex->tex_id); |
155 for (unsigned i = 0; i < count; ++i) { |
| |
156 if (tex[i].refcount > 0) { |
| |
157 // TODO: asc_wprintf() for warnings |
| |
158 asc_dprintf("Texture %u still in use by %u objects.", |
| |
159 tex[i].tex_id, tex[i].refcount); |
| |
160 } |
| |
161 asc_dprintf("Destroy texture: %u", tex[i].tex_id); |
| |
162 textures[i] = tex[i].tex_id; |
| |
163 memset(&tex[i], 0, sizeof(AscTexture)); |
| |
164 } |
| |
165 glDeleteTextures(count, textures); |
| 145 } |
166 } |