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