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