mirror of https://github.com/yshui/picom.git
Merge pull request #1167 from absolutelynothelix/xrender-cache-present-region
temporary workaround for #1166
This commit is contained in:
commit
fc1d1d40e5
|
@ -56,6 +56,10 @@ typedef struct _xrender_data {
|
|||
int target_width, target_height;
|
||||
|
||||
xcb_special_event_t *present_event;
|
||||
|
||||
/// Cache an X region to avoid creating and destroying it every frame. A
|
||||
/// workaround for yshui/picom#1166.
|
||||
xcb_xfixes_region_t present_region;
|
||||
} xrender_data;
|
||||
|
||||
struct _xrender_blur_context {
|
||||
|
@ -597,6 +601,7 @@ static void deinit(backend_t *backend_data) {
|
|||
xcb_free_pixmap(xd->base.c->c, xd->back_pixmap[i]);
|
||||
}
|
||||
}
|
||||
x_destroy_region(xd->base.c, xd->present_region);
|
||||
if (xd->present_event) {
|
||||
xcb_unregister_for_special_event(xd->base.c->c, xd->present_event);
|
||||
}
|
||||
|
@ -624,16 +629,15 @@ static void present(backend_t *base, const region_t *region) {
|
|||
XCB_NONE, xd->back[xd->curr_back], orig_x, orig_y, 0,
|
||||
0, orig_x, orig_y, region_width, region_height);
|
||||
|
||||
auto xregion = x_create_region(base->c, region);
|
||||
|
||||
// Make sure we got reply from PresentPixmap before waiting for events,
|
||||
// to avoid deadlock
|
||||
auto e = xcb_request_check(
|
||||
base->c->c, xcb_present_pixmap_checked(
|
||||
xd->base.c->c, xd->target_win,
|
||||
xd->back_pixmap[xd->curr_back], 0, XCB_NONE, xregion, 0,
|
||||
0, XCB_NONE, XCB_NONE, XCB_NONE, 0, 0, 0, 0, 0, NULL));
|
||||
x_destroy_region(base->c, xregion);
|
||||
base->c->c,
|
||||
xcb_present_pixmap_checked(
|
||||
base->c->c, xd->target_win, xd->back_pixmap[xd->curr_back], 0, XCB_NONE,
|
||||
x_set_region(base->c, xd->present_region, region) ? xd->present_region
|
||||
: XCB_NONE,
|
||||
0, 0, XCB_NONE, XCB_NONE, XCB_NONE, 0, 0, 0, 0, 0, NULL));
|
||||
if (e) {
|
||||
log_error("Failed to present pixmap");
|
||||
free(e);
|
||||
|
@ -929,6 +933,10 @@ static backend_t *backend_xrender_init(session_t *ps, xcb_window_t target) {
|
|||
xd->vsync = false;
|
||||
}
|
||||
|
||||
if (xd->vsync) {
|
||||
xd->present_region = x_create_region(&ps->c, &ps->screen_reg);
|
||||
}
|
||||
|
||||
// We might need to do double buffering for vsync, and buffer 0 and 1 are for
|
||||
// double buffering.
|
||||
int first_buffer_index = xd->vsync ? 0 : 2;
|
||||
|
|
28
src/x.c
28
src/x.c
|
@ -459,6 +459,34 @@ bool x_fetch_region(struct x_connection *c, xcb_xfixes_region_t r, pixman_region
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool x_set_region(struct x_connection *c, xcb_xfixes_region_t dst, const region_t *src) {
|
||||
if (!src || dst == XCB_NONE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t nrects = 0;
|
||||
const rect_t *rects = pixman_region32_rectangles((region_t *)src, &nrects);
|
||||
if (!rects || nrects < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
xcb_rectangle_t *xrects = ccalloc(nrects, xcb_rectangle_t);
|
||||
for (int32_t i = 0; i < nrects; i++) {
|
||||
xrects[i] =
|
||||
(xcb_rectangle_t){.x = to_i16_checked(rects[i].x1),
|
||||
.y = to_i16_checked(rects[i].y1),
|
||||
.width = to_u16_checked(rects[i].x2 - rects[i].x1),
|
||||
.height = to_u16_checked(rects[i].y2 - rects[i].y1)};
|
||||
}
|
||||
|
||||
bool success =
|
||||
XCB_AWAIT_VOID(xcb_xfixes_set_region, c->c, dst, to_u32_checked(nrects), xrects);
|
||||
|
||||
free(xrects);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
uint32_t x_create_region(struct x_connection *c, const region_t *reg) {
|
||||
if (!reg) {
|
||||
return XCB_NONE;
|
||||
|
|
3
src/x.h
3
src/x.h
|
@ -321,6 +321,9 @@ x_create_picture_with_visual(struct x_connection *, int w, int h, xcb_visualid_t
|
|||
/// Fetch a X region and store it in a pixman region
|
||||
bool x_fetch_region(struct x_connection *, xcb_xfixes_region_t r, region_t *res);
|
||||
|
||||
/// Set an X region to a pixman region
|
||||
bool x_set_region(struct x_connection *c, xcb_xfixes_region_t dst, const region_t *src);
|
||||
|
||||
/// Create a X region from a pixman region
|
||||
uint32_t x_create_region(struct x_connection *c, const region_t *reg);
|
||||
|
||||
|
|
Loading…
Reference in New Issue