From 4aa7273eea642bff78477b0b220c7056628b13a8 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 10 Oct 2021 17:29:31 +0200 Subject: Add texture loading (and render in test) --- src/gl.c | 7 +++++ src/graphics/texture.c | 71 +++++++++++++++++++++++++++++++++++++++++++ src/mgl.c | 27 +++++------------ src/window.c | 81 +++++++++++++++++++++++--------------------------- 4 files changed, 123 insertions(+), 63 deletions(-) create mode 100644 src/graphics/texture.c (limited to 'src') diff --git a/src/gl.c b/src/gl.c index 282046c..fd63c81 100644 --- a/src/gl.c +++ b/src/gl.c @@ -39,6 +39,13 @@ int mgl_gl_load(mgl_gl *self) { { &self->glClear, "glClear" }, { &self->glEnable, "glEnable" }, { &self->glBlendFunc, "glBlendFunc" }, + { &self->glGenTextures, "glGenTextures" }, + { &self->glDeleteTextures, "glDeleteTextures" }, + { &self->glTexImage2D, "glTexImage2D" }, + { &self->glCompressedTexImage2D, "glCompressedTexImage2D" }, + { &self->glBindTexture, "glBindTexture" }, + { &self->glTexParameteri, "glTexParameteri" }, + { &self->glHint, "glHint" }, { NULL, NULL } }; diff --git a/src/graphics/texture.c b/src/graphics/texture.c new file mode 100644 index 0000000..3d3ea6f --- /dev/null +++ b/src/graphics/texture.c @@ -0,0 +1,71 @@ +#include "../../include/mgl/graphics/texture.h" +#include "../../include/mgl/mgl.h" + +#define STBI_NO_PSD +#define STBI_NO_TGA +#define STBI_NO_HDR +#define STBI_NO_PIC +#define STBI_NO_PNM +#define STB_IMAGE_IMPLEMENTATION +#include "../../external/stb_image.h" + +static int mgl_texture_format_to_opengl_format(mgl_texture_format format) { + switch(format) { + case MGL_TEXTURE_GRAY: return GL_LUMINANCE8; + case MGL_TEXTURE_GRAY_ALPHA: return GL_LUMINANCE8_ALPHA8; + case MGL_TEXTURE_RGB: return GL_RGB8; + case MGL_TEXTURE_RGB_ALPHA: return GL_RGBA8; + } + return 0; +} + +static int mgl_texture_format_to_source_opengl_format(mgl_texture_format format) { + switch(format) { + case MGL_TEXTURE_GRAY: return GL_LUMINANCE8_ALPHA8; + case MGL_TEXTURE_GRAY_ALPHA: return GL_LUMINANCE8_ALPHA8; + case MGL_TEXTURE_RGB: return GL_RGB; + case MGL_TEXTURE_RGB_ALPHA: return GL_RGBA; + } + return 0; +} + +/* TODO: Ensure texture is power of 2 if the hardware doesn't support non power of two textures */ +int mgl_texture_load_from_file(mgl_texture *self, const char *filepath) { + self->id = 0; + + int format; + stbi_uc *image_data = stbi_load(filepath, &self->width, &self->height, &format, 0); + if(!image_data) { + fprintf(stderr, "Error: failed to load image %s, error: %s\n", filepath, stbi_failure_reason()); + return -1; + } + self->format = format; + + mgl_context *context = mgl_get_context(); + context->gl.glGenTextures(1, &self->id); + if(self->id == 0) { + stbi_image_free(image_data); + return -1; + } + + const int opengl_texture_format = mgl_texture_format_to_opengl_format(self->format); + + 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, image_data); + context->gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + context->gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + context->gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + context->gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + context->gl.glBindTexture(GL_TEXTURE_2D, 0); + + stbi_image_free(image_data); + return 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; + } +} diff --git a/src/mgl.c b/src/mgl.c index 02ed363..cbdfb41 100644 --- a/src/mgl.c +++ b/src/mgl.c @@ -1,25 +1,9 @@ #include "../include/mgl/mgl.h" #include -#include #include - -#define GLX_USE_GL 1 -#define GLX_BUFFER_SIZE 2 -#define GLX_LEVEL 3 -#define GLX_RGBA 4 -#define GLX_DOUBLEBUFFER 5 -#define GLX_STEREO 6 -#define GLX_AUX_BUFFERS 7 -#define GLX_RED_SIZE 8 -#define GLX_GREEN_SIZE 9 -#define GLX_BLUE_SIZE 10 -#define GLX_ALPHA_SIZE 11 -#define GLX_DEPTH_SIZE 12 -#define GLX_STENCIL_SIZE 13 -#define GLX_ACCUM_RED_SIZE 14 -#define GLX_ACCUM_GREEN_SIZE 15 -#define GLX_ACCUM_BLUE_SIZE 16 -#define GLX_ACCUM_ALPHA_SIZE 17 +#ifndef NDEBUG +#include +#endif static mgl_context context; static int init_count = 0; @@ -34,12 +18,17 @@ static int ignore_xerror(Display *display, XErrorEvent *ee) { static int glx_context_init() { const int attr[] = { GLX_RGBA, + GLX_BUFFER_SIZE, 24, GLX_DEPTH_SIZE, 0, GLX_STENCIL_SIZE, 0, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_ALPHA_SIZE, 0, + GLX_ACCUM_RED_SIZE, 0, + GLX_ACCUM_GREEN_SIZE, 0, + GLX_ACCUM_BLUE_SIZE, 0, + GLX_ACCUM_ALPHA_SIZE, 0, GLX_DOUBLEBUFFER, /* TODO: Add option to turn this off? */ None }; diff --git a/src/window.c b/src/window.c index 4d877d7..7d13ffe 100644 --- a/src/window.c +++ b/src/window.c @@ -3,10 +3,28 @@ #include #include -#define GL_COLOR_BUFFER_BIT 0x00004000 -#define GL_BLEND 0x0BE2 -#define GL_SRC_ALPHA 0x0302 -#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +/* TODO: check for glx swap control extension string (GLX_EXT_swap_control, etc) */ +static void set_vertical_sync_enabled(Window window, int enabled) { + int result = 0; + mgl_context *context = mgl_get_context(); + + if(context->gl.glXSwapIntervalEXT) { + context->gl.glXSwapIntervalEXT(context->connection, window, enabled ? 1 : 0); + } else if(context->gl.glXSwapIntervalMESA) { + result = context->gl.glXSwapIntervalMESA(enabled ? 1 : 0); + } else if(context->gl.glXSwapIntervalSGI) { + result = context->gl.glXSwapIntervalSGI(enabled ? 1 : 0); + } else { + static int warned = 0; + if (!warned) { + warned = 1; + fprintf(stderr, "Warning: setting vertical sync not supported\n"); + } + } + + if(result != 0) + fprintf(stderr, "Warning: setting vertical sync failed\n"); +} int mgl_window_create(mgl_window *self, const char *title, int width, int height, mgl_window_callback *callback, void *userdata) { return mgl_window_create_with_params(self, title, width, height, DefaultRootWindow(mgl_get_context()->connection), callback, userdata); @@ -30,7 +48,7 @@ int mgl_window_create_with_params(mgl_window *self, const char *title, int width window_attr.event_mask = KeyPressMask; self->window = XCreateWindow(context->connection, parent_window, 0, 0, width, height, 0, ((XVisualInfo*)context->visual_info)->depth, InputOutput, ((XVisualInfo*)context->visual_info)->visual, CWColormap | CWEventMask, &window_attr); - //XFreeColormap(context->connection, color_map); + XFreeColormap(context->connection, color_map); if(!self->window) { fprintf(stderr, "XCreateWindow failed\n"); mgl_window_deinit(self); @@ -39,60 +57,32 @@ int mgl_window_create_with_params(mgl_window *self, const char *title, int width /* TODO: Test utf8 */ XStoreName(context->connection, self->window, title); - return 0; -} - -void mgl_window_deinit(mgl_window *self) { - mgl_context *context = mgl_get_context(); - - if(self->window) { - XDestroyWindow(context->connection, self->window); - self->window = 0; - } -} - -/* TODO: check for glx swap control extension string (GLX_EXT_swap_control, etc) */ -static void set_vertical_sync_enabled(Window window, int enabled) { - int result = 0; - mgl_context *context = mgl_get_context(); - - if(context->gl.glXSwapIntervalEXT) { - context->gl.glXSwapIntervalEXT(context->connection, window, enabled ? 1 : 0); - } else if(context->gl.glXSwapIntervalMESA) { - result = context->gl.glXSwapIntervalMESA(enabled ? 1 : 0); - } else if(context->gl.glXSwapIntervalSGI) { - result = context->gl.glXSwapIntervalSGI(enabled ? 1 : 0); - } else { - static int warned = 0; - if (!warned) { - warned = 1; - fprintf(stderr, "Warning: setting vertical sync not supported\n"); - } - } - - if(result != 0) - fprintf(stderr, "Warning: setting vertical sync failed\n"); -} - -void mgl_window_show(mgl_window *self) { - mgl_context *context = mgl_get_context(); - XMapWindow(context->connection, self->window); XFlush(context->connection); /* TODO: Switch current when rendering to another window, and set current to NULL when destroying the currently selected context */ context->gl.glXMakeCurrent(context->connection, self->window, context->glx_context); set_vertical_sync_enabled(self->window, 1); + context->gl.glEnable(GL_TEXTURE_2D); context->gl.glEnable(GL_BLEND); context->gl.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); mgl_window_draw(self); + return 0; +} + +void mgl_window_deinit(mgl_window *self) { + mgl_context *context = mgl_get_context(); + if(self->window) { + XDestroyWindow(context->connection, self->window); + self->window = 0; + } } static void on_receive_x11_event(mgl_window *window, XEvent *xev) { } -void mgl_window_event_poll(mgl_window *self) { +void mgl_window_events_poll(mgl_window *self) { Display *display = mgl_get_context()->connection; const int x11_fd = ConnectionNumber(display); @@ -114,6 +104,9 @@ void mgl_window_event_poll(mgl_window *self) { XNextEvent(display, &xev); on_receive_x11_event(self, &xev); } + } else if(num_ready_fds == -1) { + /* TODO: */ + fprintf(stderr, "Disconnected!\n"); } } -- cgit v1.2.3