Fix T46951: GLSL draw mode missing some textures.
[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         /* create 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
1011         /* bind the textures, in second loop so texture binding during
1012          * create doesn't overwrite already bound textures */
1013         for (input = inputs->first; input; input = input->next) {
1014                 if (input->tex && input->bindtex) {
1015                         GPU_texture_bind(input->tex, input->texid);
1016                         GPU_shader_uniform_texture(shader, input->shaderloc, input->tex);
1017                 }
1018         }
1019 }
1020
1021 void GPU_pass_update_uniforms(GPUPass *pass)
1022 {
1023         GPUInput *input;
1024         GPUShader *shader = pass->shader;
1025         ListBase *inputs = &pass->inputs;
1026
1027         if (!shader)
1028                 return;
1029
1030         /* pass dynamic inputs to opengl, others were removed */
1031         for (input = inputs->first; input; input = input->next) {
1032                 if (!(input->ima || input->tex || input->prv)) {
1033                         if (input->dynamictype == GPU_DYNAMIC_MAT_HARD) {
1034                                 // The hardness is actually a short pointer, so we convert it here
1035                                 float val = (float)(*(short*)input->dynamicvec);
1036                                 GPU_shader_uniform_vector(shader, input->shaderloc, 1, 1, &val);
1037                         }
1038                         else {
1039                                 GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1,
1040                                         input->dynamicvec);
1041                         }
1042                 }
1043         }
1044 }
1045
1046 void GPU_pass_unbind(GPUPass *pass)
1047 {
1048         GPUInput *input;
1049         GPUShader *shader = pass->shader;
1050         ListBase *inputs = &pass->inputs;
1051
1052         if (!shader)
1053                 return;
1054
1055         for (input = inputs->first; input; input = input->next) {
1056                 if (input->tex && input->bindtex)
1057                         GPU_texture_unbind(input->tex);
1058
1059                 if (input->ima || input->prv)
1060                         input->tex = NULL;
1061         }
1062         
1063         GPU_shader_unbind();
1064 }
1065
1066 /* Node Link Functions */
1067
1068 static GPUNodeLink *GPU_node_link_create(void)
1069 {
1070         GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink");
1071         link->type = GPU_NONE;
1072         link->users++;
1073
1074         return link;
1075 }
1076
1077 static void gpu_node_link_free(GPUNodeLink *link)
1078 {
1079         link->users--;
1080
1081         if (link->users < 0)
1082                 fprintf(stderr, "GPU_node_link_free: negative refcount\n");
1083         
1084         if (link->users == 0) {
1085                 if (link->output)
1086                         link->output->link = NULL;
1087                 MEM_freeN(link);
1088         }
1089 }
1090
1091 /* Node Functions */
1092
1093 static GPUNode *GPU_node_begin(const char *name)
1094 {
1095         GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode");
1096
1097         node->name = name;
1098
1099         return node;
1100 }
1101
1102 static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType type)
1103 {
1104         GPUInput *input;
1105         GPUNode *outnode;
1106         const char *name;
1107
1108         if (link->output) {
1109                 outnode = link->output->node;
1110                 name = outnode->name;
1111                 input = outnode->inputs.first;
1112
1113                 if ((STREQ(name, "set_value") || STREQ(name, "set_rgb")) &&
1114                     (input->type == type))
1115                 {
1116                         input = MEM_dupallocN(outnode->inputs.first);
1117                         input->type = type;
1118                         if (input->link)
1119                                 input->link->users++;
1120                         BLI_addtail(&node->inputs, input);
1121                         return;
1122                 }
1123         }
1124         
1125         input = MEM_callocN(sizeof(GPUInput), "GPUInput");
1126         input->node = node;
1127
1128         if (link->builtin) {
1129                 /* builtin uniform */
1130                 input->type = type;
1131                 input->source = GPU_SOURCE_BUILTIN;
1132                 input->builtin = link->builtin;
1133
1134                 MEM_freeN(link);
1135         }
1136         else if (link->oglbuiltin) {
1137                 /* builtin uniform */
1138                 input->type = type;
1139                 input->source = GPU_SOURCE_OPENGL_BUILTIN;
1140                 input->oglbuiltin = link->oglbuiltin;
1141
1142                 MEM_freeN(link);
1143         }
1144         else if (link->output) {
1145                 /* link to a node output */
1146                 input->type = type;
1147                 input->source = GPU_SOURCE_TEX_PIXEL;
1148                 input->link = link;
1149                 link->users++;
1150         }
1151         else if (link->dynamictex) {
1152                 /* dynamic texture, GPUTexture is updated/deleted externally */
1153                 input->type = type;
1154                 input->source = GPU_SOURCE_TEX;
1155
1156                 input->tex = link->dynamictex;
1157                 input->textarget = GL_TEXTURE_2D;
1158                 input->textype = type;
1159                 input->dynamictex = true;
1160                 input->dynamicdata = link->ptr2;
1161                 MEM_freeN(link);
1162         }
1163         else if (link->texture) {
1164                 /* small texture created on the fly, like for colorbands */
1165                 input->type = GPU_VEC4;
1166                 input->source = GPU_SOURCE_TEX;
1167                 input->textype = type;
1168
1169 #if 0
1170                 input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
1171 #endif
1172                 input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, GPU_HDR_NONE, NULL);
1173                 input->textarget = GL_TEXTURE_2D;
1174
1175                 MEM_freeN(link->ptr1);
1176                 MEM_freeN(link);
1177         }
1178         else if (link->image) {
1179                 /* blender image */
1180                 input->type = GPU_VEC4;
1181                 input->source = GPU_SOURCE_TEX;
1182
1183                 if (link->image == GPU_NODE_LINK_IMAGE_PREVIEW)
1184                         input->prv = link->ptr1;
1185                 else {
1186                         input->ima = link->ptr1;
1187                         input->iuser = link->ptr2;
1188                         input->image_isdata = link->image_isdata;
1189                 }
1190                 input->textarget = GL_TEXTURE_2D;
1191                 input->textype = GPU_TEX2D;
1192                 MEM_freeN(link);
1193         }
1194         else if (link->attribtype) {
1195                 /* vertex attribute */
1196                 input->type = type;
1197                 input->source = GPU_SOURCE_ATTRIB;
1198
1199                 input->attribtype = link->attribtype;
1200                 BLI_strncpy(input->attribname, link->attribname, sizeof(input->attribname));
1201                 MEM_freeN(link);
1202         }
1203         else {
1204                 /* uniform vector */
1205                 input->type = type;
1206                 input->source = GPU_SOURCE_VEC_UNIFORM;
1207
1208                 memcpy(input->vec, link->ptr1, type*sizeof(float));
1209                 if (link->dynamic) {
1210                         input->dynamicvec = link->ptr1;
1211                         input->dynamictype = link->dynamictype;
1212                         input->dynamicdata = link->ptr2;
1213                 }
1214                 MEM_freeN(link);
1215         }
1216
1217         BLI_addtail(&node->inputs, input);
1218 }
1219
1220 static void gpu_node_input_socket(GPUNode *node, GPUNodeStack *sock)
1221 {
1222         GPUNodeLink *link;
1223
1224         if (sock->link) {
1225                 gpu_node_input_link(node, sock->link, sock->type);
1226         }
1227         else {
1228                 link = GPU_node_link_create();
1229                 link->ptr1 = sock->vec;
1230                 gpu_node_input_link(node, link, sock->type);
1231         }
1232 }
1233
1234 static void gpu_node_output(GPUNode *node, const GPUType type, GPUNodeLink **link)
1235 {
1236         GPUOutput *output = MEM_callocN(sizeof(GPUOutput), "GPUOutput");
1237
1238         output->type = type;
1239         output->node = node;
1240
1241         if (link) {
1242                 *link = output->link = GPU_node_link_create();
1243                 output->link->type = type;
1244                 output->link->output = output;
1245
1246                 /* note: the caller owns the reference to the link, GPUOutput
1247                  * merely points to it, and if the node is destroyed it will
1248                  * set that pointer to NULL */
1249         }
1250
1251         BLI_addtail(&node->outputs, output);
1252 }
1253
1254 static void gpu_inputs_free(ListBase *inputs)
1255 {
1256         GPUInput *input;
1257
1258         for (input = inputs->first; input; input = input->next) {
1259                 if (input->link)
1260                         gpu_node_link_free(input->link);
1261                 else if (input->tex && !input->dynamictex)
1262                         GPU_texture_free(input->tex);
1263         }
1264
1265         BLI_freelistN(inputs);
1266 }
1267
1268 static void gpu_node_free(GPUNode *node)
1269 {
1270         GPUOutput *output;
1271
1272         gpu_inputs_free(&node->inputs);
1273
1274         for (output = node->outputs.first; output; output = output->next)
1275                 if (output->link) {
1276                         output->link->output = NULL;
1277                         gpu_node_link_free(output->link);
1278                 }
1279
1280         BLI_freelistN(&node->outputs);
1281         MEM_freeN(node);
1282 }
1283
1284 static void gpu_nodes_free(ListBase *nodes)
1285 {
1286         GPUNode *node;
1287
1288         while ((node = BLI_pophead(nodes))) {
1289                 gpu_node_free(node);
1290         }
1291 }
1292
1293 /* vertex attributes */
1294
1295 static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs)
1296 {
1297         GPUNode *node;
1298         GPUInput *input;
1299         int a;
1300
1301         /* convert attributes requested by node inputs to an array of layers,
1302          * checking for duplicates and assigning id's starting from zero. */
1303
1304         memset(attribs, 0, sizeof(*attribs));
1305
1306         for (node = nodes->first; node; node = node->next) {
1307                 for (input = node->inputs.first; input; input = input->next) {
1308                         if (input->source == GPU_SOURCE_ATTRIB) {
1309                                 for (a = 0; a < attribs->totlayer; a++) {
1310                                         if (attribs->layer[a].type == input->attribtype &&
1311                                             STREQ(attribs->layer[a].name, input->attribname))
1312                                         {
1313                                                 break;
1314                                         }
1315                                 }
1316
1317                                 if (a < GPU_MAX_ATTRIB) {
1318                                         if (a == attribs->totlayer) {
1319                                                 input->attribid = attribs->totlayer++;
1320                                                 input->attribfirst = 1;
1321
1322                                                 attribs->layer[a].type = input->attribtype;
1323                                                 attribs->layer[a].attribid = input->attribid;
1324                                                 BLI_strncpy(attribs->layer[a].name, input->attribname,
1325                                                             sizeof(attribs->layer[a].name));
1326                                         }
1327                                         else {
1328                                                 input->attribid = attribs->layer[a].attribid;
1329                                         }
1330                                 }
1331                         }
1332                 }
1333         }
1334 }
1335
1336 static void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin)
1337 {
1338         GPUNode *node;
1339         GPUInput *input;
1340         
1341         *builtin = 0;
1342
1343         for (node = nodes->first; node; node = node->next)
1344                 for (input = node->inputs.first; input; input = input->next)
1345                         if (input->source == GPU_SOURCE_BUILTIN)
1346                                 *builtin |= input->builtin;
1347 }
1348
1349 /* varargs linking  */
1350
1351 GPUNodeLink *GPU_attribute(const CustomDataType type, const char *name)
1352 {
1353         GPUNodeLink *link = GPU_node_link_create();
1354
1355         link->attribtype = type;
1356         link->attribname = name;
1357
1358         return link;
1359 }
1360
1361 GPUNodeLink *GPU_uniform(float *num)
1362 {
1363         GPUNodeLink *link = GPU_node_link_create();
1364
1365         link->ptr1 = num;
1366         link->ptr2 = NULL;
1367
1368         return link;
1369 }
1370
1371 GPUNodeLink *GPU_dynamic_uniform(float *num, GPUDynamicType dynamictype, void *data)
1372 {
1373         GPUNodeLink *link = GPU_node_link_create();
1374
1375         link->ptr1 = num;
1376         link->ptr2 = data;
1377         link->dynamic = true;
1378         link->dynamictype = dynamictype;
1379
1380
1381         return link;
1382 }
1383
1384 GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data)
1385 {
1386         GPUNodeLink *link = GPU_node_link_create();
1387
1388         link->image = GPU_NODE_LINK_IMAGE_BLENDER;
1389         link->ptr1 = ima;
1390         link->ptr2 = iuser;
1391         link->image_isdata = is_data;
1392
1393         return link;
1394 }
1395
1396 GPUNodeLink *GPU_image_preview(PreviewImage *prv)
1397 {
1398         GPUNodeLink *link = GPU_node_link_create();
1399         
1400         link->image = GPU_NODE_LINK_IMAGE_PREVIEW;
1401         link->ptr1 = prv;
1402         
1403         return link;
1404 }
1405
1406
1407 GPUNodeLink *GPU_texture(int size, float *pixels)
1408 {
1409         GPUNodeLink *link = GPU_node_link_create();
1410
1411         link->texture = true;
1412         link->texturesize = size;
1413         link->ptr1 = pixels;
1414
1415         return link;
1416 }
1417
1418 GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex, GPUDynamicType dynamictype, void *data)
1419 {
1420         GPUNodeLink *link = GPU_node_link_create();
1421
1422         link->dynamic = true;
1423         link->dynamictex = tex;
1424         link->dynamictype = dynamictype;
1425         link->ptr2 = data;
1426
1427         return link;
1428 }
1429
1430 GPUNodeLink *GPU_builtin(GPUBuiltin builtin)
1431 {
1432         GPUNodeLink *link = GPU_node_link_create();
1433
1434         link->builtin= builtin;
1435
1436         return link;
1437 }
1438
1439 GPUNodeLink *GPU_opengl_builtin(GPUOpenGLBuiltin builtin)
1440 {
1441         GPUNodeLink *link = GPU_node_link_create();
1442
1443         link->oglbuiltin = builtin;
1444
1445         return link;
1446 }
1447
1448 bool GPU_link(GPUMaterial *mat, const char *name, ...)
1449 {
1450         GPUNode *node;
1451         GPUFunction *function;
1452         GPUNodeLink *link, **linkptr;
1453         va_list params;
1454         int i;
1455
1456         function = gpu_lookup_function(name);
1457         if (!function) {
1458                 fprintf(stderr, "GPU failed to find function %s\n", name);
1459                 return 0;
1460         }
1461
1462         node = GPU_node_begin(name);
1463
1464         va_start(params, name);
1465         for (i = 0; i<function->totparam; i++) {
1466                 if (function->paramqual[i] != FUNCTION_QUAL_IN) {
1467                         linkptr = va_arg(params, GPUNodeLink**);
1468                         gpu_node_output(node, function->paramtype[i], linkptr);
1469                 }
1470                 else {
1471                         link = va_arg(params, GPUNodeLink*);
1472                         gpu_node_input_link(node, link, function->paramtype[i]);
1473                 }
1474         }
1475         va_end(params);
1476
1477         gpu_material_add_node(mat, node);
1478
1479         return 1;
1480 }
1481
1482 bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...)
1483 {
1484         GPUNode *node;
1485         GPUFunction *function;
1486         GPUNodeLink *link, **linkptr;
1487         va_list params;
1488         int i, totin, totout;
1489
1490         function = gpu_lookup_function(name);
1491         if (!function) {
1492                 fprintf(stderr, "GPU failed to find function %s\n", name);
1493                 return 0;
1494         }
1495
1496         node = GPU_node_begin(name);
1497         totin = 0;
1498         totout = 0;
1499
1500         if (in) {
1501                 for (i = 0; in[i].type != GPU_NONE; i++) {
1502                         gpu_node_input_socket(node, &in[i]);
1503                         totin++;
1504                 }
1505         }
1506         
1507         if (out) {
1508                 for (i = 0; out[i].type != GPU_NONE; i++) {
1509                         gpu_node_output(node, out[i].type, &out[i].link);
1510                         totout++;
1511                 }
1512         }
1513
1514         va_start(params, out);
1515         for (i = 0; i<function->totparam; i++) {
1516                 if (function->paramqual[i] != FUNCTION_QUAL_IN) {
1517                         if (totout == 0) {
1518                                 linkptr = va_arg(params, GPUNodeLink**);
1519                                 gpu_node_output(node, function->paramtype[i], linkptr);
1520                         }
1521                         else
1522                                 totout--;
1523                 }
1524                 else {
1525                         if (totin == 0) {
1526                                 link = va_arg(params, GPUNodeLink*);
1527                                 if (link->socket)
1528                                         gpu_node_input_socket(node, link->socket);
1529                                 else
1530                                         gpu_node_input_link(node, link, function->paramtype[i]);
1531                         }
1532                         else
1533                                 totin--;
1534                 }
1535         }
1536         va_end(params);
1537
1538         gpu_material_add_node(mat, node);
1539         
1540         return 1;
1541 }
1542
1543 int GPU_link_changed(GPUNodeLink *link)
1544 {
1545         GPUNode *node;
1546         GPUInput *input;
1547         const char *name;
1548
1549         if (link->output) {
1550                 node = link->output->node;
1551                 name = node->name;
1552
1553                 if (STREQ(name, "set_value") || STREQ(name, "set_rgb")) {
1554                         input = node->inputs.first;
1555                         return (input->link != NULL);
1556                 }
1557
1558                 return 1;
1559         }
1560         else
1561                 return 0;
1562 }
1563
1564 /* Pass create/free */
1565
1566 static void gpu_nodes_tag(GPUNodeLink *link)
1567 {
1568         GPUNode *node;
1569         GPUInput *input;
1570
1571         if (!link->output)
1572                 return;
1573
1574         node = link->output->node;
1575         if (node->tag)
1576                 return;
1577         
1578         node->tag = true;
1579         for (input = node->inputs.first; input; input = input->next)
1580                 if (input->link)
1581                         gpu_nodes_tag(input->link);
1582 }
1583
1584 static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
1585 {
1586         GPUNode *node, *next;
1587
1588         for (node = nodes->first; node; node = node->next)
1589                 node->tag = false;
1590
1591         gpu_nodes_tag(outlink);
1592
1593         for (node = nodes->first; node; node = next) {
1594                 next = node->next;
1595
1596                 if (!node->tag) {
1597                         BLI_remlink(nodes, node);
1598                         gpu_node_free(node);
1599                 }
1600         }
1601 }
1602
1603 GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink,
1604                                                    GPUVertexAttribs *attribs, int *builtins,
1605                                                    const GPUMatType type, const char *UNUSED(name), const bool use_opensubdiv)
1606 {
1607         GPUShader *shader;
1608         GPUPass *pass;
1609         char *vertexcode, *geometrycode, *fragmentcode;
1610
1611 #if 0
1612         if (!FUNCTION_LIB) {
1613                 GPU_nodes_free(nodes);
1614                 return NULL;
1615         }
1616 #endif
1617
1618         /* prune unused nodes */
1619         gpu_nodes_prune(nodes, outlink);
1620
1621         gpu_nodes_get_vertex_attributes(nodes, attribs);
1622         gpu_nodes_get_builtin_flag(nodes, builtins);
1623
1624         /* generate code and compile with opengl */
1625         fragmentcode = code_generate_fragment(nodes, outlink->output);
1626         vertexcode = code_generate_vertex(nodes, type);
1627         geometrycode = code_generate_geometry(nodes, use_opensubdiv);
1628         shader = GPU_shader_create_ex(vertexcode,
1629                                       fragmentcode,
1630                                       geometrycode,
1631                                       glsl_material_library,
1632                                       NULL,
1633                                       0,
1634                                       0,
1635                                       0,
1636                                       use_opensubdiv ? GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV
1637                                                      : GPU_SHADER_FLAGS_NONE);
1638
1639         /* failed? */
1640         if (!shader) {
1641                 if (fragmentcode)
1642                         MEM_freeN(fragmentcode);
1643                 if (vertexcode)
1644                         MEM_freeN(vertexcode);
1645                 memset(attribs, 0, sizeof(*attribs));
1646                 memset(builtins, 0, sizeof(*builtins));
1647                 gpu_nodes_free(nodes);
1648                 return NULL;
1649         }
1650         
1651         /* create pass */
1652         pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
1653
1654         pass->output = outlink->output;
1655         pass->shader = shader;
1656         pass->fragmentcode = fragmentcode;
1657         pass->geometrycode = geometrycode;
1658         pass->vertexcode = vertexcode;
1659         pass->libcode = glsl_material_library;
1660
1661         /* extract dynamic inputs and throw away nodes */
1662         gpu_nodes_extract_dynamic_inputs(pass, nodes);
1663         gpu_nodes_free(nodes);
1664
1665         return pass;
1666 }
1667
1668 void GPU_pass_free(GPUPass *pass)
1669 {
1670         GPU_shader_free(pass->shader);
1671         gpu_inputs_free(&pass->inputs);
1672         if (pass->fragmentcode)
1673                 MEM_freeN(pass->fragmentcode);
1674         if (pass->geometrycode)
1675                 MEM_freeN(pass->geometrycode);
1676         if (pass->vertexcode)
1677                 MEM_freeN(pass->vertexcode);
1678         MEM_freeN(pass);
1679 }