aboutsummaryrefslogtreecommitdiff
path: root/src/graphics/texture.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/graphics/texture.c')
-rw-r--r--src/graphics/texture.c117
1 files changed, 101 insertions, 16 deletions
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 <stdio.h>
-/* 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;
}