2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2007 Blender Foundation.
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): Nathan Letwory.
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/nodes/intern/node_exec.c
33 #include "DNA_node_types.h"
35 #include "BLI_listbase.h"
37 #include "BLI_utildefines.h"
41 #include "MEM_guardedalloc.h"
43 #include "node_exec.h"
46 /* for a given socket, find the actual stack entry */
47 bNodeStack *node_get_socket_stack(bNodeStack *stack, bNodeSocket *sock)
49 return stack + sock->stack_index;
52 void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out)
56 /* build pointer stack */
58 for(sock= node->inputs.first; sock; sock= sock->next) {
59 *(in++) = node_get_socket_stack(stack, sock);
64 for(sock= node->outputs.first; sock; sock= sock->next) {
65 *(out++) = node_get_socket_stack(stack, sock);
70 void node_init_input_index(bNodeSocket *sock, int *index)
72 if (sock->link && sock->link->fromsock) {
73 sock->stack_index = sock->link->fromsock->stack_index;
76 sock->stack_index = (*index)++;
80 void node_init_output_index(bNodeSocket *sock, int *index)
82 sock->stack_index = (*index)++;
85 /* basic preparation of socket stacks */
86 static struct bNodeStack *setup_stack(bNodeStack *stack, bNodeSocket *sock)
88 bNodeStack *ns = node_get_socket_stack(stack, sock);
89 float null_value[4]= {0.0f, 0.0f, 0.0f, 0.0f};
91 /* don't mess with remote socket stacks, these are initialized by other nodes! */
95 ns->sockettype = sock->type;
97 if (sock->default_value) {
100 ns->vec[0] = ((bNodeSocketValueFloat*)sock->default_value)->value;
103 copy_v3_v3(ns->vec, ((bNodeSocketValueVector*)sock->default_value)->value);
106 copy_v4_v4(ns->vec, ((bNodeSocketValueRGBA*)sock->default_value)->value);
111 switch (sock->type) {
116 copy_v3_v3(ns->vec, null_value);
119 copy_v4_v4(ns->vec, null_value);
127 bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree)
132 bNodeSocket *sock, *gsock;
138 if((ntree->init & NTREE_TYPE_INIT)==0)
139 ntreeInitTypes(ntree);
141 /* get a dependency-sorted list of nodes */
142 ntreeGetDependencyList(ntree, &nodelist, &totnodes);
144 /* XXX could let callbacks do this for specialized data */
145 exec = MEM_callocN(sizeof(bNodeTreeExec), "node tree execution data");
146 /* backpointer to node tree */
147 exec->nodetree = ntree;
149 /* group inputs essentially work as outputs */
150 for(gsock=ntree->inputs.first; gsock; gsock = gsock->next)
151 node_init_output_index(gsock, &index);
152 /* set stack indexes */
153 for(n=0; n < totnodes; ++n) {
156 node->stack_index = index;
158 /* init node socket stack indexes */
159 for (sock=node->inputs.first; sock; sock=sock->next)
160 node_init_input_index(sock, &index);
161 for (sock=node->outputs.first; sock; sock=sock->next)
162 node_init_output_index(sock, &index);
164 /* group outputs essentially work as inputs */
165 for(gsock=ntree->outputs.first; gsock; gsock = gsock->next)
166 node_init_input_index(gsock, &index);
168 /* allocated exec data pointers for nodes */
169 exec->totnodes = totnodes;
170 exec->nodeexec = MEM_callocN(exec->totnodes * sizeof(bNodeExec), "node execution data");
171 /* allocate data pointer for node stack */
172 exec->stacksize = index;
173 exec->stack = MEM_callocN(exec->stacksize * sizeof(bNodeStack), "bNodeStack");
175 /* all non-const results are considered inputs */
176 for (n=0; n < exec->stacksize; ++n)
177 exec->stack[n].hasinput = 1;
179 /* prepare group tree inputs */
180 for (sock=ntree->inputs.first; sock; sock=sock->next) {
181 /* ns = */ setup_stack(exec->stack, sock);
183 /* prepare all internal nodes for execution */
184 for(n=0, nodeexec= exec->nodeexec; n < totnodes; ++n, ++nodeexec) {
185 node = nodeexec->node = nodelist[n];
188 for (sock=node->inputs.first; sock; sock=sock->next) {
189 /* disable the node if an input link is invalid */
190 if(sock->link && !(sock->link->flag & NODE_LINK_VALID))
193 ns = setup_stack(exec->stack, sock);
197 /* tag all outputs */
198 for (sock=node->outputs.first; sock; sock=sock->next) {
199 /* ns = */ setup_stack(exec->stack, sock);
202 if(node->typeinfo->initexecfunc)
203 nodeexec->data = node->typeinfo->initexecfunc(node);
205 /* prepare group tree outputs */
206 for (sock=ntree->outputs.first; sock; sock=sock->next) {
207 ns = setup_stack(exec->stack, sock);
217 void ntree_exec_end(bNodeTreeExec *exec)
223 MEM_freeN(exec->stack);
225 for(n=0, nodeexec= exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
226 if (nodeexec->node->typeinfo->freeexecfunc)
227 nodeexec->node->typeinfo->freeexecfunc(nodeexec->node, nodeexec->data);
231 MEM_freeN(exec->nodeexec);
236 /**** Compositor/Material/Texture trees ****/
238 bNodeThreadStack *ntreeGetThreadStack(bNodeTreeExec *exec, int thread)
240 ListBase *lb= &exec->threadstack[thread];
241 bNodeThreadStack *nts;
243 for(nts=lb->first; nts; nts=nts->next) {
251 nts= MEM_callocN(sizeof(bNodeThreadStack), "bNodeThreadStack");
252 nts->stack= MEM_dupallocN(exec->stack);
254 BLI_addtail(lb, nts);
260 void ntreeReleaseThreadStack(bNodeThreadStack *nts)
265 void ntreeExecNodes(bNodeTreeExec *exec, void *callerdata, int thread)
267 bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */
268 bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */
273 /* nodes are presorted, so exec is in order of list */
275 for(n=0, nodeexec= exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
276 node = nodeexec->node;
277 if(node->need_exec) {
278 node_get_stack(node, exec->stack, nsin, nsout);
279 /* Handle muted nodes...
280 * If the mute func is not set, assume the node should never be muted,
281 * and hence execute it!
283 if(node->typeinfo->execfunc)
284 node->typeinfo->execfunc(callerdata, node, nsin, nsout);
285 else if (node->typeinfo->newexecfunc)
286 node->typeinfo->newexecfunc(callerdata, thread, node, nodeexec->data, nsin, nsout);
291 void ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *callerdata, int thread)
293 bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */
294 bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */
299 /* nodes are presorted, so exec is in order of list */
301 for(n=0, nodeexec= exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
302 node = nodeexec->node;
303 if(node->need_exec) {
304 node_get_stack(node, nts->stack, nsin, nsout);
305 /* Handle muted nodes...
306 * If the mute func is not set, assume the node should never be muted,
307 * and hence execute it!
309 if(node->typeinfo->execfunc)
310 node->typeinfo->execfunc(callerdata, node, nsin, nsout);
311 else if (node->typeinfo->newexecfunc)
312 node->typeinfo->newexecfunc(callerdata, thread, node, nodeexec->data, nsin, nsout);