| 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, |