mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2026-06-18 21:28:27 +02:00
backend-pipewire: add MemFd allocator
Instead of letting PipeWire allocate the buffers, allocate them in the PipeWire backend. This allows the PipeWire backend to define the type of the allocated buffers, which will ultimately allow to allocate buffers that can be rendered to. Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
This commit is contained in:
parent
4304468a7e
commit
fa2f05219e
1 changed files with 97 additions and 4 deletions
|
|
@ -100,6 +100,7 @@ struct pipewire_head {
|
|||
|
||||
struct pipewire_frame_data {
|
||||
struct weston_renderbuffer *renderbuffer;
|
||||
struct pipewire_memfd *memfd;
|
||||
};
|
||||
|
||||
/* Pipewire default configuration for heads */
|
||||
|
|
@ -257,7 +258,7 @@ pipewire_output_connect(struct pipewire_output *output)
|
|||
|
||||
ret = pw_stream_connect(output->stream, PW_DIRECTION_OUTPUT, PW_ID_ANY,
|
||||
PW_STREAM_FLAG_DRIVER |
|
||||
PW_STREAM_FLAG_MAP_BUFFERS,
|
||||
PW_STREAM_FLAG_ALLOC_BUFFERS,
|
||||
params, i);
|
||||
if (ret != 0) {
|
||||
weston_log("Failed to connect PipeWire stream: %s",
|
||||
|
|
@ -460,6 +461,7 @@ pipewire_output_stream_param_changed(void *data, uint32_t id,
|
|||
SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
|
||||
const struct spa_pod *params[2];
|
||||
struct spa_video_info video_info;
|
||||
uint32_t buffertype;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
int32_t stride;
|
||||
|
|
@ -477,13 +479,17 @@ pipewire_output_stream_param_changed(void *data, uint32_t id,
|
|||
|
||||
spa_format_video_raw_parse(format, &video_info.info.raw);
|
||||
|
||||
pipewire_output_debug(output, "param changed: %dx%d@(%d/%d) (%s)",
|
||||
buffertype = SPA_DATA_MemFd;
|
||||
|
||||
pipewire_output_debug(output, "param changed: %dx%d@(%d/%d) (%s) (%s)",
|
||||
video_info.info.raw.size.width,
|
||||
video_info.info.raw.size.height,
|
||||
video_info.info.raw.max_framerate.num,
|
||||
video_info.info.raw.max_framerate.denom,
|
||||
spa_debug_type_find_short_name(spa_type_video_format,
|
||||
video_info.info.raw.format));
|
||||
video_info.info.raw.format),
|
||||
spa_debug_type_find_short_name(spa_type_data_type,
|
||||
buffertype));
|
||||
|
||||
width = video_info.info.raw.size.width;
|
||||
height = video_info.info.raw.size.height;
|
||||
|
|
@ -494,7 +500,8 @@ pipewire_output_stream_param_changed(void *data, uint32_t id,
|
|||
SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
|
||||
SPA_PARAM_BUFFERS_size, SPA_POD_Int(size),
|
||||
SPA_PARAM_BUFFERS_stride, SPA_POD_Int(stride),
|
||||
SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(4, 2, 8));
|
||||
SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(4, 2, 8),
|
||||
SPA_PARAM_BUFFERS_dataType, SPA_POD_CHOICE_FLAGS_Int(1u << buffertype));
|
||||
|
||||
params[1] = spa_pod_builder_add_object(&builder,
|
||||
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
|
||||
|
|
@ -551,11 +558,77 @@ pipewire_output_stream_add_buffer_gl(struct pipewire_output *output,
|
|||
format, width, height, ptr);
|
||||
}
|
||||
|
||||
struct pipewire_memfd {
|
||||
int fd;
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
static struct pipewire_memfd *
|
||||
pipewire_output_create_memfd(struct pipewire_output *output)
|
||||
{
|
||||
struct pipewire_memfd *memfd;
|
||||
const struct pixel_format_info *format;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int stride;
|
||||
size_t size;
|
||||
int fd;
|
||||
|
||||
memfd = xzalloc(sizeof *memfd);
|
||||
|
||||
format = output->pixel_format;
|
||||
width = output->base.width;
|
||||
height = output->base.height;
|
||||
stride = width * format->bpp / 8;
|
||||
size = height * stride;
|
||||
|
||||
fd = memfd_create("weston-pipewire", MFD_CLOEXEC);
|
||||
if (fd == -1)
|
||||
return NULL;
|
||||
if (ftruncate(fd, size) == -1)
|
||||
return NULL;
|
||||
|
||||
memfd->fd = fd;
|
||||
memfd->size = size;
|
||||
|
||||
return memfd;
|
||||
}
|
||||
|
||||
static void
|
||||
pipewire_destroy_memfd(struct pipewire_output *output,
|
||||
struct pipewire_memfd *memfd)
|
||||
{
|
||||
close(memfd->fd);
|
||||
free(memfd);
|
||||
}
|
||||
|
||||
static void
|
||||
pipewire_output_setup_memfd(struct pipewire_output *output,
|
||||
struct pw_buffer *buffer,
|
||||
struct pipewire_memfd *memfd)
|
||||
{
|
||||
struct spa_buffer *buf = buffer->buffer;
|
||||
struct spa_data *d = buf->datas;
|
||||
|
||||
d[0].type = SPA_DATA_MemFd;
|
||||
d[0].flags = SPA_DATA_FLAG_READWRITE;
|
||||
d[0].fd = memfd->fd;
|
||||
d[0].mapoffset = 0;
|
||||
d[0].maxsize = memfd->size;
|
||||
d[0].data = mmap(NULL, d[0].maxsize,
|
||||
PROT_READ|PROT_WRITE, MAP_SHARED,
|
||||
d[0].fd, d[0].mapoffset);
|
||||
buf->n_datas = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
pipewire_output_stream_add_buffer(void *data, struct pw_buffer *buffer)
|
||||
{
|
||||
struct pipewire_output *output = data;
|
||||
struct weston_renderer *renderer = output->base.compositor->renderer;
|
||||
struct spa_buffer *buf = buffer->buffer;
|
||||
struct spa_data *d = buf->datas;
|
||||
unsigned int buffertype = d[0].type;
|
||||
struct pipewire_frame_data *frame_data;
|
||||
|
||||
pipewire_output_debug(output, "add buffer: %p", buffer);
|
||||
|
|
@ -563,6 +636,19 @@ pipewire_output_stream_add_buffer(void *data, struct pw_buffer *buffer)
|
|||
frame_data = xzalloc(sizeof *frame_data);
|
||||
buffer->user_data = frame_data;
|
||||
|
||||
if (buffertype & (1u << SPA_DATA_MemFd)) {
|
||||
struct pipewire_memfd *memfd;
|
||||
|
||||
memfd = pipewire_output_create_memfd(output);
|
||||
if (!memfd) {
|
||||
pw_stream_set_error(output->stream, -ENOMEM,
|
||||
"failed to allocate MemFd buffer");
|
||||
return;
|
||||
}
|
||||
pipewire_output_setup_memfd(output, buffer, memfd);
|
||||
frame_data->memfd = memfd;
|
||||
}
|
||||
|
||||
switch (renderer->type) {
|
||||
case WESTON_RENDERER_PIXMAN:
|
||||
frame_data->renderbuffer = pipewire_output_stream_add_buffer_pixman(output, buffer);
|
||||
|
|
@ -580,9 +666,16 @@ pipewire_output_stream_remove_buffer(void *data, struct pw_buffer *buffer)
|
|||
{
|
||||
struct pipewire_output *output = data;
|
||||
struct pipewire_frame_data *frame_data = buffer->user_data;
|
||||
struct spa_buffer *buf = buffer->buffer;
|
||||
struct spa_data *d = buf->datas;
|
||||
|
||||
pipewire_output_debug(output, "remove buffer: %p", buffer);
|
||||
|
||||
if (frame_data->memfd) {
|
||||
munmap(d[0].data, d[0].maxsize);
|
||||
pipewire_destroy_memfd(output, frame_data->memfd);
|
||||
}
|
||||
|
||||
if (frame_data->renderbuffer)
|
||||
weston_renderbuffer_unref(frame_data->renderbuffer);
|
||||
free(frame_data);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue