Depth of field high quality:
[blender.git] / source / blender / gpu / intern / gpu_codegen.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2005 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Brecht Van Lommel.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/gpu/intern/gpu_codegen.c
29  *  \ingroup gpu
30  *
31  * Convert material node-trees to GLSL.
32  */
33
34 #include "MEM_guardedalloc.h"
35
36 #include "DNA_customdata_types.h"
37 #include "DNA_image_types.h"
38 #include "DNA_material_types.h"
39
40 #include "BLI_blenlib.h"
41 #include "BLI_utildefines.h"
42 #include "BLI_dynstr.h"
43 #include "BLI_ghash.h"
44
45 #include "GPU_glew.h"
46 #include "GPU_material.h"
47 #include "GPU_extensions.h"
48
49 #include "BLI_sys_types.h" // for intptr_t support
50
51 #include "gpu_codegen.h"
52
53 #include <string.h>
54 #include <stdarg.h>
55
56 extern char datatoc_gpu_shader_material_glsl[];
57 extern char datatoc_gpu_shader_vertex_glsl[];
58 extern char datatoc_gpu_shader_vertex_world_glsl[];
59
60
61 static char *glsl_material_library = NULL;
62
63
64 /* type definitions and constants */
65
66 enum {
67         MAX_FUNCTION_NAME = 64
68 };
69 enum {
70         MAX_PARAMETER = 32
71 };
72
73 typedef enum {
74         FUNCTION_QUAL_IN,
75         FUNCTION_QUAL_OUT,
76         FUNCTION_QUAL_INOUT
77 } GPUFunctionQual;
78
79 typedef struct GPUFunction {
80         char name[MAX_FUNCTION_NAME];
81         GPUType paramtype[MAX_PARAMETER];
82         GPUFunctionQual paramqual[MAX_PARAMETER];
83         int totparam;
84 } GPUFunction;
85
86 /* Indices match the GPUType enum */
87 static const char *GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4",
88         NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4"};
89
90 /* GLSL code parsing for finding function definitions.
91  * These are stored in a hash for lookup when creating a material. */
92
93 static GHash *FUNCTION_HASH= NULL;
94 /* static char *FUNCTION_PROTOTYPES= NULL;
95  * static GPUShader *FUNCTION_LIB= NULL;*/
96
97 static int gpu_str_prefix(const char *str, const char *prefix)
98 {
99         while (*str && *prefix) {
100                 if (*str != *prefix)
101                         return 0;
102
103                 str++;
104                 prefix++;
105         }
106         
107         return (*prefix == '\0');
108 }
109
110 static char *gpu_str_skip_token(char *str, char *token, int max)
111 {
112         int len = 0;
113
114         /* skip a variable/function name */
115         while (*str) {
116                 if (ELEM(*str, ' ', '(', ')', ',', '\t', '\n', '\r'))
117                         break;
118                 else {
119                         if (token && len < max-1) {
120                                 *token= *str;
121                                 token++;
122                                 len++;
123                         }
124                         str++;
125                 }
126         }
127
128         if (token)
129                 *token= '\0';
130
131         /* skip the next special characters:
132          * note the missing ')' */
133         while (*str) {
134                 if (ELEM(*str, ' ', '(', ',', '\t', '\n', '\r'))
135                         str++;
136                 else
137                         break;
138         }
139
140         return str;
141 }
142
143 static void gpu_parse_functions_string(GHash *hash, char *code)
144 {
145         GPUFunction *function;
146         GPUType type;
147         GPUFunctionQual qual;
148         int i;
149
150         while ((code = strstr(code, "void "))) {
151                 function = MEM_callocN(sizeof(GPUFunction), "GPUFunction");
152
153                 code = gpu_str_skip_token(code, NULL, 0);
154                 code = gpu_str_skip_token(code, function->name, MAX_FUNCTION_NAME);
155
156                 /* get parameters */
157                 while (*code && *code != ')') {
158                         /* test if it's an input or output */
159                         qual = FUNCTION_QUAL_IN;
160                         if (gpu_str_prefix(code, "out "))
161                                 qual = FUNCTION_QUAL_OUT;
162                         if (gpu_str_prefix(code, "inout "))
163                                 qual = FUNCTION_QUAL_INOUT;
164                         if ((qual != FUNCTION_QUAL_IN) || gpu_str_prefix(code, "in "))
165                                 code = gpu_str_skip_token(code, NULL, 0);
166
167                         /* test for type */
168                         type= GPU_NONE;
169                         for (i=1; i<=16; i++) {
170                                 if (GPU_DATATYPE_STR[i] && gpu_str_prefix(code, GPU_DATATYPE_STR[i])) {
171                                         type= i;
172                                         break;
173                                 }
174                         }
175
176                         if (!type && gpu_str_prefix(code, "sampler2DShadow"))
177                                 type= GPU_SHADOW2D;
178                         if (!type && gpu_str_prefix(code, "sampler2D"))
179                                 type= GPU_TEX2D;
180
181                         if (type) {
182                                 /* add parameter */
183                                 code = gpu_str_skip_token(code, NULL, 0);
184                                 code = gpu_str_skip_token(code, NULL, 0);
185                                 function->paramqual[function->totparam]= qual;
186                                 function->paramtype[function->totparam]= type;
187                                 function->totparam++;
188                         }
189                         else {
190                                 fprintf(stderr, "GPU invalid function parameter in %s.\n", function->name);
191                                 break;
192                         }
193                 }
194
195                 if (function->name[0] == '\0' || function->totparam == 0) {
196                         fprintf(stderr, "GPU functions parse error.\n");
197                         MEM_freeN(function);
198                         break;
199                 }
200
201                 BLI_ghash_insert(hash, function->name, function);
202         }
203 }
204
205 #if 0
206 static char *gpu_generate_function_prototyps(GHash *hash)
207 {
208         DynStr *ds = BLI_dynstr_new();
209         GHashIterator *ghi;
210         GPUFunction *function;
211         char *name, *prototypes;
212         int a;
213         
214         /* automatically generate function prototypes to add to the top of the
215          * generated code, to avoid have to add the actual code & recompile all */
216         ghi = BLI_ghashIterator_new(hash);
217
218         for (; !BLI_ghashIterator_done(ghi); BLI_ghashIterator_step(ghi)) {
219                 name = BLI_ghashIterator_getValue(ghi);
220                 function = BLI_ghashIterator_getValue(ghi);
221
222                 BLI_dynstr_appendf(ds, "void %s(", name);
223                 for (a=0; a<function->totparam; a++) {
224                         if (function->paramqual[a] == FUNCTION_QUAL_OUT)
225                                 BLI_dynstr_append(ds, "out ");
226                         else if (function->paramqual[a] == FUNCTION_QUAL_INOUT)
227                                 BLI_dynstr_append(ds, "inout ");
228
229                         if (function->paramtype[a] == GPU_TEX2D)
230                                 BLI_dynstr_append(ds, "sampler2D");
231                         else if (function->paramtype[a] == GPU_SHADOW2D)
232                                 BLI_dynstr_append(ds, "sampler2DShadow");
233                         else
234                                 BLI_dynstr_append(ds, GPU_DATATYPE_STR[function->paramtype[a]]);
235                                 
236                         //BLI_dynstr_appendf(ds, " param%d", a);
237                         
238                         if (a != function->totparam-1)
239                                 BLI_dynstr_append(ds, ", ");
240                 }
241                 BLI_dynstr_append(ds, ");\n");
242         }
243
244         BLI_dynstr_append(ds, "\n");
245
246         prototypes = BLI_dynstr_get_cstring(ds);
247         BLI_dynstr_free(ds);
248
249         return prototypes;
250 }
251 #endif
252
253 static GPUFunction *gpu_lookup_function(const char *name)
254 {
255         if (!FUNCTION_HASH) {
256                 FUNCTION_HASH = BLI_ghash_str_new("GPU_lookup_function gh");
257                 gpu_parse_functions_string(FUNCTION_HASH, glsl_material_library);
258         }
259
260         return BLI_ghash_lookup(FUNCTION_HASH, (const void *)name);
261 }
262
263 void gpu_codegen_init(void)
264 {
265         GPU_code_generate_glsl_lib();
266 }
267
268 void gpu_codegen_exit(void)
269 {
270         extern Material defmaterial;    // render module abuse...
271
272         if (defmaterial.gpumaterial.first)
273                 GPU_material_free(&defmaterial.gpumaterial);
274
275         if (FUNCTION_HASH) {
276                 BLI_ghash_free(FUNCTION_HASH, NULL, MEM_freeN);
277                 FUNCTION_HASH = NULL;
278         }
279
280         GPU_shader_free_builtin_shaders();
281
282         if (glsl_material_library) {
283                 MEM_freeN(glsl_material_library);
284                 glsl_material_library = NULL;
285         }
286
287         /*if (FUNCTION_PROTOTYPES) {
288                 MEM_freeN(FUNCTION_PROTOTYPES);
289                 FUNCTION_PROTOTYPES = NULL;
290         }*/
291         /*if (FUNCTION_LIB) {
292                 GPU_shader_free(FUNCTION_LIB);
293                 FUNCTION_LIB = NULL;
294         }*/
295 }
296
297 /* GLSL code generation */
298
299 static void codegen_convert_datatype(DynStr *ds, int from, int to, const char *tmp, int id)
300 {
301         char name[1024];
302
303         BLI_snprintf(name, sizeof(name), "%s%d", tmp, id);
304
305         if (from == to) {
306                 BLI_dynstr_append(ds, name);
307         }
308         else if (to == GPU_FLOAT) {
309                 if (from == GPU_VEC4)
310                         BLI_dynstr_appendf(ds, "dot(%s.rgb, vec3(0.35, 0.45, 0.2))", name);
311                 else if (from == GPU_VEC3)
312                         BLI_dynstr_appendf(ds, "dot(%s, vec3(0.33))", name);
313                 else if (from == GPU_VEC2)
314                         BLI_dynstr_appendf(ds, "%s.r", name);
315         }
316         else if (to == GPU_VEC2) {
317                 if (from == GPU_VEC4)
318                         BLI_dynstr_appendf(ds, "vec2(dot(%s.rgb, vec3(0.35, 0.45, 0.2)), %s.a)", name, name);
319                 else if (from == GPU_VEC3)
320                         BLI_dynstr_appendf(ds, "vec2(dot(%s.rgb, vec3(0.33)), 1.0)", name);
321                 else if (from == GPU_FLOAT)
322                         BLI_dynstr_appendf(ds, "vec2(%s, 1.0)", name);
323         }
324         else if (to == GPU_VEC3) {
325                 if (from == GPU_VEC4)
326                         BLI_dynstr_appendf(ds, "%s.rgb", name);
327                 else if (from == GPU_VEC2)
328                         BLI_dynstr_appendf(ds, "vec3(%s.r, %s.r, %s.r)", name, name, name);
329                 else if (from == GPU_FLOAT)
330                         BLI_dynstr_appendf(ds, "vec3(%s, %s, %s)", name, name, name);
331         }
332         else {
333                 if (from == GPU_VEC3)
334                         BLI_dynstr_appendf(ds, "vec4(%s, 1.0)", name);
335                 else if (from == GPU_VEC2)
336                         BLI_dynstr_appendf(ds, "vec4(%s.r, %s.r, %s.r, %s.g)", name, name, name, name);
337                 else if (from == GPU_FLOAT)
338                         BLI_dynstr_appendf(ds, "vec4(%s, %s, %s, 1.0)", name, name, name);
339         }
340 }
341
342 static void codegen_print_datatype(DynStr *ds, const GPUType type, float *data)
343 {
344         int i;
345
346         BLI_dynstr_appendf(ds, "%s(", GPU_DATATYPE_STR[type]);
347
348         for (i=0; i<type; i++) {
349                 BLI_dynstr_appendf(ds, "%f", data[i]);
350                 if (i == type-1)
351                         BLI_dynstr_append(ds, ")");
352                 else
353                         BLI_dynstr_append(ds, ", ");
354         }
355 }
356
357 static int codegen_input_has_texture(GPUInput *input)
358 {
359         if (input->link)
360                 return 0;
361         else if (input->ima || input->prv)
362                 return 1;
363         else
364                 return input->tex != NULL;
365 }
366
367 const char *GPU_builtin_name(GPUBuiltin builtin)
368 {
369         if (builtin == GPU_VIEW_MATRIX)
370                 return "unfviewmat";
371         else if (builtin == GPU_OBJECT_MATRIX)
372                 return "unfobmat";
373         else if (builtin == GPU_INVERSE_VIEW_MATRIX)
374                 return "unfinvviewmat";
375         else if (builtin == GPU_INVERSE_OBJECT_MATRIX)
376                 return "unfinvobmat";
377         else if (builtin == GPU_VIEW_POSITION)
378                 return "varposition";
379         else if (builtin == GPU_VIEW_NORMAL)
380                 return "varnormal";
381         else if (builtin == GPU_OBCOLOR)
382                 return "unfobcolor";
383         else if (builtin == GPU_AUTO_BUMPSCALE)
384                 return "unfobautobumpscale";
385         else if (builtin == GPU_CAMERA_TEXCO_FACTORS)
386                 return "unfcameratexfactors";
387         else
388                 return "";
389 }
390
391 /* assign only one texid per buffer to avoid sampling the same texture twice */
392 static void codegen_set_texid(GHash *bindhash, GPUInput *input, int *texid, void *key)
393 {
394         if (BLI_ghash_haskey(bindhash, key)) {
395                 /* Reuse existing texid */
396                 input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, key));
397         }
398         else {
399                 /* Allocate new texid */
400                 input->texid = *texid;
401                 (*texid)++;
402                 input->bindtex = true;
403                 BLI_ghash_insert(bindhash, key, SET_INT_IN_POINTER(input->texid));
404         }
405 }
406
407 static void codegen_set_unique_ids(ListBase *nodes)
408 {
409         GHash *bindhash, *definehash;
410         GPUNode *node;
411         GPUInput *input;
412         GPUOutput *output;
413         int id = 1, texid = 0;
414
415         bindhash= BLI_ghash_ptr_new("codegen_set_unique_ids1 gh");
416         definehash= BLI_ghash_ptr_new("codegen_set_unique_ids2 gh");
417
418         for (node=nodes->first; node; node=node->next) {
419                 for (input=node->inputs.first; input; input=input->next) {
420                         /* set id for unique names of uniform variables */
421                         input->id = id++;
422                         input->bindtex = false;
423                         input->definetex = false;
424
425                         /* set texid used for settings texture slot with multitexture */
426                         if (codegen_input_has_texture(input) &&
427                             ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL)))
428                         {
429                                 /* assign only one texid per buffer to avoid sampling
430                                  * the same texture twice */
431                                 if (input->link) {
432                                         /* input is texture from buffer */
433                                         codegen_set_texid(bindhash, input, &texid, input->link);
434                                 }
435                                 else if (input->ima) {
436                                         /* input is texture from image */
437                                         codegen_set_texid(bindhash, input, &texid, input->ima);
438                                 }
439                                 else if (input->prv) {
440                                         /* input is texture from preview render */
441                                         codegen_set_texid(bindhash, input, &texid, input->prv);
442                                 }
443                                 else if (input->tex) {
444                                         /* input is user created texture, check tex pointer */
445                                         codegen_set_texid(bindhash, input, &texid, input->tex);
446                                 }
447
448                                 /* make sure this pixel is defined exactly once */
449                                 if (input->source == GPU_SOURCE_TEX_PIXEL) {
450                                         if (input->ima) {
451                                                 if (!BLI_ghash_haskey(definehash, input->ima)) {
452                                                         input->definetex = true;
453                                                         BLI_ghash_insert(definehash, input->ima, SET_INT_IN_POINTER(input->texid));
454                                                 }
455                                         }
456                                         else {
457                                                 if (!BLI_ghash_haskey(definehash, input->link)) {
458                                                         input->definetex = true;
459                                                         BLI_ghash_insert(definehash, input->link, SET_INT_IN_POINTER(input->texid));
460                                                 }
461                                         }
462                                 }
463                         }
464                 }
465
466                 for (output=node->outputs.first; output; output=output->next)
467                         /* set id for unique names of tmp variables storing output */
468                         output->id = id++;
469         }
470
471         BLI_ghash_free(bindhash, NULL, NULL);
472         BLI_ghash_free(definehash, NULL, NULL);
473 }
474
475 static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
476 {
477         GPUNode *node;
478         GPUInput *input;
479         const char *name;
480         int builtins = 0;
481
482         /* print uniforms */
483         for (node=nodes->first; node; node=node->next) {
484                 for (input=node->inputs.first; input; input=input->next) {
485                         if ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL)) {
486                                 /* create exactly one sampler for each texture */
487                                 if (codegen_input_has_texture(input) && input->bindtex)
488                                         BLI_dynstr_appendf(ds, "uniform %s samp%d;\n",
489                                                 (input->textype == GPU_TEX2D) ? "sampler2D" : "sampler2DShadow",
490                                                 input->texid);
491                         }
492                         else if (input->source == GPU_SOURCE_BUILTIN) {
493                                 /* only define each builting uniform/varying once */
494                                 if (!(builtins & input->builtin)) {
495                                         builtins |= input->builtin;
496                                         name = GPU_builtin_name(input->builtin);
497
498                                         if (gpu_str_prefix(name, "unf")) {
499                                                 BLI_dynstr_appendf(ds, "uniform %s %s;\n",
500                                                         GPU_DATATYPE_STR[input->type], name);
501                                         }
502                                         else {
503                                                 BLI_dynstr_appendf(ds, "varying %s %s;\n",
504                                                         GPU_DATATYPE_STR[input->type], name);
505                                         }
506                                 }
507                         }
508                         else if (input->source == GPU_SOURCE_VEC_UNIFORM) {
509                                 if (input->dynamicvec) {
510                                         /* only create uniforms for dynamic vectors */
511                                         BLI_dynstr_appendf(ds, "uniform %s unf%d;\n",
512                                                 GPU_DATATYPE_STR[input->type], input->id);
513                                 }
514                                 else {
515                                         /* for others use const so the compiler can do folding */
516                                         BLI_dynstr_appendf(ds, "const %s cons%d = ",
517                                                 GPU_DATATYPE_STR[input->type], input->id);
518                                         codegen_print_datatype(ds, input->type, input->vec);
519                                         BLI_dynstr_append(ds, ";\n");
520                                 }
521                         }
522                         else if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
523                                 BLI_dynstr_appendf(ds, "varying %s var%d;\n",
524                                         GPU_DATATYPE_STR[input->type], input->attribid);
525                         }
526                 }
527         }
528
529         BLI_dynstr_append(ds, "\n");
530
531         return builtins;
532 }
533
534 static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
535 {
536         GPUNode *node;
537         GPUInput *input;
538         GPUOutput *output;
539
540         for (node=nodes->first; node; node=node->next) {
541                 /* load pixels from textures */
542                 for (input=node->inputs.first; input; input=input->next) {
543                         if (input->source == GPU_SOURCE_TEX_PIXEL) {
544                                 if (codegen_input_has_texture(input) && input->definetex) {
545                                         BLI_dynstr_appendf(ds, "\tvec4 tex%d = texture2D(", input->texid);
546                                         BLI_dynstr_appendf(ds, "samp%d, gl_TexCoord[%d].st);\n",
547                                                 input->texid, input->texid);
548                                 }
549                         }
550                 }
551
552                 /* declare temporary variables for node output storage */
553                 for (output=node->outputs.first; output; output=output->next)
554                         BLI_dynstr_appendf(ds, "\t%s tmp%d;\n",
555                                 GPU_DATATYPE_STR[output->type], output->id);
556         }
557
558         BLI_dynstr_append(ds, "\n");
559 }
560
561 static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *finaloutput)
562 {
563         GPUNode *node;
564         GPUInput *input;
565         GPUOutput *output;
566
567         for (node=nodes->first; node; node=node->next) {
568                 BLI_dynstr_appendf(ds, "\t%s(", node->name);
569                 
570                 for (input=node->inputs.first; input; input=input->next) {
571                         if (input->source == GPU_SOURCE_TEX) {
572                                 BLI_dynstr_appendf(ds, "samp%d", input->texid);
573                                 if (input->link)
574                                         BLI_dynstr_appendf(ds, ", gl_TexCoord[%d].st", input->texid);
575                         }
576                         else if (input->source == GPU_SOURCE_TEX_PIXEL) {
577                                 codegen_convert_datatype(ds, input->link->output->type, input->type,
578                                         "tmp", input->link->output->id);
579                         }
580                         else if (input->source == GPU_SOURCE_BUILTIN) {
581                                 if (input->builtin == GPU_VIEW_NORMAL)
582                                         BLI_dynstr_append(ds, "facingnormal");
583                                 else
584                                         BLI_dynstr_append(ds, GPU_builtin_name(input->builtin));
585                         }
586                         else if (input->source == GPU_SOURCE_VEC_UNIFORM) {
587                                 if (input->dynamicvec)
588                                         BLI_dynstr_appendf(ds, "unf%d", input->id);
589                                 else
590                                         BLI_dynstr_appendf(ds, "cons%d", input->id);
591                         }
592                         else if (input->source == GPU_SOURCE_ATTRIB) {
593                                 BLI_dynstr_appendf(ds, "var%d", input->attribid);
594                         }
595                         else if (input->source == GPU_SOURCE_OPENGL_BUILTIN) {
596                                 if (input->oglbuiltin == GPU_MATCAP_NORMAL)
597                                         BLI_dynstr_append(ds, "gl_SecondaryColor");
598                                 else if (input->oglbuiltin == GPU_COLOR)
599                                         BLI_dynstr_append(ds, "gl_Color");
600                         }
601
602                         BLI_dynstr_append(ds, ", ");
603                 }
604
605                 for (output=node->outputs.first; output; output=output->next) {
606                         BLI_dynstr_appendf(ds, "tmp%d", output->id);
607                         if (output->next)
608                                 BLI_dynstr_append(ds, ", ");
609                 }
610
611                 BLI_dynstr_append(ds, ");\n");
612         }
613
614         BLI_dynstr_append(ds, "\n\tgl_FragColor = ");
615         codegen_convert_datatype(ds, finaloutput->type, GPU_VEC4, "tmp", finaloutput->id);
616         BLI_dynstr_append(ds, ";\n");
617 }
618
619 static char *code_generate_fragment(ListBase *nodes, GPUOutput *output)
620 {
621         DynStr *ds = BLI_dynstr_new();
622         char *code;
623         int builtins;
624
625         /*BLI_dynstr_append(ds, FUNCTION_PROTOTYPES);*/
626
627         codegen_set_unique_ids(nodes);
628         builtins = codegen_print_uniforms_functions(ds, nodes);
629
630         //if (G.debug & G_DEBUG)
631         //      BLI_dynstr_appendf(ds, "/* %s */\n", name);
632
633         BLI_dynstr_append(ds, "void main(void)\n");
634         BLI_dynstr_append(ds, "{\n");
635
636         if (builtins & GPU_VIEW_NORMAL)
637                 BLI_dynstr_append(ds, "\tvec3 facingnormal = (gl_FrontFacing)? varnormal: -varnormal;\n");
638         
639         codegen_declare_tmps(ds, nodes);
640         codegen_call_functions(ds, nodes, output);
641
642         BLI_dynstr_append(ds, "}\n");
643
644         /* create shader */
645         code = BLI_dynstr_get_cstring(ds);
646         BLI_dynstr_free(ds);
647
648         //if (G.debug & G_DEBUG) printf("%s\n", code);
649
650         return code;
651 }
652
653 static char *code_generate_vertex(ListBase *nodes, const GPUMatType type)
654 {
655         DynStr *ds = BLI_dynstr_new();
656         GPUNode *node;
657         GPUInput *input;
658         char *code;
659         char *vertcode;
660         
661         for (node=nodes->first; node; node=node->next) {
662                 for (input=node->inputs.first; input; input=input->next) {
663                         if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
664                                 BLI_dynstr_appendf(ds, "attribute %s att%d;\n",
665                                         GPU_DATATYPE_STR[input->type], input->attribid);
666                                 BLI_dynstr_appendf(ds, "varying %s var%d;\n",
667                                         GPU_DATATYPE_STR[input->type], input->attribid);
668                         }
669                 }
670         }
671
672         BLI_dynstr_append(ds, "\n");
673
674         switch (type) {
675                 case GPU_MATERIAL_TYPE_MESH:
676                         vertcode = datatoc_gpu_shader_vertex_glsl;
677                         break;
678                 case GPU_MATERIAL_TYPE_WORLD:
679                         vertcode = datatoc_gpu_shader_vertex_world_glsl;
680                         break;
681                 default:
682                         fprintf(stderr, "invalid material type, set one after GPU_material_construct_begin\n");
683                         break;
684         }
685
686         BLI_dynstr_append(ds, vertcode);
687         
688         for (node=nodes->first; node; node=node->next)
689                 for (input=node->inputs.first; input; input=input->next)
690                         if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
691                                 if (input->attribtype == CD_TANGENT) { /* silly exception */
692                                         BLI_dynstr_appendf(ds, "\tvar%d.xyz = normalize(gl_NormalMatrix * att%d.xyz);\n", input->attribid, input->attribid);
693                                         BLI_dynstr_appendf(ds, "\tvar%d.w = att%d.w;\n", input->attribid, input->attribid);
694                                 }
695                                 else
696                                         BLI_dynstr_appendf(ds, "\tvar%d = att%d;\n", input->attribid, input->attribid);
697                         }
698                         /* unfortunately special handling is needed here because we abuse gl_Color/gl_SecondaryColor flat shading */
699                         else if (input->source == GPU_SOURCE_OPENGL_BUILTIN) {
700                                 if (input->oglbuiltin == GPU_MATCAP_NORMAL) {
701                                         /* remap to 0.0 - 1.0 range. This is done because OpenGL 2.0 clamps colors
702                                          * between shader stages and we want the full range of the normal */
703                                         BLI_dynstr_appendf(ds, "\tvec3 matcapcol = vec3(0.5, 0.5, 0.5) * varnormal + vec3(0.5, 0.5, 0.5);\n");
704                                         BLI_dynstr_appendf(ds, "\tgl_FrontSecondaryColor = vec4(matcapcol, 1.0);\n");
705                                 }
706                                 else if (input->oglbuiltin == GPU_COLOR) {
707                                         BLI_dynstr_appendf(ds, "\tgl_FrontColor = gl_Color;\n");
708                                 }
709                         }
710
711         BLI_dynstr_append(ds, "}\n\n");
712
713         code = BLI_dynstr_get_cstring(ds);
714
715         BLI_dynstr_free(ds);
716
717         //if (G.debug & G_DEBUG) printf("%s\n", code);
718
719         return code;
720 }
721
722 void GPU_code_generate_glsl_lib(void)
723 {
724         DynStr *ds;
725
726         /* only initialize the library once */
727         if (glsl_material_library)
728                 return;
729
730         ds = BLI_dynstr_new();
731
732         BLI_dynstr_append(ds, datatoc_gpu_shader_material_glsl);
733
734
735         glsl_material_library = BLI_dynstr_get_cstring(ds);
736
737         BLI_dynstr_free(ds);
738 }
739
740
741 /* GPU pass binding/unbinding */
742
743 GPUShader *GPU_pass_shader(GPUPass *pass)
744 {
745         return pass->shader;
746 }
747
748 static void gpu_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
749 {
750         GPUShader *shader = pass->shader;
751         GPUNode *node;
752         GPUInput *next, *input;
753         ListBase *inputs = &pass->inputs;
754         int extract, z;
755
756         memset(inputs, 0, sizeof(*inputs));
757
758         if (!shader)
759                 return;
760
761         GPU_shader_bind(shader);
762
763         for (node=nodes->first; node; node=node->next) {
764                 z = 0;
765                 for (input=node->inputs.first; input; input=next, z++) {
766                         next = input->next;
767
768                         /* attributes don't need to be bound, they already have
769                          * an id that the drawing functions will use */
770                         if (input->source == GPU_SOURCE_ATTRIB ||
771                             input->source == GPU_SOURCE_BUILTIN ||
772                             input->source == GPU_SOURCE_OPENGL_BUILTIN)
773                         {
774                                 continue;
775                         }
776
777                         if (input->ima || input->tex || input->prv)
778                                 BLI_snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid);
779                         else
780                                 BLI_snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id);
781
782                         /* pass non-dynamic uniforms to opengl */
783                         extract = 0;
784
785                         if (input->ima || input->tex || input->prv) {
786                                 if (input->bindtex)
787                                         extract = 1;
788                         }
789                         else if (input->dynamicvec)
790                                 extract = 1;
791
792                         if (extract)
793                                 input->shaderloc = GPU_shader_get_uniform(shader, input->shadername);
794
795                         /* extract nodes */
796                         if (extract) {
797                                 BLI_remlink(&node->inputs, input);
798                                 BLI_addtail(inputs, input);
799                         }
800                 }
801         }
802
803         GPU_shader_unbind();
804 }
805
806 void GPU_pass_bind(GPUPass *pass, double time, int mipmap)
807 {
808         GPUInput *input;
809         GPUShader *shader = pass->shader;
810         ListBase *inputs = &pass->inputs;
811
812         if (!shader)
813                 return;
814
815         GPU_shader_bind(shader);
816
817         /* now bind the textures */
818         for (input=inputs->first; input; input=input->next) {
819                 if (input->ima)
820                         input->tex = GPU_texture_from_blender(input->ima, input->iuser, input->image_isdata, time, mipmap);
821                 else if (input->prv)
822                         input->tex = GPU_texture_from_preview(input->prv, mipmap);
823
824                 if (input->tex && input->bindtex) {
825                         GPU_texture_bind(input->tex, input->texid);
826                         GPU_shader_uniform_texture(shader, input->shaderloc, input->tex);
827                 }
828                         
829         }
830 }
831
832 void GPU_pass_update_uniforms(GPUPass *pass)
833 {
834         GPUInput *input;
835         GPUShader *shader = pass->shader;
836         ListBase *inputs = &pass->inputs;
837
838         if (!shader)
839                 return;
840
841         /* pass dynamic inputs to opengl, others were removed */
842         for (input=inputs->first; input; input=input->next)
843                 if (!(input->ima || input->tex || input->prv))
844                         GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1,
845                                 input->dynamicvec);
846 }
847
848 void GPU_pass_unbind(GPUPass *pass)
849 {
850         GPUInput *input;
851         GPUShader *shader = pass->shader;
852         ListBase *inputs = &pass->inputs;
853
854         if (!shader)
855                 return;
856
857         for (input=inputs->first; input; input=input->next) {
858                 if (input->tex && input->bindtex)
859                         GPU_texture_unbind(input->tex);
860
861                 if (input->ima || input->prv)
862                         input->tex = NULL;
863         }
864         
865         GPU_shader_unbind();
866 }
867
868 /* Node Link Functions */
869
870 static GPUNodeLink *GPU_node_link_create(void)
871 {
872         GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink");
873         link->type = GPU_NONE;
874         link->users++;
875
876         return link;
877 }
878
879 static void gpu_node_link_free(GPUNodeLink *link)
880 {
881         link->users--;
882
883         if (link->users < 0)
884                 fprintf(stderr, "GPU_node_link_free: negative refcount\n");
885         
886         if (link->users == 0) {
887                 if (link->output)
888                         link->output->link = NULL;
889                 MEM_freeN(link);
890         }
891 }
892
893 /* Node Functions */
894
895 static GPUNode *GPU_node_begin(const char *name)
896 {
897         GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode");
898
899         node->name= name;
900
901         return node;
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 (STREQ(name, "set_value") || STREQ(name, "set_rgb")) {
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 = true;
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, GPU_HDR_NONE, 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 == GPU_NODE_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, 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                                             STREQ(attribs->layer[a].name, input->attribname))
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, GPUDynamicType dynamictype, void *data)
1169 {
1170         GPUNodeLink *link = GPU_node_link_create();
1171
1172         link->ptr1= num;
1173         link->ptr2= data;
1174         link->dynamic= true;
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 = GPU_NODE_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= GPU_NODE_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 = true;
1209         link->texturesize = size;
1210         link->ptr1= pixels;
1211
1212         return link;
1213 }
1214
1215 GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex, GPUDynamicType dynamictype, void *data)
1216 {
1217         GPUNodeLink *link = GPU_node_link_create();
1218
1219         link->dynamic = true;
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_material_add_node(mat, node);
1275
1276         return 1;
1277 }
1278
1279 bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...)
1280 {
1281         GPUNode *node;
1282         GPUFunction *function;
1283         GPUNodeLink *link, **linkptr;
1284         va_list params;
1285         int i, totin, totout;
1286
1287         function = gpu_lookup_function(name);
1288         if (!function) {
1289                 fprintf(stderr, "GPU failed to find function %s\n", name);
1290                 return 0;
1291         }
1292
1293         node = GPU_node_begin(name);
1294         totin = 0;
1295         totout = 0;
1296
1297         if (in) {
1298                 for (i = 0; in[i].type != GPU_NONE; i++) {
1299                         gpu_node_input_socket(node, &in[i]);
1300                         totin++;
1301                 }
1302         }
1303         
1304         if (out) {
1305                 for (i = 0; out[i].type != GPU_NONE; i++) {
1306                         gpu_node_output(node, out[i].type, &out[i].link);
1307                         totout++;
1308                 }
1309         }
1310
1311         va_start(params, out);
1312         for (i=0; i<function->totparam; i++) {
1313                 if (function->paramqual[i] != FUNCTION_QUAL_IN) {
1314                         if (totout == 0) {
1315                                 linkptr= va_arg(params, GPUNodeLink**);
1316                                 gpu_node_output(node, function->paramtype[i], linkptr);
1317                         }
1318                         else
1319                                 totout--;
1320                 }
1321                 else {
1322                         if (totin == 0) {
1323                                 link= va_arg(params, GPUNodeLink*);
1324                                 if (link->socket)
1325                                         gpu_node_input_socket(node, link->socket);
1326                                 else
1327                                         gpu_node_input_link(node, link, function->paramtype[i]);
1328                         }
1329                         else
1330                                 totin--;
1331                 }
1332         }
1333         va_end(params);
1334
1335         gpu_material_add_node(mat, node);
1336         
1337         return 1;
1338 }
1339
1340 int GPU_link_changed(GPUNodeLink *link)
1341 {
1342         GPUNode *node;
1343         GPUInput *input;
1344         const char *name;
1345
1346         if (link->output) {
1347                 node = link->output->node;
1348                 name = node->name;
1349
1350                 if (STREQ(name, "set_value") || STREQ(name, "set_rgb")) {
1351                         input = node->inputs.first;
1352                         return (input->link != NULL);
1353                 }
1354
1355                 return 1;
1356         }
1357         else
1358                 return 0;
1359 }
1360
1361 /* Pass create/free */
1362
1363 static void gpu_nodes_tag(GPUNodeLink *link)
1364 {
1365         GPUNode *node;
1366         GPUInput *input;
1367
1368         if (!link->output)
1369                 return;
1370
1371         node = link->output->node;
1372         if (node->tag)
1373                 return;
1374         
1375         node->tag = true;
1376         for (input=node->inputs.first; input; input=input->next)
1377                 if (input->link)
1378                         gpu_nodes_tag(input->link);
1379 }
1380
1381 static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
1382 {
1383         GPUNode *node, *next;
1384
1385         for (node=nodes->first; node; node=node->next)
1386                 node->tag = false;
1387
1388         gpu_nodes_tag(outlink);
1389
1390         for (node=nodes->first; node; node=next) {
1391                 next = node->next;
1392
1393                 if (!node->tag) {
1394                         BLI_remlink(nodes, node);
1395                         gpu_node_free(node);
1396                 }
1397         }
1398 }
1399
1400 GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink,
1401                                                    GPUVertexAttribs *attribs, int *builtins,
1402                                                    const GPUMatType type, const char *UNUSED(name))
1403 {
1404         GPUShader *shader;
1405         GPUPass *pass;
1406         char *vertexcode, *fragmentcode;
1407
1408         /*if (!FUNCTION_LIB) {
1409                 GPU_nodes_free(nodes);
1410                 return NULL;
1411         }*/
1412
1413         /* prune unused nodes */
1414         gpu_nodes_prune(nodes, outlink);
1415
1416         gpu_nodes_get_vertex_attributes(nodes, attribs);
1417         gpu_nodes_get_builtin_flag(nodes, builtins);
1418
1419         /* generate code and compile with opengl */
1420         fragmentcode = code_generate_fragment(nodes, outlink->output);
1421         vertexcode = code_generate_vertex(nodes, type);
1422         shader = GPU_shader_create(vertexcode, fragmentcode, NULL, glsl_material_library, NULL);
1423
1424         /* failed? */
1425         if (!shader) {
1426                 if (fragmentcode)
1427                         MEM_freeN(fragmentcode);
1428                 if (vertexcode)
1429                         MEM_freeN(vertexcode);
1430                 memset(attribs, 0, sizeof(*attribs));
1431                 memset(builtins, 0, sizeof(*builtins));
1432                 gpu_nodes_free(nodes);
1433                 return NULL;
1434         }
1435         
1436         /* create pass */
1437         pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
1438
1439         pass->output = outlink->output;
1440         pass->shader = shader;
1441         pass->fragmentcode = fragmentcode;
1442         pass->vertexcode = vertexcode;
1443         pass->libcode = glsl_material_library;
1444
1445         /* extract dynamic inputs and throw away nodes */
1446         gpu_nodes_extract_dynamic_inputs(pass, nodes);
1447         gpu_nodes_free(nodes);
1448
1449         return pass;
1450 }
1451
1452 void GPU_pass_free(GPUPass *pass)
1453 {
1454         GPU_shader_free(pass->shader);
1455         gpu_inputs_free(&pass->inputs);
1456         if (pass->fragmentcode)
1457                 MEM_freeN(pass->fragmentcode);
1458         if (pass->vertexcode)
1459                 MEM_freeN(pass->vertexcode);
1460         MEM_freeN(pass);
1461 }
1462