Blender  V2.59
gpu_codegen.c
Go to the documentation of this file.
00001 /*
00002  * $Id: gpu_codegen.c 35376 2011-03-06 23:12:12Z campbellbarton $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version. The Blender
00010  * Foundation also sells licenses for use in proprietary software under
00011  * the Blender License.  See http://www.blender.org/BL/ for information
00012  * about this.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software Foundation,
00021  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00022  *
00023  * The Original Code is Copyright (C) 2005 Blender Foundation.
00024  * All rights reserved.
00025  *
00026  * The Original Code is: all of this file.
00027  *
00028  * Contributor(s): Brecht Van Lommel.
00029  *
00030  * ***** END GPL LICENSE BLOCK *****
00031  */
00032 
00038 #include "GL/glew.h"
00039 
00040 #include "MEM_guardedalloc.h"
00041 
00042 #include "DNA_customdata_types.h"
00043 #include "DNA_image_types.h"
00044 #include "DNA_material_types.h"
00045 
00046 #include "BLI_blenlib.h"
00047 #include "BLI_utildefines.h"
00048 #include "BLI_dynstr.h"
00049 #include "BLI_ghash.h"
00050 #include "BLI_heap.h"
00051 
00052 #include "GPU_material.h"
00053 #include "GPU_extensions.h"
00054 
00055 #include "BLO_sys_types.h" // for intptr_t support
00056 
00057 #include "gpu_codegen.h"
00058 
00059 #include <string.h>
00060 #include <stdarg.h>
00061 
00062 #ifdef _WIN32
00063 #ifndef vsnprintf
00064 #define vsnprintf _vsnprintf
00065 #endif
00066 #ifndef snprintf
00067 #define snprintf _snprintf
00068 #endif
00069 #endif
00070 
00071 extern char datatoc_gpu_shader_material_glsl[];
00072 extern char datatoc_gpu_shader_vertex_glsl[];
00073 
00074 /* structs and defines */
00075 
00076 typedef enum GPUDataSource {
00077         GPU_SOURCE_VEC_UNIFORM,
00078         GPU_SOURCE_BUILTIN,
00079         GPU_SOURCE_TEX_PIXEL,
00080         GPU_SOURCE_TEX,
00081         GPU_SOURCE_ATTRIB
00082 } GPUDataSource;
00083 
00084 static const char* GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4",
00085         0, 0, 0, 0, "mat3", 0, 0, 0, 0, 0, 0, "mat4"};
00086 
00087 struct GPUNode {
00088         struct GPUNode *next, *prev;
00089 
00090         const char *name;
00091         int tag;
00092 
00093         ListBase inputs;
00094         ListBase outputs;
00095 };
00096 
00097 struct GPUNodeLink {
00098         GPUNodeStack *socket;
00099 
00100         int attribtype;
00101         const char *attribname;
00102 
00103         int image;
00104 
00105         int texture;
00106         int texturesize;
00107 
00108         void *ptr1, *ptr2;
00109 
00110         int dynamic;
00111 
00112         int type;
00113         int users;
00114 
00115         GPUTexture *dynamictex;
00116 
00117         GPUBuiltin builtin;
00118 
00119         struct GPUOutput *output;
00120 };
00121 
00122 typedef struct GPUOutput {
00123         struct GPUOutput *next, *prev;
00124 
00125         GPUNode *node;
00126         int type;                               /* data type = length of vector/matrix */
00127         GPUNodeLink *link;              /* output link */
00128         int id;                                 /* unique id as created by code generator */
00129 } GPUOutput;
00130 
00131 typedef struct GPUInput {
00132         struct GPUInput *next, *prev;
00133 
00134         GPUNode *node;
00135 
00136         int type;                               /* datatype */
00137         int source;                             /* data source */
00138 
00139         int id;                                 /* unique id as created by code generator */
00140         int texid;                              /* number for multitexture */
00141         int attribid;                   /* id for vertex attributes */
00142         int bindtex;                    /* input is responsible for binding the texture? */
00143         int definetex;                  /* input is responsible for defining the pixel? */
00144         int textarget;                  /* GL_TEXTURE_* */
00145         int textype;                    /* datatype */
00146 
00147         struct Image *ima;              /* image */
00148         struct ImageUser *iuser;/* image user */
00149         float *dynamicvec;              /* vector data in case it is dynamic */
00150         GPUTexture *tex;                /* input texture, only set at runtime */
00151         int shaderloc;                  /* id from opengl */
00152         char shadername[32];    /* name in shader */
00153 
00154         float vec[16];                  /* vector data */
00155         GPUNodeLink *link;
00156         int dynamictex;                 /* dynamic? */
00157         int attribtype;                 /* attribute type */
00158         char attribname[32];    /* attribute name */
00159         int attribfirst;                /* this is the first one that is bound */
00160         GPUBuiltin builtin;             /* builtin uniform */
00161 } GPUInput;
00162 
00163 struct GPUPass {
00164         struct GPUPass *next, *prev;
00165 
00166         ListBase inputs;
00167         struct GPUOutput *output;
00168         struct GPUShader *shader;
00169 };
00170 
00171 /* Strings utility */
00172 
00173 static void BLI_dynstr_printf(DynStr *dynstr, const char *format, ...)
00174 {
00175         va_list args;
00176         int retval;
00177         char str[2048];
00178 
00179         va_start(args, format);
00180         retval = vsnprintf(str, sizeof(str), format, args);
00181         va_end(args);
00182 
00183         if (retval >= sizeof(str))
00184                 fprintf(stderr, "BLI_dynstr_printf: limit exceeded\n");
00185         else
00186                 BLI_dynstr_append(dynstr, str);
00187 }
00188 
00189 /* GLSL code parsing for finding function definitions.
00190  * These are stored in a hash for lookup when creating a material. */
00191 
00192 static GHash *FUNCTION_HASH= NULL;
00193 /*static char *FUNCTION_PROTOTYPES= NULL;
00194 static GPUShader *FUNCTION_LIB= NULL;*/
00195 
00196 static int gpu_str_prefix(const char *str, const char *prefix)
00197 {
00198         while(*str && *prefix) {
00199                 if(*str != *prefix)
00200                         return 0;
00201 
00202                 str++;
00203                 prefix++;
00204         }
00205         
00206         return (*prefix == '\0');
00207 }
00208 
00209 static char *gpu_str_skip_token(char *str, char *token, int max)
00210 {
00211         int len = 0;
00212 
00213         /* skip a variable/function name */
00214         while(*str) {
00215                 if(ELEM6(*str, ' ', '(', ')', ',', '\t', '\n'))
00216                         break;
00217                 else {
00218                         if(token && len < max-1) {
00219                                 *token= *str;
00220                                 token++;
00221                                 len++;
00222                         }
00223                         str++;
00224                 }
00225         }
00226 
00227         if(token)
00228                 *token= '\0';
00229 
00230         /* skip the next special characters:
00231          * note the missing ')' */
00232         while(*str) {
00233                 if(ELEM5(*str, ' ', '(', ',', '\t', '\n'))
00234                         str++;
00235                 else
00236                         break;
00237         }
00238 
00239         return str;
00240 }
00241 
00242 static void gpu_parse_functions_string(GHash *hash, char *code)
00243 {
00244         GPUFunction *function;
00245         int i, type, qual;
00246 
00247         while((code = strstr(code, "void "))) {
00248                 function = MEM_callocN(sizeof(GPUFunction), "GPUFunction");
00249 
00250                 code = gpu_str_skip_token(code, NULL, 0);
00251                 code = gpu_str_skip_token(code, function->name, MAX_FUNCTION_NAME);
00252 
00253                 /* get parameters */
00254                 while(*code && *code != ')') {
00255                         /* test if it's an input or output */
00256                         qual = FUNCTION_QUAL_IN;
00257                         if(gpu_str_prefix(code, "out "))
00258                                 qual = FUNCTION_QUAL_OUT;
00259                         if(gpu_str_prefix(code, "inout "))
00260                                 qual = FUNCTION_QUAL_INOUT;
00261                         if((qual != FUNCTION_QUAL_IN) || gpu_str_prefix(code, "in "))
00262                                 code = gpu_str_skip_token(code, NULL, 0);
00263 
00264                         /* test for type */
00265                         type= 0;
00266                         for(i=1; i<=16; i++) {
00267                                 if(GPU_DATATYPE_STR[i] && gpu_str_prefix(code, GPU_DATATYPE_STR[i])) {
00268                                         type= i;
00269                                         break;
00270                                 }
00271                         }
00272 
00273                         if(!type && gpu_str_prefix(code, "sampler2DShadow"))
00274                                 type= GPU_SHADOW2D;
00275                         if(!type && gpu_str_prefix(code, "sampler1D"))
00276                                 type= GPU_TEX1D;
00277                         if(!type && gpu_str_prefix(code, "sampler2D"))
00278                                 type= GPU_TEX2D;
00279 
00280                         if(type) {
00281                                 /* add paramater */
00282                                 code = gpu_str_skip_token(code, NULL, 0);
00283                                 code = gpu_str_skip_token(code, NULL, 0);
00284                                 function->paramqual[function->totparam]= qual;
00285                                 function->paramtype[function->totparam]= type;
00286                                 function->totparam++;
00287                         }
00288                         else {
00289                                 fprintf(stderr, "GPU invalid function parameter in %s.\n", function->name);
00290                                 break;
00291                         }
00292                 }
00293 
00294                 if(strlen(function->name) == 0 || function->totparam == 0) {
00295                         fprintf(stderr, "GPU functions parse error.\n");
00296                         MEM_freeN(function);
00297                         break;
00298                 }
00299 
00300                 BLI_ghash_insert(hash, function->name, function);
00301         }
00302 }
00303 
00304 #if 0
00305 static char *gpu_generate_function_prototyps(GHash *hash)
00306 {
00307         DynStr *ds = BLI_dynstr_new();
00308         GHashIterator *ghi;
00309         GPUFunction *function;
00310         char *name, *prototypes;
00311         int a;
00312         
00313         /* automatically generate function prototypes to add to the top of the
00314          * generated code, to avoid have to add the actual code & recompile all */
00315         ghi = BLI_ghashIterator_new(hash);
00316 
00317         for(; !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) {
00318                 name = BLI_ghashIterator_getValue(ghi);
00319                 function = BLI_ghashIterator_getValue(ghi);
00320 
00321                 BLI_dynstr_printf(ds, "void %s(", name);
00322                 for(a=0; a<function->totparam; a++) {
00323                         if(function->paramqual[a] == FUNCTION_QUAL_OUT)
00324                                 BLI_dynstr_append(ds, "out ");
00325                         else if(function->paramqual[a] == FUNCTION_QUAL_INOUT)
00326                                 BLI_dynstr_append(ds, "inout ");
00327 
00328                         if(function->paramtype[a] == GPU_TEX1D)
00329                                 BLI_dynstr_append(ds, "sampler1D");
00330                         else if(function->paramtype[a] == GPU_TEX2D)
00331                                 BLI_dynstr_append(ds, "sampler2D");
00332                         else if(function->paramtype[a] == GPU_SHADOW2D)
00333                                 BLI_dynstr_append(ds, "sampler2DShadow");
00334                         else
00335                                 BLI_dynstr_append(ds, GPU_DATATYPE_STR[function->paramtype[a]]);
00336                                 
00337                         //BLI_dynstr_printf(ds, " param%d", a);
00338                         
00339                         if(a != function->totparam-1)
00340                                 BLI_dynstr_append(ds, ", ");
00341                 }
00342                 BLI_dynstr_append(ds, ");\n");
00343         }
00344 
00345         BLI_dynstr_append(ds, "\n");
00346 
00347         prototypes = BLI_dynstr_get_cstring(ds);
00348         BLI_dynstr_free(ds);
00349 
00350         return prototypes;
00351 }
00352 #endif
00353 
00354 GPUFunction *GPU_lookup_function(const char *name)
00355 {
00356         if(!FUNCTION_HASH) {
00357                 FUNCTION_HASH = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "GPU_lookup_function gh");
00358                 gpu_parse_functions_string(FUNCTION_HASH, datatoc_gpu_shader_material_glsl);
00359                 /*FUNCTION_PROTOTYPES = gpu_generate_function_prototyps(FUNCTION_HASH);
00360                 FUNCTION_LIB = GPU_shader_create_lib(datatoc_gpu_shader_material_glsl);*/
00361         }
00362 
00363         return (GPUFunction*)BLI_ghash_lookup(FUNCTION_HASH, (void *)name);
00364 }
00365 
00366 void GPU_extensions_exit(void)
00367 {
00368         extern Material defmaterial;    // render module abuse...
00369 
00370         if(defmaterial.gpumaterial.first)
00371                 GPU_material_free(&defmaterial);
00372 
00373         if(FUNCTION_HASH) {
00374                 BLI_ghash_free(FUNCTION_HASH, NULL, (GHashValFreeFP)MEM_freeN);
00375                 FUNCTION_HASH = NULL;
00376         }
00377         /*if(FUNCTION_PROTOTYPES) {
00378                 MEM_freeN(FUNCTION_PROTOTYPES);
00379                 FUNCTION_PROTOTYPES = NULL;
00380         }*/
00381         /*if(FUNCTION_LIB) {
00382                 GPU_shader_free(FUNCTION_LIB);
00383                 FUNCTION_LIB = NULL;
00384         }*/
00385 }
00386 
00387 /* GLSL code generation */
00388 
00389 static void codegen_convert_datatype(DynStr *ds, int from, int to, const char *tmp, int id)
00390 {
00391         char name[1024];
00392 
00393         snprintf(name, sizeof(name), "%s%d", tmp, id);
00394 
00395         if (from == to) {
00396                 BLI_dynstr_append(ds, name);
00397         }
00398         else if (to == GPU_FLOAT) {
00399                 if (from == GPU_VEC4)
00400                         BLI_dynstr_printf(ds, "dot(%s.rgb, vec3(0.35, 0.45, 0.2))", name);
00401                 else if (from == GPU_VEC3)
00402                         BLI_dynstr_printf(ds, "dot(%s, vec3(0.33))", name);
00403                 else if (from == GPU_VEC2)
00404                         BLI_dynstr_printf(ds, "%s.r", name);
00405         }
00406         else if (to == GPU_VEC2) {
00407                 if (from == GPU_VEC4)
00408                         BLI_dynstr_printf(ds, "vec2(dot(%s.rgb, vec3(0.35, 0.45, 0.2)), %s.a)", name, name);
00409                 else if (from == GPU_VEC3)
00410                         BLI_dynstr_printf(ds, "vec2(dot(%s.rgb, vec3(0.33)), 1.0)", name);
00411                 else if (from == GPU_FLOAT)
00412                         BLI_dynstr_printf(ds, "vec2(%s, 1.0)", name);
00413         }
00414         else if (to == GPU_VEC3) {
00415                 if (from == GPU_VEC4)
00416                         BLI_dynstr_printf(ds, "%s.rgb", name);
00417                 else if (from == GPU_VEC2)
00418                         BLI_dynstr_printf(ds, "vec3(%s.r, %s.r, %s.r)", name, name, name);
00419                 else if (from == GPU_FLOAT)
00420                         BLI_dynstr_printf(ds, "vec3(%s, %s, %s)", name, name, name);
00421         }
00422         else {
00423                 if (from == GPU_VEC3)
00424                         BLI_dynstr_printf(ds, "vec4(%s, 1.0)", name);
00425                 else if (from == GPU_VEC2)
00426                         BLI_dynstr_printf(ds, "vec4(%s.r, %s.r, %s.r, %s.g)", name, name, name, name);
00427                 else if (from == GPU_FLOAT)
00428                         BLI_dynstr_printf(ds, "vec4(%s, %s, %s, 1.0)", name, name, name);
00429         }
00430 }
00431 
00432 static void codegen_print_datatype(DynStr *ds, int type, float *data)
00433 {
00434         int i;
00435 
00436         BLI_dynstr_printf(ds, "%s(", GPU_DATATYPE_STR[type]);
00437 
00438         for(i=0; i<type; i++) {
00439                 BLI_dynstr_printf(ds, "%f", data[i]);
00440                 if(i == type-1)
00441                         BLI_dynstr_append(ds, ")");
00442                 else
00443                         BLI_dynstr_append(ds, ", ");
00444         }
00445 }
00446 
00447 static int codegen_input_has_texture(GPUInput *input)
00448 {
00449         if (input->link)
00450                 return 0;
00451         else if(input->ima)
00452                 return 1;
00453         else
00454                 return input->tex != 0;
00455 }
00456 
00457 const char *GPU_builtin_name(GPUBuiltin builtin)
00458 {
00459         if(builtin == GPU_VIEW_MATRIX)
00460                 return "unfviewmat";
00461         else if(builtin == GPU_OBJECT_MATRIX)
00462                 return "unfobmat";
00463         else if(builtin == GPU_INVERSE_VIEW_MATRIX)
00464                 return "unfinvviewmat";
00465         else if(builtin == GPU_INVERSE_OBJECT_MATRIX)
00466                 return "unfinvobmat";
00467         else if(builtin == GPU_VIEW_POSITION)
00468                 return "varposition";
00469         else if(builtin == GPU_VIEW_NORMAL)
00470                 return "varnormal";
00471         else if(builtin == GPU_OBCOLOR)
00472                 return "unfobcolor";
00473         else
00474                 return "";
00475 }
00476 
00477 static void codegen_set_unique_ids(ListBase *nodes)
00478 {
00479         GHash *bindhash, *definehash;
00480         GPUNode *node;
00481         GPUInput *input;
00482         GPUOutput *output;
00483         int id = 1, texid = 0;
00484 
00485         bindhash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "codegen_set_unique_ids1 gh");
00486         definehash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "codegen_set_unique_ids2 gh");
00487 
00488         for (node=nodes->first; node; node=node->next) {
00489                 for (input=node->inputs.first; input; input=input->next) {
00490                         /* set id for unique names of uniform variables */
00491                         input->id = id++;
00492                         input->bindtex = 0;
00493                         input->definetex = 0;
00494 
00495                         /* set texid used for settings texture slot with multitexture */
00496                         if (codegen_input_has_texture(input) &&
00497                                 ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL))) {
00498                                 if (input->link) {
00499                                         /* input is texture from buffer, assign only one texid per
00500                                            buffer to avoid sampling the same texture twice */
00501                                         if (!BLI_ghash_haskey(bindhash, input->link)) {
00502                                                 input->texid = texid++;
00503                                                 input->bindtex = 1;
00504                                                 BLI_ghash_insert(bindhash, input->link, SET_INT_IN_POINTER(input->texid));
00505                                         }
00506                                         else
00507                                                 input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->link));
00508                                 }
00509                                 else if(input->ima) {
00510                                         /* input is texture from image, assign only one texid per
00511                                            buffer to avoid sampling the same texture twice */
00512                                         if (!BLI_ghash_haskey(bindhash, input->ima)) {
00513                                                 input->texid = texid++;
00514                                                 input->bindtex = 1;
00515                                                 BLI_ghash_insert(bindhash, input->ima, SET_INT_IN_POINTER(input->texid));
00516                                         }
00517                                         else
00518                                                 input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->ima));
00519                                 }
00520                                 else {
00521                                         if (!BLI_ghash_haskey(bindhash, input->tex)) {
00522                                                 /* input is user created texture, check tex pointer */
00523                                                 input->texid = texid++;
00524                                                 input->bindtex = 1;
00525                                                 BLI_ghash_insert(bindhash, input->tex, SET_INT_IN_POINTER(input->texid));
00526                                         }
00527                                         else
00528                                                 input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->tex));
00529                                 }
00530 
00531                                 /* make sure this pixel is defined exactly once */
00532                                 if (input->source == GPU_SOURCE_TEX_PIXEL) {
00533                                         if(input->ima) {
00534                                                 if (!BLI_ghash_haskey(definehash, input->ima)) {
00535                                                         input->definetex = 1;
00536                                                         BLI_ghash_insert(definehash, input->ima, SET_INT_IN_POINTER(input->texid));
00537                                                 }
00538                                         }
00539                                         else {
00540                                                 if (!BLI_ghash_haskey(definehash, input->link)) {
00541                                                         input->definetex = 1;
00542                                                         BLI_ghash_insert(definehash, input->link, SET_INT_IN_POINTER(input->texid));
00543                                                 }
00544                                         }
00545                                 }
00546                         }
00547                 }
00548 
00549                 for (output=node->outputs.first; output; output=output->next)
00550                         /* set id for unique names of tmp variables storing output */
00551                         output->id = id++;
00552         }
00553 
00554         BLI_ghash_free(bindhash, NULL, NULL);
00555         BLI_ghash_free(definehash, NULL, NULL);
00556 }
00557 
00558 static void codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
00559 {
00560         GPUNode *node;
00561         GPUInput *input;
00562         const char *name;
00563         int builtins = 0;
00564 
00565         /* print uniforms */
00566         for (node=nodes->first; node; node=node->next) {
00567                 for (input=node->inputs.first; input; input=input->next) {
00568                         if ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL)) {
00569                                 /* create exactly one sampler for each texture */
00570                                 if (codegen_input_has_texture(input) && input->bindtex)
00571                                         BLI_dynstr_printf(ds, "uniform %s samp%d;\n",
00572                                                 (input->textype == GPU_TEX1D)? "sampler1D":
00573                                                 (input->textype == GPU_TEX2D)? "sampler2D": "sampler2DShadow",
00574                                                 input->texid);
00575                         }
00576                         else if(input->source == GPU_SOURCE_BUILTIN) {
00577                                 /* only define each builting uniform/varying once */
00578                                 if(!(builtins & input->builtin)) {
00579                                         builtins |= input->builtin;
00580                                         name = GPU_builtin_name(input->builtin);
00581 
00582                                         if(gpu_str_prefix(name, "unf")) {
00583                                                 BLI_dynstr_printf(ds, "uniform %s %s;\n",
00584                                                         GPU_DATATYPE_STR[input->type], name);
00585                                         }
00586                                         else {
00587                                                 BLI_dynstr_printf(ds, "varying %s %s;\n",
00588                                                         GPU_DATATYPE_STR[input->type], name);
00589                                         }
00590                                 }
00591                         }
00592                         else if (input->source == GPU_SOURCE_VEC_UNIFORM) {
00593                                 if(input->dynamicvec) {
00594                                         /* only create uniforms for dynamic vectors */
00595                                         BLI_dynstr_printf(ds, "uniform %s unf%d;\n",
00596                                                 GPU_DATATYPE_STR[input->type], input->id);
00597                                 }
00598                                 else {
00599                                         /* for others use const so the compiler can do folding */
00600                                         BLI_dynstr_printf(ds, "const %s cons%d = ",
00601                                                 GPU_DATATYPE_STR[input->type], input->id);
00602                                         codegen_print_datatype(ds, input->type, input->vec);
00603                                         BLI_dynstr_append(ds, ";\n");
00604                                 }
00605                         }
00606                         else if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
00607                                 BLI_dynstr_printf(ds, "varying %s var%d;\n",
00608                                         GPU_DATATYPE_STR[input->type], input->attribid);
00609                         }
00610                 }
00611         }
00612 
00613         BLI_dynstr_append(ds, "\n");
00614 }
00615 
00616 static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
00617 {
00618         GPUNode *node;
00619         GPUInput *input;
00620         GPUOutput *output;
00621 
00622         for (node=nodes->first; node; node=node->next) {
00623                 /* load pixels from textures */
00624                 for (input=node->inputs.first; input; input=input->next) {
00625                         if (input->source == GPU_SOURCE_TEX_PIXEL) {
00626                                 if (codegen_input_has_texture(input) && input->definetex) {
00627                                         BLI_dynstr_printf(ds, "\tvec4 tex%d = texture2D(", input->texid);
00628                                         BLI_dynstr_printf(ds, "samp%d, gl_TexCoord[%d].st);\n",
00629                                                 input->texid, input->texid);
00630                                 }
00631                         }
00632                 }
00633 
00634                 /* declare temporary variables for node output storage */
00635                 for (output=node->outputs.first; output; output=output->next)
00636                         BLI_dynstr_printf(ds, "\t%s tmp%d;\n",
00637                                 GPU_DATATYPE_STR[output->type], output->id);
00638         }
00639 
00640         BLI_dynstr_append(ds, "\n");
00641 }
00642 
00643 static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *finaloutput)
00644 {
00645         GPUNode *node;
00646         GPUInput *input;
00647         GPUOutput *output;
00648 
00649         for (node=nodes->first; node; node=node->next) {
00650                 BLI_dynstr_printf(ds, "\t%s(", node->name);
00651                 
00652                 for (input=node->inputs.first; input; input=input->next) {
00653                         if (input->source == GPU_SOURCE_TEX) {
00654                                 BLI_dynstr_printf(ds, "samp%d", input->texid);
00655                                 if (input->link)
00656                                         BLI_dynstr_printf(ds, ", gl_TexCoord[%d].st", input->texid);
00657                         }
00658                         else if (input->source == GPU_SOURCE_TEX_PIXEL) {
00659                                 if (input->link && input->link->output)
00660                                         codegen_convert_datatype(ds, input->link->output->type, input->type,
00661                                                 "tmp", input->link->output->id);
00662                                 else
00663                                         codegen_convert_datatype(ds, input->link->output->type, input->type,
00664                                                 "tex", input->texid);
00665                         }
00666                         else if(input->source == GPU_SOURCE_BUILTIN)
00667                                 BLI_dynstr_printf(ds, "%s", GPU_builtin_name(input->builtin));
00668                         else if(input->source == GPU_SOURCE_VEC_UNIFORM) {
00669                                 if(input->dynamicvec)
00670                                         BLI_dynstr_printf(ds, "unf%d", input->id);
00671                                 else
00672                                         BLI_dynstr_printf(ds, "cons%d", input->id);
00673                         }
00674                         else if (input->source == GPU_SOURCE_ATTRIB)
00675                                 BLI_dynstr_printf(ds, "var%d", input->attribid);
00676 
00677                         BLI_dynstr_append(ds, ", ");
00678                 }
00679 
00680                 for (output=node->outputs.first; output; output=output->next) {
00681                         BLI_dynstr_printf(ds, "tmp%d", output->id);
00682                         if (output->next)
00683                                 BLI_dynstr_append(ds, ", ");
00684                 }
00685 
00686                 BLI_dynstr_append(ds, ");\n");
00687         }
00688 
00689         BLI_dynstr_append(ds, "\n\tgl_FragColor = ");
00690         codegen_convert_datatype(ds, finaloutput->type, GPU_VEC4, "tmp", finaloutput->id);
00691         BLI_dynstr_append(ds, ";\n");
00692 }
00693 
00694 static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, const char *UNUSED(name))
00695 {
00696         DynStr *ds = BLI_dynstr_new();
00697         char *code;
00698 
00699         /*BLI_dynstr_append(ds, FUNCTION_PROTOTYPES);*/
00700 
00701         codegen_set_unique_ids(nodes);
00702         codegen_print_uniforms_functions(ds, nodes);
00703 
00704         //if(G.f & G_DEBUG)
00705         //      BLI_dynstr_printf(ds, "/* %s */\n", name);
00706 
00707         BLI_dynstr_append(ds, "void main(void)\n");
00708         BLI_dynstr_append(ds, "{\n");
00709 
00710         codegen_declare_tmps(ds, nodes);
00711         codegen_call_functions(ds, nodes, output);
00712 
00713         BLI_dynstr_append(ds, "}\n");
00714 
00715         /* create shader */
00716         code = BLI_dynstr_get_cstring(ds);
00717         BLI_dynstr_free(ds);
00718 
00719         //if(G.f & G_DEBUG) printf("%s\n", code);
00720 
00721         return code;
00722 }
00723 
00724 static char *code_generate_vertex(ListBase *nodes)
00725 {
00726         DynStr *ds = BLI_dynstr_new();
00727         GPUNode *node;
00728         GPUInput *input;
00729         char *code;
00730         
00731         for (node=nodes->first; node; node=node->next) {
00732                 for (input=node->inputs.first; input; input=input->next) {
00733                         if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
00734                                 BLI_dynstr_printf(ds, "attribute %s att%d;\n",
00735                                         GPU_DATATYPE_STR[input->type], input->attribid);
00736                                 BLI_dynstr_printf(ds, "varying %s var%d;\n",
00737                                         GPU_DATATYPE_STR[input->type], input->attribid);
00738                         }
00739                 }
00740         }
00741 
00742         BLI_dynstr_append(ds, "\n");
00743         BLI_dynstr_append(ds, datatoc_gpu_shader_vertex_glsl);
00744 
00745         for (node=nodes->first; node; node=node->next)
00746                 for (input=node->inputs.first; input; input=input->next)
00747                         if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
00748                                 if(input->attribtype == CD_TANGENT) /* silly exception */
00749                                 {
00750                                         BLI_dynstr_printf(ds, "\tvar%d.xyz = normalize((gl_ModelViewMatrix * vec4(att%d.xyz, 0)).xyz);\n", input->attribid, input->attribid);
00751                                         BLI_dynstr_printf(ds, "\tvar%d.w = att%d.w;\n", input->attribid, input->attribid);
00752                                 }
00753                                 else
00754                                         BLI_dynstr_printf(ds, "\tvar%d = att%d;\n", input->attribid, input->attribid);
00755                         }
00756 
00757         BLI_dynstr_append(ds, "}\n\n");
00758 
00759         code = BLI_dynstr_get_cstring(ds);
00760 
00761         BLI_dynstr_free(ds);
00762 
00763         //if(G.f & G_DEBUG) printf("%s\n", code);
00764 
00765         return code;
00766 }
00767 
00768 /* GPU pass binding/unbinding */
00769 
00770 GPUShader *GPU_pass_shader(GPUPass *pass)
00771 {
00772         return pass->shader;
00773 }
00774 
00775 static void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
00776 {
00777         GPUShader *shader = pass->shader;
00778         GPUNode *node;
00779         GPUInput *next, *input;
00780         ListBase *inputs = &pass->inputs;
00781         int extract, z;
00782 
00783         memset(inputs, 0, sizeof(*inputs));
00784 
00785         if(!shader)
00786                 return;
00787 
00788         GPU_shader_bind(shader);
00789 
00790         for (node=nodes->first; node; node=node->next) {
00791                 z = 0;
00792                 for (input=node->inputs.first; input; input=next, z++) {
00793                         next = input->next;
00794 
00795                         /* attributes don't need to be bound, they already have
00796                          * an id that the drawing functions will use */
00797                         if(input->source == GPU_SOURCE_ATTRIB ||
00798                            input->source == GPU_SOURCE_BUILTIN)
00799                                 continue;
00800 
00801                         if (input->ima || input->tex)
00802                                 snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid);
00803                         else
00804                                 snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id);
00805 
00806                         /* pass non-dynamic uniforms to opengl */
00807                         extract = 0;
00808 
00809                         if(input->ima || input->tex) {
00810                                 if (input->bindtex)
00811                                         extract = 1;
00812                         }
00813                         else if(input->dynamicvec)
00814                                 extract = 1;
00815 
00816                         if(extract)
00817                                 input->shaderloc = GPU_shader_get_uniform(shader, input->shadername);
00818 
00819                         /* extract nodes */
00820                         if(extract) {
00821                                 BLI_remlink(&node->inputs, input);
00822                                 BLI_addtail(inputs, input);
00823                         }
00824                 }
00825         }
00826 
00827         GPU_shader_unbind(shader);
00828 }
00829 
00830 void GPU_pass_bind(GPUPass *pass, double time, int mipmap)
00831 {
00832         GPUInput *input;
00833         GPUShader *shader = pass->shader;
00834         ListBase *inputs = &pass->inputs;
00835 
00836         if (!shader)
00837                 return;
00838 
00839         GPU_shader_bind(shader);
00840 
00841         /* now bind the textures */
00842         for (input=inputs->first; input; input=input->next) {
00843                 if (input->ima)
00844                         input->tex = GPU_texture_from_blender(input->ima, input->iuser, time, mipmap);
00845 
00846                 if(input->tex && input->bindtex) {
00847                         GPU_texture_bind(input->tex, input->texid);
00848                         GPU_shader_uniform_texture(shader, input->shaderloc, input->tex);
00849                 }
00850         }
00851 }
00852 
00853 void GPU_pass_update_uniforms(GPUPass *pass)
00854 {
00855         GPUInput *input;
00856         GPUShader *shader = pass->shader;
00857         ListBase *inputs = &pass->inputs;
00858 
00859         if (!shader)
00860                 return;
00861 
00862         /* pass dynamic inputs to opengl, others were removed */
00863         for (input=inputs->first; input; input=input->next)
00864                 if(!(input->ima || input->tex))
00865                         GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1,
00866                                 input->dynamicvec);
00867 }
00868 
00869 void GPU_pass_unbind(GPUPass *pass)
00870 {
00871         GPUInput *input;
00872         GPUShader *shader = pass->shader;
00873         ListBase *inputs = &pass->inputs;
00874 
00875         if (!shader)
00876                 return;
00877 
00878         for (input=inputs->first; input; input=input->next) {
00879                 if(input->tex && input->bindtex)
00880                         GPU_texture_unbind(input->tex);
00881 
00882                 if (input->ima)
00883                         input->tex = 0;
00884         }
00885         
00886         GPU_shader_unbind(shader);
00887 }
00888 
00889 /* Node Link Functions */
00890 
00891 static GPUNodeLink *GPU_node_link_create(int type)
00892 {
00893         GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink");
00894         link->type = type;
00895         link->users++;
00896 
00897         return link;
00898 }
00899 
00900 static void GPU_node_link_free(GPUNodeLink *link)
00901 {
00902         link->users--;
00903 
00904         if (link->users < 0)
00905                 fprintf(stderr, "GPU_node_link_free: negative refcount\n");
00906         
00907         if (link->users == 0) {
00908                 if (link->output)
00909                         link->output->link = NULL;
00910                 MEM_freeN(link);
00911         }
00912 }
00913 
00914 /* Node Functions */
00915 
00916 static GPUNode *GPU_node_begin(const char *name)
00917 {
00918         GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode");
00919 
00920         node->name= name;
00921 
00922         return node;
00923 }
00924 
00925 static void GPU_node_end(GPUNode *UNUSED(node))
00926 {
00927         /* empty */
00928 }
00929 
00930 static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
00931 {
00932         GPUInput *input;
00933         GPUNode *outnode;
00934         const char *name;
00935 
00936         if(link->output) {
00937                 outnode = link->output->node;
00938                 name = outnode->name;
00939 
00940                 if(strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) {
00941                         input = MEM_dupallocN(outnode->inputs.first);
00942                         input->type = type;
00943                         if(input->link)
00944                                 input->link->users++;
00945                         BLI_addtail(&node->inputs, input);
00946                         return;
00947                 }
00948         }
00949         
00950         input = MEM_callocN(sizeof(GPUInput), "GPUInput");
00951         input->node = node;
00952 
00953         if(link->builtin) {
00954                 /* builtin uniform */
00955                 input->type = type;
00956                 input->source = GPU_SOURCE_BUILTIN;
00957                 input->builtin = link->builtin;
00958 
00959                 MEM_freeN(link);
00960         }
00961         else if(link->output) {
00962                 /* link to a node output */
00963                 input->type = type;
00964                 input->source = GPU_SOURCE_TEX_PIXEL;
00965                 input->link = link;
00966                 link->users++;
00967         }
00968         else if(link->dynamictex) {
00969                 /* dynamic texture, GPUTexture is updated/deleted externally */
00970                 input->type = type;
00971                 input->source = GPU_SOURCE_TEX;
00972 
00973                 input->tex = link->dynamictex;
00974                 input->textarget = GL_TEXTURE_2D;
00975                 input->textype = type;
00976                 input->dynamictex = 1;
00977                 MEM_freeN(link);
00978         }
00979         else if(link->texture) {
00980                 /* small texture created on the fly, like for colorbands */
00981                 input->type = GPU_VEC4;
00982                 input->source = GPU_SOURCE_TEX;
00983                 input->textype = type;
00984 
00985                 if (type == GPU_TEX1D) {
00986                         input->tex = GPU_texture_create_1D(link->texturesize, link->ptr1, NULL);
00987                         input->textarget = GL_TEXTURE_1D;
00988                 }
00989                 else {
00990                         input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
00991                         input->textarget = GL_TEXTURE_2D;
00992                 }
00993 
00994                 MEM_freeN(link->ptr1);
00995                 MEM_freeN(link);
00996         }
00997         else if(link->image) {
00998                 /* blender image */
00999                 input->type = GPU_VEC4;
01000                 input->source = GPU_SOURCE_TEX;
01001 
01002                 input->ima = link->ptr1;
01003                 input->iuser = link->ptr2;
01004                 input->textarget = GL_TEXTURE_2D;
01005                 input->textype = GPU_TEX2D;
01006                 MEM_freeN(link);
01007         }
01008         else if(link->attribtype) {
01009                 /* vertex attribute */
01010                 input->type = type;
01011                 input->source = GPU_SOURCE_ATTRIB;
01012 
01013                 input->attribtype = link->attribtype;
01014                 BLI_strncpy(input->attribname, link->attribname, sizeof(input->attribname));
01015                 MEM_freeN(link);
01016         }
01017         else {
01018                 /* uniform vector */
01019                 input->type = type;
01020                 input->source = GPU_SOURCE_VEC_UNIFORM;
01021 
01022                 memcpy(input->vec, link->ptr1, type*sizeof(float));
01023                 if(link->dynamic)
01024                         input->dynamicvec= link->ptr1;
01025                 MEM_freeN(link);
01026         }
01027 
01028         BLI_addtail(&node->inputs, input);
01029 }
01030 
01031 static void gpu_node_input_socket(GPUNode *node, GPUNodeStack *sock)
01032 {
01033         GPUNodeLink *link;
01034 
01035         if(sock->link) {
01036                 gpu_node_input_link(node, sock->link, sock->type);
01037         }
01038         else {
01039                  link = GPU_node_link_create(0);
01040                 link->ptr1 = sock->vec;
01041                 gpu_node_input_link(node, link, sock->type);
01042         }
01043 }
01044 
01045 static void GPU_node_output(GPUNode *node, int type, const char *UNUSED(name), GPUNodeLink **link)
01046 {
01047         GPUOutput *output = MEM_callocN(sizeof(GPUOutput), "GPUOutput");
01048 
01049         output->type = type;
01050         output->node = node;
01051 
01052         if (link) {
01053                 *link = output->link = GPU_node_link_create(type);
01054                 output->link->output = output;
01055 
01056                 /* note: the caller owns the reference to the linkfer, GPUOutput
01057                    merely points to it, and if the node is destroyed it will
01058                    set that pointer to NULL */
01059         }
01060 
01061         BLI_addtail(&node->outputs, output);
01062 }
01063 
01064 static void GPU_inputs_free(ListBase *inputs)
01065 {
01066         GPUInput *input;
01067 
01068         for(input=inputs->first; input; input=input->next) {
01069                 if(input->link)
01070                         GPU_node_link_free(input->link);
01071                 else if(input->tex && !input->dynamictex)
01072                         GPU_texture_free(input->tex);
01073         }
01074 
01075         BLI_freelistN(inputs);
01076 }
01077 
01078 static void GPU_node_free(GPUNode *node)
01079 {
01080         GPUOutput *output;
01081 
01082         GPU_inputs_free(&node->inputs);
01083 
01084         for (output=node->outputs.first; output; output=output->next)
01085                 if (output->link) {
01086                         output->link->output = NULL;
01087                         GPU_node_link_free(output->link);
01088                 }
01089 
01090         BLI_freelistN(&node->outputs);
01091         MEM_freeN(node);
01092 }
01093 
01094 static void GPU_nodes_free(ListBase *nodes)
01095 {
01096         GPUNode *node;
01097 
01098         while (nodes->first) {
01099                 node = nodes->first;
01100                 BLI_remlink(nodes, node);
01101                 GPU_node_free(node);
01102         }
01103 }
01104 
01105 /* vertex attributes */
01106 
01107 static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs)
01108 {
01109         GPUNode *node;
01110         GPUInput *input;
01111         int a;
01112 
01113         /* convert attributes requested by node inputs to an array of layers,
01114          * checking for duplicates and assigning id's starting from zero. */
01115 
01116         memset(attribs, 0, sizeof(*attribs));
01117 
01118         for(node=nodes->first; node; node=node->next) {
01119                 for(input=node->inputs.first; input; input=input->next) {
01120                         if(input->source == GPU_SOURCE_ATTRIB) {
01121                                 for(a=0; a<attribs->totlayer; a++) {
01122                                         if(attribs->layer[a].type == input->attribtype &&
01123                                                 strcmp(attribs->layer[a].name, input->attribname) == 0)
01124                                                 break;
01125                                 }
01126 
01127                                 if(a == attribs->totlayer && a < GPU_MAX_ATTRIB) {
01128                                         input->attribid = attribs->totlayer++;
01129                                         input->attribfirst = 1;
01130 
01131                                         attribs->layer[a].type = input->attribtype;
01132                                         attribs->layer[a].glindex = input->attribid;
01133                                         BLI_strncpy(attribs->layer[a].name, input->attribname,
01134                                                 sizeof(attribs->layer[a].name));
01135                                 }
01136                                 else
01137                                         input->attribid = attribs->layer[a].glindex;
01138                         }
01139                 }
01140         }
01141 }
01142 
01143 static void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin)
01144 {
01145         GPUNode *node;
01146         GPUInput *input;
01147         
01148         *builtin= 0;
01149 
01150         for(node=nodes->first; node; node=node->next)
01151                 for(input=node->inputs.first; input; input=input->next)
01152                         if(input->source == GPU_SOURCE_BUILTIN)
01153                                 *builtin |= input->builtin;
01154 }
01155 
01156 /* varargs linking  */
01157 
01158 GPUNodeLink *GPU_attribute(int type, const char *name)
01159 {
01160         GPUNodeLink *link = GPU_node_link_create(0);
01161 
01162         link->attribtype= type;
01163         link->attribname= name;
01164 
01165         return link;
01166 }
01167 
01168 GPUNodeLink *GPU_uniform(float *num)
01169 {
01170         GPUNodeLink *link = GPU_node_link_create(0);
01171 
01172         link->ptr1= num;
01173         link->ptr2= NULL;
01174 
01175         return link;
01176 }
01177 
01178 GPUNodeLink *GPU_dynamic_uniform(float *num)
01179 {
01180         GPUNodeLink *link = GPU_node_link_create(0);
01181 
01182         link->ptr1= num;
01183         link->ptr2= NULL;
01184         link->dynamic= 1;
01185 
01186         return link;
01187 }
01188 
01189 GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser)
01190 {
01191         GPUNodeLink *link = GPU_node_link_create(0);
01192 
01193         link->image= 1;
01194         link->ptr1= ima;
01195         link->ptr2= iuser;
01196 
01197         return link;
01198 }
01199 
01200 GPUNodeLink *GPU_texture(int size, float *pixels)
01201 {
01202         GPUNodeLink *link = GPU_node_link_create(0);
01203 
01204         link->texture = 1;
01205         link->texturesize = size;
01206         link->ptr1= pixels;
01207 
01208         return link;
01209 }
01210 
01211 GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex)
01212 {
01213         GPUNodeLink *link = GPU_node_link_create(0);
01214 
01215         link->dynamic = 1;
01216         link->dynamictex = tex;
01217 
01218         return link;
01219 }
01220 
01221 GPUNodeLink *GPU_socket(GPUNodeStack *sock)
01222 {
01223         GPUNodeLink *link = GPU_node_link_create(0);
01224 
01225         link->socket= sock;
01226 
01227         return link;
01228 }
01229 
01230 GPUNodeLink *GPU_builtin(GPUBuiltin builtin)
01231 {
01232         GPUNodeLink *link = GPU_node_link_create(0);
01233 
01234         link->builtin= builtin;
01235 
01236         return link;
01237 }
01238 
01239 int GPU_link(GPUMaterial *mat, const char *name, ...)
01240 {
01241         GPUNode *node;
01242         GPUFunction *function;
01243         GPUNodeLink *link, **linkptr;
01244         va_list params;
01245         int i;
01246 
01247         function = GPU_lookup_function(name);
01248         if(!function) {
01249                 fprintf(stderr, "GPU failed to find function %s\n", name);
01250                 return 0;
01251         }
01252 
01253         node = GPU_node_begin(name);
01254 
01255         va_start(params, name);
01256         for(i=0; i<function->totparam; i++) {
01257                 if(function->paramqual[i] != FUNCTION_QUAL_IN) {
01258                         linkptr= va_arg(params, GPUNodeLink**);
01259                         GPU_node_output(node, function->paramtype[i], "", linkptr);
01260                 }
01261                 else {
01262                         link= va_arg(params, GPUNodeLink*);
01263                         gpu_node_input_link(node, link, function->paramtype[i]);
01264                 }
01265         }
01266         va_end(params);
01267 
01268         GPU_node_end(node);
01269 
01270         gpu_material_add_node(mat, node);
01271 
01272         return 1;
01273 }
01274 
01275 int GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...)
01276 {
01277         GPUNode *node;
01278         GPUFunction *function;
01279         GPUNodeLink *link, **linkptr;
01280         va_list params;
01281         int i, totin, totout;
01282 
01283         function = GPU_lookup_function(name);
01284         if(!function) {
01285                 fprintf(stderr, "GPU failed to find function %s\n", name);
01286                 return 0;
01287         }
01288 
01289         node = GPU_node_begin(name);
01290         totin = 0;
01291         totout = 0;
01292 
01293         if(in) {
01294                 for(i = 0; in[i].type != GPU_NONE; i++) {
01295                         gpu_node_input_socket(node, &in[i]);
01296                         totin++;
01297                 }
01298         }
01299         
01300         if(out) {
01301                 for(i = 0; out[i].type != GPU_NONE; i++) {
01302                         GPU_node_output(node, out[i].type, out[i].name, &out[i].link);
01303                         totout++;
01304                 }
01305         }
01306 
01307         va_start(params, out);
01308         for(i=0; i<function->totparam; i++) {
01309                 if(function->paramqual[i] != FUNCTION_QUAL_IN) {
01310                         if(totout == 0) {
01311                                 linkptr= va_arg(params, GPUNodeLink**);
01312                                 GPU_node_output(node, function->paramtype[i], "", linkptr);
01313                         }
01314                         else
01315                                 totout--;
01316                 }
01317                 else {
01318                         if(totin == 0) {
01319                                 link= va_arg(params, GPUNodeLink*);
01320                                 if(link->socket)
01321                                         gpu_node_input_socket(node, link->socket);
01322                                 else
01323                                         gpu_node_input_link(node, link, function->paramtype[i]);
01324                         }
01325                         else
01326                                 totin--;
01327                 }
01328         }
01329         va_end(params);
01330 
01331         GPU_node_end(node);
01332 
01333         gpu_material_add_node(mat, node);
01334         
01335         return 1;
01336 }
01337 
01338 int GPU_link_changed(GPUNodeLink *link)
01339 {
01340         GPUNode *node;
01341         GPUInput *input;
01342         const char *name;
01343 
01344         if(link->output) {
01345                 node = link->output->node;
01346                 name = node->name;
01347 
01348                 if(strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) {
01349                         input = node->inputs.first;
01350                         return (input->link != NULL);
01351                 }
01352 
01353                 return 1;
01354         }
01355         else
01356                 return 0;
01357 }
01358 
01359 /* Pass create/free */
01360 
01361 static void gpu_nodes_tag(GPUNodeLink *link)
01362 {
01363         GPUNode *node;
01364         GPUInput *input;
01365 
01366         if(!link->output)
01367                 return;
01368 
01369         node = link->output->node;
01370         if(node->tag)
01371                 return;
01372         
01373         node->tag= 1;
01374         for(input=node->inputs.first; input; input=input->next)
01375                 if(input->link)
01376                         gpu_nodes_tag(input->link);
01377 }
01378 
01379 static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
01380 {
01381         GPUNode *node, *next;
01382 
01383         for(node=nodes->first; node; node=node->next)
01384                 node->tag= 0;
01385 
01386         gpu_nodes_tag(outlink);
01387 
01388         for(node=nodes->first; node; node=next) {
01389                 next = node->next;
01390 
01391                 if(!node->tag) {
01392                         BLI_remlink(nodes, node);
01393                         GPU_node_free(node);
01394                 }
01395         }
01396 }
01397 
01398 GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttribs *attribs, int *builtins, const char *name)
01399 {
01400         GPUShader *shader;
01401         GPUPass *pass;
01402         char *vertexcode, *fragmentcode;
01403 
01404         /*if(!FUNCTION_LIB) {
01405                 GPU_nodes_free(nodes);
01406                 return NULL;
01407         }*/
01408 
01409         /* prune unused nodes */
01410         gpu_nodes_prune(nodes, outlink);
01411 
01412         gpu_nodes_get_vertex_attributes(nodes, attribs);
01413         gpu_nodes_get_builtin_flag(nodes, builtins);
01414 
01415         /* generate code and compile with opengl */
01416         fragmentcode = code_generate_fragment(nodes, outlink->output, name);
01417         vertexcode = code_generate_vertex(nodes);
01418         shader = GPU_shader_create(vertexcode, fragmentcode, datatoc_gpu_shader_material_glsl); /*FUNCTION_LIB);*/
01419         MEM_freeN(fragmentcode);
01420         MEM_freeN(vertexcode);
01421 
01422         /* failed? */
01423         if (!shader) {
01424                 memset(attribs, 0, sizeof(*attribs));
01425                 memset(builtins, 0, sizeof(*builtins));
01426                 GPU_nodes_free(nodes);
01427                 return NULL;
01428         }
01429         
01430         /* create pass */
01431         pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
01432 
01433         pass->output = outlink->output;
01434         pass->shader = shader;
01435 
01436         /* extract dynamic inputs and throw away nodes */
01437         GPU_nodes_extract_dynamic_inputs(pass, nodes);
01438         GPU_nodes_free(nodes);
01439 
01440         return pass;
01441 }
01442 
01443 void GPU_pass_free(GPUPass *pass)
01444 {
01445         GPU_shader_free(pass->shader);
01446         GPU_inputs_free(&pass->inputs);
01447         MEM_freeN(pass);
01448 }
01449