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