revision 1207:f7ca985659c6
summary |
tree |
shortlog |
changelog |
graph |
changeset |
raw | bz2 | zip | gz changeset | 1207:f7ca985659c6 |
parent | 1206:a9b41bcb8410 |
child | 1208:6955202d6408 |
author | nkeynes |
date | Tue Feb 07 11:20:00 2012 +1000 (10 years ago) |
Gen helper functions for uniform + attribute variables, along with the main
program use, to provide a more usable interface to the shaders
program use, to provide a more usable interface to the shaders
1.1 --- a/src/pvr2/gl_sl.c Mon Jan 30 23:11:03 2012 +10001.2 +++ b/src/pvr2/gl_sl.c Tue Feb 07 11:20:00 2012 +10001.3 @@ -21,6 +21,7 @@1.4 #include "lxdream.h"1.5 #include "display.h"1.6 #include "pvr2/glutil.h"1.7 +#include "pvr2/shaders.h"1.9 #define MAX_ERROR_BUF 40961.10 #define INVALID_SHADER 01.11 @@ -151,25 +152,22 @@1.12 glDeleteObjectARB(program);1.13 }1.15 -static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)1.16 +static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)1.17 {1.18 return glGetUniformLocationARB(program, name);1.19 }1.21 -static inline GLint glsl_get_attrib_location_prim(gl_program_t program, const char *name)1.22 +static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)1.23 {1.24 return glGetAttribLocationARB(program, name);1.25 }1.27 -static inline void glsl_set_uniform_int_prim(GLint location, GLint value)1.28 -{1.29 - glUniform1iARB(location,value);1.30 -}1.31 -1.32 -static inline void glsl_set_uniform_mat4_prim(GLint location, GLfloat *value)1.33 -{1.34 - glUniformMatrix4fvARB(location, 1, GL_FALSE, value);1.35 -}1.36 +#define glsl_set_uniform_sampler1D(id,v) glUniform1iARB(id,v)1.37 +#define glsl_set_uniform_sampler2D(id,v) glUniform1iARB(id,v)1.38 +#define glsl_set_uniform_vec4(id,v) glUniform4fvARB(id,1,v)1.39 +#define glsl_set_uniform_mat4(id,v) glUniformMatrix4fvARB(id,1,GL_FALSE,v)1.40 +#define glsl_set_attrib_vec3(id,stride,v) glVertexAttribPointerARB(id, 3, GL_FLOAT, GL_FALSE, stride, v)1.41 +#define glsl_set_attrib_vec4(id,stride,v) glVertexAttribPointerARB(id, 4, GL_FLOAT, GL_FALSE, stride, v)1.43 #elif HAVE_OPENGL_SHADER1.45 @@ -279,24 +277,23 @@1.46 glDeleteProgram(program);1.47 }1.49 -static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)1.50 +static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)1.51 {1.52 return glGetUniformLocation(program, name);1.53 }1.54 -static inline void glsl_set_uniform_int_prim(GLint location, GLint value)1.55 -{1.56 - glUniform1i(location, value);1.57 -}1.58 -1.59 -static inline void glsl_set_uniform_mat4_prim(GLint location, GLfloat *value)1.60 -{1.61 - glUniformMatrix4fv(location, 1, GL_TRUE, value);1.62 -}1.63 -1.64 -static inline GLint glsl_get_attrib_location_prim(gl_program_t program, const char *name)1.65 +static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)1.66 {1.67 return glGetAttribLocation(program, name);1.68 }1.69 +1.70 +#define glsl_set_uniform_sampler1D(id,v) glUniform1i(id,v)1.71 +#define glsl_set_uniform_sampler2D(id,v) glUniform1i(id,v)1.72 +#define glsl_set_uniform_vec4(id,v) glUniform4fv(id,1,v)1.73 +#define glsl_set_uniform_mat4(id,v) glUniformMatrix4fv(id,1,GL_FALSE,v)1.74 +#define glsl_set_attrib_vec3(id,stride,v) glVertexAttribPointer(id, 3, GL_FLOAT, GL_FALSE, stride, v)1.75 +#define glsl_set_attrib_vec4(id,stride,v) glVertexAttribPointer(id, 4, GL_FLOAT, GL_FALSE, stride, v)1.76 +1.77 +1.78 #else1.79 gboolean glsl_is_supported()1.80 {1.81 @@ -335,23 +332,23 @@1.82 {1.83 }1.85 -static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)1.86 +static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)1.87 {1.88 return 0;1.89 }1.91 -static inline void glsl_set_uniform_int_prim(GLint location, GLint value)1.92 -{1.93 -}1.94 -1.95 -static inline void glsl_set_uniform_mat4_prim(GLint location, GLfloat *value)1.96 -{1.97 -}1.98 -1.99 -static inline GLint glsl_get_attrib_location_prim(gl_program_t program, const char *name)1.100 +static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)1.101 {1.102 return 0;1.103 }1.104 +1.105 +#define glsl_set_uniform_sampler2D(id,v)1.106 +#define glsl_set_uniform_vec4(id,v)1.107 +#define glsl_set_uniform_mat4(id,v)1.108 +#define glsl_set_attrib_vec3(id,stride,v)1.109 +#define glsl_set_attrib_vec4(id,stride,v)1.110 +1.111 +1.112 #endif1.114 /****************************************************************************/1.115 @@ -429,6 +426,7 @@1.116 return FALSE;1.117 }1.119 + glsl_init_programs(program_array);1.120 glsl_use_program(0);1.121 return TRUE;1.122 }1.123 @@ -444,46 +442,6 @@1.124 }1.125 }1.127 -gboolean glsl_set_shader(unsigned i)1.128 -{1.129 - assert( i >= 0 && i <= GLSL_LAST_PROGRAM );1.130 -1.131 - if( program_array[i] != INVALID_PROGRAM ) {1.132 - glsl_use_program(program_array[i]);1.133 - return TRUE;1.134 - } else {1.135 - return FALSE;1.136 - }1.137 -}1.138 -1.139 -GLint glsl_get_uniform_location( unsigned program, const char *name )1.140 -{1.141 - assert( program >= 0 && program <= GLSL_LAST_PROGRAM );1.142 -1.143 - return glsl_get_uniform_location_prim(program_array[program], name);1.144 -}1.145 -1.146 -GLint glsl_get_attrib_location( unsigned program, const char *name )1.147 -{1.148 - assert( program >= 0 && program <= GLSL_LAST_PROGRAM );1.149 -1.150 - return glsl_get_attrib_location_prim(program_array[program], name);1.151 -}1.152 -1.153 -void glsl_set_uniform_int( unsigned program, const char *name, GLint value )1.154 -{1.155 - assert( program >= 0 && program <= GLSL_LAST_PROGRAM );1.156 - GLint location = glsl_get_uniform_location_prim(program_array[program], name);1.157 - glsl_set_uniform_int_prim(location, value);1.158 -}1.159 -1.160 -void glsl_set_uniform_mat4( unsigned program, const char *name, GLfloat *value )1.161 -{1.162 - assert( program >= 0 && program <= GLSL_LAST_PROGRAM );1.163 - GLint location = glsl_get_uniform_location_prim(program_array[program], name);1.164 - glsl_set_uniform_mat4_prim(location, value);1.165 -}1.166 -1.167 void glsl_clear_shader()1.168 {1.169 glsl_use_program(0);
2.1 --- a/src/pvr2/glrender.c Mon Jan 30 23:11:03 2012 +10002.2 +++ b/src/pvr2/glrender.c Tue Feb 07 11:20:00 2012 +10002.3 @@ -24,6 +24,7 @@2.4 #include "pvr2/glutil.h"2.5 #include "pvr2/scene.h"2.6 #include "pvr2/tileiter.h"2.7 +#include "pvr2/shaders.h"2.9 #ifdef APPLE_BUILD2.10 #include "OpenGL/CGLCurrent.h"2.11 @@ -160,9 +161,9 @@2.12 glFogf(GL_FOG_END, 1.0);2.14 if( have_shaders ) {2.15 - glsl_set_shader(DEFAULT_PROGRAM);2.16 - glsl_set_uniform_int(DEFAULT_PROGRAM, "primary_texture", 0);2.17 - glsl_set_uniform_int(DEFAULT_PROGRAM, "palette_texture", 1);2.18 + glsl_use_pvr2_shader();2.19 + glsl_set_pvr2_shader_primary_texture(0);2.20 + glsl_set_pvr2_shader_palette_texture(1);2.21 glsl_clear_shader();2.22 }2.23 }2.24 @@ -460,7 +461,7 @@2.25 glSecondaryColorPointerEXT(3, GL_FLOAT, sizeof(struct vertex_struct), pvr2_scene.vertex_array[0].offset_rgba );2.26 glFogCoordPointerEXT(GL_FLOAT, sizeof(struct vertex_struct), &pvr2_scene.vertex_array[0].offset_rgba[3] );2.27 /* Turn on the shaders (if available) */2.28 - glsl_set_shader(DEFAULT_PROGRAM);2.29 + glsl_use_pvr2_shader();2.31 /* Render the background */2.32 gl_render_bkgnd( pvr2_scene.bkgnd_poly );
3.1 --- a/src/pvr2/glutil.h Mon Jan 30 23:11:03 2012 +10003.2 +++ b/src/pvr2/glutil.h Tue Feb 07 11:20:00 2012 +10003.3 @@ -21,7 +21,6 @@3.5 #include <stdio.h>3.6 #include "display.h"3.7 -#include "pvr2/shaders.h"3.9 #ifdef __cplusplus3.10 extern "C" {3.11 @@ -56,17 +55,17 @@3.12 gboolean isGLMultitextureSupported();3.13 gboolean isGLMirroredTextureSupported();3.15 +/****** Extension variant wrangling *****/3.16 +3.17 +3.18 +3.19 +3.20 /****** Shader handling (gl_sl.c) *****/3.21 gboolean glsl_is_supported(void);3.22 const char *glsl_get_version(void);3.23 gboolean glsl_load_shaders( );3.24 void glsl_unload_shaders(void);3.25 -gboolean glsl_set_shader( unsigned program_id );3.26 void glsl_clear_shader();3.27 -GLint glsl_get_uniform_location( unsigned program, const char *name );3.28 -void glsl_set_uniform_int( unsigned program, const char *name, GLint value );3.29 -void glsl_set_uniform_mat4( unsigned program, const char *name, GLfloat *value );3.30 -GLint glsl_get_attrib_location(unsigned program, const char *name);3.32 /* Convenience formatting function for driver use */3.33 void fprint_extensions( FILE *out, const char *extensions );
4.1 --- a/src/pvr2/shaders.glsl Mon Jan 30 23:11:03 2012 +10004.2 +++ b/src/pvr2/shaders.glsl Tue Feb 07 11:20:00 2012 +10004.3 @@ -105,5 +105,5 @@4.4 gl_FragDepth = gl_FragCoord.z;4.5 }4.7 -#program DEFAULT_PROGRAM = DEFAULT_VERTEX_SHADER DEFAULT_FRAGMENT_SHADER4.8 +#program pvr2_shader = DEFAULT_VERTEX_SHADER DEFAULT_FRAGMENT_SHADER
5.1 --- a/src/tools/genglsl.c Mon Jan 30 23:11:03 2012 +10005.2 +++ b/src/tools/genglsl.c Tue Feb 07 11:20:00 2012 +10005.3 @@ -21,6 +21,7 @@5.4 */5.6 #include <assert.h>5.7 +#include <ctype.h>5.8 #include <errno.h>5.9 #include <stdio.h>5.10 #include <stdlib.h>5.11 @@ -37,15 +38,24 @@5.12 FRAGMENT_SHADER = 15.13 } shader_type_t;5.15 +typedef struct variable {5.16 + gboolean uniform; /* TRUE = uniform, FALSE = attribute */5.17 + const char *name;5.18 + const char *type;5.19 +} *variable_t;5.20 +5.21 typedef struct shader {5.22 shader_type_t type;5.23 const char *name;5.24 char *body;5.25 + GList *variables;5.26 } *shader_t;5.28 typedef struct program {5.29 const char *name;5.30 gchar **shader_names;5.31 + GList *shaders;5.32 + GList *variables;5.33 } *program_t;5.35 typedef struct glsldata {5.36 @@ -55,6 +65,85 @@5.37 GList *programs;5.38 } *glsldata_t;5.40 +#define isident(c) (isalnum(c)||(c)=='_')5.41 +5.42 +static void parseVarDecl( shader_t shader, gboolean uniform, char *input )5.43 +{5.44 + unsigned i;5.45 + char *p = g_strstrip(input);5.46 + for( i=0; isident(p[i]); i++)5.47 + if( p[i] == 0 ) {5.48 + fprintf( stderr, "Error: unable to parse variable decl '%s'\n", p );5.49 + return; /* incomplete decl? */5.50 + }5.51 + char *type = g_strndup(p, i);5.52 + p = g_strstrip(input+i);5.53 + for( i=0; isident(p[i]); i++)5.54 + if( p[i] == 0 ) {5.55 + fprintf( stderr, "Error: unable to parse variable decl '%s'\n", p );5.56 + return; /* incomplete decl? */5.57 + }5.58 + char *name = g_strndup(p, i);5.59 + variable_t var = g_malloc0(sizeof(struct variable));5.60 + var->uniform = uniform;5.61 + var->type = type;5.62 + var->name = name;5.63 + shader->variables = g_list_append(shader->variables,var);5.64 +}5.65 +5.66 +static shader_t findShader( GList *shaders, const char *name )5.67 +{5.68 + GList *ptr = shaders;5.69 + while( ptr != NULL ) {5.70 + shader_t shader = ptr->data;5.71 + if( strcmp(shader->name, name) == 0 )5.72 + return shader;5.73 + ptr = ptr->next;5.74 + }5.75 + return NULL;5.76 +}5.77 +5.78 +static gboolean addProgramVariable( program_t program, variable_t variable )5.79 +{5.80 + GList *ptr = program->variables;5.81 + while( ptr != NULL ) {5.82 + variable_t varp = ptr->data;5.83 + if( strcmp(varp->name, variable->name) == 0 ) {5.84 + if( varp->uniform == variable->uniform && strcmp(varp->type, variable->type) == 0 )5.85 + return TRUE; /* All ok */5.86 + fprintf( stderr, "Error: Variable type mismatch on '%s'\n", variable->name );5.87 + return FALSE;5.88 + }5.89 + ptr = ptr->next;5.90 + }5.91 + program->variables = g_list_append(program->variables, variable);5.92 + return TRUE;5.93 +}5.94 +5.95 +static void linkPrograms( glsldata_t data )5.96 +{5.97 + GList *program_ptr = data->programs;5.98 + unsigned i;5.99 + while( program_ptr != NULL ) {5.100 + program_t program = program_ptr->data;5.101 + for( i=0; program->shader_names[i] != NULL; i++ ) {5.102 + shader_t shader = findShader(data->shaders, program->shader_names[i]);5.103 + if( shader == NULL ) {5.104 + fprintf( stderr, "Error: unable to resolve shader '%s'\n", program->shader_names[i] );\5.105 + } else {5.106 + GList *varptr = shader->variables;5.107 + while( varptr != NULL ) {5.108 + addProgramVariable(program, varptr->data);5.109 + varptr = varptr->next;5.110 + }5.111 + }5.112 + }5.113 + program_ptr = program_ptr->next;5.114 + }5.115 +5.116 +}5.117 +5.118 +5.119 static struct glsldata *readInput( const char *filename )5.120 {5.121 char buf[MAX_LINE];5.122 @@ -68,19 +157,16 @@5.123 }5.125 shader_t shader = NULL;5.126 - glsldata_t result = malloc(sizeof(struct glsldata));5.127 + glsldata_t result = g_malloc0(sizeof(struct glsldata));5.128 assert( result != NULL );5.129 result->filename = strdup(filename);5.130 - result->shaders = NULL;5.131 - result->programs = NULL;5.132 - result->max_shaders = 0;5.134 while( fgets(buf, sizeof(buf), f) != NULL ) {5.135 if( strlen(buf) == 0 )5.136 continue;5.138 if( strncmp(buf, "#vertex ", 8) == 0 ) {5.139 - shader = malloc(sizeof(struct shader));5.140 + shader = g_malloc0(sizeof(struct shader));5.141 assert( shader != NULL );5.142 shader->type = VERTEX_SHADER;5.143 shader->name = strdup(g_strstrip(buf+8));5.144 @@ -90,7 +176,7 @@5.145 current_posn = 0;5.146 result->shaders = g_list_append(result->shaders, shader);5.147 } else if( strncmp( buf, "#fragment ", 10 ) == 0 ) {5.148 - shader = malloc(sizeof(struct shader));5.149 + shader = g_malloc0(sizeof(struct shader));5.150 assert( shader != NULL );5.151 shader->type = FRAGMENT_SHADER;5.152 shader->name = strdup(g_strstrip(buf+10));5.153 @@ -101,7 +187,7 @@5.154 result->shaders = g_list_append(result->shaders, shader);5.155 } else if( strncmp( buf, "#program ", 9 ) == 0 ) {5.156 shader = NULL;5.157 - program_t program = malloc(sizeof(struct program));5.158 + program_t program = g_malloc0(sizeof(struct program));5.159 char *rest = buf+9;5.160 char *equals = strchr(rest, '=');5.161 if( equals == NULL ) {5.162 @@ -124,10 +210,17 @@5.163 }5.164 strcpy( shader->body + current_posn, buf );5.165 current_posn += len;5.166 + char *line = g_strstrip(buf);5.167 + if( strncmp( line, "uniform ", 8 ) == 0 ) {5.168 + parseVarDecl(shader, TRUE, line+8);5.169 + } else if( strncmp( line, "attribute ", 10 ) == 0 ) {5.170 + parseVarDecl(shader, FALSE, line+10);5.171 + }5.172 }5.173 }5.175 fclose(f);5.176 + linkPrograms(result);5.177 return result;5.178 }5.180 @@ -149,6 +242,28 @@5.181 }5.182 }5.184 +static const char *sl_type_map[][3] = {5.185 + {"int", "int", "int *"},5.186 + {"short", "short", "short *"},5.187 + {"sampler", "int", "int *"},5.188 + {"vec", "GLfloat *", "GLfloat *"},5.189 + {"mat", "GLfloat *", "GLfloat *"},5.190 + {NULL, NULL}5.191 +};5.192 +5.193 +static const char *getCType( const char *sl_type, gboolean isUniform ) {5.194 + for( unsigned i=0; sl_type_map[i][0] != NULL; i++ ) {5.195 + if( strncmp(sl_type_map[i][0], sl_type, strlen(sl_type_map[i][0])) == 0 ) {5.196 + if( isUniform ) {5.197 + return sl_type_map[i][1];5.198 + } else {5.199 + return sl_type_map[i][2];5.200 + }5.201 + }5.202 + }5.203 + return "void *";5.204 +}5.205 +5.206 static void writeHeader( FILE *out, glsldata_t data )5.207 {5.208 fprintf( out, "/*\n * This file automatically generated by genglsl from %s\n */\n", data->filename );5.209 @@ -185,26 +300,26 @@5.210 fprintf( f, "#define GLSL_VERTEX_SHADER 1\n" );5.211 fprintf( f, "#define GLSL_FRAGMENT_SHADER 2\n" );5.213 - fprintf( f, "typedef enum {\n" );5.214 - last_name = NULL;5.215 count = 0;5.216 GList *program_ptr;5.217 for( program_ptr = data->programs; program_ptr != NULL; program_ptr = program_ptr->next ) {5.218 count++;5.219 - program_t program = (program_t)program_ptr->data;5.220 - fprintf( f, " %s,\n", program->name );5.221 - last_name = program->name;5.222 }5.223 - fprintf( f, "} program_id;\n\n" );5.224 + fprintf( f, "#define GLSL_NUM_PROGRAMS %d\n", count );5.226 - if( last_name == NULL )5.227 - last_name = "NULL";5.228 - fprintf( f, "#define GLSL_LAST_PROGRAM %s\n", last_name );5.229 - fprintf( f, "#define GLSL_NUM_PROGRAMS %d\n", count );5.230 - fprintf( f, "#define GLSL_NO_PROGRAM -1\n\n" );5.231 -5.232 - fprintf( f, "int glsl_load_programs();\n" );5.233 - fprintf( f, "void glsl_use_program_id( program_id );\n" );5.234 + for( program_ptr = data->programs; program_ptr != NULL; program_ptr = program_ptr->next ) {5.235 + program_t program = program_ptr->data;5.236 + GList *var_ptr;5.237 + fprintf( f, "void glsl_use_%s();\n", program->name );5.238 + for( var_ptr = program->variables; var_ptr != NULL; var_ptr = var_ptr->next ) {5.239 + variable_t var = var_ptr->data;5.240 + if( var->uniform ) {5.241 + fprintf( f, "void glsl_set_%s_%s(%s value); /* uniform %s %s */ \n", program->name, var->name, getCType(var->type,var->uniform), var->type, var->name );5.242 + } else {5.243 + fprintf( f, "void glsl_set_%s_%s_pointer(%s ptr); /* attribute %s %s */ \n", program->name, var->name, getCType(var->type,var->uniform), var->type, var->name);5.244 + }5.245 + }5.246 + }5.248 fprintf( f, "#endif /* !lxdream_glsl_H */\n" );5.250 @@ -234,6 +349,7 @@5.252 fprintf( f, "const int program_list[][%d] = {\n", data->max_shaders+1 );5.253 GList *program_ptr;5.254 + GList *var_ptr;5.255 unsigned i;5.256 for( program_ptr = data->programs; program_ptr != NULL; program_ptr = program_ptr->next ) {5.257 program_t program = (program_t)program_ptr->data;5.258 @@ -245,6 +361,48 @@5.259 }5.260 fprintf( f, " {GLSL_NO_SHADER}};\n" );5.262 + /* per-program functions */5.263 + for( program_ptr = data->programs; program_ptr != NULL; program_ptr = program_ptr->next ) {5.264 + program_t program = program_ptr->data;5.265 + fprintf( f, "\nstatic gl_program_t prog_%s_id;\n",program->name );5.266 + for( var_ptr = program->variables; var_ptr != NULL; var_ptr = var_ptr->next ) {5.267 + variable_t var = var_ptr->data;5.268 + fprintf( f, "static GLint var_%s_%s_loc;\n", program->name, var->name);5.269 + }5.270 +5.271 + }5.272 + for( program_ptr = data->programs; program_ptr != NULL; program_ptr = program_ptr->next ) {5.273 + program_t program = program_ptr->data;5.274 + fprintf( f, "\nvoid glsl_use_%s() {\n glsl_use_program(prog_%s_id);\n}\n", program->name, program->name );5.275 +5.276 + for( var_ptr = program->variables; var_ptr != NULL; var_ptr = var_ptr->next ) {5.277 + variable_t var = var_ptr->data;5.278 + if( var->uniform ) {5.279 + fprintf( f, "void glsl_set_%s_%s(%s value){ /* uniform %s %s */ \n", program->name, var->name, getCType(var->type,var->uniform), var->type, var->name );5.280 + fprintf( f, " glsl_set_uniform_%s(var_%s_%s_loc,value);\n}\n", var->type, program->name, var->name );5.281 + } else {5.282 + fprintf( f, "void glsl_set_%s_%s_pointer(%s ptr, GLsizei stride){ /* attribute %s %s */ \n", program->name, var->name, getCType(var->type,var->uniform), var->type, var->name);5.283 + fprintf( f, " glsl_set_attrib_%s(var_%s_%s_loc,stride, ptr);\n}\n", var->type, program->name, var->name );5.284 + }5.285 + }5.286 + }5.287 +5.288 + fprintf( f, "\nstatic void glsl_init_programs( gl_program_t *ids ) {\n" );5.289 + for( program_ptr = data->programs, i=0; program_ptr != NULL; program_ptr = program_ptr->next, i++ ) {5.290 + program_t program = program_ptr->data;5.291 +5.292 + fprintf( f, " prog_%s_id = ids[%d];\n\n", program->name, i );5.293 + for( var_ptr = program->variables; var_ptr != NULL; var_ptr = var_ptr->next ) {5.294 + variable_t var = var_ptr->data;5.295 + if( var->uniform ) {5.296 + fprintf( f, " var_%s_%s_loc = glsl_get_uniform_location(prog_%s_id, \"%s\");\n", program->name, var->name, program->name, var->name );5.297 + } else {5.298 + fprintf( f, " var_%s_%s_loc = glsl_get_attrib_location(prog_%s_id, \"%s\");\n", program->name, var->name, program->name, var->name );5.299 + }5.300 + }5.301 + }5.302 + fprintf( f, "}\n" );5.303 +5.304 fclose(f);5.305 }
.