Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/nodes/composite/node_composite_tree.c')
-rw-r--r--source/blender/nodes/composite/node_composite_tree.c551
1 files changed, 48 insertions, 503 deletions
diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c
index 03462738d58..841dde3302b 100644
--- a/source/blender/nodes/composite/node_composite_tree.c
+++ b/source/blender/nodes/composite/node_composite_tree.c
@@ -44,6 +44,7 @@
#include "BKE_animsys.h"
#include "BKE_colortools.h"
+#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_main.h"
@@ -51,7 +52,6 @@
#include "BKE_tracking.h"
#include "node_common.h"
-#include "node_exec.h"
#include "node_util.h"
#include "PIL_time.h"
@@ -65,14 +65,17 @@
#include "COM_compositor.h"
#endif
-static void foreach_nodetree(Main *main, void *calldata, bNodeTreeCallback func)
+static void composite_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from)
{
- Scene *sce;
- for (sce= main->scene.first; sce; sce= sce->id.next) {
- if (sce->nodetree) {
- func(calldata, &sce->id, sce->nodetree);
- }
- }
+ Scene *scene = CTX_data_scene(C);
+
+ *r_from = NULL;
+ *r_id = &scene->id;
+ *r_ntree = scene->nodetree;
+
+ /* update output sockets based on available layers */
+ ntreeCompositForceHidden(scene->nodetree, scene);
+
}
static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCallback func)
@@ -86,6 +89,7 @@ static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCa
func(calldata, NODE_CLASS_MATTE, N_("Matte"));
func(calldata, NODE_CLASS_DISTORT, N_("Distort"));
func(calldata, NODE_CLASS_GROUP, N_("Group"));
+ func(calldata, NODE_CLASS_INTERFACE, N_("Interface"));
func(calldata, NODE_CLASS_LAYOUT, N_("Layout"));
}
@@ -95,9 +99,6 @@ static void free_node_cache(bNodeTree *UNUSED(ntree), bNode *node)
for (sock= node->outputs.first; sock; sock= sock->next) {
if (sock->cache) {
-#ifdef WITH_COMPOSITOR_LEGACY
- free_compbuf(sock->cache);
-#endif
sock->cache= NULL;
}
}
@@ -106,33 +107,17 @@ static void free_node_cache(bNodeTree *UNUSED(ntree), bNode *node)
static void free_cache(bNodeTree *ntree)
{
bNode *node;
- for (node= ntree->nodes.first; node; node= node->next)
+ for (node = ntree->nodes.first; node; node = node->next)
free_node_cache(ntree, node);
}
-static void update_node(bNodeTree *ntree, bNode *node)
-{
- bNodeSocket *sock;
-
- for (sock= node->outputs.first; sock; sock= sock->next) {
- if (sock->cache) {
- //free_compbuf(sock->cache);
- //sock->cache= NULL;
- }
- }
- node->need_exec= 1;
- /* individual node update call */
- if (node->typeinfo->updatefunc)
- node->typeinfo->updatefunc(ntree, node);
-}
-
/* local tree then owns all compbufs */
static void localize(bNodeTree *localtree, bNodeTree *ntree)
{
bNode *node, *node_next;
bNodeSocket *sock;
- for (node= ntree->nodes.first; node; node= node->next) {
+ for (node = ntree->nodes.first; node; node = node->next) {
/* ensure new user input gets handled ok */
node->need_exec= 0;
node->new_node->original = node;
@@ -149,28 +134,15 @@ static void localize(bNodeTree *localtree, bNodeTree *ntree)
}
}
- /* copy over the preview buffers to update graduatly */
- if (node->preview) {
- bNodePreview *preview = MEM_callocN(sizeof(bNodePreview), "Preview");
- preview->pad = node->preview->pad;
- preview->xsize = node->preview->xsize;
- preview->ysize = node->preview->ysize;
- preview->rect = MEM_dupallocN(node->preview->rect);
- node->new_node->preview = preview;
- }
-
for (sock= node->outputs.first; sock; sock= sock->next) {
sock->new_sock->cache= sock->cache;
-#ifdef WITH_COMPOSITOR_LEGACY
- compbuf_set_node(sock->new_sock->cache, node->new_node);
-#endif
sock->cache= NULL;
sock->new_sock->new_sock= sock;
}
}
/* replace muted nodes and reroute nodes by internal links */
- for (node= localtree->nodes.first; node; node= node_next) {
+ for (node = localtree->nodes.first; node; node = node_next) {
node_next = node->next;
if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) {
@@ -192,22 +164,7 @@ static void localize(bNodeTree *localtree, bNodeTree *ntree)
static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
{
- bNode *lnode;
-
- /* move over the compbufs and previews */
- for (lnode= localtree->nodes.first; lnode; lnode= lnode->next) {
- if ( (lnode->exec & NODE_READY) && !(lnode->exec & NODE_SKIPPED) ) {
- if (ntreeNodeExists(ntree, lnode->new_node)) {
-
- if (lnode->preview && lnode->preview->rect) {
- nodeFreePreview(lnode->new_node);
- lnode->new_node->preview= lnode->preview;
- lnode->preview= NULL;
- }
-
- }
- }
- }
+ BKE_node_preview_sync_tree(ntree, localtree);
}
static void local_merge(bNodeTree *localtree, bNodeTree *ntree)
@@ -216,6 +173,8 @@ static void local_merge(bNodeTree *localtree, bNodeTree *ntree)
bNodeSocket *lsock;
/* move over the compbufs and previews */
+ BKE_node_preview_merge_tree(ntree, localtree, true);
+
for (lnode= localtree->nodes.first; lnode; lnode= lnode->next) {
if (ntreeNodeExists(ntree, lnode->new_node)) {
if (ELEM(lnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
@@ -239,9 +198,6 @@ static void local_merge(bNodeTree *localtree, bNodeTree *ntree)
for (lsock= lnode->outputs.first; lsock; lsock= lsock->next) {
if (ntreeOutputExists(lnode->new_node, lsock->new_sock)) {
lsock->new_sock->cache= lsock->cache;
-#ifdef WITH_COMPOSITOR_LEGACY
- compbuf_set_node(lsock->new_sock->cache, lnode->new_node);
-#endif
lsock->cache= NULL;
lsock->new_sock= NULL;
}
@@ -255,442 +211,38 @@ static void update(bNodeTree *ntree)
ntreeSetOutput(ntree);
ntree_update_reroute_nodes(ntree);
-}
-
-bNodeTreeType ntreeType_Composite = {
- /* type */ NTREE_COMPOSIT,
- /* idname */ "NTCompositing Nodetree",
-
- /* node_types */ { NULL, NULL },
-
- /* free_cache */ free_cache,
- /* free_node_cache */ free_node_cache,
- /* foreach_nodetree */ foreach_nodetree,
- /* foreach_nodeclass */ foreach_nodeclass,
- /* localize */ localize,
- /* local_sync */ local_sync,
- /* local_merge */ local_merge,
- /* update */ update,
- /* update_node */ update_node,
- /* validate_link */ NULL,
- /* update_internal_links */ node_update_internal_links_default
-};
-
-
-/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
- * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
- */
-struct bNodeTreeExec *ntreeCompositBeginExecTree(bNodeTree *ntree, int use_tree_data)
-{
- bNodeTreeExec *exec;
- bNode *node;
- bNodeSocket *sock;
-
- if (use_tree_data) {
- /* XXX hack: prevent exec data from being generated twice.
- * this should be handled by the renderer!
- */
- if (ntree->execdata)
- return ntree->execdata;
- }
-
- /* ensures only a single output node is enabled */
- ntreeSetOutput(ntree);
-
- exec = ntree_exec_begin(ntree);
-
- for (node= exec->nodetree->nodes.first; node; node= node->next) {
- /* initialize needed for groups */
- node->exec= 0;
-
- for (sock= node->outputs.first; sock; sock= sock->next) {
- bNodeStack *ns= node_get_socket_stack(exec->stack, sock);
- if (ns && sock->cache) {
- ns->data= sock->cache;
- sock->cache= NULL;
- }
- }
- /* cannot initialize them while using in threads */
- if (ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT)) {
- curvemapping_initialize(node->storage);
- if (node->type==CMP_NODE_CURVE_RGB)
- curvemapping_premultiply(node->storage, 0);
- }
- }
-
- if (use_tree_data) {
- /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
- * which only store the ntree pointer. Should be fixed at some point!
- */
- ntree->execdata = exec;
- }
-
- return exec;
-}
-
-/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
- * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
- */
-void ntreeCompositEndExecTree(bNodeTreeExec *exec, int use_tree_data)
-{
- if (exec) {
- bNodeTree *ntree= exec->nodetree;
- bNode *node;
- bNodeStack *ns;
-
- for (node= exec->nodetree->nodes.first; node; node= node->next) {
- bNodeSocket *sock;
-
- for (sock= node->outputs.first; sock; sock= sock->next) {
- ns = node_get_socket_stack(exec->stack, sock);
- if (ns && ns->data) {
- sock->cache= ns->data;
- ns->data= NULL;
- }
- }
- if (node->type==CMP_NODE_CURVE_RGB)
- curvemapping_premultiply(node->storage, 1);
-
- node->need_exec= 0;
- }
-
- ntree_exec_end(exec);
-
- if (use_tree_data) {
- /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
- ntree->execdata = NULL;
- }
- }
-}
-
-#ifdef WITH_COMPOSITOR
-#ifdef WITH_COMPOSITOR_LEGACY
-
-/* ***************************** threaded version for execute composite nodes ************* */
-/* these are nodes without input, only giving values */
-/* or nodes with only value inputs */
-static int node_only_value(bNode *node)
-{
- bNodeSocket *sock;
-
- if (ELEM3(node->type, CMP_NODE_TIME, CMP_NODE_VALUE, CMP_NODE_RGB))
- return 1;
-
- /* doing this for all node types goes wrong. memory free errors */
- if (node->inputs.first && node->type==CMP_NODE_MAP_VALUE) {
- int retval= 1;
- for (sock= node->inputs.first; sock; sock= sock->next) {
- if (sock->link)
- retval &= node_only_value(sock->link->fromnode);
- }
- return retval;
- }
- return 0;
-}
-
-/* not changing info, for thread callback */
-typedef struct ThreadData {
- bNodeStack *stack;
- RenderData *rd;
-} ThreadData;
-
-static void *exec_composite_node(void *nodeexec_v)
-{
- bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */
- bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */
- bNodeExec *nodeexec= nodeexec_v;
- bNode *node= nodeexec->node;
- ThreadData *thd= (ThreadData *)node->threaddata;
-
- node_get_stack(node, thd->stack, nsin, nsout);
-
- if (node->typeinfo->execfunc)
- node->typeinfo->execfunc(thd->rd, node, nsin, nsout);
- else if (node->typeinfo->newexecfunc)
- node->typeinfo->newexecfunc(thd->rd, 0, node, nodeexec->data, nsin, nsout);
-
- node->exec |= NODE_READY;
- return NULL;
-}
-
-/* return total of executable nodes, for timecursor */
-static int setExecutableNodes(bNodeTreeExec *exec, ThreadData *thd)
-{
- bNodeTree *ntree = exec->nodetree;
- bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */
- bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */
- bNodeExec *nodeexec;
- bNode *node;
- bNodeSocket *sock;
- int n, totnode= 0, group_edit= 0;
-
- /* if we are in group edit, viewer nodes get skipped when group has viewer */
- for (node= ntree->nodes.first; node; node= node->next)
- if (node->type==NODE_GROUP && (node->flag & NODE_GROUP_EDIT))
- if (ntreeHasType((bNodeTree *)node->id, CMP_NODE_VIEWER))
- group_edit= 1;
-
- /* NB: using the exec data list here to have valid dependency sort */
- for (n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
- int a;
- node = nodeexec->node;
-
- node_get_stack(node, exec->stack, nsin, nsout);
-
- /* test the outputs */
- /* skip value-only nodes (should be in type!) */
- if (!node_only_value(node)) {
- for (a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
- if (nsout[a]->data==NULL && nsout[a]->hasoutput) {
- node->need_exec= 1;
- break;
- }
- }
- }
-
- /* test the inputs */
- for (a=0, sock= node->inputs.first; sock; sock= sock->next, a++) {
- /* skip viewer nodes in bg render or group edit */
- if ( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) && (G.background || group_edit))
- node->need_exec= 0;
- /* is sock in use? */
- else if (sock->link) {
- bNodeLink *link= sock->link;
-
- /* this is the test for a cyclic case */
- if (link->fromnode==NULL || link->tonode==NULL);
- else if (link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF) {
- if (link->fromnode->need_exec) {
- node->need_exec= 1;
- break;
- }
- }
- else {
- node->need_exec= 0;
- printf("Node %s skipped, cyclic dependency\n", node->name);
- }
- }
- }
-
- if (node->need_exec) {
-
- /* free output buffers */
- for (a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
- if (nsout[a]->data) {
- free_compbuf(nsout[a]->data);
- nsout[a]->data= NULL;
- }
- }
- totnode++;
- /* printf("node needs exec %s\n", node->name); */
-
- /* tag for getExecutableNode() */
- node->exec= 0;
- }
- else {
- /* tag for getExecutableNode() */
- node->exec= NODE_READY|NODE_FINISHED|NODE_SKIPPED;
-
- }
- }
-
- /* last step: set the stack values for only-value nodes */
- /* just does all now, compared to a full buffer exec this is nothing */
- if (totnode) {
- for (n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
- node = nodeexec->node;
- if (node->need_exec==0 && node_only_value(node)) {
- if (node->typeinfo->execfunc) {
- node_get_stack(node, exec->stack, nsin, nsout);
- node->typeinfo->execfunc(thd->rd, node, nsin, nsout);
- }
- }
- }
- }
-
- return totnode;
-}
-
-/* while executing tree, free buffers from nodes that are not needed anymore */
-static void freeExecutableNode(bNodeTreeExec *exec)
-{
- /* node outputs can be freed when:
- * - not a render result or image node
- * - when node outputs go to nodes all being set NODE_FINISHED
- */
- bNodeTree *ntree = exec->nodetree;
- bNodeExec *nodeexec;
- bNode *node;
- bNodeSocket *sock;
- int n;
-
- /* set exec flag for finished nodes that might need freed */
- for (node= ntree->nodes.first; node; node= node->next) {
- if (node->type!=CMP_NODE_R_LAYERS)
- if (node->exec & NODE_FINISHED)
- node->exec |= NODE_FREEBUFS;
- }
- /* clear this flag for input links that are not done yet.
- * Using the exec data for valid dependency sort.
- */
- for (n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
- node = nodeexec->node;
- if ((node->exec & NODE_FINISHED)==0) {
- for (sock= node->inputs.first; sock; sock= sock->next)
- if (sock->link)
- sock->link->fromnode->exec &= ~NODE_FREEBUFS;
- }
- }
- /* now we can free buffers */
- for (node= ntree->nodes.first; node; node= node->next) {
- if (node->exec & NODE_FREEBUFS) {
- for (sock= node->outputs.first; sock; sock= sock->next) {
- bNodeStack *ns= node_get_socket_stack(exec->stack, sock);
- if (ns && ns->data) {
- free_compbuf(ns->data);
- ns->data= NULL;
- // printf("freed buf node %s\n", node->name);
- }
- }
- }
- }
-}
-
-static bNodeExec *getExecutableNode(bNodeTreeExec *exec)
-{
- bNodeExec *nodeexec;
- bNodeSocket *sock;
- int n;
- for (n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
- if (nodeexec->node->exec==0) {
- /* input sockets should be ready */
- for (sock= nodeexec->node->inputs.first; sock; sock= sock->next) {
- if (sock->link && sock->link->fromnode)
- if ((sock->link->fromnode->exec & NODE_READY)==0)
- break;
- }
- if (sock==NULL)
- return nodeexec;
- }
+ if (ntree->update & NTREE_UPDATE_NODES) {
+ /* clean up preview cache, in case nodes have been removed */
+ BKE_node_preview_remove_unused(ntree);
}
- return NULL;
}
-/* check if texture nodes need exec or end */
-static void ntree_composite_texnode(bNodeTree *ntree, int init)
-{
- bNode *node;
-
- for (node= ntree->nodes.first; node; node= node->next) {
- if (node->type==CMP_NODE_TEXTURE && node->id) {
- Tex *tex= (Tex *)node->id;
- if (tex->nodetree && tex->use_nodes) {
- /* has internal flag to detect it only does it once */
- if (init) {
- if (!tex->nodetree->execdata)
- tex->nodetree->execdata = ntreeTexBeginExecTree(tex->nodetree, 1);
- }
- else
- ntreeTexEndExecTree(tex->nodetree->execdata, 1);
- tex->nodetree->execdata = NULL;
- }
- }
- }
-
-}
+bNodeTreeType *ntreeType_Composite;
-/* optimized tree execute test for compositing */
-static void ntreeCompositExecTreeOld(bNodeTree *ntree, RenderData *rd, int do_preview)
+void register_node_tree_type_cmp(void)
{
- bNodeExec *nodeexec;
- bNode *node;
- ListBase threads;
- ThreadData thdata;
- int totnode, curnode, rendering = TRUE, n;
- bNodeTreeExec *exec = ntree->execdata;
-
- if (do_preview)
- ntreeInitPreview(ntree, 0, 0);
-
- if (!ntree->execdata) {
- /* XXX this is the top-level tree, so we use the ntree->execdata pointer. */
- exec = ntreeCompositBeginExecTree(ntree, 1);
- }
- ntree_composite_texnode(ntree, 1);
-
- /* prevent unlucky accidents */
- if (G.background)
- rd->scemode &= ~R_COMP_CROP;
-
- /* setup callerdata for thread callback */
- thdata.rd= rd;
- thdata.stack= exec->stack;
-
- /* fixed seed, for example noise texture */
- BLI_srandom(rd->cfra);
-
- /* sets need_exec tags in nodes */
- curnode = totnode= setExecutableNodes(exec, &thdata);
-
- BLI_init_threads(&threads, exec_composite_node, rd->threads);
-
- while (rendering) {
-
- if (BLI_available_threads(&threads)) {
- nodeexec= getExecutableNode(exec);
- if (nodeexec) {
- node = nodeexec->node;
- if (ntree->progress && totnode)
- ntree->progress(ntree->prh, (1.0f - curnode/(float)totnode));
- if (ntree->stats_draw) {
- char str[128];
- BLI_snprintf(str, sizeof(str), "Compositing %d %s", curnode, node->name);
- ntree->stats_draw(ntree->sdh, str);
- }
- curnode--;
-
- node->threaddata = &thdata;
- node->exec= NODE_PROCESSING;
- BLI_insert_thread(&threads, nodeexec);
- }
- else
- PIL_sleep_ms(50);
- }
- else
- PIL_sleep_ms(50);
-
- rendering= 0;
- /* test for ESC */
- if (ntree->test_break && ntree->test_break(ntree->tbh)) {
- for (node= ntree->nodes.first; node; node= node->next)
- node->exec |= NODE_READY;
- }
-
- /* check for ready ones, and if we need to continue */
- for (n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
- node = nodeexec->node;
- if (node->exec & NODE_READY) {
- if ((node->exec & NODE_FINISHED)==0) {
- BLI_remove_thread(&threads, nodeexec); /* this waits for running thread to finish btw */
- node->exec |= NODE_FINISHED;
-
- /* freeing unused buffers */
- if (rd->scemode & R_COMP_FREE)
- freeExecutableNode(exec);
- }
- }
- else rendering= 1;
- }
- }
-
- BLI_end_threads(&threads);
-
- /* XXX top-level tree uses the ntree->execdata pointer */
- ntreeCompositEndExecTree(exec, 1);
+ bNodeTreeType *tt = ntreeType_Composite = MEM_callocN(sizeof(bNodeTreeType), "compositor node tree type");
+
+ tt->type = NTREE_COMPOSIT;
+ strcpy(tt->idname, "CompositorNodeTree");
+ strcpy(tt->ui_name, "Compositing");
+ tt->ui_icon = 0; /* defined in drawnode.c */
+ strcpy(tt->ui_description, "");
+
+ tt->free_cache = free_cache;
+ tt->free_node_cache = free_node_cache;
+ tt->foreach_nodeclass = foreach_nodeclass;
+ tt->localize = localize;
+ tt->local_sync = local_sync;
+ tt->local_merge = local_merge;
+ tt->update = update;
+ tt->get_from_context = composite_get_from_context;
+
+ tt->ext.srna = &RNA_CompositorNodeTree;
+
+ ntreeTypeAdd(tt);
}
-#endif /* WITH_COMPOSITOR_LEGACY */
-#endif /* WITH_COMPOSITOR */
void *COM_linker_hack = NULL;
@@ -699,16 +251,7 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int rendering, int
const ColorManagedDisplaySettings *display_settings)
{
#ifdef WITH_COMPOSITOR
-#ifdef WITH_COMPOSITOR_LEGACY
- if (G.debug_value == 200)
- {
- ntreeCompositExecTreeOld(ntree, rd, do_preview);
- }
- else
-#endif
- {
- COM_execute(rd, ntree, rendering, view_settings, display_settings);
- }
+ COM_execute(rd, ntree, rendering, view_settings, display_settings);
#else
(void)ntree, (void)rd, (void)rendering, (void)do_preview;
(void)view_settings, (void)display_settings;
@@ -827,7 +370,8 @@ static int node_animation_properties(bNodeTree *ntree, bNode *node)
lb = RNA_struct_type_properties(ptr.type);
for (link = lb->first; link; link = link->next) {
- int driven, len = 1, index;
+ int len = 1, index;
+ bool driven;
prop = (PropertyRNA *)link;
if (RNA_property_array_check(prop))
@@ -843,7 +387,8 @@ static int node_animation_properties(bNodeTree *ntree, bNode *node)
/* now check node sockets */
for (sock = node->inputs.first; sock; sock = sock->next) {
- int driven, len = 1, index;
+ int len = 1, index;
+ bool driven;
RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
prop = RNA_struct_find_property(&ptr, "default_value");