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