aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-10-10 17:29:31 +0200
committerdec05eba <dec05eba@protonmail.com>2021-10-10 17:29:31 +0200
commit4aa7273eea642bff78477b0b220c7056628b13a8 (patch)
tree014430c208905164f99b37d663944192b8d6fd8c /src
parentb81aff95e7924c38dbd1cf639011be1848af6967 (diff)
Add texture loading (and render in test)
Diffstat (limited to 'src')
-rw-r--r--src/gl.c7
-rw-r--r--src/graphics/texture.c71
-rw-r--r--src/mgl.c27
-rw-r--r--src/window.c81
4 files changed, 123 insertions, 63 deletions
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 <X11/Xutil.h>
-#include <stdlib.h>
#include <stdio.h>
-
-#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 <stdlib.h>
+#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 <X11/Xutil.h>
#include <stdio.h>
-#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");
}
}