bc77d15f76bf861328a8e48c34eaba5b1bb268dc
[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                                 {
636                                         BLI_dynstr_appendf(ds, "\tvar%d.xyz = normalize((gl_ModelViewMatrix * vec4(att%d.xyz, 0)).xyz);\n", input->attribid, input->attribid);
637                                         BLI_dynstr_appendf(ds, "\tvar%d.w = att%d.w;\n", input->attribid, input->attribid);
638                                 }
639                                 else
640                                         BLI_dynstr_appendf(ds, "\tvar%d = att%d;\n", input->attribid, input->attribid);
641                         }
642
643         BLI_dynstr_append(ds, "}\n\n");
644
645         code = BLI_dynstr_get_cstring(ds);
646
647         BLI_dynstr_free(ds);
648
649         //if(G.f & G_DEBUG) printf("%s\n", code);
650
651         return code;
652 }
653
654 int GPU_bicubic_bump_support(void)
655 {
656         return GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0;
657 }
658
659 void GPU_code_generate_glsl_lib(void)
660 {
661         DynStr *ds;
662
663         /* only initialize the library once */
664         if(glsl_material_library)
665                 return;
666
667         ds = BLI_dynstr_new();
668
669         if(GPU_bicubic_bump_support()){
670                 BLI_dynstr_append(ds, "/* These are needed for high quality bump mapping */\n"
671                                 "#version 130\n"
672                                 "#extension GL_ARB_texture_query_lod: enable\n"
673                                 "#define BUMP_BICUBIC\n");
674         }
675         BLI_dynstr_append(ds, datatoc_gpu_shader_material_glsl);
676
677
678         glsl_material_library = BLI_dynstr_get_cstring(ds);
679
680         BLI_dynstr_free(ds);
681 }
682
683
684 /* GPU pass binding/unbinding */
685
686 GPUShader *GPU_pass_shader(GPUPass *pass)
687 {
688         return pass->shader;
689 }
690
691 static void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
692 {
693         GPUShader *shader = pass->shader;
694         GPUNode *node;
695         GPUInput *next, *input;
696         ListBase *inputs = &pass->inputs;
697         int extract, z;
698
699         memset(inputs, 0, sizeof(*inputs));
700
701         if(!shader)
702                 return;
703
704         GPU_shader_bind(shader);
705
706         for (node=nodes->first; node; node=node->next) {
707                 z = 0;
708                 for (input=node->inputs.first; input; input=next, z++) {
709                         next = input->next;
710
711                         /* attributes don't need to be bound, they already have
712                          * an id that the drawing functions will use */
713                         if(input->source == GPU_SOURCE_ATTRIB ||
714                            input->source == GPU_SOURCE_BUILTIN)
715                                 continue;
716
717                         if (input->ima || input->tex)
718                                 BLI_snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid);
719                         else
720                                 BLI_snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id);
721
722                         /* pass non-dynamic uniforms to opengl */
723                         extract = 0;
724
725                         if(input->ima || input->tex) {
726                                 if (input->bindtex)
727                                         extract = 1;
728                         }
729                         else if(input->dynamicvec)
730                                 extract = 1;
731
732                         if(extract)
733                                 input->shaderloc = GPU_shader_get_uniform(shader, input->shadername);
734
735                         /* extract nodes */
736                         if(extract) {
737                                 BLI_remlink(&node->inputs, input);
738                                 BLI_addtail(inputs, input);
739                         }
740                 }
741         }
742
743         GPU_shader_unbind(shader);
744 }
745
746 void GPU_pass_bind(GPUPass *pass, double time, int mipmap)
747 {
748         GPUInput *input;
749         GPUShader *shader = pass->shader;
750         ListBase *inputs = &pass->inputs;
751
752         if (!shader)
753                 return;
754
755         GPU_shader_bind(shader);
756
757         /* now bind the textures */
758         for (input=inputs->first; input; input=input->next) {
759                 if (input->ima)
760                         input->tex = GPU_texture_from_blender(input->ima, input->iuser, time, mipmap);
761
762                 if(input->tex && input->bindtex) {
763                         GPU_texture_bind(input->tex, input->texid);
764                         GPU_shader_uniform_texture(shader, input->shaderloc, input->tex);
765                 }
766         }
767 }
768
769 void GPU_pass_update_uniforms(GPUPass *pass)
770 {
771         GPUInput *input;
772         GPUShader *shader = pass->shader;
773         ListBase *inputs = &pass->inputs;
774
775         if (!shader)
776                 return;
777
778         /* pass dynamic inputs to opengl, others were removed */
779         for (input=inputs->first; input; input=input->next)
780                 if(!(input->ima || input->tex))
781                         GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1,
782                                 input->dynamicvec);
783 }
784
785 void GPU_pass_unbind(GPUPass *pass)
786 {
787         GPUInput *input;
788         GPUShader *shader = pass->shader;
789         ListBase *inputs = &pass->inputs;
790
791         if (!shader)
792                 return;
793
794         for (input=inputs->first; input; input=input->next) {
795                 if(input->tex && input->bindtex)
796                         GPU_texture_unbind(input->tex);
797
798                 if (input->ima)
799                         input->tex = NULL;
800         }
801         
802         GPU_shader_unbind(shader);
803 }
804
805 /* Node Link Functions */
806
807 static GPUNodeLink *GPU_node_link_create(int type)
808 {
809         GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink");
810         link->type = type;
811         link->users++;
812
813         return link;
814 }
815
816 static void GPU_node_link_free(GPUNodeLink *link)
817 {
818         link->users--;
819
820         if (link->users < 0)
821                 fprintf(stderr, "GPU_node_link_free: negative refcount\n");
822         
823         if (link->users == 0) {
824                 if (link->output)
825                         link->output->link = NULL;
826                 MEM_freeN(link);
827         }
828 }
829
830 /* Node Functions */
831
832 static GPUNode *GPU_node_begin(const char *name)
833 {
834         GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode");
835
836         node->name= name;
837
838         return node;
839 }
840
841 static void GPU_node_end(GPUNode *UNUSED(node))
842 {
843         /* empty */
844 }
845
846 static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
847 {
848         GPUInput *input;
849         GPUNode *outnode;
850         const char *name;
851
852         if(link->output) {
853                 outnode = link->output->node;
854                 name = outnode->name;
855
856                 if(strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) {
857                         input = MEM_dupallocN(outnode->inputs.first);
858                         input->type = type;
859                         if(input->link)
860                                 input->link->users++;
861                         BLI_addtail(&node->inputs, input);
862                         return;
863                 }
864         }
865         
866         input = MEM_callocN(sizeof(GPUInput), "GPUInput");
867         input->node = node;
868
869         if(link->builtin) {
870                 /* builtin uniform */
871                 input->type = type;
872                 input->source = GPU_SOURCE_BUILTIN;
873                 input->builtin = link->builtin;
874
875                 MEM_freeN(link);
876         }
877         else if(link->output) {
878                 /* link to a node output */
879                 input->type = type;
880                 input->source = GPU_SOURCE_TEX_PIXEL;
881                 input->link = link;
882                 link->users++;
883         }
884         else if(link->dynamictex) {
885                 /* dynamic texture, GPUTexture is updated/deleted externally */
886                 input->type = type;
887                 input->source = GPU_SOURCE_TEX;
888
889                 input->tex = link->dynamictex;
890                 input->textarget = GL_TEXTURE_2D;
891                 input->textype = type;
892                 input->dynamictex = 1;
893                 input->dynamicdata = link->ptr2;
894                 MEM_freeN(link);
895         }
896         else if(link->texture) {
897                 /* small texture created on the fly, like for colorbands */
898                 input->type = GPU_VEC4;
899                 input->source = GPU_SOURCE_TEX;
900                 input->textype = type;
901
902                 //input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
903                 input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, NULL);
904                 input->textarget = GL_TEXTURE_2D;
905
906                 MEM_freeN(link->ptr1);
907                 MEM_freeN(link);
908         }
909         else if(link->image) {
910                 /* blender image */
911                 input->type = GPU_VEC4;
912                 input->source = GPU_SOURCE_TEX;
913
914                 input->ima = link->ptr1;
915                 input->iuser = link->ptr2;
916                 input->textarget = GL_TEXTURE_2D;
917                 input->textype = GPU_TEX2D;
918                 MEM_freeN(link);
919         }
920         else if(link->attribtype) {
921                 /* vertex attribute */
922                 input->type = type;
923                 input->source = GPU_SOURCE_ATTRIB;
924
925                 input->attribtype = link->attribtype;
926                 BLI_strncpy(input->attribname, link->attribname, sizeof(input->attribname));
927                 MEM_freeN(link);
928         }
929         else {
930                 /* uniform vector */
931                 input->type = type;
932                 input->source = GPU_SOURCE_VEC_UNIFORM;
933
934                 memcpy(input->vec, link->ptr1, type*sizeof(float));
935                 if(link->dynamic) {
936                         input->dynamicvec= link->ptr1;
937                         input->dynamictype= link->dynamictype;
938                         input->dynamicdata= link->ptr2;
939                 }
940                 MEM_freeN(link);
941         }
942
943         BLI_addtail(&node->inputs, input);
944 }
945
946 static void gpu_node_input_socket(GPUNode *node, GPUNodeStack *sock)
947 {
948         GPUNodeLink *link;
949
950         if(sock->link) {
951                 gpu_node_input_link(node, sock->link, sock->type);
952         }
953         else {
954                 link = GPU_node_link_create(0);
955                 link->ptr1 = sock->vec;
956                 gpu_node_input_link(node, link, sock->type);
957         }
958 }
959
960 static void GPU_node_output(GPUNode *node, int type, const char *UNUSED(name), GPUNodeLink **link)
961 {
962         GPUOutput *output = MEM_callocN(sizeof(GPUOutput), "GPUOutput");
963
964         output->type = type;
965         output->node = node;
966
967         if (link) {
968                 *link = output->link = GPU_node_link_create(type);
969                 output->link->output = output;
970
971                 /* note: the caller owns the reference to the linkfer, GPUOutput
972                    merely points to it, and if the node is destroyed it will
973                    set that pointer to NULL */
974         }
975
976         BLI_addtail(&node->outputs, output);
977 }
978
979 static void GPU_inputs_free(ListBase *inputs)
980 {
981         GPUInput *input;
982
983         for(input=inputs->first; input; input=input->next) {
984                 if(input->link)
985                         GPU_node_link_free(input->link);
986                 else if(input->tex && !input->dynamictex)
987                         GPU_texture_free(input->tex);
988         }
989
990         BLI_freelistN(inputs);
991 }
992
993 static void GPU_node_free(GPUNode *node)
994 {
995         GPUOutput *output;
996
997         GPU_inputs_free(&node->inputs);
998
999         for (output=node->outputs.first; output; output=output->next)
1000                 if (output->link) {
1001                         output->link->output = NULL;
1002                         GPU_node_link_free(output->link);
1003                 }
1004
1005         BLI_freelistN(&node->outputs);
1006         MEM_freeN(node);
1007 }
1008
1009 static void GPU_nodes_free(ListBase *nodes)
1010 {
1011         GPUNode *node;
1012
1013         while (nodes->first) {
1014                 node = nodes->first;
1015                 BLI_remlink(nodes, node);
1016                 GPU_node_free(node);
1017         }
1018 }
1019
1020 /* vertex attributes */
1021
1022 static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs)
1023 {
1024         GPUNode *node;
1025         GPUInput *input;
1026         int a;
1027
1028         /* convert attributes requested by node inputs to an array of layers,
1029          * checking for duplicates and assigning id's starting from zero. */
1030
1031         memset(attribs, 0, sizeof(*attribs));
1032
1033         for(node=nodes->first; node; node=node->next) {
1034                 for(input=node->inputs.first; input; input=input->next) {
1035                         if(input->source == GPU_SOURCE_ATTRIB) {
1036                                 for(a=0; a<attribs->totlayer; a++) {
1037                                         if(attribs->layer[a].type == input->attribtype &&
1038                                                 strcmp(attribs->layer[a].name, input->attribname) == 0)
1039                                                 break;
1040                                 }
1041
1042                                 if(a == attribs->totlayer && a < GPU_MAX_ATTRIB) {
1043                                         input->attribid = attribs->totlayer++;
1044                                         input->attribfirst = 1;
1045
1046                                         attribs->layer[a].type = input->attribtype;
1047                                         attribs->layer[a].attribid = input->attribid;
1048                                         BLI_strncpy(attribs->layer[a].name, input->attribname,
1049                                                 sizeof(attribs->layer[a].name));
1050                                 }
1051                                 else
1052                                         input->attribid = attribs->layer[a].attribid;
1053                         }
1054                 }
1055         }
1056 }
1057
1058 static void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin)
1059 {
1060         GPUNode *node;
1061         GPUInput *input;
1062         
1063         *builtin= 0;
1064
1065         for(node=nodes->first; node; node=node->next)
1066                 for(input=node->inputs.first; input; input=input->next)
1067                         if(input->source == GPU_SOURCE_BUILTIN)
1068                                 *builtin |= input->builtin;
1069 }
1070
1071 /* varargs linking  */
1072
1073 GPUNodeLink *GPU_attribute(int type, const char *name)
1074 {
1075         GPUNodeLink *link = GPU_node_link_create(0);
1076
1077         link->attribtype= type;
1078         link->attribname= name;
1079
1080         return link;
1081 }
1082
1083 GPUNodeLink *GPU_uniform(float *num)
1084 {
1085         GPUNodeLink *link = GPU_node_link_create(0);
1086
1087         link->ptr1= num;
1088         link->ptr2= NULL;
1089
1090         return link;
1091 }
1092
1093 GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data)
1094 {
1095         GPUNodeLink *link = GPU_node_link_create(0);
1096
1097         link->ptr1= num;
1098         link->ptr2= data;
1099         link->dynamic= 1;
1100         link->dynamictype = dynamictype;
1101
1102
1103         return link;
1104 }
1105
1106 GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser)
1107 {
1108         GPUNodeLink *link = GPU_node_link_create(0);
1109
1110         link->image= 1;
1111         link->ptr1= ima;
1112         link->ptr2= iuser;
1113
1114         return link;
1115 }
1116
1117 GPUNodeLink *GPU_texture(int size, float *pixels)
1118 {
1119         GPUNodeLink *link = GPU_node_link_create(0);
1120
1121         link->texture = 1;
1122         link->texturesize = size;
1123         link->ptr1= pixels;
1124
1125         return link;
1126 }
1127
1128 GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex, int dynamictype, void *data)
1129 {
1130         GPUNodeLink *link = GPU_node_link_create(0);
1131
1132         link->dynamic = 1;
1133         link->dynamictex = tex;
1134         link->dynamictype = dynamictype;
1135         link->ptr2 = data;
1136
1137         return link;
1138 }
1139
1140 GPUNodeLink *GPU_socket(GPUNodeStack *sock)
1141 {
1142         GPUNodeLink *link = GPU_node_link_create(0);
1143
1144         link->socket= sock;
1145
1146         return link;
1147 }
1148
1149 GPUNodeLink *GPU_builtin(GPUBuiltin builtin)
1150 {
1151         GPUNodeLink *link = GPU_node_link_create(0);
1152
1153         link->builtin= builtin;
1154
1155         return link;
1156 }
1157
1158 int GPU_link(GPUMaterial *mat, const char *name, ...)
1159 {
1160         GPUNode *node;
1161         GPUFunction *function;
1162         GPUNodeLink *link, **linkptr;
1163         va_list params;
1164         int i;
1165
1166         function = GPU_lookup_function(name);
1167         if(!function) {
1168                 fprintf(stderr, "GPU failed to find function %s\n", name);
1169                 return 0;
1170         }
1171
1172         node = GPU_node_begin(name);
1173
1174         va_start(params, name);
1175         for(i=0; i<function->totparam; i++) {
1176                 if(function->paramqual[i] != FUNCTION_QUAL_IN) {
1177                         linkptr= va_arg(params, GPUNodeLink**);
1178                         GPU_node_output(node, function->paramtype[i], "", linkptr);
1179                 }
1180                 else {
1181                         link= va_arg(params, GPUNodeLink*);
1182                         gpu_node_input_link(node, link, function->paramtype[i]);
1183                 }
1184         }
1185         va_end(params);
1186
1187         GPU_node_end(node);
1188
1189         gpu_material_add_node(mat, node);
1190
1191         return 1;
1192 }
1193
1194 int GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...)
1195 {
1196         GPUNode *node;
1197         GPUFunction *function;
1198         GPUNodeLink *link, **linkptr;
1199         va_list params;
1200         int i, totin, totout;
1201
1202         function = GPU_lookup_function(name);
1203         if(!function) {
1204                 fprintf(stderr, "GPU failed to find function %s\n", name);
1205                 return 0;
1206         }
1207
1208         node = GPU_node_begin(name);
1209         totin = 0;
1210         totout = 0;
1211
1212         if(in) {
1213                 for(i = 0; in[i].type != GPU_NONE; i++) {
1214                         gpu_node_input_socket(node, &in[i]);
1215                         totin++;
1216                 }
1217         }
1218         
1219         if(out) {
1220                 for(i = 0; out[i].type != GPU_NONE; i++) {
1221                         GPU_node_output(node, out[i].type, out[i].name, &out[i].link);
1222                         totout++;
1223                 }
1224         }
1225
1226         va_start(params, out);
1227         for(i=0; i<function->totparam; i++) {
1228                 if(function->paramqual[i] != FUNCTION_QUAL_IN) {
1229                         if(totout == 0) {
1230                                 linkptr= va_arg(params, GPUNodeLink**);
1231                                 GPU_node_output(node, function->paramtype[i], "", linkptr);
1232                         }
1233                         else
1234                                 totout--;
1235                 }
1236                 else {
1237                         if(totin == 0) {
1238                                 link= va_arg(params, GPUNodeLink*);
1239                                 if(link->socket)
1240                                         gpu_node_input_socket(node, link->socket);
1241                                 else
1242                                         gpu_node_input_link(node, link, function->paramtype[i]);
1243                         }
1244                         else
1245                                 totin--;
1246                 }
1247         }
1248         va_end(params);
1249
1250         GPU_node_end(node);
1251
1252         gpu_material_add_node(mat, node);
1253         
1254         return 1;
1255 }
1256
1257 int GPU_link_changed(GPUNodeLink *link)
1258 {
1259         GPUNode *node;
1260         GPUInput *input;
1261         const char *name;
1262
1263         if(link->output) {
1264                 node = link->output->node;
1265                 name = node->name;
1266
1267                 if(strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) {
1268                         input = node->inputs.first;
1269                         return (input->link != NULL);
1270                 }
1271
1272                 return 1;
1273         }
1274         else
1275                 return 0;
1276 }
1277
1278 /* Pass create/free */
1279
1280 static void gpu_nodes_tag(GPUNodeLink *link)
1281 {
1282         GPUNode *node;
1283         GPUInput *input;
1284
1285         if(!link->output)
1286                 return;
1287
1288         node = link->output->node;
1289         if(node->tag)
1290                 return;
1291         
1292         node->tag= 1;
1293         for(input=node->inputs.first; input; input=input->next)
1294                 if(input->link)
1295                         gpu_nodes_tag(input->link);
1296 }
1297
1298 static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
1299 {
1300         GPUNode *node, *next;
1301
1302         for(node=nodes->first; node; node=node->next)
1303                 node->tag= 0;
1304
1305         gpu_nodes_tag(outlink);
1306
1307         for(node=nodes->first; node; node=next) {
1308                 next = node->next;
1309
1310                 if(!node->tag) {
1311                         BLI_remlink(nodes, node);
1312                         GPU_node_free(node);
1313                 }
1314         }
1315 }
1316
1317 GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttribs *attribs, int *builtins, const char *name)
1318 {
1319         GPUShader *shader;
1320         GPUPass *pass;
1321         char *vertexcode, *fragmentcode;
1322
1323         /*if(!FUNCTION_LIB) {
1324                 GPU_nodes_free(nodes);
1325                 return NULL;
1326         }*/
1327
1328         /* prune unused nodes */
1329         gpu_nodes_prune(nodes, outlink);
1330
1331         gpu_nodes_get_vertex_attributes(nodes, attribs);
1332         gpu_nodes_get_builtin_flag(nodes, builtins);
1333
1334         /* generate code and compile with opengl */
1335         fragmentcode = code_generate_fragment(nodes, outlink->output, name);
1336         vertexcode = code_generate_vertex(nodes);
1337         shader = GPU_shader_create(vertexcode, fragmentcode, glsl_material_library); /*FUNCTION_LIB);*/
1338
1339         /* failed? */
1340         if (!shader) {
1341                 memset(attribs, 0, sizeof(*attribs));
1342                 memset(builtins, 0, sizeof(*builtins));
1343                 GPU_nodes_free(nodes);
1344                 return NULL;
1345         }
1346         
1347         /* create pass */
1348         pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
1349
1350         pass->output = outlink->output;
1351         pass->shader = shader;
1352         pass->fragmentcode = fragmentcode;
1353         pass->vertexcode = vertexcode;
1354         pass->libcode = glsl_material_library;
1355
1356         /* extract dynamic inputs and throw away nodes */
1357         GPU_nodes_extract_dynamic_inputs(pass, nodes);
1358         GPU_nodes_free(nodes);
1359
1360         return pass;
1361 }
1362
1363 void GPU_pass_free(GPUPass *pass)
1364 {
1365         GPU_shader_free(pass->shader);
1366         GPU_inputs_free(&pass->inputs);
1367         if (pass->fragmentcode)
1368                 MEM_freeN(pass->fragmentcode);
1369         if (pass->vertexcode)
1370                 MEM_freeN(pass->vertexcode);
1371         MEM_freeN(pass);
1372 }
1373