mirror of
https://github.com/hyprwm/xdg-desktop-portal-hyprland.git
synced 2024-11-25 23:45:58 +01:00
screencast: introduce buffer_type
We want to support WL_SHM and DMABUFS based buffers. The buffer_type member tracks the type of a xdpw_buffer and screencopy_frame_info of the screencast_instance will be an array with an element for each buffer type indexed by the value of the buffer_type enum. Only members of the xdpw_screencopy_frame_info relevant to the buffer type should be used.
This commit is contained in:
parent
88a8a9cb7e
commit
12de0cd144
5 changed files with 70 additions and 42 deletions
|
@ -22,6 +22,11 @@ enum source_types {
|
||||||
WINDOW = 2,
|
WINDOW = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum buffer_type {
|
||||||
|
WL_SHM = 0,
|
||||||
|
DMABUF = 1,
|
||||||
|
};
|
||||||
|
|
||||||
enum xdpw_chooser_types {
|
enum xdpw_chooser_types {
|
||||||
XDPW_CHOOSER_DEFAULT,
|
XDPW_CHOOSER_DEFAULT,
|
||||||
XDPW_CHOOSER_NONE,
|
XDPW_CHOOSER_NONE,
|
||||||
|
@ -68,6 +73,7 @@ struct xdpw_screencopy_frame_info {
|
||||||
|
|
||||||
struct xdpw_buffer {
|
struct xdpw_buffer {
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
|
enum buffer_type buffer_type;
|
||||||
|
|
||||||
uint32_t width;
|
uint32_t width;
|
||||||
uint32_t height;
|
uint32_t height;
|
||||||
|
@ -127,11 +133,12 @@ struct xdpw_screencast_instance {
|
||||||
struct xdpw_wlr_output *target_output;
|
struct xdpw_wlr_output *target_output;
|
||||||
uint32_t max_framerate;
|
uint32_t max_framerate;
|
||||||
struct zwlr_screencopy_frame_v1 *wlr_frame;
|
struct zwlr_screencopy_frame_v1 *wlr_frame;
|
||||||
struct xdpw_screencopy_frame_info screencopy_frame_info;
|
struct xdpw_screencopy_frame_info screencopy_frame_info[2];
|
||||||
bool with_cursor;
|
bool with_cursor;
|
||||||
int err;
|
int err;
|
||||||
bool quit;
|
bool quit;
|
||||||
bool need_buffer;
|
bool need_buffer;
|
||||||
|
enum buffer_type buffer_type;
|
||||||
|
|
||||||
// fps limit
|
// fps limit
|
||||||
struct fps_limit_state fps_limit;
|
struct fps_limit_state fps_limit;
|
||||||
|
@ -152,7 +159,7 @@ struct xdpw_wlr_output {
|
||||||
|
|
||||||
void randname(char *buf);
|
void randname(char *buf);
|
||||||
struct xdpw_buffer *xdpw_buffer_create(struct xdpw_screencast_instance *cast,
|
struct xdpw_buffer *xdpw_buffer_create(struct xdpw_screencast_instance *cast,
|
||||||
struct xdpw_screencopy_frame_info *frame_info);
|
enum buffer_type buffer_type, struct xdpw_screencopy_frame_info *frame_info);
|
||||||
void xdpw_buffer_destroy(struct xdpw_buffer *buffer);
|
void xdpw_buffer_destroy(struct xdpw_buffer *buffer);
|
||||||
enum wl_shm_format xdpw_format_wl_shm_from_drm_fourcc(uint32_t format);
|
enum wl_shm_format xdpw_format_wl_shm_from_drm_fourcc(uint32_t format);
|
||||||
uint32_t xdpw_format_drm_fourcc_from_wl_shm(enum wl_shm_format format);
|
uint32_t xdpw_format_drm_fourcc_from_wl_shm(enum wl_shm_format format);
|
||||||
|
|
|
@ -68,8 +68,8 @@ static struct spa_pod *build_format(struct spa_pod_builder *b, enum spa_video_fo
|
||||||
static uint32_t build_formats(struct spa_pod_builder *b, struct xdpw_screencast_instance *cast,
|
static uint32_t build_formats(struct spa_pod_builder *b, struct xdpw_screencast_instance *cast,
|
||||||
const struct spa_pod *params[static 1]) {
|
const struct spa_pod *params[static 1]) {
|
||||||
uint32_t param_count = 1;
|
uint32_t param_count = 1;
|
||||||
params[0] = build_format(b, xdpw_format_pw_from_drm_fourcc(cast->screencopy_frame_info.format),
|
params[0] = build_format(b, xdpw_format_pw_from_drm_fourcc(cast->screencopy_frame_info[WL_SHM].format),
|
||||||
cast->screencopy_frame_info.width, cast->screencopy_frame_info.height, cast->framerate);
|
cast->screencopy_frame_info[WL_SHM].width, cast->screencopy_frame_info[WL_SHM].height, cast->framerate);
|
||||||
|
|
||||||
return param_count;
|
return param_count;
|
||||||
}
|
}
|
||||||
|
@ -122,6 +122,8 @@ static void pwr_handle_stream_param_changed(void *data, uint32_t id,
|
||||||
struct spa_pod_builder b =
|
struct spa_pod_builder b =
|
||||||
SPA_POD_BUILDER_INIT(params_buffer, sizeof(params_buffer));
|
SPA_POD_BUILDER_INIT(params_buffer, sizeof(params_buffer));
|
||||||
const struct spa_pod *params[2];
|
const struct spa_pod *params[2];
|
||||||
|
uint32_t blocks;
|
||||||
|
uint32_t data_type;
|
||||||
|
|
||||||
if (!param || id != SPA_PARAM_Format) {
|
if (!param || id != SPA_PARAM_Format) {
|
||||||
return;
|
return;
|
||||||
|
@ -130,9 +132,16 @@ static void pwr_handle_stream_param_changed(void *data, uint32_t id,
|
||||||
spa_format_video_raw_parse(param, &cast->pwr_format);
|
spa_format_video_raw_parse(param, &cast->pwr_format);
|
||||||
cast->framerate = (uint32_t)(cast->pwr_format.max_framerate.num / cast->pwr_format.max_framerate.denom);
|
cast->framerate = (uint32_t)(cast->pwr_format.max_framerate.num / cast->pwr_format.max_framerate.denom);
|
||||||
|
|
||||||
|
if (spa_pod_find_prop(param, NULL, SPA_FORMAT_VIDEO_modifier) != NULL) {
|
||||||
|
abort();
|
||||||
|
} else {
|
||||||
|
cast->buffer_type = WL_SHM;
|
||||||
|
blocks = 1;
|
||||||
|
data_type = 1<<SPA_DATA_MemFd;
|
||||||
|
}
|
||||||
|
|
||||||
params[0] = build_buffer(&b, 1, cast->screencopy_frame_info.size,
|
params[0] = build_buffer(&b, blocks, cast->screencopy_frame_info[cast->buffer_type].size,
|
||||||
cast->screencopy_frame_info.stride, 1<<SPA_DATA_MemFd);
|
cast->screencopy_frame_info[cast->buffer_type].stride, data_type);
|
||||||
|
|
||||||
params[1] = spa_pod_builder_add_object(&b,
|
params[1] = spa_pod_builder_add_object(&b,
|
||||||
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
|
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
|
||||||
|
@ -152,6 +161,7 @@ static void pwr_handle_stream_add_buffer(void *data, struct pw_buffer *buffer) {
|
||||||
|
|
||||||
// Select buffer type from negotiation result
|
// Select buffer type from negotiation result
|
||||||
if ((d[0].type & (1u << SPA_DATA_MemFd)) > 0) {
|
if ((d[0].type & (1u << SPA_DATA_MemFd)) > 0) {
|
||||||
|
assert(cast->buffer_type == WL_SHM);
|
||||||
d[0].type = SPA_DATA_MemFd;
|
d[0].type = SPA_DATA_MemFd;
|
||||||
} else {
|
} else {
|
||||||
logprint(ERROR, "pipewire: unsupported buffer type");
|
logprint(ERROR, "pipewire: unsupported buffer type");
|
||||||
|
@ -161,7 +171,7 @@ static void pwr_handle_stream_add_buffer(void *data, struct pw_buffer *buffer) {
|
||||||
|
|
||||||
logprint(TRACE, "pipewire: selected buffertype %u", d[0].type);
|
logprint(TRACE, "pipewire: selected buffertype %u", d[0].type);
|
||||||
|
|
||||||
struct xdpw_buffer *xdpw_buffer = xdpw_buffer_create(cast, &cast->screencopy_frame_info);
|
struct xdpw_buffer *xdpw_buffer = xdpw_buffer_create(cast, cast->buffer_type, &cast->screencopy_frame_info[cast->buffer_type]);
|
||||||
if (xdpw_buffer == NULL) {
|
if (xdpw_buffer == NULL) {
|
||||||
logprint(ERROR, "pipewire: failed to create xdpw buffer");
|
logprint(ERROR, "pipewire: failed to create xdpw buffer");
|
||||||
cast->err = 1;
|
cast->err = 1;
|
||||||
|
|
|
@ -455,7 +455,7 @@ static int method_screencast_start(sd_bus_message *msg, void *data,
|
||||||
"streams", "a(ua{sv})", 1,
|
"streams", "a(ua{sv})", 1,
|
||||||
cast->node_id, 2,
|
cast->node_id, 2,
|
||||||
"position", "(ii)", 0, 0,
|
"position", "(ii)", 0, 0,
|
||||||
"size", "(ii)", cast->screencopy_frame_info.width, cast->screencopy_frame_info.height);
|
"size", "(ii)", cast->screencopy_frame_info[WL_SHM].width, cast->screencopy_frame_info[WL_SHM].height);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -57,11 +57,15 @@ static struct wl_buffer *import_wl_shm_buffer(struct xdpw_screencast_instance *c
|
||||||
}
|
}
|
||||||
|
|
||||||
struct xdpw_buffer *xdpw_buffer_create(struct xdpw_screencast_instance *cast,
|
struct xdpw_buffer *xdpw_buffer_create(struct xdpw_screencast_instance *cast,
|
||||||
struct xdpw_screencopy_frame_info *frame_info) {
|
enum buffer_type buffer_type, struct xdpw_screencopy_frame_info *frame_info) {
|
||||||
struct xdpw_buffer *buffer = calloc(1, sizeof(struct xdpw_buffer));
|
struct xdpw_buffer *buffer = calloc(1, sizeof(struct xdpw_buffer));
|
||||||
buffer->width = frame_info->width;
|
buffer->width = frame_info->width;
|
||||||
buffer->height = frame_info->height;
|
buffer->height = frame_info->height;
|
||||||
buffer->format = frame_info->format;
|
buffer->format = frame_info->format;
|
||||||
|
buffer->buffer_type = buffer_type;
|
||||||
|
|
||||||
|
switch (buffer_type) {
|
||||||
|
case WL_SHM:
|
||||||
buffer->size = frame_info->size;
|
buffer->size = frame_info->size;
|
||||||
buffer->stride = frame_info->stride;
|
buffer->stride = frame_info->stride;
|
||||||
buffer->offset = 0;
|
buffer->offset = 0;
|
||||||
|
@ -87,6 +91,10 @@ struct xdpw_buffer *xdpw_buffer_create(struct xdpw_screencast_instance *cast,
|
||||||
free(buffer);
|
free(buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case DMABUF:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,11 +87,11 @@ static void wlr_frame_buffer(void *data, struct zwlr_screencopy_frame_v1 *frame,
|
||||||
logprint(TRACE, "wlroots: buffer event handler");
|
logprint(TRACE, "wlroots: buffer event handler");
|
||||||
cast->wlr_frame = frame;
|
cast->wlr_frame = frame;
|
||||||
|
|
||||||
cast->screencopy_frame_info.width = width;
|
cast->screencopy_frame_info[WL_SHM].width = width;
|
||||||
cast->screencopy_frame_info.height = height;
|
cast->screencopy_frame_info[WL_SHM].height = height;
|
||||||
cast->screencopy_frame_info.stride = stride;
|
cast->screencopy_frame_info[WL_SHM].stride = stride;
|
||||||
cast->screencopy_frame_info.size = stride * height;
|
cast->screencopy_frame_info[WL_SHM].size = stride * height;
|
||||||
cast->screencopy_frame_info.format = xdpw_format_drm_fourcc_from_wl_shm(format);
|
cast->screencopy_frame_info[WL_SHM].format = xdpw_format_drm_fourcc_from_wl_shm(format);
|
||||||
|
|
||||||
if (zwlr_screencopy_manager_v1_get_version(cast->ctx->screencopy_manager) < 3) {
|
if (zwlr_screencopy_manager_v1_get_version(cast->ctx->screencopy_manager) < 3) {
|
||||||
wlr_frame_buffer_done(cast, frame);
|
wlr_frame_buffer_done(cast, frame);
|
||||||
|
@ -116,10 +116,10 @@ static void wlr_frame_buffer_done(void *data,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if announced screencopy information is compatible with pipewire meta
|
// Check if announced screencopy information is compatible with pipewire meta
|
||||||
if ((cast->pwr_format.format != xdpw_format_pw_from_drm_fourcc(cast->screencopy_frame_info.format) &&
|
if ((cast->pwr_format.format != xdpw_format_pw_from_drm_fourcc(cast->screencopy_frame_info[cast->buffer_type].format) &&
|
||||||
cast->pwr_format.format != xdpw_format_pw_strip_alpha(xdpw_format_pw_from_drm_fourcc(cast->screencopy_frame_info.format))) ||
|
cast->pwr_format.format != xdpw_format_pw_strip_alpha(xdpw_format_pw_from_drm_fourcc(cast->screencopy_frame_info[cast->buffer_type].format))) ||
|
||||||
cast->pwr_format.size.width != cast->screencopy_frame_info.width ||
|
cast->pwr_format.size.width != cast->screencopy_frame_info[cast->buffer_type].width ||
|
||||||
cast->pwr_format.size.height != cast->screencopy_frame_info.height) {
|
cast->pwr_format.size.height != cast->screencopy_frame_info[cast->buffer_type].height) {
|
||||||
logprint(DEBUG, "wlroots: pipewire and wlroots metadata are incompatible. Renegotiate stream");
|
logprint(DEBUG, "wlroots: pipewire and wlroots metadata are incompatible. Renegotiate stream");
|
||||||
cast->frame_state = XDPW_FRAME_STATE_RENEG;
|
cast->frame_state = XDPW_FRAME_STATE_RENEG;
|
||||||
xdpw_wlr_frame_finish(cast);
|
xdpw_wlr_frame_finish(cast);
|
||||||
|
@ -140,8 +140,11 @@ static void wlr_frame_buffer_done(void *data,
|
||||||
assert(cast->current_frame.xdpw_buffer);
|
assert(cast->current_frame.xdpw_buffer);
|
||||||
|
|
||||||
// Check if dequeued buffer is compatible with announced buffer
|
// Check if dequeued buffer is compatible with announced buffer
|
||||||
if (cast->current_frame.xdpw_buffer->size != cast->screencopy_frame_info.size ||
|
if (( cast->buffer_type == WL_SHM &&
|
||||||
cast->current_frame.xdpw_buffer->stride != cast->screencopy_frame_info.stride) {
|
(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->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");
|
logprint(DEBUG, "wlroots: pipewire buffer has wrong dimensions");
|
||||||
cast->frame_state = XDPW_FRAME_STATE_FAILED;
|
cast->frame_state = XDPW_FRAME_STATE_FAILED;
|
||||||
xdpw_wlr_frame_finish(cast);
|
xdpw_wlr_frame_finish(cast);
|
||||||
|
|
Loading…
Reference in a new issue