Search
lxdream.org :: lxdream/src/tools/genglsl.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/tools/genglsl.c
changeset 1207:f7ca985659c6
prev1169:23a9613aceb1
next1208:6955202d6408
author nkeynes
date Tue Feb 07 11:20:00 2012 +1000 (9 years ago)
permissions -rw-r--r--
last change Gen helper functions for uniform + attribute variables, along with the main
program use, to provide a more usable interface to the shaders
file annotate diff log raw
1.1 --- a/src/tools/genglsl.c Thu Apr 07 21:42:55 2011 +1000
1.2 +++ b/src/tools/genglsl.c Tue Feb 07 11:20:00 2012 +1000
1.3 @@ -21,6 +21,7 @@
1.4 */
1.5
1.6 #include <assert.h>
1.7 +#include <ctype.h>
1.8 #include <errno.h>
1.9 #include <stdio.h>
1.10 #include <stdlib.h>
1.11 @@ -37,15 +38,24 @@
1.12 FRAGMENT_SHADER = 1
1.13 } shader_type_t;
1.14
1.15 +typedef struct variable {
1.16 + gboolean uniform; /* TRUE = uniform, FALSE = attribute */
1.17 + const char *name;
1.18 + const char *type;
1.19 +} *variable_t;
1.20 +
1.21 typedef struct shader {
1.22 shader_type_t type;
1.23 const char *name;
1.24 char *body;
1.25 + GList *variables;
1.26 } *shader_t;
1.27
1.28 typedef struct program {
1.29 const char *name;
1.30 gchar **shader_names;
1.31 + GList *shaders;
1.32 + GList *variables;
1.33 } *program_t;
1.34
1.35 typedef struct glsldata {
1.36 @@ -55,6 +65,85 @@
1.37 GList *programs;
1.38 } *glsldata_t;
1.39
1.40 +#define isident(c) (isalnum(c)||(c)=='_')
1.41 +
1.42 +static void parseVarDecl( shader_t shader, gboolean uniform, char *input )
1.43 +{
1.44 + unsigned i;
1.45 + char *p = g_strstrip(input);
1.46 + for( i=0; isident(p[i]); i++)
1.47 + if( p[i] == 0 ) {
1.48 + fprintf( stderr, "Error: unable to parse variable decl '%s'\n", p );
1.49 + return; /* incomplete decl? */
1.50 + }
1.51 + char *type = g_strndup(p, i);
1.52 + p = g_strstrip(input+i);
1.53 + for( i=0; isident(p[i]); i++)
1.54 + if( p[i] == 0 ) {
1.55 + fprintf( stderr, "Error: unable to parse variable decl '%s'\n", p );
1.56 + return; /* incomplete decl? */
1.57 + }
1.58 + char *name = g_strndup(p, i);
1.59 + variable_t var = g_malloc0(sizeof(struct variable));
1.60 + var->uniform = uniform;
1.61 + var->type = type;
1.62 + var->name = name;
1.63 + shader->variables = g_list_append(shader->variables,var);
1.64 +}
1.65 +
1.66 +static shader_t findShader( GList *shaders, const char *name )
1.67 +{
1.68 + GList *ptr = shaders;
1.69 + while( ptr != NULL ) {
1.70 + shader_t shader = ptr->data;
1.71 + if( strcmp(shader->name, name) == 0 )
1.72 + return shader;
1.73 + ptr = ptr->next;
1.74 + }
1.75 + return NULL;
1.76 +}
1.77 +
1.78 +static gboolean addProgramVariable( program_t program, variable_t variable )
1.79 +{
1.80 + GList *ptr = program->variables;
1.81 + while( ptr != NULL ) {
1.82 + variable_t varp = ptr->data;
1.83 + if( strcmp(varp->name, variable->name) == 0 ) {
1.84 + if( varp->uniform == variable->uniform && strcmp(varp->type, variable->type) == 0 )
1.85 + return TRUE; /* All ok */
1.86 + fprintf( stderr, "Error: Variable type mismatch on '%s'\n", variable->name );
1.87 + return FALSE;
1.88 + }
1.89 + ptr = ptr->next;
1.90 + }
1.91 + program->variables = g_list_append(program->variables, variable);
1.92 + return TRUE;
1.93 +}
1.94 +
1.95 +static void linkPrograms( glsldata_t data )
1.96 +{
1.97 + GList *program_ptr = data->programs;
1.98 + unsigned i;
1.99 + while( program_ptr != NULL ) {
1.100 + program_t program = program_ptr->data;
1.101 + for( i=0; program->shader_names[i] != NULL; i++ ) {
1.102 + shader_t shader = findShader(data->shaders, program->shader_names[i]);
1.103 + if( shader == NULL ) {
1.104 + fprintf( stderr, "Error: unable to resolve shader '%s'\n", program->shader_names[i] );\
1.105 + } else {
1.106 + GList *varptr = shader->variables;
1.107 + while( varptr != NULL ) {
1.108 + addProgramVariable(program, varptr->data);
1.109 + varptr = varptr->next;
1.110 + }
1.111 + }
1.112 + }
1.113 + program_ptr = program_ptr->next;
1.114 + }
1.115 +
1.116 +}
1.117 +
1.118 +
1.119 static struct glsldata *readInput( const char *filename )
1.120 {
1.121 char buf[MAX_LINE];
1.122 @@ -68,19 +157,16 @@
1.123 }
1.124
1.125 shader_t shader = NULL;
1.126 - glsldata_t result = malloc(sizeof(struct glsldata));
1.127 + glsldata_t result = g_malloc0(sizeof(struct glsldata));
1.128 assert( result != NULL );
1.129 result->filename = strdup(filename);
1.130 - result->shaders = NULL;
1.131 - result->programs = NULL;
1.132 - result->max_shaders = 0;
1.133
1.134 while( fgets(buf, sizeof(buf), f) != NULL ) {
1.135 if( strlen(buf) == 0 )
1.136 continue;
1.137
1.138 if( strncmp(buf, "#vertex ", 8) == 0 ) {
1.139 - shader = malloc(sizeof(struct shader));
1.140 + shader = g_malloc0(sizeof(struct shader));
1.141 assert( shader != NULL );
1.142 shader->type = VERTEX_SHADER;
1.143 shader->name = strdup(g_strstrip(buf+8));
1.144 @@ -90,7 +176,7 @@
1.145 current_posn = 0;
1.146 result->shaders = g_list_append(result->shaders, shader);
1.147 } else if( strncmp( buf, "#fragment ", 10 ) == 0 ) {
1.148 - shader = malloc(sizeof(struct shader));
1.149 + shader = g_malloc0(sizeof(struct shader));
1.150 assert( shader != NULL );
1.151 shader->type = FRAGMENT_SHADER;
1.152 shader->name = strdup(g_strstrip(buf+10));
1.153 @@ -101,7 +187,7 @@
1.154 result->shaders = g_list_append(result->shaders, shader);
1.155 } else if( strncmp( buf, "#program ", 9 ) == 0 ) {
1.156 shader = NULL;
1.157 - program_t program = malloc(sizeof(struct program));
1.158 + program_t program = g_malloc0(sizeof(struct program));
1.159 char *rest = buf+9;
1.160 char *equals = strchr(rest, '=');
1.161 if( equals == NULL ) {
1.162 @@ -124,10 +210,17 @@
1.163 }
1.164 strcpy( shader->body + current_posn, buf );
1.165 current_posn += len;
1.166 + char *line = g_strstrip(buf);
1.167 + if( strncmp( line, "uniform ", 8 ) == 0 ) {
1.168 + parseVarDecl(shader, TRUE, line+8);
1.169 + } else if( strncmp( line, "attribute ", 10 ) == 0 ) {
1.170 + parseVarDecl(shader, FALSE, line+10);
1.171 + }
1.172 }
1.173 }
1.174
1.175 fclose(f);
1.176 + linkPrograms(result);
1.177 return result;
1.178 }
1.179
1.180 @@ -149,6 +242,28 @@
1.181 }
1.182 }
1.183
1.184 +static const char *sl_type_map[][3] = {
1.185 + {"int", "int", "int *"},
1.186 + {"short", "short", "short *"},
1.187 + {"sampler", "int", "int *"},
1.188 + {"vec", "GLfloat *", "GLfloat *"},
1.189 + {"mat", "GLfloat *", "GLfloat *"},
1.190 + {NULL, NULL}
1.191 +};
1.192 +
1.193 +static const char *getCType( const char *sl_type, gboolean isUniform ) {
1.194 + for( unsigned i=0; sl_type_map[i][0] != NULL; i++ ) {
1.195 + if( strncmp(sl_type_map[i][0], sl_type, strlen(sl_type_map[i][0])) == 0 ) {
1.196 + if( isUniform ) {
1.197 + return sl_type_map[i][1];
1.198 + } else {
1.199 + return sl_type_map[i][2];
1.200 + }
1.201 + }
1.202 + }
1.203 + return "void *";
1.204 +}
1.205 +
1.206 static void writeHeader( FILE *out, glsldata_t data )
1.207 {
1.208 fprintf( out, "/*\n * This file automatically generated by genglsl from %s\n */\n", data->filename );
1.209 @@ -185,26 +300,26 @@
1.210 fprintf( f, "#define GLSL_VERTEX_SHADER 1\n" );
1.211 fprintf( f, "#define GLSL_FRAGMENT_SHADER 2\n" );
1.212
1.213 - fprintf( f, "typedef enum {\n" );
1.214 - last_name = NULL;
1.215 count = 0;
1.216 GList *program_ptr;
1.217 for( program_ptr = data->programs; program_ptr != NULL; program_ptr = program_ptr->next ) {
1.218 count++;
1.219 - program_t program = (program_t)program_ptr->data;
1.220 - fprintf( f, " %s,\n", program->name );
1.221 - last_name = program->name;
1.222 }
1.223 - fprintf( f, "} program_id;\n\n" );
1.224 + fprintf( f, "#define GLSL_NUM_PROGRAMS %d\n", count );
1.225
1.226 - if( last_name == NULL )
1.227 - last_name = "NULL";
1.228 - fprintf( f, "#define GLSL_LAST_PROGRAM %s\n", last_name );
1.229 - fprintf( f, "#define GLSL_NUM_PROGRAMS %d\n", count );
1.230 - fprintf( f, "#define GLSL_NO_PROGRAM -1\n\n" );
1.231 -
1.232 - fprintf( f, "int glsl_load_programs();\n" );
1.233 - fprintf( f, "void glsl_use_program_id( program_id );\n" );
1.234 + for( program_ptr = data->programs; program_ptr != NULL; program_ptr = program_ptr->next ) {
1.235 + program_t program = program_ptr->data;
1.236 + GList *var_ptr;
1.237 + fprintf( f, "void glsl_use_%s();\n", program->name );
1.238 + for( var_ptr = program->variables; var_ptr != NULL; var_ptr = var_ptr->next ) {
1.239 + variable_t var = var_ptr->data;
1.240 + if( var->uniform ) {
1.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 );
1.242 + } else {
1.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);
1.244 + }
1.245 + }
1.246 + }
1.247
1.248 fprintf( f, "#endif /* !lxdream_glsl_H */\n" );
1.249
1.250 @@ -234,6 +349,7 @@
1.251
1.252 fprintf( f, "const int program_list[][%d] = {\n", data->max_shaders+1 );
1.253 GList *program_ptr;
1.254 + GList *var_ptr;
1.255 unsigned i;
1.256 for( program_ptr = data->programs; program_ptr != NULL; program_ptr = program_ptr->next ) {
1.257 program_t program = (program_t)program_ptr->data;
1.258 @@ -245,6 +361,48 @@
1.259 }
1.260 fprintf( f, " {GLSL_NO_SHADER}};\n" );
1.261
1.262 + /* per-program functions */
1.263 + for( program_ptr = data->programs; program_ptr != NULL; program_ptr = program_ptr->next ) {
1.264 + program_t program = program_ptr->data;
1.265 + fprintf( f, "\nstatic gl_program_t prog_%s_id;\n",program->name );
1.266 + for( var_ptr = program->variables; var_ptr != NULL; var_ptr = var_ptr->next ) {
1.267 + variable_t var = var_ptr->data;
1.268 + fprintf( f, "static GLint var_%s_%s_loc;\n", program->name, var->name);
1.269 + }
1.270 +
1.271 + }
1.272 + for( program_ptr = data->programs; program_ptr != NULL; program_ptr = program_ptr->next ) {
1.273 + program_t program = program_ptr->data;
1.274 + fprintf( f, "\nvoid glsl_use_%s() {\n glsl_use_program(prog_%s_id);\n}\n", program->name, program->name );
1.275 +
1.276 + for( var_ptr = program->variables; var_ptr != NULL; var_ptr = var_ptr->next ) {
1.277 + variable_t var = var_ptr->data;
1.278 + if( var->uniform ) {
1.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 );
1.280 + fprintf( f, " glsl_set_uniform_%s(var_%s_%s_loc,value);\n}\n", var->type, program->name, var->name );
1.281 + } else {
1.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);
1.283 + fprintf( f, " glsl_set_attrib_%s(var_%s_%s_loc,stride, ptr);\n}\n", var->type, program->name, var->name );
1.284 + }
1.285 + }
1.286 + }
1.287 +
1.288 + fprintf( f, "\nstatic void glsl_init_programs( gl_program_t *ids ) {\n" );
1.289 + for( program_ptr = data->programs, i=0; program_ptr != NULL; program_ptr = program_ptr->next, i++ ) {
1.290 + program_t program = program_ptr->data;
1.291 +
1.292 + fprintf( f, " prog_%s_id = ids[%d];\n\n", program->name, i );
1.293 + for( var_ptr = program->variables; var_ptr != NULL; var_ptr = var_ptr->next ) {
1.294 + variable_t var = var_ptr->data;
1.295 + if( var->uniform ) {
1.296 + fprintf( f, " var_%s_%s_loc = glsl_get_uniform_location(prog_%s_id, \"%s\");\n", program->name, var->name, program->name, var->name );
1.297 + } else {
1.298 + fprintf( f, " var_%s_%s_loc = glsl_get_attrib_location(prog_%s_id, \"%s\");\n", program->name, var->name, program->name, var->name );
1.299 + }
1.300 + }
1.301 + }
1.302 + fprintf( f, "}\n" );
1.303 +
1.304 fclose(f);
1.305 }
1.306
.