static uint64_t vl_dri3_screen_get_timestamp(struct vl_screen *vscreen, void *drawable) { struct vl_dri3_screen *scrn = (struct vl_dri3_screen *)vscreen; assert(scrn); if (!dri3_set_drawable(scrn, (Drawable)drawable)) return 0; if (!scrn->last_ust) { xcb_present_notify_msc(scrn->conn, scrn->drawable, ++scrn->send_msc_serial, 0, 0, 0); xcb_flush(scrn->conn); while (scrn->special_event && scrn->send_msc_serial > scrn->recv_msc_serial) { if (!dri3_wait_present_events(scrn)) return 0; } } return scrn->last_ust; }
static struct pipe_resource * vl_dri3_screen_texture_from_drawable(struct vl_screen *vscreen, void *drawable) { struct vl_dri3_screen *scrn = (struct vl_dri3_screen *)vscreen; struct vl_dri3_buffer *buffer; assert(scrn); if (!dri3_set_drawable(scrn, (Drawable)drawable)) return NULL; if (scrn->flushed) { while (scrn->special_event && scrn->recv_sbc < scrn->send_sbc) if (!dri3_wait_present_events(scrn)) return NULL; } scrn->flushed = false; buffer = (scrn->is_pixmap) ? dri3_get_front_buffer(scrn) : dri3_get_back_buffer(scrn); if (!buffer) return NULL; return buffer->texture; }
static void vl_dri3_flush_frontbuffer(struct pipe_screen *screen, struct pipe_resource *resource, unsigned level, unsigned layer, void *context_private, struct pipe_box *sub_box) { struct vl_dri3_screen *scrn = (struct vl_dri3_screen *)context_private; uint32_t options = XCB_PRESENT_OPTION_NONE; struct vl_dri3_buffer *back; struct pipe_box src_box; xcb_xfixes_region_t region; xcb_rectangle_t rectangle; back = scrn->back_buffers[scrn->cur_back]; if (!back) return; while (scrn->special_event && scrn->recv_sbc < scrn->send_sbc) if (!dri3_wait_present_events(scrn)) return; rectangle.x = 0; rectangle.y = 0; rectangle.width = (scrn->output_texture) ? scrn->clip_width : scrn->width; rectangle.height = (scrn->output_texture) ? scrn->clip_height : scrn->height; region = xcb_generate_id(scrn->conn); xcb_xfixes_create_region(scrn->conn, region, 2, &rectangle); if (scrn->is_different_gpu) { u_box_origin_2d(back->width, back->height, &src_box); scrn->pipe->resource_copy_region(scrn->pipe, back->linear_texture, 0, 0, 0, 0, back->texture, 0, &src_box); scrn->pipe->flush(scrn->pipe, NULL, 0); } xshmfence_reset(back->shm_fence); back->busy = true; xcb_present_pixmap(scrn->conn, scrn->drawable, back->pixmap, (uint32_t)(++scrn->send_sbc), 0, region, 0, 0, None, None, back->sync_fence, options, scrn->next_msc, 0, 0, 0, NULL); xcb_flush(scrn->conn); return; }
static int dri3_find_back(struct vl_dri3_screen *scrn) { int b; for (;;) { for (b = 0; b < BACK_BUFFER_NUM; b++) { int id = (b + scrn->cur_back) % BACK_BUFFER_NUM; struct vl_dri3_buffer *buffer = scrn->back_buffers[id]; if (!buffer || !buffer->busy) return id; } xcb_flush(scrn->conn); if (!dri3_wait_present_events(scrn)) return -1; } }
static void vl_dri3_flush_frontbuffer(struct pipe_screen *screen, struct pipe_resource *resource, unsigned level, unsigned layer, void *context_private, struct pipe_box *sub_box) { struct vl_dri3_screen *scrn = (struct vl_dri3_screen *)context_private; uint32_t options = XCB_PRESENT_OPTION_NONE; struct vl_dri3_buffer *back; back = scrn->back_buffers[scrn->cur_back]; if (!back) return; if (scrn->flushed) { while (scrn->special_event && scrn->recv_sbc < scrn->send_sbc) if (!dri3_wait_present_events(scrn)) return; } xshmfence_reset(back->shm_fence); back->busy = true; xcb_present_pixmap(scrn->conn, scrn->drawable, back->pixmap, (uint32_t)(++scrn->send_sbc), 0, 0, 0, 0, None, None, back->sync_fence, options, scrn->next_msc, 0, 0, 0, NULL); xcb_flush(scrn->conn); scrn->flushed = true; return; }