#include <xcb/xcb.h>
#include <xcb/dri3.h>
#include <xcb/present.h>
+#include <xcb/xfixes.h>
#include <X11/Xlib-xcb.h>
#include "util/macros.h"
#include "drm-uapi/drm_fourcc.h"
-/* From xmlpool/options.h, user exposed so should be stable */
+/* From driconf.h, user exposed so should be stable */
#define DRI_CONF_VBLANK_NEVER 0
#define DRI_CONF_VBLANK_DEF_INTERVAL_0 1
#define DRI_CONF_VBLANK_DEF_INTERVAL_1 2
}
static bool
-dri3_wait_for_event_locked(struct loader_dri3_drawable *draw)
+dri3_wait_for_event_locked(struct loader_dri3_drawable *draw,
+ unsigned *full_sequence)
{
xcb_generic_event_t *ev;
xcb_present_generic_event_t *ge;
/* Only have one thread waiting for events at a time */
if (draw->has_event_waiter) {
cnd_wait(&draw->event_cnd, &draw->mtx);
+ if (full_sequence)
+ *full_sequence = draw->last_special_event_sequence;
/* Another thread has updated the protected info, so retest. */
return true;
} else {
}
if (!ev)
return false;
+ draw->last_special_event_sequence = ev->full_sequence;
+ if (full_sequence)
+ *full_sequence = ev->full_sequence;
ge = (void *) ev;
dri3_handle_present_event(draw, ge);
return true;
target_msc,
divisor,
remainder);
- xcb_generic_event_t *ev;
unsigned full_sequence;
mtx_lock(&draw->mtx);
- xcb_flush(draw->conn);
/* Wait for the event */
do {
- ev = xcb_wait_for_special_event(draw->conn, draw->special_event);
- if (!ev) {
+ if (!dri3_wait_for_event_locked(draw, &full_sequence)) {
mtx_unlock(&draw->mtx);
return false;
}
-
- full_sequence = ev->full_sequence;
- dri3_handle_present_event(draw, (void *) ev);
} while (full_sequence != cookie.sequence || draw->notify_msc < target_msc);
*ust = draw->notify_ust;
target_sbc = draw->send_sbc;
while (draw->recv_sbc < target_sbc) {
- if (!dri3_wait_for_event_locked(draw)) {
+ if (!dri3_wait_for_event_locked(draw, NULL)) {
mtx_unlock(&draw->mtx);
return 0;
}
return id;
}
}
- if (!dri3_wait_for_event_locked(draw)) {
+ if (!dri3_wait_for_event_locked(draw, NULL)) {
mtx_unlock(&draw->mtx);
return -1;
}
if (flush)
flags |= __DRI2_FLUSH_CONTEXT;
- loader_dri3_flush(draw, flags, __DRI2_THROTTLE_SWAPBUFFER);
+ loader_dri3_flush(draw, flags, __DRI2_THROTTLE_COPYSUBBUFFER);
back = dri3_find_back_alloc(draw);
if (!back)
xcb_drawable_t dest,
xcb_drawable_t src)
{
- loader_dri3_flush(draw, __DRI2_FLUSH_DRAWABLE, 0);
+ loader_dri3_flush(draw, __DRI2_FLUSH_DRAWABLE, __DRI2_THROTTLE_COPYSUBBUFFER);
dri3_fence_reset(draw->conn, dri3_fake_front_buffer(draw));
dri3_copy_area(draw->conn,
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,
case __DRI_IMAGE_FORMAT_ABGR2101010:
case __DRI_IMAGE_FORMAT_SARGB8:
case __DRI_IMAGE_FORMAT_SABGR8:
+ case __DRI_IMAGE_FORMAT_SXRGB8:
return 4;
case __DRI_IMAGE_FORMAT_XBGR16161616F:
case __DRI_IMAGE_FORMAT_ABGR16161616F:
switch (format) {
case __DRI_IMAGE_FORMAT_SARGB8: return __DRI_IMAGE_FOURCC_SARGB8888;
case __DRI_IMAGE_FORMAT_SABGR8: return __DRI_IMAGE_FOURCC_SABGR8888;
+ case __DRI_IMAGE_FORMAT_SXRGB8: return __DRI_IMAGE_FOURCC_SXRGB8888;
case __DRI_IMAGE_FORMAT_RGB565: return DRM_FORMAT_RGB565;
case __DRI_IMAGE_FORMAT_XRGB8888: return DRM_FORMAT_XRGB8888;
case __DRI_IMAGE_FORMAT_ARGB8888: return DRM_FORMAT_ARGB8888;
image = pixmap_buffer;
}
+ buffer_fds[i] = -1;
+
ret = draw->ext->image->queryImage(image, __DRI_IMAGE_ATTRIB_FD,
&buffer_fds[i]);
ret &= draw->ext->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE,
no_buffer_attrib:
do {
- close(buffer_fds[i]);
+ if (buffer_fds[i] != -1)
+ close(buffer_fds[i]);
} while (--i >= 0);
draw->ext->image->destroyImage(pixmap_buffer);
no_linear_buffer:
if (!loader_dri3_blit_image(draw,
new_buffer->image,
buffer->image,
- 0, 0, draw->width, draw->height,
+ 0, 0,
+ MIN2(buffer->width, new_buffer->width),
+ MIN2(buffer->height, new_buffer->height),
0, 0, 0) &&
!buffer->linear_buffer) {
dri3_fence_reset(draw->conn, new_buffer);