Code cleanup: reorder BKE_scene_use_new_shading_nodes checks last
[blender.git] / source / blender / nodes / shader / node_shader_tree.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):
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/nodes/shader/node_shader_tree.c
29  *  \ingroup nodes
30  */
31
32
33 #include <string.h>
34
35 #include "DNA_lamp_types.h"
36 #include "DNA_material_types.h"
37 #include "DNA_node_types.h"
38 #include "DNA_scene_types.h"
39 #include "DNA_space_types.h"
40 #include "DNA_world_types.h"
41
42 #include "BLI_listbase.h"
43 #include "BLI_math.h"
44 #include "BLI_threads.h"
45 #include "BLI_utildefines.h"
46
47 #include "BLF_translation.h"
48
49 #include "BKE_context.h"
50 #include "BKE_global.h"
51 #include "BKE_main.h"
52 #include "BKE_node.h"
53 #include "BKE_scene.h"
54
55 #include "RNA_access.h"
56
57 #include "GPU_material.h"
58
59 #include "RE_shader_ext.h"
60
61 #include "node_common.h"
62 #include "node_exec.h"
63 #include "node_util.h"
64 #include "node_shader_util.h"
65
66 static int shader_tree_poll(const bContext *C, bNodeTreeType *UNUSED(treetype))
67 {
68         Scene *scene = CTX_data_scene(C);
69         /* allow empty engine string too, this is from older versions that didn't have registerable engines yet */
70         return (scene->r.engine[0] == '\0' ||
71                 STREQ(scene->r.engine, "BLENDER_RENDER") ||
72                 STREQ(scene->r.engine, "BLENDER_GAME") ||
73                 STREQ(scene->r.engine, "CYCLES"));
74 }
75
76 static void shader_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from)
77 {
78         SpaceNode *snode = CTX_wm_space_node(C);
79         Scene *scene = CTX_data_scene(C);
80         Object *ob = OBACT;
81         
82         if ((snode->shaderfrom == SNODE_SHADER_OBJECT) ||
83             (BKE_scene_use_new_shading_nodes(scene) == false))
84         {
85                 if (ob) {
86                         *r_from = &ob->id;
87                         if (ob->type == OB_LAMP) {
88                                 *r_id = ob->data;
89                                 *r_ntree = ((Lamp *)ob->data)->nodetree;
90                         }
91                         else {
92                                 Material *ma = give_current_material(ob, ob->actcol);
93                                 if (ma) {
94                                         *r_id = &ma->id;
95                                         *r_ntree = ma->nodetree;
96                                 }
97                         }
98                 }
99         }
100         else { /* SNODE_SHADER_WORLD */
101                 if (scene->world) {
102                         *r_from = NULL;
103                         *r_id = &scene->world->id;
104                         *r_ntree = scene->world->nodetree;
105                 }
106         }
107 }
108
109 static void foreach_nodeclass(Scene *scene, void *calldata, bNodeClassCallback func)
110 {
111         func(calldata, NODE_CLASS_INPUT, N_("Input"));
112         func(calldata, NODE_CLASS_OUTPUT, N_("Output"));
113
114         if (BKE_scene_use_new_shading_nodes(scene)) {
115                 func(calldata, NODE_CLASS_SHADER, N_("Shader"));
116                 func(calldata, NODE_CLASS_TEXTURE, N_("Texture"));
117         }
118         
119         func(calldata, NODE_CLASS_OP_COLOR, N_("Color"));
120         func(calldata, NODE_CLASS_OP_VECTOR, N_("Vector"));
121         func(calldata, NODE_CLASS_CONVERTOR, N_("Convertor"));
122         func(calldata, NODE_CLASS_SCRIPT, N_("Script"));
123         func(calldata, NODE_CLASS_GROUP, N_("Group"));
124         func(calldata, NODE_CLASS_INTERFACE, N_("Interface"));
125         func(calldata, NODE_CLASS_LAYOUT, N_("Layout"));
126 }
127
128 static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree))
129 {
130         bNode *node, *node_next;
131         
132         /* replace muted nodes and reroute nodes by internal links */
133         for (node = localtree->nodes.first; node; node = node_next) {
134                 node_next = node->next;
135                 
136                 if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) {
137                         nodeInternalRelink(localtree, node);
138                         nodeFreeNode(localtree, node);
139                 }
140         }
141 }
142
143 static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
144 {
145         BKE_node_preview_sync_tree(ntree, localtree);
146 }
147
148 static void local_merge(bNodeTree *localtree, bNodeTree *ntree)
149 {
150         BKE_node_preview_merge_tree(ntree, localtree, true);
151 }
152
153 static void update(bNodeTree *ntree)
154 {
155         ntreeSetOutput(ntree);
156         
157         ntree_update_reroute_nodes(ntree);
158         
159         if (ntree->update & NTREE_UPDATE_NODES) {
160                 /* clean up preview cache, in case nodes have been removed */
161                 BKE_node_preview_remove_unused(ntree);
162         }
163 }
164
165 bNodeTreeType *ntreeType_Shader;
166
167 void register_node_tree_type_sh(void)
168 {
169         bNodeTreeType *tt = ntreeType_Shader = MEM_callocN(sizeof(bNodeTreeType), "shader node tree type");
170         
171         tt->type = NTREE_SHADER;
172         strcpy(tt->idname, "ShaderNodeTree");
173         strcpy(tt->ui_name, "Shader");
174         tt->ui_icon = 0;    /* defined in drawnode.c */
175         strcpy(tt->ui_description, "Shader nodes");
176         
177         tt->foreach_nodeclass = foreach_nodeclass;
178         tt->localize = localize;
179         tt->local_sync = local_sync;
180         tt->local_merge = local_merge;
181         tt->update = update;
182         tt->poll = shader_tree_poll;
183         tt->get_from_context = shader_get_from_context;
184         
185         tt->ext.srna = &RNA_ShaderNodeTree;
186         
187         ntreeTypeAdd(tt);
188 }
189
190 /* GPU material from shader nodes */
191
192 void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat, short compatibility)
193 {
194         /* localize tree to create links for reroute and mute */
195         bNodeTree *localtree = ntreeLocalize(ntree);
196         bNodeTreeExec *exec;
197
198         exec = ntreeShaderBeginExecTree(localtree);
199         ntreeExecGPUNodes(exec, mat, 1, compatibility);
200         ntreeShaderEndExecTree(exec);
201
202         ntreeFreeTree_ex(localtree, false);
203         MEM_freeN(localtree);
204 }
205
206 /* **************** call to switch lamploop for material node ************ */
207
208 void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *);
209
210 void set_node_shader_lamp_loop(void (*lamp_loop_func)(ShadeInput *, ShadeResult *))
211 {
212         node_shader_lamp_loop = lamp_loop_func;
213 }
214
215
216 bNodeTreeExec *ntreeShaderBeginExecTree_internal(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
217 {
218         bNodeTreeExec *exec;
219         bNode *node;
220         
221         /* ensures only a single output node is enabled */
222         ntreeSetOutput(ntree);
223         
224         /* common base initialization */
225         exec = ntree_exec_begin(context, ntree, parent_key);
226         
227         /* allocate the thread stack listbase array */
228         exec->threadstack = MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array");
229         
230         for (node = exec->nodetree->nodes.first; node; node = node->next)
231                 node->need_exec = 1;
232         
233         return exec;
234 }
235
236 bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree)
237 {
238         bNodeExecContext context;
239         bNodeTreeExec *exec;
240         
241         /* XXX hack: prevent exec data from being generated twice.
242          * this should be handled by the renderer!
243          */
244         if (ntree->execdata)
245                 return ntree->execdata;
246         
247         context.previews = ntree->previews;
248         
249         exec = ntreeShaderBeginExecTree_internal(&context, ntree, NODE_INSTANCE_KEY_BASE);
250         
251         /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
252          * which only store the ntree pointer. Should be fixed at some point!
253          */
254         ntree->execdata = exec;
255         
256         return exec;
257 }
258
259 void ntreeShaderEndExecTree_internal(bNodeTreeExec *exec)
260 {
261         bNodeThreadStack *nts;
262         int a;
263         
264         if (exec->threadstack) {
265                 for (a = 0; a < BLENDER_MAX_THREADS; a++) {
266                         for (nts = exec->threadstack[a].first; nts; nts = nts->next)
267                                 if (nts->stack) MEM_freeN(nts->stack);
268                         BLI_freelistN(&exec->threadstack[a]);
269                 }
270                 
271                 MEM_freeN(exec->threadstack);
272                 exec->threadstack = NULL;
273         }
274         
275         ntree_exec_end(exec);
276 }
277
278 void ntreeShaderEndExecTree(bNodeTreeExec *exec)
279 {
280         if (exec) {
281                 /* exec may get freed, so assign ntree */
282                 bNodeTree *ntree = exec->nodetree;
283                 ntreeShaderEndExecTree_internal(exec);
284                 
285                 /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
286                 ntree->execdata = NULL;
287         }
288 }
289
290 /* only for Blender internal */
291 bool ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr)
292 {
293         ShaderCallData scd;
294         /**
295          * \note: preserve material from ShadeInput for material id, nodetree execs change it
296          * fix for bug "[#28012] Mat ID messy with shader nodes"
297          */
298         Material *mat = shi->mat;
299         bNodeThreadStack *nts = NULL;
300         bNodeTreeExec *exec = ntree->execdata;
301         int compat;
302         
303         /* convert caller data to struct */
304         scd.shi = shi;
305         scd.shr = shr;
306         
307         /* each material node has own local shaderesult, with optional copying */
308         memset(shr, 0, sizeof(ShadeResult));
309         
310         /* ensure execdata is only initialized once */
311         if (!exec) {
312                 BLI_lock_thread(LOCK_NODES);
313                 if (!ntree->execdata)
314                         ntree->execdata = ntreeShaderBeginExecTree(ntree);
315                 BLI_unlock_thread(LOCK_NODES);
316
317                 exec = ntree->execdata;
318         }
319         
320         nts = ntreeGetThreadStack(exec, shi->thread);
321         compat = ntreeExecThreadNodes(exec, nts, &scd, shi->thread);
322         ntreeReleaseThreadStack(nts);
323         
324         // \note: set material back to preserved material
325         shi->mat = mat;
326                 
327         /* better not allow negative for now */
328         if (shr->combined[0] < 0.0f) shr->combined[0] = 0.0f;
329         if (shr->combined[1] < 0.0f) shr->combined[1] = 0.0f;
330         if (shr->combined[2] < 0.0f) shr->combined[2] = 0.0f;
331         
332         /* if compat is zero, it has been using non-compatible nodes */
333         return compat;
334 }