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