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