diff --git a/libweston/renderer-gl/gl-renderer-internal.h b/libweston/renderer-gl/gl-renderer-internal.h index b52c3c1d..b8b6504d 100644 --- a/libweston/renderer-gl/gl-renderer-internal.h +++ b/libweston/renderer-gl/gl-renderer-internal.h @@ -202,12 +202,17 @@ void gl_shader_destroy(struct gl_renderer *gr, struct gl_shader *shader); struct gl_shader * -gl_shader_create(struct gl_renderer *gr, - const struct gl_shader_requirements *requirements); +gl_renderer_create_fallback_shader(struct gl_renderer *gr); -int -gl_shader_requirements_cmp(const struct gl_shader_requirements *a, - const struct gl_shader_requirements *b); +void +gl_renderer_garbage_collect_programs(struct gl_renderer *gr); + +bool +gl_renderer_use_program(struct gl_renderer *gr, struct gl_shader **shaderp); + +struct gl_shader * +gl_renderer_get_program(struct gl_renderer *gr, + const struct gl_shader_requirements *requirements); struct weston_log_scope * gl_shader_scope_create(struct gl_renderer *gr); diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c index 81c59c2a..e400ecb8 100644 --- a/libweston/renderer-gl/gl-renderer.c +++ b/libweston/renderer-gl/gl-renderer.c @@ -703,110 +703,6 @@ gl_fbo_texture_fini(struct gl_fbo_texture *fbotex) fbotex->tex = 0; } -static struct gl_shader * -gl_renderer_get_program(struct gl_renderer *gr, - const struct gl_shader_requirements *requirements) -{ - struct gl_shader_requirements reqs = *requirements; - struct gl_shader *shader; - - assert(reqs.pad_bits_ == 0); - - if (gr->fragment_shader_debug) - reqs.green_tint = true; - - if (gr->current_shader && - gl_shader_requirements_cmp(&reqs, &gr->current_shader->key) == 0) - return gr->current_shader; - - wl_list_for_each(shader, &gr->shader_list, link) { - if (gl_shader_requirements_cmp(&reqs, &shader->key) == 0) - return shader; - } - - shader = gl_shader_create(gr, &reqs); - if (shader) - return shader; - - weston_log("warning: failed to generate gl program\n"); - return NULL; -} - -static struct gl_shader * -gl_renderer_create_fallback_shader(struct gl_renderer *gr) -{ - static const struct gl_shader_requirements fallback_requirements = { - .variant = SHADER_VARIANT_SOLID, - }; - struct gl_shader *shader; - - shader = gl_shader_create(gr, &fallback_requirements); - if (!shader) - return NULL; - - /* - * This shader must be exempt from any automatic garbage collection. - * It is destroyed explicitly. - */ - wl_list_remove(&shader->link); - wl_list_init(&shader->link); - - return shader; -} - -static bool -gl_renderer_use_program(struct gl_renderer *gr, struct gl_shader **shaderp) -{ - static const GLfloat fallback_shader_color[4] = { 0.2, 0.1, 0.0, 1.0 }; - struct gl_shader *shader = *shaderp; - - if (!shader) { - weston_log("Error: trying to use NULL GL shader.\n"); - gr->current_shader = NULL; - shader = gr->fallback_shader; - glUseProgram(shader->program); - glUniform4fv(shader->color_uniform, 1, fallback_shader_color); - glUniform1f(shader->alpha_uniform, 1.0f); - *shaderp = shader; - return false; - } - - 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, }; diff --git a/libweston/renderer-gl/gl-shaders.c b/libweston/renderer-gl/gl-shaders.c index 6803acdd..0c5cec7f 100644 --- a/libweston/renderer-gl/gl-shaders.c +++ b/libweston/renderer-gl/gl-shaders.c @@ -159,7 +159,7 @@ create_shader_config_string(const struct gl_shader_requirements *req) return str; } -struct gl_shader * +static struct gl_shader * gl_shader_create(struct gl_renderer *gr, const struct gl_shader_requirements *requirements) { @@ -268,7 +268,7 @@ gl_shader_destroy(struct gl_renderer *gr, struct gl_shader *shader) free(shader); } -int +static int gl_shader_requirements_cmp(const struct gl_shader_requirements *a, const struct gl_shader_requirements *b) { @@ -322,3 +322,107 @@ gl_shader_scope_create(struct gl_renderer *gr) NULL, gr); } + +struct gl_shader * +gl_renderer_create_fallback_shader(struct gl_renderer *gr) +{ + static const struct gl_shader_requirements fallback_requirements = { + .variant = SHADER_VARIANT_SOLID, + }; + struct gl_shader *shader; + + shader = gl_shader_create(gr, &fallback_requirements); + if (!shader) + return NULL; + + /* + * This shader must be exempt from any automatic garbage collection. + * It is destroyed explicitly. + */ + wl_list_remove(&shader->link); + wl_list_init(&shader->link); + + return shader; +} + +struct gl_shader * +gl_renderer_get_program(struct gl_renderer *gr, + const struct gl_shader_requirements *requirements) +{ + struct gl_shader_requirements reqs = *requirements; + struct gl_shader *shader; + + assert(reqs.pad_bits_ == 0); + + if (gr->fragment_shader_debug) + reqs.green_tint = true; + + if (gr->current_shader && + gl_shader_requirements_cmp(&reqs, &gr->current_shader->key) == 0) + return gr->current_shader; + + wl_list_for_each(shader, &gr->shader_list, link) { + if (gl_shader_requirements_cmp(&reqs, &shader->key) == 0) + return shader; + } + + shader = gl_shader_create(gr, &reqs); + if (shader) + return shader; + + weston_log("warning: failed to generate gl program\n"); + return NULL; +} + +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); + } +} + +bool +gl_renderer_use_program(struct gl_renderer *gr, struct gl_shader **shaderp) +{ + static const GLfloat fallback_shader_color[4] = { 0.2, 0.1, 0.0, 1.0 }; + struct gl_shader *shader = *shaderp; + + if (!shader) { + weston_log("Error: trying to use NULL GL shader.\n"); + gr->current_shader = NULL; + shader = gr->fallback_shader; + glUseProgram(shader->program); + glUniform4fv(shader->color_uniform, 1, fallback_shader_color); + glUniform1f(shader->alpha_uniform, 1.0f); + *shaderp = shader; + return false; + } + + 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; +}