mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-04-14 08:22:25 -04:00
backend/x11: re-send last buffer on expose event
Instead of requesting a new frame from the compositor when we receive an expose event, re-submit the last frame. This makes the X11 backend behave like the other backends and removes the last wlr_output_update_needs_frame() call in backends, at the cost of keeping the current buffer locked for potentially a longer time.
This commit is contained in:
parent
664ec59095
commit
5da9ad3e34
3 changed files with 81 additions and 27 deletions
|
|
@ -69,10 +69,7 @@ static void handle_x11_event(struct wlr_x11_backend *x11,
|
||||||
struct wlr_x11_output *output =
|
struct wlr_x11_output *output =
|
||||||
get_x11_output_from_window_id(x11, ev->window);
|
get_x11_output_from_window_id(x11, ev->window);
|
||||||
if (output != NULL) {
|
if (output != NULL) {
|
||||||
pixman_region32_union_rect(
|
handle_x11_expose_event(output, ev);
|
||||||
&output->exposed, &output->exposed,
|
|
||||||
ev->x, ev->y, ev->width, ev->height);
|
|
||||||
wlr_output_update_needs_frame(&output->wlr_output);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,7 @@ static void output_destroy(struct wlr_output *wlr_output) {
|
||||||
|
|
||||||
wlr_pointer_finish(&output->pointer);
|
wlr_pointer_finish(&output->pointer);
|
||||||
wlr_touch_finish(&output->touch);
|
wlr_touch_finish(&output->touch);
|
||||||
|
wlr_buffer_unlock(output->current_buffer);
|
||||||
|
|
||||||
struct wlr_x11_buffer *buffer, *buffer_tmp;
|
struct wlr_x11_buffer *buffer, *buffer_tmp;
|
||||||
wl_list_for_each_safe(buffer, buffer_tmp, &output->buffers, link) {
|
wl_list_for_each_safe(buffer, buffer_tmp, &output->buffers, link) {
|
||||||
|
|
@ -286,6 +287,34 @@ static struct wlr_x11_buffer *get_or_create_x11_buffer(
|
||||||
return create_x11_buffer(output, wlr_buffer);
|
return create_x11_buffer(output, wlr_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static xcb_xfixes_region_t create_region(struct wlr_x11_backend *x11,
|
||||||
|
const pixman_region32_t *region) {
|
||||||
|
int rects_len = 0;
|
||||||
|
const pixman_box32_t *rects = pixman_region32_rectangles(region, &rects_len);
|
||||||
|
|
||||||
|
xcb_rectangle_t *xcb_rects = calloc(rects_len, sizeof(xcb_rectangle_t));
|
||||||
|
if (!xcb_rects) {
|
||||||
|
return XCB_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < rects_len; i++) {
|
||||||
|
const pixman_box32_t *box = &rects[i];
|
||||||
|
xcb_rects[i] = (struct xcb_rectangle_t){
|
||||||
|
.x = box->x1,
|
||||||
|
.y = box->y1,
|
||||||
|
.width = box->x2 - box->x1,
|
||||||
|
.height = box->y2 - box->y1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_xfixes_region_t x11_region = xcb_generate_id(x11->xcb);
|
||||||
|
xcb_xfixes_create_region(x11->xcb, x11_region, rects_len, xcb_rects);
|
||||||
|
|
||||||
|
free(xcb_rects);
|
||||||
|
|
||||||
|
return x11_region;
|
||||||
|
}
|
||||||
|
|
||||||
static bool output_commit_buffer(struct wlr_x11_output *output,
|
static bool output_commit_buffer(struct wlr_x11_output *output,
|
||||||
const struct wlr_output_state *state) {
|
const struct wlr_output_state *state) {
|
||||||
struct wlr_x11_backend *x11 = output->x11;
|
struct wlr_x11_backend *x11 = output->x11;
|
||||||
|
|
@ -300,29 +329,7 @@ static bool output_commit_buffer(struct wlr_x11_output *output,
|
||||||
xcb_xfixes_region_t region = XCB_NONE;
|
xcb_xfixes_region_t region = XCB_NONE;
|
||||||
if (state->committed & WLR_OUTPUT_STATE_DAMAGE) {
|
if (state->committed & WLR_OUTPUT_STATE_DAMAGE) {
|
||||||
pixman_region32_union(&output->exposed, &output->exposed, &state->damage);
|
pixman_region32_union(&output->exposed, &output->exposed, &state->damage);
|
||||||
|
region = create_region(x11, &output->exposed);
|
||||||
int rects_len = 0;
|
|
||||||
const pixman_box32_t *rects = pixman_region32_rectangles(&output->exposed, &rects_len);
|
|
||||||
|
|
||||||
xcb_rectangle_t *xcb_rects = calloc(rects_len, sizeof(xcb_rectangle_t));
|
|
||||||
if (!xcb_rects) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < rects_len; i++) {
|
|
||||||
const pixman_box32_t *box = &rects[i];
|
|
||||||
xcb_rects[i] = (struct xcb_rectangle_t){
|
|
||||||
.x = box->x1,
|
|
||||||
.y = box->y1,
|
|
||||||
.width = box->x2 - box->x1,
|
|
||||||
.height = box->y2 - box->y1,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
region = xcb_generate_id(x11->xcb);
|
|
||||||
xcb_xfixes_create_region(x11->xcb, region, rects_len, xcb_rects);
|
|
||||||
|
|
||||||
free(xcb_rects);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pixman_region32_clear(&output->exposed);
|
pixman_region32_clear(&output->exposed);
|
||||||
|
|
@ -338,6 +345,9 @@ static bool output_commit_buffer(struct wlr_x11_output *output,
|
||||||
xcb_xfixes_destroy_region(x11->xcb, region);
|
xcb_xfixes_destroy_region(x11->xcb, region);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wlr_buffer_unlock(output->current_buffer);
|
||||||
|
output->current_buffer = wlr_buffer_lock(buffer);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
|
@ -705,6 +715,12 @@ void handle_x11_present_event(struct wlr_x11_backend *x11,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (output->last_msc == complete_notify->msc && complete_notify->serial == 0) {
|
||||||
|
// This is a present complete event triggered by a synthetic
|
||||||
|
// present request sent from handle_x11_expose_event()
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
output->last_msc = complete_notify->msc;
|
output->last_msc = complete_notify->msc;
|
||||||
|
|
||||||
struct timespec t;
|
struct timespec t;
|
||||||
|
|
@ -732,3 +748,39 @@ void handle_x11_present_event(struct wlr_x11_backend *x11,
|
||||||
wlr_log(WLR_DEBUG, "Unhandled Present event %"PRIu16, event->event_type);
|
wlr_log(WLR_DEBUG, "Unhandled Present event %"PRIu16, event->event_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handle_x11_expose_event(struct wlr_x11_output *output,
|
||||||
|
xcb_expose_event_t *ev) {
|
||||||
|
struct wlr_x11_backend *x11 = output->x11;
|
||||||
|
|
||||||
|
pixman_region32_union_rect(&output->exposed, &output->exposed,
|
||||||
|
ev->x, ev->y, ev->width, ev->height);
|
||||||
|
|
||||||
|
if (output->current_buffer == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have access to the last submitted buffer, re-send the previous
|
||||||
|
// present request
|
||||||
|
|
||||||
|
struct wlr_x11_buffer *x11_buffer =
|
||||||
|
get_or_create_x11_buffer(output, output->current_buffer);
|
||||||
|
if (!x11_buffer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_xfixes_region_t region = create_region(x11, &output->exposed);
|
||||||
|
|
||||||
|
pixman_region32_clear(&output->exposed);
|
||||||
|
|
||||||
|
uint32_t serial = 0;
|
||||||
|
uint32_t options = 0;
|
||||||
|
uint64_t target_msc = output->last_msc;
|
||||||
|
xcb_present_pixmap(x11->xcb, output->win, x11_buffer->pixmap, serial,
|
||||||
|
0, region, 0, 0, XCB_NONE, XCB_NONE, XCB_NONE, options, target_msc,
|
||||||
|
0, 0, 0, NULL);
|
||||||
|
|
||||||
|
if (region != XCB_NONE) {
|
||||||
|
xcb_xfixes_destroy_region(x11->xcb, region);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,9 @@ struct wlr_x11_output {
|
||||||
|
|
||||||
pixman_region32_t exposed;
|
pixman_region32_t exposed;
|
||||||
|
|
||||||
|
// Last submitted buffer, to be re-submitted on expose events
|
||||||
|
struct wlr_buffer *current_buffer;
|
||||||
|
|
||||||
uint64_t last_msc;
|
uint64_t last_msc;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -141,5 +144,7 @@ void handle_x11_configure_notify(struct wlr_x11_output *output,
|
||||||
xcb_configure_notify_event_t *event);
|
xcb_configure_notify_event_t *event);
|
||||||
void handle_x11_present_event(struct wlr_x11_backend *x11,
|
void handle_x11_present_event(struct wlr_x11_backend *x11,
|
||||||
xcb_ge_generic_event_t *event);
|
xcb_ge_generic_event_t *event);
|
||||||
|
void handle_x11_expose_event(struct wlr_x11_output *output,
|
||||||
|
xcb_expose_event_t *event);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue