@ -159,7 +159,7 @@ create_shader_config_string(const struct gl_shader_requirements *req)
return str ;
return str ;
}
}
struct gl_shader *
static st ruct gl_shader *
gl_shader_create ( struct gl_renderer * gr ,
gl_shader_create ( struct gl_renderer * gr ,
const struct gl_shader_requirements * requirements )
const struct gl_shader_requirements * requirements )
{
{
@ -268,7 +268,7 @@ gl_shader_destroy(struct gl_renderer *gr, struct gl_shader *shader)
free ( shader ) ;
free ( shader ) ;
}
}
int
static int
gl_shader_requirements_cmp ( const struct gl_shader_requirements * a ,
gl_shader_requirements_cmp ( const struct gl_shader_requirements * a ,
const struct gl_shader_requirements * b )
const struct gl_shader_requirements * b )
{
{
@ -322,3 +322,107 @@ gl_shader_scope_create(struct gl_renderer *gr)
NULL ,
NULL ,
gr ) ;
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 ;
}