Blender V2.61 - r43446
|
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 }