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