Blender V5.0
operation.cc
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#include <limits>
6#include <memory>
7
8#include "BLI_map.hh"
9#include "BLI_string_ref.hh"
10
11#include "COM_context.hh"
13#include "COM_domain.hh"
15#include "COM_operation.hh"
17#include "COM_result.hh"
19
20namespace blender::compositor {
21
23
24Operation::~Operation() = default;
25
27{
28 evaluate_input_processors();
29
30 execute();
31
33
34 release_inputs();
35
37}
38
40{
41 return results_.lookup(identifier);
42}
43
45{
46 results_mapped_to_inputs_.add_new(identifier, result);
47}
48
50{
51 for (Result &result : results_.values()) {
52 result.free();
53 }
54}
55
57{
58 /* Default to an identity domain in case no domain input was found, most likely because all
59 * inputs are single values. */
60 Domain operation_domain = Domain::identity();
61 int current_domain_priority = std::numeric_limits<int>::max();
62
63 /* Go over the inputs and find the domain of the non single value input with the highest domain
64 * priority. */
65 for (StringRef identifier : input_descriptors_.keys()) {
66 const Result &result = get_input(identifier);
68
69 /* A single value input can't be a domain input. */
70 if (result.is_single_value() || descriptor.expects_single_value) {
71 continue;
72 }
73
74 /* An input that skips operation domain realization can't be a domain input. */
75 if (descriptor.realization_mode != InputRealizationMode::OperationDomain) {
76 continue;
77 }
78
79 /* Notice that the lower the domain priority value is, the higher the priority is, hence the
80 * less than comparison. */
81 if (descriptor.domain_priority < current_domain_priority) {
82 operation_domain = result.domain();
83 current_domain_priority = descriptor.domain_priority;
84 }
85 }
86
87 return operation_domain;
88}
89
91{
92 /* Each input processor type is added to all inputs entirely before the next type. This is done
93 * because the construction of the input processors may depend on the result of previous input
94 * processors for all inputs. For instance, the realize on domain input processor considers the
95 * value of all inputs, so previous input processors for all inputs needs to be added and
96 * evaluated first. */
97
98 for (const StringRef &identifier : results_mapped_to_inputs_.keys()) {
100 context(), get_input(identifier), get_input_descriptor(identifier));
101 add_and_evaluate_input_processor(identifier, conversion);
102 }
103
104 for (const StringRef &identifier : results_mapped_to_inputs_.keys()) {
106 context(), get_input(identifier), get_input_descriptor(identifier), compute_domain());
107 add_and_evaluate_input_processor(identifier, realize_on_domain);
108 }
109}
110
112{
113 /* Allow null inputs to facilitate construct_if_needed pattern of addition. For instance, see the
114 * implementation of the add_and_evaluate_input_processors method. */
115 if (!processor) {
116 return;
117 }
118
119 ProcessorsVector &processors = input_processors_.lookup_or_add_default(identifier);
120
121 /* Get the result that should serve as the input for the processor. This is either the result
122 * mapped to the input or the result of the last processor depending on whether this is the first
123 * processor or not. */
124 Result &result = processors.is_empty() ? get_input(identifier) : processors.last()->get_result();
125
126 /* Map the input result of the processor and add it to the processors vector. */
127 processor->map_input_to_result(&result);
128 processors.append(std::unique_ptr<SimpleOperation>(processor));
129
130 /* Switch the result mapped to the input to be the output result of the processor. */
131 switch_result_mapped_to_input(identifier, &processor->get_result());
132
133 processor->evaluate();
134}
135
137
139{
140 return *results_mapped_to_inputs_.lookup(identifier);
141}
142
144{
145 results_mapped_to_inputs_.lookup(identifier) = result;
146}
147
149{
150 results_.add_new(identifier, result);
151}
152
154{
155 input_descriptors_.add_new(identifier, descriptor);
156}
157
159{
160 return input_descriptors_.lookup(identifier);
161}
162
164{
165 return context_;
166}
167
168void Operation::evaluate_input_processors()
169{
170 if (!input_processors_added_) {
172 input_processors_added_ = true;
173 return;
174 }
175
176 for (const ProcessorsVector &processors : input_processors_.values()) {
177 for (const std::unique_ptr<SimpleOperation> &processor : processors) {
178 processor->evaluate();
179 }
180 }
181}
182
183void Operation::release_inputs()
184{
185 for (Result *result : results_mapped_to_inputs_.values()) {
186 result->release();
187 }
188}
189
190} // namespace blender::compositor
void append(const T &value)
const T & last(const int64_t n=0) const
bool is_empty() const
static SimpleOperation * construct_if_needed(Context &context, const Result &input_result, const InputDescriptor &input_descriptor)
static Domain identity()
Definition domain.cc:36
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
static SimpleOperation * construct_if_needed(Context &context, const Result &input_result, const InputDescriptor &input_descriptor, const Domain &operation_domain)
descriptor
Vector< std::unique_ptr< SimpleOperation > > ProcessorsVector