aboutsummaryrefslogtreecommitdiff
path: root/src/window
diff options
context:
space:
mode:
Diffstat (limited to 'src/window')
-rw-r--r--src/window/window.c83
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");