diff options
-rw-r--r-- | include/mgl/mgl.h | 3 | ||||
-rw-r--r-- | include/mgl/window/window.h | 1 | ||||
-rw-r--r-- | src/mgl.c | 67 | ||||
-rw-r--r-- | src/window/window.c | 83 |
4 files changed, 79 insertions, 75 deletions
diff --git a/include/mgl/mgl.h b/include/mgl/mgl.h index b43e4b9..f2373b7 100644 --- a/include/mgl/mgl.h +++ b/include/mgl/mgl.h @@ -10,9 +10,6 @@ typedef struct mgl_context mgl_context; struct mgl_context { mgl_connection connection; mgl_gl gl; - GLXFBConfig *fbconfigs; - _XVisualInfo *visual_info; - GLXFBConfig fbconfig; unsigned long wm_delete_window_atom; unsigned long net_wm_ping_atom; unsigned long net_wm_pid_atom; diff --git a/include/mgl/window/window.h b/include/mgl/window/window.h index 7dd85b4..34f8cbb 100644 --- a/include/mgl/window/window.h +++ b/include/mgl/window/window.h @@ -52,6 +52,7 @@ typedef struct { mgl_window_handle parent_window; /* 0 = root window */ bool hidden; /* false by default */ bool override_redirect; /* false by default */ + bool support_alpha; /* support alpha for the window, false by default */ } mgl_window_create_params; typedef enum { @@ -1,7 +1,6 @@ #include "../include/mgl/mgl.h" #include <X11/Xutil.h> #include <X11/XKBlib.h> -#include <X11/extensions/Xrender.h> #include <stdio.h> #ifndef NDEBUG #include <stdlib.h> @@ -23,66 +22,6 @@ static int ignore_xioerror(Display *display) { return 0; } -static int glx_context_init() { - const int attr[] = { - GLX_RENDER_TYPE, GLX_RGBA_BIT, - GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, - GLX_DOUBLEBUFFER, True, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_ALPHA_SIZE, 8, - GLX_DEPTH_SIZE, 0, - None - }; - - context.fbconfigs = NULL; - context.visual_info = NULL; - context.fbconfig = NULL; - - int numfbconfigs = 0; - context.fbconfigs = context.gl.glXChooseFBConfig(context.connection, DefaultScreen(context.connection), attr, &numfbconfigs); - for(int i = 0; i < numfbconfigs; i++) { - context.visual_info = context.gl.glXGetVisualFromFBConfig(context.connection, context.fbconfigs[i]); - if(!context.visual_info) - continue; - - XRenderPictFormat *pict_format = XRenderFindVisualFormat(context.connection, ((XVisualInfo*)context.visual_info)->visual); - if(!pict_format) { - XFree(context.visual_info); - context.visual_info = NULL; - continue; - } - - context.fbconfig = context.fbconfigs[i]; - if(pict_format->direct.alphaMask > 0) - break; - - XFree(context.visual_info); - context.visual_info = NULL; - context.fbconfig = NULL; - } - - if(!context.visual_info) { - fprintf(stderr, "mgl error: no appropriate visual found\n"); - return -1; - } - - return 0; -} - -static void glx_context_deinit() { - if(context.visual_info) { - XFree(context.visual_info); - context.visual_info = NULL; - } - - if(context.fbconfigs) { - XFree(context.fbconfigs); - context.fbconfigs = NULL; - } -} - int mgl_init(void) { ++init_count; if(init_count == 1) { @@ -111,11 +50,6 @@ int mgl_init(void) { mgl_deinit(); return -1; } - - if(glx_context_init() != 0) { - mgl_deinit(); - return -1; - } } return 0; } @@ -136,7 +70,6 @@ void mgl_deinit(void) { GLX needs to be unloaded after closing the display on nvidia because nvidia registers cleanup callbacks on exit, that uses the x11 display. */ - glx_context_deinit(); mgl_gl_unload(&context.gl); } } diff --git a/src/window/window.c b/src/window/window.c index eeb2e43..1817a2f 100644 --- a/src/window/window.c +++ b/src/window/window.c @@ -5,6 +5,7 @@ #include <X11/Xutil.h> #include <X11/cursorfont.h> #include <X11/Xatom.h> +#include <X11/extensions/Xrender.h> #include <stdlib.h> #include <string.h> #include <errno.h> @@ -68,6 +69,9 @@ typedef struct { unsigned int prev_keycode_pressed; bool key_was_released; Colormap color_map; + GLXFBConfig *fbconfigs; + GLXFBConfig fbconfig; + XVisualInfo *visual_info; /* Used to stack text event on top of key press/release events and other text events. For example pressing a key should give the user both key press and text events @@ -79,7 +83,55 @@ typedef struct { static void x11_context_deinit(x11_context *self); -static int x11_context_init(x11_context *self) { +static bool glx_context_choose(mgl_context *context, GLXFBConfig **fbconfigs, GLXFBConfig *fbconfig, XVisualInfo **visual_info, bool alpha) { + const int attr[] = { + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_DOUBLEBUFFER, True, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, alpha ? 8 : 0, + GLX_DEPTH_SIZE, 0, + None + }; + + *fbconfigs = NULL; + *visual_info = NULL; + *fbconfig = NULL; + + int numfbconfigs = 0; + *fbconfigs = context->gl.glXChooseFBConfig(context->connection, DefaultScreen(context->connection), attr, &numfbconfigs); + for(int i = 0; i < numfbconfigs; i++) { + *visual_info = (XVisualInfo*)context->gl.glXGetVisualFromFBConfig(context->connection, (*fbconfigs)[i]); + if(!*visual_info) + continue; + + XRenderPictFormat *pict_format = XRenderFindVisualFormat(context->connection, (*visual_info)->visual); + if(!pict_format) { + XFree(*visual_info); + *visual_info = NULL; + continue; + } + + *fbconfig = (*fbconfigs)[i]; + if((alpha && pict_format->direct.alphaMask > 0) || (!alpha && pict_format->direct.alphaMask == 0)) + break; + + XFree(*visual_info); + *visual_info = NULL; + *fbconfig = NULL; + } + + if(!*visual_info) { + fprintf(stderr, "mgl error: no appropriate visual found\n"); + return false; + } + + return true; +} + +static int x11_context_init(x11_context *self, bool alpha) { mgl_context *context = mgl_get_context(); self->glx_context = NULL; @@ -101,6 +153,15 @@ static int x11_context_init(x11_context *self) { self->key_was_released = false; self->color_map = None; + self->fbconfigs = NULL; + self->fbconfig = NULL; + self->visual_info = NULL; + + if(!glx_context_choose(context, &self->fbconfigs, &self->fbconfig, &self->visual_info, alpha)) { + x11_context_deinit(self); + return -1; + } + self->default_cursor = XCreateFontCursor(context->connection, XC_arrow); if(!self->default_cursor) { x11_context_deinit(self); @@ -157,6 +218,18 @@ void x11_context_deinit(x11_context *self) { context->gl.glXDestroyContext(context->connection, self->glx_context); self->glx_context = NULL; } + + if(self->visual_info) { + XFree(self->visual_info); + self->visual_info = NULL; + } + + if(self->fbconfigs) { + XFree(self->fbconfigs); + self->fbconfigs = NULL; + } + + self->fbconfig = NULL; } static bool x11_context_append_event(x11_context *self, const mgl_event *event) { @@ -228,7 +301,7 @@ static int mgl_window_init(mgl_window *self, const char *title, const mgl_window } x11_context *x11_context = self->context; - if(x11_context_init(x11_context) != 0) { + if(x11_context_init(x11_context, params ? params->support_alpha : false) != 0) { fprintf(stderr, "mgl error: x11_context_init failed\n"); mgl_window_deinit(self); return -1; @@ -240,14 +313,14 @@ static int mgl_window_init(mgl_window *self, const char *title, const mgl_window if(parent_window == 0) parent_window = DefaultRootWindow(context->connection); - x11_context->glx_context = context->gl.glXCreateNewContext(context->connection, context->fbconfig, GLX_RGBA_TYPE, 0, True); + x11_context->glx_context = context->gl.glXCreateNewContext(context->connection, x11_context->fbconfig, GLX_RGBA_TYPE, 0, True); if(!x11_context->glx_context) { fprintf(stderr, "mgl error: glXCreateContext failed\n"); mgl_window_deinit(self); return -1; } - x11_context->color_map = XCreateColormap(context->connection, DefaultRootWindow(context->connection), ((XVisualInfo*)context->visual_info)->visual, AllocNone); + x11_context->color_map = XCreateColormap(context->connection, DefaultRootWindow(context->connection), x11_context->visual_info->visual, AllocNone); if(!x11_context->color_map) { fprintf(stderr, "mgl error: XCreateColormap failed\n"); mgl_window_deinit(self); @@ -280,7 +353,7 @@ static int mgl_window_init(mgl_window *self, const char *title, const mgl_window } else { self->window = XCreateWindow(context->connection, parent_window, params->position.x, params->position.y, window_size.x, window_size.y, 0, - ((XVisualInfo*)context->visual_info)->depth, InputOutput, ((XVisualInfo*)context->visual_info)->visual, + x11_context->visual_info->depth, InputOutput, x11_context->visual_info->visual, CWColormap | CWEventMask | CWOverrideRedirect | CWBorderPixel | CWBackPixmap, &window_attr); if(!self->window) { fprintf(stderr, "mgl error: XCreateWindow failed\n"); |