This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/compositor/realtime_compositor/COM_operation.hh
Omar Emara 79953d5482 Realtime Compositor: Fix clang tidy warnings
Fix a number of warnings reported by Clang Tidy in the realtime
compositor's code.

Differential Revision: https://developer.blender.org/D15654

Reviewed By: Clement Foucault
2022-08-10 13:04:36 +02:00

176 lines
9.3 KiB
C++

/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include <memory>
#include <string>
#include "BLI_map.hh"
#include "BLI_string_ref.hh"
#include "BLI_vector.hh"
#include "COM_context.hh"
#include "COM_domain.hh"
#include "COM_input_descriptor.hh"
#include "COM_result.hh"
#include "COM_static_shader_manager.hh"
#include "COM_texture_pool.hh"
namespace blender::realtime_compositor {
class SimpleOperation;
/* A type representing a vector of simple operations that store the input processors for a
* particular input. */
using ProcessorsVector = Vector<std::unique_ptr<SimpleOperation>>;
/* ------------------------------------------------------------------------------------------------
* Operation
*
* The operation is the basic unit of the compositor. The evaluator compiles the compositor node
* tree into an ordered stream of operations which are then executed in order during evaluation.
* The operation class can be sub-classed to implement a new operation. Operations have a number of
* inputs and outputs that are declared during construction and are identified by string
* identifiers. Inputs are declared by calling declare_input_descriptor providing an appropriate
* descriptor. Those inputs are mapped to the results computed by other operations whose outputs
* are linked to the inputs. Such mappings are established by the compiler during compilation by
* calling the map_input_to_result method. Outputs are populated by calling the populate_result
* method, providing a result of an appropriate type. Upon execution, the operation allocates a
* result for each of its outputs and computes their value based on its inputs and options.
*
* Each input may have one or more input processors, which are simple operations that process the
* inputs before the operation is executed, see the discussion in COM_simple_operation.hh for more
* information. And thus the effective input of the operation is the result of the last input
* processor if one exists. Input processors are added and evaluated by calling the
* add_and_evaluate_input_processors method, which provides a default implementation that does
* things like implicit conversion, domain realization, and more. This default implementation can,
* however, be overridden, extended, or removed. Once the input processors are added and evaluated
* for the first time, they are stored in the operation and future evaluations can evaluate them
* directly without having to add them again.
*
* The operation is evaluated by calling the evaluate method, which first adds the input processors
* if they weren't added already and evaluates them, then it resets the results of the operation,
* then it calls the execute method of the operation, and finally it releases the results mapped to
* the inputs to declare that they are no longer needed. */
class Operation {
private:
/* A reference to the compositor context. This member references the same object in all
* operations but is included in the class for convenience. */
Context &context_;
/* A mapping between each output of the operation identified by its identifier and the result for
* that output. A result for each output of the operation should be constructed and added to the
* map during operation construction by calling the populate_result method. The results should be
* allocated and their contents should be computed in the execute method. */
Map<std::string, Result> results_;
/* A mapping between each input of the operation identified by its identifier and its input
* descriptor. Those descriptors should be declared during operation construction by calling the
* declare_input_descriptor method. */
Map<std::string, InputDescriptor> input_descriptors_;
/* A mapping between each input of the operation identified by its identifier and a pointer to
* the computed result providing its data. The mapped result is either one that was computed by
* another operation or one that was internally computed in the operation by the last input
* processor for that input. It is the responsibility of the evaluator to map the inputs to their
* linked results before evaluating the operation by calling the map_input_to_result method. */
Map<StringRef, Result *> results_mapped_to_inputs_;
/* A mapping between each input of the operation identified by its identifier and an ordered list
* of simple operations to process that input. This is initialized the first time the input
* processors are evaluated by calling the add_and_evaluate_input_processors method. Further
* evaluations will evaluate the processors directly without the need to add them again. The
* input_processors_added_ member indicates whether the processors were already added and can be
* evaluated directly or need to be added and evaluated. */
Map<StringRef, ProcessorsVector> input_processors_;
/* True if the input processors were already added and can be evaluated directly. False if the
* input processors are not yet added and needs to be added. */
bool input_processors_added_ = false;
public:
Operation(Context &context);
virtual ~Operation();
/* Evaluate the operation by:
* 1. Evaluating the input processors.
* 2. Resetting the results of the operation.
* 3. Calling the execute method of the operation.
* 4. Releasing the results mapped to the inputs. */
void evaluate();
/* Get a reference to the output result identified by the given identifier. */
Result &get_result(StringRef identifier);
/* Map the input identified by the given identifier to the result providing its data. See
* results_mapped_to_inputs_ for more details. This should be called by the evaluator to
* establish links between different operations. */
void map_input_to_result(StringRef identifier, Result *result);
protected:
/* Compute the operation domain of this operation. By default, this implements a default logic
* that infers the operation domain from the inputs, which may be overridden for a different
* logic. See the discussion in COM_domain.hh for the inference logic and more information. */
virtual Domain compute_domain();
/* Add and evaluate any needed input processors, which essentially just involves calling the
* add_and_evaluate_input_processor method with the needed processors. This is called before
* executing the operation to prepare its inputs. The class defines a default implementation
* which adds typically needed processors, but derived classes can override the method to have
* a different implementation, extend the implementation, or remove it entirely. */
virtual void add_and_evaluate_input_processors();
/* Given the identifier of an input of the operation and a processor operation:
* - Add the given processor to the list of input processors for the input.
* - Map the input of the processor to be the result of the last input processor or the result
* mapped to the input if no previous processors exists.
* - Switch the result mapped to the input to be the output result of the processor.
* - Evaluate the processor. */
void add_and_evaluate_input_processor(StringRef identifier, SimpleOperation *processor);
/* This method should allocate the operation results, execute the operation, and compute the
* output results. */
virtual void execute() = 0;
/* Get a reference to the result connected to the input identified by the given identifier. */
Result &get_input(StringRef identifier) const;
/* Switch the result mapped to the input identified by the given identifier with the given
* result. */
void switch_result_mapped_to_input(StringRef identifier, Result *result);
/* Add the given result to the results_ map identified by the given output identifier. This
* should be called during operation construction for all outputs. The provided result shouldn't
* be allocated or initialized, this will happen later during execution. */
void populate_result(StringRef identifier, Result result);
/* Declare the descriptor of the input identified by the given identifier to be the given
* descriptor. Adds the given descriptor to the input_descriptors_ map identified by the given
* input identifier. This should be called during operation constructor for all inputs. */
void declare_input_descriptor(StringRef identifier, InputDescriptor descriptor);
/* Get a reference to the descriptor of the input identified by the given identified. */
InputDescriptor &get_input_descriptor(StringRef identifier);
/* Returns a reference to the compositor context. */
Context &context();
/* Returns a reference to the texture pool of the compositor context. */
TexturePool &texture_pool() const;
/* Returns a reference to the shader manager of the compositor context. */
StaticShaderManager &shader_manager() const;
private:
/* Evaluate the input processors. If the input processors were already added they will be
* evaluated directly. Otherwise, the input processors will be added and evaluated. */
void evaluate_input_processors();
/* Resets the results of the operation. See the reset method in the Result class for more
* information. */
void reset_results();
/* Release the results that are mapped to the inputs of the operation. This is called after the
* evaluation of the operation to declare that the results are no longer needed by this
* operation. */
void release_inputs();
};
} // namespace blender::realtime_compositor