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): 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 }