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