mirror of
https://github.com/hyprwm/xdg-desktop-portal-hyprland.git
synced 2024-12-22 17:59:47 +01:00
screencast: support multiplane buffers with xdpw_buffer
This commit is contained in:
parent
5799adeb57
commit
1a7276068b
4 changed files with 77 additions and 54 deletions
|
@ -79,11 +79,12 @@ struct xdpw_buffer {
|
|||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t format;
|
||||
int plane_count;
|
||||
|
||||
int fd;
|
||||
uint32_t size;
|
||||
uint32_t stride;
|
||||
uint32_t offset;
|
||||
int fd[4];
|
||||
uint32_t size[4];
|
||||
uint32_t stride[4];
|
||||
uint32_t offset[4];
|
||||
|
||||
struct gbm_bo *bo;
|
||||
|
||||
|
|
|
@ -220,19 +220,21 @@ static void pwr_handle_stream_add_buffer(void *data, struct pw_buffer *buffer) {
|
|||
wl_list_insert(&cast->buffer_list, &xdpw_buffer->link);
|
||||
buffer->user_data = xdpw_buffer;
|
||||
|
||||
d[0].maxsize = xdpw_buffer->size;
|
||||
d[0].mapoffset = 0;
|
||||
d[0].chunk->size = xdpw_buffer->size;
|
||||
d[0].chunk->stride = xdpw_buffer->stride;
|
||||
d[0].chunk->offset = xdpw_buffer->offset;
|
||||
d[0].flags = 0;
|
||||
d[0].fd = xdpw_buffer->fd;
|
||||
d[0].data = NULL;
|
||||
|
||||
// clients have implemented to check chunk->size if the buffer is valid instead
|
||||
// of using the flags. Until they are patched we should use some arbitrary value.
|
||||
if (xdpw_buffer->buffer_type == DMABUF && d[0].chunk->size == 0) {
|
||||
d[0].chunk->size = 9; // This was choosen by a fair d20.
|
||||
assert(xdpw_buffer->plane_count >= 0 && buffer->buffer->n_datas == (uint32_t)xdpw_buffer->plane_count);
|
||||
for (uint32_t plane = 0; plane < buffer->buffer->n_datas; plane++) {
|
||||
d[plane].maxsize = xdpw_buffer->size[plane];
|
||||
d[plane].mapoffset = 0;
|
||||
d[plane].chunk->size = xdpw_buffer->size[plane];
|
||||
d[plane].chunk->stride = xdpw_buffer->stride[plane];
|
||||
d[plane].chunk->offset = xdpw_buffer->offset[plane];
|
||||
d[plane].flags = 0;
|
||||
d[plane].fd = xdpw_buffer->fd[plane];
|
||||
d[plane].data = NULL;
|
||||
// clients have implemented to check chunk->size if the buffer is valid instead
|
||||
// of using the flags. Until they are patched we should use some arbitrary value.
|
||||
if (xdpw_buffer->buffer_type == DMABUF && d[plane].chunk->size == 0) {
|
||||
d[plane].chunk->size = 9; // This was choosen by a fair d20.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -248,7 +250,9 @@ static void pwr_handle_stream_remove_buffer(void *data, struct pw_buffer *buffer
|
|||
if (cast->current_frame.pw_buffer == buffer) {
|
||||
cast->current_frame.pw_buffer = NULL;
|
||||
}
|
||||
buffer->buffer->datas[0].fd = -1;
|
||||
for (uint32_t plane = 0; plane < buffer->buffer->n_datas; plane++) {
|
||||
buffer->buffer->datas[plane].fd = -1;
|
||||
}
|
||||
buffer->user_data = NULL;
|
||||
}
|
||||
|
||||
|
@ -300,18 +304,25 @@ void xdpw_pwr_enqueue_buffer(struct xdpw_screencast_instance *cast) {
|
|||
}
|
||||
|
||||
if (buffer_corrupt) {
|
||||
d[0].chunk->flags = SPA_CHUNK_FLAG_CORRUPTED;
|
||||
for (uint32_t plane = 0; plane < spa_buf->n_datas; plane++) {
|
||||
d[plane].chunk->flags = SPA_CHUNK_FLAG_CORRUPTED;
|
||||
}
|
||||
} else {
|
||||
d[0].chunk->flags = SPA_CHUNK_FLAG_NONE;
|
||||
for (uint32_t plane = 0; plane < spa_buf->n_datas; plane++) {
|
||||
d[plane].chunk->flags = SPA_CHUNK_FLAG_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
logprint(TRACE, "********************");
|
||||
logprint(TRACE, "pipewire: fd %u", d[0].fd);
|
||||
logprint(TRACE, "pipewire: maxsize %d", d[0].maxsize);
|
||||
logprint(TRACE, "pipewire: size %d", d[0].chunk->size);
|
||||
logprint(TRACE, "pipewire: stride %d", d[0].chunk->stride);
|
||||
logprint(TRACE, "pipewire: offset %d", d[0].chunk->offset);
|
||||
logprint(TRACE, "pipewire: chunk flags %d", d[0].chunk->flags);
|
||||
for (uint32_t plane = 0; plane < spa_buf->n_datas; plane++) {
|
||||
logprint(TRACE, "pipewire: plane %d", plane);
|
||||
logprint(TRACE, "pipewire: fd %u", d[plane].fd);
|
||||
logprint(TRACE, "pipewire: maxsize %d", d[plane].maxsize);
|
||||
logprint(TRACE, "pipewire: size %d", d[plane].chunk->size);
|
||||
logprint(TRACE, "pipewire: stride %d", d[plane].chunk->stride);
|
||||
logprint(TRACE, "pipewire: offset %d", d[plane].chunk->offset);
|
||||
logprint(TRACE, "pipewire: chunk flags %d", d[plane].chunk->flags);
|
||||
}
|
||||
logprint(TRACE, "pipewire: width %d", cast->current_frame.xdpw_buffer->width);
|
||||
logprint(TRACE, "pipewire: height %d", cast->current_frame.xdpw_buffer->height);
|
||||
logprint(TRACE, "pipewire: y_invert %d", cast->current_frame.y_invert);
|
||||
|
|
|
@ -110,28 +110,29 @@ struct xdpw_buffer *xdpw_buffer_create(struct xdpw_screencast_instance *cast,
|
|||
|
||||
switch (buffer_type) {
|
||||
case WL_SHM:
|
||||
buffer->size = frame_info->size;
|
||||
buffer->stride = frame_info->stride;
|
||||
buffer->offset = 0;
|
||||
buffer->fd = anonymous_shm_open();
|
||||
if (buffer->fd == -1) {
|
||||
buffer->plane_count = 1;
|
||||
buffer->size[0] = frame_info->size;
|
||||
buffer->stride[0] = frame_info->stride;
|
||||
buffer->offset[0] = 0;
|
||||
buffer->fd[0] = anonymous_shm_open();
|
||||
if (buffer->fd[0] == -1) {
|
||||
logprint(ERROR, "xdpw: unable to create anonymous filedescriptor");
|
||||
free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ftruncate(buffer->fd, buffer->size) < 0) {
|
||||
if (ftruncate(buffer->fd[0], buffer->size[0]) < 0) {
|
||||
logprint(ERROR, "xdpw: unable to truncate filedescriptor");
|
||||
close(buffer->fd);
|
||||
close(buffer->fd[0]);
|
||||
free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer->buffer = import_wl_shm_buffer(cast, buffer->fd, xdpw_format_wl_shm_from_drm_fourcc(frame_info->format),
|
||||
frame_info->width, frame_info->height, frame_info->stride);
|
||||
buffer->buffer = import_wl_shm_buffer(cast, buffer->fd[0], xdpw_format_wl_shm_from_drm_fourcc(frame_info->format),
|
||||
frame_info->width, frame_info->height, frame_info->stride);
|
||||
if (buffer->buffer == NULL) {
|
||||
logprint(ERROR, "xdpw: unable to create wl_buffer");
|
||||
close(buffer->fd);
|
||||
close(buffer->fd[0]);
|
||||
free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -149,6 +150,7 @@ struct xdpw_buffer *xdpw_buffer_create(struct xdpw_screencast_instance *cast,
|
|||
free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
buffer->plane_count = gbm_bo_get_plane_count(buffer->bo);
|
||||
|
||||
struct zwp_linux_buffer_params_v1 *params;
|
||||
params = zwp_linux_dmabuf_v1_create_params(cast->ctx->linux_dmabuf);
|
||||
|
@ -159,22 +161,27 @@ struct xdpw_buffer *xdpw_buffer_create(struct xdpw_screencast_instance *cast,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
buffer->size = 0;
|
||||
buffer->stride = gbm_bo_get_stride(buffer->bo);
|
||||
buffer->offset = gbm_bo_get_offset(buffer->bo, 0);
|
||||
uint64_t mod = gbm_bo_get_modifier(buffer->bo);
|
||||
buffer->fd = gbm_bo_get_fd(buffer->bo);
|
||||
for (int plane = 0; plane < buffer->plane_count; plane++) {
|
||||
buffer->size[plane] = 0;
|
||||
buffer->stride[plane] = gbm_bo_get_stride_for_plane(buffer->bo, plane);
|
||||
buffer->offset[plane] = gbm_bo_get_offset(buffer->bo, plane);
|
||||
uint64_t mod = gbm_bo_get_modifier(buffer->bo);
|
||||
buffer->fd[plane] = gbm_bo_get_fd_for_plane(buffer->bo, plane);
|
||||
|
||||
if (buffer->fd < 0) {
|
||||
logprint(ERROR, "xdpw: failed to get file descriptor");
|
||||
zwp_linux_buffer_params_v1_destroy(params);
|
||||
gbm_bo_destroy(buffer->bo);
|
||||
free(buffer);
|
||||
return NULL;
|
||||
if (buffer->fd[plane] < 0) {
|
||||
logprint(ERROR, "xdpw: failed to get file descriptor");
|
||||
zwp_linux_buffer_params_v1_destroy(params);
|
||||
gbm_bo_destroy(buffer->bo);
|
||||
for (int plane_tmp = 0; plane_tmp < plane; plane_tmp++) {
|
||||
close(buffer->fd[plane_tmp]);
|
||||
}
|
||||
free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zwp_linux_buffer_params_v1_add(params, buffer->fd[plane], plane,
|
||||
buffer->offset[plane], buffer->stride[plane], mod >> 32, mod & 0xffffffff);
|
||||
}
|
||||
|
||||
zwp_linux_buffer_params_v1_add(params, buffer->fd, 0, buffer->offset, buffer->stride,
|
||||
mod >> 32, mod & 0xffffffff);
|
||||
buffer->buffer = zwp_linux_buffer_params_v1_create_immed(params,
|
||||
buffer->width, buffer->height,
|
||||
buffer->format, /* flags */ 0);
|
||||
|
@ -183,7 +190,9 @@ struct xdpw_buffer *xdpw_buffer_create(struct xdpw_screencast_instance *cast,
|
|||
if (!buffer->buffer) {
|
||||
logprint(ERROR, "xdpw: failed to create buffer");
|
||||
gbm_bo_destroy(buffer->bo);
|
||||
close(buffer->fd);
|
||||
for (int plane = 0; plane < buffer->plane_count; plane++) {
|
||||
close(buffer->fd[plane]);
|
||||
}
|
||||
free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -197,7 +206,9 @@ void xdpw_buffer_destroy(struct xdpw_buffer *buffer) {
|
|||
if (buffer->buffer_type == DMABUF) {
|
||||
gbm_bo_destroy(buffer->bo);
|
||||
}
|
||||
close(buffer->fd);
|
||||
for (int plane = 0; plane < buffer->plane_count; plane++) {
|
||||
close(buffer->fd[plane]);
|
||||
}
|
||||
wl_list_remove(&buffer->link);
|
||||
free(buffer);
|
||||
}
|
||||
|
|
|
@ -151,8 +151,8 @@ static void wlr_frame_buffer_done(void *data,
|
|||
|
||||
// Check if dequeued buffer is compatible with announced buffer
|
||||
if (( cast->buffer_type == WL_SHM &&
|
||||
(cast->current_frame.xdpw_buffer->size != cast->screencopy_frame_info[cast->buffer_type].size ||
|
||||
cast->current_frame.xdpw_buffer->stride != cast->screencopy_frame_info[cast->buffer_type].stride)) ||
|
||||
(cast->current_frame.xdpw_buffer->size[0] != cast->screencopy_frame_info[cast->buffer_type].size ||
|
||||
cast->current_frame.xdpw_buffer->stride[0] != cast->screencopy_frame_info[cast->buffer_type].stride)) ||
|
||||
cast->current_frame.xdpw_buffer->width != cast->screencopy_frame_info[cast->buffer_type].width ||
|
||||
cast->current_frame.xdpw_buffer->height != cast->screencopy_frame_info[cast->buffer_type].height) {
|
||||
logprint(DEBUG, "wlroots: pipewire buffer has wrong dimensions");
|
||||
|
|
Loading…
Reference in a new issue