diff options
Diffstat (limited to 'src/window')
-rw-r--r-- | src/window/window.c | 83 |
1 files changed, 78 insertions, 5 deletions
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"); |