core: use a long-lived XFixes region

This is a workaround for #301. This doesn't fix the bug, but by
allocating X resources much less frequently, this should make the
bug almost never happen.

Also, it might generally be a good idea to not create/destroy X
resources so often. (XFixes Region accounts for >99% of the resource
creations/destructions)

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2020-08-30 09:11:45 +01:00
parent 82403578b3
commit 292c1e57f6
No known key found for this signature in database
GPG Key ID: 37C999F617EA1A47
3 changed files with 18 additions and 5 deletions

View File

@ -230,6 +230,10 @@ typedef struct session {
bool tmout_unredir_hit;
/// Whether we need to redraw the screen
bool redraw_needed;
/// Cache a xfixes region so we don't need to allocate it everytime.
/// A workaround for yshui/picom#301
xcb_xfixes_region_t damaged_region;
/// The region needs to painted on next paint.
region_t *damage;
/// The region damaged on the last paint.

View File

@ -591,11 +591,9 @@ static inline void repair_win(session_t *ps, struct managed_win *w) {
set_ignore_cookie(
ps, xcb_damage_subtract(ps->c, w->damage, XCB_NONE, XCB_NONE));
} else {
xcb_xfixes_region_t tmp = x_new_id(ps->c);
xcb_xfixes_create_region(ps->c, tmp, 0, NULL);
set_ignore_cookie(ps, xcb_damage_subtract(ps->c, w->damage, XCB_NONE, tmp));
x_fetch_region(ps->c, tmp, &parts);
xcb_xfixes_destroy_region(ps->c, tmp);
set_ignore_cookie(
ps, xcb_damage_subtract(ps->c, w->damage, XCB_NONE, ps->damaged_region));
x_fetch_region(ps->c, ps->damaged_region, &parts);
pixman_region32_translate(&parts, w->g.x + w->g.border_width,
w->g.y + w->g.border_width);
}

View File

@ -1750,6 +1750,12 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
XCB_XFIXES_MINOR_VERSION)
.sequence);
ps->damaged_region = x_new_id(ps->c);
if (!XCB_AWAIT_VOID(xcb_xfixes_create_region, ps->c, ps->damaged_region, 0, NULL)) {
log_fatal("Failed to create a XFixes region");
goto err;
}
ext_info = xcb_get_extension_data(ps->c, &xcb_glx_id);
if (ext_info && ext_info->present) {
ps->glx_exists = true;
@ -2279,6 +2285,11 @@ static void session_destroy(session_t *ps) {
ps->debug_window = XCB_NONE;
}
if (ps->damaged_region != XCB_NONE) {
xcb_xfixes_destroy_region(ps->c, ps->damaged_region);
ps->damaged_region = XCB_NONE;
}
if (ps->o.experimental_backends) {
// backend is deinitialized in unredirect()
assert(ps->backend_data == NULL);