diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h index 3e0c686dae2..04c9d4840db 100644 --- a/src/egl/drivers/dri2/egl_dri2.h +++ b/src/egl/drivers/dri2/egl_dri2.h @@ -338,6 +338,7 @@ struct dri2_egl_surface { #ifdef HAVE_DRM_PLATFORM struct gbm_dri_surface *gbm_surf; + unsigned excess_bo_frames; #endif #if defined(HAVE_WAYLAND_PLATFORM) || defined(HAVE_DRM_PLATFORM) diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c index 11ff7a73037..334e57ad57a 100644 --- a/src/egl/drivers/dri2/platform_drm.c +++ b/src/egl/drivers/dri2/platform_drm.c @@ -216,22 +216,59 @@ dri2_drm_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf) return EGL_TRUE; } +static void +destroy_oldest_unused_bo(struct dri2_egl_surface *dri2_surf) +{ + int max_age = 0; + struct dri2_egl_buffer *oldest_buffer = NULL; + + for (unsigned i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { + if (dri2_surf->color_buffers[i].locked || + dri2_surf->back == &dri2_surf->color_buffers[i]) + continue; + + if (!max_age || dri2_surf->color_buffers[i].age > max_age) { + oldest_buffer = &dri2_surf->color_buffers[i]; + max_age = dri2_surf->color_buffers[i].age; + } + } + + gbm_bo_destroy(oldest_buffer->bo); + oldest_buffer->bo = NULL; + oldest_buffer->age = 0; + + dri2_surf->excess_bo_frames = 0; +} + static int get_back_bo(struct dri2_egl_surface *dri2_surf) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display); struct gbm_dri_surface *surf = dri2_surf->gbm_surf; - int age = 0; + int min_age = 0, max_age = 0; if (dri2_surf->back == NULL) { for (unsigned i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { - if (!dri2_surf->color_buffers[i].locked && - dri2_surf->color_buffers[i].age >= age) { - dri2_surf->back = &dri2_surf->color_buffers[i]; - age = dri2_surf->color_buffers[i].age; + if (!dri2_surf->color_buffers[i].locked) { + int age = dri2_surf->color_buffers[i].age; + + if (!min_age || age < min_age) + min_age = age; + + if (!max_age || age > max_age) { + dri2_surf->back = &dri2_surf->color_buffers[i]; + max_age = age; + } } } + + if (min_age && min_age < max_age) { + if (++dri2_surf->excess_bo_frames == 1000) + destroy_oldest_unused_bo(dri2_surf); + } else { + dri2_surf->excess_bo_frames = 0; + } } if (dri2_surf->back == NULL)