UI: Refactor timecode functions into BLI_timecode
[blender.git] / source / blender / nodes / intern / node_exec.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
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. 
8  *
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.
13  *
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.
17  *
18  * The Original Code is Copyright (C) 2007 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Nathan Letwory.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/nodes/intern/node_exec.c
29  *  \ingroup nodes
30  */
31
32
33 #include "DNA_node_types.h"
34
35 #include "BLI_listbase.h"
36 #include "BLI_math.h"
37 #include "BLI_utildefines.h"
38
39 #include "BKE_global.h"
40 #include "BKE_node.h"
41
42 #include "MEM_guardedalloc.h"
43
44 #include "node_exec.h"
45 #include "node_util.h"
46
47
48 /* supported socket types in old nodes */
49 int node_exec_socket_use_stack(bNodeSocket *sock)
50 {
51         return ELEM4(sock->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA, SOCK_SHADER);
52 }
53
54 /* for a given socket, find the actual stack entry */
55 bNodeStack *node_get_socket_stack(bNodeStack *stack, bNodeSocket *sock)
56 {
57         if (stack && sock && sock->stack_index >= 0)
58                 return stack + sock->stack_index;
59         return NULL;
60 }
61
62 void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out)
63 {
64         bNodeSocket *sock;
65         
66         /* build pointer stack */
67         if (in) {
68                 for (sock = node->inputs.first; sock; sock = sock->next) {
69                         *(in++) = node_get_socket_stack(stack, sock);
70                 }
71         }
72         
73         if (out) {
74                 for (sock = node->outputs.first; sock; sock = sock->next) {
75                         *(out++) = node_get_socket_stack(stack, sock);
76                 }
77         }
78 }
79
80 static void node_init_input_index(bNodeSocket *sock, int *index)
81 {
82         if (sock->link && sock->link->fromsock) {
83                 sock->stack_index = sock->link->fromsock->stack_index;
84         }
85         else {
86                 if (node_exec_socket_use_stack(sock))
87                         sock->stack_index = (*index)++;
88                 else
89                         sock->stack_index = -1;
90         }
91 }
92
93 static void node_init_output_index(bNodeSocket *sock, int *index, ListBase *internal_links)
94 {
95         if (internal_links) {
96                 bNodeLink *link;
97                 /* copy the stack index from internally connected input to skip the node */
98                 for (link = internal_links->first; link; link = link->next) {
99                         if (link->tosock == sock) {
100                                 sock->stack_index = link->fromsock->stack_index;
101                                 /* set the link pointer to indicate that this socket
102                                  * should not overwrite the stack value!
103                                  */
104                                 sock->link = link;
105                                 break;
106                         }
107                 }
108                 /* if not internally connected, assign a new stack index anyway to avoid bad stack access */
109                 if (!link) {
110                         if (node_exec_socket_use_stack(sock))
111                                 sock->stack_index = (*index)++;
112                         else
113                                 sock->stack_index = -1;
114                 }
115         }
116         else {
117                 if (node_exec_socket_use_stack(sock))
118                         sock->stack_index = (*index)++;
119                 else
120                         sock->stack_index = -1;
121         }
122 }
123
124 /* basic preparation of socket stacks */
125 static struct bNodeStack *setup_stack(bNodeStack *stack, bNodeTree *ntree, bNode *node, bNodeSocket *sock)
126 {
127         bNodeStack *ns = node_get_socket_stack(stack, sock);
128         if (!ns)
129                 return NULL;
130         
131         /* don't mess with remote socket stacks, these are initialized by other nodes! */
132         if (sock->link)
133                 return ns;
134         
135         ns->sockettype = sock->type;
136         
137         switch (sock->type) {
138                 case SOCK_FLOAT:
139                         ns->vec[0] = node_socket_get_float(ntree, node, sock);
140                         break;
141                 case SOCK_VECTOR:
142                         node_socket_get_vector(ntree, node, sock, ns->vec);
143                         break;
144                 case SOCK_RGBA:
145                         node_socket_get_color(ntree, node, sock, ns->vec);
146                         break;
147         }
148         
149         return ns;
150 }
151
152 bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
153 {
154         bNodeTreeExec *exec;
155         bNode *node;
156         bNodeExec *nodeexec;
157         bNodeInstanceKey nodekey;
158         bNodeSocket *sock;
159         bNodeStack *ns;
160         int index;
161         bNode **nodelist;
162         int totnodes, n;
163         
164         /* ensure all sock->link pointers and node levels are correct */
165         ntreeUpdateTree(G.main, ntree);
166         
167         /* get a dependency-sorted list of nodes */
168         ntreeGetDependencyList(ntree, &nodelist, &totnodes);
169         
170         /* XXX could let callbacks do this for specialized data */
171         exec = MEM_callocN(sizeof(bNodeTreeExec), "node tree execution data");
172         /* backpointer to node tree */
173         exec->nodetree = ntree;
174         
175         /* set stack indices */
176         index = 0;
177         for (n = 0; n < totnodes; ++n) {
178                 node = nodelist[n];
179                 
180                 node->stack_index = index;
181                 
182                 /* init node socket stack indexes */
183                 for (sock = node->inputs.first; sock; sock = sock->next)
184                         node_init_input_index(sock, &index);
185                 
186                 if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) {
187                         for (sock = node->outputs.first; sock; sock = sock->next)
188                                 node_init_output_index(sock, &index, &node->internal_links);
189                 }
190                 else {
191                         for (sock = node->outputs.first; sock; sock = sock->next)
192                                 node_init_output_index(sock, &index, NULL);
193                 }
194         }
195         
196         /* allocated exec data pointers for nodes */
197         exec->totnodes = totnodes;
198         exec->nodeexec = MEM_callocN(exec->totnodes * sizeof(bNodeExec), "node execution data");
199         /* allocate data pointer for node stack */
200         exec->stacksize = index;
201         exec->stack = MEM_callocN(exec->stacksize * sizeof(bNodeStack), "bNodeStack");
202         
203         /* all non-const results are considered inputs */
204         for (n = 0; n < exec->stacksize; ++n)
205                 exec->stack[n].hasinput = 1;
206         
207         /* prepare all nodes for execution */
208         for (n = 0, nodeexec = exec->nodeexec; n < totnodes; ++n, ++nodeexec) {
209                 node = nodeexec->node = nodelist[n];
210                 nodeexec->freeexecfunc = node->typeinfo->freeexecfunc;
211                 
212                 /* tag inputs */
213                 for (sock = node->inputs.first; sock; sock = sock->next) {
214                         /* disable the node if an input link is invalid */
215                         if (sock->link && !(sock->link->flag & NODE_LINK_VALID))
216                                 node->need_exec = 0;
217                         
218                         ns = setup_stack(exec->stack, ntree, node, sock);
219                         if (ns)
220                                 ns->hasoutput = 1;
221                 }
222                 
223                 /* tag all outputs */
224                 for (sock = node->outputs.first; sock; sock = sock->next) {
225                         /* ns = */ setup_stack(exec->stack, ntree, node, sock);
226                 }
227                 
228                 nodekey = BKE_node_instance_key(parent_key, ntree, node);
229                 nodeexec->data.preview = context->previews ? BKE_node_instance_hash_lookup(context->previews, nodekey) : NULL;
230                 if (node->typeinfo->initexecfunc)
231                         nodeexec->data.data = node->typeinfo->initexecfunc(context, node, nodekey);
232         }
233         
234         if (nodelist)
235                 MEM_freeN(nodelist);
236         
237         return exec;
238 }
239
240 void ntree_exec_end(bNodeTreeExec *exec)
241 {
242         bNodeExec *nodeexec;
243         int n;
244         
245         if (exec->stack)
246                 MEM_freeN(exec->stack);
247         
248         for (n = 0, nodeexec = exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
249                 if (nodeexec->freeexecfunc)
250                         nodeexec->freeexecfunc(nodeexec->data.data);
251         }
252         
253         if (exec->nodeexec)
254                 MEM_freeN(exec->nodeexec);
255         
256         MEM_freeN(exec);
257 }
258
259 /**** Material/Texture trees ****/
260
261 bNodeThreadStack *ntreeGetThreadStack(bNodeTreeExec *exec, int thread)
262 {
263         ListBase *lb = &exec->threadstack[thread];
264         bNodeThreadStack *nts;
265         
266         for (nts = lb->first; nts; nts = nts->next) {
267                 if (!nts->used) {
268                         nts->used = TRUE;
269                         break;
270                 }
271         }
272         
273         if (!nts) {
274                 nts = MEM_callocN(sizeof(bNodeThreadStack), "bNodeThreadStack");
275                 nts->stack = MEM_dupallocN(exec->stack);
276                 nts->used = TRUE;
277                 BLI_addtail(lb, nts);
278         }
279
280         return nts;
281 }
282
283 void ntreeReleaseThreadStack(bNodeThreadStack *nts)
284 {
285         nts->used = 0;
286 }
287
288 bool ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *callerdata, int thread)
289 {
290         bNodeStack *nsin[MAX_SOCKET] = {NULL};   /* arbitrary... watch this */
291         bNodeStack *nsout[MAX_SOCKET] = {NULL};  /* arbitrary... watch this */
292         bNodeExec *nodeexec;
293         bNode *node;
294         int n;
295         
296         /* nodes are presorted, so exec is in order of list */
297         
298         for (n = 0, nodeexec = exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
299                 node = nodeexec->node;
300                 if (node->need_exec) {
301                         node_get_stack(node, nts->stack, nsin, nsout);
302                         /* Handle muted nodes...
303                          * If the mute func is not set, assume the node should never be muted,
304                          * and hence execute it!
305                          */
306 //                      if (node->typeinfo->compatibility == NODE_NEW_SHADING)
307 //                              return false;
308                         if (node->typeinfo->execfunc)
309                                 node->typeinfo->execfunc(callerdata, thread, node, &nodeexec->data, nsin, nsout);
310                 }
311         }
312         
313         /* signal to that all went OK, for render */
314         return true;
315 }