style cleanup, brackets in else/if, some indentation.
[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
32
33 #include "GL/glew.h"
34
35 #include "MEM_guardedalloc.h"
36
37 #include "DNA_customdata_types.h"
38 #include "DNA_image_types.h"
39 #include "DNA_material_types.h"
40
41 #include "BLI_blenlib.h"
42 #include "BLI_utildefines.h"
43 #include "BLI_dynstr.h"
44 #include "BLI_ghash.h"
45 #include "BLI_heap.h"
46
47 #include "GPU_material.h"
48 #include "GPU_extensions.h"
49
50 #include "BLO_sys_types.h" // for intptr_t support
51
52 #include "gpu_codegen.h"
53
54 #include "node_util.h" /* For muting node stuff... */
55
56 #include <string.h>
57 #include <stdarg.h>
58
59 extern char datatoc_gpu_shader_material_glsl[];
60 extern char datatoc_gpu_shader_vertex_glsl[];
61
62
63 static char *glsl_material_library = NULL;
64
65
66 /* structs and defines */
67
68 static const char* GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4",
69         NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4"};
70
71 /* GLSL code parsing for finding function definitions.
72  * These are stored in a hash for lookup when creating a material. */
73
74 static GHash *FUNCTION_HASH= NULL;
75 /*static char *FUNCTION_PROTOTYPES= NULL;
76 static GPUShader *FUNCTION_LIB= NULL;*/
77
78 static int gpu_str_prefix(const char *str, const char *prefix)
79 {
80         while(*str && *prefix) {
81                 if(*str != *prefix)
82                         return 0;
83
84                 str++;
85                 prefix++;
86         }
87         
88         return (*prefix == '\0');
89 }
90
91 static char *gpu_str_skip_token(char *str, char *token, int max)
92 {
93         int len = 0;
94
95         /* skip a variable/function name */
96         while(*str) {
97                 if(ELEM7(*str, ' ', '(', ')', ',', '\t', '\n', '\r'))
98                         break;
99                 else {
100                         if(token && len < max-1) {
101                                 *token= *str;
102                                 token++;
103                                 len++;
104                         }
105                         str++;
106                 }
107         }
108
109         if(token)
110                 *token= '\0';
111
112         /* skip the next special characters:
113          * note the missing ')' */
114         while(*str) {
115                 if(ELEM6(*str, ' ', '(', ',', '\t', '\n', '\r'))
116                         str++;
117                 else
118                         break;
119         }
120
121         return str;
122 }
123
124 static void gpu_parse_functions_string(GHash *hash, char *code)
125 {
126         GPUFunction *function;
127         int i, type, qual;
128
129         while((code = strstr(code, "void "))) {
130                 function = MEM_callocN(sizeof(GPUFunction), "GPUFunction");
131
132                 code = gpu_str_skip_token(code, NULL, 0);
133                 code = gpu_str_skip_token(code, function->name, MAX_FUNCTION_NAME);
134
135                 /* get parameters */
136                 while(*code && *code != ')') {
137                         /* test if it's an input or output */
138                         qual = FUNCTION_QUAL_IN;
139                         if(gpu_str_prefix(code, "out "))
140                                 qual = FUNCTION_QUAL_OUT;
141                         if(gpu_str_prefix(code, "inout "))
142                                 qual = FUNCTION_QUAL_INOUT;
143                         if((qual != FUNCTION_QUAL_IN) || gpu_str_prefix(code, "in "))
144                                 code = gpu_str_skip_token(code, NULL, 0);
145
146                         /* test for type */
147                         type= 0;
148                         for(i=1; i<=16; i++) {
149                                 if(GPU_DATATYPE_STR[i] && gpu_str_prefix(code, GPU_DATATYPE_STR[i])) {
150                                         type= i;
151                                         break;
152                                 }
153                         }
154
155                         if(!type && gpu_str_prefix(code, "sampler2DShadow"))
156                                 type= GPU_SHADOW2D;
157                         if(!type && gpu_str_prefix(code, "sampler2D"))
158                                 type= GPU_TEX2D;
159
160                         if(type) {
161                                 /* add paramater */
162                                 code = gpu_str_skip_token(code, NULL, 0);
163                                 code = gpu_str_skip_token(code, NULL, 0);
164                                 function->paramqual[function->totparam]= qual;
165                                 function->paramtype[function->totparam]= type;
166                                 function->totparam++;
167                         }
168                         else {
169                                 fprintf(stderr, "GPU invalid function parameter in %s.\n", function->name);
170                                 break;
171                         }
172                 }
173
174                 if(function->name[0] == '\0' || function->totparam == 0) {
175                         fprintf(stderr, "GPU functions parse error.\n");
176                         MEM_freeN(function);
177                         break;
178                 }
179
180                 BLI_ghash_insert(hash, function->name, function);
181         }
182 }
183
184 #if 0
185 static char *gpu_generate_function_prototyps(GHash *hash)
186 {
187         DynStr *ds = BLI_dynstr_new();
188         GHashIterator *ghi;
189         GPUFunction *function;
190         char *name, *prototypes;
191         int a;
192         
193         /* automatically generate function prototypes to add to the top of the
194          * generated code, to avoid have to add the actual code & recompile all */
195         ghi = BLI_ghashIterator_new(hash);
196
197         for(; !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) {
198                 name = BLI_ghashIterator_getValue(ghi);
199                 function = BLI_ghashIterator_getValue(ghi);
200
201                 BLI_dynstr_appendf(ds, "void %s(", name);
202                 for(a=0; a<function->totparam; a++) {
203                         if(function->paramqual[a] == FUNCTION_QUAL_OUT)
204                                 BLI_dynstr_append(ds, "out ");
205                         else if(function->paramqual[a] == FUNCTION_QUAL_INOUT)
206                                 BLI_dynstr_append(ds, "inout ");
207
208                         if(function->paramtype[a] == GPU_TEX2D)
209                                 BLI_dynstr_append(ds, "sampler2D");
210                         else if(function->paramtype[a] == GPU_SHADOW2D)
211                                 BLI_dynstr_append(ds, "sampler2DShadow");
212                         else
213                                 BLI_dynstr_append(ds, GPU_DATATYPE_STR[function->paramtype[a]]);
214                                 
215                         //BLI_dynstr_appendf(ds, " param%d", a);
216                         
217                         if(a != function->totparam-1)
218                                 BLI_dynstr_append(ds, ", ");
219                 }
220                 BLI_dynstr_append(ds, ");\n");
221         }
222
223         BLI_dynstr_append(ds, "\n");
224
225         prototypes = BLI_dynstr_get_cstring(ds);
226         BLI_dynstr_free(ds);
227
228         return prototypes;
229 }
230 #endif
231
232 GPUFunction *GPU_lookup_function(const char *name)
233 {
234         if(!FUNCTION_HASH) {
235                 FUNCTION_HASH = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "GPU_lookup_function gh");
236                 gpu_parse_functions_string(FUNCTION_HASH, glsl_material_library);
237                 /*FUNCTION_PROTOTYPES = gpu_generate_function_prototyps(FUNCTION_HASH);
238                 FUNCTION_LIB = GPU_shader_create_lib(datatoc_gpu_shader_material_glsl);*/
239         }
240
241         return (GPUFunction*)BLI_ghash_lookup(FUNCTION_HASH, (void *)name);
242 }
243
244 void GPU_codegen_init(void)
245 {
246         GPU_code_generate_glsl_lib();
247 }
248
249 void GPU_codegen_exit(void)
250 {
251         extern Material defmaterial;    // render module abuse...
252
253         if(defmaterial.gpumaterial.first)
254                 GPU_material_free(&defmaterial);
255
256         if(FUNCTION_HASH) {
257                 BLI_ghash_free(FUNCTION_HASH, NULL, (GHashValFreeFP)MEM_freeN);
258                 FUNCTION_HASH = NULL;
259         }
260
261         if(glsl_material_library) {
262                 MEM_freeN(glsl_material_library);
263                 glsl_material_library = NULL;
264         }
265
266         /*if(FUNCTION_PROTOTYPES) {
267                 MEM_freeN(FUNCTION_PROTOTYPES);
268                 FUNCTION_PROTOTYPES = NULL;
269         }*/
270         /*if(FUNCTION_LIB) {
271                 GPU_shader_free(FUNCTION_LIB);
272                 FUNCTION_LIB = NULL;
273         }*/
274 }
275
276 /* GLSL code generation */
277
278 static void codegen_convert_datatype(DynStr *ds, int from, int to, const char *tmp, int id)
279 {
280         char name[1024];
281
282         BLI_snprintf(name, sizeof(name), "%s%d", tmp, id);
283
284         if (from == to) {
285                 BLI_dynstr_append(ds, name);
286         }
287         else if (to == GPU_FLOAT) {
288                 if (from == GPU_VEC4)
289                         BLI_dynstr_appendf(ds, "dot(%s.rgb, vec3(0.35, 0.45, 0.2))", name);
290                 else if (from == GPU_VEC3)
291                         BLI_dynstr_appendf(ds, "dot(%s, vec3(0.33))", name);
292                 else if (from == GPU_VEC2)
293                         BLI_dynstr_appendf(ds, "%s.r", name);
294         }
295         else if (to == GPU_VEC2) {
296                 if (from == GPU_VEC4)
297                         BLI_dynstr_appendf(ds, "vec2(dot(%s.rgb, vec3(0.35, 0.45, 0.2)), %s.a)", name, name);
298                 else if (from == GPU_VEC3)
299                         BLI_dynstr_appendf(ds, "vec2(dot(%s.rgb, vec3(0.33)), 1.0)", name);
300                 else if (from == GPU_FLOAT)
301                         BLI_dynstr_appendf(ds, "vec2(%s, 1.0)", name);
302         }
303         else if (to == GPU_VEC3) {
304                 if (from == GPU_VEC4)
305                         BLI_dynstr_appendf(ds, "%s.rgb", name);
306                 else if (from == GPU_VEC2)
307                         BLI_dynstr_appendf(ds, "vec3(%s.r, %s.r, %s.r)", name, name, name);
308                 else if (from == GPU_FLOAT)
309                         BLI_dynstr_appendf(ds, "vec3(%s, %s, %s)", name, name, name);
310         }
311         else {
312                 if (from == GPU_VEC3)
313                         BLI_dynstr_appendf(ds, "vec4(%s, 1.0)", name);
314                 else if (from == GPU_VEC2)
315                         BLI_dynstr_appendf(ds, "vec4(%s.r, %s.r, %s.r, %s.g)", name, name, name, name);
316                 else if (from == GPU_FLOAT)
317                         BLI_dynstr_appendf(ds, "vec4(%s, %s, %s, 1.0)", name, name, name);
318         }
319 }
320
321 static void codegen_print_datatype(DynStr *ds, int type, float *data)
322 {
323         int i;
324
325         BLI_dynstr_appendf(ds, "%s(", GPU_DATATYPE_STR[type]);
326
327         for(i=0; i<type; i++) {
328                 BLI_dynstr_appendf(ds, "%f", data[i]);
329                 if(i == type-1)
330                         BLI_dynstr_append(ds, ")");
331                 else
332                         BLI_dynstr_append(ds, ", ");
333         }
334 }
335
336 static int codegen_input_has_texture(GPUInput *input)
337 {
338         if (input->link)
339                 return 0;
340         else if(input->ima)
341                 return 1;
342         else
343                 return input->tex != NULL;
344 }
345
346 const char *GPU_builtin_name(GPUBuiltin builtin)
347 {
348         if(builtin == GPU_VIEW_MATRIX)
349                 return "unfviewmat";
350         else if(builtin == GPU_OBJECT_MATRIX)
351                 return "unfobmat";
352         else if(builtin == GPU_INVERSE_VIEW_MATRIX)
353                 return "unfinvviewmat";
354         else if(builtin == GPU_INVERSE_OBJECT_MATRIX)
355                 return "unfinvobmat";
356         else if(builtin == GPU_VIEW_POSITION)
357                 return "varposition";
358         else if(builtin == GPU_VIEW_NORMAL)
359                 return "varnormal";
360         else if(builtin == GPU_OBCOLOR)
361                 return "unfobcolor";
362         else if(builtin == GPU_AUTO_BUMPSCALE)
363                 return "unfobautobumpscale";
364         else
365                 return "";
366 }
367
368 static void codegen_set_unique_ids(ListBase *nodes)
369 {
370         GHash *bindhash, *definehash;
371         GPUNode *node;
372         GPUInput *input;
373         GPUOutput *output;
374         int id = 1, texid = 0;
375
376         bindhash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "codegen_set_unique_ids1 gh");
377         definehash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "codegen_set_unique_ids2 gh");
378
379         for (node=nodes->first; node; node=node->next) {
380                 for (input=node->inputs.first; input; input=input->next) {
381                         /* set id for unique names of uniform variables */
382                         input->id = id++;
383                         input->bindtex = 0;
384                         input->definetex = 0;
385
386                         /* set texid used for settings texture slot with multitexture */
387                         if (codegen_input_has_texture(input) &&
388                                 ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL))) {
389                                 if (input->link) {
390                                         /* input is texture from buffer, assign only one texid per
391                                            buffer to avoid sampling the same texture twice */
392                                         if (!BLI_ghash_haskey(bindhash, input->link)) {
393                                                 input->texid = texid++;
394                                                 input->bindtex = 1;
395                                                 BLI_ghash_insert(bindhash, input->link, SET_INT_IN_POINTER(input->texid));
396                                         }
397                                         else
398                                                 input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->link));
399                                 }
400                                 else if(input->ima) {
401                                         /* input is texture from image, assign only one texid per
402                                            buffer to avoid sampling the same texture twice */
403                                         if (!BLI_ghash_haskey(bindhash, input->ima)) {
404                                                 input->texid = texid++;
405                                                 input->bindtex = 1;
406                                                 BLI_ghash_insert(bindhash, input->ima, SET_INT_IN_POINTER(input->texid));
407                                         }
408                                         else
409                                                 input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->ima));
410                                 }
411                                 else {
412                                         if (!BLI_ghash_haskey(bindhash, input->tex)) {
413                                                 /* input is user created texture, check tex pointer */
414                                                 input->texid = texid++;
415                                                 input->bindtex = 1;
416                                                 BLI_ghash_insert(bindhash, input->tex, SET_INT_IN_POINTER(input->texid));
417                                         }
418                                         else
419                                                 input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->tex));
420                                 }
421
422                                 /* make sure this pixel is defined exactly once */
423                                 if (input->source == GPU_SOURCE_TEX_PIXEL) {
424                                         if(input->ima) {
425                                                 if (!BLI_ghash_haskey(definehash, input->ima)) {
426                                                         input->definetex = 1;
427                                                         BLI_ghash_insert(definehash, input->ima, SET_INT_IN_POINTER(input->texid));
428                                                 }
429                                         }
430                                         else {
431                                                 if (!BLI_ghash_haskey(definehash, input->link)) {
432                                                         input->definetex = 1;
433                                                         BLI_ghash_insert(definehash, input->link, SET_INT_IN_POINTER(input->texid));
434                                                 }
435                                         }
436                                 }
437                         }
438                 }
439
440                 for (output=node->outputs.first; output; output=output->next)
441                         /* set id for unique names of tmp variables storing output */
442                         output->id = id++;
443         }
444
445         BLI_ghash_free(bindhash, NULL, NULL);
446         BLI_ghash_free(definehash, NULL, NULL);
447 }
448
449 static void codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
450 {
451         GPUNode *node;
452         GPUInput *input;
453         const char *name;
454         int builtins = 0;
455
456         /* print uniforms */
457         for (node=nodes->first; node; node=node->next) {
458                 for (input=node->inputs.first; input; input=input->next) {
459                         if ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL)) {
460                                 /* create exactly one sampler for each texture */
461                                 if (codegen_input_has_texture(input) && input->bindtex)
462                                         BLI_dynstr_appendf(ds, "uniform %s samp%d;\n",
463                                                 (input->textype == GPU_TEX2D)? "sampler2D": "sampler2DShadow",
464                                                 input->texid);
465                         }
466                         else if(input->source == GPU_SOURCE_BUILTIN) {
467                                 /* only define each builting uniform/varying once */
468                                 if(!(builtins & input->builtin)) {
469                                         builtins |= input->builtin;
470                                         name = GPU_builtin_name(input->builtin);
471
472                                         if(gpu_str_prefix(name, "unf")) {
473                                                 BLI_dynstr_appendf(ds, "uniform %s %s;\n",
474                                                         GPU_DATATYPE_STR[input->type], name);
475                                         }
476                                         else {
477                                                 BLI_dynstr_appendf(ds, "varying %s %s;\n",
478                                                         GPU_DATATYPE_STR[input->type], name);
479                                         }
480                                 }
481                         }
482                         else if (input->source == GPU_SOURCE_VEC_UNIFORM) {
483                                 if(input->dynamicvec) {
484                                         /* only create uniforms for dynamic vectors */
485                                         BLI_dynstr_appendf(ds, "uniform %s unf%d;\n",
486                                                 GPU_DATATYPE_STR[input->type], input->id);
487                                 }
488                                 else {
489                                         /* for others use const so the compiler can do folding */
490                                         BLI_dynstr_appendf(ds, "const %s cons%d = ",
491                                                 GPU_DATATYPE_STR[input->type], input->id);
492                                         codegen_print_datatype(ds, input->type, input->vec);
493                                         BLI_dynstr_append(ds, ";\n");
494                                 }
495                         }
496                         else if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
497                                 BLI_dynstr_appendf(ds, "varying %s var%d;\n",
498                                         GPU_DATATYPE_STR[input->type], input->attribid);
499                         }
500                 }
501         }
502
503         BLI_dynstr_append(ds, "\n");
504 }
505
506 static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
507 {
508         GPUNode *node;
509         GPUInput *input;
510         GPUOutput *output;
511
512         for (node=nodes->first; node; node=node->next) {
513                 /* load pixels from textures */
514                 for (input=node->inputs.first; input; input=input->next) {
515                         if (input->source == GPU_SOURCE_TEX_PIXEL) {
516                                 if (codegen_input_has_texture(input) && input->definetex) {
517                                         BLI_dynstr_appendf(ds, "\tvec4 tex%d = texture2D(", input->texid);
518                                         BLI_dynstr_appendf(ds, "samp%d, gl_TexCoord[%d].st);\n",
519                                                 input->texid, input->texid);
520                                 }
521                         }
522                 }
523
524                 /* declare temporary variables for node output storage */
525                 for (output=node->outputs.first; output; output=output->next)
526                         BLI_dynstr_appendf(ds, "\t%s tmp%d;\n",
527                                 GPU_DATATYPE_STR[output->type], output->id);
528         }
529
530         BLI_dynstr_append(ds, "\n");
531 }
532
533 static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *finaloutput)
534 {
535         GPUNode *node;
536         GPUInput *input;
537         GPUOutput *output;
538
539         for (node=nodes->first; node; node=node->next) {
540                 BLI_dynstr_appendf(ds, "\t%s(", node->name);
541                 
542                 for (input=node->inputs.first; input; input=input->next) {
543                         if (input->source == GPU_SOURCE_TEX) {
544                                 BLI_dynstr_appendf(ds, "samp%d", input->texid);
545                                 if (input->link)
546                                         BLI_dynstr_appendf(ds, ", gl_TexCoord[%d].st", input->texid);
547                         }
548                         else if (input->source == GPU_SOURCE_TEX_PIXEL) {
549                                 codegen_convert_datatype(ds, input->link->output->type, input->type,
550                                         "tmp", input->link->output->id);
551                         }
552                         else if(input->source == GPU_SOURCE_BUILTIN)
553                                 BLI_dynstr_appendf(ds, "%s", GPU_builtin_name(input->builtin));
554                         else if(input->source == GPU_SOURCE_VEC_UNIFORM) {
555                                 if(input->dynamicvec)
556                                         BLI_dynstr_appendf(ds, "unf%d", input->id);
557                                 else
558                                         BLI_dynstr_appendf(ds, "cons%d", input->id);
559                         }
560                         else if (input->source == GPU_SOURCE_ATTRIB)
561                                 BLI_dynstr_appendf(ds, "var%d", input->attribid);
562
563                         BLI_dynstr_append(ds, ", ");
564                 }
565
566                 for (output=node->outputs.first; output; output=output->next) {
567                         BLI_dynstr_appendf(ds, "tmp%d", output->id);
568                         if (output->next)
569                                 BLI_dynstr_append(ds, ", ");
570                 }
571
572                 BLI_dynstr_append(ds, ");\n");
573         }
574
575         BLI_dynstr_append(ds, "\n\tgl_FragColor = ");
576         codegen_convert_datatype(ds, finaloutput->type, GPU_VEC4, "tmp", finaloutput->id);
577         BLI_dynstr_append(ds, ";\n");
578 }
579
580 static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, const char *UNUSED(name))
581 {
582         DynStr *ds = BLI_dynstr_new();
583         char *code;
584
585         /*BLI_dynstr_append(ds, FUNCTION_PROTOTYPES);*/
586
587         codegen_set_unique_ids(nodes);
588         codegen_print_uniforms_functions(ds, nodes);
589
590         //if(G.f & G_DEBUG)
591         //      BLI_dynstr_appendf(ds, "/* %s */\n", name);
592
593         BLI_dynstr_append(ds, "void main(void)\n");
594         BLI_dynstr_append(ds, "{\n");
595
596         codegen_declare_tmps(ds, nodes);
597         codegen_call_functions(ds, nodes, output);
598
599         BLI_dynstr_append(ds, "}\n");
600
601         /* create shader */
602         code = BLI_dynstr_get_cstring(ds);
603         BLI_dynstr_free(ds);
604
605         //if(G.f & G_DEBUG) printf("%s\n", code);
606
607         return code;
608 }
609
610 static char *code_generate_vertex(ListBase *nodes)
611 {
612         DynStr *ds = BLI_dynstr_new();
613         GPUNode *node;
614         GPUInput *input;
615         char *code;
616         
617         for (node=nodes->first; node; node=node->next) {
618                 for (input=node->inputs.first; input; input=input->next) {
619                         if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
620                                 BLI_dynstr_appendf(ds, "attribute %s att%d;\n",
621                                         GPU_DATATYPE_STR[input->type], input->attribid);
622                                 BLI_dynstr_appendf(ds, "varying %s var%d;\n",
623                                         GPU_DATATYPE_STR[input->type], input->attribid);
624                         }
625                 }
626         }
627
628         BLI_dynstr_append(ds, "\n");
629         BLI_dynstr_append(ds, datatoc_gpu_shader_vertex_glsl);
630
631         for (node=nodes->first; node; node=node->next)
632                 for (input=node->inputs.first; input; input=input->next)
633                         if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
634                                 if(input->attribtype == CD_TANGENT) { /* silly exception */
635                                         BLI_dynstr_appendf(ds, "\tvar%d.xyz = normalize((gl_ModelViewMatrix * vec4(att%d.xyz, 0)).xyz);\n", input->attribid, input->attribid);
636                                         BLI_dynstr_appendf(ds, "\tvar%d.w = att%d.w;\n", input->attribid, input->attribid);
637                                 }
638                                 else
639                                         BLI_dynstr_appendf(ds, "\tvar%d = att%d;\n", input->attribid, input->attribid);
640                         }
641
642         BLI_dynstr_append(ds, "}\n\n");
643
644         code = BLI_dynstr_get_cstring(ds);
645
646         BLI_dynstr_free(ds);
647
648         //if(G.f & G_DEBUG) printf("%s\n", code);
649
650         return code;
651 }
652
653 int GPU_bicubic_bump_support(void)
654 {
655         return GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0;
656 }
657
658 void GPU_code_generate_glsl_lib(void)
659 {
660         DynStr *ds;
661
662         /* only initialize the library once */
663         if(glsl_material_library)
664                 return;
665
666         ds = BLI_dynstr_new();
667
668         if(GPU_bicubic_bump_support()){
669                 BLI_dynstr_append(ds, "/* These are needed for high quality bump mapping */\n"
670                                 "#version 130\n"
671                                 "#extension GL_ARB_texture_query_lod: enable\n"
672                                 "#define BUMP_BICUBIC\n");
673         }
674         BLI_dynstr_append(ds, datatoc_gpu_shader_material_glsl);
675
676
677         glsl_material_library = BLI_dynstr_get_cstring(ds);
678
679         BLI_dynstr_free(ds);
680 }
681
682
683 /* GPU pass binding/unbinding */
684
685 GPUShader *GPU_pass_shader(GPUPass *pass)
686 {
687         return pass->shader;
688 }
689
690 static void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
691 {
692         GPUShader *shader = pass->shader;
693         GPUNode *node;
694         GPUInput *next, *input;
695         ListBase *inputs = &pass->inputs;
696         int extract, z;
697
698         memset(inputs, 0, sizeof(*inputs));
699
700         if(!shader)
701                 return;
702
703         GPU_shader_bind(shader);
704
705         for (node=nodes->first; node; node=node->next) {
706                 z = 0;
707                 for (input=node->inputs.first; input; input=next, z++) {
708                         next = input->next;
709
710                         /* attributes don't need to be bound, they already have
711                          * an id that the drawing functions will use */
712                         if(input->source == GPU_SOURCE_ATTRIB ||
713                            input->source == GPU_SOURCE_BUILTIN)
714                                 continue;
715
716                         if (input->ima || input->tex)
717                                 BLI_snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid);
718                         else
719                                 BLI_snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id);
720
721                         /* pass non-dynamic uniforms to opengl */
722                         extract = 0;
723
724                         if(input->ima || input->tex) {
725                                 if (input->bindtex)
726                                         extract = 1;
727                         }
728                         else if(input->dynamicvec)
729                                 extract = 1;
730
731                         if(extract)
732                                 input->shaderloc = GPU_shader_get_uniform(shader, input->shadername);
733
734                         /* extract nodes */
735                         if(extract) {
736                                 BLI_remlink(&node->inputs, input);
737                                 BLI_addtail(inputs, input);
738                         }
739                 }
740         }
741
742         GPU_shader_unbind(shader);
743 }
744
745 void GPU_pass_bind(GPUPass *pass, double time, int mipmap)
746 {
747         GPUInput *input;
748         GPUShader *shader = pass->shader;
749         ListBase *inputs = &pass->inputs;
750
751         if (!shader)
752                 return;
753
754         GPU_shader_bind(shader);
755
756         /* now bind the textures */
757         for (input=inputs->first; input; input=input->next) {
758                 if (input->ima)
759                         input->tex = GPU_texture_from_blender(input->ima, input->iuser, time, mipmap);
760
761                 if(input->tex && input->bindtex) {
762                         GPU_texture_bind(input->tex, input->texid);
763                         GPU_shader_uniform_texture(shader, input->shaderloc, input->tex);
764                 }
765         }
766 }
767
768 void GPU_pass_update_uniforms(GPUPass *pass)
769 {
770         GPUInput *input;
771         GPUShader *shader = pass->shader;
772         ListBase *inputs = &pass->inputs;
773
774         if (!shader)
775                 return;
776
777         /* pass dynamic inputs to opengl, others were removed */
778         for (input=inputs->first; input; input=input->next)
779                 if(!(input->ima || input->tex))
780                         GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1,
781                                 input->dynamicvec);
782 }
783
784 void GPU_pass_unbind(GPUPass *pass)
785 {
786         GPUInput *input;
787         GPUShader *shader = pass->shader;
788         ListBase *inputs = &pass->inputs;
789
790         if (!shader)
791                 return;
792
793         for (input=inputs->first; input; input=input->next) {
794                 if(input->tex && input->bindtex)
795                         GPU_texture_unbind(input->tex);
796
797                 if (input->ima)
798                         input->tex = NULL;
799         }
800         
801         GPU_shader_unbind(shader);
802 }
803
804 /* Node Link Functions */
805
806 static GPUNodeLink *GPU_node_link_create(int type)
807 {
808         GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink");
809         link->type = type;
810         link->users++;
811
812         return link;
813 }
814
815 static void GPU_node_link_free(GPUNodeLink *link)
816 {
817         link->users--;
818
819         if (link->users < 0)
820                 fprintf(stderr, "GPU_node_link_free: negative refcount\n");
821         
822         if (link->users == 0) {
823                 if (link->output)
824                         link->output->link = NULL;
825                 MEM_freeN(link);
826         }
827 }
828
829 /* Node Functions */
830
831 static GPUNode *GPU_node_begin(const char *name)
832 {
833         GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode");
834
835         node->name= name;
836
837         return node;
838 }
839
840 static void GPU_node_end(GPUNode *UNUSED(node))
841 {
842         /* empty */
843 }
844
845 static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
846 {
847         GPUInput *input;
848         GPUNode *outnode;
849         const char *name;
850
851         if(link->output) {
852                 outnode = link->output->node;
853                 name = outnode->name;
854
855                 if(strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) {
856                         input = MEM_dupallocN(outnode->inputs.first);
857                         input->type = type;
858                         if(input->link)
859                                 input->link->users++;
860                         BLI_addtail(&node->inputs, input);
861                         return;
862                 }
863         }
864         
865         input = MEM_callocN(sizeof(GPUInput), "GPUInput");
866         input->node = node;
867
868         if(link->builtin) {
869                 /* builtin uniform */
870                 input->type = type;
871                 input->source = GPU_SOURCE_BUILTIN;
872                 input->builtin = link->builtin;
873
874                 MEM_freeN(link);
875         }
876         else if(link->output) {
877                 /* link to a node output */
878                 input->type = type;
879                 input->source = GPU_SOURCE_TEX_PIXEL;
880                 input->link = link;
881                 link->users++;
882         }
883         else if(link->dynamictex) {
884                 /* dynamic texture, GPUTexture is updated/deleted externally */
885                 input->type = type;
886                 input->source = GPU_SOURCE_TEX;
887
888                 input->tex = link->dynamictex;
889                 input->textarget = GL_TEXTURE_2D;
890                 input->textype = type;
891                 input->dynamictex = 1;
892                 input->dynamicdata = link->ptr2;
893                 MEM_freeN(link);
894         }
895         else if(link->texture) {
896                 /* small texture created on the fly, like for colorbands */
897                 input->type = GPU_VEC4;
898                 input->source = GPU_SOURCE_TEX;
899                 input->textype = type;
900
901                 //input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
902                 input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, NULL);
903                 input->textarget = GL_TEXTURE_2D;
904
905                 MEM_freeN(link->ptr1);
906                 MEM_freeN(link);
907         }
908         else if(link->image) {
909                 /* blender image */
910                 input->type = GPU_VEC4;
911                 input->source = GPU_SOURCE_TEX;
912
913                 input->ima = link->ptr1;
914                 input->iuser = link->ptr2;
915                 input->textarget = GL_TEXTURE_2D;
916                 input->textype = GPU_TEX2D;
917                 MEM_freeN(link);
918         }
919         else if(link->attribtype) {
920                 /* vertex attribute */
921                 input->type = type;
922                 input->source = GPU_SOURCE_ATTRIB;
923
924                 input->attribtype = link->attribtype;
925                 BLI_strncpy(input->attribname, link->attribname, sizeof(input->attribname));
926                 MEM_freeN(link);
927         }
928         else {
929                 /* uniform vector */
930                 input->type = type;
931                 input->source = GPU_SOURCE_VEC_UNIFORM;
932
933                 memcpy(input->vec, link->ptr1, type*sizeof(float));
934                 if(link->dynamic) {
935                         input->dynamicvec= link->ptr1;
936                         input->dynamictype= link->dynamictype;
937                         input->dynamicdata= link->ptr2;
938                 }
939                 MEM_freeN(link);
940         }
941
942         BLI_addtail(&node->inputs, input);
943 }
944
945 static void gpu_node_input_socket(GPUNode *node, GPUNodeStack *sock)
946 {
947         GPUNodeLink *link;
948
949         if(sock->link) {
950                 gpu_node_input_link(node, sock->link, sock->type);
951         }
952         else {
953                 link = GPU_node_link_create(0);
954                 link->ptr1 = sock->vec;
955                 gpu_node_input_link(node, link, sock->type);
956         }
957 }
958
959 static void GPU_node_output(GPUNode *node, int type, const char *UNUSED(name), GPUNodeLink **link)
960 {
961         GPUOutput *output = MEM_callocN(sizeof(GPUOutput), "GPUOutput");
962
963         output->type = type;
964         output->node = node;
965
966         if (link) {
967                 *link = output->link = GPU_node_link_create(type);
968                 output->link->output = output;
969
970                 /* note: the caller owns the reference to the linkfer, GPUOutput
971                    merely points to it, and if the node is destroyed it will
972                    set that pointer to NULL */
973         }
974
975         BLI_addtail(&node->outputs, output);
976 }
977
978 static void GPU_inputs_free(ListBase *inputs)
979 {
980         GPUInput *input;
981
982         for(input=inputs->first; input; input=input->next) {
983                 if(input->link)
984                         GPU_node_link_free(input->link);
985                 else if(input->tex && !input->dynamictex)
986                         GPU_texture_free(input->tex);
987         }
988
989         BLI_freelistN(inputs);
990 }
991
992 static void GPU_node_free(GPUNode *node)
993 {
994         GPUOutput *output;
995
996         GPU_inputs_free(&node->inputs);
997
998         for (output=node->outputs.first; output; output=output->next)
999                 if (output->link) {
1000                         output->link->output = NULL;
1001                         GPU_node_link_free(output->link);
1002                 }
1003
1004         BLI_freelistN(&node->outputs);
1005         MEM_freeN(node);
1006 }
1007
1008 static void GPU_nodes_free(ListBase *nodes)
1009 {
1010         GPUNode *node;
1011
1012         while (nodes->first) {
1013                 node = nodes->first;
1014                 BLI_remlink(nodes, node);
1015                 GPU_node_free(node);
1016         }
1017 }
1018
1019 /* vertex attributes */
1020
1021 static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs)
1022 {
1023         GPUNode *node;
1024         GPUInput *input;
1025         int a;
1026
1027         /* convert attributes requested by node inputs to an array of layers,
1028          * checking for duplicates and assigning id's starting from zero. */
1029
1030         memset(attribs, 0, sizeof(*attribs));
1031
1032         for(node=nodes->first; node; node=node->next) {
1033                 for(input=node->inputs.first; input; input=input->next) {
1034                         if(input->source == GPU_SOURCE_ATTRIB) {
1035                                 for(a=0; a<attribs->totlayer; a++) {
1036                                         if(attribs->layer[a].type == input->attribtype &&
1037                                                 strcmp(attribs->layer[a].name, input->attribname) == 0)
1038                                                 break;
1039                                 }
1040
1041                                 if(a == attribs->totlayer && a < GPU_MAX_ATTRIB) {
1042                                         input->attribid = attribs->totlayer++;
1043                                         input->attribfirst = 1;
1044
1045                                         attribs->layer[a].type = input->attribtype;
1046                                         attribs->layer[a].attribid = input->attribid;
1047                                         BLI_strncpy(attribs->layer[a].name, input->attribname,
1048                                                 sizeof(attribs->layer[a].name));
1049                                 }
1050                                 else
1051                                         input->attribid = attribs->layer[a].attribid;
1052                         }
1053                 }
1054         }
1055 }
1056
1057 static void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin)
1058 {
1059         GPUNode *node;
1060         GPUInput *input;
1061         
1062         *builtin= 0;
1063
1064         for(node=nodes->first; node; node=node->next)
1065                 for(input=node->inputs.first; input; input=input->next)
1066                         if(input->source == GPU_SOURCE_BUILTIN)
1067                                 *builtin |= input->builtin;
1068 }
1069
1070 /* varargs linking  */
1071
1072 GPUNodeLink *GPU_attribute(int type, const char *name)
1073 {
1074         GPUNodeLink *link = GPU_node_link_create(0);
1075
1076         link->attribtype= type;
1077         link->attribname= name;
1078
1079         return link;
1080 }
1081
1082 GPUNodeLink *GPU_uniform(float *num)
1083 {
1084         GPUNodeLink *link = GPU_node_link_create(0);
1085
1086         link->ptr1= num;
1087         link->ptr2= NULL;
1088
1089         return link;
1090 }
1091
1092 GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data)
1093 {
1094         GPUNodeLink *link = GPU_node_link_create(0);
1095
1096         link->ptr1= num;
1097         link->ptr2= data;
1098         link->dynamic= 1;
1099         link->dynamictype = dynamictype;
1100
1101
1102         return link;
1103 }
1104
1105 GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser)
1106 {
1107         GPUNodeLink *link = GPU_node_link_create(0);
1108
1109         link->image= 1;
1110         link->ptr1= ima;
1111         link->ptr2= iuser;
1112
1113         return link;
1114 }
1115
1116 GPUNodeLink *GPU_texture(int size, float *pixels)
1117 {
1118         GPUNodeLink *link = GPU_node_link_create(0);
1119
1120         link->texture = 1;
1121         link->texturesize = size;
1122         link->ptr1= pixels;
1123
1124         return link;
1125 }
1126
1127 GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex, int dynamictype, void *data)
1128 {
1129         GPUNodeLink *link = GPU_node_link_create(0);
1130
1131         link->dynamic = 1;
1132         link->dynamictex = tex;
1133         link->dynamictype = dynamictype;
1134         link->ptr2 = data;
1135
1136         return link;
1137 }
1138
1139 GPUNodeLink *GPU_socket(GPUNodeStack *sock)
1140 {
1141         GPUNodeLink *link = GPU_node_link_create(0);
1142
1143         link->socket= sock;
1144
1145         return link;
1146 }
1147
1148 GPUNodeLink *GPU_builtin(GPUBuiltin builtin)
1149 {
1150         GPUNodeLink *link = GPU_node_link_create(0);
1151
1152         link->builtin= builtin;
1153
1154         return link;
1155 }
1156
1157 int GPU_link(GPUMaterial *mat, const char *name, ...)
1158 {
1159         GPUNode *node;
1160         GPUFunction *function;
1161         GPUNodeLink *link, **linkptr;
1162         va_list params;
1163         int i;
1164
1165         function = GPU_lookup_function(name);
1166         if(!function) {
1167                 fprintf(stderr, "GPU failed to find function %s\n", name);
1168                 return 0;
1169         }
1170
1171         node = GPU_node_begin(name);
1172
1173         va_start(params, name);
1174         for(i=0; i<function->totparam; i++) {
1175                 if(function->paramqual[i] != FUNCTION_QUAL_IN) {
1176                         linkptr= va_arg(params, GPUNodeLink**);
1177                         GPU_node_output(node, function->paramtype[i], "", linkptr);
1178                 }
1179                 else {
1180                         link= va_arg(params, GPUNodeLink*);
1181                         gpu_node_input_link(node, link, function->paramtype[i]);
1182                 }
1183         }
1184         va_end(params);
1185
1186         GPU_node_end(node);
1187
1188         gpu_material_add_node(mat, node);
1189
1190         return 1;
1191 }
1192
1193 int GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...)
1194 {
1195         GPUNode *node;
1196         GPUFunction *function;
1197         GPUNodeLink *link, **linkptr;
1198         va_list params;
1199         int i, totin, totout;
1200
1201         function = GPU_lookup_function(name);
1202         if(!function) {
1203                 fprintf(stderr, "GPU failed to find function %s\n", name);
1204                 return 0;
1205         }
1206
1207         node = GPU_node_begin(name);
1208         totin = 0;
1209         totout = 0;
1210
1211         if(in) {
1212                 for(i = 0; in[i].type != GPU_NONE; i++) {
1213                         gpu_node_input_socket(node, &in[i]);
1214                         totin++;
1215                 }
1216         }
1217         
1218         if(out) {
1219                 for(i = 0; out[i].type != GPU_NONE; i++) {
1220                         GPU_node_output(node, out[i].type, out[i].name, &out[i].link);
1221                         totout++;
1222                 }
1223         }
1224
1225         va_start(params, out);
1226         for(i=0; i<function->totparam; i++) {
1227                 if(function->paramqual[i] != FUNCTION_QUAL_IN) {
1228                         if(totout == 0) {
1229                                 linkptr= va_arg(params, GPUNodeLink**);
1230                                 GPU_node_output(node, function->paramtype[i], "", linkptr);
1231                         }
1232                         else
1233                                 totout--;
1234                 }
1235                 else {
1236                         if(totin == 0) {
1237                                 link= va_arg(params, GPUNodeLink*);
1238                                 if(link->socket)
1239                                         gpu_node_input_socket(node, link->socket);
1240                                 else
1241                                         gpu_node_input_link(node, link, function->paramtype[i]);
1242                         }
1243                         else
1244                                 totin--;
1245                 }
1246         }
1247         va_end(params);
1248
1249         GPU_node_end(node);
1250
1251         gpu_material_add_node(mat, node);
1252         
1253         return 1;
1254 }
1255
1256 int GPU_link_changed(GPUNodeLink *link)
1257 {
1258         GPUNode *node;
1259         GPUInput *input;
1260         const char *name;
1261
1262         if(link->output) {
1263                 node = link->output->node;
1264                 name = node->name;
1265
1266                 if(strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) {
1267                         input = node->inputs.first;
1268                         return (input->link != NULL);
1269                 }
1270
1271                 return 1;
1272         }
1273         else
1274                 return 0;
1275 }
1276
1277 /* Pass create/free */
1278
1279 static void gpu_nodes_tag(GPUNodeLink *link)
1280 {
1281         GPUNode *node;
1282         GPUInput *input;
1283
1284         if(!link->output)
1285                 return;
1286
1287         node = link->output->node;
1288         if(node->tag)
1289                 return;
1290         
1291         node->tag= 1;
1292         for(input=node->inputs.first; input; input=input->next)
1293                 if(input->link)
1294                         gpu_nodes_tag(input->link);
1295 }
1296
1297 static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
1298 {
1299         GPUNode *node, *next;
1300
1301         for(node=nodes->first; node; node=node->next)
1302                 node->tag= 0;
1303
1304         gpu_nodes_tag(outlink);
1305
1306         for(node=nodes->first; node; node=next) {
1307                 next = node->next;
1308
1309                 if(!node->tag) {
1310                         BLI_remlink(nodes, node);
1311                         GPU_node_free(node);
1312                 }
1313         }
1314 }
1315
1316 GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttribs *attribs, int *builtins, const char *name)
1317 {
1318         GPUShader *shader;
1319         GPUPass *pass;
1320         char *vertexcode, *fragmentcode;
1321
1322         /*if(!FUNCTION_LIB) {
1323                 GPU_nodes_free(nodes);
1324                 return NULL;
1325         }*/
1326
1327         /* prune unused nodes */
1328         gpu_nodes_prune(nodes, outlink);
1329
1330         gpu_nodes_get_vertex_attributes(nodes, attribs);
1331         gpu_nodes_get_builtin_flag(nodes, builtins);
1332
1333         /* generate code and compile with opengl */
1334         fragmentcode = code_generate_fragment(nodes, outlink->output, name);
1335         vertexcode = code_generate_vertex(nodes);
1336         shader = GPU_shader_create(vertexcode, fragmentcode, glsl_material_library); /*FUNCTION_LIB);*/
1337
1338         /* failed? */
1339         if (!shader) {
1340                 memset(attribs, 0, sizeof(*attribs));
1341                 memset(builtins, 0, sizeof(*builtins));
1342                 GPU_nodes_free(nodes);
1343                 return NULL;
1344         }
1345         
1346         /* create pass */
1347         pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
1348
1349         pass->output = outlink->output;
1350         pass->shader = shader;
1351         pass->fragmentcode = fragmentcode;
1352         pass->vertexcode = vertexcode;
1353         pass->libcode = glsl_material_library;
1354
1355         /* extract dynamic inputs and throw away nodes */
1356         GPU_nodes_extract_dynamic_inputs(pass, nodes);
1357         GPU_nodes_free(nodes);
1358
1359         return pass;
1360 }
1361
1362 void GPU_pass_free(GPUPass *pass)
1363 {
1364         GPU_shader_free(pass->shader);
1365         GPU_inputs_free(&pass->inputs);
1366         if (pass->fragmentcode)
1367                 MEM_freeN(pass->fragmentcode);
1368         if (pass->vertexcode)
1369                 MEM_freeN(pass->vertexcode);
1370         MEM_freeN(pass);
1371 }
1372