Debug GPU functionality from soc-viewport_fx by Jason Wilkins
[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 int GPU_bicubic_bump_support(void)
723 {
724         return GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0;
725 }
726
727 void GPU_code_generate_glsl_lib(void)
728 {
729         DynStr *ds;
730
731         /* only initialize the library once */
732         if (glsl_material_library)
733                 return;
734
735         ds = BLI_dynstr_new();
736
737         BLI_dynstr_append(ds, datatoc_gpu_shader_material_glsl);
738
739
740         glsl_material_library = BLI_dynstr_get_cstring(ds);
741
742         BLI_dynstr_free(ds);
743 }
744
745
746 /* GPU pass binding/unbinding */
747
748 GPUShader *GPU_pass_shader(GPUPass *pass)
749 {
750         return pass->shader;
751 }
752
753 static void gpu_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
754 {
755         GPUShader *shader = pass->shader;
756         GPUNode *node;
757         GPUInput *next, *input;
758         ListBase *inputs = &pass->inputs;
759         int extract, z;
760
761         memset(inputs, 0, sizeof(*inputs));
762
763         if (!shader)
764                 return;
765
766         GPU_shader_bind(shader);
767
768         for (node=nodes->first; node; node=node->next) {
769                 z = 0;
770                 for (input=node->inputs.first; input; input=next, z++) {
771                         next = input->next;
772
773                         /* attributes don't need to be bound, they already have
774                          * an id that the drawing functions will use */
775                         if (input->source == GPU_SOURCE_ATTRIB ||
776                             input->source == GPU_SOURCE_BUILTIN ||
777                             input->source == GPU_SOURCE_OPENGL_BUILTIN)
778                         {
779                                 continue;
780                         }
781
782                         if (input->ima || input->tex || input->prv)
783                                 BLI_snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid);
784                         else
785                                 BLI_snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id);
786
787                         /* pass non-dynamic uniforms to opengl */
788                         extract = 0;
789
790                         if (input->ima || input->tex || input->prv) {
791                                 if (input->bindtex)
792                                         extract = 1;
793                         }
794                         else if (input->dynamicvec)
795                                 extract = 1;
796
797                         if (extract)
798                                 input->shaderloc = GPU_shader_get_uniform(shader, input->shadername);
799
800                         /* extract nodes */
801                         if (extract) {
802                                 BLI_remlink(&node->inputs, input);
803                                 BLI_addtail(inputs, input);
804                         }
805                 }
806         }
807
808         GPU_shader_unbind();
809 }
810
811 void GPU_pass_bind(GPUPass *pass, double time, int mipmap)
812 {
813         GPUInput *input;
814         GPUShader *shader = pass->shader;
815         ListBase *inputs = &pass->inputs;
816
817         if (!shader)
818                 return;
819
820         GPU_shader_bind(shader);
821
822         /* now bind the textures */
823         for (input=inputs->first; input; input=input->next) {
824                 if (input->ima)
825                         input->tex = GPU_texture_from_blender(input->ima, input->iuser, input->image_isdata, time, mipmap);
826                 else if (input->prv)
827                         input->tex = GPU_texture_from_preview(input->prv, mipmap);
828
829                 if (input->tex && input->bindtex) {
830                         GPU_texture_bind(input->tex, input->texid);
831                         GPU_shader_uniform_texture(shader, input->shaderloc, input->tex);
832                 }
833                         
834         }
835 }
836
837 void GPU_pass_update_uniforms(GPUPass *pass)
838 {
839         GPUInput *input;
840         GPUShader *shader = pass->shader;
841         ListBase *inputs = &pass->inputs;
842
843         if (!shader)
844                 return;
845
846         /* pass dynamic inputs to opengl, others were removed */
847         for (input=inputs->first; input; input=input->next)
848                 if (!(input->ima || input->tex || input->prv))
849                         GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1,
850                                 input->dynamicvec);
851 }
852
853 void GPU_pass_unbind(GPUPass *pass)
854 {
855         GPUInput *input;
856         GPUShader *shader = pass->shader;
857         ListBase *inputs = &pass->inputs;
858
859         if (!shader)
860                 return;
861
862         for (input=inputs->first; input; input=input->next) {
863                 if (input->tex && input->bindtex)
864                         GPU_texture_unbind(input->tex);
865
866                 if (input->ima || input->prv)
867                         input->tex = NULL;
868         }
869         
870         GPU_shader_unbind();
871 }
872
873 /* Node Link Functions */
874
875 static GPUNodeLink *GPU_node_link_create(void)
876 {
877         GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink");
878         link->type = GPU_NONE;
879         link->users++;
880
881         return link;
882 }
883
884 static void gpu_node_link_free(GPUNodeLink *link)
885 {
886         link->users--;
887
888         if (link->users < 0)
889                 fprintf(stderr, "GPU_node_link_free: negative refcount\n");
890         
891         if (link->users == 0) {
892                 if (link->output)
893                         link->output->link = NULL;
894                 MEM_freeN(link);
895         }
896 }
897
898 /* Node Functions */
899
900 static GPUNode *GPU_node_begin(const char *name)
901 {
902         GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode");
903
904         node->name= name;
905
906         return node;
907 }
908
909 static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType type)
910 {
911         GPUInput *input;
912         GPUNode *outnode;
913         const char *name;
914
915         if (link->output) {
916                 outnode = link->output->node;
917                 name = outnode->name;
918
919                 if (STREQ(name, "set_value") || STREQ(name, "set_rgb")) {
920                         input = MEM_dupallocN(outnode->inputs.first);
921                         input->type = type;
922                         if (input->link)
923                                 input->link->users++;
924                         BLI_addtail(&node->inputs, input);
925                         return;
926                 }
927         }
928         
929         input = MEM_callocN(sizeof(GPUInput), "GPUInput");
930         input->node = node;
931
932         if (link->builtin) {
933                 /* builtin uniform */
934                 input->type = type;
935                 input->source = GPU_SOURCE_BUILTIN;
936                 input->builtin = link->builtin;
937
938                 MEM_freeN(link);
939         }
940         else if (link->oglbuiltin) {
941                 /* builtin uniform */
942                 input->type = type;
943                 input->source = GPU_SOURCE_OPENGL_BUILTIN;
944                 input->oglbuiltin = link->oglbuiltin;
945
946                 MEM_freeN(link);
947         }
948         else if (link->output) {
949                 /* link to a node output */
950                 input->type = type;
951                 input->source = GPU_SOURCE_TEX_PIXEL;
952                 input->link = link;
953                 link->users++;
954         }
955         else if (link->dynamictex) {
956                 /* dynamic texture, GPUTexture is updated/deleted externally */
957                 input->type = type;
958                 input->source = GPU_SOURCE_TEX;
959
960                 input->tex = link->dynamictex;
961                 input->textarget = GL_TEXTURE_2D;
962                 input->textype = type;
963                 input->dynamictex = true;
964                 input->dynamicdata = link->ptr2;
965                 MEM_freeN(link);
966         }
967         else if (link->texture) {
968                 /* small texture created on the fly, like for colorbands */
969                 input->type = GPU_VEC4;
970                 input->source = GPU_SOURCE_TEX;
971                 input->textype = type;
972
973                 //input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
974                 input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, GPU_HDR_NONE, NULL);
975                 input->textarget = GL_TEXTURE_2D;
976
977                 MEM_freeN(link->ptr1);
978                 MEM_freeN(link);
979         }
980         else if (link->image) {
981                 /* blender image */
982                 input->type = GPU_VEC4;
983                 input->source = GPU_SOURCE_TEX;
984
985                 if (link->image == GPU_NODE_LINK_IMAGE_PREVIEW)
986                         input->prv = link->ptr1;
987                 else {
988                         input->ima = link->ptr1;
989                         input->iuser = link->ptr2;
990                         input->image_isdata = link->image_isdata;
991                 }
992                 input->textarget = GL_TEXTURE_2D;
993                 input->textype = GPU_TEX2D;
994                 MEM_freeN(link);
995         }
996         else if (link->attribtype) {
997                 /* vertex attribute */
998                 input->type = type;
999                 input->source = GPU_SOURCE_ATTRIB;
1000
1001                 input->attribtype = link->attribtype;
1002                 BLI_strncpy(input->attribname, link->attribname, sizeof(input->attribname));
1003                 MEM_freeN(link);
1004         }
1005         else {
1006                 /* uniform vector */
1007                 input->type = type;
1008                 input->source = GPU_SOURCE_VEC_UNIFORM;
1009
1010                 memcpy(input->vec, link->ptr1, type*sizeof(float));
1011                 if (link->dynamic) {
1012                         input->dynamicvec= link->ptr1;
1013                         input->dynamictype= link->dynamictype;
1014                         input->dynamicdata= link->ptr2;
1015                 }
1016                 MEM_freeN(link);
1017         }
1018
1019         BLI_addtail(&node->inputs, input);
1020 }
1021
1022 static void gpu_node_input_socket(GPUNode *node, GPUNodeStack *sock)
1023 {
1024         GPUNodeLink *link;
1025
1026         if (sock->link) {
1027                 gpu_node_input_link(node, sock->link, sock->type);
1028         }
1029         else {
1030                 link = GPU_node_link_create();
1031                 link->ptr1 = sock->vec;
1032                 gpu_node_input_link(node, link, sock->type);
1033         }
1034 }
1035
1036 static void gpu_node_output(GPUNode *node, const GPUType type, GPUNodeLink **link)
1037 {
1038         GPUOutput *output = MEM_callocN(sizeof(GPUOutput), "GPUOutput");
1039
1040         output->type = type;
1041         output->node = node;
1042
1043         if (link) {
1044                 *link = output->link = GPU_node_link_create();
1045                 output->link->type = type;
1046                 output->link->output = output;
1047
1048                 /* note: the caller owns the reference to the linkfer, GPUOutput
1049                  * merely points to it, and if the node is destroyed it will
1050                  * set that pointer to NULL */
1051         }
1052
1053         BLI_addtail(&node->outputs, output);
1054 }
1055
1056 static void gpu_inputs_free(ListBase *inputs)
1057 {
1058         GPUInput *input;
1059
1060         for (input=inputs->first; input; input=input->next) {
1061                 if (input->link)
1062                         gpu_node_link_free(input->link);
1063                 else if (input->tex && !input->dynamictex)
1064                         GPU_texture_free(input->tex);
1065         }
1066
1067         BLI_freelistN(inputs);
1068 }
1069
1070 static void gpu_node_free(GPUNode *node)
1071 {
1072         GPUOutput *output;
1073
1074         gpu_inputs_free(&node->inputs);
1075
1076         for (output=node->outputs.first; output; output=output->next)
1077                 if (output->link) {
1078                         output->link->output = NULL;
1079                         gpu_node_link_free(output->link);
1080                 }
1081
1082         BLI_freelistN(&node->outputs);
1083         MEM_freeN(node);
1084 }
1085
1086 static void gpu_nodes_free(ListBase *nodes)
1087 {
1088         GPUNode *node;
1089
1090         while ((node = BLI_pophead(nodes))) {
1091                 gpu_node_free(node);
1092         }
1093 }
1094
1095 /* vertex attributes */
1096
1097 static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs)
1098 {
1099         GPUNode *node;
1100         GPUInput *input;
1101         int a;
1102
1103         /* convert attributes requested by node inputs to an array of layers,
1104          * checking for duplicates and assigning id's starting from zero. */
1105
1106         memset(attribs, 0, sizeof(*attribs));
1107
1108         for (node=nodes->first; node; node=node->next) {
1109                 for (input=node->inputs.first; input; input=input->next) {
1110                         if (input->source == GPU_SOURCE_ATTRIB) {
1111                                 for (a=0; a<attribs->totlayer; a++) {
1112                                         if (attribs->layer[a].type == input->attribtype &&
1113                                             STREQ(attribs->layer[a].name, input->attribname))
1114                                         {
1115                                                 break;
1116                                         }
1117                                 }
1118
1119                                 if (a < GPU_MAX_ATTRIB) {
1120                                         if (a == attribs->totlayer) {
1121                                                 input->attribid = attribs->totlayer++;
1122                                                 input->attribfirst = 1;
1123
1124                                                 attribs->layer[a].type = input->attribtype;
1125                                                 attribs->layer[a].attribid = input->attribid;
1126                                                 BLI_strncpy(attribs->layer[a].name, input->attribname,
1127                                                             sizeof(attribs->layer[a].name));
1128                                         }
1129                                         else {
1130                                                 input->attribid = attribs->layer[a].attribid;
1131                                         }
1132                                 }
1133                         }
1134                 }
1135         }
1136 }
1137
1138 static void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin)
1139 {
1140         GPUNode *node;
1141         GPUInput *input;
1142         
1143         *builtin= 0;
1144
1145         for (node=nodes->first; node; node=node->next)
1146                 for (input=node->inputs.first; input; input=input->next)
1147                         if (input->source == GPU_SOURCE_BUILTIN)
1148                                 *builtin |= input->builtin;
1149 }
1150
1151 /* varargs linking  */
1152
1153 GPUNodeLink *GPU_attribute(const CustomDataType type, const char *name)
1154 {
1155         GPUNodeLink *link = GPU_node_link_create();
1156
1157         link->attribtype= type;
1158         link->attribname= name;
1159
1160         return link;
1161 }
1162
1163 GPUNodeLink *GPU_uniform(float *num)
1164 {
1165         GPUNodeLink *link = GPU_node_link_create();
1166
1167         link->ptr1= num;
1168         link->ptr2= NULL;
1169
1170         return link;
1171 }
1172
1173 GPUNodeLink *GPU_dynamic_uniform(float *num, GPUDynamicType dynamictype, void *data)
1174 {
1175         GPUNodeLink *link = GPU_node_link_create();
1176
1177         link->ptr1= num;
1178         link->ptr2= data;
1179         link->dynamic= true;
1180         link->dynamictype = dynamictype;
1181
1182
1183         return link;
1184 }
1185
1186 GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data)
1187 {
1188         GPUNodeLink *link = GPU_node_link_create();
1189
1190         link->image = GPU_NODE_LINK_IMAGE_BLENDER;
1191         link->ptr1 = ima;
1192         link->ptr2 = iuser;
1193         link->image_isdata = is_data;
1194
1195         return link;
1196 }
1197
1198 GPUNodeLink *GPU_image_preview(PreviewImage *prv)
1199 {
1200         GPUNodeLink *link = GPU_node_link_create();
1201         
1202         link->image= GPU_NODE_LINK_IMAGE_PREVIEW;
1203         link->ptr1= prv;
1204         
1205         return link;
1206 }
1207
1208
1209 GPUNodeLink *GPU_texture(int size, float *pixels)
1210 {
1211         GPUNodeLink *link = GPU_node_link_create();
1212
1213         link->texture = true;
1214         link->texturesize = size;
1215         link->ptr1= pixels;
1216
1217         return link;
1218 }
1219
1220 GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex, GPUDynamicType dynamictype, void *data)
1221 {
1222         GPUNodeLink *link = GPU_node_link_create();
1223
1224         link->dynamic = true;
1225         link->dynamictex = tex;
1226         link->dynamictype = dynamictype;
1227         link->ptr2 = data;
1228
1229         return link;
1230 }
1231
1232 GPUNodeLink *GPU_builtin(GPUBuiltin builtin)
1233 {
1234         GPUNodeLink *link = GPU_node_link_create();
1235
1236         link->builtin= builtin;
1237
1238         return link;
1239 }
1240
1241 GPUNodeLink *GPU_opengl_builtin(GPUOpenGLBuiltin builtin)
1242 {
1243         GPUNodeLink *link = GPU_node_link_create();
1244
1245         link->oglbuiltin = builtin;
1246
1247         return link;
1248 }
1249
1250 bool GPU_link(GPUMaterial *mat, const char *name, ...)
1251 {
1252         GPUNode *node;
1253         GPUFunction *function;
1254         GPUNodeLink *link, **linkptr;
1255         va_list params;
1256         int i;
1257
1258         function = gpu_lookup_function(name);
1259         if (!function) {
1260                 fprintf(stderr, "GPU failed to find function %s\n", name);
1261                 return 0;
1262         }
1263
1264         node = GPU_node_begin(name);
1265
1266         va_start(params, name);
1267         for (i=0; i<function->totparam; i++) {
1268                 if (function->paramqual[i] != FUNCTION_QUAL_IN) {
1269                         linkptr= va_arg(params, GPUNodeLink**);
1270                         gpu_node_output(node, function->paramtype[i], linkptr);
1271                 }
1272                 else {
1273                         link= va_arg(params, GPUNodeLink*);
1274                         gpu_node_input_link(node, link, function->paramtype[i]);
1275                 }
1276         }
1277         va_end(params);
1278
1279         gpu_material_add_node(mat, node);
1280
1281         return 1;
1282 }
1283
1284 bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...)
1285 {
1286         GPUNode *node;
1287         GPUFunction *function;
1288         GPUNodeLink *link, **linkptr;
1289         va_list params;
1290         int i, totin, totout;
1291
1292         function = gpu_lookup_function(name);
1293         if (!function) {
1294                 fprintf(stderr, "GPU failed to find function %s\n", name);
1295                 return 0;
1296         }
1297
1298         node = GPU_node_begin(name);
1299         totin = 0;
1300         totout = 0;
1301
1302         if (in) {
1303                 for (i = 0; in[i].type != GPU_NONE; i++) {
1304                         gpu_node_input_socket(node, &in[i]);
1305                         totin++;
1306                 }
1307         }
1308         
1309         if (out) {
1310                 for (i = 0; out[i].type != GPU_NONE; i++) {
1311                         gpu_node_output(node, out[i].type, &out[i].link);
1312                         totout++;
1313                 }
1314         }
1315
1316         va_start(params, out);
1317         for (i=0; i<function->totparam; i++) {
1318                 if (function->paramqual[i] != FUNCTION_QUAL_IN) {
1319                         if (totout == 0) {
1320                                 linkptr= va_arg(params, GPUNodeLink**);
1321                                 gpu_node_output(node, function->paramtype[i], linkptr);
1322                         }
1323                         else
1324                                 totout--;
1325                 }
1326                 else {
1327                         if (totin == 0) {
1328                                 link= va_arg(params, GPUNodeLink*);
1329                                 if (link->socket)
1330                                         gpu_node_input_socket(node, link->socket);
1331                                 else
1332                                         gpu_node_input_link(node, link, function->paramtype[i]);
1333                         }
1334                         else
1335                                 totin--;
1336                 }
1337         }
1338         va_end(params);
1339
1340         gpu_material_add_node(mat, node);
1341         
1342         return 1;
1343 }
1344
1345 int GPU_link_changed(GPUNodeLink *link)
1346 {
1347         GPUNode *node;
1348         GPUInput *input;
1349         const char *name;
1350
1351         if (link->output) {
1352                 node = link->output->node;
1353                 name = node->name;
1354
1355                 if (STREQ(name, "set_value") || STREQ(name, "set_rgb")) {
1356                         input = node->inputs.first;
1357                         return (input->link != NULL);
1358                 }
1359
1360                 return 1;
1361         }
1362         else
1363                 return 0;
1364 }
1365
1366 /* Pass create/free */
1367
1368 static void gpu_nodes_tag(GPUNodeLink *link)
1369 {
1370         GPUNode *node;
1371         GPUInput *input;
1372
1373         if (!link->output)
1374                 return;
1375
1376         node = link->output->node;
1377         if (node->tag)
1378                 return;
1379         
1380         node->tag = true;
1381         for (input=node->inputs.first; input; input=input->next)
1382                 if (input->link)
1383                         gpu_nodes_tag(input->link);
1384 }
1385
1386 static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
1387 {
1388         GPUNode *node, *next;
1389
1390         for (node=nodes->first; node; node=node->next)
1391                 node->tag = false;
1392
1393         gpu_nodes_tag(outlink);
1394
1395         for (node=nodes->first; node; node=next) {
1396                 next = node->next;
1397
1398                 if (!node->tag) {
1399                         BLI_remlink(nodes, node);
1400                         gpu_node_free(node);
1401                 }
1402         }
1403 }
1404
1405 GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink,
1406                                                    GPUVertexAttribs *attribs, int *builtins,
1407                                                    const GPUMatType type, const char *UNUSED(name))
1408 {
1409         GPUShader *shader;
1410         GPUPass *pass;
1411         char *vertexcode, *fragmentcode;
1412
1413         /*if (!FUNCTION_LIB) {
1414                 GPU_nodes_free(nodes);
1415                 return NULL;
1416         }*/
1417
1418         /* prune unused nodes */
1419         gpu_nodes_prune(nodes, outlink);
1420
1421         gpu_nodes_get_vertex_attributes(nodes, attribs);
1422         gpu_nodes_get_builtin_flag(nodes, builtins);
1423
1424         /* generate code and compile with opengl */
1425         fragmentcode = code_generate_fragment(nodes, outlink->output);
1426         vertexcode = code_generate_vertex(nodes, type);
1427         shader = GPU_shader_create(vertexcode, fragmentcode, glsl_material_library, NULL);
1428
1429         /* failed? */
1430         if (!shader) {
1431                 if (fragmentcode)
1432                         MEM_freeN(fragmentcode);
1433                 if (vertexcode)
1434                         MEM_freeN(vertexcode);
1435                 memset(attribs, 0, sizeof(*attribs));
1436                 memset(builtins, 0, sizeof(*builtins));
1437                 gpu_nodes_free(nodes);
1438                 return NULL;
1439         }
1440         
1441         /* create pass */
1442         pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
1443
1444         pass->output = outlink->output;
1445         pass->shader = shader;
1446         pass->fragmentcode = fragmentcode;
1447         pass->vertexcode = vertexcode;
1448         pass->libcode = glsl_material_library;
1449
1450         /* extract dynamic inputs and throw away nodes */
1451         gpu_nodes_extract_dynamic_inputs(pass, nodes);
1452         gpu_nodes_free(nodes);
1453
1454         return pass;
1455 }
1456
1457 void GPU_pass_free(GPUPass *pass)
1458 {
1459         GPU_shader_free(pass->shader);
1460         gpu_inputs_free(&pass->inputs);
1461         if (pass->fragmentcode)
1462                 MEM_freeN(pass->fragmentcode);
1463         if (pass->vertexcode)
1464                 MEM_freeN(pass->vertexcode);
1465         MEM_freeN(pass);
1466 }
1467