From e948b743631ac9c38ec35fed4d13d8d9e9088191 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Sat, 10 Feb 2024 14:00:53 +0000 Subject: [PATCH 1/4] backend: gl: remove an unused type Signed-off-by: Yuxuan Shui --- src/backend/gl/glx.h | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/backend/gl/glx.h b/src/backend/gl/glx.h index a7663d94..86701023 100644 --- a/src/backend/gl/glx.h +++ b/src/backend/gl/glx.h @@ -19,20 +19,6 @@ struct glx_fbconfig_info { int y_inverted; }; -/// The search criteria for glx_find_fbconfig -struct glx_fbconfig_criteria { - /// Bit width of the red component - int red_size; - /// Bit width of the green component - int green_size; - /// Bit width of the blue component - int blue_size; - /// Bit width of the alpha component - int alpha_size; - /// The depth of X visual - int visual_depth; -}; - struct glx_fbconfig_info *glx_find_fbconfig(struct x_connection *, struct xvisual_info); struct glxext_info { From e8d42885fa85b1ceacdc11dbc4e7dd6ff37b4b5f Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Sat, 10 Feb 2024 14:19:48 +0000 Subject: [PATCH 2/4] backend: gl: don't force fbconfig info on to heap It's fairly small, so it's reasonable to put it on the stack. Signed-off-by: Yuxuan Shui --- src/backend/gl/glx.c | 35 +++++++++++++++++------------------ src/backend/gl/glx.h | 3 ++- src/common.h | 2 +- src/opengl.c | 2 +- src/opengl.h | 5 +---- src/picom.c | 5 ----- src/render.c | 29 +++++++++++++++-------------- src/render.h | 2 +- 8 files changed, 38 insertions(+), 45 deletions(-) diff --git a/src/backend/gl/glx.c b/src/backend/gl/glx.c index af2f891e..c86ccb55 100644 --- a/src/backend/gl/glx.c +++ b/src/backend/gl/glx.c @@ -54,10 +54,13 @@ struct _glx_data { } \ } while (0) -struct glx_fbconfig_info *glx_find_fbconfig(struct x_connection *c, struct xvisual_info m) { +bool glx_find_fbconfig(struct x_connection *c, struct xvisual_info m, + struct glx_fbconfig_info *info) { log_debug("Looking for FBConfig for RGBA%d%d%d%d, depth %d", m.red_size, m.blue_size, m.green_size, m.alpha_size, m.visual_depth); + info->cfg = NULL; + int ncfg; // clang-format off GLXFBConfig *cfg = @@ -143,16 +146,13 @@ struct glx_fbconfig_info *glx_find_fbconfig(struct x_connection *c, struct xvisu min_cost = depthbuf + stencil + bufsize * (doublebuf + 1); } free(cfg); - if (!found) { - return NULL; + if (found) { + info->cfg = ret; + info->texture_tgts = texture_tgts; + info->texture_fmt = texture_fmt; + info->y_inverted = y_inverted; } - - auto info = cmalloc(struct glx_fbconfig_info); - info->cfg = ret; - info->texture_tgts = texture_tgts; - info->texture_fmt = texture_fmt; - info->y_inverted = y_inverted; - return info; + return found; } /** @@ -394,8 +394,8 @@ glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b wd->inner = (struct backend_image_inner_base *)inner; free(r); - auto fbcfg = glx_find_fbconfig(base->c, fmt); - if (!fbcfg) { + struct glx_fbconfig_info fbcfg; + if (!glx_find_fbconfig(base->c, fmt, &fbcfg)) { log_error("Couldn't find FBConfig with requested visual %x", fmt.visual); goto err; } @@ -403,29 +403,28 @@ glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b // Choose a suitable texture target for our pixmap. // Refer to GLX_EXT_texture_om_pixmap spec to see what are the mean // of the bits in texture_tgts - if (!(fbcfg->texture_tgts & GLX_TEXTURE_2D_BIT_EXT)) { + if (!(fbcfg.texture_tgts & GLX_TEXTURE_2D_BIT_EXT)) { log_error("Cannot bind pixmap to GL_TEXTURE_2D, giving up"); goto err; } log_debug("depth %d, rgba %d", fmt.visual_depth, - (fbcfg->texture_fmt == GLX_TEXTURE_FORMAT_RGBA_EXT)); + (fbcfg.texture_fmt == GLX_TEXTURE_FORMAT_RGBA_EXT)); GLint attrs[] = { GLX_TEXTURE_FORMAT_EXT, - fbcfg->texture_fmt, + fbcfg.texture_fmt, GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, 0, }; - inner->y_inverted = fbcfg->y_inverted; + inner->y_inverted = fbcfg.y_inverted; glxpixmap = cmalloc(struct _glx_pixmap); glxpixmap->pixmap = pixmap; - glxpixmap->glpixmap = glXCreatePixmap(base->c->dpy, fbcfg->cfg, pixmap, attrs); + glxpixmap->glpixmap = glXCreatePixmap(base->c->dpy, fbcfg.cfg, pixmap, attrs); glxpixmap->owned = owned; - free(fbcfg); if (!glxpixmap->glpixmap) { log_error("Failed to create glpixmap for pixmap %#010x", pixmap); diff --git a/src/backend/gl/glx.h b/src/backend/gl/glx.h index 86701023..71679365 100644 --- a/src/backend/gl/glx.h +++ b/src/backend/gl/glx.h @@ -19,7 +19,8 @@ struct glx_fbconfig_info { int y_inverted; }; -struct glx_fbconfig_info *glx_find_fbconfig(struct x_connection *, struct xvisual_info); +bool glx_find_fbconfig(struct x_connection *c, struct xvisual_info m, + struct glx_fbconfig_info *info); struct glxext_info { bool initialized; diff --git a/src/common.h b/src/common.h index 6ba9b4f8..35316e10 100644 --- a/src/common.h +++ b/src/common.h @@ -204,7 +204,7 @@ typedef struct session { /// Custom GLX program used for painting window. // XXX should be in struct glx_session glx_prog_main_t glx_prog_win; - struct glx_fbconfig_info *argb_fbconfig; + struct glx_fbconfig_info argb_fbconfig; #endif /// Sync fence to sync draw operations xcb_sync_fence_t sync_fence; diff --git a/src/opengl.c b/src/opengl.c index eb40f1b3..26679b37 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -279,7 +279,7 @@ void glx_destroy(session_t *ps) { free(ps->psglx); ps->psglx = NULL; - ps->argb_fbconfig = NULL; + ps->argb_fbconfig = (struct glx_fbconfig_info){0}; } /** diff --git a/src/opengl.h b/src/opengl.h index 6f6da068..5bf92ed4 100644 --- a/src/opengl.h +++ b/src/opengl.h @@ -228,10 +228,7 @@ static inline void free_texture(session_t *ps, glx_texture_t **pptex) { */ static inline void free_paint_glx(session_t *ps, paint_t *ppaint) { free_texture(ps, &ppaint->ptex); -#ifdef CONFIG_OPENGL - free(ppaint->fbcfg); -#endif - ppaint->fbcfg = NULL; + ppaint->fbcfg = (struct glx_fbconfig_info){0}; } /** diff --git a/src/picom.c b/src/picom.c index 841c6f32..ff355480 100644 --- a/src/picom.c +++ b/src/picom.c @@ -2640,11 +2640,6 @@ static void session_destroy(session_t *ps) { unredirect(ps); } -#ifdef CONFIG_OPENGL - free(ps->argb_fbconfig); - ps->argb_fbconfig = NULL; -#endif - file_watch_destroy(ps->loop, ps->file_watch_handle); ps->file_watch_handle = NULL; diff --git a/src/render.c b/src/render.c index 371a9be7..a76f1e90 100644 --- a/src/render.c +++ b/src/render.c @@ -55,19 +55,20 @@ static inline bool paint_bind_tex(session_t *ps, paint_t *ppaint, int wid, int h struct glx_fbconfig_info *fbcfg; if (!visual) { assert(depth == 32); - if (!ps->argb_fbconfig) { - ps->argb_fbconfig = glx_find_fbconfig( - &ps->c, (struct xvisual_info){.red_size = 8, - .green_size = 8, - .blue_size = 8, - .alpha_size = 8, - .visual_depth = 32}); + if (!ps->argb_fbconfig.cfg) { + glx_find_fbconfig(&ps->c, + (struct xvisual_info){.red_size = 8, + .green_size = 8, + .blue_size = 8, + .alpha_size = 8, + .visual_depth = 32}, + &ps->argb_fbconfig); } - if (!ps->argb_fbconfig) { + if (!ps->argb_fbconfig.cfg) { log_error("Failed to find appropriate FBConfig for 32 bit depth"); return false; } - fbcfg = ps->argb_fbconfig; + fbcfg = &ps->argb_fbconfig; } else { auto m = x_get_visual_info(&ps->c, visual); if (m.visual_depth < 0) { @@ -79,14 +80,14 @@ static inline bool paint_bind_tex(session_t *ps, paint_t *ppaint, int wid, int h return false; } - if (!ppaint->fbcfg) { - ppaint->fbcfg = glx_find_fbconfig(&ps->c, m); + if (!ppaint->fbcfg.cfg) { + glx_find_fbconfig(&ps->c, m, &ppaint->fbcfg); } - if (!ppaint->fbcfg) { + if (!ppaint->fbcfg.cfg) { log_error("Failed to find appropriate FBConfig for X pixmap"); return false; } - fbcfg = ppaint->fbcfg; + fbcfg = &ppaint->fbcfg; } if (force || !glx_tex_bound(ppaint->ptex, ppaint->pixmap)) { @@ -1528,7 +1529,7 @@ void deinit_render(session_t *ps) { free_root_tile(ps); #ifdef CONFIG_OPENGL - free(ps->root_tile_paint.fbcfg); + ps->root_tile_paint.fbcfg = (struct glx_fbconfig_info){0}; if (bkend_use_glx(ps)) { glx_destroy(ps); } diff --git a/src/render.h b/src/render.h index 4e0c7a81..62258f0e 100644 --- a/src/render.h +++ b/src/render.h @@ -21,7 +21,7 @@ typedef struct paint { xcb_render_picture_t pict; glx_texture_t *ptex; #ifdef CONFIG_OPENGL - struct glx_fbconfig_info *fbcfg; + struct glx_fbconfig_info fbcfg; #endif } paint_t; From 241d7f1d035524025df3186ac6cce51026245577 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Sat, 10 Feb 2024 14:32:08 +0000 Subject: [PATCH 3/4] backend: glx: cache GLX FBConfigs This should marginally speed up pixmap binding for the glx backend (we don't need FBConfigs for egl). Fix a long running complaint in #381 (unrelated issue, but there is complaint in there about glXChooseFBConfig being called whenever we bind a new pixmap). Signed-off-by: Yuxuan Shui --- src/backend/gl/glx.c | 52 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/src/backend/gl/glx.c b/src/backend/gl/glx.c index c86ccb55..215f7b23 100644 --- a/src/backend/gl/glx.c +++ b/src/backend/gl/glx.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -44,6 +45,13 @@ struct _glx_data { struct gl_data gl; xcb_window_t target_win; GLXContext ctx; + struct glx_fbconfig_cache *cached_fbconfigs; +}; + +struct glx_fbconfig_cache { + UT_hash_handle hh; + struct xvisual_info visual_info; + struct glx_fbconfig_info info; }; #define glXGetFBConfigAttribChecked(a, b, attr, c) \ @@ -56,8 +64,8 @@ struct _glx_data { bool glx_find_fbconfig(struct x_connection *c, struct xvisual_info m, struct glx_fbconfig_info *info) { - log_debug("Looking for FBConfig for RGBA%d%d%d%d, depth %d", m.red_size, - m.blue_size, m.green_size, m.alpha_size, m.visual_depth); + log_debug("Looking for FBConfig for RGBA%d%d%d%d, depth: %d, visual id: %#x", m.red_size, + m.blue_size, m.green_size, m.alpha_size, m.visual_depth, m.visual); info->cfg = NULL; @@ -197,6 +205,12 @@ void glx_deinit(backend_t *base) { gd->ctx = 0; } + struct glx_fbconfig_cache *cached_fbconfig = NULL, *tmp = NULL; + HASH_ITER(hh, gd->cached_fbconfigs, cached_fbconfig, tmp) { + HASH_DEL(gd->cached_fbconfigs, cached_fbconfig); + free(cached_fbconfig); + } + free(gd); } @@ -367,6 +381,7 @@ end: static void * glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, bool owned) { struct _glx_pixmap *glxpixmap = NULL; + auto gd = (struct _glx_data *)base; // Retrieve pixmap parameters, if they aren't provided if (fmt.visual_depth > OPENGL_MAX_DEPTH) { log_error("Requested depth %d higher than max possible depth %d.", @@ -394,36 +409,51 @@ glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b wd->inner = (struct backend_image_inner_base *)inner; free(r); - struct glx_fbconfig_info fbcfg; - if (!glx_find_fbconfig(base->c, fmt, &fbcfg)) { - log_error("Couldn't find FBConfig with requested visual %x", fmt.visual); - goto err; + struct glx_fbconfig_cache *cached_fbconfig = NULL; + HASH_FIND(hh, gd->cached_fbconfigs, &fmt, sizeof(fmt), cached_fbconfig); + if (!cached_fbconfig) { + struct glx_fbconfig_info fbconfig; + if (!glx_find_fbconfig(base->c, fmt, &fbconfig)) { + log_error("Couldn't find FBConfig with requested visual %#x", + fmt.visual); + goto err; + } + cached_fbconfig = cmalloc(struct glx_fbconfig_cache); + cached_fbconfig->visual_info = fmt; + cached_fbconfig->info = fbconfig; + HASH_ADD(hh, gd->cached_fbconfigs, visual_info, sizeof(fmt), cached_fbconfig); + } else { + log_debug("Found cached FBConfig for RGBA%d%d%d%d, depth: %d, visual id: " + "%#x", + fmt.red_size, fmt.blue_size, fmt.green_size, fmt.alpha_size, + fmt.visual_depth, fmt.visual); } + struct glx_fbconfig_info *fbconfig = &cached_fbconfig->info; // Choose a suitable texture target for our pixmap. // Refer to GLX_EXT_texture_om_pixmap spec to see what are the mean // of the bits in texture_tgts - if (!(fbcfg.texture_tgts & GLX_TEXTURE_2D_BIT_EXT)) { + if (!(fbconfig->texture_tgts & GLX_TEXTURE_2D_BIT_EXT)) { log_error("Cannot bind pixmap to GL_TEXTURE_2D, giving up"); goto err; } log_debug("depth %d, rgba %d", fmt.visual_depth, - (fbcfg.texture_fmt == GLX_TEXTURE_FORMAT_RGBA_EXT)); + (fbconfig->texture_fmt == GLX_TEXTURE_FORMAT_RGBA_EXT)); GLint attrs[] = { GLX_TEXTURE_FORMAT_EXT, - fbcfg.texture_fmt, + fbconfig->texture_fmt, GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, 0, }; - inner->y_inverted = fbcfg.y_inverted; + inner->y_inverted = fbconfig->y_inverted; glxpixmap = cmalloc(struct _glx_pixmap); glxpixmap->pixmap = pixmap; - glxpixmap->glpixmap = glXCreatePixmap(base->c->dpy, fbcfg.cfg, pixmap, attrs); + glxpixmap->glpixmap = glXCreatePixmap(base->c->dpy, fbconfig->cfg, pixmap, attrs); glxpixmap->owned = owned; if (!glxpixmap->glpixmap) { From 85bb56e8a6f056fa11937453c70503b28396f7df Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Wed, 14 Feb 2024 18:26:50 +0000 Subject: [PATCH 4/4] Update CHANGELOG.md Signed-off-by: Yuxuan Shui --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 330d69c2..c993ddef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ * Allow `corner-radius-rules` to override `corner-radius = 0`. Previously setting corner radius to 0 globally disables rounded corners. (#1170) +## Notable changes + +* Marginally improve performance when resizing/opening/closing windows. (#1190) + # v11.2 (2024-Feb-13) ## Build changes