src/texture.c

changeset 88
6234b7ea48f3
parent 86
943bf9d7c6d6
child 89
e1f682a8a145
--- a/src/texture.c	Sat Apr 19 19:30:46 2025 +0200
+++ b/src/texture.c	Sun Apr 20 15:41:16 2025 +0200
@@ -25,11 +25,14 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "ascension/context.h"
 #include "ascension/texture.h"
 #include "ascension/error.h"
+#include "ascension/filesystem.h"
 
 #include <assert.h>
 #include <GL/glew.h>
+#include <SDL2/SDL_image.h>
 
 void asc_texture_bind(AscTexture const *tex, int uniform_location, int unit) {
     glActiveTexture(GL_TEXTURE0 + unit);
@@ -48,16 +51,62 @@
         asc_dprintf("Texture address: %"PRIxPTR, (uintptr_t) tex);
         return;
     }
+    tex->width = surface->w;
+    tex->height = surface->h;
     glBindTexture(tex->target,tex->tex_id);
     glPixelStorei(GL_UNPACK_ROW_LENGTH,
                   surface->pitch / surface->format->BytesPerPixel);
-    glTexImage2D(tex->target, 0, GL_RGBA,
+
+    // Determine the format and internal format based on the SDL surface format
+    GLint internal_format;
+    GLenum format;
+    switch (surface->format->format) {
+        case SDL_PIXELFORMAT_RGB24:
+            internal_format = GL_RGB8;
+            format = GL_RGB;
+            break;
+        case SDL_PIXELFORMAT_BGR24:
+            internal_format = GL_RGB8;
+            format = GL_BGR;
+            break;
+        case SDL_PIXELFORMAT_RGBA32:
+        case SDL_PIXELFORMAT_ABGR32:
+            internal_format = GL_RGBA8;
+            format = GL_RGBA;
+            break;
+        case SDL_PIXELFORMAT_ARGB32:
+        case SDL_PIXELFORMAT_BGRA32:
+            internal_format = GL_RGBA8;
+            format = GL_BGRA;
+            break;
+        default:
+            // TODO: add more output once asc_error allows format strings
+            asc_error("Unsupported pixel format.");
+            return;
+    }
+    glTexImage2D(tex->target, 0, internal_format,
                  surface->w, surface->h,
-                 0, GL_BGRA,
+                 0, format,
                  GL_UNSIGNED_BYTE, surface->pixels);
+    // TODO: replace catch all with proper error handling for this single call
     asc_error_catch_all_gl();
 }
 
+void asc_texture_from_file(AscTexture *tex, const char *name) {
+    cxmutstr filepath = asc_filesystem_combine_paths(cx_strcast(asc_context.texture_path), cx_str(name));
+    asc_dprintf("Load texture from %" CX_PRIstr, CX_SFMT(filepath));
+    SDL_Surface *image = IMG_Load(filepath.ptr);
+    cx_strfree(&filepath);
+    if (image == NULL) {
+        asc_error("Failed to load texture.");
+        asc_error(IMG_GetError());
+        return;
+    }
+    asc_texture_from_surface(tex, image);
+    asc_dprintf("Free temporary surface %"PRIxPTR, (uintptr_t) image);
+    SDL_FreeSurface(image);
+}
+
 void asc_texture_init(
         AscTexture *tex,
         enum asc_texture_target target,
@@ -65,7 +114,8 @@
         enum asc_texture_mag_filter mag_filter
 ) {
     static const GLenum texture_targets[] = {
-            GL_TEXTURE_RECTANGLE
+            GL_TEXTURE_RECTANGLE,
+            GL_TEXTURE_2D,
     };
     static const GLint texture_filters[] = {
             GL_NEAREST,

mercurial