Blender V2.61 - r43446

node_composite_tree.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version. 
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2007 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s):
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <stdio.h>
00034 
00035 #include "DNA_anim_types.h"
00036 #include "DNA_scene_types.h"
00037 #include "DNA_node_types.h"
00038 
00039 #include "BLI_listbase.h"
00040 #include "BLI_threads.h"
00041 
00042 #include "BLF_translation.h"
00043 
00044 #include "BKE_animsys.h"
00045 #include "BKE_colortools.h"
00046 #include "BKE_fcurve.h"
00047 #include "BKE_global.h"
00048 #include "BKE_main.h"
00049 #include "BKE_node.h"
00050 #include "BKE_tracking.h"
00051 #include "BKE_utildefines.h"
00052 
00053 #include "node_exec.h"
00054 #include "node_util.h"
00055 
00056 #include "PIL_time.h"
00057 
00058 #include "RNA_access.h"
00059 
00060 #include "NOD_composite.h"
00061 #include "node_composite_util.h"
00062 
00063 static void foreach_nodetree(Main *main, void *calldata, bNodeTreeCallback func)
00064 {
00065     Scene *sce;
00066     for(sce= main->scene.first; sce; sce= sce->id.next) {
00067         if(sce->nodetree) {
00068             func(calldata, &sce->id, sce->nodetree);
00069         }
00070     }
00071 }
00072 
00073 static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCallback func)
00074 {
00075     func(calldata, NODE_CLASS_INPUT, IFACE_("Input"));
00076     func(calldata, NODE_CLASS_OUTPUT, IFACE_("Output"));
00077     func(calldata, NODE_CLASS_OP_COLOR, IFACE_("Color"));
00078     func(calldata, NODE_CLASS_OP_VECTOR, IFACE_("Vector"));
00079     func(calldata, NODE_CLASS_OP_FILTER, IFACE_("Filter"));
00080     func(calldata, NODE_CLASS_CONVERTOR, IFACE_("Convertor"));
00081     func(calldata, NODE_CLASS_MATTE, IFACE_("Matte"));
00082     func(calldata, NODE_CLASS_DISTORT, IFACE_("Distort"));
00083     func(calldata, NODE_CLASS_GROUP, IFACE_("Group"));
00084     func(calldata, NODE_CLASS_LAYOUT, IFACE_("Layout"));
00085 }
00086 
00087 static void free_node_cache(bNodeTree *UNUSED(ntree), bNode *node)
00088 {
00089     bNodeSocket *sock;
00090     
00091     for(sock= node->outputs.first; sock; sock= sock->next) {
00092         if(sock->cache) {
00093             free_compbuf(sock->cache);
00094             sock->cache= NULL;
00095         }
00096     }
00097 }
00098 
00099 static void free_cache(bNodeTree *ntree)
00100 {
00101     bNode *node;
00102     for(node= ntree->nodes.first; node; node= node->next)
00103         free_node_cache(ntree, node);
00104 }
00105 
00106 static void update_node(bNodeTree *ntree, bNode *node)
00107 {
00108     bNodeSocket *sock;
00109 
00110     for(sock= node->outputs.first; sock; sock= sock->next) {
00111         if(sock->cache) {
00112             //free_compbuf(sock->cache);
00113             //sock->cache= NULL;
00114         }
00115     }
00116     node->need_exec= 1;
00117     
00118     /* individual node update call */
00119     if (node->typeinfo->updatefunc)
00120         node->typeinfo->updatefunc(ntree, node);
00121 }
00122 
00123 /* local tree then owns all compbufs */
00124 static void localize(bNodeTree *UNUSED(localtree), bNodeTree *ntree)
00125 {
00126     bNode *node;
00127     bNodeSocket *sock;
00128     
00129     for(node= ntree->nodes.first; node; node= node->next) {
00130         /* ensure new user input gets handled ok */
00131         node->need_exec= 0;
00132         
00133         /* move over the compbufs */
00134         /* right after ntreeCopyTree() oldsock pointers are valid */
00135         
00136         if(ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
00137             if(node->id) {
00138                 if(node->flag & NODE_DO_OUTPUT)
00139                     node->new_node->id= (ID *)copy_image((Image *)node->id);
00140                 else
00141                     node->new_node->id= NULL;
00142             }
00143         }
00144         
00145         for(sock= node->outputs.first; sock; sock= sock->next) {
00146             sock->new_sock->cache= sock->cache;
00147             compbuf_set_node(sock->new_sock->cache, node->new_node);
00148             
00149             sock->cache= NULL;
00150             sock->new_sock->new_sock= sock;
00151         }
00152     }
00153 }
00154 
00155 static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
00156 {
00157     bNode *lnode;
00158     
00159     /* move over the compbufs and previews */
00160     for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) {
00161         if( (lnode->exec & NODE_READY) && !(lnode->exec & NODE_SKIPPED) ) {
00162             if(ntreeNodeExists(ntree, lnode->new_node)) {
00163                 
00164                 if(lnode->preview && lnode->preview->rect) {
00165                     nodeFreePreview(lnode->new_node);
00166                     lnode->new_node->preview= lnode->preview;
00167                     lnode->preview= NULL;
00168                 }
00169             }
00170         }
00171     }
00172 }
00173 
00174 static void local_merge(bNodeTree *localtree, bNodeTree *ntree)
00175 {
00176     bNode *lnode;
00177     bNodeSocket *lsock;
00178     
00179     /* move over the compbufs and previews */
00180     for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) {
00181         if(ntreeNodeExists(ntree, lnode->new_node)) {
00182             if(ELEM(lnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
00183                 if(lnode->id && (lnode->flag & NODE_DO_OUTPUT)) {
00184                     /* image_merge does sanity check for pointers */
00185                     BKE_image_merge((Image *)lnode->new_node->id, (Image *)lnode->id);
00186                 }
00187             }
00188             else if(lnode->type==CMP_NODE_MOVIEDISTORTION) {
00189                 /* special case for distortion node: distortion context is allocating in exec function
00190                    and to achive much better performance on further calls this context should be
00191                    copied back to original node */
00192                 if(lnode->storage) {
00193                     if(lnode->new_node->storage)
00194                         BKE_tracking_distortion_destroy(lnode->new_node->storage);
00195 
00196                     lnode->new_node->storage= BKE_tracking_distortion_copy(lnode->storage);
00197                 }
00198             }
00199             
00200             for(lsock= lnode->outputs.first; lsock; lsock= lsock->next) {
00201                 if(ntreeOutputExists(lnode->new_node, lsock->new_sock)) {
00202                     lsock->new_sock->cache= lsock->cache;
00203                     compbuf_set_node(lsock->new_sock->cache, lnode->new_node);
00204                     lsock->cache= NULL;
00205                     lsock->new_sock= NULL;
00206                 }
00207             }
00208         }
00209     }
00210 }
00211 
00212 static void update(bNodeTree *ntree)
00213 {
00214     ntreeSetOutput(ntree);
00215 }
00216 
00217 bNodeTreeType ntreeType_Composite = {
00218     /* type */              NTREE_COMPOSIT,
00219     /* idname */            "NTCompositing Nodetree",
00220     
00221     /* node_types */        { NULL, NULL },
00222     
00223     /* free_cache */        free_cache,
00224     /* free_node_cache */   free_node_cache,
00225     /* foreach_nodetree */  foreach_nodetree,
00226     /* foreach_nodeclass */ foreach_nodeclass,
00227     /* localize */          localize,
00228     /* local_sync */        local_sync,
00229     /* local_merge */       local_merge,
00230     /* update */            update,
00231     /* update_node */       update_node,
00232     /* validate_link */     NULL,
00233     /* mutefunc */          node_compo_pass_on,
00234     /* mutelinksfunc */     node_mute_get_links,
00235     /* gpumutefunc */       NULL
00236 };
00237 
00238 
00239 /* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
00240  * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
00241  */
00242 struct bNodeTreeExec *ntreeCompositBeginExecTree(bNodeTree *ntree, int use_tree_data)
00243 {
00244     bNodeTreeExec *exec;
00245     bNode *node;
00246     bNodeSocket *sock;
00247     
00248     if (use_tree_data) {
00249         /* XXX hack: prevent exec data from being generated twice.
00250          * this should be handled by the renderer!
00251          */
00252         if (ntree->execdata)
00253             return ntree->execdata;
00254     }
00255     
00256     /* ensures only a single output node is enabled */
00257     ntreeSetOutput(ntree);
00258     
00259     exec = ntree_exec_begin(ntree);
00260     
00261     for(node= exec->nodetree->nodes.first; node; node= node->next) {
00262         /* initialize needed for groups */
00263         node->exec= 0;  
00264         
00265         for(sock= node->outputs.first; sock; sock= sock->next) {
00266             bNodeStack *ns= node_get_socket_stack(exec->stack, sock);
00267             if(ns && sock->cache) {
00268                 ns->data= sock->cache;
00269                 sock->cache= NULL;
00270             }
00271         }
00272         /* cannot initialize them while using in threads */
00273         if(ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT)) {
00274             curvemapping_initialize(node->storage);
00275             if(node->type==CMP_NODE_CURVE_RGB)
00276                 curvemapping_premultiply(node->storage, 0);
00277         }
00278     }
00279     
00280     if (use_tree_data) {
00281         /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
00282          * which only store the ntree pointer. Should be fixed at some point!
00283          */
00284         ntree->execdata = exec;
00285     }
00286     
00287     return exec;
00288 }
00289 
00290 /* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
00291  * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
00292  */
00293 void ntreeCompositEndExecTree(bNodeTreeExec *exec, int use_tree_data)
00294 {
00295     if(exec) {
00296         bNodeTree *ntree= exec->nodetree;
00297         bNode *node;
00298         bNodeStack *ns;
00299         
00300         for(node= exec->nodetree->nodes.first; node; node= node->next) {
00301             bNodeSocket *sock;
00302             
00303             for(sock= node->outputs.first; sock; sock= sock->next) {
00304                 ns = node_get_socket_stack(exec->stack, sock);
00305                 if(ns && ns->data) {
00306                     sock->cache= ns->data;
00307                     ns->data= NULL;
00308                 }
00309             }
00310             if(node->type==CMP_NODE_CURVE_RGB)
00311                 curvemapping_premultiply(node->storage, 1);
00312             
00313             node->need_exec= 0;
00314         }
00315     
00316         ntree_exec_end(exec);
00317         
00318         if (use_tree_data) {
00319             /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
00320             ntree->execdata = NULL;
00321         }
00322     }
00323 }
00324 
00325 /* ***************************** threaded version for execute composite nodes ************* */
00326 /* these are nodes without input, only giving values */
00327 /* or nodes with only value inputs */
00328 static int node_only_value(bNode *node)
00329 {
00330     bNodeSocket *sock;
00331     
00332     if(ELEM3(node->type, CMP_NODE_TIME, CMP_NODE_VALUE, CMP_NODE_RGB))
00333         return 1;
00334     
00335     /* doing this for all node types goes wrong. memory free errors */
00336     if(node->inputs.first && node->type==CMP_NODE_MAP_VALUE) {
00337         int retval= 1;
00338         for(sock= node->inputs.first; sock; sock= sock->next) {
00339             if(sock->link)
00340                 retval &= node_only_value(sock->link->fromnode);
00341         }
00342         return retval;
00343     }
00344     return 0;
00345 }
00346 
00347 /* not changing info, for thread callback */
00348 typedef struct ThreadData {
00349     bNodeStack *stack;
00350     RenderData *rd;
00351 } ThreadData;
00352 
00353 static void *exec_composite_node(void *nodeexec_v)
00354 {
00355     bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
00356     bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
00357     bNodeExec *nodeexec= nodeexec_v;
00358     bNode *node= nodeexec->node;
00359     ThreadData *thd= (ThreadData *)node->threaddata;
00360     
00361     node_get_stack(node, thd->stack, nsin, nsout);
00362     
00363     if((node->flag & NODE_MUTED) && node->typeinfo->mutefunc)
00364         node->typeinfo->mutefunc(thd->rd, 0, node, nodeexec->data, nsin, nsout);
00365     else if(node->typeinfo->execfunc)
00366         node->typeinfo->execfunc(thd->rd, node, nsin, nsout);
00367     else if (node->typeinfo->newexecfunc)
00368         node->typeinfo->newexecfunc(thd->rd, 0, node, nodeexec->data, nsin, nsout);
00369     
00370     node->exec |= NODE_READY;
00371     return NULL;
00372 }
00373 
00374 /* return total of executable nodes, for timecursor */
00375 static int setExecutableNodes(bNodeTreeExec *exec, ThreadData *thd)
00376 {
00377     bNodeTree *ntree = exec->nodetree;
00378     bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
00379     bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
00380     bNodeExec *nodeexec;
00381     bNode *node;
00382     bNodeSocket *sock;
00383     int n, totnode= 0, group_edit= 0;
00384     
00385     /* if we are in group edit, viewer nodes get skipped when group has viewer */
00386     for(node= ntree->nodes.first; node; node= node->next)
00387         if(node->type==NODE_GROUP && (node->flag & NODE_GROUP_EDIT))
00388             if(ntreeHasType((bNodeTree *)node->id, CMP_NODE_VIEWER))
00389                 group_edit= 1;
00390     
00391     /* NB: using the exec data list here to have valid dependency sort */
00392     for(n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
00393         int a;
00394         node = nodeexec->node;
00395         
00396         node_get_stack(node, exec->stack, nsin, nsout);
00397         
00398         /* test the outputs */
00399         /* skip value-only nodes (should be in type!) */
00400         if(!node_only_value(node)) {
00401             for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
00402                 if(nsout[a]->data==NULL && nsout[a]->hasoutput) {
00403                     node->need_exec= 1;
00404                     break;
00405                 }
00406             }
00407         }
00408         
00409         /* test the inputs */
00410         for(a=0, sock= node->inputs.first; sock; sock= sock->next, a++) {
00411             /* skip viewer nodes in bg render or group edit */
00412             if( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) && (G.background || group_edit))
00413                 node->need_exec= 0;
00414             /* is sock in use? */
00415             else if(sock->link) {
00416                 bNodeLink *link= sock->link;
00417                 
00418                 /* this is the test for a cyclic case */
00419                 if(link->fromnode==NULL || link->tonode==NULL);
00420                 else if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF) {
00421                     if(link->fromnode->need_exec) {
00422                         node->need_exec= 1;
00423                         break;
00424                     }
00425                 }
00426                 else {
00427                     node->need_exec= 0;
00428                     printf("Node %s skipped, cyclic dependency\n", node->name);
00429                 }
00430             }
00431         }
00432         
00433         if(node->need_exec) {
00434             
00435             /* free output buffers */
00436             for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
00437                 if(nsout[a]->data) {
00438                     free_compbuf(nsout[a]->data);
00439                     nsout[a]->data= NULL;
00440                 }
00441             }
00442             totnode++;
00443             /* printf("node needs exec %s\n", node->name); */
00444             
00445             /* tag for getExecutableNode() */
00446             node->exec= 0;
00447         }
00448         else {
00449             /* tag for getExecutableNode() */
00450             node->exec= NODE_READY|NODE_FINISHED|NODE_SKIPPED;
00451             
00452         }
00453     }
00454     
00455     /* last step: set the stack values for only-value nodes */
00456     /* just does all now, compared to a full buffer exec this is nothing */
00457     if(totnode) {
00458         for(n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
00459             node = nodeexec->node;
00460             if(node->need_exec==0 && node_only_value(node)) {
00461                 if(node->typeinfo->execfunc) {
00462                     node_get_stack(node, exec->stack, nsin, nsout);
00463                     node->typeinfo->execfunc(thd->rd, node, nsin, nsout);
00464                 }
00465             }
00466         }
00467     }
00468     
00469     return totnode;
00470 }
00471 
00472 /* while executing tree, free buffers from nodes that are not needed anymore */
00473 static void freeExecutableNode(bNodeTreeExec *exec)
00474 {
00475     /* node outputs can be freed when:
00476     - not a render result or image node
00477     - when node outputs go to nodes all being set NODE_FINISHED
00478     */
00479     bNodeTree *ntree = exec->nodetree;
00480     bNodeExec *nodeexec;
00481     bNode *node;
00482     bNodeSocket *sock;
00483     int n;
00484     
00485     /* set exec flag for finished nodes that might need freed */
00486     for(node= ntree->nodes.first; node; node= node->next) {
00487         if(node->type!=CMP_NODE_R_LAYERS)
00488             if(node->exec & NODE_FINISHED)
00489                 node->exec |= NODE_FREEBUFS;
00490     }
00491     /* clear this flag for input links that are not done yet.
00492      * Using the exec data for valid dependency sort.
00493      */
00494     for(n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
00495         node = nodeexec->node;
00496         if((node->exec & NODE_FINISHED)==0) {
00497             for(sock= node->inputs.first; sock; sock= sock->next)
00498                 if(sock->link)
00499                     sock->link->fromnode->exec &= ~NODE_FREEBUFS;
00500         }
00501     }
00502     /* now we can free buffers */
00503     for(node= ntree->nodes.first; node; node= node->next) {
00504         if(node->exec & NODE_FREEBUFS) {
00505             for(sock= node->outputs.first; sock; sock= sock->next) {
00506                 bNodeStack *ns= node_get_socket_stack(exec->stack, sock);
00507                 if(ns && ns->data) {
00508                     free_compbuf(ns->data);
00509                     ns->data= NULL;
00510                     // printf("freed buf node %s \n", node->name);
00511                 }
00512             }
00513         }
00514     }
00515 }
00516 
00517 static bNodeExec *getExecutableNode(bNodeTreeExec *exec)
00518 {
00519     bNodeExec *nodeexec;
00520     bNodeSocket *sock;
00521     int n;
00522     
00523     for(n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
00524         if(nodeexec->node->exec==0) {
00525             /* input sockets should be ready */
00526             for(sock= nodeexec->node->inputs.first; sock; sock= sock->next) {
00527                 if(sock->link && sock->link->fromnode)
00528                     if((sock->link->fromnode->exec & NODE_READY)==0)
00529                         break;
00530             }
00531             if(sock==NULL)
00532                 return nodeexec;
00533         }
00534     }
00535     return NULL;
00536 }
00537 
00538 /* check if texture nodes need exec or end */
00539 static  void ntree_composite_texnode(bNodeTree *ntree, int init)
00540 {
00541     bNode *node;
00542     
00543     for(node= ntree->nodes.first; node; node= node->next) {
00544         if(node->type==CMP_NODE_TEXTURE && node->id) {
00545             Tex *tex= (Tex *)node->id;
00546             if(tex->nodetree && tex->use_nodes) {
00547                 /* has internal flag to detect it only does it once */
00548                 if(init) {
00549                     if (!tex->nodetree->execdata)
00550                         tex->nodetree->execdata = ntreeTexBeginExecTree(tex->nodetree, 1); 
00551                 }
00552                 else
00553                     ntreeTexEndExecTree(tex->nodetree->execdata, 1);
00554                     tex->nodetree->execdata = NULL;
00555             }
00556         }
00557     }
00558 
00559 }
00560 
00561 /* optimized tree execute test for compositing */
00562 void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview)
00563 {
00564     bNodeExec *nodeexec;
00565     bNode *node;
00566     ListBase threads;
00567     ThreadData thdata;
00568     int totnode, curnode, rendering= 1, n;
00569     bNodeTreeExec *exec= ntree->execdata;
00570     
00571     if(ntree==NULL) return;
00572     
00573     if(do_preview)
00574         ntreeInitPreview(ntree, 0, 0);
00575     
00576     if (!ntree->execdata) {
00577         /* XXX this is the top-level tree, so we use the ntree->execdata pointer. */
00578         exec = ntreeCompositBeginExecTree(ntree, 1);
00579     }
00580     ntree_composite_texnode(ntree, 1);
00581     
00582     /* prevent unlucky accidents */
00583     if(G.background)
00584         rd->scemode &= ~R_COMP_CROP;
00585     
00586     /* setup callerdata for thread callback */
00587     thdata.rd= rd;
00588     thdata.stack= exec->stack;
00589     
00590     /* fixed seed, for example noise texture */
00591     BLI_srandom(rd->cfra);
00592 
00593     /* sets need_exec tags in nodes */
00594     curnode = totnode= setExecutableNodes(exec, &thdata);
00595 
00596     BLI_init_threads(&threads, exec_composite_node, rd->threads);
00597     
00598     while(rendering) {
00599         
00600         if(BLI_available_threads(&threads)) {
00601             nodeexec= getExecutableNode(exec);
00602             if(nodeexec) {
00603                 node = nodeexec->node;
00604                 if(ntree->progress && totnode)
00605                     ntree->progress(ntree->prh, (1.0f - curnode/(float)totnode));
00606                 if(ntree->stats_draw) {
00607                     char str[128];
00608                     BLI_snprintf(str, sizeof(str), "Compositing %d %s", curnode, node->name);
00609                     ntree->stats_draw(ntree->sdh, str);
00610                 }
00611                 curnode--;
00612                 
00613                 node->threaddata = &thdata;
00614                 node->exec= NODE_PROCESSING;
00615                 BLI_insert_thread(&threads, nodeexec);
00616             }
00617             else
00618                 PIL_sleep_ms(50);
00619         }
00620         else
00621             PIL_sleep_ms(50);
00622         
00623         rendering= 0;
00624         /* test for ESC */
00625         if(ntree->test_break && ntree->test_break(ntree->tbh)) {
00626             for(node= ntree->nodes.first; node; node= node->next)
00627                 node->exec |= NODE_READY;
00628         }
00629         
00630         /* check for ready ones, and if we need to continue */
00631         for(n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
00632             node = nodeexec->node;
00633             if(node->exec & NODE_READY) {
00634                 if((node->exec & NODE_FINISHED)==0) {
00635                     BLI_remove_thread(&threads, nodeexec); /* this waits for running thread to finish btw */
00636                     node->exec |= NODE_FINISHED;
00637                     
00638                     /* freeing unused buffers */
00639                     if(rd->scemode & R_COMP_FREE)
00640                         freeExecutableNode(exec);
00641                 }
00642             }
00643             else rendering= 1;
00644         }
00645     }
00646     
00647     BLI_end_threads(&threads);
00648     
00649     /* XXX top-level tree uses the ntree->execdata pointer */
00650     ntreeCompositEndExecTree(exec, 1);
00651 }
00652 
00653 /* *********************************************** */
00654 
00655 /* clumsy checking... should do dynamic outputs once */
00656 static void force_hidden_passes(bNode *node, int passflag)
00657 {
00658     bNodeSocket *sock;
00659     
00660     for(sock= node->outputs.first; sock; sock= sock->next)
00661         sock->flag &= ~SOCK_UNAVAIL;
00662     
00663     sock= BLI_findlink(&node->outputs, RRES_OUT_Z);
00664     if(!(passflag & SCE_PASS_Z)) sock->flag |= SOCK_UNAVAIL;
00665     sock= BLI_findlink(&node->outputs, RRES_OUT_NORMAL);
00666     if(!(passflag & SCE_PASS_NORMAL)) sock->flag |= SOCK_UNAVAIL;
00667     sock= BLI_findlink(&node->outputs, RRES_OUT_VEC);
00668     if(!(passflag & SCE_PASS_VECTOR)) sock->flag |= SOCK_UNAVAIL;
00669     sock= BLI_findlink(&node->outputs, RRES_OUT_UV);
00670     if(!(passflag & SCE_PASS_UV)) sock->flag |= SOCK_UNAVAIL;
00671     sock= BLI_findlink(&node->outputs, RRES_OUT_RGBA);
00672     if(!(passflag & SCE_PASS_RGBA)) sock->flag |= SOCK_UNAVAIL;
00673     sock= BLI_findlink(&node->outputs, RRES_OUT_DIFF);
00674     if(!(passflag & SCE_PASS_DIFFUSE)) sock->flag |= SOCK_UNAVAIL;
00675     sock= BLI_findlink(&node->outputs, RRES_OUT_SPEC);
00676     if(!(passflag & SCE_PASS_SPEC)) sock->flag |= SOCK_UNAVAIL;
00677     sock= BLI_findlink(&node->outputs, RRES_OUT_SHADOW);
00678     if(!(passflag & SCE_PASS_SHADOW)) sock->flag |= SOCK_UNAVAIL;
00679     sock= BLI_findlink(&node->outputs, RRES_OUT_AO);
00680     if(!(passflag & SCE_PASS_AO)) sock->flag |= SOCK_UNAVAIL;
00681     sock= BLI_findlink(&node->outputs, RRES_OUT_REFLECT);
00682     if(!(passflag & SCE_PASS_REFLECT)) sock->flag |= SOCK_UNAVAIL;
00683     sock= BLI_findlink(&node->outputs, RRES_OUT_REFRACT);
00684     if(!(passflag & SCE_PASS_REFRACT)) sock->flag |= SOCK_UNAVAIL;
00685     sock= BLI_findlink(&node->outputs, RRES_OUT_INDIRECT);
00686     if(!(passflag & SCE_PASS_INDIRECT)) sock->flag |= SOCK_UNAVAIL;
00687     sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXOB);
00688     if(!(passflag & SCE_PASS_INDEXOB)) sock->flag |= SOCK_UNAVAIL;
00689     sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXMA);
00690     if(!(passflag & SCE_PASS_INDEXMA)) sock->flag |= SOCK_UNAVAIL;
00691     sock= BLI_findlink(&node->outputs, RRES_OUT_MIST);
00692     if(!(passflag & SCE_PASS_MIST)) sock->flag |= SOCK_UNAVAIL;
00693     sock= BLI_findlink(&node->outputs, RRES_OUT_EMIT);
00694     if(!(passflag & SCE_PASS_EMIT)) sock->flag |= SOCK_UNAVAIL;
00695     sock= BLI_findlink(&node->outputs, RRES_OUT_ENV);
00696     if(!(passflag & SCE_PASS_ENVIRONMENT)) sock->flag |= SOCK_UNAVAIL;
00697     
00698 }
00699 
00700 /* based on rules, force sockets hidden always */
00701 void ntreeCompositForceHidden(bNodeTree *ntree, Scene *curscene)
00702 {
00703     bNode *node;
00704     
00705     if(ntree==NULL) return;
00706     
00707     for(node= ntree->nodes.first; node; node= node->next) {
00708         if( node->type==CMP_NODE_R_LAYERS) {
00709             Scene *sce= node->id?(Scene *)node->id:curscene;
00710             SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1);
00711             if(srl)
00712                 force_hidden_passes(node, srl->passflag);
00713         }
00714         else if( node->type==CMP_NODE_IMAGE) {
00715             Image *ima= (Image *)node->id;
00716             if(ima) {
00717                 if(ima->rr) {
00718                     ImageUser *iuser= node->storage;
00719                     RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
00720                     if(rl)
00721                         force_hidden_passes(node, rl->passflag);
00722                     else
00723                         force_hidden_passes(node, 0);
00724                 }
00725                 else if(ima->type!=IMA_TYPE_MULTILAYER) {   /* if ->rr not yet read we keep inputs */
00726                     force_hidden_passes(node, RRES_OUT_Z);
00727                 }
00728                 else
00729                     force_hidden_passes(node, 0);
00730             }
00731             else
00732                 force_hidden_passes(node, 0);
00733         }
00734     }
00735 
00736 }
00737 
00738 /* called from render pipeline, to tag render input and output */
00739 /* need to do all scenes, to prevent errors when you re-render 1 scene */
00740 void ntreeCompositTagRender(Scene *curscene)
00741 {
00742     Scene *sce;
00743     
00744     for(sce= G.main->scene.first; sce; sce= sce->id.next) {
00745         if(sce->nodetree) {
00746             bNode *node;
00747             
00748             for(node= sce->nodetree->nodes.first; node; node= node->next) {
00749                 if(node->id==(ID *)curscene || node->type==CMP_NODE_COMPOSITE)
00750                     nodeUpdate(sce->nodetree, node);
00751                 else if(node->type==CMP_NODE_TEXTURE) /* uses scene sizex/sizey */
00752                     nodeUpdate(sce->nodetree, node);
00753             }
00754         }
00755     }
00756 }
00757 
00758 static int node_animation_properties(bNodeTree *ntree, bNode *node)
00759 {
00760     bNodeSocket *sock;
00761     const ListBase *lb;
00762     Link *link;
00763     PointerRNA ptr;
00764     PropertyRNA *prop;
00765     
00766     /* check to see if any of the node's properties have fcurves */
00767     RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr);
00768     lb = RNA_struct_type_properties(ptr.type);
00769     
00770     for (link=lb->first; link; link=link->next) {
00771         int driven, len=1, index;
00772         prop = (PropertyRNA *)link;
00773         
00774         if (RNA_property_array_check(prop))
00775             len = RNA_property_array_length(&ptr, prop);
00776         
00777         for (index=0; index<len; index++) {
00778             if (rna_get_fcurve(&ptr, prop, index, NULL, &driven)) {
00779                 nodeUpdate(ntree, node);
00780                 return 1;
00781             }
00782         }
00783     }
00784     
00785     /* now check node sockets */
00786     for (sock = node->inputs.first; sock; sock=sock->next) {
00787         int driven, len=1, index;
00788         
00789         RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
00790         prop = RNA_struct_find_property(&ptr, "default_value");
00791         if (prop) {
00792             if (RNA_property_array_check(prop))
00793                 len = RNA_property_array_length(&ptr, prop);
00794             
00795             for (index=0; index<len; index++) {
00796                 if (rna_get_fcurve(&ptr, prop, index, NULL, &driven)) {
00797                     nodeUpdate(ntree, node);
00798                     return 1;
00799                 }
00800             }
00801         }
00802     }
00803 
00804     return 0;
00805 }
00806 
00807 /* tags nodes that have animation capabilities */
00808 int ntreeCompositTagAnimated(bNodeTree *ntree)
00809 {
00810     bNode *node;
00811     int tagged= 0;
00812     
00813     if(ntree==NULL) return 0;
00814     
00815     for(node= ntree->nodes.first; node; node= node->next) {
00816         
00817         tagged = node_animation_properties(ntree, node);
00818         
00819         /* otherwise always tag these node types */
00820         if(node->type==CMP_NODE_IMAGE) {
00821             Image *ima= (Image *)node->id;
00822             if(ima && ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
00823                 nodeUpdate(ntree, node);
00824                 tagged= 1;
00825             }
00826         }
00827         else if(node->type==CMP_NODE_TIME) {
00828             nodeUpdate(ntree, node);
00829             tagged= 1;
00830         }
00831         /* here was tag render layer, but this is called after a render, so re-composites fail */
00832         else if(node->type==NODE_GROUP) {
00833             if( ntreeCompositTagAnimated((bNodeTree *)node->id) ) {
00834                 nodeUpdate(ntree, node);
00835             }
00836         }
00837         else if(ELEM(node->type, CMP_NODE_MOVIECLIP, CMP_NODE_TRANSFORM)) {
00838             nodeUpdate(ntree, node);
00839             tagged= 1;
00840         }
00841     }
00842     
00843     return tagged;
00844 }
00845 
00846 
00847 /* called from image window preview */
00848 void ntreeCompositTagGenerators(bNodeTree *ntree)
00849 {
00850     bNode *node;
00851     
00852     if(ntree==NULL) return;
00853     
00854     for(node= ntree->nodes.first; node; node= node->next) {
00855         if( ELEM(node->type, CMP_NODE_R_LAYERS, CMP_NODE_IMAGE))
00856             nodeUpdate(ntree, node);
00857     }
00858 }
00859 
00860 /* XXX after render animation system gets a refresh, this call allows composite to end clean */
00861 void ntreeCompositClearTags(bNodeTree *ntree)
00862 {
00863     bNode *node;
00864     
00865     if(ntree==NULL) return;
00866     
00867     for(node= ntree->nodes.first; node; node= node->next) {
00868         node->need_exec= 0;
00869         if(node->type==NODE_GROUP)
00870             ntreeCompositClearTags((bNodeTree *)node->id);
00871     }
00872 }