|
|
|
@@ -62,10 +62,54 @@ struct vl_dri_screen |
|
|
|
xcb_dri2_swap_buffers_cookie_t swap_cookie; |
|
|
|
xcb_dri2_wait_sbc_cookie_t wait_cookie; |
|
|
|
xcb_dri2_get_buffers_cookie_t buffers_cookie; |
|
|
|
|
|
|
|
int64_t last_ust, ns_frame, last_msc, next_msc, skew_msc; |
|
|
|
}; |
|
|
|
|
|
|
|
static const unsigned int attachments[1] = { XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT }; |
|
|
|
|
|
|
|
static void |
|
|
|
vl_dri2_handle_stamps(struct vl_dri_screen* scrn, |
|
|
|
uint32_t ust_hi, uint32_t ust_lo, |
|
|
|
uint32_t msc_hi, uint32_t msc_lo) |
|
|
|
{ |
|
|
|
int64_t ust = ((((uint64_t)ust_hi) << 32) | ust_lo) * 1000; |
|
|
|
int64_t msc = (((uint64_t)msc_hi) << 32) | msc_lo; |
|
|
|
|
|
|
|
if (scrn->last_ust && scrn->last_msc && (ust > scrn->last_ust) && (msc > scrn->last_msc)) |
|
|
|
scrn->ns_frame = (ust - scrn->last_ust) / (msc - scrn->last_msc); |
|
|
|
|
|
|
|
if (scrn->next_msc && (scrn->next_msc < msc)) |
|
|
|
scrn->skew_msc++; |
|
|
|
|
|
|
|
scrn->last_ust = ust; |
|
|
|
scrn->last_msc = msc; |
|
|
|
} |
|
|
|
|
|
|
|
static xcb_dri2_get_buffers_reply_t* |
|
|
|
vl_dri2_get_flush_reply(struct vl_dri_screen *scrn) |
|
|
|
{ |
|
|
|
xcb_dri2_wait_sbc_reply_t *wait_sbc_reply; |
|
|
|
|
|
|
|
assert(scrn); |
|
|
|
|
|
|
|
if (!scrn->flushed) |
|
|
|
return NULL; |
|
|
|
|
|
|
|
scrn->flushed = false; |
|
|
|
|
|
|
|
free(xcb_dri2_swap_buffers_reply(scrn->conn, scrn->swap_cookie, NULL)); |
|
|
|
|
|
|
|
wait_sbc_reply = xcb_dri2_wait_sbc_reply(scrn->conn, scrn->wait_cookie, NULL); |
|
|
|
if (!wait_sbc_reply) |
|
|
|
return NULL; |
|
|
|
vl_dri2_handle_stamps(scrn, wait_sbc_reply->ust_hi, wait_sbc_reply->ust_lo, |
|
|
|
wait_sbc_reply->msc_hi, wait_sbc_reply->msc_lo); |
|
|
|
free(wait_sbc_reply); |
|
|
|
|
|
|
|
return xcb_dri2_get_buffers_reply(scrn->conn, scrn->buffers_cookie, NULL); |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
vl_dri2_flush_frontbuffer(struct pipe_screen *screen, |
|
|
|
struct pipe_resource *resource, |
|
|
|
@@ -73,20 +117,22 @@ vl_dri2_flush_frontbuffer(struct pipe_screen *screen, |
|
|
|
void *context_private) |
|
|
|
{ |
|
|
|
struct vl_dri_screen *scrn = (struct vl_dri_screen*)context_private; |
|
|
|
uint32_t msc_hi, msc_lo; |
|
|
|
|
|
|
|
assert(screen); |
|
|
|
assert(resource); |
|
|
|
assert(context_private); |
|
|
|
|
|
|
|
if (scrn->flushed) |
|
|
|
free(xcb_dri2_swap_buffers_reply(scrn->conn, scrn->swap_cookie, NULL)); |
|
|
|
else |
|
|
|
scrn->flushed = true; |
|
|
|
free(vl_dri2_get_flush_reply(scrn)); |
|
|
|
|
|
|
|
msc_hi = scrn->next_msc >> 32; |
|
|
|
msc_lo = scrn->next_msc & 0xFFFFFFFF; |
|
|
|
|
|
|
|
scrn->swap_cookie = xcb_dri2_swap_buffers_unchecked(scrn->conn, scrn->drawable, 0, 0, 0, 0, 0, 0); |
|
|
|
scrn->swap_cookie = xcb_dri2_swap_buffers_unchecked(scrn->conn, scrn->drawable, msc_hi, msc_lo, 0, 0, 0, 0); |
|
|
|
scrn->wait_cookie = xcb_dri2_wait_sbc_unchecked(scrn->conn, scrn->drawable, 0, 0); |
|
|
|
scrn->buffers_cookie = xcb_dri2_get_buffers_unchecked(scrn->conn, scrn->drawable, 1, 1, attachments); |
|
|
|
|
|
|
|
scrn->flushed = true; |
|
|
|
scrn->current_buffer = !scrn->current_buffer; |
|
|
|
} |
|
|
|
|
|
|
|
@@ -95,12 +141,31 @@ vl_dri2_destroy_drawable(struct vl_dri_screen *scrn) |
|
|
|
{ |
|
|
|
xcb_void_cookie_t destroy_cookie; |
|
|
|
if (scrn->drawable) { |
|
|
|
free(vl_dri2_get_flush_reply(scrn)); |
|
|
|
destroy_cookie = xcb_dri2_destroy_drawable_checked(scrn->conn, scrn->drawable); |
|
|
|
/* ignore any error here, since the drawable can be destroyed long ago */ |
|
|
|
free(xcb_request_check(scrn->conn, destroy_cookie)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
vl_dri2_set_drawable(struct vl_dri_screen *scrn, Drawable drawable) |
|
|
|
{ |
|
|
|
assert(scrn); |
|
|
|
assert(drawable); |
|
|
|
|
|
|
|
if (scrn->drawable == drawable) |
|
|
|
return; |
|
|
|
|
|
|
|
vl_dri2_destroy_drawable(scrn); |
|
|
|
|
|
|
|
xcb_dri2_create_drawable(scrn->conn, drawable); |
|
|
|
scrn->current_buffer = false; |
|
|
|
vl_compositor_reset_dirty_area(&scrn->dirty_areas[0]); |
|
|
|
vl_compositor_reset_dirty_area(&scrn->dirty_areas[1]); |
|
|
|
scrn->drawable = drawable; |
|
|
|
} |
|
|
|
|
|
|
|
struct pipe_resource* |
|
|
|
vl_screen_texture_from_drawable(struct vl_screen *vscreen, Drawable drawable) |
|
|
|
{ |
|
|
|
@@ -114,42 +179,23 @@ vl_screen_texture_from_drawable(struct vl_screen *vscreen, Drawable drawable) |
|
|
|
|
|
|
|
assert(scrn); |
|
|
|
|
|
|
|
if (scrn->flushed) { |
|
|
|
free(xcb_dri2_swap_buffers_reply(scrn->conn, scrn->swap_cookie, NULL)); |
|
|
|
free(xcb_dri2_wait_sbc_reply(scrn->conn, scrn->wait_cookie, NULL)); |
|
|
|
vl_dri2_set_drawable(scrn, drawable); |
|
|
|
reply = vl_dri2_get_flush_reply(scrn); |
|
|
|
if (!reply) { |
|
|
|
xcb_dri2_get_buffers_cookie_t cookie; |
|
|
|
cookie = xcb_dri2_get_buffers_unchecked(scrn->conn, drawable, 1, 1, attachments); |
|
|
|
reply = xcb_dri2_get_buffers_reply(scrn->conn, cookie, NULL); |
|
|
|
} |
|
|
|
|
|
|
|
if (scrn->drawable != drawable) { |
|
|
|
vl_dri2_destroy_drawable(scrn); |
|
|
|
xcb_dri2_create_drawable(scrn->conn, drawable); |
|
|
|
scrn->current_buffer = false; |
|
|
|
vl_compositor_reset_dirty_area(&scrn->dirty_areas[0]); |
|
|
|
vl_compositor_reset_dirty_area(&scrn->dirty_areas[1]); |
|
|
|
scrn->drawable = drawable; |
|
|
|
|
|
|
|
if (scrn->flushed) { |
|
|
|
free(xcb_dri2_get_buffers_reply(scrn->conn, scrn->buffers_cookie, NULL)); |
|
|
|
scrn->flushed = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (!scrn->flushed) |
|
|
|
scrn->buffers_cookie = xcb_dri2_get_buffers_unchecked(scrn->conn, drawable, 1, 1, attachments); |
|
|
|
else |
|
|
|
scrn->flushed = false; |
|
|
|
|
|
|
|
reply = xcb_dri2_get_buffers_reply(scrn->conn, scrn->buffers_cookie, NULL); |
|
|
|
if (!reply) |
|
|
|
return NULL; |
|
|
|
|
|
|
|
assert(reply->count == 1); |
|
|
|
buffers = xcb_dri2_get_buffers_buffers(reply); |
|
|
|
if (!buffers) { |
|
|
|
free(reply); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
assert(reply->count == 1); |
|
|
|
|
|
|
|
if (reply->width != scrn->width || reply->height != scrn->height) { |
|
|
|
vl_compositor_reset_dirty_area(&scrn->dirty_areas[0]); |
|
|
|
vl_compositor_reset_dirty_area(&scrn->dirty_areas[1]); |
|
|
|
@@ -192,6 +238,40 @@ vl_screen_get_dirty_area(struct vl_screen *vscreen) |
|
|
|
return &scrn->dirty_areas[scrn->current_buffer]; |
|
|
|
} |
|
|
|
|
|
|
|
uint64_t |
|
|
|
vl_screen_get_timestamp(struct vl_screen *vscreen, Drawable drawable) |
|
|
|
{ |
|
|
|
struct vl_dri_screen *scrn = (struct vl_dri_screen*)vscreen; |
|
|
|
xcb_dri2_get_msc_cookie_t cookie; |
|
|
|
xcb_dri2_get_msc_reply_t *reply; |
|
|
|
|
|
|
|
assert(scrn); |
|
|
|
|
|
|
|
vl_dri2_set_drawable(scrn, drawable); |
|
|
|
if (!scrn->last_ust) { |
|
|
|
cookie = xcb_dri2_get_msc_unchecked(scrn->conn, drawable); |
|
|
|
reply = xcb_dri2_get_msc_reply(scrn->conn, cookie, NULL); |
|
|
|
|
|
|
|
if (reply) { |
|
|
|
vl_dri2_handle_stamps(scrn, reply->ust_hi, reply->ust_lo, |
|
|
|
reply->msc_hi, reply->msc_lo); |
|
|
|
free(reply); |
|
|
|
} |
|
|
|
} |
|
|
|
return scrn->last_ust; |
|
|
|
} |
|
|
|
|
|
|
|
void |
|
|
|
vl_screen_set_next_timestamp(struct vl_screen *vscreen, uint64_t stamp) |
|
|
|
{ |
|
|
|
struct vl_dri_screen *scrn = (struct vl_dri_screen*)vscreen; |
|
|
|
assert(scrn); |
|
|
|
if (stamp && scrn->last_ust && scrn->ns_frame && scrn->last_msc) |
|
|
|
scrn->next_msc = ((int64_t)stamp - scrn->last_ust) / scrn->ns_frame + scrn->last_msc + scrn->skew_msc; |
|
|
|
else |
|
|
|
scrn->next_msc = 0; |
|
|
|
} |
|
|
|
|
|
|
|
void* |
|
|
|
vl_screen_get_private(struct vl_screen *vscreen) |
|
|
|
{ |