Blender V4.3
COM_operation.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
7#include <memory>
8#include <string>
9
10#include "BLI_map.hh"
11#include "BLI_string_ref.hh"
12#include "BLI_vector.hh"
13
14#include "COM_context.hh"
15#include "COM_domain.hh"
17#include "COM_result.hh"
18#include "COM_texture_pool.hh"
19
21
22class SimpleOperation;
23
24/* A type representing a vector of simple operations that store the input processors for a
25 * particular input. */
27
28/* ------------------------------------------------------------------------------------------------
29 * Operation
30 *
31 * The operation is the basic unit of the compositor. The evaluator compiles the compositor node
32 * tree into an ordered stream of operations which are then executed in order during evaluation.
33 * The operation class can be sub-classed to implement a new operation. Operations have a number of
34 * inputs and outputs that are declared during construction and are identified by string
35 * identifiers. Inputs are declared by calling declare_input_descriptor providing an appropriate
36 * descriptor. Those inputs are mapped to the results computed by other operations whose outputs
37 * are linked to the inputs. Such mappings are established by the compiler during compilation by
38 * calling the map_input_to_result method. Outputs are populated by calling the populate_result
39 * method, providing a result of an appropriate type. Upon execution, the operation allocates a
40 * result for each of its outputs and computes their value based on its inputs and options.
41 *
42 * Each input may have one or more input processors, which are simple operations that process the
43 * inputs before the operation is executed, see the discussion in COM_simple_operation.hh for more
44 * information. And thus the effective input of the operation is the result of the last input
45 * processor if one exists. Input processors are added and evaluated by calling the
46 * add_and_evaluate_input_processors method, which provides a default implementation that does
47 * things like implicit conversion, domain realization, and more. This default implementation can,
48 * however, be overridden, extended, or removed. Once the input processors are added and evaluated
49 * for the first time, they are stored in the operation and future evaluations can evaluate them
50 * directly without having to add them again.
51 *
52 * The operation is evaluated by calling the evaluate method, which first adds the input processors
53 * if they weren't added already and evaluates them, then it resets the results of the operation,
54 * then it calls the execute method of the operation, and finally it releases the results mapped to
55 * the inputs to declare that they are no longer needed. */
56class Operation {
57 private:
58 /* A reference to the compositor context. This member references the same object in all
59 * operations but is included in the class for convenience. */
60 Context &context_;
61 /* A mapping between each output of the operation identified by its identifier and the result for
62 * that output. A result for each output of the operation should be constructed and added to the
63 * map during operation construction by calling the populate_result method. The results should be
64 * allocated and their contents should be computed in the execute method. */
66 /* A mapping between each input of the operation identified by its identifier and its input
67 * descriptor. Those descriptors should be declared during operation construction by calling the
68 * declare_input_descriptor method. */
69 Map<std::string, InputDescriptor> input_descriptors_;
70 /* A mapping between each input of the operation identified by its identifier and a pointer to
71 * the computed result providing its data. The mapped result is either one that was computed by
72 * another operation or one that was internally computed in the operation by the last input
73 * processor for that input. It is the responsibility of the evaluator to map the inputs to their
74 * linked results before evaluating the operation by calling the map_input_to_result method. */
75 Map<StringRef, Result *> results_mapped_to_inputs_;
76 /* A mapping between each input of the operation identified by its identifier and an ordered list
77 * of simple operations to process that input. This is initialized the first time the input
78 * processors are evaluated by calling the add_and_evaluate_input_processors method. Further
79 * evaluations will evaluate the processors directly without the need to add them again. The
80 * input_processors_added_ member indicates whether the processors were already added and can be
81 * evaluated directly or need to be added and evaluated. */
82 Map<StringRef, ProcessorsVector> input_processors_;
83 /* True if the input processors were already added and can be evaluated directly. False if the
84 * input processors are not yet added and needs to be added. */
85 bool input_processors_added_ = false;
86
87 public:
88 Operation(Context &context);
89
90 virtual ~Operation();
91
92 /* Evaluate the operation by:
93 * 1. Evaluating the input processors.
94 * 2. Resetting the results of the operation.
95 * 3. Calling the execute method of the operation.
96 * 4. Releasing the results mapped to the inputs. */
97 virtual void evaluate();
98
99 /* Get a reference to the output result identified by the given identifier. */
100 Result &get_result(StringRef identifier);
101
102 /* Map the input identified by the given identifier to the result providing its data. See
103 * results_mapped_to_inputs_ for more details. This should be called by the evaluator to
104 * establish links between different operations. */
105 void map_input_to_result(StringRef identifier, Result *result);
106
107 protected:
108 /* Compute the operation domain of this operation. By default, this implements a default logic
109 * that infers the operation domain from the inputs, which may be overridden for a different
110 * logic. See the discussion in COM_domain.hh for the inference logic and more information. */
111 virtual Domain compute_domain();
112
113 /* Add and evaluate any needed input processors, which essentially just involves calling the
114 * add_and_evaluate_input_processor method with the needed processors. This is called before
115 * executing the operation to prepare its inputs. The class defines a default implementation
116 * which adds typically needed processors, but derived classes can override the method to have
117 * a different implementation, extend the implementation, or remove it entirely. */
119
120 /* Given the identifier of an input of the operation and a processor operation:
121 * - Add the given processor to the list of input processors for the input.
122 * - Map the input of the processor to be the result of the last input processor or the result
123 * mapped to the input if no previous processors exists.
124 * - Switch the result mapped to the input to be the output result of the processor.
125 * - Evaluate the processor. */
127
128 /* This method should allocate the operation results, execute the operation, and compute the
129 * output results. */
130 virtual void execute() = 0;
131
132 /* Compute and set a preview of the operation if needed. This method defaults to an empty
133 * implementation and should be implemented by operations which can have previews. */
134 virtual void compute_preview();
135
136 /* Get a reference to the result connected to the input identified by the given identifier. */
137 Result &get_input(StringRef identifier) const;
138
139 /* Switch the result mapped to the input identified by the given identifier with the given
140 * result. */
141 void switch_result_mapped_to_input(StringRef identifier, Result *result);
142
143 /* Add the given result to the results_ map identified by the given output identifier. This
144 * should be called during operation construction for all outputs. The provided result shouldn't
145 * be allocated or initialized, this will happen later during execution. */
146 void populate_result(StringRef identifier, Result result);
147
148 /* Declare the descriptor of the input identified by the given identifier to be the given
149 * descriptor. Adds the given descriptor to the input_descriptors_ map identified by the given
150 * input identifier. This should be called during operation constructor for all inputs. */
152
153 /* Get a reference to the descriptor of the input identified by the given identified. */
155
156 /* Returns a reference to the compositor context. */
157 Context &context() const;
158
159 /* Returns a reference to the texture pool of the compositor context. */
160 TexturePool &texture_pool() const;
161
162 private:
163 /* Evaluate the input processors. If the input processors were already added they will be
164 * evaluated directly. Otherwise, the input processors will be added and evaluated. */
165 void evaluate_input_processors();
166
167 /* Resets the results of the operation. See the reset method in the Result class for more
168 * information. */
169 void reset_results();
170
171 /* Release the results that are mapped to the inputs of the operation. This is called after the
172 * evaluation of the operation to declare that the results are no longer needed by this
173 * operation. */
174 void release_inputs();
175
176 /* Release the results that were allocated in the execute method but are not actually needed.
177 * This can be the case if the execute method allocated a dummy texture for an unneeded result,
178 * see the description of Result::allocate_texture() for more information. This is called after
179 * the evaluation of the operation. */
180 void release_unneeded_results();
181};
182
183} // namespace blender::realtime_compositor
Result & get_input(StringRef identifier) const
Definition operation.cc:144
void switch_result_mapped_to_input(StringRef identifier, Result *result)
Definition operation.cc:149
Result & get_result(StringRef identifier)
Definition operation.cc:46
InputDescriptor & get_input_descriptor(StringRef identifier)
Definition operation.cc:164
void populate_result(StringRef identifier, Result result)
Definition operation.cc:154
void add_and_evaluate_input_processor(StringRef identifier, SimpleOperation *processor)
Definition operation.cc:117
void map_input_to_result(StringRef identifier, Result *result)
Definition operation.cc:51
void declare_input_descriptor(StringRef identifier, InputDescriptor descriptor)
Definition operation.cc:159
descriptor