Merge pull request #1190 from yshui/cache-fbconfig

cache GLX fbconfigs
This commit is contained in:
Maxim Solovyov 2024-02-14 23:23:29 +03:00 committed by GitHub
commit 2238cf1e54
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 76 additions and 63 deletions

View File

@ -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

View File

@ -17,6 +17,7 @@
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <uthash.h>
#include <xcb/composite.h>
#include <xcb/xcb.h>
#include <xcb/xcb_aux.h>
@ -45,6 +46,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) \
@ -55,9 +63,12 @@ struct _glx_data {
} \
} while (0)
struct glx_fbconfig_info *glx_find_fbconfig(struct x_connection *c, struct xvisual_info m) {
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);
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, visual id: %#x", m.red_size,
m.blue_size, m.green_size, m.alpha_size, m.visual_depth, m.visual);
info->cfg = NULL;
int ncfg;
// clang-format off
@ -145,16 +156,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;
}
/**
@ -199,6 +207,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);
}
@ -369,6 +383,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.",
@ -396,38 +411,52 @@ 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) {
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;
free(fbcfg);
if (!glxpixmap->glpixmap) {
log_error("Failed to create glpixmap for pixmap %#010x", pixmap);

View File

@ -19,21 +19,8 @@ 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);
bool glx_find_fbconfig(struct x_connection *c, struct xvisual_info m,
struct glx_fbconfig_info *info);
struct glxext_info {
bool initialized;

View File

@ -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;

View File

@ -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};
}
/**

View File

@ -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};
}
/**

View File

@ -2641,11 +2641,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;

View File

@ -56,19 +56,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) {
@ -80,14 +81,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)) {
@ -1529,7 +1530,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);
}

View File

@ -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;