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