*/
#include <fcntl.h>
-#include <poll.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <xcb/xcb.h>
#include <xcb/dri3.h>
#include <xcb/present.h>
+#include <xcb/xfixes.h>
#include <X11/Xlib-xcb.h>
xcb_generic_event_t *ev;
xcb_present_generic_event_t *ge;
- if (draw->window_destroyed)
- return false;
-
xcb_flush(draw->conn);
/* Only have one thread waiting for events at a time */
if (draw->has_event_waiter) {
cnd_wait(&draw->event_cnd, &draw->mtx);
- if (draw->window_destroyed)
- return false;
if (full_sequence)
*full_sequence = draw->last_special_event_sequence;
/* Another thread has updated the protected info, so retest. */
return true;
} else {
- struct pollfd pfds;
-
draw->has_event_waiter = true;
/* Allow other threads access to the drawable while we're waiting. */
mtx_unlock(&draw->mtx);
-
- pfds.fd = xcb_get_file_descriptor(draw->conn);
- pfds.events = POLLIN;
-
- ev = xcb_poll_for_special_event(draw->conn, draw->special_event);
- while (!ev) {
- /* Wait up to ~1s for the XCB FD to become readable */
- if (poll(&pfds, 1, 1000) < 1) {
- xcb_get_window_attributes_cookie_t cookie;
- xcb_get_window_attributes_reply_t *attrib;
- xcb_generic_error_t *error;
-
- /* Check if the window still exists */
- cookie = xcb_get_window_attributes(draw->conn, draw->drawable);
- attrib = xcb_get_window_attributes_reply(draw->conn, cookie, &error);
- free(attrib);
-
- if (error) {
- if (error->error_code == BadWindow)
- draw->window_destroyed = true;
-
- free(error);
- break;
- }
- }
-
- ev = xcb_poll_for_special_event(draw->conn, draw->special_event);
- }
-
+ ev = xcb_wait_for_special_event(draw->conn, draw->special_event);
mtx_lock(&draw->mtx);
draw->has_event_waiter = false;
cnd_broadcast(&draw->event_cnd);
loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw,
int64_t target_msc, int64_t divisor,
int64_t remainder, unsigned flush_flags,
+ const int *rects, int n_rects,
bool force_copy)
{
struct loader_dri3_buffer *back;
#endif
back->busy = 1;
back->last_swap = draw->send_sbc;
+
+ xcb_xfixes_region_t region = 0;
+ xcb_rectangle_t xcb_rects[64];
+
+ if (n_rects > 0 && n_rects <= ARRAY_SIZE(xcb_rects)) {
+ for (int i = 0; i < n_rects; i++) {
+ const int *rect = &rects[i * 4];
+ xcb_rects[i].x = rect[0];
+ xcb_rects[i].y = draw->height - rect[1] - rect[3];
+ xcb_rects[i].width = rect[2];
+ xcb_rects[i].height = rect[3];
+ }
+
+ region = xcb_generate_id(draw->conn);
+ xcb_xfixes_create_region(draw->conn, region, n_rects, xcb_rects);
+ }
+
xcb_present_pixmap(draw->conn,
draw->drawable,
back->pixmap,
(uint32_t) draw->send_sbc,
0, /* valid */
- 0, /* update */
+ region, /* update */
0, /* x_off */
0, /* y_off */
None, /* target_crtc */
remainder, 0, NULL);
ret = (int64_t) draw->send_sbc;
+ if (region)
+ xcb_xfixes_destroy_region(draw->conn, region);
+
/* Schedule a server-side back-preserving blit if necessary.
* This happens iff all conditions below are satisfied:
* a) We have a fake front,