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