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