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