From a3c6774f211ee765f910df76837548bdadd4e959 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 15 Nov 2021 08:20:13 +0100 Subject: Add dynamic font atlas creation (not finished) --- src/graphics/texture.c | 117 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 101 insertions(+), 16 deletions(-) (limited to 'src/graphics/texture.c') diff --git a/src/graphics/texture.c b/src/graphics/texture.c index f6549f1..2387fa7 100644 --- a/src/graphics/texture.c +++ b/src/graphics/texture.c @@ -3,7 +3,7 @@ #include "../../include/mgl/mgl.h" #include -/* TODO: Check for glTexImage2D failure */ +/* TODO: Check for glTexImage2D/glTexSubImage2D failure */ static int mgl_texture_format_to_opengl_format(mgl_texture_format format) { switch(format) { @@ -49,11 +49,31 @@ static mgl_texture_format mgl_image_format_to_mgl_texture_format(mgl_image_forma return 0; } -int mgl_texture_load_from_file(mgl_texture *self, const char *filepath, mgl_texture_load_options *load_options) { +int mgl_texture_init(mgl_texture *self) { self->id = 0; self->width = 0; self->height = 0; - + self->format = 0; + self->max_width = 0; + self->max_height = 0; + self->pixel_coordinates = false; + + mgl_context *context = mgl_get_context(); + context->gl.glGenTextures(1, &self->id); + if(self->id == 0) { + fprintf(stderr, "Error: failed to init texture (glGenTextures failed)\n"); + return -1; + } + + int max_texture_size = 0; + context->gl.glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); + self->max_width = max_texture_size; + self->max_height = max_texture_size; + + return 0; +} + +int mgl_texture_load_from_file(mgl_texture *self, const char *filepath, mgl_texture_load_options *load_options) { mgl_image image; if(mgl_image_load_from_file(&image, filepath) != 0) return -1; @@ -68,21 +88,22 @@ int mgl_texture_load_from_image(mgl_texture *self, const mgl_image *image, mgl_t } int mgl_texture_load_from_memory(mgl_texture *self, const unsigned char *data, int width, int height, mgl_image_format format, mgl_texture_load_options *load_options) { - self->id = 0; + if(width < 0 || height < 0) + return -1; + + if(width > self->max_width || height > self->max_height) + return -1; + self->width = width; self->height = height; self->format = mgl_image_format_to_mgl_texture_format(format); + self->pixel_coordinates = load_options ? load_options->pixel_coordinates : false; - mgl_context *context = mgl_get_context(); - context->gl.glGenTextures(1, &self->id); - if(self->id == 0) { - fprintf(stderr, "Error: failed to load image from memory (glGenTextures failed)\n"); - mgl_texture_unload(self); - return -1; - } - - const int opengl_texture_format = load_options && load_options->compressed ? mgl_texture_format_to_compressed_opengl_format(self->format) : mgl_texture_format_to_opengl_format(self->format); + int opengl_texture_format = mgl_texture_format_to_opengl_format(self->format); + if(load_options && load_options->compressed) + opengl_texture_format = mgl_texture_format_to_compressed_opengl_format(self->format); + mgl_context *context = mgl_get_context(); context->gl.glBindTexture(GL_TEXTURE_2D, self->id); context->gl.glTexImage2D(GL_TEXTURE_2D, 0, opengl_texture_format, self->width, self->height, 0, mgl_texture_format_to_source_opengl_format(self->format), GL_UNSIGNED_BYTE, data); context->gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -94,13 +115,77 @@ int mgl_texture_load_from_memory(mgl_texture *self, const unsigned char *data, i return 0; } +int mgl_texture_update(mgl_texture *self, const unsigned char *data, int offset_x, int offset_y, int width, int height, mgl_image_format format) { + if(offset_x + width > self->width || offset_y + height > self->height) + return -1; + + mgl_context *context = mgl_get_context(); + context->gl.glBindTexture(GL_TEXTURE_2D, self->id); + const mgl_texture_format texture_format = mgl_image_format_to_mgl_texture_format(format); + /* TODO: TODO: Only do one glTexSubImage2D */ +#if 1 + for(int i = 0; i < height; ++i) { + context->gl.glTexSubImage2D(GL_TEXTURE_2D, 0, offset_x, offset_y + i, width, 1, mgl_texture_format_to_source_opengl_format(texture_format), GL_UNSIGNED_BYTE, data + (i * width)); + } +#else + context->gl.glTexSubImage2D(GL_TEXTURE_2D, 0, offset_x, offset_y, width, height, mgl_texture_format_to_source_opengl_format(texture_format), GL_UNSIGNED_BYTE, data); +#endif + context->gl.glBindTexture(GL_TEXTURE_2D, 0); + return 0; +} + +int mgl_texture_resize(mgl_texture *self, int new_width, int new_height, mgl_texture_load_options *load_options) { + if(new_width == self->width && new_height == self->height) + return 0; + + if(new_width < 0 || new_height < 0) + return -1; + + if(new_width > self->max_width || new_height > self->max_height) + return -1; + + self->width = new_width; + self->height = new_height; + + const int opengl_texture_format = load_options && load_options->compressed ? mgl_texture_format_to_compressed_opengl_format(self->format) : mgl_texture_format_to_opengl_format(self->format); + + mgl_context *context = mgl_get_context(); + context->gl.glBindTexture(GL_TEXTURE_2D, self->id); + context->gl.glTexImage2D(GL_TEXTURE_2D, 0, opengl_texture_format, self->width, self->height, 0, mgl_texture_format_to_source_opengl_format(self->format), GL_UNSIGNED_BYTE, NULL); + context->gl.glBindTexture(GL_TEXTURE_2D, 0); + return 0; +} + +void mgl_texture_use(const mgl_texture *texture) { + mgl_context *context = mgl_get_context(); + + if(texture) { + float matrix[16] = { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f, + }; + + if(texture->pixel_coordinates) { + matrix[0] = 1.0f / (float)texture->width; + matrix[5] = 1.0f / (float)texture->height; + } + + context->gl.glMatrixMode(GL_TEXTURE); + context->gl.glLoadMatrixf(matrix); + context->gl.glMatrixMode(GL_MODELVIEW); + + context->gl.glBindTexture(GL_TEXTURE_2D, texture->id); + } else { + context->gl.glBindTexture(GL_TEXTURE_2D, 0); + } +} + void mgl_texture_unload(mgl_texture *self) { mgl_context *context = mgl_get_context(); if(self->id) { context->gl.glDeleteTextures(1, &self->id); self->id = 0; } - self->width = 0; - self->height = 0; - self->format = 0; } -- cgit v1.2.3