From d89631c792f62022288010ab6ef2d82969c099e8 Mon Sep 17 00:00:00 2001 From: columbarius Date: Tue, 22 Jun 2021 03:49:13 +0200 Subject: [PATCH] screencast: allocate dmabuf with implicit modifier This is using the older gbm api without support for explicit modifiers. This is required to support AMD gpus using the GFX8 or older architecture and older intel gpus. --- include/screencast_common.h | 2 ++ src/screencast/pipewire_screencast.c | 3 ++ src/screencast/screencast_common.c | 51 +++++++++++++++++++++++++++- 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/include/screencast_common.h b/include/screencast_common.h index b871c59..f88fbd4 100644 --- a/include/screencast_common.h +++ b/include/screencast_common.h @@ -85,6 +85,8 @@ struct xdpw_buffer { uint32_t stride; uint32_t offset; + struct gbm_bo *bo; + struct wl_buffer *buffer; }; diff --git a/src/screencast/pipewire_screencast.c b/src/screencast/pipewire_screencast.c index d00d496..3d060e3 100644 --- a/src/screencast/pipewire_screencast.c +++ b/src/screencast/pipewire_screencast.c @@ -186,6 +186,9 @@ static void pwr_handle_stream_add_buffer(void *data, struct pw_buffer *buffer) { if ((d[0].type & (1u << SPA_DATA_MemFd)) > 0) { assert(cast->buffer_type == WL_SHM); d[0].type = SPA_DATA_MemFd; + } else if ((d[0].type & (1u << SPA_DATA_DmaBuf)) > 0) { + assert(cast->buffer_type == DMABUF); + d[0].type = SPA_DATA_DmaBuf; } else { logprint(ERROR, "pipewire: unsupported buffer type"); cast->err = 1; diff --git a/src/screencast/screencast_common.c b/src/screencast/screencast_common.c index 10a6097..ee65a26 100644 --- a/src/screencast/screencast_common.c +++ b/src/screencast/screencast_common.c @@ -7,6 +7,7 @@ #include #include #include +#include "linux-dmabuf-unstable-v1-client-protocol.h" #include "logger.h" @@ -135,7 +136,52 @@ struct xdpw_buffer *xdpw_buffer_create(struct xdpw_screencast_instance *cast, } break; case DMABUF: - abort(); + buffer->bo = gbm_bo_create(cast->ctx->gbm, + frame_info->width, frame_info->height, frame_info->format, + GBM_BO_USE_RENDERING); + if (buffer->bo == NULL) { + logprint(ERROR, "xdpw: failed to create gbm_bo"); + free(buffer); + return NULL; + } + + struct zwp_linux_buffer_params_v1 *params; + params = zwp_linux_dmabuf_v1_create_params(cast->ctx->linux_dmabuf); + if (!params) { + logprint(ERROR, "xdpw: failed to create linux_buffer_params"); + gbm_bo_destroy(buffer->bo); + free(buffer); + 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); + + 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; + } + + 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); + zwp_linux_buffer_params_v1_destroy(params); + + if (!buffer->buffer) { + logprint(ERROR, "xdpw: failed to create buffer"); + gbm_bo_destroy(buffer->bo); + close(buffer->fd); + free(buffer); + return NULL; + } } return buffer; @@ -143,6 +189,9 @@ struct xdpw_buffer *xdpw_buffer_create(struct xdpw_screencast_instance *cast, void xdpw_buffer_destroy(struct xdpw_buffer *buffer) { wl_buffer_destroy(buffer->buffer); + if (buffer->buffer_type == DMABUF) { + gbm_bo_destroy(buffer->bo); + } close(buffer->fd); wl_list_remove(&buffer->link); free(buffer);