Code cleanup: use lowercase "gpu" prefix for static functions
[blender.git] / source / blender / gpu / intern / gpu_codegen.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2005 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Brecht Van Lommel.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/gpu/intern/gpu_codegen.c
29  *  \ingroup gpu
30  *
31  * Convert material node-trees to GLSL.
32  */
33
34 #include "GPU_glew.h"
35
36 #include "MEM_guardedalloc.h"
37
38 #include "DNA_customdata_types.h"
39 #include "DNA_image_types.h"
40 #include "DNA_material_types.h"
41
42 #include "BLI_blenlib.h"
43 #include "BLI_utildefines.h"
44 #include "BLI_dynstr.h"
45 #include "BLI_ghash.h"
46
47 #include "GPU_material.h"
48 #include "GPU_extensions.h"
49
50 #include "BLI_sys_types.h" // for intptr_t support
51
52 #include "gpu_codegen.h"
53
54 #include <string.h>
55 #include <stdarg.h>
56
57 extern char datatoc_gpu_shader_material_glsl[];
58 extern char datatoc_gpu_shader_vertex_glsl[];
59 extern char datatoc_gpu_shader_vertex_world_glsl[];
60
61
62 static char *glsl_material_library = NULL;
63
64
65 /* structs and defines */
66
67 /* Indices match the GPUType enum */
68 static const char *GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4",
69         NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4"};
70
71 #define LINK_IMAGE_BLENDER      1
72 #define LINK_IMAGE_PREVIEW      2
73
74 /* GLSL code parsing for finding function definitions.
75  * These are stored in a hash for lookup when creating a material. */
76
77 static GHash *FUNCTION_HASH= NULL;
78 /* static char *FUNCTION_PROTOTYPES= NULL;
79  * static GPUShader *FUNCTION_LIB= NULL;*/
80
81 static int gpu_str_prefix(const char *str, const char *prefix)
82 {
83         while (*str && *prefix) {
84                 if (*str != *prefix)
85                         return 0;
86
87                 str++;
88                 prefix++;
89         }
90         
91         return (*prefix == '\0');
92 }
93
94 static char *gpu_str_skip_token(char *str, char *token, int max)
95 {
96         int len = 0;
97
98         /* skip a variable/function name */
99         while (*str) {
100                 if (ELEM(*str, ' ', '(', ')', ',', '\t', '\n', '\r'))
101                         break;
102                 else {
103                         if (token && len < max-1) {
104                                 *token= *str;
105                                 token++;
106                                 len++;
107                         }
108                         str++;
109                 }
110         }
111
112         if (token)
113                 *token= '\0';
114
115         /* skip the next special characters:
116          * note the missing ')' */
117         while (*str) {
118                 if (ELEM(*str, ' ', '(', ',', '\t', '\n', '\r'))
119                         str++;
120                 else
121                         break;
122         }
123
124         return str;
125 }
126
127 static void gpu_parse_functions_string(GHash *hash, char *code)
128 {
129         GPUFunction *function;
130         GPUType type;
131         int i, qual;
132
133         while ((code = strstr(code, "void "))) {
134                 function = MEM_callocN(sizeof(GPUFunction), "GPUFunction");
135
136                 code = gpu_str_skip_token(code, NULL, 0);
137                 code = gpu_str_skip_token(code, function->name, MAX_FUNCTION_NAME);
138
139                 /* get parameters */
140                 while (*code && *code != ')') {
141                         /* test if it's an input or output */
142                         qual = FUNCTION_QUAL_IN;
143                         if (gpu_str_prefix(code, "out "))
144                                 qual = FUNCTION_QUAL_OUT;
145                         if (gpu_str_prefix(code, "inout "))
146                                 qual = FUNCTION_QUAL_INOUT;
147                         if ((qual != FUNCTION_QUAL_IN) || gpu_str_prefix(code, "in "))
148                                 code = gpu_str_skip_token(code, NULL, 0);
149
150                         /* test for type */
151                         type= GPU_NONE;
152                         for (i=1; i<=16; i++) {
153                                 if (GPU_DATATYPE_STR[i] && gpu_str_prefix(code, GPU_DATATYPE_STR[i])) {
154                                         type= i;
155                                         break;
156                                 }
157                         }
158
159                         if (!type && gpu_str_prefix(code, "sampler2DShadow"))
160                                 type= GPU_SHADOW2D;
161                         if (!type && gpu_str_prefix(code, "sampler2D"))
162                                 type= GPU_TEX2D;
163
164                         if (type) {
165                                 /* add parameter */
166                                 code = gpu_str_skip_token(code, NULL, 0);
167                                 code = gpu_str_skip_token(code, NULL, 0);
168                                 function->paramqual[function->totparam]= qual;
169                                 function->paramtype[function->totparam]= type;
170                                 function->totparam++;
171                         }
172                         else {
173                                 fprintf(stderr, "GPU invalid function parameter in %s.\n", function->name);
174                                 break;
175                         }
176                 }
177
178                 if (function->name[0] == '\0' || function->totparam == 0) {
179                         fprintf(stderr, "GPU functions parse error.\n");
180                         MEM_freeN(function);
181                         break;
182                 }
183
184                 BLI_ghash_insert(hash, function->name, function);
185         }
186 }
187
188 #if 0
189 static char *gpu_generate_function_prototyps(GHash *hash)
190 {
191         DynStr *ds = BLI_dynstr_new();
192         GHashIterator *ghi;
193         GPUFunction *function;
194         char *name, *prototypes;
195         int a;
196         
197         /* automatically generate function prototypes to add to the top of the
198          * generated code, to avoid have to add the actual code & recompile all */
199         ghi = BLI_ghashIterator_new(hash);
200
201         for (; !BLI_ghashIterator_done(ghi); BLI_ghashIterator_step(ghi)) {
202                 name = BLI_ghashIterator_getValue(ghi);
203                 function = BLI_ghashIterator_getValue(ghi);
204
205                 BLI_dynstr_appendf(ds, "void %s(", name);
206                 for (a=0; a<function->totparam; a++) {
207                         if (function->paramqual[a] == FUNCTION_QUAL_OUT)
208                                 BLI_dynstr_append(ds, "out ");
209                         else if (function->paramqual[a] == FUNCTION_QUAL_INOUT)
210                                 BLI_dynstr_append(ds, "inout ");
211
212                         if (function->paramtype[a] == GPU_TEX2D)
213                                 BLI_dynstr_append(ds, "sampler2D");
214                         else if (function->paramtype[a] == GPU_SHADOW2D)
215                                 BLI_dynstr_append(ds, "sampler2DShadow");
216                         else
217                                 BLI_dynstr_append(ds, GPU_DATATYPE_STR[function->paramtype[a]]);
218                                 
219                         //BLI_dynstr_appendf(ds, " param%d", a);
220                         
221                         if (a != function->totparam-1)
222                                 BLI_dynstr_append(ds, ", ");
223                 }
224                 BLI_dynstr_append(ds, ");\n");
225         }
226
227         BLI_dynstr_append(ds, "\n");
228
229         prototypes = BLI_dynstr_get_cstring(ds);
230         BLI_dynstr_free(ds);
231
232         return prototypes;
233 }
234 #endif
235
236 GPUFunction *GPU_lookup_function(const char *name)
237 {
238         if (!FUNCTION_HASH) {
239                 FUNCTION_HASH = BLI_ghash_str_new("GPU_lookup_function gh");
240                 gpu_parse_functions_string(FUNCTION_HASH, glsl_material_library);
241         }
242
243         return BLI_ghash_lookup(FUNCTION_HASH, (const void *)name);
244 }
245
246 void gpu_codegen_init(void)
247 {
248         GPU_code_generate_glsl_lib();
249 }
250
251 void gpu_codegen_exit(void)
252 {
253         extern Material defmaterial;    // render module abuse...
254
255         if (defmaterial.gpumaterial.first)
256                 GPU_material_free(&defmaterial.gpumaterial);
257
258         if (FUNCTION_HASH) {
259                 BLI_ghash_free(FUNCTION_HASH, NULL, MEM_freeN);
260                 FUNCTION_HASH = NULL;
261         }
262
263         GPU_shader_free_builtin_shaders();
264
265         if (glsl_material_library) {
266                 MEM_freeN(glsl_material_library);
267                 glsl_material_library = NULL;
268         }
269
270         /*if (FUNCTION_PROTOTYPES) {
271                 MEM_freeN(FUNCTION_PROTOTYPES);
272                 FUNCTION_PROTOTYPES = NULL;
273         }*/
274         /*if (FUNCTION_LIB) {
275                 GPU_shader_free(FUNCTION_LIB);
276                 FUNCTION_LIB = NULL;
277         }*/
278 }
279
280 /* GLSL code generation */
281
282 static void codegen_convert_datatype(DynStr *ds, int from, int to, const char *tmp, int id)
283 {
284         char name[1024];
285
286         BLI_snprintf(name, sizeof(name), "%s%d", tmp, id);
287
288         if (from == to) {
289                 BLI_dynstr_append(ds, name);
290         }
291         else if (to == GPU_FLOAT) {
292                 if (from == GPU_VEC4)
293                         BLI_dynstr_appendf(ds, "dot(%s.rgb, vec3(0.35, 0.45, 0.2))", name);
294                 else if (from == GPU_VEC3)
295                         BLI_dynstr_appendf(ds, "dot(%s, vec3(0.33))", name);
296                 else if (from == GPU_VEC2)
297                         BLI_dynstr_appendf(ds, "%s.r", name);
298         }
299         else if (to == GPU_VEC2) {
300                 if (from == GPU_VEC4)
301                         BLI_dynstr_appendf(ds, "vec2(dot(%s.rgb, vec3(0.35, 0.45, 0.2)), %s.a)", name, name);
302                 else if (from == GPU_VEC3)
303                         BLI_dynstr_appendf(ds, "vec2(dot(%s.rgb, vec3(0.33)), 1.0)", name);
304                 else if (from == GPU_FLOAT)
305                         BLI_dynstr_appendf(ds, "vec2(%s, 1.0)", name);
306         }
307         else if (to == GPU_VEC3) {
308                 if (from == GPU_VEC4)
309                         BLI_dynstr_appendf(ds, "%s.rgb", name);
310                 else if (from == GPU_VEC2)
311                         BLI_dynstr_appendf(ds, "vec3(%s.r, %s.r, %s.r)", name, name, name);
312                 else if (from == GPU_FLOAT)
313                         BLI_dynstr_appendf(ds, "vec3(%s, %s, %s)", name, name, name);
314         }
315         else {
316                 if (from == GPU_VEC3)
317                         BLI_dynstr_appendf(ds, "vec4(%s, 1.0)", name);
318                 else if (from == GPU_VEC2)
319                         BLI_dynstr_appendf(ds, "vec4(%s.r, %s.r, %s.r, %s.g)", name, name, name, name);
320                 else if (from == GPU_FLOAT)
321                         BLI_dynstr_appendf(ds, "vec4(%s, %s, %s, 1.0)", name, name, name);
322         }
323 }
324
325 static void codegen_print_datatype(DynStr *ds, const GPUType type, float *data)
326 {
327         int i;
328
329         BLI_dynstr_appendf(ds, "%s(", GPU_DATATYPE_STR[type]);
330
331         for (i=0; i<type; i++) {
332                 BLI_dynstr_appendf(ds, "%f", data[i]);
333                 if (i == type-1)
334                         BLI_dynstr_append(ds, ")");
335                 else
336                         BLI_dynstr_append(ds, ", ");
337         }
338 }
339
340 static int codegen_input_has_texture(GPUInput *input)
341 {
342         if (input->link)
343                 return 0;
344         else if (input->ima || input->prv)
345                 return 1;
346         else
347                 return input->tex != NULL;
348 }
349
350 const char *GPU_builtin_name(GPUBuiltin builtin)
351 {
352         if (builtin == GPU_VIEW_MATRIX)
353                 return "unfviewmat";
354         else if (builtin == GPU_OBJECT_MATRIX)
355                 return "unfobmat";
356         else if (builtin == GPU_INVERSE_VIEW_MATRIX)
357                 return "unfinvviewmat";
358         else if (builtin == GPU_INVERSE_OBJECT_MATRIX)
359                 return "unfinvobmat";
360         else if (builtin == GPU_VIEW_POSITION)
361                 return "varposition";
362         else if (builtin == GPU_VIEW_NORMAL)
363                 return "varnormal";
364         else if (builtin == GPU_OBCOLOR)
365                 return "unfobcolor";
366         else if (builtin == GPU_AUTO_BUMPSCALE)
367                 return "unfobautobumpscale";
368         else
369                 return "";
370 }
371
372 static void codegen_set_unique_ids(ListBase *nodes)
373 {
374         GHash *bindhash, *definehash;
375         GPUNode *node;
376         GPUInput *input;
377         GPUOutput *output;
378         int id = 1, texid = 0;
379
380         bindhash= BLI_ghash_ptr_new("codegen_set_unique_ids1 gh");
381         definehash= BLI_ghash_ptr_new("codegen_set_unique_ids2 gh");
382
383         for (node=nodes->first; node; node=node->next) {
384                 for (input=node->inputs.first; input; input=input->next) {
385                         /* set id for unique names of uniform variables */
386                         input->id = id++;
387                         input->bindtex = 0;
388                         input->definetex = 0;
389
390                         /* set texid used for settings texture slot with multitexture */
391                         if (codegen_input_has_texture(input) &&
392                             ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL)))
393                         {
394                                 if (input->link) {
395                                         /* input is texture from buffer, assign only one texid per
396                                          * buffer to avoid sampling the same texture twice */
397                                         if (!BLI_ghash_haskey(bindhash, input->link)) {
398                                                 input->texid = texid++;
399                                                 input->bindtex = 1;
400                                                 BLI_ghash_insert(bindhash, input->link, SET_INT_IN_POINTER(input->texid));
401                                         }
402                                         else
403                                                 input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->link));
404                                 }
405                                 else if (input->ima) {
406                                         /* input is texture from image, assign only one texid per
407                                          * buffer to avoid sampling the same texture twice */
408                                         if (!BLI_ghash_haskey(bindhash, input->ima)) {
409                                                 input->texid = texid++;
410                                                 input->bindtex = 1;
411                                                 BLI_ghash_insert(bindhash, input->ima, SET_INT_IN_POINTER(input->texid));
412                                         }
413                                         else
414                                                 input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->ima));
415                                 }
416                                 else if (input->prv) {
417                                         /* input is texture from preview render, assign only one texid per
418                                          * buffer to avoid sampling the same texture twice */
419                                         if (!BLI_ghash_haskey(bindhash, input->prv)) {
420                                                 input->texid = texid++;
421                                                 input->bindtex = 1;
422                                                 BLI_ghash_insert(bindhash, input->prv, SET_INT_IN_POINTER(input->texid));
423                                         }
424                                         else
425                                                 input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->prv));
426                                 }
427                                 else {
428                                         if (!BLI_ghash_haskey(bindhash, input->tex)) {
429                                                 /* input is user created texture, check tex pointer */
430                                                 input->texid = texid++;
431                                                 input->bindtex = 1;
432                                                 BLI_ghash_insert(bindhash, input->tex, SET_INT_IN_POINTER(input->texid));
433                                         }
434                                         else
435                                                 input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->tex));
436                                 }
437
438                                 /* make sure this pixel is defined exactly once */
439                                 if (input->source == GPU_SOURCE_TEX_PIXEL) {
440                                         if (input->ima) {
441                                                 if (!BLI_ghash_haskey(definehash, input->ima)) {
442                                                         input->definetex = 1;
443                                                         BLI_ghash_insert(definehash, input->ima, SET_INT_IN_POINTER(input->texid));
444                                                 }
445                                         }
446                                         else {
447                                                 if (!BLI_ghash_haskey(definehash, input->link)) {
448                                                         input->definetex = 1;
449                                                         BLI_ghash_insert(definehash, input->link, SET_INT_IN_POINTER(input->texid));
450                                                 }
451                                         }
452                                 }
453                         }
454                 }
455
456                 for (output=node->outputs.first; output; output=output->next)
457                         /* set id for unique names of tmp variables storing output */
458                         output->id = id++;
459         }
460
461         BLI_ghash_free(bindhash, NULL, NULL);
462         BLI_ghash_free(definehash, NULL, NULL);
463 }
464
465 static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
466 {
467         GPUNode *node;
468         GPUInput *input;
469         const char *name;
470         int builtins = 0;
471
472         /* print uniforms */
473         for (node=nodes->first; node; node=node->next) {
474                 for (input=node->inputs.first; input; input=input->next) {
475                         if ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL)) {
476                                 /* create exactly one sampler for each texture */
477                                 if (codegen_input_has_texture(input) && input->bindtex)
478                                         BLI_dynstr_appendf(ds, "uniform %s samp%d;\n",
479                                                 (input->textype == GPU_TEX2D) ? "sampler2D" : "sampler2DShadow",
480                                                 input->texid);
481                         }
482                         else if (input->source == GPU_SOURCE_BUILTIN) {
483                                 /* only define each builting uniform/varying once */
484                                 if (!(builtins & input->builtin)) {
485                                         builtins |= input->builtin;
486                                         name = GPU_builtin_name(input->builtin);
487
488                                         if (gpu_str_prefix(name, "unf")) {
489                                                 BLI_dynstr_appendf(ds, "uniform %s %s;\n",
490                                                         GPU_DATATYPE_STR[input->type], name);
491                                         }
492                                         else {
493                                                 BLI_dynstr_appendf(ds, "varying %s %s;\n",
494                                                         GPU_DATATYPE_STR[input->type], name);
495                                         }
496                                 }
497                         }
498                         else if (input->source == GPU_SOURCE_VEC_UNIFORM) {
499                                 if (input->dynamicvec) {
500                                         /* only create uniforms for dynamic vectors */
501                                         BLI_dynstr_appendf(ds, "uniform %s unf%d;\n",
502                                                 GPU_DATATYPE_STR[input->type], input->id);
503                                 }
504                                 else {
505                                         /* for others use const so the compiler can do folding */
506                                         BLI_dynstr_appendf(ds, "const %s cons%d = ",
507                                                 GPU_DATATYPE_STR[input->type], input->id);
508                                         codegen_print_datatype(ds, input->type, input->vec);
509                                         BLI_dynstr_append(ds, ";\n");
510                                 }
511                         }
512                         else if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
513                                 BLI_dynstr_appendf(ds, "varying %s var%d;\n",
514                                         GPU_DATATYPE_STR[input->type], input->attribid);
515                         }
516                 }
517         }
518
519         BLI_dynstr_append(ds, "\n");
520
521         return builtins;
522 }
523
524 static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
525 {
526         GPUNode *node;
527         GPUInput *input;
528         GPUOutput *output;
529
530         for (node=nodes->first; node; node=node->next) {
531                 /* load pixels from textures */
532                 for (input=node->inputs.first; input; input=input->next) {
533                         if (input->source == GPU_SOURCE_TEX_PIXEL) {
534                                 if (codegen_input_has_texture(input) && input->definetex) {
535                                         BLI_dynstr_appendf(ds, "\tvec4 tex%d = texture2D(", input->texid);
536                                         BLI_dynstr_appendf(ds, "samp%d, gl_TexCoord[%d].st);\n",
537                                                 input->texid, input->texid);
538                                 }
539                         }
540                 }
541
542                 /* declare temporary variables for node output storage */
543                 for (output=node->outputs.first; output; output=output->next)
544                         BLI_dynstr_appendf(ds, "\t%s tmp%d;\n",
545                                 GPU_DATATYPE_STR[output->type], output->id);
546         }
547
548         BLI_dynstr_append(ds, "\n");
549 }
550
551 static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *finaloutput)
552 {
553         GPUNode *node;
554         GPUInput *input;
555         GPUOutput *output;
556
557         for (node=nodes->first; node; node=node->next) {
558                 BLI_dynstr_appendf(ds, "\t%s(", node->name);
559                 
560                 for (input=node->inputs.first; input; input=input->next) {
561                         if (input->source == GPU_SOURCE_TEX) {
562                                 BLI_dynstr_appendf(ds, "samp%d", input->texid);
563                                 if (input->link)
564                                         BLI_dynstr_appendf(ds, ", gl_TexCoord[%d].st", input->texid);
565                         }
566                         else if (input->source == GPU_SOURCE_TEX_PIXEL) {
567                                 codegen_convert_datatype(ds, input->link->output->type, input->type,
568                                         "tmp", input->link->output->id);
569                         }
570                         else if (input->source == GPU_SOURCE_BUILTIN) {
571                                 if (input->builtin == GPU_VIEW_NORMAL)
572                                         BLI_dynstr_append(ds, "facingnormal");
573                                 else
574                                         BLI_dynstr_append(ds, GPU_builtin_name(input->builtin));
575                         }
576                         else if (input->source == GPU_SOURCE_VEC_UNIFORM) {
577                                 if (input->dynamicvec)
578                                         BLI_dynstr_appendf(ds, "unf%d", input->id);
579                                 else
580                                         BLI_dynstr_appendf(ds, "cons%d", input->id);
581                         }
582                         else if (input->source == GPU_SOURCE_ATTRIB) {
583                                 BLI_dynstr_appendf(ds, "var%d", input->attribid);
584                         }
585                         else if (input->source == GPU_SOURCE_OPENGL_BUILTIN) {
586                                 if (input->oglbuiltin == GPU_MATCAP_NORMAL)
587                                         BLI_dynstr_append(ds, "gl_SecondaryColor");
588                                 else if (input->oglbuiltin == GPU_COLOR)
589                                         BLI_dynstr_append(ds, "gl_Color");
590                         }
591
592                         BLI_dynstr_append(ds, ", ");
593                 }
594
595                 for (output=node->outputs.first; output; output=output->next) {
596                         BLI_dynstr_appendf(ds, "tmp%d", output->id);
597                         if (output->next)
598                                 BLI_dynstr_append(ds, ", ");
599                 }
600
601                 BLI_dynstr_append(ds, ");\n");
602         }
603
604         BLI_dynstr_append(ds, "\n\tgl_FragColor = ");
605         codegen_convert_datatype(ds, finaloutput->type, GPU_VEC4, "tmp", finaloutput->id);
606         BLI_dynstr_append(ds, ";\n");
607 }
608
609 static char *code_generate_fragment(ListBase *nodes, GPUOutput *output)
610 {
611         DynStr *ds = BLI_dynstr_new();
612         char *code;
613         int builtins;
614
615         /*BLI_dynstr_append(ds, FUNCTION_PROTOTYPES);*/
616
617         codegen_set_unique_ids(nodes);
618         builtins = codegen_print_uniforms_functions(ds, nodes);
619
620         //if (G.debug & G_DEBUG)
621         //      BLI_dynstr_appendf(ds, "/* %s */\n", name);
622
623         BLI_dynstr_append(ds, "void main(void)\n");
624         BLI_dynstr_append(ds, "{\n");
625
626         if (builtins & GPU_VIEW_NORMAL)
627                 BLI_dynstr_append(ds, "\tvec3 facingnormal = (gl_FrontFacing)? varnormal: -varnormal;\n");
628         
629         codegen_declare_tmps(ds, nodes);
630         codegen_call_functions(ds, nodes, output);
631
632         BLI_dynstr_append(ds, "}\n");
633
634         /* create shader */
635         code = BLI_dynstr_get_cstring(ds);
636         BLI_dynstr_free(ds);
637
638         //if (G.debug & G_DEBUG) printf("%s\n", code);
639
640         return code;
641 }
642
643 static char *code_generate_vertex(ListBase *nodes, const GPUMatType type)
644 {
645         DynStr *ds = BLI_dynstr_new();
646         GPUNode *node;
647         GPUInput *input;
648         char *code;
649         char *vertcode;
650         
651         for (node=nodes->first; node; node=node->next) {
652                 for (input=node->inputs.first; input; input=input->next) {
653                         if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
654                                 BLI_dynstr_appendf(ds, "attribute %s att%d;\n",
655                                         GPU_DATATYPE_STR[input->type], input->attribid);
656                                 BLI_dynstr_appendf(ds, "varying %s var%d;\n",
657                                         GPU_DATATYPE_STR[input->type], input->attribid);
658                         }
659                 }
660         }
661
662         BLI_dynstr_append(ds, "\n");
663
664         switch (type) {
665                 case GPU_MATERIAL_TYPE_MESH:
666                         vertcode = datatoc_gpu_shader_vertex_glsl;
667                         break;
668                 case GPU_MATERIAL_TYPE_WORLD:
669                         vertcode = datatoc_gpu_shader_vertex_world_glsl;
670                         break;
671                 default:
672                         fprintf(stderr, "invalid material type, set one after GPU_material_construct_begin\n");
673                         break;
674         }
675
676         BLI_dynstr_append(ds, vertcode);
677         
678         for (node=nodes->first; node; node=node->next)
679                 for (input=node->inputs.first; input; input=input->next)
680                         if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
681                                 if (input->attribtype == CD_TANGENT) { /* silly exception */
682                                         BLI_dynstr_appendf(ds, "\tvar%d.xyz = normalize(gl_NormalMatrix * att%d.xyz);\n", input->attribid, input->attribid);
683                                         BLI_dynstr_appendf(ds, "\tvar%d.w = att%d.w;\n", input->attribid, input->attribid);
684                                 }
685                                 else
686                                         BLI_dynstr_appendf(ds, "\tvar%d = att%d;\n", input->attribid, input->attribid);
687                         }
688                         /* unfortunately special handling is needed here because we abuse gl_Color/gl_SecondaryColor flat shading */
689                         else if (input->source == GPU_SOURCE_OPENGL_BUILTIN) {
690                                 if (input->oglbuiltin == GPU_MATCAP_NORMAL) {
691                                         /* remap to 0.0 - 1.0 range. This is done because OpenGL 2.0 clamps colors
692                                          * between shader stages and we want the full range of the normal */
693                                         BLI_dynstr_appendf(ds, "\tvec3 matcapcol = vec3(0.5, 0.5, 0.5) * varnormal + vec3(0.5, 0.5, 0.5);\n");
694                                         BLI_dynstr_appendf(ds, "\tgl_FrontSecondaryColor = vec4(matcapcol, 1.0);\n");
695                                 }
696                                 else if (input->oglbuiltin == GPU_COLOR) {
697                                         BLI_dynstr_appendf(ds, "\tgl_FrontColor = gl_Color;\n");
698                                 }
699                         }
700
701         BLI_dynstr_append(ds, "}\n\n");
702
703         code = BLI_dynstr_get_cstring(ds);
704
705         BLI_dynstr_free(ds);
706
707         //if (G.debug & G_DEBUG) printf("%s\n", code);
708
709         return code;
710 }
711
712 int GPU_bicubic_bump_support(void)
713 {
714         return GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0;
715 }
716
717 void GPU_code_generate_glsl_lib(void)
718 {
719         DynStr *ds;
720
721         /* only initialize the library once */
722         if (glsl_material_library)
723                 return;
724
725         ds = BLI_dynstr_new();
726
727         BLI_dynstr_append(ds, datatoc_gpu_shader_material_glsl);
728
729
730         glsl_material_library = BLI_dynstr_get_cstring(ds);
731
732         BLI_dynstr_free(ds);
733 }
734
735
736 /* GPU pass binding/unbinding */
737
738 GPUShader *GPU_pass_shader(GPUPass *pass)
739 {
740         return pass->shader;
741 }
742
743 static void gpu_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
744 {
745         GPUShader *shader = pass->shader;
746         GPUNode *node;
747         GPUInput *next, *input;
748         ListBase *inputs = &pass->inputs;
749         int extract, z;
750
751         memset(inputs, 0, sizeof(*inputs));
752
753         if (!shader)
754                 return;
755
756         GPU_shader_bind(shader);
757
758         for (node=nodes->first; node; node=node->next) {
759                 z = 0;
760                 for (input=node->inputs.first; input; input=next, z++) {
761                         next = input->next;
762
763                         /* attributes don't need to be bound, they already have
764                          * an id that the drawing functions will use */
765                         if (input->source == GPU_SOURCE_ATTRIB ||
766                             input->source == GPU_SOURCE_BUILTIN ||
767                             input->source == GPU_SOURCE_OPENGL_BUILTIN)
768                         {
769                                 continue;
770                         }
771
772                         if (input->ima || input->tex || input->prv)
773                                 BLI_snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid);
774                         else
775                                 BLI_snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id);
776
777                         /* pass non-dynamic uniforms to opengl */
778                         extract = 0;
779
780                         if (input->ima || input->tex || input->prv) {
781                                 if (input->bindtex)
782                                         extract = 1;
783                         }
784                         else if (input->dynamicvec)
785                                 extract = 1;
786
787                         if (extract)
788                                 input->shaderloc = GPU_shader_get_uniform(shader, input->shadername);
789
790                         /* extract nodes */
791                         if (extract) {
792                                 BLI_remlink(&node->inputs, input);
793                                 BLI_addtail(inputs, input);
794                         }
795                 }
796         }
797
798         GPU_shader_unbind();
799 }
800
801 void GPU_pass_bind(GPUPass *pass, double time, int mipmap)
802 {
803         GPUInput *input;
804         GPUShader *shader = pass->shader;
805         ListBase *inputs = &pass->inputs;
806
807         if (!shader)
808                 return;
809
810         GPU_shader_bind(shader);
811
812         /* now bind the textures */
813         for (input=inputs->first; input; input=input->next) {
814                 if (input->ima)
815                         input->tex = GPU_texture_from_blender(input->ima, input->iuser, input->image_isdata, time, mipmap);
816                 else if (input->prv)
817                         input->tex = GPU_texture_from_preview(input->prv, mipmap);
818
819                 if (input->tex && input->bindtex) {
820                         GPU_texture_bind(input->tex, input->texid);
821                         GPU_shader_uniform_texture(shader, input->shaderloc, input->tex);
822                 }
823                         
824         }
825 }
826
827 void GPU_pass_update_uniforms(GPUPass *pass)
828 {
829         GPUInput *input;
830         GPUShader *shader = pass->shader;
831         ListBase *inputs = &pass->inputs;
832
833         if (!shader)
834                 return;
835
836         /* pass dynamic inputs to opengl, others were removed */
837         for (input=inputs->first; input; input=input->next)
838                 if (!(input->ima || input->tex || input->prv))
839                         GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1,
840                                 input->dynamicvec);
841 }
842
843 void GPU_pass_unbind(GPUPass *pass)
844 {
845         GPUInput *input;
846         GPUShader *shader = pass->shader;
847         ListBase *inputs = &pass->inputs;
848
849         if (!shader)
850                 return;
851
852         for (input=inputs->first; input; input=input->next) {
853                 if (input->tex && input->bindtex)
854                         GPU_texture_unbind(input->tex);
855
856                 if (input->ima || input->prv)
857                         input->tex = NULL;
858         }
859         
860         GPU_shader_unbind();
861 }
862
863 /* Node Link Functions */
864
865 static GPUNodeLink *GPU_node_link_create(void)
866 {
867         GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink");
868         link->type = GPU_NONE;
869         link->users++;
870
871         return link;
872 }
873
874 static void gpu_node_link_free(GPUNodeLink *link)
875 {
876         link->users--;
877
878         if (link->users < 0)
879                 fprintf(stderr, "GPU_node_link_free: negative refcount\n");
880         
881         if (link->users == 0) {
882                 if (link->output)
883                         link->output->link = NULL;
884                 MEM_freeN(link);
885         }
886 }
887
888 /* Node Functions */
889
890 static GPUNode *GPU_node_begin(const char *name)
891 {
892         GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode");
893
894         node->name= name;
895
896         return node;
897 }
898
899 static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType type)
900 {
901         GPUInput *input;
902         GPUNode *outnode;
903         const char *name;
904
905         if (link->output) {
906                 outnode = link->output->node;
907                 name = outnode->name;
908
909                 if (strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) {
910                         input = MEM_dupallocN(outnode->inputs.first);
911                         input->type = type;
912                         if (input->link)
913                                 input->link->users++;
914                         BLI_addtail(&node->inputs, input);
915                         return;
916                 }
917         }
918         
919         input = MEM_callocN(sizeof(GPUInput), "GPUInput");
920         input->node = node;
921
922         if (link->builtin) {
923                 /* builtin uniform */
924                 input->type = type;
925                 input->source = GPU_SOURCE_BUILTIN;
926                 input->builtin = link->builtin;
927
928                 MEM_freeN(link);
929         }
930         else if (link->oglbuiltin) {
931                 /* builtin uniform */
932                 input->type = type;
933                 input->source = GPU_SOURCE_OPENGL_BUILTIN;
934                 input->oglbuiltin = link->oglbuiltin;
935
936                 MEM_freeN(link);
937         }
938         else if (link->output) {
939                 /* link to a node output */
940                 input->type = type;
941                 input->source = GPU_SOURCE_TEX_PIXEL;
942                 input->link = link;
943                 link->users++;
944         }
945         else if (link->dynamictex) {
946                 /* dynamic texture, GPUTexture is updated/deleted externally */
947                 input->type = type;
948                 input->source = GPU_SOURCE_TEX;
949
950                 input->tex = link->dynamictex;
951                 input->textarget = GL_TEXTURE_2D;
952                 input->textype = type;
953                 input->dynamictex = 1;
954                 input->dynamicdata = link->ptr2;
955                 MEM_freeN(link);
956         }
957         else if (link->texture) {
958                 /* small texture created on the fly, like for colorbands */
959                 input->type = GPU_VEC4;
960                 input->source = GPU_SOURCE_TEX;
961                 input->textype = type;
962
963                 //input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
964                 input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, NULL);
965                 input->textarget = GL_TEXTURE_2D;
966
967                 MEM_freeN(link->ptr1);
968                 MEM_freeN(link);
969         }
970         else if (link->image) {
971                 /* blender image */
972                 input->type = GPU_VEC4;
973                 input->source = GPU_SOURCE_TEX;
974
975                 if (link->image == LINK_IMAGE_PREVIEW)
976                         input->prv = link->ptr1;
977                 else {
978                         input->ima = link->ptr1;
979                         input->iuser = link->ptr2;
980                         input->image_isdata = link->image_isdata;
981                 }
982                 input->textarget = GL_TEXTURE_2D;
983                 input->textype = GPU_TEX2D;
984                 MEM_freeN(link);
985         }
986         else if (link->attribtype) {
987                 /* vertex attribute */
988                 input->type = type;
989                 input->source = GPU_SOURCE_ATTRIB;
990
991                 input->attribtype = link->attribtype;
992                 BLI_strncpy(input->attribname, link->attribname, sizeof(input->attribname));
993                 MEM_freeN(link);
994         }
995         else {
996                 /* uniform vector */
997                 input->type = type;
998                 input->source = GPU_SOURCE_VEC_UNIFORM;
999
1000                 memcpy(input->vec, link->ptr1, type*sizeof(float));
1001                 if (link->dynamic) {
1002                         input->dynamicvec= link->ptr1;
1003                         input->dynamictype= link->dynamictype;
1004                         input->dynamicdata= link->ptr2;
1005                 }
1006                 MEM_freeN(link);
1007         }
1008
1009         BLI_addtail(&node->inputs, input);
1010 }
1011
1012 static void gpu_node_input_socket(GPUNode *node, GPUNodeStack *sock)
1013 {
1014         GPUNodeLink *link;
1015
1016         if (sock->link) {
1017                 gpu_node_input_link(node, sock->link, sock->type);
1018         }
1019         else {
1020                 link = GPU_node_link_create();
1021                 link->ptr1 = sock->vec;
1022                 gpu_node_input_link(node, link, sock->type);
1023         }
1024 }
1025
1026 static void gpu_node_output(GPUNode *node, const GPUType type, GPUNodeLink **link)
1027 {
1028         GPUOutput *output = MEM_callocN(sizeof(GPUOutput), "GPUOutput");
1029
1030         output->type = type;
1031         output->node = node;
1032
1033         if (link) {
1034                 *link = output->link = GPU_node_link_create();
1035                 output->link->type = type;
1036                 output->link->output = output;
1037
1038                 /* note: the caller owns the reference to the linkfer, GPUOutput
1039                  * merely points to it, and if the node is destroyed it will
1040                  * set that pointer to NULL */
1041         }
1042
1043         BLI_addtail(&node->outputs, output);
1044 }
1045
1046 static void gpu_inputs_free(ListBase *inputs)
1047 {
1048         GPUInput *input;
1049
1050         for (input=inputs->first; input; input=input->next) {
1051                 if (input->link)
1052                         gpu_node_link_free(input->link);
1053                 else if (input->tex && !input->dynamictex)
1054                         GPU_texture_free(input->tex);
1055         }
1056
1057         BLI_freelistN(inputs);
1058 }
1059
1060 static void gpu_node_free(GPUNode *node)
1061 {
1062         GPUOutput *output;
1063
1064         gpu_inputs_free(&node->inputs);
1065
1066         for (output=node->outputs.first; output; output=output->next)
1067                 if (output->link) {
1068                         output->link->output = NULL;
1069                         gpu_node_link_free(output->link);
1070                 }
1071
1072         BLI_freelistN(&node->outputs);
1073         MEM_freeN(node);
1074 }
1075
1076 static void gpu_nodes_free(ListBase *nodes)
1077 {
1078         GPUNode *node;
1079
1080         while ((node = BLI_pophead(nodes))) {
1081                 gpu_node_free(node);
1082         }
1083 }
1084
1085 /* vertex attributes */
1086
1087 static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs)
1088 {
1089         GPUNode *node;
1090         GPUInput *input;
1091         int a;
1092
1093         /* convert attributes requested by node inputs to an array of layers,
1094          * checking for duplicates and assigning id's starting from zero. */
1095
1096         memset(attribs, 0, sizeof(*attribs));
1097
1098         for (node=nodes->first; node; node=node->next) {
1099                 for (input=node->inputs.first; input; input=input->next) {
1100                         if (input->source == GPU_SOURCE_ATTRIB) {
1101                                 for (a=0; a<attribs->totlayer; a++) {
1102                                         if (attribs->layer[a].type == input->attribtype &&
1103                                             strcmp(attribs->layer[a].name, input->attribname) == 0)
1104                                         {
1105                                                 break;
1106                                         }
1107                                 }
1108
1109                                 if (a < GPU_MAX_ATTRIB) {
1110                                         if (a == attribs->totlayer) {
1111                                                 input->attribid = attribs->totlayer++;
1112                                                 input->attribfirst = 1;
1113
1114                                                 attribs->layer[a].type = input->attribtype;
1115                                                 attribs->layer[a].attribid = input->attribid;
1116                                                 BLI_strncpy(attribs->layer[a].name, input->attribname,
1117                                                             sizeof(attribs->layer[a].name));
1118                                         }
1119                                         else {
1120                                                 input->attribid = attribs->layer[a].attribid;
1121                                         }
1122                                 }
1123                         }
1124                 }
1125         }
1126 }
1127
1128 static void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin)
1129 {
1130         GPUNode *node;
1131         GPUInput *input;
1132         
1133         *builtin= 0;
1134
1135         for (node=nodes->first; node; node=node->next)
1136                 for (input=node->inputs.first; input; input=input->next)
1137                         if (input->source == GPU_SOURCE_BUILTIN)
1138                                 *builtin |= input->builtin;
1139 }
1140
1141 /* varargs linking  */
1142
1143 GPUNodeLink *GPU_attribute(const CustomDataType type, const char *name)
1144 {
1145         GPUNodeLink *link = GPU_node_link_create();
1146
1147         link->attribtype= type;
1148         link->attribname= name;
1149
1150         return link;
1151 }
1152
1153 GPUNodeLink *GPU_uniform(float *num)
1154 {
1155         GPUNodeLink *link = GPU_node_link_create();
1156
1157         link->ptr1= num;
1158         link->ptr2= NULL;
1159
1160         return link;
1161 }
1162
1163 GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data)
1164 {
1165         GPUNodeLink *link = GPU_node_link_create();
1166
1167         link->ptr1= num;
1168         link->ptr2= data;
1169         link->dynamic= 1;
1170         link->dynamictype = dynamictype;
1171
1172
1173         return link;
1174 }
1175
1176 GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data)
1177 {
1178         GPUNodeLink *link = GPU_node_link_create();
1179
1180         link->image = LINK_IMAGE_BLENDER;
1181         link->ptr1 = ima;
1182         link->ptr2 = iuser;
1183         link->image_isdata = is_data;
1184
1185         return link;
1186 }
1187
1188 GPUNodeLink *GPU_image_preview(PreviewImage *prv)
1189 {
1190         GPUNodeLink *link = GPU_node_link_create();
1191         
1192         link->image= LINK_IMAGE_PREVIEW;
1193         link->ptr1= prv;
1194         
1195         return link;
1196 }
1197
1198
1199 GPUNodeLink *GPU_texture(int size, float *pixels)
1200 {
1201         GPUNodeLink *link = GPU_node_link_create();
1202
1203         link->texture = 1;
1204         link->texturesize = size;
1205         link->ptr1= pixels;
1206
1207         return link;
1208 }
1209
1210 GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex, int dynamictype, void *data)
1211 {
1212         GPUNodeLink *link = GPU_node_link_create();
1213
1214         link->dynamic = 1;
1215         link->dynamictex = tex;
1216         link->dynamictype = dynamictype;
1217         link->ptr2 = data;
1218
1219         return link;
1220 }
1221
1222 GPUNodeLink *GPU_builtin(GPUBuiltin builtin)
1223 {
1224         GPUNodeLink *link = GPU_node_link_create();
1225
1226         link->builtin= builtin;
1227
1228         return link;
1229 }
1230
1231 GPUNodeLink *GPU_opengl_builtin(GPUOpenGLBuiltin builtin)
1232 {
1233         GPUNodeLink *link = GPU_node_link_create();
1234
1235         link->oglbuiltin = builtin;
1236
1237         return link;
1238 }
1239
1240 bool GPU_link(GPUMaterial *mat, const char *name, ...)
1241 {
1242         GPUNode *node;
1243         GPUFunction *function;
1244         GPUNodeLink *link, **linkptr;
1245         va_list params;
1246         int i;
1247
1248         function = GPU_lookup_function(name);
1249         if (!function) {
1250                 fprintf(stderr, "GPU failed to find function %s\n", name);
1251                 return 0;
1252         }
1253
1254         node = GPU_node_begin(name);
1255
1256         va_start(params, name);
1257         for (i=0; i<function->totparam; i++) {
1258                 if (function->paramqual[i] != FUNCTION_QUAL_IN) {
1259                         linkptr= va_arg(params, GPUNodeLink**);
1260                         gpu_node_output(node, function->paramtype[i], linkptr);
1261                 }
1262                 else {
1263                         link= va_arg(params, GPUNodeLink*);
1264                         gpu_node_input_link(node, link, function->paramtype[i]);
1265                 }
1266         }
1267         va_end(params);
1268
1269         gpu_material_add_node(mat, node);
1270
1271         return 1;
1272 }
1273
1274 bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...)
1275 {
1276         GPUNode *node;
1277         GPUFunction *function;
1278         GPUNodeLink *link, **linkptr;
1279         va_list params;
1280         int i, totin, totout;
1281
1282         function = GPU_lookup_function(name);
1283         if (!function) {
1284                 fprintf(stderr, "GPU failed to find function %s\n", name);
1285                 return 0;
1286         }
1287
1288         node = GPU_node_begin(name);
1289         totin = 0;
1290         totout = 0;
1291
1292         if (in) {
1293                 for (i = 0; in[i].type != GPU_NONE; i++) {
1294                         gpu_node_input_socket(node, &in[i]);
1295                         totin++;
1296                 }
1297         }
1298         
1299         if (out) {
1300                 for (i = 0; out[i].type != GPU_NONE; i++) {
1301                         gpu_node_output(node, out[i].type, &out[i].link);
1302                         totout++;
1303                 }
1304         }
1305
1306         va_start(params, out);
1307         for (i=0; i<function->totparam; i++) {
1308                 if (function->paramqual[i] != FUNCTION_QUAL_IN) {
1309                         if (totout == 0) {
1310                                 linkptr= va_arg(params, GPUNodeLink**);
1311                                 gpu_node_output(node, function->paramtype[i], linkptr);
1312                         }
1313                         else
1314                                 totout--;
1315                 }
1316                 else {
1317                         if (totin == 0) {
1318                                 link= va_arg(params, GPUNodeLink*);
1319                                 if (link->socket)
1320                                         gpu_node_input_socket(node, link->socket);
1321                                 else
1322                                         gpu_node_input_link(node, link, function->paramtype[i]);
1323                         }
1324                         else
1325                                 totin--;
1326                 }
1327         }
1328         va_end(params);
1329
1330         gpu_material_add_node(mat, node);
1331         
1332         return 1;
1333 }
1334
1335 int GPU_link_changed(GPUNodeLink *link)
1336 {
1337         GPUNode *node;
1338         GPUInput *input;
1339         const char *name;
1340
1341         if (link->output) {
1342                 node = link->output->node;
1343                 name = node->name;
1344
1345                 if (strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) {
1346                         input = node->inputs.first;
1347                         return (input->link != NULL);
1348                 }
1349
1350                 return 1;
1351         }
1352         else
1353                 return 0;
1354 }
1355
1356 /* Pass create/free */
1357
1358 static void gpu_nodes_tag(GPUNodeLink *link)
1359 {
1360         GPUNode *node;
1361         GPUInput *input;
1362
1363         if (!link->output)
1364                 return;
1365
1366         node = link->output->node;
1367         if (node->tag)
1368                 return;
1369         
1370         node->tag= 1;
1371         for (input=node->inputs.first; input; input=input->next)
1372                 if (input->link)
1373                         gpu_nodes_tag(input->link);
1374 }
1375
1376 static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
1377 {
1378         GPUNode *node, *next;
1379
1380         for (node=nodes->first; node; node=node->next)
1381                 node->tag= 0;
1382
1383         gpu_nodes_tag(outlink);
1384
1385         for (node=nodes->first; node; node=next) {
1386                 next = node->next;
1387
1388                 if (!node->tag) {
1389                         BLI_remlink(nodes, node);
1390                         gpu_node_free(node);
1391                 }
1392         }
1393 }
1394
1395 GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink,
1396                                                    GPUVertexAttribs *attribs, int *builtins,
1397                                                    const GPUMatType type, const char *UNUSED(name))
1398 {
1399         GPUShader *shader;
1400         GPUPass *pass;
1401         char *vertexcode, *fragmentcode;
1402
1403         /*if (!FUNCTION_LIB) {
1404                 GPU_nodes_free(nodes);
1405                 return NULL;
1406         }*/
1407
1408         /* prune unused nodes */
1409         gpu_nodes_prune(nodes, outlink);
1410
1411         gpu_nodes_get_vertex_attributes(nodes, attribs);
1412         gpu_nodes_get_builtin_flag(nodes, builtins);
1413
1414         /* generate code and compile with opengl */
1415         fragmentcode = code_generate_fragment(nodes, outlink->output);
1416         vertexcode = code_generate_vertex(nodes, type);
1417         shader = GPU_shader_create(vertexcode, fragmentcode, glsl_material_library, NULL);
1418
1419         /* failed? */
1420         if (!shader) {
1421                 if (fragmentcode)
1422                         MEM_freeN(fragmentcode);
1423                 if (vertexcode)
1424                         MEM_freeN(vertexcode);
1425                 memset(attribs, 0, sizeof(*attribs));
1426                 memset(builtins, 0, sizeof(*builtins));
1427                 gpu_nodes_free(nodes);
1428                 return NULL;
1429         }
1430         
1431         /* create pass */
1432         pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
1433
1434         pass->output = outlink->output;
1435         pass->shader = shader;
1436         pass->fragmentcode = fragmentcode;
1437         pass->vertexcode = vertexcode;
1438         pass->libcode = glsl_material_library;
1439
1440         /* extract dynamic inputs and throw away nodes */
1441         gpu_nodes_extract_dynamic_inputs(pass, nodes);
1442         gpu_nodes_free(nodes);
1443
1444         return pass;
1445 }
1446
1447 void GPU_pass_free(GPUPass *pass)
1448 {
1449         GPU_shader_free(pass->shader);
1450         gpu_inputs_free(&pass->inputs);
1451         if (pass->fragmentcode)
1452                 MEM_freeN(pass->fragmentcode);
1453         if (pass->vertexcode)
1454                 MEM_freeN(pass->vertexcode);
1455         MEM_freeN(pass);
1456 }
1457