1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2007 Blender Foundation.
17  * All rights reserved.
18  */
19 
20 /** \file
21  * \ingroup nodes
22  */
23 
24 #include <stdio.h>
25 
26 #include "DNA_color_types.h"
27 #include "DNA_node_types.h"
28 #include "DNA_scene_types.h"
29 
30 #include "BLT_translation.h"
31 
32 #include "BKE_context.h"
33 #include "BKE_global.h"
34 #include "BKE_main.h"
35 #include "BKE_node.h"
36 #include "BKE_tracking.h"
37 
38 #include "node_common.h"
39 #include "node_util.h"
40 
41 #include "RNA_access.h"
42 
43 #include "NOD_composite.h"
44 #include "node_composite_util.h"
45 
46 #ifdef WITH_COMPOSITOR
47 #  include "COM_compositor.h"
48 #endif
49 
composite_get_from_context(const bContext * C,bNodeTreeType * UNUSED (treetype),bNodeTree ** r_ntree,ID ** r_id,ID ** r_from)50 static void composite_get_from_context(const bContext *C,
51                                        bNodeTreeType *UNUSED(treetype),
52                                        bNodeTree **r_ntree,
53                                        ID **r_id,
54                                        ID **r_from)
55 {
56   Scene *scene = CTX_data_scene(C);
57 
58   *r_from = NULL;
59   *r_id = &scene->id;
60   *r_ntree = scene->nodetree;
61 }
62 
foreach_nodeclass(Scene * UNUSED (scene),void * calldata,bNodeClassCallback func)63 static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCallback func)
64 {
65   func(calldata, NODE_CLASS_INPUT, N_("Input"));
66   func(calldata, NODE_CLASS_OUTPUT, N_("Output"));
67   func(calldata, NODE_CLASS_OP_COLOR, N_("Color"));
68   func(calldata, NODE_CLASS_OP_VECTOR, N_("Vector"));
69   func(calldata, NODE_CLASS_OP_FILTER, N_("Filter"));
70   func(calldata, NODE_CLASS_CONVERTOR, N_("Convertor"));
71   func(calldata, NODE_CLASS_MATTE, N_("Matte"));
72   func(calldata, NODE_CLASS_DISTORT, N_("Distort"));
73   func(calldata, NODE_CLASS_GROUP, N_("Group"));
74   func(calldata, NODE_CLASS_INTERFACE, N_("Interface"));
75   func(calldata, NODE_CLASS_LAYOUT, N_("Layout"));
76 }
77 
free_node_cache(bNodeTree * UNUSED (ntree),bNode * node)78 static void free_node_cache(bNodeTree *UNUSED(ntree), bNode *node)
79 {
80   bNodeSocket *sock;
81 
82   for (sock = node->outputs.first; sock; sock = sock->next) {
83     if (sock->cache) {
84       sock->cache = NULL;
85     }
86   }
87 }
88 
free_cache(bNodeTree * ntree)89 static void free_cache(bNodeTree *ntree)
90 {
91   bNode *node;
92   for (node = ntree->nodes.first; node; node = node->next) {
93     free_node_cache(ntree, node);
94   }
95 }
96 
97 /* local tree then owns all compbufs */
localize(bNodeTree * localtree,bNodeTree * ntree)98 static void localize(bNodeTree *localtree, bNodeTree *ntree)
99 {
100 
101   bNode *node = ntree->nodes.first;
102   bNode *local_node = localtree->nodes.first;
103   while (node != NULL) {
104 
105     /* Ensure new user input gets handled ok. */
106     node->need_exec = 0;
107     local_node->original = node;
108 
109     /* move over the compbufs */
110     /* right after ntreeCopyTree() oldsock pointers are valid */
111 
112     if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
113       if (node->id) {
114         if (node->flag & NODE_DO_OUTPUT) {
115           local_node->id = (ID *)node->id;
116         }
117         else {
118           local_node->id = NULL;
119         }
120       }
121     }
122 
123     bNodeSocket *output_sock = node->outputs.first;
124     bNodeSocket *local_output_sock = local_node->outputs.first;
125     while (output_sock != NULL) {
126       local_output_sock->cache = output_sock->cache;
127       output_sock->cache = NULL;
128       /* This is actually link to original: someone was just lazy enough and tried to save few
129        * bytes in the cost of readability. */
130       local_output_sock->new_sock = output_sock;
131 
132       output_sock = output_sock->next;
133       local_output_sock = local_output_sock->next;
134     }
135 
136     node = node->next;
137     local_node = local_node->next;
138   }
139 }
140 
local_sync(bNodeTree * localtree,bNodeTree * ntree)141 static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
142 {
143   BKE_node_preview_sync_tree(ntree, localtree);
144 }
145 
local_merge(Main * bmain,bNodeTree * localtree,bNodeTree * ntree)146 static void local_merge(Main *bmain, bNodeTree *localtree, bNodeTree *ntree)
147 {
148   bNode *lnode;
149   bNodeSocket *lsock;
150 
151   /* move over the compbufs and previews */
152   BKE_node_preview_merge_tree(ntree, localtree, true);
153 
154   for (lnode = localtree->nodes.first; lnode; lnode = lnode->next) {
155     if (ntreeNodeExists(ntree, lnode->new_node)) {
156       if (ELEM(lnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
157         if (lnode->id && (lnode->flag & NODE_DO_OUTPUT)) {
158           /* image_merge does sanity check for pointers */
159           BKE_image_merge(bmain, (Image *)lnode->new_node->id, (Image *)lnode->id);
160         }
161       }
162       else if (lnode->type == CMP_NODE_MOVIEDISTORTION) {
163         /* special case for distortion node: distortion context is allocating in exec function
164          * and to achieve much better performance on further calls this context should be
165          * copied back to original node */
166         if (lnode->storage) {
167           if (lnode->new_node->storage) {
168             BKE_tracking_distortion_free(lnode->new_node->storage);
169           }
170 
171           lnode->new_node->storage = BKE_tracking_distortion_copy(lnode->storage);
172         }
173       }
174 
175       for (lsock = lnode->outputs.first; lsock; lsock = lsock->next) {
176         if (ntreeOutputExists(lnode->new_node, lsock->new_sock)) {
177           lsock->new_sock->cache = lsock->cache;
178           lsock->cache = NULL;
179           lsock->new_sock = NULL;
180         }
181       }
182     }
183   }
184 }
185 
update(bNodeTree * ntree)186 static void update(bNodeTree *ntree)
187 {
188   ntreeSetOutput(ntree);
189 
190   ntree_update_reroute_nodes(ntree);
191 
192   if (ntree->update & NTREE_UPDATE_NODES) {
193     /* clean up preview cache, in case nodes have been removed */
194     BKE_node_preview_remove_unused(ntree);
195   }
196 }
197 
composite_node_add_init(bNodeTree * UNUSED (bnodetree),bNode * bnode)198 static void composite_node_add_init(bNodeTree *UNUSED(bnodetree), bNode *bnode)
199 {
200   /* Composite node will only show previews for input classes
201    * by default, other will be hidden
202    * but can be made visible with the show_preview option */
203   if (bnode->typeinfo->nclass != NODE_CLASS_INPUT) {
204     bnode->flag &= ~NODE_PREVIEW;
205   }
206 }
207 
208 bNodeTreeType *ntreeType_Composite;
209 
register_node_tree_type_cmp(void)210 void register_node_tree_type_cmp(void)
211 {
212   bNodeTreeType *tt = ntreeType_Composite = MEM_callocN(sizeof(bNodeTreeType),
213                                                         "compositor node tree type");
214 
215   tt->type = NTREE_COMPOSIT;
216   strcpy(tt->idname, "CompositorNodeTree");
217   strcpy(tt->ui_name, N_("Compositor"));
218   tt->ui_icon = 0; /* defined in drawnode.c */
219   strcpy(tt->ui_description, N_("Compositing nodes"));
220 
221   tt->free_cache = free_cache;
222   tt->free_node_cache = free_node_cache;
223   tt->foreach_nodeclass = foreach_nodeclass;
224   tt->localize = localize;
225   tt->local_sync = local_sync;
226   tt->local_merge = local_merge;
227   tt->update = update;
228   tt->get_from_context = composite_get_from_context;
229   tt->node_add_init = composite_node_add_init;
230 
231   tt->rna_ext.srna = &RNA_CompositorNodeTree;
232 
233   ntreeTypeAdd(tt);
234 }
235 
236 extern void *COM_linker_hack; /* Quiet warning. */
237 void *COM_linker_hack = NULL;
238 
ntreeCompositExecTree(Scene * scene,bNodeTree * ntree,RenderData * rd,int rendering,int do_preview,const ColorManagedViewSettings * view_settings,const ColorManagedDisplaySettings * display_settings,const char * view_name)239 void ntreeCompositExecTree(Scene *scene,
240                            bNodeTree *ntree,
241                            RenderData *rd,
242                            int rendering,
243                            int do_preview,
244                            const ColorManagedViewSettings *view_settings,
245                            const ColorManagedDisplaySettings *display_settings,
246                            const char *view_name)
247 {
248 #ifdef WITH_COMPOSITOR
249   COM_execute(rd, scene, ntree, rendering, view_settings, display_settings, view_name);
250 #else
251   UNUSED_VARS(scene, ntree, rd, rendering, view_settings, display_settings, view_name);
252 #endif
253 
254   UNUSED_VARS(do_preview);
255 }
256 
257 /* *********************************************** */
258 
259 /* Update the outputs of the render layer nodes.
260  * Since the outputs depend on the render engine, this part is a bit complex:
261  * - ntreeCompositUpdateRLayers is called and loops over all render layer nodes.
262  * - Each render layer node calls the update function of the
263  *   render engine that's used for its scene.
264  * - The render engine calls RE_engine_register_pass for each pass.
265  * - RE_engine_register_pass calls ntreeCompositRegisterPass,.
266  *   which calls node_cmp_rlayers_register_pass for every render layer node.
267  */
ntreeCompositUpdateRLayers(bNodeTree * ntree)268 void ntreeCompositUpdateRLayers(bNodeTree *ntree)
269 {
270   bNode *node;
271 
272   if (ntree == NULL) {
273     return;
274   }
275 
276   for (node = ntree->nodes.first; node; node = node->next) {
277     if (node->type == CMP_NODE_R_LAYERS) {
278       node_cmp_rlayers_outputs(ntree, node);
279     }
280   }
281 }
282 
ntreeCompositRegisterPass(bNodeTree * ntree,Scene * scene,ViewLayer * view_layer,const char * name,eNodeSocketDatatype type)283 void ntreeCompositRegisterPass(bNodeTree *ntree,
284                                Scene *scene,
285                                ViewLayer *view_layer,
286                                const char *name,
287                                eNodeSocketDatatype type)
288 {
289   bNode *node;
290 
291   if (ntree == NULL) {
292     return;
293   }
294 
295   for (node = ntree->nodes.first; node; node = node->next) {
296     if (node->type == CMP_NODE_R_LAYERS) {
297       node_cmp_rlayers_register_pass(ntree, node, scene, view_layer, name, type);
298     }
299   }
300 }
301 
302 /* called from render pipeline, to tag render input and output */
303 /* need to do all scenes, to prevent errors when you re-render 1 scene */
ntreeCompositTagRender(Scene * scene)304 void ntreeCompositTagRender(Scene *scene)
305 {
306   /* XXX Think using G_MAIN here is valid, since you want to update current file's scene nodes,
307    * not the ones in temp main generated for rendering?
308    * This is still rather weak though,
309    * ideally render struct would store own main AND original G_MAIN. */
310 
311   for (Scene *sce_iter = G_MAIN->scenes.first; sce_iter; sce_iter = sce_iter->id.next) {
312     if (sce_iter->nodetree) {
313       bNode *node;
314 
315       for (node = sce_iter->nodetree->nodes.first; node; node = node->next) {
316         if (node->id == (ID *)scene || node->type == CMP_NODE_COMPOSITE) {
317           nodeUpdate(sce_iter->nodetree, node);
318         }
319         else if (node->type == CMP_NODE_TEXTURE) /* uses scene sizex/sizey */ {
320           nodeUpdate(sce_iter->nodetree, node);
321         }
322       }
323     }
324   }
325 }
326 
327 /* XXX after render animation system gets a refresh, this call allows composite to end clean */
ntreeCompositClearTags(bNodeTree * ntree)328 void ntreeCompositClearTags(bNodeTree *ntree)
329 {
330   bNode *node;
331 
332   if (ntree == NULL) {
333     return;
334   }
335 
336   for (node = ntree->nodes.first; node; node = node->next) {
337     node->need_exec = 0;
338     if (node->type == NODE_GROUP) {
339       ntreeCompositClearTags((bNodeTree *)node->id);
340     }
341   }
342 }
343