Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/compositor/intern/COM_NodeOperationBuilder.cpp')
-rw-r--r--source/blender/compositor/intern/COM_NodeOperationBuilder.cpp953
1 files changed, 482 insertions, 471 deletions
diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp
index 37a1d7c005f..0f331a25ed9 100644
--- a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp
+++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp
@@ -39,12 +39,10 @@ extern "C" {
#include "COM_NodeOperationBuilder.h" /* own include */
-NodeOperationBuilder::NodeOperationBuilder(const CompositorContext *context, bNodeTree *b_nodetree) :
- m_context(context),
- m_current_node(NULL),
- m_active_viewer(NULL)
+NodeOperationBuilder::NodeOperationBuilder(const CompositorContext *context, bNodeTree *b_nodetree)
+ : m_context(context), m_current_node(NULL), m_active_viewer(NULL)
{
- m_graph.from_bNodeTree(*context, b_nodetree);
+ m_graph.from_bNodeTree(*context, b_nodetree);
}
NodeOperationBuilder::~NodeOperationBuilder()
@@ -53,208 +51,215 @@ NodeOperationBuilder::~NodeOperationBuilder()
void NodeOperationBuilder::convertToOperations(ExecutionSystem *system)
{
- /* interface handle for nodes */
- NodeConverter converter(this);
+ /* interface handle for nodes */
+ NodeConverter converter(this);
- for (int index = 0; index < m_graph.nodes().size(); index++) {
- Node *node = (Node *)m_graph.nodes()[index];
+ for (int index = 0; index < m_graph.nodes().size(); index++) {
+ Node *node = (Node *)m_graph.nodes()[index];
- m_current_node = node;
+ m_current_node = node;
- DebugInfo::node_to_operations(node);
- node->convertToOperations(converter, *m_context);
- }
+ DebugInfo::node_to_operations(node);
+ node->convertToOperations(converter, *m_context);
+ }
- m_current_node = NULL;
+ m_current_node = NULL;
- /* The input map constructed by nodes maps operation inputs to node inputs.
- * Inverting yields a map of node inputs to all connected operation inputs,
- * so multiple operations can use the same node input.
- */
- OpInputInverseMap inverse_input_map;
- for (InputSocketMap::const_iterator it = m_input_map.begin(); it != m_input_map.end(); ++it)
- inverse_input_map[it->second].push_back(it->first);
+ /* The input map constructed by nodes maps operation inputs to node inputs.
+ * Inverting yields a map of node inputs to all connected operation inputs,
+ * so multiple operations can use the same node input.
+ */
+ OpInputInverseMap inverse_input_map;
+ for (InputSocketMap::const_iterator it = m_input_map.begin(); it != m_input_map.end(); ++it)
+ inverse_input_map[it->second].push_back(it->first);
- for (NodeGraph::Links::const_iterator it = m_graph.links().begin(); it != m_graph.links().end(); ++it) {
- const NodeGraph::Link &link = *it;
- NodeOutput *from = link.getFromSocket();
- NodeInput *to = link.getToSocket();
+ for (NodeGraph::Links::const_iterator it = m_graph.links().begin(); it != m_graph.links().end();
+ ++it) {
+ const NodeGraph::Link &link = *it;
+ NodeOutput *from = link.getFromSocket();
+ NodeInput *to = link.getToSocket();
- NodeOperationOutput *op_from = find_operation_output(m_output_map, from);
- const OpInputs &op_to_list = find_operation_inputs(inverse_input_map, to);
- if (!op_from || op_to_list.empty()) {
- /* XXX allow this? error/debug message? */
- //BLI_assert(false);
- /* XXX note: this can happen with certain nodes (e.g. OutputFile)
- * which only generate operations in certain circumstances (rendering)
- * just let this pass silently for now ...
- */
- continue;
- }
+ NodeOperationOutput *op_from = find_operation_output(m_output_map, from);
+ const OpInputs &op_to_list = find_operation_inputs(inverse_input_map, to);
+ if (!op_from || op_to_list.empty()) {
+ /* XXX allow this? error/debug message? */
+ //BLI_assert(false);
+ /* XXX note: this can happen with certain nodes (e.g. OutputFile)
+ * which only generate operations in certain circumstances (rendering)
+ * just let this pass silently for now ...
+ */
+ continue;
+ }
- for (OpInputs::const_iterator it = op_to_list.begin(); it != op_to_list.end(); ++it) {
- NodeOperationInput *op_to = *it;
- addLink(op_from, op_to);
- }
- }
+ for (OpInputs::const_iterator it = op_to_list.begin(); it != op_to_list.end(); ++it) {
+ NodeOperationInput *op_to = *it;
+ addLink(op_from, op_to);
+ }
+ }
- add_operation_input_constants();
+ add_operation_input_constants();
- resolve_proxies();
+ resolve_proxies();
- add_datatype_conversions();
+ add_datatype_conversions();
- determineResolutions();
+ determineResolutions();
- /* surround complex ops with read/write buffer */
- add_complex_operation_buffers();
+ /* surround complex ops with read/write buffer */
+ add_complex_operation_buffers();
- /* links not available from here on */
- /* XXX make m_links a local variable to avoid confusion! */
- m_links.clear();
+ /* links not available from here on */
+ /* XXX make m_links a local variable to avoid confusion! */
+ m_links.clear();
- prune_operations();
+ prune_operations();
- /* ensure topological (link-based) order of nodes */
- /*sort_operations();*/ /* not needed yet */
+ /* ensure topological (link-based) order of nodes */
+ /*sort_operations();*/ /* not needed yet */
- /* create execution groups */
- group_operations();
+ /* create execution groups */
+ group_operations();
- /* transfer resulting operations to the system */
- system->set_operations(m_operations, m_groups);
+ /* transfer resulting operations to the system */
+ system->set_operations(m_operations, m_groups);
}
void NodeOperationBuilder::addOperation(NodeOperation *operation)
{
- m_operations.push_back(operation);
+ m_operations.push_back(operation);
}
-void NodeOperationBuilder::mapInputSocket(NodeInput *node_socket, NodeOperationInput *operation_socket)
+void NodeOperationBuilder::mapInputSocket(NodeInput *node_socket,
+ NodeOperationInput *operation_socket)
{
- BLI_assert(m_current_node);
- BLI_assert(node_socket->getNode() == m_current_node);
+ BLI_assert(m_current_node);
+ BLI_assert(node_socket->getNode() == m_current_node);
- /* note: this maps operation sockets to node sockets.
- * for resolving links the map will be inverted first in convertToOperations,
- * to get a list of links for each node input socket.
- */
- m_input_map[operation_socket] = node_socket;
+ /* note: this maps operation sockets to node sockets.
+ * for resolving links the map will be inverted first in convertToOperations,
+ * to get a list of links for each node input socket.
+ */
+ m_input_map[operation_socket] = node_socket;
}
-void NodeOperationBuilder::mapOutputSocket(NodeOutput *node_socket, NodeOperationOutput *operation_socket)
+void NodeOperationBuilder::mapOutputSocket(NodeOutput *node_socket,
+ NodeOperationOutput *operation_socket)
{
- BLI_assert(m_current_node);
- BLI_assert(node_socket->getNode() == m_current_node);
+ BLI_assert(m_current_node);
+ BLI_assert(node_socket->getNode() == m_current_node);
- m_output_map[node_socket] = operation_socket;
+ m_output_map[node_socket] = operation_socket;
}
void NodeOperationBuilder::addLink(NodeOperationOutput *from, NodeOperationInput *to)
{
- if (to->isConnected())
- return;
+ if (to->isConnected())
+ return;
- m_links.push_back(Link(from, to));
+ m_links.push_back(Link(from, to));
- /* register with the input */
- to->setLink(from);
+ /* register with the input */
+ to->setLink(from);
}
void NodeOperationBuilder::removeInputLink(NodeOperationInput *to)
{
- for (Links::iterator it = m_links.begin(); it != m_links.end(); ++it) {
- Link &link = *it;
- if (link.to() == to) {
- /* unregister with the input */
- to->setLink(NULL);
+ for (Links::iterator it = m_links.begin(); it != m_links.end(); ++it) {
+ Link &link = *it;
+ if (link.to() == to) {
+ /* unregister with the input */
+ to->setLink(NULL);
- m_links.erase(it);
- return;
- }
- }
+ m_links.erase(it);
+ return;
+ }
+ }
}
-NodeInput *NodeOperationBuilder::find_node_input(const InputSocketMap &map, NodeOperationInput *op_input)
+NodeInput *NodeOperationBuilder::find_node_input(const InputSocketMap &map,
+ NodeOperationInput *op_input)
{
- InputSocketMap::const_iterator it = map.find(op_input);
- return (it != map.end() ? it->second : NULL);
+ InputSocketMap::const_iterator it = map.find(op_input);
+ return (it != map.end() ? it->second : NULL);
}
-const NodeOperationBuilder::OpInputs &NodeOperationBuilder::find_operation_inputs(const OpInputInverseMap &map, NodeInput *node_input)
+const NodeOperationBuilder::OpInputs &NodeOperationBuilder::find_operation_inputs(
+ const OpInputInverseMap &map, NodeInput *node_input)
{
- static const OpInputs empty_list;
- OpInputInverseMap::const_iterator it = map.find(node_input);
- return (it != map.end() ? it->second : empty_list);
+ static const OpInputs empty_list;
+ OpInputInverseMap::const_iterator it = map.find(node_input);
+ return (it != map.end() ? it->second : empty_list);
}
-NodeOperationOutput *NodeOperationBuilder::find_operation_output(const OutputSocketMap &map, NodeOutput *node_output)
+NodeOperationOutput *NodeOperationBuilder::find_operation_output(const OutputSocketMap &map,
+ NodeOutput *node_output)
{
- OutputSocketMap::const_iterator it = map.find(node_output);
- return (it != map.end() ? it->second : NULL);
+ OutputSocketMap::const_iterator it = map.find(node_output);
+ return (it != map.end() ? it->second : NULL);
}
PreviewOperation *NodeOperationBuilder::make_preview_operation() const
{
- BLI_assert(m_current_node);
+ BLI_assert(m_current_node);
- if (!(m_current_node->getbNode()->flag & NODE_PREVIEW))
- return NULL;
- /* previews only in the active group */
- if (!m_current_node->isInActiveGroup())
- return NULL;
- /* do not calculate previews of hidden nodes */
- if (m_current_node->getbNode()->flag & NODE_HIDDEN)
- return NULL;
+ if (!(m_current_node->getbNode()->flag & NODE_PREVIEW))
+ return NULL;
+ /* previews only in the active group */
+ if (!m_current_node->isInActiveGroup())
+ return NULL;
+ /* do not calculate previews of hidden nodes */
+ if (m_current_node->getbNode()->flag & NODE_HIDDEN)
+ return NULL;
- bNodeInstanceHash *previews = m_context->getPreviewHash();
- if (previews) {
- PreviewOperation *operation = new PreviewOperation(m_context->getViewSettings(), m_context->getDisplaySettings());
- operation->setbNodeTree(m_context->getbNodeTree());
- operation->verifyPreview(previews, m_current_node->getInstanceKey());
- return operation;
- }
+ bNodeInstanceHash *previews = m_context->getPreviewHash();
+ if (previews) {
+ PreviewOperation *operation = new PreviewOperation(m_context->getViewSettings(),
+ m_context->getDisplaySettings());
+ operation->setbNodeTree(m_context->getbNodeTree());
+ operation->verifyPreview(previews, m_current_node->getInstanceKey());
+ return operation;
+ }
- return NULL;
+ return NULL;
}
void NodeOperationBuilder::addPreview(NodeOperationOutput *output)
{
- PreviewOperation *operation = make_preview_operation();
- if (operation) {
- addOperation(operation);
+ PreviewOperation *operation = make_preview_operation();
+ if (operation) {
+ addOperation(operation);
- addLink(output, operation->getInputSocket(0));
- }
+ addLink(output, operation->getInputSocket(0));
+ }
}
void NodeOperationBuilder::addNodeInputPreview(NodeInput *input)
{
- PreviewOperation *operation = make_preview_operation();
- if (operation) {
- addOperation(operation);
+ PreviewOperation *operation = make_preview_operation();
+ if (operation) {
+ addOperation(operation);
- mapInputSocket(input, operation->getInputSocket(0));
- }
+ mapInputSocket(input, operation->getInputSocket(0));
+ }
}
void NodeOperationBuilder::registerViewer(ViewerOperation *viewer)
{
- if (m_active_viewer) {
- if (m_current_node->isInActiveGroup()) {
- /* deactivate previous viewer */
- m_active_viewer->setActive(false);
+ if (m_active_viewer) {
+ if (m_current_node->isInActiveGroup()) {
+ /* deactivate previous viewer */
+ m_active_viewer->setActive(false);
- m_active_viewer = viewer;
- viewer->setActive(true);
- }
- }
- else {
- if (m_current_node->getbNodeTree() == m_context->getbNodeTree()) {
- m_active_viewer = viewer;
- viewer->setActive(true);
- }
- }
+ m_active_viewer = viewer;
+ viewer->setActive(true);
+ }
+ }
+ else {
+ if (m_current_node->getbNodeTree() == m_context->getbNodeTree()) {
+ m_active_viewer = viewer;
+ viewer->setActive(true);
+ }
+ }
}
/****************************
@@ -263,430 +268,436 @@ void NodeOperationBuilder::registerViewer(ViewerOperation *viewer)
void NodeOperationBuilder::add_datatype_conversions()
{
- Links convert_links;
- for (Links::const_iterator it = m_links.begin(); it != m_links.end(); ++it) {
- const Link &link = *it;
+ Links convert_links;
+ for (Links::const_iterator it = m_links.begin(); it != m_links.end(); ++it) {
+ const Link &link = *it;
- /* proxy operations can skip data type conversion */
- NodeOperation *from_op = &link.from()->getOperation();
- NodeOperation *to_op = &link.to()->getOperation();
- if (!(from_op->useDatatypeConversion() || to_op->useDatatypeConversion()))
- continue;
+ /* proxy operations can skip data type conversion */
+ NodeOperation *from_op = &link.from()->getOperation();
+ NodeOperation *to_op = &link.to()->getOperation();
+ if (!(from_op->useDatatypeConversion() || to_op->useDatatypeConversion()))
+ continue;
- if (link.from()->getDataType() != link.to()->getDataType())
- convert_links.push_back(link);
- }
- for (Links::const_iterator it = convert_links.begin(); it != convert_links.end(); ++it) {
- const Link &link = *it;
- NodeOperation *converter = Converter::convertDataType(link.from(), link.to());
- if (converter) {
- addOperation(converter);
+ if (link.from()->getDataType() != link.to()->getDataType())
+ convert_links.push_back(link);
+ }
+ for (Links::const_iterator it = convert_links.begin(); it != convert_links.end(); ++it) {
+ const Link &link = *it;
+ NodeOperation *converter = Converter::convertDataType(link.from(), link.to());
+ if (converter) {
+ addOperation(converter);
- removeInputLink(link.to());
- addLink(link.from(), converter->getInputSocket(0));
- addLink(converter->getOutputSocket(0), link.to());
- }
- }
+ removeInputLink(link.to());
+ addLink(link.from(), converter->getInputSocket(0));
+ addLink(converter->getOutputSocket(0), link.to());
+ }
+ }
}
void NodeOperationBuilder::add_operation_input_constants()
{
- /* Note: unconnected inputs cached first to avoid modifying
- * m_operations while iterating over it
- */
- typedef std::vector<NodeOperationInput*> Inputs;
- Inputs pending_inputs;
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
- NodeOperation *op = *it;
- for (int k = 0; k < op->getNumberOfInputSockets(); ++k) {
- NodeOperationInput *input = op->getInputSocket(k);
- if (!input->isConnected())
- pending_inputs.push_back(input);
- }
- }
- for (Inputs::const_iterator it = pending_inputs.begin(); it != pending_inputs.end(); ++it) {
- NodeOperationInput *input = *it;
- add_input_constant_value(input, find_node_input(m_input_map, input));
- }
-}
-
-void NodeOperationBuilder::add_input_constant_value(NodeOperationInput *input, NodeInput *node_input)
-{
- switch (input->getDataType()) {
- case COM_DT_VALUE: {
- float value;
- if (node_input && node_input->getbNodeSocket())
- value = node_input->getEditorValueFloat();
- else
- value = 0.0f;
-
- SetValueOperation *op = new SetValueOperation();
- op->setValue(value);
- addOperation(op);
- addLink(op->getOutputSocket(), input);
- break;
- }
- case COM_DT_COLOR: {
- float value[4];
- if (node_input && node_input->getbNodeSocket())
- node_input->getEditorValueColor(value);
- else
- zero_v4(value);
-
- SetColorOperation *op = new SetColorOperation();
- op->setChannels(value);
- addOperation(op);
- addLink(op->getOutputSocket(), input);
- break;
- }
- case COM_DT_VECTOR: {
- float value[3];
- if (node_input && node_input->getbNodeSocket())
- node_input->getEditorValueVector(value);
- else
- zero_v3(value);
-
- SetVectorOperation *op = new SetVectorOperation();
- op->setVector(value);
- addOperation(op);
- addLink(op->getOutputSocket(), input);
- break;
- }
- }
+ /* Note: unconnected inputs cached first to avoid modifying
+ * m_operations while iterating over it
+ */
+ typedef std::vector<NodeOperationInput *> Inputs;
+ Inputs pending_inputs;
+ for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
+ NodeOperation *op = *it;
+ for (int k = 0; k < op->getNumberOfInputSockets(); ++k) {
+ NodeOperationInput *input = op->getInputSocket(k);
+ if (!input->isConnected())
+ pending_inputs.push_back(input);
+ }
+ }
+ for (Inputs::const_iterator it = pending_inputs.begin(); it != pending_inputs.end(); ++it) {
+ NodeOperationInput *input = *it;
+ add_input_constant_value(input, find_node_input(m_input_map, input));
+ }
+}
+
+void NodeOperationBuilder::add_input_constant_value(NodeOperationInput *input,
+ NodeInput *node_input)
+{
+ switch (input->getDataType()) {
+ case COM_DT_VALUE: {
+ float value;
+ if (node_input && node_input->getbNodeSocket())
+ value = node_input->getEditorValueFloat();
+ else
+ value = 0.0f;
+
+ SetValueOperation *op = new SetValueOperation();
+ op->setValue(value);
+ addOperation(op);
+ addLink(op->getOutputSocket(), input);
+ break;
+ }
+ case COM_DT_COLOR: {
+ float value[4];
+ if (node_input && node_input->getbNodeSocket())
+ node_input->getEditorValueColor(value);
+ else
+ zero_v4(value);
+
+ SetColorOperation *op = new SetColorOperation();
+ op->setChannels(value);
+ addOperation(op);
+ addLink(op->getOutputSocket(), input);
+ break;
+ }
+ case COM_DT_VECTOR: {
+ float value[3];
+ if (node_input && node_input->getbNodeSocket())
+ node_input->getEditorValueVector(value);
+ else
+ zero_v3(value);
+
+ SetVectorOperation *op = new SetVectorOperation();
+ op->setVector(value);
+ addOperation(op);
+ addLink(op->getOutputSocket(), input);
+ break;
+ }
+ }
}
void NodeOperationBuilder::resolve_proxies()
{
- Links proxy_links;
- for (Links::const_iterator it = m_links.begin(); it != m_links.end(); ++it) {
- const Link &link = *it;
- /* don't replace links from proxy to proxy, since we may need them for replacing others! */
- if (link.from()->getOperation().isProxyOperation() &&
- !link.to()->getOperation().isProxyOperation())
- {
- proxy_links.push_back(link);
- }
- }
-
- for (Links::const_iterator it = proxy_links.begin(); it != proxy_links.end(); ++it) {
- const Link &link = *it;
-
- NodeOperationInput *to = link.to();
- NodeOperationOutput *from = link.from();
- do {
- /* walk upstream bypassing the proxy operation */
- from = from->getOperation().getInputSocket(0)->getLink();
- } while (from && from->getOperation().isProxyOperation());
-
- removeInputLink(to);
- /* we may not have a final proxy input link,
- * in that case it just gets dropped
- */
- if (from)
- addLink(from, to);
- }
+ Links proxy_links;
+ for (Links::const_iterator it = m_links.begin(); it != m_links.end(); ++it) {
+ const Link &link = *it;
+ /* don't replace links from proxy to proxy, since we may need them for replacing others! */
+ if (link.from()->getOperation().isProxyOperation() &&
+ !link.to()->getOperation().isProxyOperation()) {
+ proxy_links.push_back(link);
+ }
+ }
+
+ for (Links::const_iterator it = proxy_links.begin(); it != proxy_links.end(); ++it) {
+ const Link &link = *it;
+
+ NodeOperationInput *to = link.to();
+ NodeOperationOutput *from = link.from();
+ do {
+ /* walk upstream bypassing the proxy operation */
+ from = from->getOperation().getInputSocket(0)->getLink();
+ } while (from && from->getOperation().isProxyOperation());
+
+ removeInputLink(to);
+ /* we may not have a final proxy input link,
+ * in that case it just gets dropped
+ */
+ if (from)
+ addLink(from, to);
+ }
}
void NodeOperationBuilder::determineResolutions()
{
- /* determine all resolutions of the operations (Width/Height) */
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
- NodeOperation *op = *it;
-
- if (op->isOutputOperation(m_context->isRendering()) && !op->isPreviewOperation()) {
- unsigned int resolution[2] = {0, 0};
- unsigned int preferredResolution[2] = {0, 0};
- op->determineResolution(resolution, preferredResolution);
- op->setResolution(resolution);
- }
- }
-
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
- NodeOperation *op = *it;
-
- if (op->isOutputOperation(m_context->isRendering()) && op->isPreviewOperation()) {
- unsigned int resolution[2] = {0, 0};
- unsigned int preferredResolution[2] = {0, 0};
- op->determineResolution(resolution, preferredResolution);
- op->setResolution(resolution);
- }
- }
-
- /* add convert resolution operations when needed */
- {
- Links convert_links;
- for (Links::const_iterator it = m_links.begin(); it != m_links.end(); ++it) {
- const Link &link = *it;
-
- if (link.to()->getResizeMode() != COM_SC_NO_RESIZE) {
- NodeOperation &from_op = link.from()->getOperation();
- NodeOperation &to_op = link.to()->getOperation();
- if (from_op.getWidth() != to_op.getWidth() || from_op.getHeight() != to_op.getHeight())
- convert_links.push_back(link);
- }
- }
- for (Links::const_iterator it = convert_links.begin(); it != convert_links.end(); ++it) {
- const Link &link = *it;
- Converter::convertResolution(*this, link.from(), link.to());
- }
- }
-}
-
-NodeOperationBuilder::OpInputs NodeOperationBuilder::cache_output_links(NodeOperationOutput *output) const
-{
- OpInputs inputs;
- for (Links::const_iterator it = m_links.begin(); it != m_links.end(); ++it) {
- const Link &link = *it;
- if (link.from() == output)
- inputs.push_back(link.to());
- }
- return inputs;
-}
-
-WriteBufferOperation *NodeOperationBuilder::find_attached_write_buffer_operation(NodeOperationOutput *output) const
-{
- for (Links::const_iterator it = m_links.begin(); it != m_links.end(); ++it) {
- const Link &link = *it;
- if (link.from() == output) {
- NodeOperation &op = link.to()->getOperation();
- if (op.isWriteBufferOperation())
- return (WriteBufferOperation *)(&op);
- }
- }
- return NULL;
+ /* determine all resolutions of the operations (Width/Height) */
+ for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
+ NodeOperation *op = *it;
+
+ if (op->isOutputOperation(m_context->isRendering()) && !op->isPreviewOperation()) {
+ unsigned int resolution[2] = {0, 0};
+ unsigned int preferredResolution[2] = {0, 0};
+ op->determineResolution(resolution, preferredResolution);
+ op->setResolution(resolution);
+ }
+ }
+
+ for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
+ NodeOperation *op = *it;
+
+ if (op->isOutputOperation(m_context->isRendering()) && op->isPreviewOperation()) {
+ unsigned int resolution[2] = {0, 0};
+ unsigned int preferredResolution[2] = {0, 0};
+ op->determineResolution(resolution, preferredResolution);
+ op->setResolution(resolution);
+ }
+ }
+
+ /* add convert resolution operations when needed */
+ {
+ Links convert_links;
+ for (Links::const_iterator it = m_links.begin(); it != m_links.end(); ++it) {
+ const Link &link = *it;
+
+ if (link.to()->getResizeMode() != COM_SC_NO_RESIZE) {
+ NodeOperation &from_op = link.from()->getOperation();
+ NodeOperation &to_op = link.to()->getOperation();
+ if (from_op.getWidth() != to_op.getWidth() || from_op.getHeight() != to_op.getHeight())
+ convert_links.push_back(link);
+ }
+ }
+ for (Links::const_iterator it = convert_links.begin(); it != convert_links.end(); ++it) {
+ const Link &link = *it;
+ Converter::convertResolution(*this, link.from(), link.to());
+ }
+ }
+}
+
+NodeOperationBuilder::OpInputs NodeOperationBuilder::cache_output_links(
+ NodeOperationOutput *output) const
+{
+ OpInputs inputs;
+ for (Links::const_iterator it = m_links.begin(); it != m_links.end(); ++it) {
+ const Link &link = *it;
+ if (link.from() == output)
+ inputs.push_back(link.to());
+ }
+ return inputs;
+}
+
+WriteBufferOperation *NodeOperationBuilder::find_attached_write_buffer_operation(
+ NodeOperationOutput *output) const
+{
+ for (Links::const_iterator it = m_links.begin(); it != m_links.end(); ++it) {
+ const Link &link = *it;
+ if (link.from() == output) {
+ NodeOperation &op = link.to()->getOperation();
+ if (op.isWriteBufferOperation())
+ return (WriteBufferOperation *)(&op);
+ }
+ }
+ return NULL;
}
void NodeOperationBuilder::add_input_buffers(NodeOperation * /*operation*/,
NodeOperationInput *input)
{
- if (!input->isConnected())
- return;
+ if (!input->isConnected())
+ return;
- NodeOperationOutput *output = input->getLink();
- if (output->getOperation().isReadBufferOperation()) {
- /* input is already buffered, no need to add another */
- return;
- }
+ NodeOperationOutput *output = input->getLink();
+ if (output->getOperation().isReadBufferOperation()) {
+ /* input is already buffered, no need to add another */
+ return;
+ }
- /* this link will be replaced below */
- removeInputLink(input);
+ /* this link will be replaced below */
+ removeInputLink(input);
- /* check of other end already has write operation, otherwise add a new one */
- WriteBufferOperation *writeoperation = find_attached_write_buffer_operation(output);
- if (!writeoperation) {
- writeoperation = new WriteBufferOperation(output->getDataType());
- writeoperation->setbNodeTree(m_context->getbNodeTree());
- addOperation(writeoperation);
+ /* check of other end already has write operation, otherwise add a new one */
+ WriteBufferOperation *writeoperation = find_attached_write_buffer_operation(output);
+ if (!writeoperation) {
+ writeoperation = new WriteBufferOperation(output->getDataType());
+ writeoperation->setbNodeTree(m_context->getbNodeTree());
+ addOperation(writeoperation);
- addLink(output, writeoperation->getInputSocket(0));
+ addLink(output, writeoperation->getInputSocket(0));
- writeoperation->readResolutionFromInputSocket();
- }
+ writeoperation->readResolutionFromInputSocket();
+ }
- /* add readbuffer op for the input */
- ReadBufferOperation *readoperation = new ReadBufferOperation(output->getDataType());
- readoperation->setMemoryProxy(writeoperation->getMemoryProxy());
- this->addOperation(readoperation);
+ /* add readbuffer op for the input */
+ ReadBufferOperation *readoperation = new ReadBufferOperation(output->getDataType());
+ readoperation->setMemoryProxy(writeoperation->getMemoryProxy());
+ this->addOperation(readoperation);
- addLink(readoperation->getOutputSocket(), input);
+ addLink(readoperation->getOutputSocket(), input);
- readoperation->readResolutionFromWriteBuffer();
+ readoperation->readResolutionFromWriteBuffer();
}
-void NodeOperationBuilder::add_output_buffers(NodeOperation *operation, NodeOperationOutput *output)
+void NodeOperationBuilder::add_output_buffers(NodeOperation *operation,
+ NodeOperationOutput *output)
{
- /* cache connected sockets, so we can safely remove links first before replacing them */
- OpInputs targets = cache_output_links(output);
- if (targets.empty())
- return;
+ /* cache connected sockets, so we can safely remove links first before replacing them */
+ OpInputs targets = cache_output_links(output);
+ if (targets.empty())
+ return;
- WriteBufferOperation *writeOperation = NULL;
- for (OpInputs::const_iterator it = targets.begin(); it != targets.end(); ++it) {
- NodeOperationInput *target = *it;
+ WriteBufferOperation *writeOperation = NULL;
+ for (OpInputs::const_iterator it = targets.begin(); it != targets.end(); ++it) {
+ NodeOperationInput *target = *it;
- /* try to find existing write buffer operation */
- if (target->getOperation().isWriteBufferOperation()) {
- BLI_assert(writeOperation == NULL); /* there should only be one write op connected */
- writeOperation = (WriteBufferOperation *)(&target->getOperation());
- }
- else {
- /* remove all links to other nodes */
- removeInputLink(target);
- }
- }
+ /* try to find existing write buffer operation */
+ if (target->getOperation().isWriteBufferOperation()) {
+ BLI_assert(writeOperation == NULL); /* there should only be one write op connected */
+ writeOperation = (WriteBufferOperation *)(&target->getOperation());
+ }
+ else {
+ /* remove all links to other nodes */
+ removeInputLink(target);
+ }
+ }
- /* if no write buffer operation exists yet, create a new one */
- if (!writeOperation) {
- writeOperation = new WriteBufferOperation(operation->getOutputSocket()->getDataType());
- writeOperation->setbNodeTree(m_context->getbNodeTree());
- addOperation(writeOperation);
+ /* if no write buffer operation exists yet, create a new one */
+ if (!writeOperation) {
+ writeOperation = new WriteBufferOperation(operation->getOutputSocket()->getDataType());
+ writeOperation->setbNodeTree(m_context->getbNodeTree());
+ addOperation(writeOperation);
- addLink(output, writeOperation->getInputSocket(0));
- }
+ addLink(output, writeOperation->getInputSocket(0));
+ }
- writeOperation->readResolutionFromInputSocket();
+ writeOperation->readResolutionFromInputSocket();
- /* add readbuffer op for every former connected input */
- for (OpInputs::const_iterator it = targets.begin(); it != targets.end(); ++it) {
- NodeOperationInput *target = *it;
- if (&target->getOperation() == writeOperation)
- continue; /* skip existing write op links */
+ /* add readbuffer op for every former connected input */
+ for (OpInputs::const_iterator it = targets.begin(); it != targets.end(); ++it) {
+ NodeOperationInput *target = *it;
+ if (&target->getOperation() == writeOperation)
+ continue; /* skip existing write op links */
- ReadBufferOperation *readoperation = new ReadBufferOperation(operation->getOutputSocket()->getDataType());
- readoperation->setMemoryProxy(writeOperation->getMemoryProxy());
- addOperation(readoperation);
+ ReadBufferOperation *readoperation = new ReadBufferOperation(
+ operation->getOutputSocket()->getDataType());
+ readoperation->setMemoryProxy(writeOperation->getMemoryProxy());
+ addOperation(readoperation);
- addLink(readoperation->getOutputSocket(), target);
+ addLink(readoperation->getOutputSocket(), target);
- readoperation->readResolutionFromWriteBuffer();
- }
+ readoperation->readResolutionFromWriteBuffer();
+ }
}
void NodeOperationBuilder::add_complex_operation_buffers()
{
- /* note: complex ops and get cached here first, since adding operations
- * will invalidate iterators over the main m_operations
- */
- Operations complex_ops;
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it)
- if ((*it)->isComplex())
- complex_ops.push_back(*it);
+ /* note: complex ops and get cached here first, since adding operations
+ * will invalidate iterators over the main m_operations
+ */
+ Operations complex_ops;
+ for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it)
+ if ((*it)->isComplex())
+ complex_ops.push_back(*it);
- for (Operations::const_iterator it = complex_ops.begin(); it != complex_ops.end(); ++it) {
- NodeOperation *op = *it;
+ for (Operations::const_iterator it = complex_ops.begin(); it != complex_ops.end(); ++it) {
+ NodeOperation *op = *it;
- DebugInfo::operation_read_write_buffer(op);
+ DebugInfo::operation_read_write_buffer(op);
- for (int index = 0; index < op->getNumberOfInputSockets(); index++)
- add_input_buffers(op, op->getInputSocket(index));
+ for (int index = 0; index < op->getNumberOfInputSockets(); index++)
+ add_input_buffers(op, op->getInputSocket(index));
- for (int index = 0; index < op->getNumberOfOutputSockets(); index++)
- add_output_buffers(op, op->getOutputSocket(index));
- }
+ for (int index = 0; index < op->getNumberOfOutputSockets(); index++)
+ add_output_buffers(op, op->getOutputSocket(index));
+ }
}
-typedef std::set<NodeOperation*> Tags;
+typedef std::set<NodeOperation *> Tags;
static void find_reachable_operations_recursive(Tags &reachable, NodeOperation *op)
{
- if (reachable.find(op) != reachable.end())
- return;
- reachable.insert(op);
+ if (reachable.find(op) != reachable.end())
+ return;
+ reachable.insert(op);
- for (int i = 0; i < op->getNumberOfInputSockets(); ++i) {
- NodeOperationInput *input = op->getInputSocket(i);
- if (input->isConnected())
- find_reachable_operations_recursive(reachable, &input->getLink()->getOperation());
- }
+ for (int i = 0; i < op->getNumberOfInputSockets(); ++i) {
+ NodeOperationInput *input = op->getInputSocket(i);
+ if (input->isConnected())
+ find_reachable_operations_recursive(reachable, &input->getLink()->getOperation());
+ }
- /* associated write-buffer operations are executed as well */
- if (op->isReadBufferOperation()) {
- ReadBufferOperation *read_op = (ReadBufferOperation *)op;
- MemoryProxy *memproxy = read_op->getMemoryProxy();
- find_reachable_operations_recursive(reachable, memproxy->getWriteBufferOperation());
- }
+ /* associated write-buffer operations are executed as well */
+ if (op->isReadBufferOperation()) {
+ ReadBufferOperation *read_op = (ReadBufferOperation *)op;
+ MemoryProxy *memproxy = read_op->getMemoryProxy();
+ find_reachable_operations_recursive(reachable, memproxy->getWriteBufferOperation());
+ }
}
void NodeOperationBuilder::prune_operations()
{
- Tags reachable;
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
- NodeOperation *op = *it;
+ Tags reachable;
+ for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
+ NodeOperation *op = *it;
- /* output operations are primary executed operations */
- if (op->isOutputOperation(m_context->isRendering()))
- find_reachable_operations_recursive(reachable, op);
- }
+ /* output operations are primary executed operations */
+ if (op->isOutputOperation(m_context->isRendering()))
+ find_reachable_operations_recursive(reachable, op);
+ }
- /* delete unreachable operations */
- Operations reachable_ops;
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
- NodeOperation *op = *it;
+ /* delete unreachable operations */
+ Operations reachable_ops;
+ for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
+ NodeOperation *op = *it;
- if (reachable.find(op) != reachable.end())
- reachable_ops.push_back(op);
- else
- delete op;
- }
- /* finally replace the operations list with the pruned list */
- m_operations = reachable_ops;
+ if (reachable.find(op) != reachable.end())
+ reachable_ops.push_back(op);
+ else
+ delete op;
+ }
+ /* finally replace the operations list with the pruned list */
+ m_operations = reachable_ops;
}
/* topological (depth-first) sorting of operations */
-static void sort_operations_recursive(NodeOperationBuilder::Operations &sorted, Tags &visited, NodeOperation *op)
+static void sort_operations_recursive(NodeOperationBuilder::Operations &sorted,
+ Tags &visited,
+ NodeOperation *op)
{
- if (visited.find(op) != visited.end())
- return;
- visited.insert(op);
+ if (visited.find(op) != visited.end())
+ return;
+ visited.insert(op);
- for (int i = 0; i < op->getNumberOfInputSockets(); ++i) {
- NodeOperationInput *input = op->getInputSocket(i);
- if (input->isConnected())
- sort_operations_recursive(sorted, visited, &input->getLink()->getOperation());
- }
+ for (int i = 0; i < op->getNumberOfInputSockets(); ++i) {
+ NodeOperationInput *input = op->getInputSocket(i);
+ if (input->isConnected())
+ sort_operations_recursive(sorted, visited, &input->getLink()->getOperation());
+ }
- sorted.push_back(op);
+ sorted.push_back(op);
}
void NodeOperationBuilder::sort_operations()
{
- Operations sorted;
- sorted.reserve(m_operations.size());
- Tags visited;
+ Operations sorted;
+ sorted.reserve(m_operations.size());
+ Tags visited;
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it)
- sort_operations_recursive(sorted, visited, *it);
+ for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it)
+ sort_operations_recursive(sorted, visited, *it);
- m_operations = sorted;
+ m_operations = sorted;
}
static void add_group_operations_recursive(Tags &visited, NodeOperation *op, ExecutionGroup *group)
{
- if (visited.find(op) != visited.end())
- return;
- visited.insert(op);
+ if (visited.find(op) != visited.end())
+ return;
+ visited.insert(op);
- if (!group->addOperation(op))
- return;
+ if (!group->addOperation(op))
+ return;
- /* add all eligible input ops to the group */
- for (int i = 0; i < op->getNumberOfInputSockets(); ++i) {
- NodeOperationInput *input = op->getInputSocket(i);
- if (input->isConnected())
- add_group_operations_recursive(visited, &input->getLink()->getOperation(), group);
- }
+ /* add all eligible input ops to the group */
+ for (int i = 0; i < op->getNumberOfInputSockets(); ++i) {
+ NodeOperationInput *input = op->getInputSocket(i);
+ if (input->isConnected())
+ add_group_operations_recursive(visited, &input->getLink()->getOperation(), group);
+ }
}
ExecutionGroup *NodeOperationBuilder::make_group(NodeOperation *op)
{
- ExecutionGroup *group = new ExecutionGroup();
- m_groups.push_back(group);
+ ExecutionGroup *group = new ExecutionGroup();
+ m_groups.push_back(group);
- Tags visited;
- add_group_operations_recursive(visited, op, group);
+ Tags visited;
+ add_group_operations_recursive(visited, op, group);
- return group;
+ return group;
}
void NodeOperationBuilder::group_operations()
{
- for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
- NodeOperation *op = *it;
-
- if (op->isOutputOperation(m_context->isRendering())) {
- ExecutionGroup *group = make_group(op);
- group->setOutputExecutionGroup(true);
- }
-
- /* add new groups for associated memory proxies where needed */
- if (op->isReadBufferOperation()) {
- ReadBufferOperation *read_op = (ReadBufferOperation *)op;
- MemoryProxy *memproxy = read_op->getMemoryProxy();
-
- if (memproxy->getExecutor() == NULL) {
- ExecutionGroup *group = make_group(memproxy->getWriteBufferOperation());
- memproxy->setExecutor(group);
- }
- }
- }
+ for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) {
+ NodeOperation *op = *it;
+
+ if (op->isOutputOperation(m_context->isRendering())) {
+ ExecutionGroup *group = make_group(op);
+ group->setOutputExecutionGroup(true);
+ }
+
+ /* add new groups for associated memory proxies where needed */
+ if (op->isReadBufferOperation()) {
+ ReadBufferOperation *read_op = (ReadBufferOperation *)op;
+ MemoryProxy *memproxy = read_op->getMemoryProxy();
+
+ if (memproxy->getExecutor() == NULL) {
+ ExecutionGroup *group = make_group(memproxy->getWriteBufferOperation());
+ memproxy->setExecutor(group);
+ }
+ }
+ }
}