use BLI_strncpy and BLI_snprintf when the size of the string is known.
[blender-staging.git] / source / blender / nodes / composite / node_composite_tree.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) 2007 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s):
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/nodes/composite/node_composite_tree.c
29  *  \ingroup nodes
30  */
31
32
33 #include <stdio.h>
34
35 #include "DNA_anim_types.h"
36 #include "DNA_scene_types.h"
37 #include "DNA_node_types.h"
38
39 #include "BLI_listbase.h"
40 #include "BLI_threads.h"
41
42 #include "BLF_translation.h"
43
44 #include "BKE_animsys.h"
45 #include "BKE_colortools.h"
46 #include "BKE_fcurve.h"
47 #include "BKE_global.h"
48 #include "BKE_main.h"
49 #include "BKE_node.h"
50 #include "BKE_tracking.h"
51 #include "BKE_utildefines.h"
52
53 #include "node_exec.h"
54 #include "node_util.h"
55
56 #include "PIL_time.h"
57
58 #include "RNA_access.h"
59
60 #include "NOD_composite.h"
61 #include "node_composite_util.h"
62
63 static void foreach_nodetree(Main *main, void *calldata, bNodeTreeCallback func)
64 {
65         Scene *sce;
66         for(sce= main->scene.first; sce; sce= sce->id.next) {
67                 if(sce->nodetree) {
68                         func(calldata, &sce->id, sce->nodetree);
69                 }
70         }
71 }
72
73 static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCallback func)
74 {
75         func(calldata, NODE_CLASS_INPUT, IFACE_("Input"));
76         func(calldata, NODE_CLASS_OUTPUT, IFACE_("Output"));
77         func(calldata, NODE_CLASS_OP_COLOR, IFACE_("Color"));
78         func(calldata, NODE_CLASS_OP_VECTOR, IFACE_("Vector"));
79         func(calldata, NODE_CLASS_OP_FILTER, IFACE_("Filter"));
80         func(calldata, NODE_CLASS_CONVERTOR, IFACE_("Convertor"));
81         func(calldata, NODE_CLASS_MATTE, IFACE_("Matte"));
82         func(calldata, NODE_CLASS_DISTORT, IFACE_("Distort"));
83         func(calldata, NODE_CLASS_GROUP, IFACE_("Group"));
84         func(calldata, NODE_CLASS_LAYOUT, IFACE_("Layout"));
85 }
86
87 static void free_node_cache(bNodeTree *UNUSED(ntree), bNode *node)
88 {
89         bNodeSocket *sock;
90         
91         for(sock= node->outputs.first; sock; sock= sock->next) {
92                 if(sock->cache) {
93                         free_compbuf(sock->cache);
94                         sock->cache= NULL;
95                 }
96         }
97 }
98
99 static void free_cache(bNodeTree *ntree)
100 {
101         bNode *node;
102         for(node= ntree->nodes.first; node; node= node->next)
103                 free_node_cache(ntree, node);
104 }
105
106 static void update_node(bNodeTree *ntree, bNode *node)
107 {
108         bNodeSocket *sock;
109
110         for(sock= node->outputs.first; sock; sock= sock->next) {
111                 if(sock->cache) {
112                         //free_compbuf(sock->cache);
113                         //sock->cache= NULL;
114                 }
115         }
116         node->need_exec= 1;
117         
118         /* individual node update call */
119         if (node->typeinfo->updatefunc)
120                 node->typeinfo->updatefunc(ntree, node);
121 }
122
123 /* local tree then owns all compbufs */
124 static void localize(bNodeTree *UNUSED(localtree), bNodeTree *ntree)
125 {
126         bNode *node;
127         bNodeSocket *sock;
128         
129         for(node= ntree->nodes.first; node; node= node->next) {
130                 /* ensure new user input gets handled ok */
131                 node->need_exec= 0;
132                 
133                 /* move over the compbufs */
134                 /* right after ntreeCopyTree() oldsock pointers are valid */
135                 
136                 if(ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
137                         if(node->id) {
138                                 if(node->flag & NODE_DO_OUTPUT)
139                                         node->new_node->id= (ID *)copy_image((Image *)node->id);
140                                 else
141                                         node->new_node->id= NULL;
142                         }
143                 }
144                 
145                 for(sock= node->outputs.first; sock; sock= sock->next) {
146                         sock->new_sock->cache= sock->cache;
147                         compbuf_set_node(sock->new_sock->cache, node->new_node);
148                         
149                         sock->cache= NULL;
150                         sock->new_sock->new_sock= sock;
151                 }
152         }
153 }
154
155 static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
156 {
157         bNode *lnode;
158         
159         /* move over the compbufs and previews */
160         for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) {
161                 if( (lnode->exec & NODE_READY) && !(lnode->exec & NODE_SKIPPED) ) {
162                         if(ntreeNodeExists(ntree, lnode->new_node)) {
163                                 
164                                 if(lnode->preview && lnode->preview->rect) {
165                                         nodeFreePreview(lnode->new_node);
166                                         lnode->new_node->preview= lnode->preview;
167                                         lnode->preview= NULL;
168                                 }
169                         }
170                 }
171         }
172 }
173
174 static void local_merge(bNodeTree *localtree, bNodeTree *ntree)
175 {
176         bNode *lnode;
177         bNodeSocket *lsock;
178         
179         /* move over the compbufs and previews */
180         for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) {
181                 if(ntreeNodeExists(ntree, lnode->new_node)) {
182                         if(ELEM(lnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
183                                 if(lnode->id && (lnode->flag & NODE_DO_OUTPUT)) {
184                                         /* image_merge does sanity check for pointers */
185                                         BKE_image_merge((Image *)lnode->new_node->id, (Image *)lnode->id);
186                                 }
187                         }
188                         else if(lnode->type==CMP_NODE_MOVIEDISTORTION) {
189                                 /* special case for distortion node: distortion context is allocating in exec function
190                                    and to achive much better performance on further calls this context should be
191                                    copied back to original node */
192                                 if(lnode->storage) {
193                                         if(lnode->new_node->storage)
194                                                 BKE_tracking_distortion_destroy(lnode->new_node->storage);
195
196                                         lnode->new_node->storage= BKE_tracking_distortion_copy(lnode->storage);
197                                 }
198                         }
199                         
200                         for(lsock= lnode->outputs.first; lsock; lsock= lsock->next) {
201                                 if(ntreeOutputExists(lnode->new_node, lsock->new_sock)) {
202                                         lsock->new_sock->cache= lsock->cache;
203                                         compbuf_set_node(lsock->new_sock->cache, lnode->new_node);
204                                         lsock->cache= NULL;
205                                         lsock->new_sock= NULL;
206                                 }
207                         }
208                 }
209         }
210 }
211
212 static void update(bNodeTree *ntree)
213 {
214         ntreeSetOutput(ntree);
215 }
216
217 bNodeTreeType ntreeType_Composite = {
218         /* type */                              NTREE_COMPOSIT,
219         /* idname */                    "NTCompositing Nodetree",
220         
221         /* node_types */                { NULL, NULL },
222         
223         /* free_cache */                free_cache,
224         /* free_node_cache */   free_node_cache,
225         /* foreach_nodetree */  foreach_nodetree,
226         /* foreach_nodeclass */ foreach_nodeclass,
227         /* localize */                  localize,
228         /* local_sync */                local_sync,
229         /* local_merge */               local_merge,
230         /* update */                    update,
231         /* update_node */               update_node,
232         /* validate_link */             NULL,
233         /* mutefunc */                  node_compo_pass_on,
234         /* mutelinksfunc */             node_mute_get_links,
235         /* gpumutefunc */               NULL
236 };
237
238
239 /* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
240  * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
241  */
242 struct bNodeTreeExec *ntreeCompositBeginExecTree(bNodeTree *ntree, int use_tree_data)
243 {
244         bNodeTreeExec *exec;
245         bNode *node;
246         bNodeSocket *sock;
247         
248         if (use_tree_data) {
249                 /* XXX hack: prevent exec data from being generated twice.
250                  * this should be handled by the renderer!
251                  */
252                 if (ntree->execdata)
253                         return ntree->execdata;
254         }
255         
256         /* ensures only a single output node is enabled */
257         ntreeSetOutput(ntree);
258         
259         exec = ntree_exec_begin(ntree);
260         
261         for(node= exec->nodetree->nodes.first; node; node= node->next) {
262                 /* initialize needed for groups */
263                 node->exec= 0;  
264                 
265                 for(sock= node->outputs.first; sock; sock= sock->next) {
266                         bNodeStack *ns= node_get_socket_stack(exec->stack, sock);
267                         if(ns && sock->cache) {
268                                 ns->data= sock->cache;
269                                 sock->cache= NULL;
270                         }
271                 }
272                 /* cannot initialize them while using in threads */
273                 if(ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT)) {
274                         curvemapping_initialize(node->storage);
275                         if(node->type==CMP_NODE_CURVE_RGB)
276                                 curvemapping_premultiply(node->storage, 0);
277                 }
278         }
279         
280         if (use_tree_data) {
281                 /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
282                  * which only store the ntree pointer. Should be fixed at some point!
283                  */
284                 ntree->execdata = exec;
285         }
286         
287         return exec;
288 }
289
290 /* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
291  * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
292  */
293 void ntreeCompositEndExecTree(bNodeTreeExec *exec, int use_tree_data)
294 {
295         if(exec) {
296                 bNodeTree *ntree= exec->nodetree;
297                 bNode *node;
298                 bNodeStack *ns;
299                 
300                 for(node= exec->nodetree->nodes.first; node; node= node->next) {
301                         bNodeSocket *sock;
302                         
303                         for(sock= node->outputs.first; sock; sock= sock->next) {
304                                 ns = node_get_socket_stack(exec->stack, sock);
305                                 if(ns && ns->data) {
306                                         sock->cache= ns->data;
307                                         ns->data= NULL;
308                                 }
309                         }
310                         if(node->type==CMP_NODE_CURVE_RGB)
311                                 curvemapping_premultiply(node->storage, 1);
312                         
313                         node->need_exec= 0;
314                 }
315         
316                 ntree_exec_end(exec);
317                 
318                 if (use_tree_data) {
319                         /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
320                         ntree->execdata = NULL;
321                 }
322         }
323 }
324
325 /* ***************************** threaded version for execute composite nodes ************* */
326 /* these are nodes without input, only giving values */
327 /* or nodes with only value inputs */
328 static int node_only_value(bNode *node)
329 {
330         bNodeSocket *sock;
331         
332         if(ELEM3(node->type, CMP_NODE_TIME, CMP_NODE_VALUE, CMP_NODE_RGB))
333                 return 1;
334         
335         /* doing this for all node types goes wrong. memory free errors */
336         if(node->inputs.first && node->type==CMP_NODE_MAP_VALUE) {
337                 int retval= 1;
338                 for(sock= node->inputs.first; sock; sock= sock->next) {
339                         if(sock->link)
340                                 retval &= node_only_value(sock->link->fromnode);
341                 }
342                 return retval;
343         }
344         return 0;
345 }
346
347 /* not changing info, for thread callback */
348 typedef struct ThreadData {
349         bNodeStack *stack;
350         RenderData *rd;
351 } ThreadData;
352
353 static void *exec_composite_node(void *nodeexec_v)
354 {
355         bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
356         bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
357         bNodeExec *nodeexec= nodeexec_v;
358         bNode *node= nodeexec->node;
359         ThreadData *thd= (ThreadData *)node->threaddata;
360         
361         node_get_stack(node, thd->stack, nsin, nsout);
362         
363         if((node->flag & NODE_MUTED) && node->typeinfo->mutefunc)
364                 node->typeinfo->mutefunc(thd->rd, 0, node, nodeexec->data, nsin, nsout);
365         else if(node->typeinfo->execfunc)
366                 node->typeinfo->execfunc(thd->rd, node, nsin, nsout);
367         else if (node->typeinfo->newexecfunc)
368                 node->typeinfo->newexecfunc(thd->rd, 0, node, nodeexec->data, nsin, nsout);
369         
370         node->exec |= NODE_READY;
371         return NULL;
372 }
373
374 /* return total of executable nodes, for timecursor */
375 static int setExecutableNodes(bNodeTreeExec *exec, ThreadData *thd)
376 {
377         bNodeTree *ntree = exec->nodetree;
378         bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
379         bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
380         bNodeExec *nodeexec;
381         bNode *node;
382         bNodeSocket *sock;
383         int n, totnode= 0, group_edit= 0;
384         
385         /* if we are in group edit, viewer nodes get skipped when group has viewer */
386         for(node= ntree->nodes.first; node; node= node->next)
387                 if(node->type==NODE_GROUP && (node->flag & NODE_GROUP_EDIT))
388                         if(ntreeHasType((bNodeTree *)node->id, CMP_NODE_VIEWER))
389                                 group_edit= 1;
390         
391         /* NB: using the exec data list here to have valid dependency sort */
392         for(n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
393                 int a;
394                 node = nodeexec->node;
395                 
396                 node_get_stack(node, exec->stack, nsin, nsout);
397                 
398                 /* test the outputs */
399                 /* skip value-only nodes (should be in type!) */
400                 if(!node_only_value(node)) {
401                         for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
402                                 if(nsout[a]->data==NULL && nsout[a]->hasoutput) {
403                                         node->need_exec= 1;
404                                         break;
405                                 }
406                         }
407                 }
408                 
409                 /* test the inputs */
410                 for(a=0, sock= node->inputs.first; sock; sock= sock->next, a++) {
411                         /* skip viewer nodes in bg render or group edit */
412                         if( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) && (G.background || group_edit))
413                                 node->need_exec= 0;
414                         /* is sock in use? */
415                         else if(sock->link) {
416                                 bNodeLink *link= sock->link;
417                                 
418                                 /* this is the test for a cyclic case */
419                                 if(link->fromnode==NULL || link->tonode==NULL);
420                                 else if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF) {
421                                         if(link->fromnode->need_exec) {
422                                                 node->need_exec= 1;
423                                                 break;
424                                         }
425                                 }
426                                 else {
427                                         node->need_exec= 0;
428                                         printf("Node %s skipped, cyclic dependency\n", node->name);
429                                 }
430                         }
431                 }
432                 
433                 if(node->need_exec) {
434                         
435                         /* free output buffers */
436                         for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
437                                 if(nsout[a]->data) {
438                                         free_compbuf(nsout[a]->data);
439                                         nsout[a]->data= NULL;
440                                 }
441                         }
442                         totnode++;
443                         /* printf("node needs exec %s\n", node->name); */
444                         
445                         /* tag for getExecutableNode() */
446                         node->exec= 0;
447                 }
448                 else {
449                         /* tag for getExecutableNode() */
450                         node->exec= NODE_READY|NODE_FINISHED|NODE_SKIPPED;
451                         
452                 }
453         }
454         
455         /* last step: set the stack values for only-value nodes */
456         /* just does all now, compared to a full buffer exec this is nothing */
457         if(totnode) {
458                 for(n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
459                         node = nodeexec->node;
460                         if(node->need_exec==0 && node_only_value(node)) {
461                                 if(node->typeinfo->execfunc) {
462                                         node_get_stack(node, exec->stack, nsin, nsout);
463                                         node->typeinfo->execfunc(thd->rd, node, nsin, nsout);
464                                 }
465                         }
466                 }
467         }
468         
469         return totnode;
470 }
471
472 /* while executing tree, free buffers from nodes that are not needed anymore */
473 static void freeExecutableNode(bNodeTreeExec *exec)
474 {
475         /* node outputs can be freed when:
476         - not a render result or image node
477         - when node outputs go to nodes all being set NODE_FINISHED
478         */
479         bNodeTree *ntree = exec->nodetree;
480         bNodeExec *nodeexec;
481         bNode *node;
482         bNodeSocket *sock;
483         int n;
484         
485         /* set exec flag for finished nodes that might need freed */
486         for(node= ntree->nodes.first; node; node= node->next) {
487                 if(node->type!=CMP_NODE_R_LAYERS)
488                         if(node->exec & NODE_FINISHED)
489                                 node->exec |= NODE_FREEBUFS;
490         }
491         /* clear this flag for input links that are not done yet.
492          * Using the exec data for valid dependency sort.
493          */
494         for(n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
495                 node = nodeexec->node;
496                 if((node->exec & NODE_FINISHED)==0) {
497                         for(sock= node->inputs.first; sock; sock= sock->next)
498                                 if(sock->link)
499                                         sock->link->fromnode->exec &= ~NODE_FREEBUFS;
500                 }
501         }
502         /* now we can free buffers */
503         for(node= ntree->nodes.first; node; node= node->next) {
504                 if(node->exec & NODE_FREEBUFS) {
505                         for(sock= node->outputs.first; sock; sock= sock->next) {
506                                 bNodeStack *ns= node_get_socket_stack(exec->stack, sock);
507                                 if(ns && ns->data) {
508                                         free_compbuf(ns->data);
509                                         ns->data= NULL;
510                                         // printf("freed buf node %s \n", node->name);
511                                 }
512                         }
513                 }
514         }
515 }
516
517 static bNodeExec *getExecutableNode(bNodeTreeExec *exec)
518 {
519         bNodeExec *nodeexec;
520         bNodeSocket *sock;
521         int n;
522         
523         for(n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
524                 if(nodeexec->node->exec==0) {
525                         /* input sockets should be ready */
526                         for(sock= nodeexec->node->inputs.first; sock; sock= sock->next) {
527                                 if(sock->link && sock->link->fromnode)
528                                         if((sock->link->fromnode->exec & NODE_READY)==0)
529                                                 break;
530                         }
531                         if(sock==NULL)
532                                 return nodeexec;
533                 }
534         }
535         return NULL;
536 }
537
538 /* check if texture nodes need exec or end */
539 static  void ntree_composite_texnode(bNodeTree *ntree, int init)
540 {
541         bNode *node;
542         
543         for(node= ntree->nodes.first; node; node= node->next) {
544                 if(node->type==CMP_NODE_TEXTURE && node->id) {
545                         Tex *tex= (Tex *)node->id;
546                         if(tex->nodetree && tex->use_nodes) {
547                                 /* has internal flag to detect it only does it once */
548                                 if(init) {
549                                         if (!tex->nodetree->execdata)
550                                                 tex->nodetree->execdata = ntreeTexBeginExecTree(tex->nodetree, 1); 
551                                 }
552                                 else
553                                         ntreeTexEndExecTree(tex->nodetree->execdata, 1);
554                                         tex->nodetree->execdata = NULL;
555                         }
556                 }
557         }
558
559 }
560
561 /* optimized tree execute test for compositing */
562 void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview)
563 {
564         bNodeExec *nodeexec;
565         bNode *node;
566         ListBase threads;
567         ThreadData thdata;
568         int totnode, curnode, rendering= 1, n;
569         bNodeTreeExec *exec= ntree->execdata;
570         
571         if(ntree==NULL) return;
572         
573         if(do_preview)
574                 ntreeInitPreview(ntree, 0, 0);
575         
576         if (!ntree->execdata) {
577                 /* XXX this is the top-level tree, so we use the ntree->execdata pointer. */
578                 exec = ntreeCompositBeginExecTree(ntree, 1);
579         }
580         ntree_composite_texnode(ntree, 1);
581         
582         /* prevent unlucky accidents */
583         if(G.background)
584                 rd->scemode &= ~R_COMP_CROP;
585         
586         /* setup callerdata for thread callback */
587         thdata.rd= rd;
588         thdata.stack= exec->stack;
589         
590         /* fixed seed, for example noise texture */
591         BLI_srandom(rd->cfra);
592
593         /* sets need_exec tags in nodes */
594         curnode = totnode= setExecutableNodes(exec, &thdata);
595
596         BLI_init_threads(&threads, exec_composite_node, rd->threads);
597         
598         while(rendering) {
599                 
600                 if(BLI_available_threads(&threads)) {
601                         nodeexec= getExecutableNode(exec);
602                         if(nodeexec) {
603                                 node = nodeexec->node;
604                                 if(ntree->progress && totnode)
605                                         ntree->progress(ntree->prh, (1.0f - curnode/(float)totnode));
606                                 if(ntree->stats_draw) {
607                                         char str[128];
608                                         BLI_snprintf(str, sizeof(str), "Compositing %d %s", curnode, node->name);
609                                         ntree->stats_draw(ntree->sdh, str);
610                                 }
611                                 curnode--;
612                                 
613                                 node->threaddata = &thdata;
614                                 node->exec= NODE_PROCESSING;
615                                 BLI_insert_thread(&threads, nodeexec);
616                         }
617                         else
618                                 PIL_sleep_ms(50);
619                 }
620                 else
621                         PIL_sleep_ms(50);
622                 
623                 rendering= 0;
624                 /* test for ESC */
625                 if(ntree->test_break && ntree->test_break(ntree->tbh)) {
626                         for(node= ntree->nodes.first; node; node= node->next)
627                                 node->exec |= NODE_READY;
628                 }
629                 
630                 /* check for ready ones, and if we need to continue */
631                 for(n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
632                         node = nodeexec->node;
633                         if(node->exec & NODE_READY) {
634                                 if((node->exec & NODE_FINISHED)==0) {
635                                         BLI_remove_thread(&threads, nodeexec); /* this waits for running thread to finish btw */
636                                         node->exec |= NODE_FINISHED;
637                                         
638                                         /* freeing unused buffers */
639                                         if(rd->scemode & R_COMP_FREE)
640                                                 freeExecutableNode(exec);
641                                 }
642                         }
643                         else rendering= 1;
644                 }
645         }
646         
647         BLI_end_threads(&threads);
648         
649         /* XXX top-level tree uses the ntree->execdata pointer */
650         ntreeCompositEndExecTree(exec, 1);
651 }
652
653 /* *********************************************** */
654
655 /* clumsy checking... should do dynamic outputs once */
656 static void force_hidden_passes(bNode *node, int passflag)
657 {
658         bNodeSocket *sock;
659         
660         for(sock= node->outputs.first; sock; sock= sock->next)
661                 sock->flag &= ~SOCK_UNAVAIL;
662         
663         sock= BLI_findlink(&node->outputs, RRES_OUT_Z);
664         if(!(passflag & SCE_PASS_Z)) sock->flag |= SOCK_UNAVAIL;
665         sock= BLI_findlink(&node->outputs, RRES_OUT_NORMAL);
666         if(!(passflag & SCE_PASS_NORMAL)) sock->flag |= SOCK_UNAVAIL;
667         sock= BLI_findlink(&node->outputs, RRES_OUT_VEC);
668         if(!(passflag & SCE_PASS_VECTOR)) sock->flag |= SOCK_UNAVAIL;
669         sock= BLI_findlink(&node->outputs, RRES_OUT_UV);
670         if(!(passflag & SCE_PASS_UV)) sock->flag |= SOCK_UNAVAIL;
671         sock= BLI_findlink(&node->outputs, RRES_OUT_RGBA);
672         if(!(passflag & SCE_PASS_RGBA)) sock->flag |= SOCK_UNAVAIL;
673         sock= BLI_findlink(&node->outputs, RRES_OUT_DIFF);
674         if(!(passflag & SCE_PASS_DIFFUSE)) sock->flag |= SOCK_UNAVAIL;
675         sock= BLI_findlink(&node->outputs, RRES_OUT_SPEC);
676         if(!(passflag & SCE_PASS_SPEC)) sock->flag |= SOCK_UNAVAIL;
677         sock= BLI_findlink(&node->outputs, RRES_OUT_SHADOW);
678         if(!(passflag & SCE_PASS_SHADOW)) sock->flag |= SOCK_UNAVAIL;
679         sock= BLI_findlink(&node->outputs, RRES_OUT_AO);
680         if(!(passflag & SCE_PASS_AO)) sock->flag |= SOCK_UNAVAIL;
681         sock= BLI_findlink(&node->outputs, RRES_OUT_REFLECT);
682         if(!(passflag & SCE_PASS_REFLECT)) sock->flag |= SOCK_UNAVAIL;
683         sock= BLI_findlink(&node->outputs, RRES_OUT_REFRACT);
684         if(!(passflag & SCE_PASS_REFRACT)) sock->flag |= SOCK_UNAVAIL;
685         sock= BLI_findlink(&node->outputs, RRES_OUT_INDIRECT);
686         if(!(passflag & SCE_PASS_INDIRECT)) sock->flag |= SOCK_UNAVAIL;
687         sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXOB);
688         if(!(passflag & SCE_PASS_INDEXOB)) sock->flag |= SOCK_UNAVAIL;
689         sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXMA);
690         if(!(passflag & SCE_PASS_INDEXMA)) sock->flag |= SOCK_UNAVAIL;
691         sock= BLI_findlink(&node->outputs, RRES_OUT_MIST);
692         if(!(passflag & SCE_PASS_MIST)) sock->flag |= SOCK_UNAVAIL;
693         sock= BLI_findlink(&node->outputs, RRES_OUT_EMIT);
694         if(!(passflag & SCE_PASS_EMIT)) sock->flag |= SOCK_UNAVAIL;
695         sock= BLI_findlink(&node->outputs, RRES_OUT_ENV);
696         if(!(passflag & SCE_PASS_ENVIRONMENT)) sock->flag |= SOCK_UNAVAIL;
697         
698 }
699
700 /* based on rules, force sockets hidden always */
701 void ntreeCompositForceHidden(bNodeTree *ntree, Scene *curscene)
702 {
703         bNode *node;
704         
705         if(ntree==NULL) return;
706         
707         for(node= ntree->nodes.first; node; node= node->next) {
708                 if( node->type==CMP_NODE_R_LAYERS) {
709                         Scene *sce= node->id?(Scene *)node->id:curscene;
710                         SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1);
711                         if(srl)
712                                 force_hidden_passes(node, srl->passflag);
713                 }
714                 else if( node->type==CMP_NODE_IMAGE) {
715                         Image *ima= (Image *)node->id;
716                         if(ima) {
717                                 if(ima->rr) {
718                                         ImageUser *iuser= node->storage;
719                                         RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
720                                         if(rl)
721                                                 force_hidden_passes(node, rl->passflag);
722                                         else
723                                                 force_hidden_passes(node, 0);
724                                 }
725                                 else if(ima->type!=IMA_TYPE_MULTILAYER) {       /* if ->rr not yet read we keep inputs */
726                                         force_hidden_passes(node, RRES_OUT_Z);
727                                 }
728                                 else
729                                         force_hidden_passes(node, 0);
730                         }
731                         else
732                                 force_hidden_passes(node, 0);
733                 }
734         }
735
736 }
737
738 /* called from render pipeline, to tag render input and output */
739 /* need to do all scenes, to prevent errors when you re-render 1 scene */
740 void ntreeCompositTagRender(Scene *curscene)
741 {
742         Scene *sce;
743         
744         for(sce= G.main->scene.first; sce; sce= sce->id.next) {
745                 if(sce->nodetree) {
746                         bNode *node;
747                         
748                         for(node= sce->nodetree->nodes.first; node; node= node->next) {
749                                 if(node->id==(ID *)curscene || node->type==CMP_NODE_COMPOSITE)
750                                         nodeUpdate(sce->nodetree, node);
751                                 else if(node->type==CMP_NODE_TEXTURE) /* uses scene sizex/sizey */
752                                         nodeUpdate(sce->nodetree, node);
753                         }
754                 }
755         }
756 }
757
758 static int node_animation_properties(bNodeTree *ntree, bNode *node)
759 {
760         bNodeSocket *sock;
761         const ListBase *lb;
762         Link *link;
763         PointerRNA ptr;
764         PropertyRNA *prop;
765         
766         /* check to see if any of the node's properties have fcurves */
767         RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr);
768         lb = RNA_struct_type_properties(ptr.type);
769         
770         for (link=lb->first; link; link=link->next) {
771                 int driven, len=1, index;
772                 prop = (PropertyRNA *)link;
773                 
774                 if (RNA_property_array_check(prop))
775                         len = RNA_property_array_length(&ptr, prop);
776                 
777                 for (index=0; index<len; index++) {
778                         if (rna_get_fcurve(&ptr, prop, index, NULL, &driven)) {
779                                 nodeUpdate(ntree, node);
780                                 return 1;
781                         }
782                 }
783         }
784         
785         /* now check node sockets */
786         for (sock = node->inputs.first; sock; sock=sock->next) {
787                 int driven, len=1, index;
788                 
789                 RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
790                 prop = RNA_struct_find_property(&ptr, "default_value");
791                 if (prop) {
792                         if (RNA_property_array_check(prop))
793                                 len = RNA_property_array_length(&ptr, prop);
794                         
795                         for (index=0; index<len; index++) {
796                                 if (rna_get_fcurve(&ptr, prop, index, NULL, &driven)) {
797                                         nodeUpdate(ntree, node);
798                                         return 1;
799                                 }
800                         }
801                 }
802         }
803
804         return 0;
805 }
806
807 /* tags nodes that have animation capabilities */
808 int ntreeCompositTagAnimated(bNodeTree *ntree)
809 {
810         bNode *node;
811         int tagged= 0;
812         
813         if(ntree==NULL) return 0;
814         
815         for(node= ntree->nodes.first; node; node= node->next) {
816                 
817                 tagged = node_animation_properties(ntree, node);
818                 
819                 /* otherwise always tag these node types */
820                 if(node->type==CMP_NODE_IMAGE) {
821                         Image *ima= (Image *)node->id;
822                         if(ima && ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
823                                 nodeUpdate(ntree, node);
824                                 tagged= 1;
825                         }
826                 }
827                 else if(node->type==CMP_NODE_TIME) {
828                         nodeUpdate(ntree, node);
829                         tagged= 1;
830                 }
831                 /* here was tag render layer, but this is called after a render, so re-composites fail */
832                 else if(node->type==NODE_GROUP) {
833                         if( ntreeCompositTagAnimated((bNodeTree *)node->id) ) {
834                                 nodeUpdate(ntree, node);
835                         }
836                 }
837                 else if(ELEM(node->type, CMP_NODE_MOVIECLIP, CMP_NODE_TRANSFORM)) {
838                         nodeUpdate(ntree, node);
839                         tagged= 1;
840                 }
841         }
842         
843         return tagged;
844 }
845
846
847 /* called from image window preview */
848 void ntreeCompositTagGenerators(bNodeTree *ntree)
849 {
850         bNode *node;
851         
852         if(ntree==NULL) return;
853         
854         for(node= ntree->nodes.first; node; node= node->next) {
855                 if( ELEM(node->type, CMP_NODE_R_LAYERS, CMP_NODE_IMAGE))
856                         nodeUpdate(ntree, node);
857         }
858 }
859
860 /* XXX after render animation system gets a refresh, this call allows composite to end clean */
861 void ntreeCompositClearTags(bNodeTree *ntree)
862 {
863         bNode *node;
864         
865         if(ntree==NULL) return;
866         
867         for(node= ntree->nodes.first; node; node= node->next) {
868                 node->need_exec= 0;
869                 if(node->type==NODE_GROUP)
870                         ntreeCompositClearTags((bNodeTree *)node->id);
871         }
872 }