diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index 4cdd2744..4daef0d3 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -1130,6 +1130,7 @@ struct weston_compositor { clockid_t presentation_clock; int32_t repaint_msec; + struct timespec last_repaint_start; unsigned int activate_serial; diff --git a/libweston/compositor.c b/libweston/compositor.c index 22a3a897..6e965372 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -2919,6 +2919,7 @@ output_repaint_timer_handler(void *data) int ret = 0; weston_compositor_read_presentation_clock(compositor, &now); + compositor->last_repaint_start = now; if (compositor->backend->repaint_begin) repaint_data = compositor->backend->repaint_begin(compositor); diff --git a/libweston/renderer-gl/gl-renderer-internal.h b/libweston/renderer-gl/gl-renderer-internal.h index 9e032ac7..b52c3c1d 100644 --- a/libweston/renderer-gl/gl-renderer-internal.h +++ b/libweston/renderer-gl/gl-renderer-internal.h @@ -29,6 +29,7 @@ #define GL_RENDERER_INTERNAL_H #include +#include #include #include @@ -82,6 +83,7 @@ struct gl_shader { GLint alpha_uniform; GLint color_uniform; struct wl_list link; /* gl_renderer::shader_list */ + struct timespec last_used; }; struct gl_renderer { @@ -158,9 +160,9 @@ struct gl_renderer { GLint gl_half_float_type; - /** struct gl_shader::link + /** Shader program cache in most recently used order * - * List constains cached shaders built from struct gl_shader_requirements + * Uses struct gl_shader::link. */ struct wl_list shader_list; struct weston_log_scope *shader_scope; diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c index ed5632d2..81c59c2a 100644 --- a/libweston/renderer-gl/gl-renderer.c +++ b/libweston/renderer-gl/gl-renderer.c @@ -1,6 +1,6 @@ /* * Copyright © 2012 Intel Corporation - * Copyright © 2015,2019 Collabora, Ltd. + * Copyright © 2015,2019,2021 Collabora, Ltd. * Copyright © 2016 NVIDIA Corporation * * Permission is hereby granted, free of charge, to any person obtaining @@ -774,11 +774,39 @@ gl_renderer_use_program(struct gl_renderer *gr, struct gl_shader **shaderp) if (gr->current_shader == shader) return true; + if (shader != gr->fallback_shader) { + /* Update list order for most recently used. */ + wl_list_remove(&shader->link); + wl_list_insert(&gr->shader_list, &shader->link); + } + shader->last_used = gr->compositor->last_repaint_start; + glUseProgram(shader->program); gr->current_shader = shader; return true; } +static void +gl_renderer_garbage_collect_programs(struct gl_renderer *gr) +{ + struct gl_shader *shader, *tmp; + unsigned count = 0; + + wl_list_for_each_safe(shader, tmp, &gr->shader_list, link) { + /* Keep the 10 most recently used always. */ + if (count++ < 10) + continue; + + /* Keep everything used in the past 1 minute. */ + if (timespec_sub_to_msec(&gr->compositor->last_repaint_start, + &shader->last_used) < 60000) + continue; + + /* The rest throw away. */ + gl_shader_destroy(gr, shader); + } +} + static const struct gl_shader_requirements requirements_triangle_fan = { .variant = SHADER_VARIANT_SOLID, }; @@ -1807,6 +1835,8 @@ gl_renderer_repaint_output(struct weston_output *output, TIMELINE_RENDER_POINT_TYPE_END); update_buffer_release_fences(compositor, output); + + gl_renderer_garbage_collect_programs(gr); } static int