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