static void *exec_composite_node(void *nodeexec_v) { bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */ bNodeExec *nodeexec= nodeexec_v; bNode *node= nodeexec->node; ThreadData *thd= (ThreadData *)node->threaddata; node_get_stack(node, thd->stack, nsin, nsout); if((node->flag & NODE_MUTED) && (!node_only_value(node))) { /* viewers we execute, for feedback to user */ if(ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) node->typeinfo->execfunc(thd->rd, node, nsin, nsout); else node_compo_pass_on(node, nsin, nsout); } else if(node->typeinfo->execfunc) node->typeinfo->execfunc(thd->rd, node, nsin, nsout); else if (node->typeinfo->newexecfunc) node->typeinfo->newexecfunc(thd->rd, 0, node, nodeexec->data, nsin, nsout); node->exec |= NODE_READY; return NULL; }
/* or nodes with only value inputs */ static int node_only_value(bNode *node) { bNodeSocket *sock; if (ELEM3(node->type, CMP_NODE_TIME, CMP_NODE_VALUE, CMP_NODE_RGB)) return 1; /* doing this for all node types goes wrong. memory free errors */ if (node->inputs.first && node->type==CMP_NODE_MAP_VALUE) { int retval= 1; for (sock= node->inputs.first; sock; sock= sock->next) { if (sock->link) retval &= node_only_value(sock->link->fromnode); } return retval; } return 0; }
/* return total of executable nodes, for timecursor */ static int setExecutableNodes(bNodeTreeExec *exec, ThreadData *thd) { bNodeTree *ntree = exec->nodetree; bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */ bNodeExec *nodeexec; bNode *node; bNodeSocket *sock; int n, totnode= 0, group_edit= 0; /* if we are in group edit, viewer nodes get skipped when group has viewer */ for (node= ntree->nodes.first; node; node= node->next) if (node->type==NODE_GROUP && (node->flag & NODE_GROUP_EDIT)) if (ntreeHasType((bNodeTree *)node->id, CMP_NODE_VIEWER)) group_edit= 1; /* NB: using the exec data list here to have valid dependency sort */ for (n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) { int a; node = nodeexec->node; node_get_stack(node, exec->stack, nsin, nsout); /* test the outputs */ /* skip value-only nodes (should be in type!) */ if (!node_only_value(node)) { for (a=0, sock= node->outputs.first; sock; sock= sock->next, a++) { if (nsout[a]->data==NULL && nsout[a]->hasoutput) { node->need_exec= 1; break; } } } /* test the inputs */ for (a=0, sock= node->inputs.first; sock; sock= sock->next, a++) { /* skip viewer nodes in bg render or group edit */ if ( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) && (G.background || group_edit)) node->need_exec= 0; /* is sock in use? */ else if (sock->link) { bNodeLink *link= sock->link; /* this is the test for a cyclic case */ if (link->fromnode==NULL || link->tonode==NULL); else if (link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF) { if (link->fromnode->need_exec) { node->need_exec= 1; break; } } else { node->need_exec= 0; printf("Node %s skipped, cyclic dependency\n", node->name); } } } if (node->need_exec) { /* free output buffers */ for (a=0, sock= node->outputs.first; sock; sock= sock->next, a++) { if (nsout[a]->data) { free_compbuf(nsout[a]->data); nsout[a]->data= NULL; } } totnode++; /* printf("node needs exec %s\n", node->name); */ /* tag for getExecutableNode() */ node->exec= 0; } else { /* tag for getExecutableNode() */ node->exec= NODE_READY|NODE_FINISHED|NODE_SKIPPED; } } /* last step: set the stack values for only-value nodes */ /* just does all now, compared to a full buffer exec this is nothing */ if (totnode) { for (n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) { node = nodeexec->node; if (node->need_exec==0 && node_only_value(node)) { if (node->typeinfo->execfunc) { node_get_stack(node, exec->stack, nsin, nsout); node->typeinfo->execfunc(thd->rd, node, nsin, nsout); } } } } return totnode; }