Blender V2.61 - r43446

node_exec.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): Nathan Letwory.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include "DNA_node_types.h"
00034 
00035 #include "BLI_listbase.h"
00036 #include "BLI_math.h"
00037 #include "BLI_utildefines.h"
00038 
00039 #include "BKE_node.h"
00040 
00041 #include "MEM_guardedalloc.h"
00042 
00043 #include "node_exec.h"
00044 
00045 
00046 /* for a given socket, find the actual stack entry */
00047 bNodeStack *node_get_socket_stack(bNodeStack *stack, bNodeSocket *sock)
00048 {
00049     return stack + sock->stack_index;
00050 }
00051 
00052 void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out)
00053 {
00054     bNodeSocket *sock;
00055     
00056     /* build pointer stack */
00057     if (in) {
00058         for(sock= node->inputs.first; sock; sock= sock->next) {
00059             *(in++) = node_get_socket_stack(stack, sock);
00060         }
00061     }
00062     
00063     if (out) {
00064         for(sock= node->outputs.first; sock; sock= sock->next) {
00065             *(out++) = node_get_socket_stack(stack, sock);
00066         }
00067     }
00068 }
00069 
00070 void node_init_input_index(bNodeSocket *sock, int *index)
00071 {
00072     if (sock->link && sock->link->fromsock) {
00073         sock->stack_index = sock->link->fromsock->stack_index;
00074     }
00075     else {
00076         sock->stack_index = (*index)++;
00077     }
00078 }
00079 
00080 void node_init_output_index(bNodeSocket *sock, int *index)
00081 {
00082     sock->stack_index = (*index)++;
00083 }
00084 
00085 /* basic preparation of socket stacks */
00086 static struct bNodeStack *setup_stack(bNodeStack *stack, bNodeSocket *sock)
00087 {
00088     bNodeStack *ns = node_get_socket_stack(stack, sock);
00089     float null_value[4]= {0.0f, 0.0f, 0.0f, 0.0f};
00090     
00091     /* don't mess with remote socket stacks, these are initialized by other nodes! */
00092     if (sock->link)
00093         return ns;
00094     
00095     ns->sockettype = sock->type;
00096     
00097     if (sock->default_value) {
00098         switch (sock->type) {
00099         case SOCK_FLOAT:
00100             ns->vec[0] = ((bNodeSocketValueFloat*)sock->default_value)->value;
00101             break;
00102         case SOCK_VECTOR:
00103             copy_v3_v3(ns->vec, ((bNodeSocketValueVector*)sock->default_value)->value);
00104             break;
00105         case SOCK_RGBA:
00106             copy_v4_v4(ns->vec, ((bNodeSocketValueRGBA*)sock->default_value)->value);
00107             break;
00108         }
00109     }
00110     else {
00111         switch (sock->type) {
00112         case SOCK_FLOAT:
00113             ns->vec[0] = 0.0f;
00114             break;
00115         case SOCK_VECTOR:
00116             copy_v3_v3(ns->vec, null_value);
00117             break;
00118         case SOCK_RGBA:
00119             copy_v4_v4(ns->vec, null_value);
00120             break;
00121         }
00122     }
00123     
00124     return ns;
00125 }
00126 
00127 bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree)
00128 {
00129     bNodeTreeExec *exec;
00130     bNode *node;
00131     bNodeExec *nodeexec;
00132     bNodeSocket *sock, *gsock;
00133     bNodeStack *ns;
00134     int index= 0;
00135     bNode **nodelist;
00136     int totnodes, n;
00137     
00138     if((ntree->init & NTREE_TYPE_INIT)==0)
00139         ntreeInitTypes(ntree);
00140     
00141     /* get a dependency-sorted list of nodes */
00142     ntreeGetDependencyList(ntree, &nodelist, &totnodes);
00143     
00144     /* XXX could let callbacks do this for specialized data */
00145     exec = MEM_callocN(sizeof(bNodeTreeExec), "node tree execution data");
00146     /* backpointer to node tree */
00147     exec->nodetree = ntree;
00148     
00149     /* group inputs essentially work as outputs */
00150     for(gsock=ntree->inputs.first; gsock; gsock = gsock->next)
00151         node_init_output_index(gsock, &index);
00152     /* set stack indexes */
00153     for(n=0; n < totnodes; ++n) {
00154         node = nodelist[n];
00155         
00156         node->stack_index = index;
00157         
00158         /* init node socket stack indexes */
00159         for (sock=node->inputs.first; sock; sock=sock->next)
00160             node_init_input_index(sock, &index);
00161         for (sock=node->outputs.first; sock; sock=sock->next)
00162             node_init_output_index(sock, &index);
00163     }
00164     /* group outputs essentially work as inputs */
00165     for(gsock=ntree->outputs.first; gsock; gsock = gsock->next)
00166         node_init_input_index(gsock, &index);
00167     
00168     /* allocated exec data pointers for nodes */
00169     exec->totnodes = totnodes;
00170     exec->nodeexec = MEM_callocN(exec->totnodes * sizeof(bNodeExec), "node execution data");
00171     /* allocate data pointer for node stack */
00172     exec->stacksize = index;
00173     exec->stack = MEM_callocN(exec->stacksize * sizeof(bNodeStack), "bNodeStack");
00174     
00175     /* all non-const results are considered inputs */
00176     for (n=0; n < exec->stacksize; ++n)
00177         exec->stack[n].hasinput = 1;
00178     
00179     /* prepare group tree inputs */
00180     for (sock=ntree->inputs.first; sock; sock=sock->next) {
00181         /* ns = */ setup_stack(exec->stack, sock);
00182     }
00183     /* prepare all internal nodes for execution */
00184     for(n=0, nodeexec= exec->nodeexec; n < totnodes; ++n, ++nodeexec) {
00185         node = nodeexec->node = nodelist[n];
00186         
00187         /* tag inputs */
00188         for (sock=node->inputs.first; sock; sock=sock->next) {
00189             /* disable the node if an input link is invalid */
00190             if(sock->link && !(sock->link->flag & NODE_LINK_VALID))
00191                 node->need_exec= 0;
00192             
00193             ns = setup_stack(exec->stack, sock);
00194             ns->hasoutput = 1;
00195         }
00196         
00197         /* tag all outputs */
00198         for (sock=node->outputs.first; sock; sock=sock->next) {
00199             /* ns = */ setup_stack(exec->stack, sock);
00200         }
00201         
00202         if(node->typeinfo->initexecfunc)
00203             nodeexec->data = node->typeinfo->initexecfunc(node);
00204     }
00205     /* prepare group tree outputs */
00206     for (sock=ntree->outputs.first; sock; sock=sock->next) {
00207         ns = setup_stack(exec->stack, sock);
00208         ns->hasoutput = 1;
00209     }
00210     
00211     if (nodelist)
00212         MEM_freeN(nodelist);
00213     
00214     return exec;
00215 }
00216 
00217 void ntree_exec_end(bNodeTreeExec *exec)
00218 {
00219     bNodeExec *nodeexec;
00220     int n;
00221     
00222     if (exec->stack)
00223         MEM_freeN(exec->stack);
00224     
00225     for(n=0, nodeexec= exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
00226         if (nodeexec->node->typeinfo->freeexecfunc)
00227             nodeexec->node->typeinfo->freeexecfunc(nodeexec->node, nodeexec->data);
00228     }
00229     
00230     if (exec->nodeexec)
00231         MEM_freeN(exec->nodeexec);
00232     
00233     MEM_freeN(exec);
00234 }
00235 
00236 /**** Compositor/Material/Texture trees ****/
00237 
00238 bNodeThreadStack *ntreeGetThreadStack(bNodeTreeExec *exec, int thread)
00239 {
00240     ListBase *lb= &exec->threadstack[thread];
00241     bNodeThreadStack *nts;
00242     
00243     for(nts=lb->first; nts; nts=nts->next) {
00244         if(!nts->used) {
00245             nts->used= 1;
00246             break;
00247         }
00248     }
00249     
00250     if (!nts) {
00251         nts= MEM_callocN(sizeof(bNodeThreadStack), "bNodeThreadStack");
00252         nts->stack= MEM_dupallocN(exec->stack);
00253         nts->used= 1;
00254         BLI_addtail(lb, nts);
00255     }
00256 
00257     return nts;
00258 }
00259 
00260 void ntreeReleaseThreadStack(bNodeThreadStack *nts)
00261 {
00262     nts->used = 0;
00263 }
00264 
00265 void ntreeExecNodes(bNodeTreeExec *exec, void *callerdata, int thread)
00266 {
00267     bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
00268     bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
00269     bNodeExec *nodeexec;
00270     bNode *node;
00271     int n;
00272     
00273     /* nodes are presorted, so exec is in order of list */
00274     
00275     for(n=0, nodeexec= exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
00276         node = nodeexec->node;
00277         if(node->need_exec) {
00278             node_get_stack(node, exec->stack, nsin, nsout);
00279             /* Handle muted nodes...
00280              * If the mute func is not set, assume the node should never be muted,
00281              * and hence execute it!
00282              */
00283             if((node->flag & NODE_MUTED) && node->typeinfo->mutefunc)
00284                 node->typeinfo->mutefunc(callerdata, thread, node, nodeexec->data, nsin, nsout);
00285             else if(node->typeinfo->execfunc)
00286                 node->typeinfo->execfunc(callerdata, node, nsin, nsout);
00287             else if (node->typeinfo->newexecfunc)
00288                 node->typeinfo->newexecfunc(callerdata, thread, node, nodeexec->data, nsin, nsout);
00289         }
00290     }
00291 }
00292 
00293 void ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *callerdata, int thread)
00294 {
00295     bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
00296     bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
00297     bNodeExec *nodeexec;
00298     bNode *node;
00299     int n;
00300     
00301     /* nodes are presorted, so exec is in order of list */
00302     
00303     for(n=0, nodeexec= exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
00304         node = nodeexec->node;
00305         if(node->need_exec) {
00306             node_get_stack(node, nts->stack, nsin, nsout);
00307             /* Handle muted nodes...
00308              * If the mute func is not set, assume the node should never be muted,
00309              * and hence execute it!
00310              */
00311             if((node->flag & NODE_MUTED) && node->typeinfo->mutefunc)
00312                 node->typeinfo->mutefunc(callerdata, thread, node, nodeexec->data, nsin, nsout);
00313             else if(node->typeinfo->execfunc)
00314                 node->typeinfo->execfunc(callerdata, node, nsin, nsout);
00315             else if (node->typeinfo->newexecfunc)
00316                 node->typeinfo->newexecfunc(callerdata, thread, node, nodeexec->data, nsin, nsout);
00317         }
00318     }
00319 }