Blender  V3.3
deg_eval_visibility.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2022 Blender Foundation. All rights reserved. */
3 
9 
10 #include "DNA_layer_types.h"
11 #include "DNA_object_types.h"
12 
13 #include "BLI_assert.h"
14 #include "BLI_stack.h"
15 
16 #include "DEG_depsgraph.h"
17 
18 #include "intern/depsgraph.h"
20 #include "intern/node/deg_node.h"
24 
25 namespace blender::deg {
26 
28 {
30 
31  Depsgraph *graph = reinterpret_cast<Depsgraph *>(depsgraph);
32  const Object *object = reinterpret_cast<const Object *>(id_node->id_cow);
33 
34  DEG_debug_print_eval(depsgraph, __func__, object->id.name, &object->id);
35 
36  const int required_flags = (graph->mode == DAG_EVAL_VIEWPORT) ? BASE_ENABLED_VIEWPORT :
38 
39  const bool is_enabled = object->base_flag & required_flags;
40 
41  if (id_node->is_enabled_on_eval != is_enabled) {
42  id_node->is_enabled_on_eval = is_enabled;
43 
44  /* Tag dependency graph for changed visibility, so that it is updated on all dependencies prior
45  * to a pass of an actual evaluation. */
47  }
48 }
49 
51 {
52  enum {
53  DEG_NODE_VISITED = (1 << 0),
54  };
55 
56  for (IDNode *id_node : graph->id_nodes) {
57  for (ComponentNode *comp_node : id_node->components.values()) {
58  comp_node->possibly_affects_visible_id = id_node->is_visible_on_build;
59  comp_node->affects_visible_id = id_node->is_visible_on_build && id_node->is_enabled_on_eval;
60 
61  /* Visibility component is always to be considered to have the same visibility as the
62  * `id_node->is_visible_on_build`. This is because the visibility is to be evaluated
63  * regardless of its current state as it might get changed due to animation. */
64  if (comp_node->type == NodeType::VISIBILITY) {
65  comp_node->affects_visible_id = id_node->is_visible_on_build;
66  }
67 
68  /* Enforce "visibility" of the synchronization component.
69  *
70  * This component is never connected to other ID nodes, and hence can not be handled in the
71  * same way as other components needed for evaluation. It is only needed for proper
72  * evaluation of the ID node it belongs to.
73  *
74  * The design is such that the synchronization is supposed to happen whenever any part of the
75  * ID changed/evaluated. Here we mark the component as "visible" so that genetic recalc flag
76  * flushing and scheduling will handle the component in a generic manner. */
77  if (comp_node->type == NodeType::SYNCHRONIZATION) {
78  comp_node->possibly_affects_visible_id = true;
79  comp_node->affects_visible_id = true;
80  }
81  }
82  }
83 
84  BLI_Stack *stack = BLI_stack_new(sizeof(OperationNode *), "DEG flush layers stack");
85 
86  for (OperationNode *op_node : graph->operations) {
87  op_node->custom_flags = 0;
88  op_node->num_links_pending = 0;
89  for (Relation *rel : op_node->outlinks) {
90  if ((rel->from->type == NodeType::OPERATION) && (rel->flag & RELATION_FLAG_CYCLIC) == 0) {
91  ++op_node->num_links_pending;
92  }
93  }
94  if (op_node->num_links_pending == 0) {
95  BLI_stack_push(stack, &op_node);
96  op_node->custom_flags |= DEG_NODE_VISITED;
97  }
98  }
99 
100  while (!BLI_stack_is_empty(stack)) {
101  OperationNode *op_node;
102  BLI_stack_pop(stack, &op_node);
103 
104  /* Flush flags to parents. */
105  for (Relation *rel : op_node->inlinks) {
106  if (rel->from->type == NodeType::OPERATION) {
107  const OperationNode *op_to = reinterpret_cast<const OperationNode *>(rel->to);
108  const ComponentNode *comp_to = op_to->owner;
109 
110  /* Ignore the synchronization target.
111  * It is always visible and should not affect on other components. */
112  if (comp_to->type == NodeType::SYNCHRONIZATION) {
113  continue;
114  }
115 
116  OperationNode *op_from = reinterpret_cast<OperationNode *>(rel->from);
117  ComponentNode *comp_from = op_from->owner;
118 
119  const bool target_possibly_affects_visible_id = comp_to->possibly_affects_visible_id;
120  const bool target_affects_visible_id = comp_to->affects_visible_id;
121 
123 
124  /* Visibility component forces all components of the current ID to be considered as
125  * affecting directly visible. */
126  if (comp_from->type == NodeType::VISIBILITY) {
127  const IDNode *id_node_from = comp_from->owner;
128  if (target_possibly_affects_visible_id) {
129  for (ComponentNode *comp_node : id_node_from->components.values()) {
130  comp_node->possibly_affects_visible_id |= target_possibly_affects_visible_id;
131  }
132  }
133  if (target_affects_visible_id) {
134  for (ComponentNode *comp_node : id_node_from->components.values()) {
135  comp_node->affects_visible_id |= target_affects_visible_id;
136  }
137  }
138  }
139  else {
140  comp_from->possibly_affects_visible_id |= target_possibly_affects_visible_id;
141  comp_from->affects_visible_id |= target_affects_visible_id;
142  }
143  }
144  }
145 
146  /* Schedule parent nodes. */
147  for (Relation *rel : op_node->inlinks) {
148  if (rel->from->type == NodeType::OPERATION) {
149  OperationNode *op_from = (OperationNode *)rel->from;
150  if ((rel->flag & RELATION_FLAG_CYCLIC) == 0) {
151  BLI_assert(op_from->num_links_pending > 0);
152  --op_from->num_links_pending;
153  }
154  if ((op_from->num_links_pending == 0) && (op_from->custom_flags & DEG_NODE_VISITED) == 0) {
155  BLI_stack_push(stack, &op_from);
156  op_from->custom_flags |= DEG_NODE_VISITED;
157  }
158  }
159  }
160  }
161  BLI_stack_free(stack);
162 
164 }
165 
167 {
169  return;
170  }
171 
173 }
174 
175 } // namespace blender::deg
#define BLI_assert(a)
Definition: BLI_assert.h:46
void BLI_stack_pop(BLI_Stack *stack, void *dst) ATTR_NONNULL()
Definition: stack.c:135
void BLI_stack_push(BLI_Stack *stack, const void *src) ATTR_NONNULL()
Definition: stack.c:129
bool BLI_stack_is_empty(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: stack.c:247
void BLI_stack_free(BLI_Stack *stack) ATTR_NONNULL()
Definition: stack.c:94
#define BLI_stack_new(esize, descr)
@ DAG_EVAL_VIEWPORT
Definition: DEG_depsgraph.h:45
void DEG_debug_print_eval(struct Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address)
@ ID_OB
Definition: DNA_ID_enums.h:47
@ BASE_ENABLED_RENDER
@ BASE_ENABLED_VIEWPORT
Object is a sort of wrapper for general info.
Depsgraph * graph
const IDNode * id_node
const Depsgraph * depsgraph
#define GS(x)
Definition: iris.c:225
void deg_evaluate_object_node_visibility(::Depsgraph *depsgraph, IDNode *id_node)
void deg_graph_flush_visibility_flags(Depsgraph *graph)
void deg_graph_flush_visibility_flags_if_needed(Depsgraph *graph)
char name[66]
Definition: DNA_ID.h:378
OperationNodes operations
Definition: depsgraph.h:120
eEvaluationMode mode
Definition: depsgraph.h:130
bool need_update_nodes_visibility
Definition: depsgraph.h:98
IDDepsNodes id_nodes
Definition: depsgraph.h:86
Map< ComponentIDKey, ComponentNode * > components
Definition: deg_node_id.h:80
Relations inlinks
Definition: deg_node.h:173
Relations outlinks
Definition: deg_node.h:174