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