egl/dri/wayland: Refactor buffer wait out of get_back_bo()

This is a potentially slow process, so let's break it out into its own
function so we can have more meaningful profiling data from perfetto later.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32757>
This commit is contained in:
Derek Foreman
2025-01-29 11:37:48 -06:00
parent ebfd7df1b9
commit 39fb510849
+36 -30
View File
@@ -1146,6 +1146,41 @@ create_dri_image_from_formats(struct dri2_egl_surface *dri2_surf,
surf_modifiers_count, &dri2_dpy->formats);
}
static void
wait_for_free_buffer(struct dri2_egl_display *dri2_dpy,
struct dri2_egl_surface *dri2_surf)
{
/* There might be a buffer release already queued that wasn't processed */
wl_display_dispatch_queue_pending(dri2_dpy->wl_dpy, dri2_surf->wl_queue);
while (dri2_surf->back == NULL) {
for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
/* Get an unlocked buffer, preferably one with a dri_buffer
* already allocated and with minimum age.
*/
if (dri2_surf->color_buffers[i].locked)
continue;
if (!dri2_surf->back || !dri2_surf->back->dri_image ||
(dri2_surf->color_buffers[i].age > 0 &&
dri2_surf->color_buffers[i].age < dri2_surf->back->age))
dri2_surf->back = &dri2_surf->color_buffers[i];
}
if (dri2_surf->back)
break;
/* If we don't have a buffer, then block on the server to release one for
* us, and try again. wl_display_dispatch_queue will process any pending
* events, however not all servers flush on issuing a buffer release
* event. So, we spam the server with roundtrips as they always cause a
* client flush.
*/
if (wl_display_roundtrip_queue(dri2_dpy->wl_dpy, dri2_surf->wl_queue) < 0)
return;
}
}
static int
get_back_bo(struct dri2_egl_surface *dri2_surf)
{
@@ -1174,36 +1209,7 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
dri2_dpy->formats.formats_bitmap,
dri2_wl_visual_idx_from_pipe_format(linear_pipe_format)));
/* There might be a buffer release already queued that wasn't processed */
wl_display_dispatch_queue_pending(dri2_dpy->wl_dpy, dri2_surf->wl_queue);
while (dri2_surf->back == NULL) {
for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
/* Get an unlocked buffer, preferably one with a dri_buffer
* already allocated and with minimum age.
*/
if (dri2_surf->color_buffers[i].locked)
continue;
if (!dri2_surf->back || !dri2_surf->back->dri_image ||
(dri2_surf->color_buffers[i].age > 0 &&
dri2_surf->color_buffers[i].age < dri2_surf->back->age))
dri2_surf->back = &dri2_surf->color_buffers[i];
}
if (dri2_surf->back)
break;
/* If we don't have a buffer, then block on the server to release one for
* us, and try again. wl_display_dispatch_queue will process any pending
* events, however not all servers flush on issuing a buffer release
* event. So, we spam the server with roundtrips as they always cause a
* client flush.
*/
if (wl_display_roundtrip_queue(dri2_dpy->wl_dpy, dri2_surf->wl_queue) < 0)
return -1;
}
wait_for_free_buffer(dri2_dpy, dri2_surf);
if (dri2_surf->back == NULL)
return -1;