backend/x11: keep track of exposed rects, add them to damage regions

When we receive an Expose event, that means that we must redraw that
region of the X11 window. Keep track of these regions with pixman
regions, and merge them with the additional output damaged regions.

Fixes #2670
This commit is contained in:
Ilia Mirkin 2021-01-21 06:24:52 -05:00 committed by Simon Ser
parent 922b7f415d
commit 7bc8dbb991
3 changed files with 13 additions and 2 deletions

View file

@ -72,6 +72,9 @@ 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(
&output->exposed, &output->exposed,
ev->x, ev->y, ev->width, ev->height);
wlr_output_update_needs_frame(&output->wlr_output); wlr_output_update_needs_frame(&output->wlr_output);
} }
break; break;

View file

@ -75,6 +75,8 @@ static void output_destroy(struct wlr_output *wlr_output) {
struct wlr_x11_output *output = get_x11_output_from_output(wlr_output); struct wlr_x11_output *output = get_x11_output_from_output(wlr_output);
struct wlr_x11_backend *x11 = output->x11; struct wlr_x11_backend *x11 = output->x11;
pixman_region32_fini(&output->exposed);
wlr_input_device_destroy(&output->pointer_dev); wlr_input_device_destroy(&output->pointer_dev);
wlr_input_device_destroy(&output->touch_dev); wlr_input_device_destroy(&output->touch_dev);
@ -242,10 +244,10 @@ 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 (output->wlr_output.pending.committed & WLR_OUTPUT_STATE_DAMAGE) { if (output->wlr_output.pending.committed & WLR_OUTPUT_STATE_DAMAGE) {
pixman_region32_t *damage = &output->wlr_output.pending.damage; pixman_region32_union(&output->exposed, &output->exposed, &output->wlr_output.pending.damage);
int rects_len = 0; int rects_len = 0;
pixman_box32_t *rects = pixman_region32_rectangles(damage, &rects_len); pixman_box32_t *rects = pixman_region32_rectangles(&output->exposed, &rects_len);
xcb_rectangle_t *xcb_rects = calloc(rects_len, sizeof(xcb_rectangle_t)); xcb_rectangle_t *xcb_rects = calloc(rects_len, sizeof(xcb_rectangle_t));
if (!xcb_rects) { if (!xcb_rects) {
@ -268,6 +270,8 @@ static bool output_commit_buffer(struct wlr_x11_output *output) {
free(xcb_rects); free(xcb_rects);
} }
pixman_region32_clear(&output->exposed);
uint32_t serial = output->wlr_output.commit_seq; uint32_t serial = output->wlr_output.commit_seq;
uint32_t options = 0; uint32_t options = 0;
uint64_t target_msc = output->last_msc ? output->last_msc + 1 : 0; uint64_t target_msc = output->last_msc ? output->last_msc + 1 : 0;
@ -363,6 +367,7 @@ struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend) {
} }
output->x11 = x11; output->x11 = x11;
wl_list_init(&output->buffers); wl_list_init(&output->buffers);
pixman_region32_init(&output->exposed);
struct wlr_output *wlr_output = &output->wlr_output; struct wlr_output *wlr_output = &output->wlr_output;
wlr_output_init(wlr_output, &x11->backend, &output_impl, x11->wl_display); wlr_output_init(wlr_output, &x11->backend, &output_impl, x11->wl_display);

View file

@ -14,6 +14,7 @@
#include <xcb/xcb_errors.h> #include <xcb/xcb_errors.h>
#endif #endif
#include <pixman.h>
#include <wlr/backend/x11.h> #include <wlr/backend/x11.h>
#include <wlr/interfaces/wlr_input_device.h> #include <wlr/interfaces/wlr_input_device.h>
#include <wlr/interfaces/wlr_keyboard.h> #include <wlr/interfaces/wlr_keyboard.h>
@ -47,6 +48,8 @@ struct wlr_x11_output {
struct wl_list buffers; // wlr_x11_buffer::link struct wl_list buffers; // wlr_x11_buffer::link
pixman_region32_t exposed;
uint64_t last_msc; uint64_t last_msc;
}; };