Merge commit '212a8d9e5ae7' into blender2.8
[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 #include "DNA_linestyle_types.h"
42 #include "DNA_workspace_types.h"
43
44 #include "BLI_listbase.h"
45 #include "BLI_threads.h"
46 #include "BLI_utildefines.h"
47
48 #include "BLT_translation.h"
49
50 #include "BKE_context.h"
51 #include "BKE_linestyle.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 "NOD_common.h"
62
63 #include "node_common.h"
64 #include "node_exec.h"
65 #include "node_util.h"
66 #include "node_shader_util.h"
67
68 static int shader_tree_poll(const bContext *C, bNodeTreeType *UNUSED(treetype))
69 {
70         Scene *scene = CTX_data_scene(C);
71         WorkSpace *workspace = CTX_wm_workspace(C);
72         ViewRender *view_render = BKE_viewrender_get(scene, workspace);
73         const char *engine_id = view_render->engine_id;
74
75         /* allow empty engine string too, this is from older versions that didn't have registerable engines yet */
76         return (engine_id[0] == '\0' ||
77                 STREQ(engine_id, RE_engine_id_BLENDER_RENDER) ||
78                 STREQ(engine_id, RE_engine_id_BLENDER_GAME) ||
79                 STREQ(engine_id, RE_engine_id_CYCLES) ||
80                 !BKE_viewrender_use_shading_nodes_custom(view_render));
81 }
82
83 static void shader_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from)
84 {
85         SpaceNode *snode = CTX_wm_space_node(C);
86         Scene *scene = CTX_data_scene(C);
87         WorkSpace *workspace = CTX_wm_workspace(C);
88         SceneLayer *scene_layer = CTX_data_scene_layer(C);
89         Object *ob = OBACT(scene_layer);
90         ViewRender *view_render = BKE_viewrender_get(scene, workspace);
91         
92         if ((snode->shaderfrom == SNODE_SHADER_OBJECT) ||
93             (BKE_viewrender_use_new_shading_nodes(view_render) == false))
94         {
95                 if (ob) {
96                         *r_from = &ob->id;
97                         if (ob->type == OB_LAMP) {
98                                 *r_id = ob->data;
99                                 *r_ntree = ((Lamp *)ob->data)->nodetree;
100                         }
101                         else {
102                                 Material *ma = give_current_material(ob, ob->actcol);
103                                 if (ma) {
104                                         *r_id = &ma->id;
105                                         *r_ntree = ma->nodetree;
106                                 }
107                         }
108                 }
109         }
110 #ifdef WITH_FREESTYLE
111         else if (snode->shaderfrom == SNODE_SHADER_LINESTYLE) {
112                 FreestyleLineStyle *linestyle = BKE_linestyle_active_from_scene(scene);
113                 if (linestyle) {
114                         *r_from = NULL;
115                         *r_id = &linestyle->id;
116                         *r_ntree = linestyle->nodetree;
117                 }
118         }
119 #endif
120         else { /* SNODE_SHADER_WORLD */
121                 if (scene->world) {
122                         *r_from = NULL;
123                         *r_id = &scene->world->id;
124                         *r_ntree = scene->world->nodetree;
125                 }
126         }
127 }
128
129 static void foreach_nodeclass(ViewRender *view_render, void *calldata, bNodeClassCallback func)
130 {
131         func(calldata, NODE_CLASS_INPUT, N_("Input"));
132         func(calldata, NODE_CLASS_OUTPUT, N_("Output"));
133
134         if (BKE_viewrender_use_new_shading_nodes(view_render)) {
135                 func(calldata, NODE_CLASS_SHADER, N_("Shader"));
136                 func(calldata, NODE_CLASS_TEXTURE, N_("Texture"));
137         }
138         
139         func(calldata, NODE_CLASS_OP_COLOR, N_("Color"));
140         func(calldata, NODE_CLASS_OP_VECTOR, N_("Vector"));
141         func(calldata, NODE_CLASS_CONVERTOR, N_("Convertor"));
142         func(calldata, NODE_CLASS_SCRIPT, N_("Script"));
143         func(calldata, NODE_CLASS_GROUP, N_("Group"));
144         func(calldata, NODE_CLASS_INTERFACE, N_("Interface"));
145         func(calldata, NODE_CLASS_LAYOUT, N_("Layout"));
146 }
147
148 static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree))
149 {
150         bNode *node, *node_next;
151         
152         /* replace muted nodes and reroute nodes by internal links */
153         for (node = localtree->nodes.first; node; node = node_next) {
154                 node_next = node->next;
155                 
156                 if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) {
157                         nodeInternalRelink(localtree, node);
158                         nodeFreeNode(localtree, node);
159                 }
160         }
161 }
162
163 static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
164 {
165         BKE_node_preview_sync_tree(ntree, localtree);
166 }
167
168 static void local_merge(bNodeTree *localtree, bNodeTree *ntree)
169 {
170         BKE_node_preview_merge_tree(ntree, localtree, true);
171 }
172
173 static void update(bNodeTree *ntree)
174 {
175         ntreeSetOutput(ntree);
176         
177         ntree_update_reroute_nodes(ntree);
178         
179         if (ntree->update & NTREE_UPDATE_NODES) {
180                 /* clean up preview cache, in case nodes have been removed */
181                 BKE_node_preview_remove_unused(ntree);
182         }
183 }
184
185 bNodeTreeType *ntreeType_Shader;
186
187 void register_node_tree_type_sh(void)
188 {
189         bNodeTreeType *tt = ntreeType_Shader = MEM_callocN(sizeof(bNodeTreeType), "shader node tree type");
190         
191         tt->type = NTREE_SHADER;
192         strcpy(tt->idname, "ShaderNodeTree");
193         strcpy(tt->ui_name, "Shader");
194         tt->ui_icon = 0;    /* defined in drawnode.c */
195         strcpy(tt->ui_description, "Shader nodes");
196         
197         tt->foreach_nodeclass = foreach_nodeclass;
198         tt->localize = localize;
199         tt->local_sync = local_sync;
200         tt->local_merge = local_merge;
201         tt->update = update;
202         tt->poll = shader_tree_poll;
203         tt->get_from_context = shader_get_from_context;
204         
205         tt->ext.srna = &RNA_ShaderNodeTree;
206         
207         ntreeTypeAdd(tt);
208 }
209
210 /* GPU material from shader nodes */
211
212 static void ntree_shader_link_builtin_normal(bNodeTree *ntree,
213                                              bNode *node_from,
214                                              bNodeSocket *socket_from,
215                                              bNode *displacement_node,
216                                              bNodeSocket *displacement_socket);
217
218 /* Find an output node of the shader tree.
219  *
220  * NOTE: it will only return output which is NOT in the group, which isn't how
221  * render engines works but it's how the GPU shader compilation works. This we
222  * can change in the future and make it a generic function, but for now it stays
223  * private here.
224  *
225  * It also does not yet take into account render engine specific output nodes,
226  * it should give priority to e.g. the Eevee material output node for Eevee.
227  */
228 static bNode *ntree_shader_output_node(bNodeTree *ntree)
229 {
230         /* Make sure we only have single node tagged as output. */
231         ntreeSetOutput(ntree);
232         for (bNode *node = ntree->nodes.first; node != NULL; node = node->next) {
233                 if (node->flag & NODE_DO_OUTPUT) {
234                         return node;
235                 }
236         }
237         return NULL;
238 }
239
240 /* Find socket with a specified identifier. */
241 static bNodeSocket *ntree_shader_node_find_socket(ListBase *sockets,
242                                                   const char *identifier)
243 {
244         for (bNodeSocket *sock = sockets->first; sock != NULL; sock = sock->next) {
245                 if (STREQ(sock->identifier, identifier)) {
246                         return sock;
247                 }
248         }
249         return NULL;
250 }
251
252 /* Find input socket with a specified identifier. */
253 static bNodeSocket *ntree_shader_node_find_input(bNode *node,
254                                                  const char *identifier)
255 {
256         return ntree_shader_node_find_socket(&node->inputs, identifier);
257 }
258
259 /* Find output socket with a specified identifier. */
260 static bNodeSocket *ntree_shader_node_find_output(bNode *node,
261                                                   const char *identifier)
262 {
263         return ntree_shader_node_find_socket(&node->outputs, identifier);
264 }
265
266 /* Check whether shader has a displacement.
267  *
268  * Will also return a node and it's socket which is connected to a displacement
269  * output. Additionally, link which is attached to the displacement output is
270  * also returned.
271  */
272 static bool ntree_shader_has_displacement(bNodeTree *ntree,
273                                           bNode **r_node,
274                                           bNodeSocket **r_socket,
275                                           bNodeLink **r_link)
276 {
277         bNode *output_node = ntree_shader_output_node(ntree);
278         if (output_node == NULL) {
279                 /* We can't have displacement without output node, apparently. */
280                 return false;
281         }
282         /* Make sure sockets links pointers are correct. */
283         ntreeUpdateTree(G.main, ntree);
284         bNodeSocket *displacement = ntree_shader_node_find_input(output_node,
285                                                                  "Displacement");
286
287         if (displacement == NULL) {
288                 /* Non-cycles node is used as an output. */
289                 return false;
290         }
291         if (displacement->link != NULL) {
292                 *r_node = displacement->link->fromnode;
293                 *r_socket = displacement->link->fromsock;
294                 *r_link = displacement->link;
295         }
296         return displacement->link != NULL;
297 }
298
299 static bool ntree_shader_relink_node_normal(bNodeTree *ntree,
300                                             bNode *node,
301                                             bNode *node_from,
302                                             bNodeSocket *socket_from)
303 {
304         bNodeSocket *sock = ntree_shader_node_find_input(node, "Normal");
305         /* TODO(sergey): Can we do something smarter here than just a name-based
306          * matching?
307          */
308         if (sock == NULL) {
309                 /* There's no Normal input, nothing to link. */
310                 return false;
311         }
312         if (sock->link != NULL) {
313                 /* Something is linked to the normal input already. can't
314                  * use other input for that.
315                  */
316                 return false;
317         }
318         /* Create connection between specified node and the normal input. */
319         nodeAddLink(ntree, node_from, socket_from, node, sock);
320         return true;
321 }
322
323 static void ntree_shader_link_builtin_group_normal(
324         bNodeTree *ntree,
325         bNode *group_node,
326         bNode *node_from,
327         bNodeSocket *socket_from,
328         bNode *displacement_node,
329         bNodeSocket *displacement_socket)
330 {
331         bNodeTree *group_ntree = (bNodeTree *)group_node->id;
332         /* Create input socket to plug displacement connection to. */
333         bNodeSocket *group_normal_socket =
334                 ntreeAddSocketInterface(group_ntree,
335                                         SOCK_IN,
336                                         "NodeSocketVector",
337                                         "Normal");
338         /* Need to update tree so all node instances nodes gets proper sockets. */
339         bNode *group_input_node = ntreeFindType(group_ntree, NODE_GROUP_INPUT);
340         node_group_verify(ntree, group_node, &group_ntree->id);
341         if (group_input_node)
342                 node_group_input_verify(group_ntree, group_input_node, &group_ntree->id);
343         ntreeUpdateTree(G.main, group_ntree);
344         /* Assumes sockets are always added at the end. */
345         bNodeSocket *group_node_normal_socket = group_node->inputs.last;
346         if (displacement_node == group_node) {
347                 /* If displacement is coming from this node group we need to perform
348                  * some internal re-linking in order to avoid cycles.
349                  */
350                 bNode *group_output_node = ntreeFindType(group_ntree, NODE_GROUP_OUTPUT);
351                 BLI_assert(group_output_node != NULL);
352                 bNodeSocket *group_output_node_displacement_socket =
353                         nodeFindSocket(group_output_node,
354                                        SOCK_IN,
355                                        displacement_socket->identifier);
356                 bNodeLink *group_displacement_link = group_output_node_displacement_socket->link;
357                 if (group_displacement_link == NULL) {
358                         /* Displacement output is not connected to anything, can just stop
359                          * right away.
360                          */
361                         return;
362                 }
363                 /* This code is similar to ntree_shader_relink_displacement() */
364                 bNode *group_displacement_node = group_displacement_link->fromnode;
365                 bNodeSocket *group_displacement_socket = group_displacement_link->fromsock;
366                 /* Create and link bump node.
367                  * Can't re-use bump node from parent tree because it'll cause cycle.
368                  */
369                 bNode *bump_node = nodeAddStaticNode(NULL, group_ntree, SH_NODE_BUMP);
370                 bNodeSocket *bump_input_socket = ntree_shader_node_find_input(bump_node, "Height");
371                 bNodeSocket *bump_output_socket = ntree_shader_node_find_output(bump_node, "Normal");
372                 BLI_assert(bump_input_socket != NULL);
373                 BLI_assert(bump_output_socket != NULL);
374                 nodeAddLink(group_ntree,
375                             group_displacement_node, group_displacement_socket,
376                             bump_node, bump_input_socket);
377                 /* Relink normals inside of the instanced tree. */
378                 ntree_shader_link_builtin_normal(group_ntree,
379                                                  bump_node,
380                                                  bump_output_socket,
381                                                  group_displacement_node,
382                                                  group_displacement_socket);
383                 ntreeUpdateTree(G.main, group_ntree);
384         }
385         else if (group_input_node) {
386                 /* Connect group node normal input. */
387                 nodeAddLink(ntree,
388                             node_from, socket_from,
389                             group_node, group_node_normal_socket);
390                 BLI_assert(group_input_node != NULL);
391                 bNodeSocket *group_input_node_normal_socket =
392                         nodeFindSocket(group_input_node,
393                                        SOCK_OUT,
394                                        group_normal_socket->identifier);
395                 BLI_assert(group_input_node_normal_socket != NULL);
396                 /* Relink normals inside of the instanced tree. */
397                 ntree_shader_link_builtin_normal(group_ntree,
398                                                  group_input_node,
399                                                  group_input_node_normal_socket,
400                                                  displacement_node,
401                                                  displacement_socket);
402                 ntreeUpdateTree(G.main, group_ntree);
403         }
404 }
405
406 /* Use specified node and socket as an input for unconnected normal sockets. */
407 static void ntree_shader_link_builtin_normal(bNodeTree *ntree,
408                                              bNode *node_from,
409                                              bNodeSocket *socket_from,
410                                              bNode *displacement_node,
411                                              bNodeSocket *displacement_socket)
412 {
413         for (bNode *node = ntree->nodes.first; node != NULL; node = node->next) {
414                 if (node == node_from) {
415                         /* Don't connect node itself! */
416                         continue;
417                 }
418                 if (node->type == NODE_GROUP && node->id) {
419                         /* Special re-linking for group nodes. */
420                         ntree_shader_link_builtin_group_normal(ntree,
421                                                                node,
422                                                                node_from,
423                                                                socket_from,
424                                                                displacement_node,
425                                                                displacement_socket);
426                         continue;
427                 }
428                 if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {
429                         /* Group inputs and outputs needs nothing special. */
430                         continue;
431                 }
432                 ntree_shader_relink_node_normal(ntree, node, node_from, socket_from);
433         }
434 }
435
436 /* Re-link displacement output to unconnected normal sockets via bump node.
437  * This way material with have proper displacement in the viewport.
438  */
439 static void ntree_shader_relink_displacement(bNodeTree *ntree,
440                                              short compatibility)
441 {
442         if (compatibility != NODE_NEW_SHADING) {
443                 /* We can only deal with new shading system here. */
444                 return;
445         }
446         bNode *displacement_node;
447         bNodeSocket *displacement_socket;
448         bNodeLink *displacement_link;
449         if (!ntree_shader_has_displacement(ntree,
450                                            &displacement_node,
451                                            &displacement_socket,
452                                            &displacement_link))
453         {
454                 /* There is no displacement output connected, nothing to re-link. */
455                 return;
456         }
457         /* We have to disconnect displacement output socket, otherwise we'll have
458          * cycles in the Cycles material :)
459          */
460         nodeRemLink(ntree, displacement_link);
461         /* We can't connect displacement to normal directly, use bump node for that
462          * and hope that it gives good enough approximation.
463          */
464         bNode *bump_node = nodeAddStaticNode(NULL, ntree, SH_NODE_BUMP);
465         bNodeSocket *bump_input_socket = ntree_shader_node_find_input(bump_node, "Height");
466         bNodeSocket *bump_output_socket = ntree_shader_node_find_output(bump_node, "Normal");
467         BLI_assert(bump_input_socket != NULL);
468         BLI_assert(bump_output_socket != NULL);
469         /* Connect bump node to where displacement output was originally
470          * connected to.
471          */
472         nodeAddLink(ntree,
473                     displacement_node, displacement_socket,
474                     bump_node, bump_input_socket);
475         /* Connect all free-standing Normal inputs. */
476         ntree_shader_link_builtin_normal(ntree,
477                                          bump_node,
478                                          bump_output_socket,
479                                          displacement_node,
480                                          displacement_socket);
481         /* TODO(sergey): Reconnect Geometry Info->Normal sockets to the new
482          * bump node.
483          */
484         /* We modified the tree, it needs to be updated now. */
485         ntreeUpdateTree(G.main, ntree);
486 }
487
488 static bool ntree_tag_ssr_bsdf_cb(bNode *fromnode, bNode *UNUSED(tonode), void *userdata, const bool UNUSED(reversed))
489 {
490         switch (fromnode->type) {
491                 case SH_NODE_BSDF_ANISOTROPIC:
492                 case SH_NODE_EEVEE_SPECULAR:
493                 case SH_NODE_BSDF_PRINCIPLED:
494                 case SH_NODE_BSDF_GLOSSY:
495                 case SH_NODE_BSDF_GLASS:
496                         fromnode->ssr_id = (*(float *)userdata);
497                         (*(float *)userdata) += 1;
498                         break;
499                 default:
500                         /* We could return false here but since we (will)
501                          * allow the use of Closure as RGBA, we can have
502                          * Bsdf nodes linked to other Bsdf nodes. */
503                         break;
504         }
505
506         return true;
507 }
508
509 /* EEVEE: Scan the ntree to set the Screen Space Reflection
510  * layer id of every specular node.
511  */
512 static void ntree_shader_tag_ssr_node(bNodeTree *ntree, short compatibility)
513 {
514         if (compatibility & NODE_NEWER_SHADING) {
515                 /* We can only deal with new shading system here. */
516                 return;
517         }
518
519         bNode *output_node = ntree_shader_output_node(ntree);
520         if (output_node == NULL) {
521                 return;
522         }
523         /* Make sure sockets links pointers are correct. */
524         ntreeUpdateTree(G.main, ntree);
525
526         int lobe_count = 0;
527         nodeChainIter(ntree, output_node, ntree_tag_ssr_bsdf_cb, &lobe_count, true);
528 }
529
530 static bool ntree_tag_sss_bsdf_cb(bNode *fromnode, bNode *UNUSED(tonode), void *userdata, const bool UNUSED(reversed))
531 {
532         switch (fromnode->type) {
533                 case SH_NODE_BSDF_PRINCIPLED:
534                 case SH_NODE_SUBSURFACE_SCATTERING:
535                         fromnode->sss_id = (*(float *)userdata);
536                         (*(float *)userdata) += 1;
537                         break;
538                 default:
539                         break;
540         }
541
542         return true;
543 }
544
545 /* EEVEE: Scan the ntree to set the Subsurface Scattering id of every SSS node.
546  */
547 static void ntree_shader_tag_sss_node(bNodeTree *ntree, short compatibility)
548 {
549         if (compatibility & NODE_NEWER_SHADING) {
550                 /* We can only deal with new shading system here. */
551                 return;
552         }
553
554         bNode *output_node = ntree_shader_output_node(ntree);
555         if (output_node == NULL) {
556                 return;
557         }
558         /* Make sure sockets links pointers are correct. */
559         ntreeUpdateTree(G.main, ntree);
560
561         int sss_count = 0;
562         nodeChainIter(ntree, output_node, ntree_tag_sss_bsdf_cb, &sss_count, true);
563 }
564
565 /* EEVEE: Find which material domain are used (volume, surface ...).
566  */
567 void ntreeGPUMaterialDomain(bNodeTree *ntree, bool *has_surface_output, bool *has_volume_output)
568 {
569         /* localize tree to create links for reroute and mute */
570         bNodeTree *localtree = ntreeLocalize(ntree);
571
572         struct bNode *output = ntree_shader_output_node(localtree);
573
574         *has_surface_output = false;
575         *has_volume_output = false;
576
577         if (output != NULL) {
578                 bNodeSocket *surface_sock = ntree_shader_node_find_input(output, "Surface");
579                 bNodeSocket *volume_sock = ntree_shader_node_find_input(output, "Volume");
580
581                 if (surface_sock != NULL) {
582                         *has_surface_output = (nodeCountSocketLinks(localtree, surface_sock) > 0);
583                 }
584
585                 if (volume_sock != NULL) {
586                         *has_volume_output = (nodeCountSocketLinks(localtree, volume_sock) > 0);
587                 }
588         }
589
590         ntreeFreeTree(localtree);
591         MEM_freeN(localtree);
592 }
593
594 void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat, short compatibility)
595 {
596         /* localize tree to create links for reroute and mute */
597         bNodeTree *localtree = ntreeLocalize(ntree);
598         bNodeTreeExec *exec;
599
600         /* Perform all needed modifications on the tree in order to support
601          * displacement/bump mapping.
602          */
603         ntree_shader_relink_displacement(localtree, compatibility);
604
605         ntree_shader_tag_ssr_node(localtree, compatibility);
606         ntree_shader_tag_sss_node(localtree, compatibility);
607
608         exec = ntreeShaderBeginExecTree(localtree);
609         ntreeExecGPUNodes(exec, mat, 1, compatibility);
610         ntreeShaderEndExecTree(exec);
611
612         ntreeFreeTree(localtree);
613         MEM_freeN(localtree);
614 }
615
616 /* **************** call to switch lamploop for material node ************ */
617
618 void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *);
619
620 void set_node_shader_lamp_loop(void (*lamp_loop_func)(ShadeInput *, ShadeResult *))
621 {
622         node_shader_lamp_loop = lamp_loop_func;
623 }
624
625
626 bNodeTreeExec *ntreeShaderBeginExecTree_internal(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
627 {
628         bNodeTreeExec *exec;
629         bNode *node;
630         
631         /* ensures only a single output node is enabled */
632         ntreeSetOutput(ntree);
633         
634         /* common base initialization */
635         exec = ntree_exec_begin(context, ntree, parent_key);
636         
637         /* allocate the thread stack listbase array */
638         exec->threadstack = MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array");
639         
640         for (node = exec->nodetree->nodes.first; node; node = node->next)
641                 node->need_exec = 1;
642         
643         return exec;
644 }
645
646 bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree)
647 {
648         bNodeExecContext context;
649         bNodeTreeExec *exec;
650         
651         /* XXX hack: prevent exec data from being generated twice.
652          * this should be handled by the renderer!
653          */
654         if (ntree->execdata)
655                 return ntree->execdata;
656         
657         context.previews = ntree->previews;
658         
659         exec = ntreeShaderBeginExecTree_internal(&context, ntree, NODE_INSTANCE_KEY_BASE);
660         
661         /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
662          * which only store the ntree pointer. Should be fixed at some point!
663          */
664         ntree->execdata = exec;
665         
666         return exec;
667 }
668
669 void ntreeShaderEndExecTree_internal(bNodeTreeExec *exec)
670 {
671         bNodeThreadStack *nts;
672         int a;
673         
674         if (exec->threadstack) {
675                 for (a = 0; a < BLENDER_MAX_THREADS; a++) {
676                         for (nts = exec->threadstack[a].first; nts; nts = nts->next)
677                                 if (nts->stack) MEM_freeN(nts->stack);
678                         BLI_freelistN(&exec->threadstack[a]);
679                 }
680                 
681                 MEM_freeN(exec->threadstack);
682                 exec->threadstack = NULL;
683         }
684         
685         ntree_exec_end(exec);
686 }
687
688 void ntreeShaderEndExecTree(bNodeTreeExec *exec)
689 {
690         if (exec) {
691                 /* exec may get freed, so assign ntree */
692                 bNodeTree *ntree = exec->nodetree;
693                 ntreeShaderEndExecTree_internal(exec);
694                 
695                 /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
696                 ntree->execdata = NULL;
697         }
698 }
699
700 /* only for Blender internal */
701 bool ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr)
702 {
703         ShaderCallData scd;
704         /**
705          * \note: preserve material from ShadeInput for material id, nodetree execs change it
706          * fix for bug "[#28012] Mat ID messy with shader nodes"
707          */
708         Material *mat = shi->mat;
709         bNodeThreadStack *nts = NULL;
710         bNodeTreeExec *exec = ntree->execdata;
711         int compat;
712         
713         /* convert caller data to struct */
714         scd.shi = shi;
715         scd.shr = shr;
716         
717         /* each material node has own local shaderesult, with optional copying */
718         memset(shr, 0, sizeof(ShadeResult));
719         
720         /* ensure execdata is only initialized once */
721         if (!exec) {
722                 BLI_lock_thread(LOCK_NODES);
723                 if (!ntree->execdata)
724                         ntree->execdata = ntreeShaderBeginExecTree(ntree);
725                 BLI_unlock_thread(LOCK_NODES);
726
727                 exec = ntree->execdata;
728         }
729         
730         nts = ntreeGetThreadStack(exec, shi->thread);
731         compat = ntreeExecThreadNodes(exec, nts, &scd, shi->thread);
732         ntreeReleaseThreadStack(nts);
733         
734         // \note: set material back to preserved material
735         shi->mat = mat;
736                 
737         /* better not allow negative for now */
738         if (shr->combined[0] < 0.0f) shr->combined[0] = 0.0f;
739         if (shr->combined[1] < 0.0f) shr->combined[1] = 0.0f;
740         if (shr->combined[2] < 0.0f) shr->combined[2] = 0.0f;
741         
742         /* if compat is zero, it has been using non-compatible nodes */
743         return compat;
744 }