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