mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-09 04:00:12 +01:00
vl/dri3: implement DRI3 BufferFromPixmap
We also need render to the front buffer of temporary X pixmap, this is the case of when we using opengl as video out for vaapi. the basic implementation is to pass pixmap ID to X server, and then X will return dma-buf fd, we will get the buffer object through this dma-buf fd. Signed-off-by: Leo Liu <leo.liu@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com>
This commit is contained in:
parent
858b329c2c
commit
8d7ac0a4e4
1 changed files with 113 additions and 3 deletions
|
|
@ -72,8 +72,20 @@ struct vl_dri3_screen
|
|||
int cur_back;
|
||||
|
||||
struct u_rect dirty_areas[BACK_BUFFER_NUM];
|
||||
|
||||
struct vl_dri3_buffer *front_buffer;
|
||||
bool is_pixmap;
|
||||
};
|
||||
|
||||
static void
|
||||
dri3_free_front_buffer(struct vl_dri3_screen *scrn,
|
||||
struct vl_dri3_buffer *buffer)
|
||||
{
|
||||
xcb_sync_destroy_fence(scrn->conn, buffer->sync_fence);
|
||||
xshmfence_unmap_shm(buffer->shm_fence);
|
||||
FREE(buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
dri3_free_back_buffer(struct vl_dri3_screen *scrn,
|
||||
struct vl_dri3_buffer *buffer)
|
||||
|
|
@ -282,6 +294,7 @@ dri3_set_drawable(struct vl_dri3_screen *scrn, Drawable drawable)
|
|||
xcb_void_cookie_t cookie;
|
||||
xcb_generic_error_t *error;
|
||||
xcb_present_event_t peid;
|
||||
bool ret = true;
|
||||
|
||||
assert(drawable);
|
||||
|
||||
|
|
@ -305,6 +318,7 @@ dri3_set_drawable(struct vl_dri3_screen *scrn, Drawable drawable)
|
|||
scrn->special_event = NULL;
|
||||
}
|
||||
|
||||
scrn->is_pixmap = false;
|
||||
peid = xcb_generate_id(scrn->conn);
|
||||
cookie =
|
||||
xcb_present_select_input_checked(scrn->conn, peid, scrn->drawable,
|
||||
|
|
@ -314,15 +328,103 @@ dri3_set_drawable(struct vl_dri3_screen *scrn, Drawable drawable)
|
|||
|
||||
error = xcb_request_check(scrn->conn, cookie);
|
||||
if (error) {
|
||||
if (error->error_code != BadWindow)
|
||||
ret = false;
|
||||
else
|
||||
scrn->is_pixmap = true;
|
||||
free(error);
|
||||
return false;
|
||||
} else
|
||||
scrn->special_event =
|
||||
xcb_register_for_special_xge(scrn->conn, &xcb_present_id, peid, 0);
|
||||
|
||||
dri3_flush_present_events(scrn);
|
||||
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct vl_dri3_buffer *
|
||||
dri3_get_front_buffer(struct vl_dri3_screen *scrn)
|
||||
{
|
||||
xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie;
|
||||
xcb_dri3_buffer_from_pixmap_reply_t *bp_reply;
|
||||
xcb_sync_fence_t sync_fence;
|
||||
struct xshmfence *shm_fence;
|
||||
int fence_fd, *fds;
|
||||
struct winsys_handle whandle;
|
||||
struct pipe_resource templ, *texture = NULL;
|
||||
|
||||
if (scrn->front_buffer) {
|
||||
pipe_resource_reference(&texture, scrn->front_buffer->texture);
|
||||
return scrn->front_buffer;
|
||||
}
|
||||
|
||||
scrn->front_buffer = CALLOC_STRUCT(vl_dri3_buffer);
|
||||
if (!scrn->front_buffer)
|
||||
return NULL;
|
||||
|
||||
fence_fd = xshmfence_alloc_shm();
|
||||
if (fence_fd < 0)
|
||||
goto free_buffer;
|
||||
|
||||
shm_fence = xshmfence_map_shm(fence_fd);
|
||||
if (!shm_fence)
|
||||
goto close_fd;
|
||||
|
||||
bp_cookie = xcb_dri3_buffer_from_pixmap(scrn->conn, scrn->drawable);
|
||||
bp_reply = xcb_dri3_buffer_from_pixmap_reply(scrn->conn, bp_cookie, NULL);
|
||||
if (!bp_reply)
|
||||
goto unmap_shm;
|
||||
|
||||
fds = xcb_dri3_buffer_from_pixmap_reply_fds(scrn->conn, bp_reply);
|
||||
if (fds[0] < 0)
|
||||
goto free_reply;
|
||||
|
||||
memset(&whandle, 0, sizeof(whandle));
|
||||
whandle.type = DRM_API_HANDLE_TYPE_FD;
|
||||
whandle.handle = (unsigned)fds[0];
|
||||
whandle.stride = bp_reply->stride;
|
||||
memset(&templ, 0, sizeof(templ));
|
||||
templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
|
||||
templ.format = PIPE_FORMAT_B8G8R8X8_UNORM;
|
||||
templ.target = PIPE_TEXTURE_2D;
|
||||
templ.last_level = 0;
|
||||
templ.width0 = bp_reply->width;
|
||||
templ.height0 = bp_reply->height;
|
||||
templ.depth0 = 1;
|
||||
templ.array_size = 1;
|
||||
scrn->front_buffer->texture =
|
||||
scrn->base.pscreen->resource_from_handle(scrn->base.pscreen,
|
||||
&templ, &whandle,
|
||||
PIPE_HANDLE_USAGE_READ_WRITE);
|
||||
close(fds[0]);
|
||||
if (!scrn->front_buffer->texture)
|
||||
goto free_reply;
|
||||
|
||||
xcb_dri3_fence_from_fd(scrn->conn,
|
||||
scrn->drawable,
|
||||
(sync_fence = xcb_generate_id(scrn->conn)),
|
||||
false,
|
||||
fence_fd);
|
||||
|
||||
pipe_resource_reference(&texture, scrn->front_buffer->texture);
|
||||
scrn->front_buffer->pixmap = scrn->drawable;
|
||||
scrn->front_buffer->width = bp_reply->width;
|
||||
scrn->front_buffer->height = bp_reply->height;
|
||||
scrn->front_buffer->shm_fence = shm_fence;
|
||||
scrn->front_buffer->sync_fence = sync_fence;
|
||||
free(bp_reply);
|
||||
|
||||
return scrn->front_buffer;
|
||||
|
||||
free_reply:
|
||||
free(bp_reply);
|
||||
unmap_shm:
|
||||
xshmfence_unmap_shm(shm_fence);
|
||||
close_fd:
|
||||
close(fence_fd);
|
||||
free_buffer:
|
||||
FREE(scrn->front_buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -366,7 +468,9 @@ vl_dri3_screen_texture_from_drawable(struct vl_screen *vscreen, void *drawable)
|
|||
if (!dri3_set_drawable(scrn, (Drawable)drawable))
|
||||
return NULL;
|
||||
|
||||
buffer = dri3_get_back_buffer(scrn);
|
||||
buffer = (scrn->is_pixmap) ?
|
||||
dri3_get_front_buffer(scrn) :
|
||||
dri3_get_back_buffer(scrn);
|
||||
if (!buffer)
|
||||
return NULL;
|
||||
|
||||
|
|
@ -413,6 +517,12 @@ vl_dri3_screen_destroy(struct vl_screen *vscreen)
|
|||
|
||||
dri3_flush_present_events(scrn);
|
||||
|
||||
if (scrn->front_buffer) {
|
||||
dri3_free_front_buffer(scrn, scrn->front_buffer);
|
||||
scrn->front_buffer = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < BACK_BUFFER_NUM; ++i) {
|
||||
if (scrn->back_buffers[i]) {
|
||||
dri3_free_back_buffer(scrn, scrn->back_buffers[i]);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue