Refactor to recent matcap built-ins to not use the built in system.
[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 "GL/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 #include "BLI_heap.h"
47
48 #include "GPU_material.h"
49 #include "GPU_extensions.h"
50
51 #include "BLI_sys_types.h" // for intptr_t support
52
53 #include "gpu_codegen.h"
54
55 #include "node_util.h" /* For muting node stuff... */
56
57 #include <string.h>
58 #include <stdarg.h>
59
60 extern char datatoc_gpu_shader_material_glsl[];
61 extern char datatoc_gpu_shader_vertex_glsl[];
62
63
64 static char *glsl_material_library = NULL;
65
66
67 /* structs and defines */
68
69 static const char *GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4",
70         NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4"};
71
72 #define LINK_IMAGE_BLENDER      1
73 #define LINK_IMAGE_PREVIEW      2
74
75 /* GLSL code parsing for finding function definitions.
76  * These are stored in a hash for lookup when creating a material. */
77
78 static GHash *FUNCTION_HASH= NULL;
79 /* static char *FUNCTION_PROTOTYPES= NULL;
80  * static GPUShader *FUNCTION_LIB= NULL;*/
81
82 static int gpu_str_prefix(const char *str, const char *prefix)
83 {
84         while (*str && *prefix) {
85                 if (*str != *prefix)
86                         return 0;
87
88                 str++;
89                 prefix++;
90         }
91         
92         return (*prefix == '\0');
93 }
94
95 static char *gpu_str_skip_token(char *str, char *token, int max)
96 {
97         int len = 0;
98
99         /* skip a variable/function name */
100         while (*str) {
101                 if (ELEM7(*str, ' ', '(', ')', ',', '\t', '\n', '\r'))
102                         break;
103                 else {
104                         if (token && len < max-1) {
105                                 *token= *str;
106                                 token++;
107                                 len++;
108                         }
109                         str++;
110                 }
111         }
112
113         if (token)
114                 *token= '\0';
115
116         /* skip the next special characters:
117          * note the missing ')' */
118         while (*str) {
119                 if (ELEM6(*str, ' ', '(', ',', '\t', '\n', '\r'))
120                         str++;
121                 else
122                         break;
123         }
124
125         return str;
126 }
127
128 static void gpu_parse_functions_string(GHash *hash, char *code)
129 {
130         GPUFunction *function;
131         int i, type, 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= 0;
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 paramater */
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 (GPUFunction*)BLI_ghash_lookup(FUNCTION_HASH, (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);
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, int 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
630         codegen_declare_tmps(ds, nodes);
631         codegen_call_functions(ds, nodes, output);
632
633         BLI_dynstr_append(ds, "}\n");
634
635         /* create shader */
636         code = BLI_dynstr_get_cstring(ds);
637         BLI_dynstr_free(ds);
638
639         //if (G.debug & G_DEBUG) printf("%s\n", code);
640
641         return code;
642 }
643
644 static char *code_generate_vertex(ListBase *nodes)
645 {
646         DynStr *ds = BLI_dynstr_new();
647         GPUNode *node;
648         GPUInput *input;
649         char *code;
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         BLI_dynstr_append(ds, datatoc_gpu_shader_vertex_glsl);
664
665         for (node=nodes->first; node; node=node->next)
666                 for (input=node->inputs.first; input; input=input->next)
667                         if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
668                                 if (input->attribtype == CD_TANGENT) { /* silly exception */
669                                         BLI_dynstr_appendf(ds, "\tvar%d.xyz = normalize((gl_ModelViewMatrix * vec4(att%d.xyz, 0)).xyz);\n", input->attribid, input->attribid);
670                                         BLI_dynstr_appendf(ds, "\tvar%d.w = att%d.w;\n", input->attribid, input->attribid);
671                                 }
672                                 else
673                                         BLI_dynstr_appendf(ds, "\tvar%d = att%d;\n", input->attribid, input->attribid);
674                         }
675                         /* unfortunately special handling is needed here because we abuse gl_Color/gl_SecondaryColor flat shading */
676                         else if (input->source == GPU_SOURCE_OPENGL_BUILTIN) {
677                                 if (input->oglbuiltin == GPU_MATCAP_NORMAL) {
678                                         /* remap to 0.0 - 1.0 range. This is done because OpenGL 2.0 clamps colors
679                                          * between shader stages and we want the full range of the normal */
680                                         BLI_dynstr_appendf(ds, "\tvec3 matcapcol = vec3(0.5, 0.5, 0.5) * varnormal + vec3(0.5, 0.5, 0.5);\n");
681                                         BLI_dynstr_appendf(ds, "\tgl_FrontSecondaryColor = vec4(matcapcol, 1.0);\n");
682                                 }
683                                 else if (input->oglbuiltin == GPU_COLOR) {
684                                         BLI_dynstr_appendf(ds, "\tgl_FrontColor = gl_Color;\n");
685                                 }
686                         }
687
688         BLI_dynstr_append(ds, "}\n\n");
689
690         code = BLI_dynstr_get_cstring(ds);
691
692         BLI_dynstr_free(ds);
693
694         //if (G.debug & G_DEBUG) printf("%s\n", code);
695
696         return code;
697 }
698
699 int GPU_bicubic_bump_support(void)
700 {
701         return GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0;
702 }
703
704 void GPU_code_generate_glsl_lib(void)
705 {
706         DynStr *ds;
707
708         /* only initialize the library once */
709         if (glsl_material_library)
710                 return;
711
712         ds = BLI_dynstr_new();
713
714         BLI_dynstr_append(ds, datatoc_gpu_shader_material_glsl);
715
716
717         glsl_material_library = BLI_dynstr_get_cstring(ds);
718
719         BLI_dynstr_free(ds);
720 }
721
722
723 /* GPU pass binding/unbinding */
724
725 GPUShader *GPU_pass_shader(GPUPass *pass)
726 {
727         return pass->shader;
728 }
729
730 static void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
731 {
732         GPUShader *shader = pass->shader;
733         GPUNode *node;
734         GPUInput *next, *input;
735         ListBase *inputs = &pass->inputs;
736         int extract, z;
737
738         memset(inputs, 0, sizeof(*inputs));
739
740         if (!shader)
741                 return;
742
743         GPU_shader_bind(shader);
744
745         for (node=nodes->first; node; node=node->next) {
746                 z = 0;
747                 for (input=node->inputs.first; input; input=next, z++) {
748                         next = input->next;
749
750                         /* attributes don't need to be bound, they already have
751                          * an id that the drawing functions will use */
752                         if (input->source == GPU_SOURCE_ATTRIB ||
753                             input->source == GPU_SOURCE_BUILTIN ||
754                             input->source == GPU_SOURCE_OPENGL_BUILTIN)
755                         {
756                                 continue;
757                         }
758
759                         if (input->ima || input->tex || input->prv)
760                                 BLI_snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid);
761                         else
762                                 BLI_snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id);
763
764                         /* pass non-dynamic uniforms to opengl */
765                         extract = 0;
766
767                         if (input->ima || input->tex || input->prv) {
768                                 if (input->bindtex)
769                                         extract = 1;
770                         }
771                         else if (input->dynamicvec)
772                                 extract = 1;
773
774                         if (extract)
775                                 input->shaderloc = GPU_shader_get_uniform(shader, input->shadername);
776
777                         /* extract nodes */
778                         if (extract) {
779                                 BLI_remlink(&node->inputs, input);
780                                 BLI_addtail(inputs, input);
781                         }
782                 }
783         }
784
785         GPU_shader_unbind();
786 }
787
788 void GPU_pass_bind(GPUPass *pass, double time, int mipmap)
789 {
790         GPUInput *input;
791         GPUShader *shader = pass->shader;
792         ListBase *inputs = &pass->inputs;
793
794         if (!shader)
795                 return;
796
797         GPU_shader_bind(shader);
798
799         /* now bind the textures */
800         for (input=inputs->first; input; input=input->next) {
801                 if (input->ima)
802                         input->tex = GPU_texture_from_blender(input->ima, input->iuser, input->image_isdata, time, mipmap);
803                 else if (input->prv)
804                         input->tex = GPU_texture_from_preview(input->prv, mipmap);
805
806                 if (input->tex && input->bindtex) {
807                         GPU_texture_bind(input->tex, input->texid);
808                         GPU_shader_uniform_texture(shader, input->shaderloc, input->tex);
809                 }
810                         
811         }
812 }
813
814 void GPU_pass_update_uniforms(GPUPass *pass)
815 {
816         GPUInput *input;
817         GPUShader *shader = pass->shader;
818         ListBase *inputs = &pass->inputs;
819
820         if (!shader)
821                 return;
822
823         /* pass dynamic inputs to opengl, others were removed */
824         for (input=inputs->first; input; input=input->next)
825                 if (!(input->ima || input->tex || input->prv))
826                         GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1,
827                                 input->dynamicvec);
828 }
829
830 void GPU_pass_unbind(GPUPass *pass)
831 {
832         GPUInput *input;
833         GPUShader *shader = pass->shader;
834         ListBase *inputs = &pass->inputs;
835
836         if (!shader)
837                 return;
838
839         for (input=inputs->first; input; input=input->next) {
840                 if (input->tex && input->bindtex)
841                         GPU_texture_unbind(input->tex);
842
843                 if (input->ima || input->prv)
844                         input->tex = NULL;
845         }
846         
847         GPU_shader_unbind();
848 }
849
850 /* Node Link Functions */
851
852 static GPUNodeLink *GPU_node_link_create(int type)
853 {
854         GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink");
855         link->type = type;
856         link->users++;
857
858         return link;
859 }
860
861 static void GPU_node_link_free(GPUNodeLink *link)
862 {
863         link->users--;
864
865         if (link->users < 0)
866                 fprintf(stderr, "GPU_node_link_free: negative refcount\n");
867         
868         if (link->users == 0) {
869                 if (link->output)
870                         link->output->link = NULL;
871                 MEM_freeN(link);
872         }
873 }
874
875 /* Node Functions */
876
877 static GPUNode *GPU_node_begin(const char *name)
878 {
879         GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode");
880
881         node->name= name;
882
883         return node;
884 }
885
886 static void GPU_node_end(GPUNode *UNUSED(node))
887 {
888         /* empty */
889 }
890
891 static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
892 {
893         GPUInput *input;
894         GPUNode *outnode;
895         const char *name;
896
897         if (link->output) {
898                 outnode = link->output->node;
899                 name = outnode->name;
900
901                 if (strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) {
902                         input = MEM_dupallocN(outnode->inputs.first);
903                         input->type = type;
904                         if (input->link)
905                                 input->link->users++;
906                         BLI_addtail(&node->inputs, input);
907                         return;
908                 }
909         }
910         
911         input = MEM_callocN(sizeof(GPUInput), "GPUInput");
912         input->node = node;
913
914         if (link->builtin) {
915                 /* builtin uniform */
916                 input->type = type;
917                 input->source = GPU_SOURCE_BUILTIN;
918                 input->builtin = link->builtin;
919
920                 MEM_freeN(link);
921         }
922         else if (link->oglbuiltin) {
923                 /* builtin uniform */
924                 input->type = type;
925                 input->source = GPU_SOURCE_OPENGL_BUILTIN;
926                 input->oglbuiltin = link->oglbuiltin;
927
928                 MEM_freeN(link);
929         }
930         else if (link->output) {
931                 /* link to a node output */
932                 input->type = type;
933                 input->source = GPU_SOURCE_TEX_PIXEL;
934                 input->link = link;
935                 link->users++;
936         }
937         else if (link->dynamictex) {
938                 /* dynamic texture, GPUTexture is updated/deleted externally */
939                 input->type = type;
940                 input->source = GPU_SOURCE_TEX;
941
942                 input->tex = link->dynamictex;
943                 input->textarget = GL_TEXTURE_2D;
944                 input->textype = type;
945                 input->dynamictex = 1;
946                 input->dynamicdata = link->ptr2;
947                 MEM_freeN(link);
948         }
949         else if (link->texture) {
950                 /* small texture created on the fly, like for colorbands */
951                 input->type = GPU_VEC4;
952                 input->source = GPU_SOURCE_TEX;
953                 input->textype = type;
954
955                 //input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
956                 input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, NULL);
957                 input->textarget = GL_TEXTURE_2D;
958
959                 MEM_freeN(link->ptr1);
960                 MEM_freeN(link);
961         }
962         else if (link->image) {
963                 /* blender image */
964                 input->type = GPU_VEC4;
965                 input->source = GPU_SOURCE_TEX;
966
967                 if (link->image == LINK_IMAGE_PREVIEW)
968                         input->prv = link->ptr1;
969                 else {
970                         input->ima = link->ptr1;
971                         input->iuser = link->ptr2;
972                         input->image_isdata = link->image_isdata;
973                 }
974                 input->textarget = GL_TEXTURE_2D;
975                 input->textype = GPU_TEX2D;
976                 MEM_freeN(link);
977         }
978         else if (link->attribtype) {
979                 /* vertex attribute */
980                 input->type = type;
981                 input->source = GPU_SOURCE_ATTRIB;
982
983                 input->attribtype = link->attribtype;
984                 BLI_strncpy(input->attribname, link->attribname, sizeof(input->attribname));
985                 MEM_freeN(link);
986         }
987         else {
988                 /* uniform vector */
989                 input->type = type;
990                 input->source = GPU_SOURCE_VEC_UNIFORM;
991
992                 memcpy(input->vec, link->ptr1, type*sizeof(float));
993                 if (link->dynamic) {
994                         input->dynamicvec= link->ptr1;
995                         input->dynamictype= link->dynamictype;
996                         input->dynamicdata= link->ptr2;
997                 }
998                 MEM_freeN(link);
999         }
1000
1001         BLI_addtail(&node->inputs, input);
1002 }
1003
1004 static void gpu_node_input_socket(GPUNode *node, GPUNodeStack *sock)
1005 {
1006         GPUNodeLink *link;
1007
1008         if (sock->link) {
1009                 gpu_node_input_link(node, sock->link, sock->type);
1010         }
1011         else {
1012                 link = GPU_node_link_create(0);
1013                 link->ptr1 = sock->vec;
1014                 gpu_node_input_link(node, link, sock->type);
1015         }
1016 }
1017
1018 static void GPU_node_output(GPUNode *node, int type, const char *UNUSED(name), GPUNodeLink **link)
1019 {
1020         GPUOutput *output = MEM_callocN(sizeof(GPUOutput), "GPUOutput");
1021
1022         output->type = type;
1023         output->node = node;
1024
1025         if (link) {
1026                 *link = output->link = GPU_node_link_create(type);
1027                 output->link->output = output;
1028
1029                 /* note: the caller owns the reference to the linkfer, GPUOutput
1030                  * merely points to it, and if the node is destroyed it will
1031                  * set that pointer to NULL */
1032         }
1033
1034         BLI_addtail(&node->outputs, output);
1035 }
1036
1037 static void GPU_inputs_free(ListBase *inputs)
1038 {
1039         GPUInput *input;
1040
1041         for (input=inputs->first; input; input=input->next) {
1042                 if (input->link)
1043                         GPU_node_link_free(input->link);
1044                 else if (input->tex && !input->dynamictex)
1045                         GPU_texture_free(input->tex);
1046         }
1047
1048         BLI_freelistN(inputs);
1049 }
1050
1051 static void GPU_node_free(GPUNode *node)
1052 {
1053         GPUOutput *output;
1054
1055         GPU_inputs_free(&node->inputs);
1056
1057         for (output=node->outputs.first; output; output=output->next)
1058                 if (output->link) {
1059                         output->link->output = NULL;
1060                         GPU_node_link_free(output->link);
1061                 }
1062
1063         BLI_freelistN(&node->outputs);
1064         MEM_freeN(node);
1065 }
1066
1067 static void GPU_nodes_free(ListBase *nodes)
1068 {
1069         GPUNode *node;
1070
1071         while ((node = BLI_pophead(nodes))) {
1072                 GPU_node_free(node);
1073         }
1074 }
1075
1076 /* vertex attributes */
1077
1078 static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs)
1079 {
1080         GPUNode *node;
1081         GPUInput *input;
1082         int a;
1083
1084         /* convert attributes requested by node inputs to an array of layers,
1085          * checking for duplicates and assigning id's starting from zero. */
1086
1087         memset(attribs, 0, sizeof(*attribs));
1088
1089         for (node=nodes->first; node; node=node->next) {
1090                 for (input=node->inputs.first; input; input=input->next) {
1091                         if (input->source == GPU_SOURCE_ATTRIB) {
1092                                 for (a=0; a<attribs->totlayer; a++) {
1093                                         if (attribs->layer[a].type == input->attribtype &&
1094                                             strcmp(attribs->layer[a].name, input->attribname) == 0)
1095                                         {
1096                                                 break;
1097                                         }
1098                                 }
1099
1100                                 if (a < GPU_MAX_ATTRIB) {
1101                                         if (a == attribs->totlayer) {
1102                                                 input->attribid = attribs->totlayer++;
1103                                                 input->attribfirst = 1;
1104
1105                                                 attribs->layer[a].type = input->attribtype;
1106                                                 attribs->layer[a].attribid = input->attribid;
1107                                                 BLI_strncpy(attribs->layer[a].name, input->attribname,
1108                                                             sizeof(attribs->layer[a].name));
1109                                         }
1110                                         else {
1111                                                 input->attribid = attribs->layer[a].attribid;
1112                                         }
1113                                 }
1114                         }
1115                 }
1116         }
1117 }
1118
1119 static void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin)
1120 {
1121         GPUNode *node;
1122         GPUInput *input;
1123         
1124         *builtin= 0;
1125
1126         for (node=nodes->first; node; node=node->next)
1127                 for (input=node->inputs.first; input; input=input->next)
1128                         if (input->source == GPU_SOURCE_BUILTIN)
1129                                 *builtin |= input->builtin;
1130 }
1131
1132 /* varargs linking  */
1133
1134 GPUNodeLink *GPU_attribute(int type, const char *name)
1135 {
1136         GPUNodeLink *link = GPU_node_link_create(0);
1137
1138         link->attribtype= type;
1139         link->attribname= name;
1140
1141         return link;
1142 }
1143
1144 GPUNodeLink *GPU_uniform(float *num)
1145 {
1146         GPUNodeLink *link = GPU_node_link_create(0);
1147
1148         link->ptr1= num;
1149         link->ptr2= NULL;
1150
1151         return link;
1152 }
1153
1154 GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data)
1155 {
1156         GPUNodeLink *link = GPU_node_link_create(0);
1157
1158         link->ptr1= num;
1159         link->ptr2= data;
1160         link->dynamic= 1;
1161         link->dynamictype = dynamictype;
1162
1163
1164         return link;
1165 }
1166
1167 GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data)
1168 {
1169         GPUNodeLink *link = GPU_node_link_create(0);
1170
1171         link->image = LINK_IMAGE_BLENDER;
1172         link->ptr1 = ima;
1173         link->ptr2 = iuser;
1174         link->image_isdata = is_data;
1175
1176         return link;
1177 }
1178
1179 GPUNodeLink *GPU_image_preview(PreviewImage *prv)
1180 {
1181         GPUNodeLink *link = GPU_node_link_create(0);
1182         
1183         link->image= LINK_IMAGE_PREVIEW;
1184         link->ptr1= prv;
1185         
1186         return link;
1187 }
1188
1189
1190 GPUNodeLink *GPU_texture(int size, float *pixels)
1191 {
1192         GPUNodeLink *link = GPU_node_link_create(0);
1193
1194         link->texture = 1;
1195         link->texturesize = size;
1196         link->ptr1= pixels;
1197
1198         return link;
1199 }
1200
1201 GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex, int dynamictype, void *data)
1202 {
1203         GPUNodeLink *link = GPU_node_link_create(0);
1204
1205         link->dynamic = 1;
1206         link->dynamictex = tex;
1207         link->dynamictype = dynamictype;
1208         link->ptr2 = data;
1209
1210         return link;
1211 }
1212
1213 GPUNodeLink *GPU_builtin(GPUBuiltin builtin)
1214 {
1215         GPUNodeLink *link = GPU_node_link_create(0);
1216
1217         link->builtin= builtin;
1218
1219         return link;
1220 }
1221
1222 GPUNodeLink *GPU_opengl_builtin(GPUOpenGLBuiltin builtin)
1223 {
1224         GPUNodeLink *link = GPU_node_link_create(0);
1225
1226         link->oglbuiltin = builtin;
1227
1228         return link;
1229 }
1230
1231 bool GPU_link(GPUMaterial *mat, const char *name, ...)
1232 {
1233         GPUNode *node;
1234         GPUFunction *function;
1235         GPUNodeLink *link, **linkptr;
1236         va_list params;
1237         int i;
1238
1239         function = GPU_lookup_function(name);
1240         if (!function) {
1241                 fprintf(stderr, "GPU failed to find function %s\n", name);
1242                 return 0;
1243         }
1244
1245         node = GPU_node_begin(name);
1246
1247         va_start(params, name);
1248         for (i=0; i<function->totparam; i++) {
1249                 if (function->paramqual[i] != FUNCTION_QUAL_IN) {
1250                         linkptr= va_arg(params, GPUNodeLink**);
1251                         GPU_node_output(node, function->paramtype[i], "", linkptr);
1252                 }
1253                 else {
1254                         link= va_arg(params, GPUNodeLink*);
1255                         gpu_node_input_link(node, link, function->paramtype[i]);
1256                 }
1257         }
1258         va_end(params);
1259
1260         GPU_node_end(node);
1261
1262         gpu_material_add_node(mat, node);
1263
1264         return 1;
1265 }
1266
1267 bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...)
1268 {
1269         GPUNode *node;
1270         GPUFunction *function;
1271         GPUNodeLink *link, **linkptr;
1272         va_list params;
1273         int i, totin, totout;
1274
1275         function = GPU_lookup_function(name);
1276         if (!function) {
1277                 fprintf(stderr, "GPU failed to find function %s\n", name);
1278                 return 0;
1279         }
1280
1281         node = GPU_node_begin(name);
1282         totin = 0;
1283         totout = 0;
1284
1285         if (in) {
1286                 for (i = 0; in[i].type != GPU_NONE; i++) {
1287                         gpu_node_input_socket(node, &in[i]);
1288                         totin++;
1289                 }
1290         }
1291         
1292         if (out) {
1293                 for (i = 0; out[i].type != GPU_NONE; i++) {
1294                         GPU_node_output(node, out[i].type, out[i].name, &out[i].link);
1295                         totout++;
1296                 }
1297         }
1298
1299         va_start(params, out);
1300         for (i=0; i<function->totparam; i++) {
1301                 if (function->paramqual[i] != FUNCTION_QUAL_IN) {
1302                         if (totout == 0) {
1303                                 linkptr= va_arg(params, GPUNodeLink**);
1304                                 GPU_node_output(node, function->paramtype[i], "", linkptr);
1305                         }
1306                         else
1307                                 totout--;
1308                 }
1309                 else {
1310                         if (totin == 0) {
1311                                 link= va_arg(params, GPUNodeLink*);
1312                                 if (link->socket)
1313                                         gpu_node_input_socket(node, link->socket);
1314                                 else
1315                                         gpu_node_input_link(node, link, function->paramtype[i]);
1316                         }
1317                         else
1318                                 totin--;
1319                 }
1320         }
1321         va_end(params);
1322
1323         GPU_node_end(node);
1324
1325         gpu_material_add_node(mat, node);
1326         
1327         return 1;
1328 }
1329
1330 int GPU_link_changed(GPUNodeLink *link)
1331 {
1332         GPUNode *node;
1333         GPUInput *input;
1334         const char *name;
1335
1336         if (link->output) {
1337                 node = link->output->node;
1338                 name = node->name;
1339
1340                 if (strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) {
1341                         input = node->inputs.first;
1342                         return (input->link != NULL);
1343                 }
1344
1345                 return 1;
1346         }
1347         else
1348                 return 0;
1349 }
1350
1351 /* Pass create/free */
1352
1353 static void gpu_nodes_tag(GPUNodeLink *link)
1354 {
1355         GPUNode *node;
1356         GPUInput *input;
1357
1358         if (!link->output)
1359                 return;
1360
1361         node = link->output->node;
1362         if (node->tag)
1363                 return;
1364         
1365         node->tag= 1;
1366         for (input=node->inputs.first; input; input=input->next)
1367                 if (input->link)
1368                         gpu_nodes_tag(input->link);
1369 }
1370
1371 static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
1372 {
1373         GPUNode *node, *next;
1374
1375         for (node=nodes->first; node; node=node->next)
1376                 node->tag= 0;
1377
1378         gpu_nodes_tag(outlink);
1379
1380         for (node=nodes->first; node; node=next) {
1381                 next = node->next;
1382
1383                 if (!node->tag) {
1384                         BLI_remlink(nodes, node);
1385                         GPU_node_free(node);
1386                 }
1387         }
1388 }
1389
1390 GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttribs *attribs, int *builtins, const char *name)
1391 {
1392         GPUShader *shader;
1393         GPUPass *pass;
1394         char *vertexcode, *fragmentcode;
1395
1396         /*if (!FUNCTION_LIB) {
1397                 GPU_nodes_free(nodes);
1398                 return NULL;
1399         }*/
1400
1401         /* prune unused nodes */
1402         gpu_nodes_prune(nodes, outlink);
1403
1404         gpu_nodes_get_vertex_attributes(nodes, attribs);
1405         gpu_nodes_get_builtin_flag(nodes, builtins);
1406
1407         /* generate code and compile with opengl */
1408         fragmentcode = code_generate_fragment(nodes, outlink->output, name);
1409         vertexcode = code_generate_vertex(nodes);
1410         shader = GPU_shader_create(vertexcode, fragmentcode, glsl_material_library, NULL);
1411
1412         /* failed? */
1413         if (!shader) {
1414                 memset(attribs, 0, sizeof(*attribs));
1415                 memset(builtins, 0, sizeof(*builtins));
1416                 GPU_nodes_free(nodes);
1417                 return NULL;
1418         }
1419         
1420         /* create pass */
1421         pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
1422
1423         pass->output = outlink->output;
1424         pass->shader = shader;
1425         pass->fragmentcode = fragmentcode;
1426         pass->vertexcode = vertexcode;
1427         pass->libcode = glsl_material_library;
1428
1429         /* extract dynamic inputs and throw away nodes */
1430         GPU_nodes_extract_dynamic_inputs(pass, nodes);
1431         GPU_nodes_free(nodes);
1432
1433         return pass;
1434 }
1435
1436 void GPU_pass_free(GPUPass *pass)
1437 {
1438         GPU_shader_free(pass->shader);
1439         GPU_inputs_free(&pass->inputs);
1440         if (pass->fragmentcode)
1441                 MEM_freeN(pass->fragmentcode);
1442         if (pass->vertexcode)
1443                 MEM_freeN(pass->vertexcode);
1444         MEM_freeN(pass);
1445 }
1446