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