OpenGL: codegen formatting
[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 extern char datatoc_gpu_shader_geometry_glsl[];
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 builtin 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, "%s %s %s;\n",
515                                                         GLEW_VERSION_3_0 ? "in" : "varying",
516                                                         GPU_DATATYPE_STR[input->type], name);
517                                         }
518                                 }
519                         }
520                         else if (input->source == GPU_SOURCE_VEC_UNIFORM) {
521                                 if (input->dynamicvec) {
522                                         /* only create uniforms for dynamic vectors */
523                                         BLI_dynstr_appendf(ds, "uniform %s unf%d;\n",
524                                                 GPU_DATATYPE_STR[input->type], input->id);
525                                 }
526                                 else {
527                                         /* for others use const so the compiler can do folding */
528                                         BLI_dynstr_appendf(ds, "const %s cons%d = ",
529                                                 GPU_DATATYPE_STR[input->type], input->id);
530                                         codegen_print_datatype(ds, input->type, input->vec);
531                                         BLI_dynstr_append(ds, ";\n");
532                                 }
533                         }
534                         else if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
535 #ifdef WITH_OPENSUBDIV
536                                 bool skip_opensubdiv = input->attribtype == CD_TANGENT;
537                                 if (skip_opensubdiv) {
538                                         BLI_dynstr_appendf(ds, "#ifndef USE_OPENSUBDIV\n");
539                                 }
540 #endif
541                                 BLI_dynstr_appendf(ds, "%s %s var%d;\n",
542                                         GLEW_VERSION_3_0 ? "in" : "varying",
543                                         GPU_DATATYPE_STR[input->type], input->attribid);
544 #ifdef WITH_OPENSUBDIV
545                                 if (skip_opensubdiv) {
546                                         BLI_dynstr_appendf(ds, "#endif\n");
547                                 }
548 #endif
549                         }
550                 }
551         }
552
553         BLI_dynstr_append(ds, "\n");
554
555         return builtins;
556 }
557
558 static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
559 {
560         GPUNode *node;
561         GPUInput *input;
562         GPUOutput *output;
563
564         for (node = nodes->first; node; node = node->next) {
565                 /* load pixels from textures */
566                 for (input = node->inputs.first; input; input = input->next) {
567                         if (input->source == GPU_SOURCE_TEX_PIXEL) {
568                                 if (codegen_input_has_texture(input) && input->definetex) {
569                                         BLI_dynstr_appendf(ds, "\tvec4 tex%d = texture2D(", input->texid);
570                                         BLI_dynstr_appendf(ds, "samp%d, gl_TexCoord[%d].st);\n",
571                                                 input->texid, input->texid);
572                                 }
573                         }
574                 }
575
576                 /* declare temporary variables for node output storage */
577                 for (output = node->outputs.first; output; output = output->next)
578                         BLI_dynstr_appendf(ds, "\t%s tmp%d;\n",
579                                 GPU_DATATYPE_STR[output->type], output->id);
580         }
581
582         BLI_dynstr_append(ds, "\n");
583 }
584
585 static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *finaloutput)
586 {
587         GPUNode *node;
588         GPUInput *input;
589         GPUOutput *output;
590
591         for (node = nodes->first; node; node = node->next) {
592                 BLI_dynstr_appendf(ds, "\t%s(", node->name);
593                 
594                 for (input = node->inputs.first; input; input = input->next) {
595                         if (input->source == GPU_SOURCE_TEX) {
596                                 BLI_dynstr_appendf(ds, "samp%d", input->texid);
597                                 if (input->link)
598                                         BLI_dynstr_appendf(ds, ", gl_TexCoord[%d].st", input->texid);
599                         }
600                         else if (input->source == GPU_SOURCE_TEX_PIXEL) {
601                                 codegen_convert_datatype(ds, input->link->output->type, input->type,
602                                         "tmp", input->link->output->id);
603                         }
604                         else if (input->source == GPU_SOURCE_BUILTIN) {
605                                 if (input->builtin == GPU_VIEW_NORMAL)
606                                         BLI_dynstr_append(ds, "facingnormal");
607                                 else
608                                         BLI_dynstr_append(ds, GPU_builtin_name(input->builtin));
609                         }
610                         else if (input->source == GPU_SOURCE_VEC_UNIFORM) {
611                                 if (input->dynamicvec)
612                                         BLI_dynstr_appendf(ds, "unf%d", input->id);
613                                 else
614                                         BLI_dynstr_appendf(ds, "cons%d", input->id);
615                         }
616                         else if (input->source == GPU_SOURCE_ATTRIB) {
617                                 BLI_dynstr_appendf(ds, "var%d", input->attribid);
618                         }
619                         else if (input->source == GPU_SOURCE_OPENGL_BUILTIN) {
620                                 if (input->oglbuiltin == GPU_MATCAP_NORMAL)
621                                         BLI_dynstr_append(ds, "gl_SecondaryColor");
622                                 else if (input->oglbuiltin == GPU_COLOR)
623                                         BLI_dynstr_append(ds, "gl_Color");
624                         }
625
626                         BLI_dynstr_append(ds, ", ");
627                 }
628
629                 for (output = node->outputs.first; output; output = output->next) {
630                         BLI_dynstr_appendf(ds, "tmp%d", output->id);
631                         if (output->next)
632                                 BLI_dynstr_append(ds, ", ");
633                 }
634
635                 BLI_dynstr_append(ds, ");\n");
636         }
637
638         BLI_dynstr_append(ds, "\n\tgl_FragColor = ");
639         codegen_convert_datatype(ds, finaloutput->type, GPU_VEC4, "tmp", finaloutput->id);
640         BLI_dynstr_append(ds, ";\n");
641 }
642
643 static char *code_generate_fragment(ListBase *nodes, GPUOutput *output)
644 {
645         DynStr *ds = BLI_dynstr_new();
646         char *code;
647         int builtins;
648
649 #ifdef WITH_OPENSUBDIV
650         GPUNode *node;
651         GPUInput *input;
652 #endif
653
654
655 #if 0
656         BLI_dynstr_append(ds, FUNCTION_PROTOTYPES);
657 #endif
658
659         codegen_set_unique_ids(nodes);
660         builtins = codegen_print_uniforms_functions(ds, nodes);
661
662 #if 0
663         if (G.debug & G_DEBUG)
664                 BLI_dynstr_appendf(ds, "/* %s */\n", name);
665 #endif
666
667         BLI_dynstr_append(ds, "void main()\n{\n");
668
669         if (builtins & GPU_VIEW_NORMAL)
670                 BLI_dynstr_append(ds, "\tvec3 facingnormal = gl_FrontFacing? varnormal: -varnormal;\n");
671
672         /* Calculate tangent space. */
673 #ifdef WITH_OPENSUBDIV
674         {
675                 bool has_tangent = false;
676                 for (node = nodes->first; node; node = node->next) {
677                         for (input = node->inputs.first; input; input = input->next) {
678                                 if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
679                                         if (input->attribtype == CD_TANGENT) {
680                                                 BLI_dynstr_appendf(ds, "#ifdef USE_OPENSUBDIV\n");
681                                                 BLI_dynstr_appendf(ds, "\t%s var%d;\n",
682                                                                    GPU_DATATYPE_STR[input->type],
683                                                                    input->attribid);
684                                                 if (has_tangent == false) {
685                                                         BLI_dynstr_appendf(ds, "\tvec3 Q1 = dFdx(inpt.v.position.xyz);\n");
686                                                         BLI_dynstr_appendf(ds, "\tvec3 Q2 = dFdy(inpt.v.position.xyz);\n");
687                                                         BLI_dynstr_appendf(ds, "\tvec2 st1 = dFdx(inpt.v.uv);\n");
688                                                         BLI_dynstr_appendf(ds, "\tvec2 st2 = dFdy(inpt.v.uv);\n");
689                                                         BLI_dynstr_appendf(ds, "\tvec3 T = normalize(Q1 * st2.t - Q2 * st1.t);\n");
690                                                 }
691                                                 BLI_dynstr_appendf(ds, "\tvar%d = vec4(T, 1.0);\n", input->attribid);
692                                                 BLI_dynstr_appendf(ds, "#endif\n");
693                                         }
694                                 }
695                         }
696                 }
697         }
698 #endif
699
700         codegen_declare_tmps(ds, nodes);
701         codegen_call_functions(ds, nodes, output);
702
703         BLI_dynstr_append(ds, "}\n");
704
705         /* create shader */
706         code = BLI_dynstr_get_cstring(ds);
707         BLI_dynstr_free(ds);
708
709 #if 0
710         if (G.debug & G_DEBUG) printf("%s\n", code);
711 #endif
712
713         return code;
714 }
715
716 static char *code_generate_vertex(ListBase *nodes, const GPUMatType type)
717 {
718         DynStr *ds = BLI_dynstr_new();
719         GPUNode *node;
720         GPUInput *input;
721         char *code;
722         char *vertcode = NULL;
723         
724         for (node = nodes->first; node; node = node->next) {
725                 for (input = node->inputs.first; input; input = input->next) {
726                         if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
727 #ifdef WITH_OPENSUBDIV
728                                 bool skip_opensubdiv = ELEM(input->attribtype, CD_MTFACE, CD_TANGENT);
729                                 if (skip_opensubdiv) {
730                                         BLI_dynstr_appendf(ds, "#ifndef USE_OPENSUBDIV\n");
731                                 }
732 #endif
733                                 BLI_dynstr_appendf(ds, "%s %s att%d;\n",
734                                         GLEW_VERSION_3_0 ? "in" : "attribute",
735                                         GPU_DATATYPE_STR[input->type], input->attribid);
736                                 BLI_dynstr_appendf(ds, "%s %s var%d;\n",
737                                         GLEW_VERSION_3_0 ? "out" : "varying",
738                                         GPU_DATATYPE_STR[input->type], input->attribid);
739 #ifdef WITH_OPENSUBDIV
740                                 if (skip_opensubdiv) {
741                                         BLI_dynstr_appendf(ds, "#endif\n");
742                                 }
743 #endif
744                         }
745                 }
746         }
747
748         BLI_dynstr_append(ds, "\n");
749
750         switch (type) {
751                 case GPU_MATERIAL_TYPE_MESH:
752                         vertcode = datatoc_gpu_shader_vertex_glsl;
753                         break;
754                 case GPU_MATERIAL_TYPE_WORLD:
755                         vertcode = datatoc_gpu_shader_vertex_world_glsl;
756                         break;
757                 default:
758                         fprintf(stderr, "invalid material type, set one after GPU_material_construct_begin\n");
759                         break;
760         }
761
762         BLI_dynstr_append(ds, vertcode);
763         
764         for (node = nodes->first; node; node = node->next)
765                 for (input = node->inputs.first; input; input = input->next)
766                         if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
767                                 if (input->attribtype == CD_TANGENT) { /* silly exception */
768 #ifdef WITH_OPENSUBDIV
769                                         BLI_dynstr_appendf(ds, "#ifndef USE_OPENSUBDIV\n");
770 #endif
771                                         BLI_dynstr_appendf(ds, "\tvar%d.xyz = normalize(gl_NormalMatrix * att%d.xyz);\n", input->attribid, input->attribid);
772                                         BLI_dynstr_appendf(ds, "\tvar%d.w = att%d.w;\n", input->attribid, input->attribid);
773 #ifdef WITH_OPENSUBDIV
774                                         BLI_dynstr_appendf(ds, "#endif\n");
775 #endif
776                                 }
777                                 else {
778 #ifdef WITH_OPENSUBDIV
779                                         bool is_mtface = input->attribtype == CD_MTFACE;
780                                         if (is_mtface) {
781                                                 BLI_dynstr_appendf(ds, "#ifndef USE_OPENSUBDIV\n");
782                                         }
783 #endif
784                                         BLI_dynstr_appendf(ds, "\tvar%d = att%d;\n", input->attribid, input->attribid);
785 #ifdef WITH_OPENSUBDIV
786                                         if (is_mtface) {
787                                                 BLI_dynstr_appendf(ds, "#endif\n");
788                                         }
789 #endif
790                                 }
791                         }
792                         /* unfortunately special handling is needed here because we abuse gl_Color/gl_SecondaryColor flat shading */
793                         else if (input->source == GPU_SOURCE_OPENGL_BUILTIN) {
794                                 if (input->oglbuiltin == GPU_MATCAP_NORMAL) {
795                                         /* remap to 0.0 - 1.0 range. This is done because OpenGL 2.0 clamps colors
796                                          * between shader stages and we want the full range of the normal */
797                                         BLI_dynstr_appendf(ds, "\tvec3 matcapcol = vec3(0.5) * varnormal + vec3(0.5);\n");
798                                         BLI_dynstr_appendf(ds, "\tgl_FrontSecondaryColor = vec4(matcapcol, 1.0);\n");
799                                 }
800                                 else if (input->oglbuiltin == GPU_COLOR) {
801                                         BLI_dynstr_appendf(ds, "\tgl_FrontColor = gl_Color;\n");
802                                 }
803                         }
804
805         BLI_dynstr_append(ds, "}\n");
806
807         code = BLI_dynstr_get_cstring(ds);
808
809         BLI_dynstr_free(ds);
810
811 #if 0
812         if (G.debug & G_DEBUG) printf("%s\n", code);
813 #endif
814
815         return code;
816 }
817
818 static char *code_generate_geometry(ListBase *nodes, bool use_opensubdiv)
819 {
820 #ifdef WITH_OPENSUBDIV
821         if (use_opensubdiv) {
822                 DynStr *ds = BLI_dynstr_new();
823                 GPUNode *node;
824                 GPUInput *input;
825                 char *code;
826
827                 /* Generate varying declarations. */
828                 for (node = nodes->first; node; node = node->next) {
829                         for (input = node->inputs.first; input; input = input->next) {
830                                 if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
831                                         if (input->attribtype == CD_MTFACE) {
832                                                 BLI_dynstr_appendf(ds, "%s %s var%d;\n",
833                                                                    GLEW_VERSION_3_0 ? "in" : "varying",
834                                                                    GPU_DATATYPE_STR[input->type],
835                                                                    input->attribid);
836                                                 BLI_dynstr_appendf(ds, "uniform int fvar%d_offset;\n",
837                                                                    input->attribid);
838                                         }
839                                 }
840                         }
841                 }
842
843                 BLI_dynstr_append(ds, datatoc_gpu_shader_geometry_glsl);
844
845                 /* Generate varying assignments. */
846                 /* TODO(sergey): Disabled for now, needs revisit. */
847 #if 0
848                 for (node = nodes->first; node; node = node->next) {
849                         for (input = node->inputs.first; input; input = input->next) {
850                                 if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
851                                         if (input->attribtype == CD_MTFACE) {
852                                                 BLI_dynstr_appendf(ds,
853                                                                    "\tINTERP_FACE_VARYING_2(var%d, "
854                                                                        "fvar%d_offset, st);\n",
855                                                                    input->attribid,
856                                                                    input->attribid);
857                                         }
858                                 }
859                         }
860                 }
861 #endif
862
863                 BLI_dynstr_append(ds, "}\n");
864                 code = BLI_dynstr_get_cstring(ds);
865                 BLI_dynstr_free(ds);
866
867                 //if (G.debug & G_DEBUG) printf("%s\n", code);
868
869                 return code;
870         }
871 #else
872         UNUSED_VARS(nodes, use_opensubdiv);
873 #endif
874         return NULL;
875 }
876
877 void GPU_code_generate_glsl_lib(void)
878 {
879         DynStr *ds;
880
881         /* only initialize the library once */
882         if (glsl_material_library)
883                 return;
884
885         ds = BLI_dynstr_new();
886
887         BLI_dynstr_append(ds, datatoc_gpu_shader_material_glsl);
888
889
890         glsl_material_library = BLI_dynstr_get_cstring(ds);
891
892         BLI_dynstr_free(ds);
893 }
894
895
896 /* GPU pass binding/unbinding */
897
898 GPUShader *GPU_pass_shader(GPUPass *pass)
899 {
900         return pass->shader;
901 }
902
903 static void gpu_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
904 {
905         GPUShader *shader = pass->shader;
906         GPUNode *node;
907         GPUInput *next, *input;
908         ListBase *inputs = &pass->inputs;
909         int extract, z;
910
911         memset(inputs, 0, sizeof(*inputs));
912
913         if (!shader)
914                 return;
915
916         GPU_shader_bind(shader);
917
918         for (node = nodes->first; node; node = node->next) {
919                 z = 0;
920                 for (input = node->inputs.first; input; input = next, z++) {
921                         next = input->next;
922
923                         /* attributes don't need to be bound, they already have
924                          * an id that the drawing functions will use */
925                         if (input->source == GPU_SOURCE_ATTRIB) {
926 #ifdef WITH_OPENSUBDIV
927                                 /* We do need mtface attributes for later, so we can
928                                  * update face-varuing variables offset in the texture
929                                  * buffer for proper sampling from the shader.
930                                  *
931                                  * We don't do anything about attribute itself, we
932                                  * only use it to learn which uniform name is to be
933                                  * updated.
934                                  *
935                                  * TODO(sergey): We can add ad extra uniform input
936                                  * for the offset, which will be purely internal and
937                                  * which would avoid having such an exceptions.
938                                  */
939                                 if (input->attribtype != CD_MTFACE) {
940                                         continue;
941                                 }
942 #else
943                                 continue;
944 #endif
945                         }
946                         if (input->source == GPU_SOURCE_BUILTIN ||
947                             input->source == GPU_SOURCE_OPENGL_BUILTIN)
948                         {
949                                 continue;
950                         }
951
952                         if (input->ima || input->tex || input->prv)
953                                 BLI_snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid);
954                         else
955                                 BLI_snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id);
956
957                         /* pass non-dynamic uniforms to opengl */
958                         extract = 0;
959
960                         if (input->ima || input->tex || input->prv) {
961                                 if (input->bindtex)
962                                         extract = 1;
963                         }
964                         else if (input->dynamicvec)
965                                 extract = 1;
966
967                         if (extract)
968                                 input->shaderloc = GPU_shader_get_uniform(shader, input->shadername);
969
970 #ifdef WITH_OPENSUBDIV
971                         if (input->source == GPU_SOURCE_ATTRIB &&
972                             input->attribtype == CD_MTFACE)
973                         {
974                                 extract = 1;
975                         }
976 #endif
977
978                         /* extract nodes */
979                         if (extract) {
980                                 BLI_remlink(&node->inputs, input);
981                                 BLI_addtail(inputs, input);
982                         }
983                 }
984         }
985
986         GPU_shader_unbind();
987 }
988
989 void GPU_pass_bind(GPUPass *pass, double time, int mipmap)
990 {
991         GPUInput *input;
992         GPUShader *shader = pass->shader;
993         ListBase *inputs = &pass->inputs;
994
995         if (!shader)
996                 return;
997
998         GPU_shader_bind(shader);
999
1000         /* now bind the textures */
1001         for (input = inputs->first; input; input = input->next) {
1002                 if (input->ima)
1003                         input->tex = GPU_texture_from_blender(input->ima, input->iuser, input->image_isdata, time, mipmap);
1004                 else if (input->prv)
1005                         input->tex = GPU_texture_from_preview(input->prv, mipmap);
1006
1007                 if (input->tex && input->bindtex) {
1008                         GPU_texture_bind(input->tex, input->texid);
1009                         GPU_shader_uniform_texture(shader, input->shaderloc, input->tex);
1010                 }
1011                         
1012         }
1013 }
1014
1015 void GPU_pass_update_uniforms(GPUPass *pass)
1016 {
1017         GPUInput *input;
1018         GPUShader *shader = pass->shader;
1019         ListBase *inputs = &pass->inputs;
1020
1021         if (!shader)
1022                 return;
1023
1024         /* pass dynamic inputs to opengl, others were removed */
1025         for (input = inputs->first; input; input = input->next) {
1026                 if (!(input->ima || input->tex || input->prv)) {
1027                         if (input->dynamictype == GPU_DYNAMIC_MAT_HARD) {
1028                                 // The hardness is actually a short pointer, so we convert it here
1029                                 float val = (float)(*(short*)input->dynamicvec);
1030                                 GPU_shader_uniform_vector(shader, input->shaderloc, 1, 1, &val);
1031                         }
1032                         else {
1033                                 GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1,
1034                                         input->dynamicvec);
1035                         }
1036                 }
1037         }
1038 }
1039
1040 void GPU_pass_unbind(GPUPass *pass)
1041 {
1042         GPUInput *input;
1043         GPUShader *shader = pass->shader;
1044         ListBase *inputs = &pass->inputs;
1045
1046         if (!shader)
1047                 return;
1048
1049         for (input = inputs->first; input; input = input->next) {
1050                 if (input->tex && input->bindtex)
1051                         GPU_texture_unbind(input->tex);
1052
1053                 if (input->ima || input->prv)
1054                         input->tex = NULL;
1055         }
1056         
1057         GPU_shader_unbind();
1058 }
1059
1060 /* Node Link Functions */
1061
1062 static GPUNodeLink *GPU_node_link_create(void)
1063 {
1064         GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink");
1065         link->type = GPU_NONE;
1066         link->users++;
1067
1068         return link;
1069 }
1070
1071 static void gpu_node_link_free(GPUNodeLink *link)
1072 {
1073         link->users--;
1074
1075         if (link->users < 0)
1076                 fprintf(stderr, "GPU_node_link_free: negative refcount\n");
1077         
1078         if (link->users == 0) {
1079                 if (link->output)
1080                         link->output->link = NULL;
1081                 MEM_freeN(link);
1082         }
1083 }
1084
1085 /* Node Functions */
1086
1087 static GPUNode *GPU_node_begin(const char *name)
1088 {
1089         GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode");
1090
1091         node->name = name;
1092
1093         return node;
1094 }
1095
1096 static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType type)
1097 {
1098         GPUInput *input;
1099         GPUNode *outnode;
1100         const char *name;
1101
1102         if (link->output) {
1103                 outnode = link->output->node;
1104                 name = outnode->name;
1105                 input = outnode->inputs.first;
1106
1107                 if ((STREQ(name, "set_value") || STREQ(name, "set_rgb")) &&
1108                     (input->type == type))
1109                 {
1110                         input = MEM_dupallocN(outnode->inputs.first);
1111                         input->type = type;
1112                         if (input->link)
1113                                 input->link->users++;
1114                         BLI_addtail(&node->inputs, input);
1115                         return;
1116                 }
1117         }
1118         
1119         input = MEM_callocN(sizeof(GPUInput), "GPUInput");
1120         input->node = node;
1121
1122         if (link->builtin) {
1123                 /* builtin uniform */
1124                 input->type = type;
1125                 input->source = GPU_SOURCE_BUILTIN;
1126                 input->builtin = link->builtin;
1127
1128                 MEM_freeN(link);
1129         }
1130         else if (link->oglbuiltin) {
1131                 /* builtin uniform */
1132                 input->type = type;
1133                 input->source = GPU_SOURCE_OPENGL_BUILTIN;
1134                 input->oglbuiltin = link->oglbuiltin;
1135
1136                 MEM_freeN(link);
1137         }
1138         else if (link->output) {
1139                 /* link to a node output */
1140                 input->type = type;
1141                 input->source = GPU_SOURCE_TEX_PIXEL;
1142                 input->link = link;
1143                 link->users++;
1144         }
1145         else if (link->dynamictex) {
1146                 /* dynamic texture, GPUTexture is updated/deleted externally */
1147                 input->type = type;
1148                 input->source = GPU_SOURCE_TEX;
1149
1150                 input->tex = link->dynamictex;
1151                 input->textarget = GL_TEXTURE_2D;
1152                 input->textype = type;
1153                 input->dynamictex = true;
1154                 input->dynamicdata = link->ptr2;
1155                 MEM_freeN(link);
1156         }
1157         else if (link->texture) {
1158                 /* small texture created on the fly, like for colorbands */
1159                 input->type = GPU_VEC4;
1160                 input->source = GPU_SOURCE_TEX;
1161                 input->textype = type;
1162
1163 #if 0
1164                 input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
1165 #endif
1166                 input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, GPU_HDR_NONE, NULL);
1167                 input->textarget = GL_TEXTURE_2D;
1168
1169                 MEM_freeN(link->ptr1);
1170                 MEM_freeN(link);
1171         }
1172         else if (link->image) {
1173                 /* blender image */
1174                 input->type = GPU_VEC4;
1175                 input->source = GPU_SOURCE_TEX;
1176
1177                 if (link->image == GPU_NODE_LINK_IMAGE_PREVIEW)
1178                         input->prv = link->ptr1;
1179                 else {
1180                         input->ima = link->ptr1;
1181                         input->iuser = link->ptr2;
1182                         input->image_isdata = link->image_isdata;
1183                 }
1184                 input->textarget = GL_TEXTURE_2D;
1185                 input->textype = GPU_TEX2D;
1186                 MEM_freeN(link);
1187         }
1188         else if (link->attribtype) {
1189                 /* vertex attribute */
1190                 input->type = type;
1191                 input->source = GPU_SOURCE_ATTRIB;
1192
1193                 input->attribtype = link->attribtype;
1194                 BLI_strncpy(input->attribname, link->attribname, sizeof(input->attribname));
1195                 MEM_freeN(link);
1196         }
1197         else {
1198                 /* uniform vector */
1199                 input->type = type;
1200                 input->source = GPU_SOURCE_VEC_UNIFORM;
1201
1202                 memcpy(input->vec, link->ptr1, type*sizeof(float));
1203                 if (link->dynamic) {
1204                         input->dynamicvec = link->ptr1;
1205                         input->dynamictype = link->dynamictype;
1206                         input->dynamicdata = link->ptr2;
1207                 }
1208                 MEM_freeN(link);
1209         }
1210
1211         BLI_addtail(&node->inputs, input);
1212 }
1213
1214 static void gpu_node_input_socket(GPUNode *node, GPUNodeStack *sock)
1215 {
1216         GPUNodeLink *link;
1217
1218         if (sock->link) {
1219                 gpu_node_input_link(node, sock->link, sock->type);
1220         }
1221         else {
1222                 link = GPU_node_link_create();
1223                 link->ptr1 = sock->vec;
1224                 gpu_node_input_link(node, link, sock->type);
1225         }
1226 }
1227
1228 static void gpu_node_output(GPUNode *node, const GPUType type, GPUNodeLink **link)
1229 {
1230         GPUOutput *output = MEM_callocN(sizeof(GPUOutput), "GPUOutput");
1231
1232         output->type = type;
1233         output->node = node;
1234
1235         if (link) {
1236                 *link = output->link = GPU_node_link_create();
1237                 output->link->type = type;
1238                 output->link->output = output;
1239
1240                 /* note: the caller owns the reference to the link, GPUOutput
1241                  * merely points to it, and if the node is destroyed it will
1242                  * set that pointer to NULL */
1243         }
1244
1245         BLI_addtail(&node->outputs, output);
1246 }
1247
1248 static void gpu_inputs_free(ListBase *inputs)
1249 {
1250         GPUInput *input;
1251
1252         for (input = inputs->first; input; input = input->next) {
1253                 if (input->link)
1254                         gpu_node_link_free(input->link);
1255                 else if (input->tex && !input->dynamictex)
1256                         GPU_texture_free(input->tex);
1257         }
1258
1259         BLI_freelistN(inputs);
1260 }
1261
1262 static void gpu_node_free(GPUNode *node)
1263 {
1264         GPUOutput *output;
1265
1266         gpu_inputs_free(&node->inputs);
1267
1268         for (output = node->outputs.first; output; output = output->next)
1269                 if (output->link) {
1270                         output->link->output = NULL;
1271                         gpu_node_link_free(output->link);
1272                 }
1273
1274         BLI_freelistN(&node->outputs);
1275         MEM_freeN(node);
1276 }
1277
1278 static void gpu_nodes_free(ListBase *nodes)
1279 {
1280         GPUNode *node;
1281
1282         while ((node = BLI_pophead(nodes))) {
1283                 gpu_node_free(node);
1284         }
1285 }
1286
1287 /* vertex attributes */
1288
1289 static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs)
1290 {
1291         GPUNode *node;
1292         GPUInput *input;
1293         int a;
1294
1295         /* convert attributes requested by node inputs to an array of layers,
1296          * checking for duplicates and assigning id's starting from zero. */
1297
1298         memset(attribs, 0, sizeof(*attribs));
1299
1300         for (node = nodes->first; node; node = node->next) {
1301                 for (input = node->inputs.first; input; input = input->next) {
1302                         if (input->source == GPU_SOURCE_ATTRIB) {
1303                                 for (a = 0; a < attribs->totlayer; a++) {
1304                                         if (attribs->layer[a].type == input->attribtype &&
1305                                             STREQ(attribs->layer[a].name, input->attribname))
1306                                         {
1307                                                 break;
1308                                         }
1309                                 }
1310
1311                                 if (a < GPU_MAX_ATTRIB) {
1312                                         if (a == attribs->totlayer) {
1313                                                 input->attribid = attribs->totlayer++;
1314                                                 input->attribfirst = 1;
1315
1316                                                 attribs->layer[a].type = input->attribtype;
1317                                                 attribs->layer[a].attribid = input->attribid;
1318                                                 BLI_strncpy(attribs->layer[a].name, input->attribname,
1319                                                             sizeof(attribs->layer[a].name));
1320                                         }
1321                                         else {
1322                                                 input->attribid = attribs->layer[a].attribid;
1323                                         }
1324                                 }
1325                         }
1326                 }
1327         }
1328 }
1329
1330 static void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin)
1331 {
1332         GPUNode *node;
1333         GPUInput *input;
1334         
1335         *builtin = 0;
1336
1337         for (node = nodes->first; node; node = node->next)
1338                 for (input = node->inputs.first; input; input = input->next)
1339                         if (input->source == GPU_SOURCE_BUILTIN)
1340                                 *builtin |= input->builtin;
1341 }
1342
1343 /* varargs linking  */
1344
1345 GPUNodeLink *GPU_attribute(const CustomDataType type, const char *name)
1346 {
1347         GPUNodeLink *link = GPU_node_link_create();
1348
1349         link->attribtype = type;
1350         link->attribname = name;
1351
1352         return link;
1353 }
1354
1355 GPUNodeLink *GPU_uniform(float *num)
1356 {
1357         GPUNodeLink *link = GPU_node_link_create();
1358
1359         link->ptr1 = num;
1360         link->ptr2 = NULL;
1361
1362         return link;
1363 }
1364
1365 GPUNodeLink *GPU_dynamic_uniform(float *num, GPUDynamicType dynamictype, void *data)
1366 {
1367         GPUNodeLink *link = GPU_node_link_create();
1368
1369         link->ptr1 = num;
1370         link->ptr2 = data;
1371         link->dynamic = true;
1372         link->dynamictype = dynamictype;
1373
1374
1375         return link;
1376 }
1377
1378 GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data)
1379 {
1380         GPUNodeLink *link = GPU_node_link_create();
1381
1382         link->image = GPU_NODE_LINK_IMAGE_BLENDER;
1383         link->ptr1 = ima;
1384         link->ptr2 = iuser;
1385         link->image_isdata = is_data;
1386
1387         return link;
1388 }
1389
1390 GPUNodeLink *GPU_image_preview(PreviewImage *prv)
1391 {
1392         GPUNodeLink *link = GPU_node_link_create();
1393         
1394         link->image = GPU_NODE_LINK_IMAGE_PREVIEW;
1395         link->ptr1 = prv;
1396         
1397         return link;
1398 }
1399
1400
1401 GPUNodeLink *GPU_texture(int size, float *pixels)
1402 {
1403         GPUNodeLink *link = GPU_node_link_create();
1404
1405         link->texture = true;
1406         link->texturesize = size;
1407         link->ptr1 = pixels;
1408
1409         return link;
1410 }
1411
1412 GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex, GPUDynamicType dynamictype, void *data)
1413 {
1414         GPUNodeLink *link = GPU_node_link_create();
1415
1416         link->dynamic = true;
1417         link->dynamictex = tex;
1418         link->dynamictype = dynamictype;
1419         link->ptr2 = data;
1420
1421         return link;
1422 }
1423
1424 GPUNodeLink *GPU_builtin(GPUBuiltin builtin)
1425 {
1426         GPUNodeLink *link = GPU_node_link_create();
1427
1428         link->builtin= builtin;
1429
1430         return link;
1431 }
1432
1433 GPUNodeLink *GPU_opengl_builtin(GPUOpenGLBuiltin builtin)
1434 {
1435         GPUNodeLink *link = GPU_node_link_create();
1436
1437         link->oglbuiltin = builtin;
1438
1439         return link;
1440 }
1441
1442 bool GPU_link(GPUMaterial *mat, const char *name, ...)
1443 {
1444         GPUNode *node;
1445         GPUFunction *function;
1446         GPUNodeLink *link, **linkptr;
1447         va_list params;
1448         int i;
1449
1450         function = gpu_lookup_function(name);
1451         if (!function) {
1452                 fprintf(stderr, "GPU failed to find function %s\n", name);
1453                 return 0;
1454         }
1455
1456         node = GPU_node_begin(name);
1457
1458         va_start(params, name);
1459         for (i = 0; i<function->totparam; i++) {
1460                 if (function->paramqual[i] != FUNCTION_QUAL_IN) {
1461                         linkptr = va_arg(params, GPUNodeLink**);
1462                         gpu_node_output(node, function->paramtype[i], linkptr);
1463                 }
1464                 else {
1465                         link = va_arg(params, GPUNodeLink*);
1466                         gpu_node_input_link(node, link, function->paramtype[i]);
1467                 }
1468         }
1469         va_end(params);
1470
1471         gpu_material_add_node(mat, node);
1472
1473         return 1;
1474 }
1475
1476 bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...)
1477 {
1478         GPUNode *node;
1479         GPUFunction *function;
1480         GPUNodeLink *link, **linkptr;
1481         va_list params;
1482         int i, totin, totout;
1483
1484         function = gpu_lookup_function(name);
1485         if (!function) {
1486                 fprintf(stderr, "GPU failed to find function %s\n", name);
1487                 return 0;
1488         }
1489
1490         node = GPU_node_begin(name);
1491         totin = 0;
1492         totout = 0;
1493
1494         if (in) {
1495                 for (i = 0; in[i].type != GPU_NONE; i++) {
1496                         gpu_node_input_socket(node, &in[i]);
1497                         totin++;
1498                 }
1499         }
1500         
1501         if (out) {
1502                 for (i = 0; out[i].type != GPU_NONE; i++) {
1503                         gpu_node_output(node, out[i].type, &out[i].link);
1504                         totout++;
1505                 }
1506         }
1507
1508         va_start(params, out);
1509         for (i = 0; i<function->totparam; i++) {
1510                 if (function->paramqual[i] != FUNCTION_QUAL_IN) {
1511                         if (totout == 0) {
1512                                 linkptr = va_arg(params, GPUNodeLink**);
1513                                 gpu_node_output(node, function->paramtype[i], linkptr);
1514                         }
1515                         else
1516                                 totout--;
1517                 }
1518                 else {
1519                         if (totin == 0) {
1520                                 link = va_arg(params, GPUNodeLink*);
1521                                 if (link->socket)
1522                                         gpu_node_input_socket(node, link->socket);
1523                                 else
1524                                         gpu_node_input_link(node, link, function->paramtype[i]);
1525                         }
1526                         else
1527                                 totin--;
1528                 }
1529         }
1530         va_end(params);
1531
1532         gpu_material_add_node(mat, node);
1533         
1534         return 1;
1535 }
1536
1537 int GPU_link_changed(GPUNodeLink *link)
1538 {
1539         GPUNode *node;
1540         GPUInput *input;
1541         const char *name;
1542
1543         if (link->output) {
1544                 node = link->output->node;
1545                 name = node->name;
1546
1547                 if (STREQ(name, "set_value") || STREQ(name, "set_rgb")) {
1548                         input = node->inputs.first;
1549                         return (input->link != NULL);
1550                 }
1551
1552                 return 1;
1553         }
1554         else
1555                 return 0;
1556 }
1557
1558 /* Pass create/free */
1559
1560 static void gpu_nodes_tag(GPUNodeLink *link)
1561 {
1562         GPUNode *node;
1563         GPUInput *input;
1564
1565         if (!link->output)
1566                 return;
1567
1568         node = link->output->node;
1569         if (node->tag)
1570                 return;
1571         
1572         node->tag = true;
1573         for (input = node->inputs.first; input; input = input->next)
1574                 if (input->link)
1575                         gpu_nodes_tag(input->link);
1576 }
1577
1578 static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
1579 {
1580         GPUNode *node, *next;
1581
1582         for (node = nodes->first; node; node = node->next)
1583                 node->tag = false;
1584
1585         gpu_nodes_tag(outlink);
1586
1587         for (node = nodes->first; node; node = next) {
1588                 next = node->next;
1589
1590                 if (!node->tag) {
1591                         BLI_remlink(nodes, node);
1592                         gpu_node_free(node);
1593                 }
1594         }
1595 }
1596
1597 GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink,
1598                                                    GPUVertexAttribs *attribs, int *builtins,
1599                                                    const GPUMatType type, const char *UNUSED(name), const bool use_opensubdiv)
1600 {
1601         GPUShader *shader;
1602         GPUPass *pass;
1603         char *vertexcode, *geometrycode, *fragmentcode;
1604
1605 #if 0
1606         if (!FUNCTION_LIB) {
1607                 GPU_nodes_free(nodes);
1608                 return NULL;
1609         }
1610 #endif
1611
1612         /* prune unused nodes */
1613         gpu_nodes_prune(nodes, outlink);
1614
1615         gpu_nodes_get_vertex_attributes(nodes, attribs);
1616         gpu_nodes_get_builtin_flag(nodes, builtins);
1617
1618         /* generate code and compile with opengl */
1619         fragmentcode = code_generate_fragment(nodes, outlink->output);
1620         vertexcode = code_generate_vertex(nodes, type);
1621         geometrycode = code_generate_geometry(nodes, use_opensubdiv);
1622         shader = GPU_shader_create_ex(vertexcode,
1623                                       fragmentcode,
1624                                       geometrycode,
1625                                       glsl_material_library,
1626                                       NULL,
1627                                       0,
1628                                       0,
1629                                       0,
1630                                       use_opensubdiv ? GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV
1631                                                      : GPU_SHADER_FLAGS_NONE);
1632
1633         /* failed? */
1634         if (!shader) {
1635                 if (fragmentcode)
1636                         MEM_freeN(fragmentcode);
1637                 if (vertexcode)
1638                         MEM_freeN(vertexcode);
1639                 memset(attribs, 0, sizeof(*attribs));
1640                 memset(builtins, 0, sizeof(*builtins));
1641                 gpu_nodes_free(nodes);
1642                 return NULL;
1643         }
1644         
1645         /* create pass */
1646         pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
1647
1648         pass->output = outlink->output;
1649         pass->shader = shader;
1650         pass->fragmentcode = fragmentcode;
1651         pass->geometrycode = geometrycode;
1652         pass->vertexcode = vertexcode;
1653         pass->libcode = glsl_material_library;
1654
1655         /* extract dynamic inputs and throw away nodes */
1656         gpu_nodes_extract_dynamic_inputs(pass, nodes);
1657         gpu_nodes_free(nodes);
1658
1659         return pass;
1660 }
1661
1662 void GPU_pass_free(GPUPass *pass)
1663 {
1664         GPU_shader_free(pass->shader);
1665         gpu_inputs_free(&pass->inputs);
1666         if (pass->fragmentcode)
1667                 MEM_freeN(pass->fragmentcode);
1668         if (pass->geometrycode)
1669                 MEM_freeN(pass->geometrycode);
1670         if (pass->vertexcode)
1671                 MEM_freeN(pass->vertexcode);
1672         MEM_freeN(pass);
1673 }