Currently we dispose any unneeded color buffers immediately if we detect that there are more unlocked buffers than we need. This can lead to feedback loops between the compositor and the application causing rapid toggling between double and tripple buffering. Scenario: 2 buffers already qeued to the compositor, egl/wayland allocates a new back buffer to avoid trottling, slowing down the frame, this allows the compositor to catch up and unlock both buffers, then EGL detects that there are more buffers than currently need, freeing the buffer, restartig the loop shortly after.
To avoid wasting CPU time on rapidly freeing and reallocating color buffers break those feedback loops by letting the unneeded buffers sit around for a short while before disposing them. Signed-off-by: Lucas Stach <l.st...@pengutronix.de> --- src/egl/drivers/dri2/platform_wayland.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c index 34e09d7ec167..3fa08c1639d1 100644 --- a/src/egl/drivers/dri2/platform_wayland.c +++ b/src/egl/drivers/dri2/platform_wayland.c @@ -474,15 +474,17 @@ get_back_bo(struct dri2_egl_surface *dri2_surf) wl_display_dispatch_queue_pending(dri2_dpy->wl_dpy, dri2_surf->wl_queue); while (dri2_surf->back == NULL) { + int age = 0; for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { /* Get an unlocked buffer, preferably one with a dri_buffer * already allocated. */ - if (dri2_surf->color_buffers[i].locked) + if (dri2_surf->color_buffers[i].locked || dri2_surf->color_buffers[i].age < age) continue; if (dri2_surf->back == NULL) dri2_surf->back = &dri2_surf->color_buffers[i]; - else if (dri2_surf->back->dri_image == NULL) + else if (dri2_surf->back->dri_image == NULL && dri2_surf->color_buffers[i].dri_image) dri2_surf->back = &dri2_surf->color_buffers[i]; + age = dri2_surf->back->age; } if (dri2_surf->back) @@ -615,10 +617,13 @@ update_buffers(struct dri2_egl_surface *dri2_surf) /* If we have an extra unlocked buffer at this point, we had to do triple * buffering for a while, but now can go back to just double buffering. - * That means we can free any unlocked buffer now. */ + * That means we can free any unlocked buffer now. To avoid toggling between + * going back to double buffering and needing to allocate third buffer too + * fast we let the unneeded buffer sit around for a short while. */ for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { if (!dri2_surf->color_buffers[i].locked && - dri2_surf->color_buffers[i].wl_buffer) { + dri2_surf->color_buffers[i].wl_buffer && + dri2_surf->color_buffers[i].age > 18) { wl_buffer_destroy(dri2_surf->color_buffers[i].wl_buffer); dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].dri_image); if (dri2_dpy->is_different_gpu) -- 2.19.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev