aboutsummaryrefslogtreecommitdiff
path: root/src/window
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2024-08-04 21:16:55 +0200
committerdec05eba <dec05eba@protonmail.com>2024-08-04 21:16:55 +0200
commit90739659800c4bf893882098d70b575c26958883 (patch)
treed36299593d9900217d55f6926bf6459c954ba6e3 /src/window
parent1636127a6edfbf5399d1706c1a6c58f87eeb5c79 (diff)
egl: fix transparent window
Diffstat (limited to 'src/window')
-rw-r--r--src/window/window.c136
1 files changed, 95 insertions, 41 deletions
diff --git a/src/window/window.c b/src/window/window.c
index 5c44fa8..06b5a6b 100644
--- a/src/window/window.c
+++ b/src/window/window.c
@@ -54,6 +54,13 @@ static bool x11_events_circular_buffer_pop(x11_events_circular_buffer *self, mgl
return true;
}
+static bool xvisual_match_alpha(Display *dpy, XVisualInfo *visual_info, bool alpha) {
+ XRenderPictFormat *pict_format = XRenderFindVisualFormat(dpy, visual_info->visual);
+ if(!pict_format)
+ return false;
+ return (alpha && pict_format->direct.alphaMask > 0) || (!alpha && pict_format->direct.alphaMask == 0);
+}
+
#define MAX_MONITORS 12
typedef struct {
@@ -88,20 +95,14 @@ static bool glx_context_choose(mgl_context *context, x11_context_glx *glx, bool
if(!glx->visual_info)
continue;
- XRenderPictFormat *pict_format = XRenderFindVisualFormat(context->connection, glx->visual_info->visual);
- if(!pict_format) {
+ if(xvisual_match_alpha(context->connection, glx->visual_info, alpha)) {
+ glx->fbconfig = glx->fbconfigs[i];
+ break;
+ } else {
XFree(glx->visual_info);
glx->visual_info = NULL;
- continue;
+ glx->fbconfig = NULL;
}
-
- glx->fbconfig = glx->fbconfigs[i];
- if((alpha && pict_format->direct.alphaMask > 0) || (!alpha && pict_format->direct.alphaMask == 0))
- break;
-
- XFree(glx->visual_info);
- glx->visual_info = NULL;
- glx->fbconfig = NULL;
}
if(!glx->visual_info) {
@@ -203,10 +204,91 @@ typedef struct {
EGLDisplay egl_display;
EGLSurface egl_surface;
EGLContext egl_context;
+ EGLConfig *configs;
EGLConfig ecfg;
XVisualInfo *visual_info;
} x11_context_egl;
+static int32_t egl_get_config_attrib(x11_context_egl *egl, EGLConfig ecfg, int32_t attribute_name) {
+ mgl_context *context = mgl_get_context();
+ int32_t value = 0;
+ context->gl.eglGetConfigAttrib(egl->egl_display, ecfg, attribute_name, &value);
+ return value;
+}
+
+static bool egl_context_choose(mgl_context *context, x11_context_egl *egl, bool alpha) {
+ egl->configs = NULL;
+ egl->ecfg = NULL;
+ egl->visual_info = NULL;
+
+ int32_t num_configs = 0;
+ context->gl.eglGetConfigs(egl->egl_display, NULL, 0, &num_configs);
+ if(num_configs == 0) {
+ fprintf(stderr, "mgl error: no configs found\n");
+ return false;
+ }
+
+ egl->configs = (EGLConfig*)calloc(num_configs, sizeof(EGLConfig));
+ if(!egl->configs) {
+ fprintf(stderr, "mgl error: failed to allocate %d configs\n", (int)num_configs);
+ return false;
+ }
+
+ context->gl.eglGetConfigs(egl->egl_display, egl->configs, num_configs, &num_configs);
+ for(int i = 0; i < num_configs; i++) {
+ egl->ecfg = egl->configs[i];
+
+ if(egl_get_config_attrib(egl, egl->ecfg, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER)
+ continue;
+
+ if(!(egl_get_config_attrib(egl, egl->ecfg, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
+ continue;
+
+ if(egl_get_config_attrib(egl, egl->ecfg, EGL_RED_SIZE) != 8)
+ continue;
+
+ if(egl_get_config_attrib(egl, egl->ecfg, EGL_GREEN_SIZE) != 8)
+ continue;
+
+ if(egl_get_config_attrib(egl, egl->ecfg, EGL_BLUE_SIZE) != 8)
+ continue;
+
+ if(egl_get_config_attrib(egl, egl->ecfg, EGL_ALPHA_SIZE) != (alpha ? 8 : 0))
+ continue;
+
+ XVisualInfo vi = {0};
+ vi.visualid = egl_get_config_attrib(egl, egl->ecfg, EGL_NATIVE_VISUAL_ID);
+ if(!vi.visualid)
+ continue;
+
+ int vis_count = 0;
+ egl->visual_info = XGetVisualInfo(context->connection, VisualIDMask, &vi, &vis_count);
+ if(!egl->visual_info)
+ continue;
+
+ if(xvisual_match_alpha(context->connection, egl->visual_info, alpha)) {
+ break;
+ } else {
+ XFree(egl->visual_info);
+ egl->visual_info = NULL;
+ egl->ecfg = NULL;
+ }
+ }
+
+ if(!egl->visual_info) {
+ if(egl->configs) {
+ free(egl->configs);
+ egl->configs = NULL;
+ }
+ egl->ecfg = NULL;
+
+ fprintf(stderr, "mgl error: no appropriate visual found\n");
+ return false;
+ }
+
+ return true;
+}
+
static void x11_context_egl_deinit(x11_context_egl *self) {
mgl_context *context = mgl_get_context();
@@ -236,20 +318,6 @@ static bool x11_context_egl_init(x11_context_egl *self, bool alpha) {
mgl_context *context = mgl_get_context();
memset(self, 0, sizeof(*self));
- int32_t num_config = 0;
-
- const int32_t attr[] = {
- EGL_BUFFER_SIZE, alpha ? 32 : 24,
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, alpha ? 8 : 0,
- // TODO:
- //EGL_DEPTH_SIZE, 0,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
- EGL_NONE, EGL_NONE
- };
-
const int32_t ctxattr[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE, EGL_NONE
@@ -269,10 +337,8 @@ static bool x11_context_egl_init(x11_context_egl *self, bool alpha) {
x11_context_egl_deinit(self);
return false;
}
-
- // TODO: Iterate all egl configs (eglGetConfigs) and match visuals to choose the correct one
- if(!context->gl.eglChooseConfig(self->egl_display, attr, &self->ecfg, 1, &num_config) || num_config != 1) {
- fprintf(stderr, "gsr error: gsr_egl_create_window failed: failed to find a matching config\n");
+
+ if(!egl_context_choose(context, self, alpha)) {
x11_context_egl_deinit(self);
return false;
}
@@ -284,18 +350,6 @@ static bool x11_context_egl_init(x11_context_egl *self, bool alpha) {
return false;
}
- // TODO: Error check
- int visual_id = 0;
- context->gl.eglGetConfigAttrib(self->egl_display, self->ecfg, EGL_NATIVE_VISUAL_ID, &visual_id);
-
- XVisualInfo vi = {0};
- vi.visualid = visual_id;
- int count = 0;
- self->visual_info = XGetVisualInfo(context->connection, VisualIDMask, &vi, &count);
- if(self->visual_info) {
- // TODO: Check if the visual really is transparent with XRenderFindVisualFormat and alphaMask value, the same way its done for GLX
- }
-
return true;
}