backend-pipewire: add fence to synchronize on finish of render
If the PipeWire-backend renders to a DmaBuf, try to use a fence to synchronize the submit of the next PipeWire buffer to the completion of the current render process. This ensures that the GPU rendering is finished before the buffer is passed to PipeWire. If fences are not available, the buffer is submitted without explicit synchronization as before. Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
This commit is contained in:
parent
f271dd34b6
commit
4b4cedfc66
|
@ -88,6 +88,7 @@ struct pipewire_output {
|
|||
struct pw_stream *stream;
|
||||
struct spa_hook stream_listener;
|
||||
|
||||
struct wl_list fence_list;
|
||||
const struct pixel_format_info *pixel_format;
|
||||
|
||||
struct wl_event_source *finish_frame_timer;
|
||||
|
@ -780,6 +781,14 @@ pipewire_output_stream_add_buffer(void *data, struct pw_buffer *buffer)
|
|||
}
|
||||
}
|
||||
|
||||
struct pipewire_fence_data {
|
||||
struct pipewire_output *output;
|
||||
struct pw_buffer *buffer;
|
||||
int fence_sync_fd;
|
||||
struct wl_event_source *fence_sync_event_source;
|
||||
struct wl_list link;
|
||||
};
|
||||
|
||||
static void
|
||||
pipewire_output_stream_remove_buffer(void *data, struct pw_buffer *buffer)
|
||||
{
|
||||
|
@ -787,6 +796,7 @@ pipewire_output_stream_remove_buffer(void *data, struct pw_buffer *buffer)
|
|||
struct pipewire_frame_data *frame_data = buffer->user_data;
|
||||
struct spa_buffer *buf = buffer->buffer;
|
||||
struct spa_data *d = buf->datas;
|
||||
struct pipewire_fence_data *fence_data;
|
||||
|
||||
pipewire_output_debug(output, "remove buffer: %p", buffer);
|
||||
|
||||
|
@ -805,6 +815,10 @@ pipewire_output_stream_remove_buffer(void *data, struct pw_buffer *buffer)
|
|||
|
||||
if (frame_data->renderbuffer)
|
||||
weston_renderbuffer_unref(frame_data->renderbuffer);
|
||||
wl_list_for_each(fence_data, &output->fence_list, link) {
|
||||
if (fence_data->buffer == buffer)
|
||||
fence_data->buffer = NULL;
|
||||
}
|
||||
free(frame_data);
|
||||
}
|
||||
|
||||
|
@ -839,6 +853,8 @@ pipewire_create_output(struct weston_backend *backend, const char *name)
|
|||
output->backend = b;
|
||||
output->pixel_format = b->pixel_format;
|
||||
|
||||
wl_list_init(&output->fence_list);
|
||||
|
||||
props = pw_properties_new(NULL, NULL);
|
||||
pw_properties_setf(props, PW_KEY_NODE_NAME, "weston.%s", name);
|
||||
|
||||
|
@ -966,6 +982,57 @@ pipewire_submit_buffer(struct pipewire_output *output,
|
|||
output->seq++;
|
||||
}
|
||||
|
||||
static int
|
||||
pipewire_output_fence_sync_handler(int fd, uint32_t mask, void *data)
|
||||
{
|
||||
struct pipewire_fence_data *fence_data = data;
|
||||
|
||||
if (fence_data->buffer)
|
||||
pipewire_submit_buffer(fence_data->output, fence_data->buffer);
|
||||
|
||||
wl_event_source_remove(fence_data->fence_sync_event_source);
|
||||
close(fence_data->fence_sync_fd);
|
||||
wl_list_remove(&fence_data->link);
|
||||
free(fence_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pipewire_schedule_submit_buffer(struct pipewire_output *output,
|
||||
struct pw_buffer *buffer)
|
||||
{
|
||||
struct weston_compositor *ec = output->base.compositor;
|
||||
struct weston_renderer *renderer = ec->renderer;
|
||||
struct pipewire_fence_data *fence_data;
|
||||
struct wl_event_loop *loop;
|
||||
int fence_sync_fd;
|
||||
|
||||
fence_sync_fd = renderer->gl->create_fence_fd(&output->base);
|
||||
if (fence_sync_fd == -1)
|
||||
return -1;
|
||||
|
||||
fence_data = zalloc(sizeof *fence_data);
|
||||
if (!fence_data) {
|
||||
close(fence_sync_fd);
|
||||
return -1;
|
||||
}
|
||||
wl_list_insert(&output->fence_list, &fence_data->link);
|
||||
|
||||
loop = wl_display_get_event_loop(output->backend->compositor->wl_display);
|
||||
|
||||
fence_data->output = output;
|
||||
fence_data->buffer = buffer;
|
||||
fence_data->fence_sync_fd = fence_sync_fd;
|
||||
fence_data->fence_sync_event_source =
|
||||
wl_event_loop_add_fd(loop, fence_data->fence_sync_fd,
|
||||
WL_EVENT_READABLE,
|
||||
pipewire_output_fence_sync_handler,
|
||||
fence_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pipewire_output_repaint(struct weston_output *base)
|
||||
{
|
||||
|
@ -974,6 +1041,7 @@ pipewire_output_repaint(struct weston_output *base)
|
|||
struct pw_buffer *buffer;
|
||||
struct pipewire_frame_data *frame_data;
|
||||
pixman_region32_t damage;
|
||||
bool submit_scheduled = false;
|
||||
|
||||
assert(output);
|
||||
|
||||
|
@ -1000,7 +1068,12 @@ pipewire_output_repaint(struct weston_output *base)
|
|||
else
|
||||
output->base.full_repaint_needed = true;
|
||||
|
||||
pipewire_submit_buffer(output, buffer);
|
||||
if (buffer->buffer->datas[0].type == SPA_DATA_DmaBuf) {
|
||||
if (pipewire_schedule_submit_buffer(output, buffer) == 0)
|
||||
submit_scheduled = true;
|
||||
}
|
||||
if (!submit_scheduled)
|
||||
pipewire_submit_buffer(output, buffer);
|
||||
|
||||
out:
|
||||
|
||||
|
|
Loading…
Reference in New Issue