23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
25 * POSSIBILITY OF SUCH DAMAGE. |
25 * POSSIBILITY OF SUCH DAMAGE. |
26 */ |
26 */ |
27 |
27 |
|
28 #include "ascension/context.h" |
28 #include "ascension/texture.h" |
29 #include "ascension/texture.h" |
29 #include "ascension/error.h" |
30 #include "ascension/error.h" |
|
31 #include "ascension/filesystem.h" |
30 |
32 |
31 #include <assert.h> |
33 #include <assert.h> |
32 #include <GL/glew.h> |
34 #include <GL/glew.h> |
|
35 #include <SDL2/SDL_image.h> |
33 |
36 |
34 void asc_texture_bind(AscTexture const *tex, int uniform_location, int unit) { |
37 void asc_texture_bind(AscTexture const *tex, int uniform_location, int unit) { |
35 glActiveTexture(GL_TEXTURE0 + unit); |
38 glActiveTexture(GL_TEXTURE0 + unit); |
36 GLenum error = glGetError(); |
39 GLenum error = glGetError(); |
37 if (error == GL_INVALID_ENUM) { |
40 if (error == GL_INVALID_ENUM) { |
46 if (asc_texture_uninitialized(tex)) { |
49 if (asc_texture_uninitialized(tex)) { |
47 asc_error("Tried to use uninitialized texture."); |
50 asc_error("Tried to use uninitialized texture."); |
48 asc_dprintf("Texture address: %"PRIxPTR, (uintptr_t) tex); |
51 asc_dprintf("Texture address: %"PRIxPTR, (uintptr_t) tex); |
49 return; |
52 return; |
50 } |
53 } |
|
54 tex->width = surface->w; |
|
55 tex->height = surface->h; |
51 glBindTexture(tex->target,tex->tex_id); |
56 glBindTexture(tex->target,tex->tex_id); |
52 glPixelStorei(GL_UNPACK_ROW_LENGTH, |
57 glPixelStorei(GL_UNPACK_ROW_LENGTH, |
53 surface->pitch / surface->format->BytesPerPixel); |
58 surface->pitch / surface->format->BytesPerPixel); |
54 glTexImage2D(tex->target, 0, GL_RGBA, |
59 |
|
60 // Determine the format and internal format based on the SDL surface format |
|
61 GLint internal_format; |
|
62 GLenum format; |
|
63 switch (surface->format->format) { |
|
64 case SDL_PIXELFORMAT_RGB24: |
|
65 internal_format = GL_RGB8; |
|
66 format = GL_RGB; |
|
67 break; |
|
68 case SDL_PIXELFORMAT_BGR24: |
|
69 internal_format = GL_RGB8; |
|
70 format = GL_BGR; |
|
71 break; |
|
72 case SDL_PIXELFORMAT_RGBA32: |
|
73 case SDL_PIXELFORMAT_ABGR32: |
|
74 internal_format = GL_RGBA8; |
|
75 format = GL_RGBA; |
|
76 break; |
|
77 case SDL_PIXELFORMAT_ARGB32: |
|
78 case SDL_PIXELFORMAT_BGRA32: |
|
79 internal_format = GL_RGBA8; |
|
80 format = GL_BGRA; |
|
81 break; |
|
82 default: |
|
83 // TODO: add more output once asc_error allows format strings |
|
84 asc_error("Unsupported pixel format."); |
|
85 return; |
|
86 } |
|
87 glTexImage2D(tex->target, 0, internal_format, |
55 surface->w, surface->h, |
88 surface->w, surface->h, |
56 0, GL_BGRA, |
89 0, format, |
57 GL_UNSIGNED_BYTE, surface->pixels); |
90 GL_UNSIGNED_BYTE, surface->pixels); |
|
91 // TODO: replace catch all with proper error handling for this single call |
58 asc_error_catch_all_gl(); |
92 asc_error_catch_all_gl(); |
|
93 } |
|
94 |
|
95 void asc_texture_from_file(AscTexture *tex, const char *name) { |
|
96 cxmutstr filepath = asc_filesystem_combine_paths(cx_strcast(asc_context.texture_path), cx_str(name)); |
|
97 asc_dprintf("Load texture from %" CX_PRIstr, CX_SFMT(filepath)); |
|
98 SDL_Surface *image = IMG_Load(filepath.ptr); |
|
99 cx_strfree(&filepath); |
|
100 if (image == NULL) { |
|
101 asc_error("Failed to load texture."); |
|
102 asc_error(IMG_GetError()); |
|
103 return; |
|
104 } |
|
105 asc_texture_from_surface(tex, image); |
|
106 asc_dprintf("Free temporary surface %"PRIxPTR, (uintptr_t) image); |
|
107 SDL_FreeSurface(image); |
59 } |
108 } |
60 |
109 |
61 void asc_texture_init( |
110 void asc_texture_init( |
62 AscTexture *tex, |
111 AscTexture *tex, |
63 enum asc_texture_target target, |
112 enum asc_texture_target target, |
64 enum asc_texture_min_filter min_filter, |
113 enum asc_texture_min_filter min_filter, |
65 enum asc_texture_mag_filter mag_filter |
114 enum asc_texture_mag_filter mag_filter |
66 ) { |
115 ) { |
67 static const GLenum texture_targets[] = { |
116 static const GLenum texture_targets[] = { |
68 GL_TEXTURE_RECTANGLE |
117 GL_TEXTURE_RECTANGLE, |
|
118 GL_TEXTURE_2D, |
69 }; |
119 }; |
70 static const GLint texture_filters[] = { |
120 static const GLint texture_filters[] = { |
71 GL_NEAREST, |
121 GL_NEAREST, |
72 GL_LINEAR, |
122 GL_LINEAR, |
73 GL_NEAREST_MIPMAP_NEAREST, |
123 GL_NEAREST_MIPMAP_NEAREST, |