From 54b2376adad98d91d32378efc3f241f120ba970f Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 10 Oct 2021 13:56:10 +0200 Subject: Draw every frame instead of x11 expose, enable vsync (if available) --- src/gl.c | 34 ++++++++++++++++++++++++-------- src/glx.c | 55 ---------------------------------------------------- src/mgl.c | 13 ++++--------- src/window.c | 63 +++++++++++++++++++++++++++++++++++++++++------------------- 4 files changed, 73 insertions(+), 92 deletions(-) delete mode 100644 src/glx.c (limited to 'src') diff --git a/src/gl.c b/src/gl.c index c83ab49..023ffbb 100644 --- a/src/gl.c +++ b/src/gl.c @@ -1,6 +1,6 @@ #include "../include/mgl/gl.h" #include -/*#include */ +/*#include */ #include typedef struct { @@ -20,28 +20,46 @@ static void* dlsym_print_fail(void *handle, const char *name) { } int mgl_gl_load(mgl_gl *self) { - const char *gl_path = "/usr/lib/libOpenGL.so.0"; - self->handle = dlopen(gl_path, RTLD_LAZY); + const char *glx_path = "/usr/lib/libGL.so.1"; + self->handle = dlopen(glx_path, RTLD_LAZY); if(!self->handle) { - fprintf(stderr, "dlopen(\"%s\", RTLD_LAZY) failed\n", gl_path); + fprintf(stderr, "dlopen(\"%s\", RTLD_LAZY) failed\n", glx_path); return -1; } - const dlsym_assign assign[] = { + const dlsym_assign required_dlsym[] = { + { &self->glXChooseVisual, "glXChooseVisual" }, + { &self->glXCreateContext, "glXCreateContext" }, + { &self->glXDestroyContext, "glXDestroyContext" }, + { &self->glXMakeCurrent, "glXMakeCurrent" }, + { &self->glXSwapBuffers, "glXSwapBuffers" }, + { &self->glViewport, "glViewport" }, { &self->glClearColor, "glClearColor" }, { &self->glClear, "glClear" }, + { NULL, NULL } }; - for(int i = 0; assign[i].func; ++i) { - *assign[i].func = dlsym_print_fail(self->handle, assign[i].name); - if(!assign[i].func) { + for(int i = 0; required_dlsym[i].func; ++i) { + *required_dlsym[i].func = dlsym_print_fail(self->handle, required_dlsym[i].name); + if(!required_dlsym[i].func) { mgl_gl_unload(self); return -1; } } + const dlsym_assign optional_dlsym[] = { + { &self->glXSwapIntervalEXT, "glXSwapIntervalEXT" }, + { &self->glXSwapIntervalMESA, "glXGetSwapIntervalMESA" }, + { &self->glXSwapIntervalSGI, "glXSwapIntervalSGI" }, + { NULL, NULL } + }; + + for(int i = 0; optional_dlsym[i].func; ++i) { + *optional_dlsym[i].func = dlsym_print_fail(self->handle, optional_dlsym[i].name); + } + return 0; } diff --git a/src/glx.c b/src/glx.c deleted file mode 100644 index 6712947..0000000 --- a/src/glx.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "../include/mgl/glx.h" -#include -/*#include */ -#include - -typedef struct { - void **func; - const char *name; -} dlsym_assign; - -static void* dlsym_print_fail(void *handle, const char *name) { - dlerror(); - void *sym = dlsym(handle, name); - char *err_str = dlerror(); - - if(!sym) - fprintf(stderr, "dlsym(handle, \"%s\") failed, error: %s\n", name, err_str ? err_str : "(null)"); - - return sym; -} - -int mgl_glx_load(mgl_glx *self) { - const char *glx_path = "/usr/lib/libGLX.so.0"; - self->handle = dlopen(glx_path, RTLD_LAZY); - if(!self->handle) { - fprintf(stderr, "dlopen(\"%s\", RTLD_LAZY) failed\n", glx_path); - return -1; - } - - const dlsym_assign assign[] = { - { &self->glXChooseVisual, "glXChooseVisual" }, - { &self->glXCreateContext, "glXCreateContext" }, - { &self->glXDestroyContext, "glXDestroyContext" }, - { &self->glXMakeCurrent, "glXMakeCurrent" }, - { &self->glXSwapBuffers, "glXSwapBuffers" }, - { NULL, NULL } - }; - - for(int i = 0; assign[i].func; ++i) { - *assign[i].func = dlsym_print_fail(self->handle, assign[i].name); - if(!assign[i].func) { - mgl_glx_unload(self); - return -1; - } - } - - return 0; -} - -void mgl_glx_unload(mgl_glx *self) { - if(self->handle) { - dlclose(self->handle); - self->handle = NULL; - } -} diff --git a/src/mgl.c b/src/mgl.c index 27d33ae..02ed363 100644 --- a/src/mgl.c +++ b/src/mgl.c @@ -44,13 +44,13 @@ static int glx_context_init() { None }; - context.visual_info = context.glx.glXChooseVisual(context.connection, DefaultScreen(context.connection), (int*)attr); + context.visual_info = context.gl.glXChooseVisual(context.connection, DefaultScreen(context.connection), (int*)attr); if(!context.visual_info) { fprintf(stderr, "glXChooseVisual failed, no appropriate visual found\n"); return -1; } - context.glx_context = context.glx.glXCreateContext(context.connection, context.visual_info, NULL, 1); + context.glx_context = context.gl.glXCreateContext(context.connection, context.visual_info, NULL, 1); if(!context.glx_context) { fprintf(stderr, "glXCreateContext failed\n"); return -1; @@ -61,7 +61,7 @@ static int glx_context_init() { static void glx_context_deinit() { if(context.glx_context) { - context.glx.glXDestroyContext(context.connection, context.glx_context); + context.gl.glXDestroyContext(context.connection, context.glx_context); context.glx_context = NULL; } @@ -83,11 +83,6 @@ int mgl_init(void) { prev_xerror = XSetErrorHandler(ignore_xerror); - if(mgl_glx_load(&context.glx) != 0) { - mgl_deinit(); - return -1; - } - if(mgl_gl_load(&context.gl) != 0) { mgl_deinit(); return -1; @@ -105,7 +100,7 @@ void mgl_deinit(void) { if(init_count == 1) { glx_context_deinit(); mgl_gl_unload(&context.gl); - mgl_glx_unload(&context.glx); + mgl_gl_unload(&context.gl); XSetErrorHandler(prev_xerror); if(context.connection) { XCloseDisplay(context.connection); diff --git a/src/window.c b/src/window.c index 9836907..bdbcd6f 100644 --- a/src/window.c +++ b/src/window.c @@ -24,7 +24,7 @@ int mgl_window_create_with_params(mgl_window *self, const char *title, int width XSetWindowAttributes window_attr; window_attr.colormap = color_map; - window_attr.event_mask = ExposureMask | KeyPressMask; + 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); @@ -48,19 +48,27 @@ void mgl_window_deinit(mgl_window *self) { } } -static void mgl_window_draw(mgl_window *self) { +/* 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(); - /* TODO: Get window size from window resize event instead */ - XWindowAttributes gwa; - XGetWindowAttributes(context->connection, self->window, &gwa); + 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"); + } + } - context->gl.glViewport(0, 0, gwa.width, gwa.height); - context->gl.glClear(GL_COLOR_BUFFER_BIT); - context->gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - if(self->callback.draw) - self->callback.draw(self, self->callback_userdata); - context->glx.glXSwapBuffers(context->connection, self->window); + if(result != 0) + fprintf(stderr, "Warning: setting vertical sync failed\n"); } void mgl_window_show(mgl_window *self) { @@ -70,19 +78,16 @@ void mgl_window_show(mgl_window *self) { XFlush(context->connection); /* TODO: Switch current when rendering to another window, and set current to NULL when destroying the currently selected context */ - context->glx.glXMakeCurrent(context->connection, self->window, context->glx_context); + context->gl.glXMakeCurrent(context->connection, self->window, context->glx_context); + set_vertical_sync_enabled(self->window, 1); mgl_window_draw(self); } static void on_receive_x11_event(mgl_window *window, XEvent *xev) { - switch(xev->type) { - case Expose: - mgl_window_draw(window); - break; - } + } -void mgl_window_event_poll(mgl_window *self, int timeout_ms) { +void mgl_window_event_poll(mgl_window *self) { Display *display = mgl_get_context()->connection; const int x11_fd = ConnectionNumber(display); @@ -91,9 +96,12 @@ void mgl_window_event_poll(mgl_window *self, int timeout_ms) { FD_SET(x11_fd, &in_fds); struct timeval tv; - tv.tv_sec = timeout_ms / 1000; - tv.tv_usec = (timeout_ms * 1000) - (tv.tv_sec * 1000 * 1000); + tv.tv_sec = 0; + tv.tv_usec = 0; + /*tv.tv_sec = timeout_ms / 1000; + tv.tv_usec = (timeout_ms * 1000) - (tv.tv_sec * 1000 * 1000);*/ + /* TODO: Is this needed when using XPending? */ const int num_ready_fds = select(1 + x11_fd, &in_fds, NULL, NULL, &tv); if(num_ready_fds > 0) { XEvent xev; @@ -103,3 +111,18 @@ void mgl_window_event_poll(mgl_window *self, int timeout_ms) { } } } + +void mgl_window_draw(mgl_window *self) { + mgl_context *context = mgl_get_context(); + + /* TODO: Get window size from window resize event instead */ + XWindowAttributes gwa; + XGetWindowAttributes(context->connection, self->window, &gwa); + + context->gl.glViewport(0, 0, gwa.width, gwa.height); + context->gl.glClear(GL_COLOR_BUFFER_BIT); + context->gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + if(self->callback.draw) + self->callback.draw(self, self->callback_userdata); + context->gl.glXSwapBuffers(context->connection, self->window); +} -- cgit v1.2.3