- add template for defining custom driver functions.
[blender.git] / source / blender / nodes / intern / node_exec.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2007 Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): Nathan Letwory.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /** \file blender/nodes/intern/node_exec.c
31  *  \ingroup nodes
32  */
33
34
35 #include "DNA_node_types.h"
36
37 #include "BLI_listbase.h"
38 #include "BLI_math.h"
39 #include "BLI_utildefines.h"
40
41 #include "BKE_node.h"
42
43 #include "MEM_guardedalloc.h"
44
45 #include "node_exec.h"
46
47
48 /* for a given socket, find the actual stack entry */
49 bNodeStack *node_get_socket_stack(bNodeStack *stack, bNodeSocket *sock)
50 {
51         return stack + sock->stack_index;
52 }
53
54 void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out)
55 {
56         bNodeSocket *sock;
57         
58         /* build pointer stack */
59         if (in) {
60                 for(sock= node->inputs.first; sock; sock= sock->next) {
61                         *(in++) = node_get_socket_stack(stack, sock);
62                 }
63         }
64         
65         if (out) {
66                 for(sock= node->outputs.first; sock; sock= sock->next) {
67                         *(out++) = node_get_socket_stack(stack, sock);
68                 }
69         }
70 }
71
72 void node_init_input_index(bNodeSocket *sock, int *index)
73 {
74         if (sock->link && sock->link->fromsock) {
75                 sock->stack_index = sock->link->fromsock->stack_index;
76         }
77         else {
78                 sock->stack_index = (*index)++;
79         }
80 }
81
82 void node_init_output_index(bNodeSocket *sock, int *index)
83 {
84         sock->stack_index = (*index)++;
85 }
86
87 /* basic preparation of socket stacks */
88 static struct bNodeStack *setup_stack(bNodeStack *stack, bNodeSocket *sock)
89 {
90         bNodeStack *ns = node_get_socket_stack(stack, sock);
91         float null_value[4]= {0.0f, 0.0f, 0.0f, 0.0f};
92         
93         /* don't mess with remote socket stacks, these are initialized by other nodes! */
94         if (sock->link)
95                 return ns;
96         
97         ns->sockettype = sock->type;
98         
99         if (sock->default_value) {
100                 switch (sock->type) {
101                 case SOCK_FLOAT:
102                         ns->vec[0] = ((bNodeSocketValueFloat*)sock->default_value)->value;
103                         break;
104                 case SOCK_VECTOR:
105                         copy_v3_v3(ns->vec, ((bNodeSocketValueVector*)sock->default_value)->value);
106                         break;
107                 case SOCK_RGBA:
108                         copy_v4_v4(ns->vec, ((bNodeSocketValueRGBA*)sock->default_value)->value);
109                         break;
110                 }
111         }
112         else {
113                 switch (sock->type) {
114                 case SOCK_FLOAT:
115                         ns->vec[0] = 0.0f;
116                         break;
117                 case SOCK_VECTOR:
118                         copy_v3_v3(ns->vec, null_value);
119                         break;
120                 case SOCK_RGBA:
121                         copy_v4_v4(ns->vec, null_value);
122                         break;
123                 }
124         }
125         
126         return ns;
127 }
128
129 bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree)
130 {
131         bNodeTreeExec *exec;
132         bNode *node;
133         bNodeExec *nodeexec;
134         bNodeSocket *sock, *gsock;
135         bNodeStack *ns;
136         int index= 0;
137         bNode **nodelist;
138         int totnodes, n;
139         
140         if((ntree->init & NTREE_TYPE_INIT)==0)
141                 ntreeInitTypes(ntree);
142         
143         /* get a dependency-sorted list of nodes */
144         ntreeGetDependencyList(ntree, &nodelist, &totnodes);
145         
146         /* XXX could let callbacks do this for specialized data */
147         exec = MEM_callocN(sizeof(bNodeTreeExec), "node tree execution data");
148         /* backpointer to node tree */
149         exec->nodetree = ntree;
150         
151         /* group inputs essentially work as outputs */
152         for(gsock=ntree->inputs.first; gsock; gsock = gsock->next)
153                 node_init_output_index(gsock, &index);
154         /* set stack indexes */
155         for(n=0; n < totnodes; ++n) {
156                 node = nodelist[n];
157                 
158                 node->stack_index = index;
159                 
160                 /* init node socket stack indexes */
161                 for (sock=node->inputs.first; sock; sock=sock->next)
162                         node_init_input_index(sock, &index);
163                 for (sock=node->outputs.first; sock; sock=sock->next)
164                         node_init_output_index(sock, &index);
165         }
166         /* group outputs essentially work as inputs */
167         for(gsock=ntree->outputs.first; gsock; gsock = gsock->next)
168                 node_init_input_index(gsock, &index);
169         
170         /* allocated exec data pointers for nodes */
171         exec->totnodes = totnodes;
172         exec->nodeexec = MEM_callocN(exec->totnodes * sizeof(bNodeExec), "node execution data");
173         /* allocate data pointer for node stack */
174         exec->stacksize = index;
175         exec->stack = MEM_callocN(exec->stacksize * sizeof(bNodeStack), "bNodeStack");
176         
177         /* all non-const results are considered inputs */
178         for (n=0; n < exec->stacksize; ++n)
179                 exec->stack[n].hasinput = 1;
180         
181         /* prepare group tree inputs */
182         for (sock=ntree->inputs.first; sock; sock=sock->next) {
183                 /* ns = */ setup_stack(exec->stack, sock);
184         }
185         /* prepare all internal nodes for execution */
186         for(n=0, nodeexec= exec->nodeexec; n < totnodes; ++n, ++nodeexec) {
187                 node = nodeexec->node = nodelist[n];
188                 
189                 /* tag inputs */
190                 for (sock=node->inputs.first; sock; sock=sock->next) {
191                         /* disable the node if an input link is invalid */
192                         if(sock->link && !(sock->link->flag & NODE_LINK_VALID))
193                                 node->need_exec= 0;
194                         
195                         ns = setup_stack(exec->stack, sock);
196                         ns->hasoutput = 1;
197                 }
198                 
199                 /* tag all outputs */
200                 for (sock=node->outputs.first; sock; sock=sock->next) {
201                         /* ns = */ setup_stack(exec->stack, sock);
202                 }
203                 
204                 if(node->typeinfo->initexecfunc)
205                         nodeexec->data = node->typeinfo->initexecfunc(node);
206         }
207         /* prepare group tree outputs */
208         for (sock=ntree->outputs.first; sock; sock=sock->next) {
209                 ns = setup_stack(exec->stack, sock);
210                 ns->hasoutput = 1;
211         }
212         
213         if (nodelist)
214                 MEM_freeN(nodelist);
215         
216         return exec;
217 }
218
219 void ntree_exec_end(bNodeTreeExec *exec)
220 {
221         bNodeExec *nodeexec;
222         int n;
223         
224         if (exec->stack)
225                 MEM_freeN(exec->stack);
226         
227         for(n=0, nodeexec= exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
228                 if (nodeexec->node->typeinfo->freeexecfunc)
229                         nodeexec->node->typeinfo->freeexecfunc(nodeexec->node, nodeexec->data);
230         }
231         
232         if (exec->nodeexec)
233                 MEM_freeN(exec->nodeexec);
234         
235         MEM_freeN(exec);
236 }
237
238 /**** Compositor/Material/Texture trees ****/
239
240 bNodeThreadStack *ntreeGetThreadStack(bNodeTreeExec *exec, int thread)
241 {
242         ListBase *lb= &exec->threadstack[thread];
243         bNodeThreadStack *nts;
244         
245         for(nts=lb->first; nts; nts=nts->next) {
246                 if(!nts->used) {
247                         nts->used= 1;
248                         break;
249                 }
250         }
251         
252         if (!nts) {
253                 nts= MEM_callocN(sizeof(bNodeThreadStack), "bNodeThreadStack");
254                 nts->stack= MEM_dupallocN(exec->stack);
255                 nts->used= 1;
256                 BLI_addtail(lb, nts);
257         }
258
259         return nts;
260 }
261
262 void ntreeReleaseThreadStack(bNodeThreadStack *nts)
263 {
264         nts->used = 0;
265 }
266
267 void ntreeExecNodes(bNodeTreeExec *exec, void *callerdata, int thread)
268 {
269         bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
270         bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
271         bNodeExec *nodeexec;
272         bNode *node;
273         int n;
274         
275         /* nodes are presorted, so exec is in order of list */
276         
277         for(n=0, nodeexec= exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
278                 node = nodeexec->node;
279                 if(node->need_exec) {
280                         node_get_stack(node, exec->stack, nsin, nsout);
281                         if(node->typeinfo->execfunc)
282                                 node->typeinfo->execfunc(callerdata, node, nsin, nsout);
283                         else if (node->typeinfo->newexecfunc)
284                                 node->typeinfo->newexecfunc(callerdata, thread, node, nodeexec->data, nsin, nsout);
285                 }
286         }
287 }
288
289 void ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *callerdata, int thread)
290 {
291         bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
292         bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
293         bNodeExec *nodeexec;
294         bNode *node;
295         int n;
296         
297         /* nodes are presorted, so exec is in order of list */
298         
299         for(n=0, nodeexec= exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
300                 node = nodeexec->node;
301                 if(node->need_exec) {
302                         node_get_stack(node, nts->stack, nsin, nsout);
303                         if(node->typeinfo->execfunc)
304                                 node->typeinfo->execfunc(callerdata, node, nsin, nsout);
305                         else if (node->typeinfo->newexecfunc)
306                                 node->typeinfo->newexecfunc(callerdata, thread, node, nodeexec->data, nsin, nsout);
307                 }
308         }
309 }