header cleanup, include BLI before BKE, also use bool for ntreeShaderExecTree
[blender.git] / source / blender / nodes / shader / nodes / node_shader_common.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) 2006 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Campbell Barton, Alfredo de Greef, David Millan Escriva,
24  * Juho Vepsäläinen
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /** \file blender/nodes/shader/nodes/node_shader_common.c
30  *  \ingroup shdnodes
31  */
32
33
34 #include "DNA_node_types.h"
35
36 #include "BLI_utildefines.h"
37
38 #include "BKE_node.h"
39
40 #include "node_shader_util.h"
41 #include "node_common.h"
42 #include "node_exec.h"
43
44 static void copy_stack(bNodeStack *to, bNodeStack *from)
45 {
46         if (to != from) {
47                 copy_v4_v4(to->vec, from->vec);
48                 to->data = from->data;
49                 to->datatype = from->datatype;
50                 
51                 /* tag as copy to prevent freeing */
52                 to->is_copy = 1;
53         }
54 }
55
56 static void move_stack(bNodeStack *to, bNodeStack *from)
57 {
58         if (to != from) {
59                 copy_v4_v4(to->vec, from->vec);
60                 to->data = from->data;
61                 to->datatype = from->datatype;
62                 to->is_copy = from->is_copy;
63                 
64                 zero_v4(from->vec);
65                 from->data = NULL;
66                 from->datatype = 0;
67                 from->is_copy = 0;
68         }
69 }
70
71 /**** GROUP ****/
72
73 static void *group_initexec(bNode *node)
74 {
75         bNodeTree *ngroup = (bNodeTree *)node->id;
76         bNodeTreeExec *exec;
77         
78         if (!ngroup)
79                 return NULL;
80         
81         /* initialize the internal node tree execution */
82         exec = ntreeShaderBeginExecTree(ngroup, 0);
83         
84         return exec;
85 }
86
87 static void group_freeexec(bNode *UNUSED(node), void *nodedata)
88 {
89         bNodeTreeExec*gexec = (bNodeTreeExec *)nodedata;
90         
91         ntreeShaderEndExecTree(gexec, 0);
92 }
93
94 /* Copy inputs to the internal stack.
95  */
96 static void group_copy_inputs(bNode *node, bNodeStack **in, bNodeStack *gstack)
97 {
98         bNodeSocket *sock;
99         bNodeStack *ns;
100         int a;
101         for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) {
102                 if (sock->groupsock) {
103                         ns = node_get_socket_stack(gstack, sock->groupsock);
104                         copy_stack(ns, in[a]);
105                 }
106         }
107 }
108
109 /* Copy internal results to the external outputs.
110  */
111 static void group_move_outputs(bNode *node, bNodeStack **out, bNodeStack *gstack)
112 {
113         bNodeSocket *sock;
114         bNodeStack *ns;
115         int a;
116         for (sock=node->outputs.first, a=0; sock; sock=sock->next, ++a) {
117                 if (sock->groupsock) {
118                         ns = node_get_socket_stack(gstack, sock->groupsock);
119                         move_stack(out[a], ns);
120                 }
121         }
122 }
123
124 static void group_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out)
125 {
126         bNodeTreeExec *exec = (bNodeTreeExec *)nodedata;
127         bNodeThreadStack *nts;
128         
129         if (!exec)
130                 return;
131         
132         /* XXX same behavior as trunk: all nodes inside group are executed.
133          * it's stupid, but just makes it work. compo redesign will do this better.
134          */
135         {
136                 bNode *inode;
137                 for (inode=exec->nodetree->nodes.first; inode; inode=inode->next)
138                         inode->need_exec = 1;
139         }
140         
141         nts = ntreeGetThreadStack(exec, thread);
142         
143         group_copy_inputs(node, in, nts->stack);
144         ntreeExecThreadNodes(exec, nts, data, thread);
145         group_move_outputs(node, out, nts->stack);
146         
147         ntreeReleaseThreadStack(nts);
148 }
149
150 static void group_gpu_copy_inputs(bNode *node, GPUNodeStack *in, bNodeStack *gstack)
151 {
152         bNodeSocket *sock;
153         bNodeStack *ns;
154         int a;
155         for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) {
156                 if (sock->groupsock) {
157                         ns = node_get_socket_stack(gstack, sock->groupsock);
158                         /* convert the external gpu stack back to internal node stack data */
159                         node_data_from_gpu_stack(ns, &in[a]);
160                 }
161         }
162 }
163
164 /* Copy internal results to the external outputs.
165  */
166 static void group_gpu_move_outputs(bNode *node, GPUNodeStack *out, bNodeStack *gstack)
167 {
168         bNodeSocket *sock;
169         bNodeStack *ns;
170         int a;
171         for (sock=node->outputs.first, a=0; sock; sock=sock->next, ++a) {
172                 if (sock->groupsock) {
173                         ns = node_get_socket_stack(gstack, sock->groupsock);
174                         /* convert the node stack data result back to gpu stack */
175                         node_gpu_stack_from_data(&out[a], sock->type, ns);
176                 }
177         }
178 }
179
180 static int gpu_group_execute(GPUMaterial *mat, bNode *node, void *nodedata, GPUNodeStack *in, GPUNodeStack *out)
181 {
182         bNodeTreeExec *exec = (bNodeTreeExec *)nodedata;
183         
184         group_gpu_copy_inputs(node, in, exec->stack);
185         ntreeExecGPUNodes(exec, mat, (node->flag & NODE_GROUP_EDIT));
186         group_gpu_move_outputs(node, out, exec->stack);
187         
188         return 1;
189 }
190
191 void register_node_type_sh_group(bNodeTreeType *ttype)
192 {
193         static bNodeType ntype;
194
195         node_type_base(ttype, &ntype, NODE_GROUP, "Group", NODE_CLASS_GROUP, NODE_OPTIONS|NODE_CONST_OUTPUT);
196         node_type_socket_templates(&ntype, NULL, NULL);
197         node_type_size(&ntype, 120, 60, 200);
198         node_type_label(&ntype, node_group_label);
199         node_type_init(&ntype, node_group_init);
200         node_type_valid(&ntype, node_group_valid);
201         node_type_template(&ntype, node_group_template);
202         node_type_update(&ntype, NULL, node_group_verify);
203         node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear);
204         node_type_exec_new(&ntype, group_initexec, group_freeexec, group_execute);
205         node_type_gpu_ext(&ntype, gpu_group_execute);
206         
207         nodeRegisterType(ttype, &ntype);
208 }