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