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')
-rw-r--r--source/blender/compositor/intern/COM_CPUDevice.cpp2
-rw-r--r--source/blender/compositor/intern/COM_ChannelInfo.h10
-rw-r--r--source/blender/compositor/intern/COM_CompositorContext.h6
-rw-r--r--source/blender/compositor/intern/COM_Converter.cpp151
-rw-r--r--source/blender/compositor/intern/COM_Converter.h34
-rw-r--r--source/blender/compositor/intern/COM_Debug.cpp141
-rw-r--r--source/blender/compositor/intern/COM_Debug.h31
-rw-r--r--source/blender/compositor/intern/COM_ExecutionGroup.cpp104
-rw-r--r--source/blender/compositor/intern/COM_ExecutionGroup.h49
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystem.cpp230
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystem.h91
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp171
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystemHelper.h126
-rw-r--r--source/blender/compositor/intern/COM_InputSocket.cpp159
-rw-r--r--source/blender/compositor/intern/COM_InputSocket.h149
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.cpp5
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.h1
-rw-r--r--source/blender/compositor/intern/COM_MemoryProxy.h1
-rw-r--r--source/blender/compositor/intern/COM_Node.cpp235
-rw-r--r--source/blender/compositor/intern/COM_Node.h234
-rw-r--r--source/blender/compositor/intern/COM_NodeBase.cpp96
-rw-r--r--source/blender/compositor/intern/COM_NodeBase.h185
-rw-r--r--source/blender/compositor/intern/COM_NodeConverter.cpp131
-rw-r--r--source/blender/compositor/intern/COM_NodeConverter.h103
-rw-r--r--source/blender/compositor/intern/COM_NodeGraph.cpp280
-rw-r--r--source/blender/compositor/intern/COM_NodeGraph.h109
-rw-r--r--source/blender/compositor/intern/COM_NodeOperation.cpp138
-rw-r--r--source/blender/compositor/intern/COM_NodeOperation.h175
-rw-r--r--source/blender/compositor/intern/COM_NodeOperationBuilder.cpp661
-rw-r--r--source/blender/compositor/intern/COM_NodeOperationBuilder.h158
-rw-r--r--source/blender/compositor/intern/COM_OpenCLDevice.cpp2
-rw-r--r--source/blender/compositor/intern/COM_OpenCLDevice.h2
-rw-r--r--source/blender/compositor/intern/COM_OutputSocket.cpp119
-rw-r--r--source/blender/compositor/intern/COM_OutputSocket.h84
-rw-r--r--source/blender/compositor/intern/COM_SingleThreadedOperation.cpp (renamed from source/blender/compositor/intern/COM_SingleThreadedNodeOperation.cpp)12
-rw-r--r--source/blender/compositor/intern/COM_SingleThreadedOperation.h (renamed from source/blender/compositor/intern/COM_SingleThreadedNodeOperation.h)8
-rw-r--r--source/blender/compositor/intern/COM_Socket.cpp68
-rw-r--r--source/blender/compositor/intern/COM_Socket.h100
-rw-r--r--source/blender/compositor/intern/COM_SocketConnection.cpp95
-rw-r--r--source/blender/compositor/intern/COM_SocketConnection.h127
-rw-r--r--source/blender/compositor/intern/COM_WorkScheduler.cpp10
41 files changed, 2287 insertions, 2306 deletions
diff --git a/source/blender/compositor/intern/COM_CPUDevice.cpp b/source/blender/compositor/intern/COM_CPUDevice.cpp
index 7029aa032cc..c7c3f7769fe 100644
--- a/source/blender/compositor/intern/COM_CPUDevice.cpp
+++ b/source/blender/compositor/intern/COM_CPUDevice.cpp
@@ -30,7 +30,7 @@ void CPUDevice::execute(WorkPackage *work)
executionGroup->determineChunkRect(&rect, chunkNumber);
- executionGroup->getOutputNodeOperation()->executeRegion(&rect, chunkNumber);
+ executionGroup->getOutputOperation()->executeRegion(&rect, chunkNumber);
executionGroup->finalizeChunkExecution(chunkNumber, NULL);
}
diff --git a/source/blender/compositor/intern/COM_ChannelInfo.h b/source/blender/compositor/intern/COM_ChannelInfo.h
index 44664442359..ec78e7e1cb1 100644
--- a/source/blender/compositor/intern/COM_ChannelInfo.h
+++ b/source/blender/compositor/intern/COM_ChannelInfo.h
@@ -49,8 +49,8 @@ typedef enum ChannelType {
/**
* @brief ChannelInfo holds information about a channel.
*
- * Channels are transported from node to node via a SocketConnection.
- * ChannelInfo holds specific setting of these channels in order that the to-node of the connection
+ * Channels are transported from node to node via a NodeLink.
+ * ChannelInfo holds specific setting of these channels in order that the to-node of the link
* Can handle specific logic per channel setting.
*
* @note currently this is not used, but a future place to implement color spacing and other things.
@@ -59,7 +59,7 @@ typedef enum ChannelType {
class ChannelInfo {
private:
/**
- * @brief the channel number, in the connection. [0-3]
+ * @brief the channel number, in the link. [0-3]
*/
int m_number;
@@ -87,12 +87,12 @@ public:
ChannelInfo();
/**
- * @brief set the index of this channel in the SocketConnection
+ * @brief set the index of this channel in the NodeLink
*/
void setNumber(const int number) { this->m_number = number; }
/**
- * @brief get the index of this channel in the SocketConnection
+ * @brief get the index of this channel in the NodeLink
*/
const int getNumber() const { return this->m_number; }
diff --git a/source/blender/compositor/intern/COM_CompositorContext.h b/source/blender/compositor/intern/COM_CompositorContext.h
index 223f900b391..a398ae937a3 100644
--- a/source/blender/compositor/intern/COM_CompositorContext.h
+++ b/source/blender/compositor/intern/COM_CompositorContext.h
@@ -181,11 +181,11 @@ public:
*/
void setHasActiveOpenCLDevices(bool hasAvtiveOpenCLDevices) { this->m_hasActiveOpenCLDevices = hasAvtiveOpenCLDevices; }
- int getChunksize() { return this->getbNodeTree()->chunksize; }
+ int getChunksize() const { return this->getbNodeTree()->chunksize; }
void setFastCalculation(bool fastCalculation) {this->m_fastCalculation = fastCalculation;}
- bool isFastCalculation() {return this->m_fastCalculation;}
- inline bool isGroupnodeBufferEnabled() {return this->getbNodeTree()->flag & NTREE_COM_GROUPNODE_BUFFER;}
+ bool isFastCalculation() const { return this->m_fastCalculation; }
+ bool isGroupnodeBufferEnabled() const { return this->getbNodeTree()->flag & NTREE_COM_GROUPNODE_BUFFER; }
};
diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp
index 7103b49f32f..9251e161839 100644
--- a/source/blender/compositor/intern/COM_Converter.cpp
+++ b/source/blender/compositor/intern/COM_Converter.cpp
@@ -22,7 +22,14 @@
#include <string.h>
+extern "C" {
+#include "DNA_node_types.h"
+
#include "BKE_node.h"
+}
+
+#include "COM_NodeOperationBuilder.h"
+#include "COM_NodeOperation.h"
#include "COM_AlphaOverNode.h"
#include "COM_BilateralBlurNode.h"
@@ -41,10 +48,7 @@
#include "COM_ColorRampNode.h"
#include "COM_ColorSpillNode.h"
#include "COM_ColorToBWNode.h"
-#include "COM_CombineHSVANode.h"
-#include "COM_CombineRGBANode.h"
-#include "COM_CombineYCCANode.h"
-#include "COM_CombineYUVANode.h"
+#include "COM_CombineColorNode.h"
#include "COM_CompositorNode.h"
#include "COM_ConvertAlphaNode.h"
#include "COM_ConvertOperation.h"
@@ -61,12 +65,10 @@
#include "COM_DoubleEdgeMaskNode.h"
#include "COM_EllipseMaskNode.h"
#include "COM_ExecutionSystem.h"
-#include "COM_ExecutionSystemHelper.h"
#include "COM_FilterNode.h"
#include "COM_FlipNode.h"
#include "COM_GammaNode.h"
#include "COM_GlareNode.h"
-#include "COM_GroupNode.h"
#include "COM_HueSaturationValueCorrectNode.h"
#include "COM_HueSaturationValueNode.h"
#include "COM_IDMaskNode.h"
@@ -85,7 +87,6 @@
#include "COM_MixNode.h"
#include "COM_MovieClipNode.h"
#include "COM_MovieDistortionNode.h"
-#include "COM_MuteNode.h"
#include "COM_NormalNode.h"
#include "COM_NormalizeNode.h"
#include "COM_OutputFileNode.h"
@@ -93,13 +94,9 @@
#include "COM_RotateNode.h"
#include "COM_ScaleNode.h"
#include "COM_ScaleOperation.h"
-#include "COM_SeparateHSVANode.h"
-#include "COM_SeparateRGBANode.h"
-#include "COM_SeparateYCCANode.h"
-#include "COM_SeparateYUVANode.h"
+#include "COM_SeparateColorNode.h"
#include "COM_SetAlphaNode.h"
#include "COM_SetValueOperation.h"
-#include "COM_SocketConnection.h"
#include "COM_SplitViewerNode.h"
#include "COM_Stabilize2dNode.h"
#include "COM_SwitchNode.h"
@@ -119,30 +116,24 @@
#include "COM_PixelateNode.h"
#include "COM_PlaneTrackDeformNode.h"
-Node *Converter::convert(bNode *b_node, bool fast)
+bool Converter::is_fast_node(bNode *b_node)
{
- Node *node = NULL;
+ return !(b_node->type == CMP_NODE_BLUR ||
+ b_node->type == CMP_NODE_VECBLUR ||
+ b_node->type == CMP_NODE_BILATERALBLUR ||
+ b_node->type == CMP_NODE_DEFOCUS ||
+ b_node->type == CMP_NODE_BOKEHBLUR ||
+ b_node->type == CMP_NODE_GLARE ||
+ b_node->type == CMP_NODE_DBLUR ||
+ b_node->type == CMP_NODE_MOVIEDISTORTION ||
+ b_node->type == CMP_NODE_LENSDIST ||
+ b_node->type == CMP_NODE_DOUBLEEDGEMASK ||
+ b_node->type == CMP_NODE_DILATEERODE);
+}
- if (b_node->flag & NODE_MUTED) {
- node = new MuteNode(b_node);
- return node;
- }
- if (fast) {
- if (b_node->type == CMP_NODE_BLUR ||
- b_node->type == CMP_NODE_VECBLUR ||
- b_node->type == CMP_NODE_BILATERALBLUR ||
- b_node->type == CMP_NODE_DEFOCUS ||
- b_node->type == CMP_NODE_BOKEHBLUR ||
- b_node->type == CMP_NODE_GLARE ||
- b_node->type == CMP_NODE_DBLUR ||
- b_node->type == CMP_NODE_MOVIEDISTORTION ||
- b_node->type == CMP_NODE_LENSDIST ||
- b_node->type == CMP_NODE_DOUBLEEDGEMASK ||
- b_node->type == CMP_NODE_DILATEERODE)
- {
- return new MuteNode(b_node);
- }
- }
+Node *Converter::convert(bNode *b_node)
+{
+ Node *node = NULL;
switch (b_node->type) {
case CMP_NODE_COMPOSITE:
@@ -221,11 +212,9 @@ Node *Converter::convert(bNode *b_node, bool fast)
node = new InvertNode(b_node);
break;
case NODE_GROUP:
- node = new GroupNode(b_node);
- break;
case NODE_GROUP_INPUT:
case NODE_GROUP_OUTPUT:
- /* handled in GroupNode::ungroup */
+ /* handled in NodeCompiler */
break;
case CMP_NODE_NORMAL:
node = new NormalNode(b_node);
@@ -405,52 +394,45 @@ Node *Converter::convert(bNode *b_node, bool fast)
case CMP_NODE_CORNERPIN:
node = new CornerPinNode(b_node);
break;
- default:
- node = new MuteNode(b_node);
- break;
}
return node;
}
-void Converter::convertDataType(SocketConnection *connection, ExecutionSystem *system)
+
+NodeOperation *Converter::convertDataType(NodeOperationOutput *from, NodeOperationInput *to)
{
- OutputSocket *outputSocket = connection->getFromSocket();
- InputSocket *inputSocket = connection->getToSocket();
- DataType fromDatatype = outputSocket->getDataType();
- DataType toDatatype = inputSocket->getDataType();
- NodeOperation *converter = NULL;
+ DataType fromDatatype = from->getDataType();
+ DataType toDatatype = to->getDataType();
+
if (fromDatatype == COM_DT_VALUE && toDatatype == COM_DT_COLOR) {
- converter = new ConvertValueToColorOperation();
+ return new ConvertValueToColorOperation();
}
else if (fromDatatype == COM_DT_VALUE && toDatatype == COM_DT_VECTOR) {
- converter = new ConvertValueToVectorOperation();
+ return new ConvertValueToVectorOperation();
}
else if (fromDatatype == COM_DT_COLOR && toDatatype == COM_DT_VALUE) {
- converter = new ConvertColorToValueOperation();
+ return new ConvertColorToValueOperation();
}
else if (fromDatatype == COM_DT_COLOR && toDatatype == COM_DT_VECTOR) {
- converter = new ConvertColorToVectorOperation();
+ return new ConvertColorToVectorOperation();
}
else if (fromDatatype == COM_DT_VECTOR && toDatatype == COM_DT_VALUE) {
- converter = new ConvertVectorToValueOperation();
+ return new ConvertVectorToValueOperation();
}
else if (fromDatatype == COM_DT_VECTOR && toDatatype == COM_DT_COLOR) {
- converter = new ConvertVectorToColorOperation();
- }
- if (converter != NULL) {
- inputSocket->relinkConnections(converter->getInputSocket(0));
- ExecutionSystemHelper::addLink(system->getConnections(), converter->getOutputSocket(), inputSocket);
- system->addOperation(converter);
+ return new ConvertVectorToColorOperation();
}
+
+ return NULL;
}
-void Converter::convertResolution(SocketConnection *connection, ExecutionSystem *system)
+void Converter::convertResolution(NodeOperationBuilder &builder, NodeOperationOutput *fromSocket, NodeOperationInput *toSocket)
{
- InputSocketResizeMode mode = connection->getToSocket()->getResizeMode();
+ InputResizeMode mode = toSocket->getResizeMode();
- NodeOperation *toOperation = (NodeOperation *)connection->getToNode();
+ NodeOperation *toOperation = &toSocket->getOperation();
const float toWidth = toOperation->getWidth();
const float toHeight = toOperation->getHeight();
- NodeOperation *fromOperation = (NodeOperation *)connection->getFromNode();
+ NodeOperation *fromOperation = &fromSocket->getOperation();
const float fromWidth = fromOperation->getWidth();
const float fromHeight = fromOperation->getHeight();
bool doCenter = false;
@@ -499,62 +481,59 @@ void Converter::convertResolution(SocketConnection *connection, ExecutionSystem
if (doCenter) {
NodeOperation *first = NULL;
- SocketConnection *c;
ScaleOperation *scaleOperation = NULL;
if (doScale) {
scaleOperation = new ScaleOperation();
+ scaleOperation->getInputSocket(1)->setResizeMode(COM_SC_NO_RESIZE);
+ scaleOperation->getInputSocket(2)->setResizeMode(COM_SC_NO_RESIZE);
first = scaleOperation;
SetValueOperation *sxop = new SetValueOperation();
sxop->setValue(scaleX);
- c = ExecutionSystemHelper::addLink(system->getConnections(), sxop->getOutputSocket(), scaleOperation->getInputSocket(1));
- c->setIgnoreResizeCheck(true);
+ builder.addLink(sxop->getOutputSocket(), scaleOperation->getInputSocket(1));
SetValueOperation *syop = new SetValueOperation();
syop->setValue(scaleY);
- c = ExecutionSystemHelper::addLink(system->getConnections(), syop->getOutputSocket(), scaleOperation->getInputSocket(2));
- c->setIgnoreResizeCheck(true);
- system->addOperation(sxop);
- system->addOperation(syop);
+ builder.addLink(syop->getOutputSocket(), scaleOperation->getInputSocket(2));
+ builder.addOperation(sxop);
+ builder.addOperation(syop);
unsigned int resolution[2] = {fromOperation->getWidth(),
fromOperation->getHeight()};
scaleOperation->setResolution(resolution);
sxop->setResolution(resolution);
syop->setResolution(resolution);
- system->addOperation(scaleOperation);
-
- c->setIgnoreResizeCheck(true);
+ builder.addOperation(scaleOperation);
}
TranslateOperation *translateOperation = new TranslateOperation();
+ translateOperation->getInputSocket(1)->setResizeMode(COM_SC_NO_RESIZE);
+ translateOperation->getInputSocket(2)->setResizeMode(COM_SC_NO_RESIZE);
if (!first) first = translateOperation;
SetValueOperation *xop = new SetValueOperation();
xop->setValue(addX);
- c = ExecutionSystemHelper::addLink(system->getConnections(), xop->getOutputSocket(), translateOperation->getInputSocket(1));
- c->setIgnoreResizeCheck(true);
+ builder.addLink(xop->getOutputSocket(), translateOperation->getInputSocket(1));
SetValueOperation *yop = new SetValueOperation();
yop->setValue(addY);
- c = ExecutionSystemHelper::addLink(system->getConnections(), yop->getOutputSocket(), translateOperation->getInputSocket(2));
- c->setIgnoreResizeCheck(true);
- system->addOperation(xop);
- system->addOperation(yop);
+ builder.addLink(yop->getOutputSocket(), translateOperation->getInputSocket(2));
+ builder.addOperation(xop);
+ builder.addOperation(yop);
unsigned int resolution[2] = {toOperation->getWidth(),
toOperation->getHeight()};
translateOperation->setResolution(resolution);
xop->setResolution(resolution);
yop->setResolution(resolution);
- system->addOperation(translateOperation);
+ builder.addOperation(translateOperation);
if (doScale) {
- c = ExecutionSystemHelper::addLink(system->getConnections(), scaleOperation->getOutputSocket(), translateOperation->getInputSocket(0));
- c->setIgnoreResizeCheck(true);
+ translateOperation->getInputSocket(0)->setResizeMode(COM_SC_NO_RESIZE);
+ builder.addLink(scaleOperation->getOutputSocket(), translateOperation->getInputSocket(0));
}
- InputSocket *inputSocket = connection->getToSocket();
- inputSocket->relinkConnections(first->getInputSocket(0));
- c = ExecutionSystemHelper::addLink(system->getConnections(), translateOperation->getOutputSocket(), inputSocket);
- c->setIgnoreResizeCheck(true);
+ /* remove previous link and replace */
+ builder.removeInputLink(toSocket);
+ first->getInputSocket(0)->setResizeMode(COM_SC_NO_RESIZE);
+ toSocket->setResizeMode(COM_SC_NO_RESIZE);
+ builder.addLink(fromSocket, first->getInputSocket(0));
+ builder.addLink(translateOperation->getOutputSocket(), toSocket);
}
-
- connection->setIgnoreResizeCheck(true);
}
diff --git a/source/blender/compositor/intern/COM_Converter.h b/source/blender/compositor/intern/COM_Converter.h
index 15bda0839fa..c1ad45bbf54 100644
--- a/source/blender/compositor/intern/COM_Converter.h
+++ b/source/blender/compositor/intern/COM_Converter.h
@@ -23,8 +23,13 @@
#ifndef _COM_Converter_h
#define _COM_Converter_h
-#include "DNA_node_types.h"
-#include "COM_Node.h"
+struct bNode;
+
+class Node;
+class NodeOperation;
+class NodeOperationInput;
+class NodeOperationOutput;
+class NodeOperationBuilder;
/**
* @brief Conversion methods for the compositor
@@ -35,37 +40,42 @@ public:
* @brief Convert/wraps a bNode in its Node instance.
*
* For all nodetypes a wrapper class is created.
- * Muted nodes are wrapped with MuteNode.
*
* @note When adding a new node to blender, this method needs to be changed to return the correct Node instance.
*
* @see Node
- * @see MuteNode
*/
- static Node *convert(bNode *b_node, bool fast);
+ static Node *convert(bNode *b_node);
+
+ /**
+ * @brief True if the node is considered 'fast'.
+ *
+ * Slow nodes will be skipped if fast execution is required.
+ */
+ static bool is_fast_node(bNode *b_node);
/**
* @brief This method will add a datetype conversion rule when the to-socket does not support the from-socket actual data type.
*
* @note this method is called when conversion is needed.
*
- * @param connection the SocketConnection what needs conversion
+ * @param link the NodeLink what needs conversion
* @param system the ExecutionSystem to add the conversion to.
- * @see SocketConnection - a link between two sockets
+ * @see NodeLink - a link between two sockets
*/
- static void convertDataType(SocketConnection *connection, ExecutionSystem *system);
+ static NodeOperation *convertDataType(NodeOperationOutput *from, NodeOperationInput *to);
/**
- * @brief This method will add a resolution rule based on the settings of the InputSocket.
+ * @brief This method will add a resolution rule based on the settings of the NodeInput.
*
* @note Conversion logic is implemented in this method
* @see InputSocketResizeMode for the possible conversions.
*
- * @param connection the SocketConnection what needs conversion
+ * @param link the NodeLink what needs conversion
* @param system the ExecutionSystem to add the conversion to.
- * @see SocketConnection - a link between two sockets
+ * @see NodeLink - a link between two sockets
*/
- static void convertResolution(SocketConnection *connection, ExecutionSystem *system);
+ static void convertResolution(NodeOperationBuilder &builder, NodeOperationOutput *fromSocket, NodeOperationInput *toSocket);
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("COM:Converter")
diff --git a/source/blender/compositor/intern/COM_Debug.cpp b/source/blender/compositor/intern/COM_Debug.cpp
index f5e3cca976c..a453af5ad13 100644
--- a/source/blender/compositor/intern/COM_Debug.cpp
+++ b/source/blender/compositor/intern/COM_Debug.cpp
@@ -46,10 +46,12 @@ extern "C" {
int DebugInfo::m_file_index = 0;
DebugInfo::NodeNameMap DebugInfo::m_node_names;
+DebugInfo::OpNameMap DebugInfo::m_op_names;
std::string DebugInfo::m_current_node_name;
+std::string DebugInfo::m_current_op_name;
DebugInfo::GroupStateMap DebugInfo::m_group_states;
-std::string DebugInfo::node_name(NodeBase *node)
+std::string DebugInfo::node_name(const Node *node)
{
NodeNameMap::const_iterator it = m_node_names.find(node);
if (it != m_node_names.end())
@@ -58,56 +60,65 @@ std::string DebugInfo::node_name(NodeBase *node)
return "";
}
+std::string DebugInfo::operation_name(const NodeOperation *op)
+{
+ OpNameMap::const_iterator it = m_op_names.find(op);
+ if (it != m_op_names.end())
+ return it->second;
+ else
+ return "";
+}
+
void DebugInfo::convert_started()
{
- m_node_names.clear();
+ m_op_names.clear();
}
-void DebugInfo::execute_started(ExecutionSystem *system)
+void DebugInfo::execute_started(const ExecutionSystem *system)
{
m_file_index = 1;
m_group_states.clear();
- for (int i = 0; i < system->getExecutionGroups().size(); ++i)
- m_group_states[system->getExecutionGroups()[i]] = EG_WAIT;
+ for (ExecutionSystem::Groups::const_iterator it = system->m_groups.begin(); it != system->m_groups.end(); ++it)
+ m_group_states[*it] = EG_WAIT;
}
-void DebugInfo::node_added(Node *node)
+void DebugInfo::node_added(const Node *node)
{
m_node_names[node] = std::string(node->getbNode() ? node->getbNode()->name : "");
}
-void DebugInfo::node_to_operations(Node *node)
+void DebugInfo::node_to_operations(const Node *node)
{
m_current_node_name = m_node_names[node];
}
-void DebugInfo::operation_added(NodeOperation *operation)
+void DebugInfo::operation_added(const NodeOperation *operation)
{
- m_node_names[operation] = m_current_node_name;
+ m_op_names[operation] = m_current_node_name;
}
-void DebugInfo::operation_read_write_buffer(NodeOperation *operation)
+void DebugInfo::operation_read_write_buffer(const NodeOperation *operation)
{
- m_current_node_name = m_node_names[operation];
+ m_current_op_name = m_op_names[operation];
}
-void DebugInfo::execution_group_started(ExecutionGroup *group)
+void DebugInfo::execution_group_started(const ExecutionGroup *group)
{
m_group_states[group] = EG_RUNNING;
}
-void DebugInfo::execution_group_finished(ExecutionGroup *group)
+void DebugInfo::execution_group_finished(const ExecutionGroup *group)
{
m_group_states[group] = EG_FINISHED;
}
-int DebugInfo::graphviz_operation(ExecutionSystem *system, NodeOperation *operation, ExecutionGroup *group, char *str, int maxlen)
+int DebugInfo::graphviz_operation(const ExecutionSystem *system, const NodeOperation *operation, const ExecutionGroup *group, char *str, int maxlen)
{
int len = 0;
std::string fillcolor = "gainsboro";
if (operation->isViewerOperation()) {
- ViewerOperation *viewer = (ViewerOperation *)operation;
+ const ViewerOperation *viewer = (const ViewerOperation *)operation;
if (viewer->isActiveViewerOutput()) {
fillcolor = "lightskyblue1";
}
@@ -139,7 +150,7 @@ int DebugInfo::graphviz_operation(ExecutionSystem *system, NodeOperation *operat
if (totinputs != 0) {
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "{");
for (int k = 0; k < totinputs; k++) {
- InputSocket *socket = operation->getInputSocket(k);
+ NodeOperationInput *socket = operation->getInputSocket(k);
if (k != 0) {
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "|");
}
@@ -160,7 +171,7 @@ int DebugInfo::graphviz_operation(ExecutionSystem *system, NodeOperation *operat
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "|");
}
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "%s\\n(%s)", m_node_names[operation].c_str(), typeid(*operation).name());
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "%s\\n(%s)", m_op_names[operation].c_str(), typeid(*operation).name());
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, " (%d,%d)", operation->getWidth(), operation->getHeight());
@@ -169,7 +180,7 @@ int DebugInfo::graphviz_operation(ExecutionSystem *system, NodeOperation *operat
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "|");
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "{");
for (int k = 0; k < totoutputs; k++) {
- OutputSocket *socket = operation->getOutputSocket(k);
+ NodeOperationOutput *socket = operation->getOutputSocket(k);
if (k != 0) {
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "|");
}
@@ -227,7 +238,7 @@ int DebugInfo::graphviz_legend(char *str, int maxlen)
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, " <TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"4\">\r\n");
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "<TR><TD COLSPAN=\"2\"><B>Legend</B></TD></TR>\r\n");
- len += graphviz_legend_color("Operation", "gainsboro", str + len, maxlen > len ? maxlen - len : 0);
+ len += graphviz_legend_color("NodeOperation", "gainsboro", str + len, maxlen > len ? maxlen - len : 0);
len += graphviz_legend_color("Output", "dodgerblue1", str + len, maxlen > len ? maxlen - len : 0);
len += graphviz_legend_color("Viewer", "lightskyblue3", str + len, maxlen > len ? maxlen - len : 0);
len += graphviz_legend_color("Active Viewer", "lightskyblue1", str + len, maxlen > len ? maxlen - len : 0);
@@ -248,26 +259,29 @@ int DebugInfo::graphviz_legend(char *str, int maxlen)
return len;
}
-bool DebugInfo::graphviz_system(ExecutionSystem *system, char *str, int maxlen)
+bool DebugInfo::graphviz_system(const ExecutionSystem *system, char *str, int maxlen)
{
char strbuf[64];
int len = 0;
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "digraph compositorexecution {\r\n");
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "ranksep=1.5\r\n");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "rankdir=LR\r\n");
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "splines=false\r\n");
- int totnodes = system->getNodes().size();
- for (int i = 0; i < totnodes; i++) {
- Node *node = system->getNodes()[i];
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "// NODE: %s\r\n", node->getbNode()->typeinfo->ui_name);
+#if 0
+ for (ExecutionSystem::Operations::const_iterator it = system->m_operations.begin();
+ it != system->m_operations.end(); ++it) {
+ NodeOperation *op = *it;
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "// OPERATION: %s\r\n", node->getbNode()->typeinfo->ui_name);
}
+#endif
- int totgroups = system->getExecutionGroups().size();
- int totops = system->getOperations().size();
+ int totops = system->m_operations.size();
+ int totgroups = system->m_groups.size();
std::map<NodeOperation *, std::vector<std::string> > op_groups;
for (int i = 0; i < totgroups; ++i) {
- ExecutionGroup *group = system->getExecutionGroups()[i];
+ const ExecutionGroup *group = system->m_groups[i];
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "// GROUP: %d\r\n", i);
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "subgraph cluster_%d{\r\n", i);
@@ -286,10 +300,8 @@ bool DebugInfo::graphviz_system(ExecutionSystem *system, char *str, int maxlen)
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "fillcolor=chartreuse4\r\n");
}
- for (int j = 0; j < totops; ++j) {
- NodeOperation *operation = system->getOperations()[j];
- if (!group->containsOperation(operation))
- continue;
+ for (ExecutionGroup::Operations::const_iterator it = group->m_operations.begin(); it != group->m_operations.end(); ++it) {
+ NodeOperation *operation = *it;
sprintf(strbuf, "_%p", group);
op_groups[operation].push_back(std::string(strbuf));
@@ -297,14 +309,14 @@ bool DebugInfo::graphviz_system(ExecutionSystem *system, char *str, int maxlen)
len += graphviz_operation(system, operation, group, str + len, maxlen > len ? maxlen - len : 0);
}
-// len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "// OUTPUTOPERATION: %p\r\n", group->getOutputNodeOperation());
-// len += snprintf(str+len, maxlen>len ? maxlen-len : 0, " O_%p\r\n", group->getOutputNodeOperation());
+// len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "// OUTPUTOPERATION: %p\r\n", group->getOutputOperation());
+// len += snprintf(str+len, maxlen>len ? maxlen-len : 0, " O_%p\r\n", group->getOutputOperation());
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}\r\n");
}
/* operations not included in any group */
for (int j = 0; j < totops; ++j) {
- NodeOperation *operation = system->getOperations()[j];
+ NodeOperation *operation = system->m_operations[j];
if (op_groups.find(operation) != op_groups.end())
continue;
@@ -314,7 +326,7 @@ bool DebugInfo::graphviz_system(ExecutionSystem *system, char *str, int maxlen)
}
for (int i = 0; i < totops; i++) {
- NodeOperation *operation = system->getOperations()[i];
+ NodeOperation *operation = system->m_operations[i];
if (operation->isReadBufferOperation()) {
ReadBufferOperation *read = (ReadBufferOperation *)operation;
@@ -330,16 +342,18 @@ bool DebugInfo::graphviz_system(ExecutionSystem *system, char *str, int maxlen)
}
}
- int totcon = system->getConnections().size();
- for (int i = 0; i < totcon; i++) {
- SocketConnection *connection = system->getConnections()[i];
+ for (int i = 0; i < totops; i++) {
+ NodeOperation *op = system->m_operations[i];
- std::string color;
- if (!connection->isValid()) {
- color = "red";
- }
- else {
- switch (connection->getFromSocket()->getDataType()) {
+ for (NodeOperation::Inputs::const_iterator it = op->m_inputs.begin(); it != op->m_inputs.end(); ++it) {
+ NodeOperationInput *to = *it;
+ NodeOperationOutput *from = to->getLink();
+
+ if (!from)
+ continue;
+
+ std::string color;
+ switch (from->getDataType()) {
case COM_DT_VALUE:
color = "grey";
break;
@@ -350,22 +364,18 @@ bool DebugInfo::graphviz_system(ExecutionSystem *system, char *str, int maxlen)
color = "orange";
break;
}
- }
-
- NodeBase *from_node = connection->getFromNode();
- NodeBase *to_node = connection->getToNode();
- OutputSocket *from_sock = connection->getFromSocket();
- InputSocket *to_sock = connection->getToSocket();
- if (from_node->isOperation() && to_node->isOperation()) {
- NodeOperation *from_op = (NodeOperation *)from_node;
- NodeOperation *to_op = (NodeOperation *)to_node;
+
+ NodeOperation *to_op = &to->getOperation();
+ NodeOperation *from_op = &from->getOperation();
std::vector<std::string> &from_groups = op_groups[from_op];
std::vector<std::string> &to_groups = op_groups[to_op];
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "// CONNECTION: %p.%p -> %p.%p\r\n", from_op, from_sock, to_op, to_sock);
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "// CONNECTION: %p.%p -> %p.%p\r\n",
+ from_op, from, to_op, to);
for (int k = 0; k < from_groups.size(); ++k) {
for (int l = 0; l < to_groups.size(); ++l) {
- len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\"O_%p%s\":\"OUT_%p\":s -> \"O_%p%s\":\"IN_%p\":n", from_op, from_groups[k].c_str(), from_sock, to_op, to_groups[l].c_str(), to_sock);
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\"O_%p%s\":\"OUT_%p\":e -> \"O_%p%s\":\"IN_%p\":w",
+ from_op, from_groups[k].c_str(), from, to_op, to_groups[l].c_str(), to);
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, " [color=%s]", color.c_str());
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\r\n");
}
@@ -380,7 +390,7 @@ bool DebugInfo::graphviz_system(ExecutionSystem *system, char *str, int maxlen)
return (len < maxlen);
}
-void DebugInfo::graphviz(ExecutionSystem *system)
+void DebugInfo::graphviz(const ExecutionSystem *system)
{
char str[1000000];
if (graphviz_system(system, str, sizeof(str) - 1)) {
@@ -399,15 +409,16 @@ void DebugInfo::graphviz(ExecutionSystem *system)
#else
-std::string DebugInfo::node_name(NodeBase * /*node*/) { return ""; }
+std::string DebugInfo::node_name(const Node * /*node*/) { return ""; }
+std::string DebugInfo::operation_name(const NodeOperation * /*op*/) { return ""; }
void DebugInfo::convert_started() {}
-void DebugInfo::execute_started(ExecutionSystem * /*system*/) {}
-void DebugInfo::node_added(Node * /*node*/) {}
-void DebugInfo::node_to_operations(Node * /*node*/) {}
-void DebugInfo::operation_added(NodeOperation * /*operation*/) {}
-void DebugInfo::operation_read_write_buffer(NodeOperation * /*operation*/) {}
-void DebugInfo::execution_group_started(ExecutionGroup * /*group*/) {}
-void DebugInfo::execution_group_finished(ExecutionGroup * /*group*/) {}
-void DebugInfo::graphviz(ExecutionSystem * /*system*/) {}
+void DebugInfo::execute_started(const ExecutionSystem * /*system*/) {}
+void DebugInfo::node_added(const Node * /*node*/) {}
+void DebugInfo::node_to_operations(const Node * /*node*/) {}
+void DebugInfo::operation_added(const NodeOperation * /*operation*/) {}
+void DebugInfo::operation_read_write_buffer(const NodeOperation * /*operation*/) {}
+void DebugInfo::execution_group_started(const ExecutionGroup * /*group*/) {}
+void DebugInfo::execution_group_finished(const ExecutionGroup * /*group*/) {}
+void DebugInfo::graphviz(const ExecutionSystem * /*system*/) {}
#endif
diff --git a/source/blender/compositor/intern/COM_Debug.h b/source/blender/compositor/intern/COM_Debug.h
index cc108157769..204e7e4f57c 100644
--- a/source/blender/compositor/intern/COM_Debug.h
+++ b/source/blender/compositor/intern/COM_Debug.h
@@ -27,7 +27,6 @@
#include "COM_defines.h"
-class NodeBase;
class Node;
class NodeOperation;
class ExecutionSystem;
@@ -41,37 +40,41 @@ public:
EG_FINISHED
} GroupState;
- typedef std::map<NodeBase *, std::string> NodeNameMap;
- typedef std::map<ExecutionGroup *, GroupState> GroupStateMap;
+ typedef std::map<const Node *, std::string> NodeNameMap;
+ typedef std::map<const NodeOperation *, std::string> OpNameMap;
+ typedef std::map<const ExecutionGroup *, GroupState> GroupStateMap;
- static std::string node_name(NodeBase *node);
+ static std::string node_name(const Node *node);
+ static std::string operation_name(const NodeOperation *op);
static void convert_started();
- static void execute_started(ExecutionSystem *system);
+ static void execute_started(const ExecutionSystem *system);
- static void node_added(Node *node);
- static void node_to_operations(Node *node);
- static void operation_added(NodeOperation *operation);
- static void operation_read_write_buffer(NodeOperation *operation);
+ static void node_added(const Node *node);
+ static void node_to_operations(const Node *node);
+ static void operation_added(const NodeOperation *operation);
+ static void operation_read_write_buffer(const NodeOperation *operation);
- static void execution_group_started(ExecutionGroup *group);
- static void execution_group_finished(ExecutionGroup *group);
+ static void execution_group_started(const ExecutionGroup *group);
+ static void execution_group_finished(const ExecutionGroup *group);
- static void graphviz(ExecutionSystem *system);
+ static void graphviz(const ExecutionSystem *system);
#ifdef COM_DEBUG
protected:
- static int graphviz_operation(ExecutionSystem *system, NodeOperation *operation, ExecutionGroup *group, char *str, int maxlen);
+ static int graphviz_operation(const ExecutionSystem *system, const NodeOperation *operation, const ExecutionGroup *group, char *str, int maxlen);
static int graphviz_legend_color(const char *name, const char *color, char *str, int maxlen);
static int graphviz_legend_line(const char *name, const char *color, const char *style, char *str, int maxlen);
static int graphviz_legend_group(const char *name, const char *color, const char *style, char *str, int maxlen);
static int graphviz_legend(char *str, int maxlen);
- static bool graphviz_system(ExecutionSystem *system, char *str, int maxlen);
+ static bool graphviz_system(const ExecutionSystem *system, char *str, int maxlen);
private:
static int m_file_index;
static NodeNameMap m_node_names; /**< map nodes to usable names for debug output */
+ static OpNameMap m_op_names; /**< map operations to usable names for debug output */
static std::string m_current_node_name; /**< base name for all operations added by a node */
+ static std::string m_current_op_name; /**< base name for automatic sub-operations */
static GroupStateMap m_group_states; /**< for visualizing group states */
#endif
};
diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cpp b/source/blender/compositor/intern/COM_ExecutionGroup.cpp
index a2e4e809a3d..586a774b89e 100644
--- a/source/blender/compositor/intern/COM_ExecutionGroup.cpp
+++ b/source/blender/compositor/intern/COM_ExecutionGroup.cpp
@@ -26,8 +26,6 @@
#include <stdlib.h>
#include "COM_ExecutionGroup.h"
-#include "COM_InputSocket.h"
-#include "COM_SocketConnection.h"
#include "COM_defines.h"
#include "COM_ExecutionSystem.h"
#include "COM_ReadBufferOperation.h"
@@ -36,7 +34,6 @@
#include "COM_WorkScheduler.h"
#include "COM_ViewerOperation.h"
#include "COM_ChunkOrder.h"
-#include "COM_ExecutionSystemHelper.h"
#include "COM_Debug.h"
#include "MEM_guardedalloc.h"
@@ -69,84 +66,43 @@ ExecutionGroup::ExecutionGroup()
CompositorPriority ExecutionGroup::getRenderPriotrity()
{
- return this->getOutputNodeOperation()->getRenderPriority();
-}
-
-bool ExecutionGroup::containsOperation(NodeOperation *operation)
-{
- for (vector<NodeOperation *>::const_iterator iterator = this->m_operations.begin(); iterator != this->m_operations.end(); ++iterator) {
- NodeOperation *inListOperation = *iterator;
- if (inListOperation == operation) {
- return true;
- }
- }
- return false;
-}
-
-const bool ExecutionGroup::isComplex() const
-{
- return this->m_complex;
+ return this->getOutputOperation()->getRenderPriority();
}
bool ExecutionGroup::canContainOperation(NodeOperation *operation)
{
if (!this->m_initialized) { return true; }
+
if (operation->isReadBufferOperation()) { return true; }
if (operation->isWriteBufferOperation()) { return false; }
if (operation->isSetOperation()) { return true; }
-
- if (!this->isComplex()) {
- return (!operation->isComplex());
- }
- else {
- return false;
- }
+
+ /* complex groups don't allow further ops (except read buffer and values, see above) */
+ if (m_complex) { return false; }
+ /* complex ops can't be added to other groups (except their own, which they initialize, see above) */
+ if (operation->isComplex()) { return false; }
+
+ return true;
}
-void ExecutionGroup::addOperation(ExecutionSystem *system, NodeOperation *operation)
+bool ExecutionGroup::addOperation(NodeOperation *operation)
{
- /* should never happen but in rare cases it can - it causes confusing crashes */
- BLI_assert(operation->isOperation() == true);
-
- if (containsOperation(operation)) return;
- if (canContainOperation(operation)) {
- if (!operation->isBufferOperation()) {
- this->m_complex = operation->isComplex();
- this->m_openCL = operation->isOpenCL();
- this->m_singleThreaded = operation->isSingleThreaded();
- this->m_initialized = true;
- }
- this->m_operations.push_back(operation);
- if (operation->isReadBufferOperation()) {
- ReadBufferOperation *readOperation = (ReadBufferOperation *)operation;
- WriteBufferOperation *writeOperation = readOperation->getMemoryProxy()->getWriteBufferOperation();
- this->addOperation(system, writeOperation);
- }
- else {
- unsigned int index;
- for (index = 0; index < operation->getNumberOfInputSockets(); index++) {
- InputSocket *inputSocket = operation->getInputSocket(index);
- if (inputSocket->isConnected()) {
- NodeOperation *node = (NodeOperation *)inputSocket->getConnection()->getFromNode();
- this->addOperation(system, node);
- }
- }
- }
- }
- else {
- if (operation->isWriteBufferOperation()) {
- WriteBufferOperation *writeoperation = (WriteBufferOperation *)operation;
- if (writeoperation->getMemoryProxy()->getExecutor() == NULL) {
- ExecutionGroup *newGroup = new ExecutionGroup();
- writeoperation->getMemoryProxy()->setExecutor(newGroup);
- newGroup->addOperation(system, operation);
- ExecutionSystemHelper::addExecutionGroup(system->getExecutionGroups(), newGroup);
- }
- }
+ if (!canContainOperation(operation))
+ return false;
+
+ if (!operation->isReadBufferOperation() && !operation->isWriteBufferOperation()) {
+ m_complex = operation->isComplex();
+ m_openCL = operation->isOpenCL();
+ m_singleThreaded = operation->isSingleThreaded();
+ m_initialized = true;
}
+
+ m_operations.push_back(operation);
+
+ return true;
}
-NodeOperation *ExecutionGroup::getOutputNodeOperation() const
+NodeOperation *ExecutionGroup::getOutputOperation() const
{
return this->m_operations[0]; // the first operation of the group is always the output operation.
}
@@ -197,7 +153,7 @@ void ExecutionGroup::deinitExecution()
}
void ExecutionGroup::determineResolution(unsigned int resolution[2])
{
- NodeOperation *operation = this->getOutputNodeOperation();
+ NodeOperation *operation = this->getOutputOperation();
resolution[0] = operation->getWidth();
resolution[1] = operation->getHeight();
this->setResolution(resolution);
@@ -226,7 +182,7 @@ void ExecutionGroup::determineNumberOfChunks()
*/
void ExecutionGroup::execute(ExecutionSystem *graph)
{
- CompositorContext &context = graph->getContext();
+ const CompositorContext &context = graph->getContext();
const bNodeTree *bTree = context.getbNodeTree();
if (this->m_width == 0 || this->m_height == 0) {return; } /// @note: break out... no pixels to calculate.
if (bTree->test_break && bTree->test_break(bTree->tbh)) {return; } /// @note: early break out for blur and preview nodes
@@ -243,7 +199,7 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
for (chunkNumber = 0; chunkNumber < this->m_numberOfChunks; chunkNumber++) {
chunkOrder[chunkNumber] = chunkNumber;
}
- NodeOperation *operation = this->getOutputNodeOperation();
+ NodeOperation *operation = this->getOutputOperation();
float centerX = 0.5;
float centerY = 0.5;
OrderOfChunks chunkorder = COM_ORDER_OF_CHUNKS_DEFAULT;
@@ -506,7 +462,7 @@ void ExecutionGroup::determineChunkRect(rcti *rect, const unsigned int chunkNumb
MemoryBuffer *ExecutionGroup::allocateOutputBuffer(int chunkNumber, rcti *rect)
{
// we asume that this method is only called from complex execution groups.
- NodeOperation *operation = this->getOutputNodeOperation();
+ NodeOperation *operation = this->getOutputOperation();
if (operation->isWriteBufferOperation()) {
WriteBufferOperation *writeOperation = (WriteBufferOperation *)operation;
MemoryBuffer *buffer = new MemoryBuffer(writeOperation->getMemoryProxy(), rect);
@@ -615,7 +571,7 @@ bool ExecutionGroup::scheduleChunkWhenPossible(ExecutionSystem *graph, int xChun
void ExecutionGroup::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
{
- this->getOutputNodeOperation()->determineDependingAreaOfInterest(input, readOperation, output);
+ this->getOutputOperation()->determineDependingAreaOfInterest(input, readOperation, output);
}
void ExecutionGroup::determineDependingMemoryProxies(vector<MemoryProxy *> *memoryProxies)
@@ -634,7 +590,7 @@ bool ExecutionGroup::isOpenCL()
void ExecutionGroup::setViewerBorder(float xmin, float xmax, float ymin, float ymax)
{
- NodeOperation *operation = this->getOutputNodeOperation();
+ NodeOperation *operation = this->getOutputOperation();
if (operation->isViewerOperation() || operation->isPreviewOperation()) {
BLI_rcti_init(&this->m_viewerBorder, xmin * this->m_width, xmax * this->m_width,
@@ -644,7 +600,7 @@ void ExecutionGroup::setViewerBorder(float xmin, float xmax, float ymin, float y
void ExecutionGroup::setRenderBorder(float xmin, float xmax, float ymin, float ymax)
{
- NodeOperation *operation = this->getOutputNodeOperation();
+ NodeOperation *operation = this->getOutputOperation();
if (operation->isOutputOperation(true)) {
/* Basically, setting border need to happen for only operations
diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.h b/source/blender/compositor/intern/COM_ExecutionGroup.h
index 47f8447015d..4b6f51c72c0 100644
--- a/source/blender/compositor/intern/COM_ExecutionGroup.h
+++ b/source/blender/compositor/intern/COM_ExecutionGroup.h
@@ -31,6 +31,12 @@
#include "COM_Device.h"
#include "COM_CompositorContext.h"
+using std::vector;
+
+class ExecutionSystem;
+class MemoryProxy;
+class ReadBufferOperation;
+class Device;
/**
* @brief the execution state of a chunk in an ExecutionGroup
@@ -51,23 +57,22 @@ typedef enum ChunkExecutionState {
COM_ES_EXECUTED = 2
} ChunkExecutionState;
-class MemoryProxy;
-class ReadBufferOperation;
-class Device;
-
/**
- * @brief Class ExecutionGroup is a group of NodeOperations that are executed as one.
+ * @brief Class ExecutionGroup is a group of Operations that are executed as one.
* This grouping is used to combine Operations that can be executed as one whole when multi-processing.
* @ingroup Execution
*/
class ExecutionGroup {
+public:
+ typedef std::vector<NodeOperation*> Operations;
+
private:
// fields
/**
* @brief list of operations in this ExecutionGroup
*/
- vector<NodeOperation *> m_operations;
+ Operations m_operations;
/**
* @brief is this ExecutionGroup an input ExecutionGroup
@@ -130,7 +135,7 @@ private:
/**
* @brief a cached vector of all read operations in the execution group.
*/
- vector<NodeOperation *> m_cachedReadOperations;
+ Operations m_cachedReadOperations;
/**
* @brief reference to the original bNodeTree, this field is only set for the 'top' execution group.
@@ -152,8 +157,8 @@ private:
ChunkExecutionState *m_chunkExecutionStates;
/**
- * @brief indicator when this ExecutionGroup has valid NodeOperations in its vector for Execution
- * @note When building the ExecutionGroup NodeOperations are added via recursion. First a WriteBufferOperations is added, then the
+ * @brief indicator when this ExecutionGroup has valid Operations in its vector for Execution
+ * @note When building the ExecutionGroup Operations are added via recursion. First a WriteBufferOperations is added, then the
* @note Operation containing the settings that is important for the ExecutiongGroup is added,
* @note When this occurs, these settings are copied over from the node to the ExecutionGroup
* @note and the Initialized flag is set to true.
@@ -245,23 +250,17 @@ private:
public:
// constructors
ExecutionGroup();
-
- // methods
- /**
- * @brief check to see if a NodeOperation is already inside this execution group
- * @param operation the NodeOperation to check
- * @return [true,false]
- */
- bool containsOperation(NodeOperation *operation);
+ // methods
/**
* @brief add an operation to this ExecutionGroup
* @note this method will add input of the operations recursively
* @note this method can create multiple ExecutionGroup's
* @param system
* @param operation
+ * @return True if the operation was successfully added
*/
- void addOperation(ExecutionSystem *system, NodeOperation *operation);
+ bool addOperation(NodeOperation *operation);
/**
* @brief is this ExecutionGroup an output ExecutionGroup
@@ -292,24 +291,24 @@ public:
/**
* @brief get the width of this execution group
*/
- const unsigned int getWidth() { return this->m_width; }
+ unsigned int getWidth() const { return m_width; }
/**
* @brief get the height of this execution group
*/
- const unsigned int getHeight() { return this->m_height; }
+ unsigned int getHeight() const { return m_height; }
/**
* @brief does this ExecutionGroup contains a complex NodeOperation
*/
- const bool isComplex() const;
+ bool isComplex() const { return m_complex; }
/**
* @brief get the output operation of this ExecutionGroup
* @return NodeOperation *output operation
*/
- NodeOperation *getOutputNodeOperation() const;
+ NodeOperation *getOutputOperation() const;
/**
* @brief compose multiple chunks into a single chunk
@@ -419,12 +418,12 @@ public:
void setRenderBorder(float xmin, float xmax, float ymin, float ymax);
+ /* allow the DebugInfo class to look at internals */
+ friend class DebugInfo;
+
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("COM:ExecutionGroup")
#endif
-
- /* allow the DebugInfo class to peek inside without having to add getters for everything */
- friend class DebugInfo;
};
#endif
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp
index 088232481d0..7c08188db90 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp
@@ -29,15 +29,11 @@ extern "C" {
}
#include "COM_Converter.h"
+#include "COM_NodeOperationBuilder.h"
#include "COM_NodeOperation.h"
#include "COM_ExecutionGroup.h"
-#include "COM_NodeBase.h"
#include "COM_WorkScheduler.h"
#include "COM_ReadBufferOperation.h"
-#include "COM_GroupNode.h"
-#include "COM_WriteBufferOperation.h"
-#include "COM_ReadBufferOperation.h"
-#include "COM_ExecutionSystemHelper.h"
#include "COM_Debug.h"
#include "BKE_global.h"
@@ -63,14 +59,15 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, Scene *scene, bNodeTree *editin
this->m_context.setRendering(rendering);
this->m_context.setHasActiveOpenCLDevices(WorkScheduler::hasGPUDevices() && (editingtree->flag & NTREE_COM_OPENCL));
- ExecutionSystemHelper::addbNodeTree(*this, 0, editingtree, NODE_INSTANCE_KEY_BASE);
-
this->m_context.setRenderData(rd);
this->m_context.setViewSettings(viewSettings);
this->m_context.setDisplaySettings(displaySettings);
- this->convertToOperations();
- this->groupOperations(); /* group operations in ExecutionGroups */
+ {
+ NodeOperationBuilder builder(&m_context, editingtree);
+ builder.convertToOperations(this);
+ }
+
unsigned int index;
unsigned int resolution[2];
@@ -107,16 +104,6 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, Scene *scene, bNodeTree *editin
ExecutionSystem::~ExecutionSystem()
{
unsigned int index;
- for (index = 0; index < this->m_connections.size(); index++) {
- SocketConnection *connection = this->m_connections[index];
- delete connection;
- }
- this->m_connections.clear();
- for (index = 0; index < this->m_nodes.size(); index++) {
- Node *node = this->m_nodes[index];
- delete node;
- }
- this->m_nodes.clear();
for (index = 0; index < this->m_operations.size(); index++) {
NodeOperation *operation = this->m_operations[index];
delete operation;
@@ -129,14 +116,19 @@ ExecutionSystem::~ExecutionSystem()
this->m_groups.clear();
}
+void ExecutionSystem::set_operations(const Operations &operations, const Groups &groups)
+{
+ m_operations = operations;
+ m_groups = groups;
+}
+
void ExecutionSystem::execute()
{
DebugInfo::execute_started(this);
unsigned int order = 0;
for (vector<NodeOperation *>::iterator iter = this->m_operations.begin(); iter != this->m_operations.end(); ++iter) {
- NodeBase *node = *iter;
- NodeOperation *operation = (NodeOperation *) node;
+ NodeOperation *operation = *iter;
if (operation->isReadBufferOperation()) {
ReadBufferOperation *readOperation = (ReadBufferOperation *)operation;
readOperation->setOffset(order);
@@ -196,202 +188,6 @@ void ExecutionSystem::executeGroups(CompositorPriority priority)
}
}
-void ExecutionSystem::addOperation(NodeOperation *operation)
-{
- ExecutionSystemHelper::addOperation(this->m_operations, operation);
- DebugInfo::operation_added(operation);
-}
-
-void ExecutionSystem::addReadWriteBufferOperations(NodeOperation *operation)
-{
- DebugInfo::operation_read_write_buffer(operation);
-
- // for every input add write and read operation if input is not a read operation
- // only add read operation to other links when they are attached to buffered operations.
- unsigned int index;
- for (index = 0; index < operation->getNumberOfInputSockets(); index++) {
- InputSocket *inputsocket = operation->getInputSocket(index);
- if (inputsocket->isConnected()) {
- SocketConnection *connection = inputsocket->getConnection();
- NodeOperation *otherEnd = (NodeOperation *)connection->getFromNode();
- if (!otherEnd->isReadBufferOperation()) {
- // check of other end already has write operation
- OutputSocket *fromsocket = connection->getFromSocket();
- WriteBufferOperation *writeoperation = fromsocket->findAttachedWriteBufferOperation();
- if (writeoperation == NULL) {
- writeoperation = new WriteBufferOperation();
- writeoperation->setbNodeTree(this->getContext().getbNodeTree());
- this->addOperation(writeoperation);
- ExecutionSystemHelper::addLink(this->getConnections(), fromsocket, writeoperation->getInputSocket(0));
- writeoperation->readResolutionFromInputSocket();
- }
- ReadBufferOperation *readoperation = new ReadBufferOperation();
- readoperation->setMemoryProxy(writeoperation->getMemoryProxy());
- connection->setFromSocket(readoperation->getOutputSocket());
- readoperation->getOutputSocket()->addConnection(connection);
- readoperation->readResolutionFromWriteBuffer();
- this->addOperation(readoperation);
- }
- }
- }
- /*
- * link the outputsocket to a write operation
- * link the writeoperation to a read operation
- * link the read operation to the next node.
- */
- OutputSocket *outputsocket = operation->getOutputSocket();
- if (outputsocket->isConnected()) {
- WriteBufferOperation *writeOperation = NULL;
- /* try to find existing write buffer operation first */
- for (index = 0; index < outputsocket->getNumberOfConnections(); index++) {
- SocketConnection *connection = outputsocket->getConnection(index);
- NodeBase *otherEnd = connection->getToNode();
- if (otherEnd->isOperation()) {
- NodeOperation *otherEndOp = (NodeOperation *)otherEnd;
- if (otherEndOp->isWriteBufferOperation()) {
- writeOperation = (WriteBufferOperation *)otherEndOp;
- break;
- }
- }
- }
- /* if no write buffer operation exists yet, create a new one */
- if (!writeOperation) {
- writeOperation = new WriteBufferOperation();
- writeOperation->setbNodeTree(this->getContext().getbNodeTree());
- this->addOperation(writeOperation);
- ExecutionSystemHelper::addLink(this->getConnections(), outputsocket, writeOperation->getInputSocket(0));
- }
- writeOperation->readResolutionFromInputSocket();
-
- for (index = 0; index < outputsocket->getNumberOfConnections(); index++) {
- SocketConnection *connection = outputsocket->getConnection(index);
- /* skip existing connections to write buffer operation */
- if (connection->getToNode() == writeOperation)
- continue;
-
- ReadBufferOperation *readoperation = new ReadBufferOperation();
- readoperation->setMemoryProxy(writeOperation->getMemoryProxy());
- connection->setFromSocket(readoperation->getOutputSocket());
- readoperation->getOutputSocket()->addConnection(connection);
- readoperation->readResolutionFromWriteBuffer();
- this->addOperation(readoperation);
- }
- }
-}
-
-#ifndef NDEBUG
-/* if this fails, there are still connection to/from this node,
- * which have not been properly relinked to operations!
- */
-static void debug_check_node_connections(Node *node)
-{
- /* note: connected inputs are not checked here,
- * it would break quite a lot and such inputs are ignored later anyway
- */
-#if 0
- for (int i = 0; i < node->getNumberOfInputSockets(); ++i) {
- BLI_assert(!node->getInputSocket(i)->isConnected());
- }
-#endif
- for (int i = 0; i < node->getNumberOfOutputSockets(); ++i) {
- BLI_assert(!node->getOutputSocket(i)->isConnected());
- }
-}
-#else
-/* stub */
-#define debug_check_node_connections(node)
-#endif
-
-void ExecutionSystem::convertToOperations()
-{
- unsigned int index;
-
- for (index = 0; index < this->m_nodes.size(); index++) {
- Node *node = (Node *)this->m_nodes[index];
- DebugInfo::node_to_operations(node);
- node->convertToOperations(this, &this->m_context);
-
- debug_check_node_connections(node);
- }
-
- for (index = 0; index < this->m_connections.size(); index++) {
- SocketConnection *connection = this->m_connections[index];
- if (connection->isValid()) {
- if (connection->getFromSocket()->getDataType() != connection->getToSocket()->getDataType()) {
- Converter::convertDataType(connection, this);
- }
- }
- }
-
- // determine all resolutions of the operations (Width/Height)
- for (index = 0; index < this->m_operations.size(); index++) {
- NodeOperation *operation = this->m_operations[index];
- if (operation->isOutputOperation(this->m_context.isRendering()) && !operation->isPreviewOperation()) {
- unsigned int resolution[2] = {0, 0};
- unsigned int preferredResolution[2] = {0, 0};
- operation->determineResolution(resolution, preferredResolution);
- operation->setResolution(resolution);
- }
- }
- for (index = 0; index < this->m_operations.size(); index++) {
- NodeOperation *operation = this->m_operations[index];
- if (operation->isOutputOperation(this->m_context.isRendering()) && operation->isPreviewOperation()) {
- unsigned int resolution[2] = {0, 0};
- unsigned int preferredResolution[2] = {0, 0};
- operation->determineResolution(resolution, preferredResolution);
- operation->setResolution(resolution);
- }
- }
-
- // add convert resolution operations when needed.
- for (index = 0; index < this->m_connections.size(); index++) {
- SocketConnection *connection = this->m_connections[index];
- if (connection->isValid()) {
- if (connection->needsResolutionConversion()) {
- Converter::convertResolution(connection, this);
- }
- }
- }
-}
-
-void ExecutionSystem::groupOperations()
-{
- vector<NodeOperation *> outputOperations;
- NodeOperation *operation;
- unsigned int index;
- // surround complex operations with ReadBufferOperation and WriteBufferOperation
- for (index = 0; index < this->m_operations.size(); index++) {
- operation = this->m_operations[index];
- if (operation->isComplex()) {
- this->addReadWriteBufferOperations(operation);
- }
- }
- ExecutionSystemHelper::findOutputNodeOperations(&outputOperations, this->getOperations(), this->m_context.isRendering());
- for (vector<NodeOperation *>::iterator iter = outputOperations.begin(); iter != outputOperations.end(); ++iter) {
- operation = *iter;
- ExecutionGroup *group = new ExecutionGroup();
- group->addOperation(this, operation);
- group->setOutputExecutionGroup(true);
- ExecutionSystemHelper::addExecutionGroup(this->getExecutionGroups(), group);
- }
-}
-
-void ExecutionSystem::addSocketConnection(SocketConnection *connection)
-{
- this->m_connections.push_back(connection);
-}
-
-void ExecutionSystem::removeSocketConnection(SocketConnection *connection)
-{
- for (vector<SocketConnection *>::iterator it = m_connections.begin(); it != m_connections.end(); ++it) {
- if (*it == connection) {
- this->m_connections.erase(it);
- return;
- }
- }
-}
-
-
void ExecutionSystem::findOutputExecutionGroup(vector<ExecutionGroup *> *result, CompositorPriority priority) const
{
unsigned int index;
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.h b/source/blender/compositor/intern/COM_ExecutionSystem.h
index 7402ff90fb5..ab903206f0a 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.h
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.h
@@ -29,7 +29,6 @@ class ExecutionGroup;
#include "DNA_node_types.h"
#include <vector>
#include "COM_Node.h"
-#include "COM_SocketConnection.h"
#include "BKE_text.h"
#include "COM_ExecutionGroup.h"
#include "COM_NodeOperation.h"
@@ -73,7 +72,7 @@ using namespace std;
* As values are ordered differently than colors a conversion happens.
*
* - Image size conversions: the system can automatically convert when resolutions do not match.
- * An InputSocket has a resize mode. This can be any of the following settings.
+ * An NodeInput has a resize mode. This can be any of the following settings.
* - [@ref InputSocketResizeMode.COM_SC_CENTER]: The center of both images are aligned
* - [@ref InputSocketResizeMode.COM_SC_FIT_WIDTH]: The width of both images are aligned
* - [@ref InputSocketResizeMode.COM_SC_FIT_HEIGHT]: the height of both images are aligned
@@ -115,6 +114,10 @@ using namespace std;
* @brief the ExecutionSystem contains the whole compositor tree.
*/
class ExecutionSystem {
+public:
+ typedef std::vector<NodeOperation*> Operations;
+ typedef std::vector<ExecutionGroup*> Groups;
+
private:
/**
* @brief the context used during execution
@@ -122,34 +125,17 @@ private:
CompositorContext m_context;
/**
- * @brief vector of nodes
- */
- vector<Node *> m_nodes;
-
- /**
* @brief vector of operations
*/
- vector<NodeOperation *> m_operations;
+ Operations m_operations;
/**
* @brief vector of groups
*/
- vector<ExecutionGroup *> m_groups;
-
- /**
- * @brief vector of connections
- */
- vector<SocketConnection *> m_connections;
+ Groups m_groups;
private: //methods
/**
- * @brief add ReadBufferOperation and WriteBufferOperation around an operation
- * @param operation the operation to add the bufferoperations around.
- */
- void addReadWriteBufferOperations(NodeOperation *operation);
-
-
- /**
* find all execution group with output nodes
*/
void findOutputExecutionGroup(vector<ExecutionGroup *> *result, CompositorPriority priority) const;
@@ -175,6 +161,7 @@ public:
*/
~ExecutionSystem();
+ void set_operations(const Operations &operations, const Groups &groups);
/**
* @brief execute this system
@@ -185,70 +172,16 @@ public:
void execute();
/**
- * @brief Add an operation to the operation list
- *
- * @param operation the operation to add
- */
- void addOperation(NodeOperation *operation);
-
- /**
- * Add an editor link to the system. convert it to an socketconnection (CPP-representative)
- * this converted socket is returned.
- */
- SocketConnection *addNodeLink(bNodeLink *bNodeLink);
- void addSocketConnection(SocketConnection *connection);
-
- /**
- * Remove a socket connection from the system.
- */
- void removeSocketConnection(SocketConnection *connection);
-
- /**
- * @brief Convert all nodes to operations
- */
- void convertToOperations();
-
- /**
- * @brief group operations in ExecutionGroup's
- * @see ExecutionGroup
- */
- void groupOperations();
-
- /**
* @brief get the reference to the compositor context
*/
- CompositorContext &getContext() { return this->m_context; }
-
- /**
- * @brief get the reference to the compositor nodes
- */
- vector<Node *> &getNodes() { return this->m_nodes; }
-
- /**
- * @brief get the reference to the compositor connections
- */
- vector<SocketConnection *>& getConnections() { return this->m_connections; }
-
- /**
- * @brief get the reference to the list of execution groups
- */
- vector<ExecutionGroup *>& getExecutionGroups() { return this->m_groups; }
-
- /**
- * @brief get the reference to the list of operations
- */
- vector<NodeOperation *>& getOperations() { return this->m_operations; }
+ const CompositorContext &getContext() const { return this->m_context; }
private:
-
- /**
- * @brief determine the actual data types of all sockets
- * @param nodes list of nodes or operations to do the data type determination
- */
- void determineActualSocketDataTypes(vector<NodeBase *> &nodes);
-
void executeGroups(CompositorPriority priority);
+ /* allow the DebugInfo class to look at internals */
+ friend class DebugInfo;
+
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("COM:ExecutionSystem")
#endif
diff --git a/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp b/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp
deleted file mode 100644
index 7def96d426e..00000000000
--- a/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright 2011, Blender Foundation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_ExecutionSystemHelper.h"
-
-#include "PIL_time.h"
-
-#include "COM_Converter.h"
-#include "COM_NodeOperation.h"
-#include "COM_ExecutionGroup.h"
-#include "COM_NodeBase.h"
-#include "COM_WorkScheduler.h"
-#include "COM_ReadBufferOperation.h"
-#include "COM_GroupNode.h"
-#include "COM_WriteBufferOperation.h"
-#include "COM_ReadBufferOperation.h"
-#include "COM_ViewerOperation.h"
-#include "COM_Debug.h"
-
-extern "C" {
-#include "BKE_node.h"
-}
-
-void ExecutionSystemHelper::addbNodeTree(ExecutionSystem &system, int nodes_start, bNodeTree *tree, bNodeInstanceKey parent_key)
-{
- vector<Node *>& nodes = system.getNodes();
- vector<SocketConnection *>& links = system.getConnections();
-
- const bNodeTree *basetree = system.getContext().getbNodeTree();
- /* update viewers in the active edittree as well the base tree (for backdrop) */
- bool is_active_group = ((parent_key.value == basetree->active_viewer_key.value) ||
- (tree == basetree));
-
- /* add all nodes of the tree to the node list */
- bNode *node = (bNode *)tree->nodes.first;
- while (node != NULL) {
- Node *nnode = addNode(nodes, node, is_active_group, system.getContext().isFastCalculation());
- if (nnode) {
- nnode->setbNodeTree(tree);
- nnode->setInstanceKey(BKE_node_instance_key(parent_key, tree, node));
- }
- node = node->next;
- }
-
- NodeRange node_range(nodes.begin() + nodes_start, nodes.end());
-
- /* add all nodelinks of the tree to the link list */
- bNodeLink *nodelink = (bNodeLink *)tree->links.first;
- while (nodelink != NULL) {
- addNodeLink(node_range, links, nodelink);
- nodelink = nodelink->next;
- }
-
- /* Expand group nodes
- * Only go up to nodes_end, to avoid ungrouping nested node groups repeatedly.
- */
- int nodes_end = nodes.size();
- for (unsigned int i = nodes_start; i < nodes_end; ++i) {
- Node *execnode = nodes[i];
- if (execnode->isGroupNode()) {
- GroupNode *groupNode = (GroupNode *)execnode;
- groupNode->ungroup(system);
- }
- }
-}
-
-void ExecutionSystemHelper::addNode(vector<Node *>& nodes, Node *node)
-{
- nodes.push_back(node);
-}
-
-Node *ExecutionSystemHelper::addNode(vector<Node *>& nodes, bNode *b_node, bool inActiveGroup, bool fast)
-{
- Node *node = Converter::convert(b_node, fast);
- if (node) {
- node->setIsInActiveGroup(inActiveGroup);
- addNode(nodes, node);
-
- DebugInfo::node_added(node);
- }
- return node;
-}
-void ExecutionSystemHelper::addOperation(vector<NodeOperation *>& operations, NodeOperation *operation)
-{
- operations.push_back(operation);
-}
-
-void ExecutionSystemHelper::addExecutionGroup(vector<ExecutionGroup *>& executionGroups, ExecutionGroup *executionGroup)
-{
- executionGroups.push_back(executionGroup);
-}
-
-void ExecutionSystemHelper::findOutputNodeOperations(vector<NodeOperation *> *result, vector<NodeOperation *>& operations, bool rendering)
-{
- unsigned int index;
-
- for (index = 0; index < operations.size(); index++) {
- NodeOperation *operation = operations[index];
- if (operation->isOutputOperation(rendering)) {
- result->push_back(operation);
- }
- }
-}
-
-static InputSocket *find_input(NodeRange &node_range, bNode *bnode, bNodeSocket *bsocket)
-{
- for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
- Node *node = *it;
- InputSocket *input = node->findInputSocketBybNodeSocket(bsocket);
- if (input)
- return input;
- }
- return NULL;
-}
-static OutputSocket *find_output(NodeRange &node_range, bNode *bnode, bNodeSocket *bsocket)
-{
- for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
- Node *node = *it;
- OutputSocket *output = node->findOutputSocketBybNodeSocket(bsocket);
- if (output)
- return output;
- }
- return NULL;
-}
-SocketConnection *ExecutionSystemHelper::addNodeLink(NodeRange &node_range, vector<SocketConnection *>& links, bNodeLink *b_nodelink)
-{
- /// @note: ignore invalid links
- if (!(b_nodelink->flag & NODE_LINK_VALID))
- return NULL;
-
- InputSocket *inputSocket = find_input(node_range, b_nodelink->tonode, b_nodelink->tosock);
- OutputSocket *outputSocket = find_output(node_range, b_nodelink->fromnode, b_nodelink->fromsock);
- if (inputSocket == NULL || outputSocket == NULL) {
- return NULL;
- }
- if (inputSocket->isConnected()) {
- return NULL;
- }
- SocketConnection *connection = addLink(links, outputSocket, inputSocket);
- return connection;
-}
-
-SocketConnection *ExecutionSystemHelper::addLink(vector<SocketConnection *>& links, OutputSocket *fromSocket, InputSocket *toSocket)
-{
- SocketConnection *newconnection = new SocketConnection();
- newconnection->setFromSocket(fromSocket);
- newconnection->setToSocket(toSocket);
- fromSocket->addConnection(newconnection);
- toSocket->setConnection(newconnection);
- links.push_back(newconnection);
- return newconnection;
-}
diff --git a/source/blender/compositor/intern/COM_ExecutionSystemHelper.h b/source/blender/compositor/intern/COM_ExecutionSystemHelper.h
deleted file mode 100644
index ae9e75e0408..00000000000
--- a/source/blender/compositor/intern/COM_ExecutionSystemHelper.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2011, Blender Foundation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-class ExecutionGroup;
-
-#ifndef _COM_ExecutionSystemHelper_h
-#define _COM_ExecutionSystemHelper_h
-
-#include "DNA_node_types.h"
-#include <vector>
-#include "COM_Node.h"
-#include "COM_SocketConnection.h"
-#include "BKE_text.h"
-#include "COM_ExecutionGroup.h"
-
-using namespace std;
-
-/**
- *
- */
-class ExecutionSystemHelper {
-
-public:
-
- /**
- * @brief add an bNodeTree to the nodes list and connections
- * @param system Execution system
- * @param nodes_start Starting index in the system's nodes list for nodes in this tree.
- * @param tree bNodeTree to add
- * @return Node representing the "Compositor node" of the maintree. or NULL when a subtree is added
- */
- static void addbNodeTree(ExecutionSystem &system, int nodes_start, bNodeTree *tree, bNodeInstanceKey parent_key);
-
- /**
- * @brief add an editor node to the system.
- * this node is converted to a Node instance.
- * and the converted node is returned
- *
- * @param b_node node to add
- * @return Node that represents the bNode or null when not able to convert.
- */
- static Node *addNode(vector<Node *>& nodes, bNode *b_node, bool isInActiveGroup, bool fast);
-
- /**
- * @brief Add a Node to a list
- *
- * @param nodes the list where the node needs to be added to
- * @param node the node to be added
- */
- static void addNode(vector<Node *>& nodes, Node *node);
-
- /**
- * @brief Add an operation to the operation list
- *
- * The id of the operation is updated.
- *
- * @param operations the list where the operation need to be added to
- * @param operation the operation to add
- */
- static void addOperation(vector<NodeOperation *> &operations, NodeOperation *operation);
-
- /**
- * @brief Add an ExecutionGroup to a list
- *
- * The id of the ExecutionGroup is updated.
- *
- * @param executionGroups the list where the executionGroup need to be added to
- * @param executionGroup the ExecutionGroup to add
- */
- static void addExecutionGroup(vector<ExecutionGroup *>& executionGroups, ExecutionGroup *executionGroup);
-
- /**
- * Find all Node Operations that needs to be executed.
- * @param rendering
- * the rendering parameter will tell what type of execution we are doing
- * false is editing, true is rendering
- */
- static void findOutputNodeOperations(vector<NodeOperation *> *result, vector<NodeOperation *>& operations, bool rendering);
-
- /**
- * @brief add a bNodeLink to the list of links
- * the bNodeLink will be wrapped in a SocketConnection
- *
- * @note Cyclic links will be ignored
- *
- * @param node_range list of possible nodes for lookup.
- * @param links list of links to add the bNodeLink to
- * @param bNodeLink the link to be added
- * @return the created SocketConnection or NULL
- */
- static SocketConnection *addNodeLink(NodeRange &node_range, vector<SocketConnection *>& links, bNodeLink *bNodeLink);
-
- /**
- * @brief create a new SocketConnection and add to a vector of links
- * @param links the vector of links
- * @param fromSocket the startpoint of the connection
- * @param toSocket the endpoint of the connection
- * @return the new created SocketConnection
- */
- static SocketConnection *addLink(vector<SocketConnection *>& links, OutputSocket *fromSocket, InputSocket *toSocket);
-
-#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:ExecutionSystemHelper")
-#endif
-};
-
-#endif /* _COM_ExecutionSystemHelper_h */
diff --git a/source/blender/compositor/intern/COM_InputSocket.cpp b/source/blender/compositor/intern/COM_InputSocket.cpp
deleted file mode 100644
index 6868745d631..00000000000
--- a/source/blender/compositor/intern/COM_InputSocket.cpp
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright 2011, Blender Foundation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_Socket.h"
-#include "COM_Node.h"
-#include "COM_SocketConnection.h"
-#include "COM_ExecutionSystem.h"
-
-InputSocket::InputSocket(DataType datatype) : Socket(datatype)
-{
- this->m_connection = NULL;
- this->m_resizeMode = COM_SC_CENTER;
-}
-InputSocket::InputSocket(DataType datatype, InputSocketResizeMode resizeMode) : Socket(datatype)
-{
- this->m_connection = NULL;
- this->m_resizeMode = resizeMode;
-}
-
-InputSocket::InputSocket(InputSocket *from) : Socket(from->getDataType())
-{
- this->m_connection = NULL;
- this->m_resizeMode = from->getResizeMode();
-}
-
-int InputSocket::isInputSocket() const { return true; }
-const int InputSocket::isConnected() const { return this->m_connection != NULL; }
-
-void InputSocket::setConnection(SocketConnection *connection)
-{
- this->m_connection = connection;
-}
-SocketConnection *InputSocket::getConnection()
-{
- return this->m_connection;
-}
-
-void InputSocket::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
-{
- if (this->isConnected()) {
- this->m_connection->getFromSocket()->determineResolution(resolution, preferredResolution);
- }
- else {
- return;
- }
-}
-
-void InputSocket::relinkConnections(InputSocket *relinkToSocket)
-{
- if (!isConnected()) {
- return;
- }
- SocketConnection *connection = this->getConnection();
- connection->setToSocket(relinkToSocket);
- relinkToSocket->setConnection(connection);
- this->setConnection(NULL);
-}
-
-void InputSocket::relinkConnectionsDuplicate(InputSocket *relinkToSocket, int editorNodeInputSocketIndex, ExecutionSystem *graph)
-{
- if (!this->isConnected()) {
- Node *node = (Node *)this->getNode();
- switch (this->getDataType()) {
- case COM_DT_COLOR:
- node->addSetColorOperation(graph, relinkToSocket, editorNodeInputSocketIndex);
- break;
- case COM_DT_VECTOR:
- node->addSetVectorOperation(graph, relinkToSocket, editorNodeInputSocketIndex);
- break;
- case COM_DT_VALUE:
- node->addSetValueOperation(graph, relinkToSocket, editorNodeInputSocketIndex);
- break;
- }
- return;
- }
- SocketConnection *newConnection = new SocketConnection();
- OutputSocket *fromSocket = this->getConnection()->getFromSocket();
- newConnection->setToSocket(relinkToSocket);
- newConnection->setFromSocket(fromSocket);
- relinkToSocket->setConnection(newConnection);
- fromSocket->addConnection(newConnection);
- graph->addSocketConnection(newConnection);
-}
-
-void InputSocket::relinkConnections(InputSocket *relinkToSocket, int editorNodeInputSocketIndex, ExecutionSystem *graph)
-{
- if (isConnected()) {
- relinkConnections(relinkToSocket);
- }
- else {
- Node *node = (Node *)this->getNode();
- switch (this->getDataType()) {
- case COM_DT_COLOR:
- node->addSetColorOperation(graph, relinkToSocket, editorNodeInputSocketIndex);
- break;
- case COM_DT_VECTOR:
- node->addSetVectorOperation(graph, relinkToSocket, editorNodeInputSocketIndex);
- break;
- case COM_DT_VALUE:
- node->addSetValueOperation(graph, relinkToSocket, editorNodeInputSocketIndex);
- break;
- }
- }
-}
-
-void InputSocket::unlinkConnections(ExecutionSystem *system)
-{
- SocketConnection *connection = getConnection();
- if (connection) {
- system->removeSocketConnection(connection);
- connection->getFromSocket()->removeConnection(connection);
- setConnection(NULL);
- delete connection;
- }
-}
-
-bool InputSocket::isStatic()
-{
- if (isConnected()) {
- NodeBase *node = this->getConnection()->getFromNode();
- if (node) {
- return node->isStatic();
- }
- }
- return true;
-}
-SocketReader *InputSocket::getReader()
-{
- return this->getOperation();
-}
-
-NodeOperation *InputSocket::getOperation() const
-{
- if (isConnected()) {
- return (NodeOperation *)this->m_connection->getFromSocket()->getNode();
- }
- else {
- return NULL;
- }
-}
diff --git a/source/blender/compositor/intern/COM_InputSocket.h b/source/blender/compositor/intern/COM_InputSocket.h
deleted file mode 100644
index 23490b66bba..00000000000
--- a/source/blender/compositor/intern/COM_InputSocket.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright 2011, Blender Foundation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_InputSocket_h
-#define _COM_InputSocket_h
-
-#include <vector>
-#include "COM_Socket.h"
-#include "COM_SocketReader.h"
-
-using namespace std;
-class SocketConnection;
-class Node;
-class ExecutionSystem;
-class OutputSocket;
-class ChannelInfo;
-class NodeOperation;
-
-/**
- * @brief Resize modes of inputsockets
- * How are the input and working resolutions matched
- * @ingroup Model
- */
-typedef enum InputSocketResizeMode {
- /** @brief Center the input image to the center of the working area of the node, no resizing occurs */
- COM_SC_CENTER = NS_CR_CENTER,
- /** @brief The bottom left of the input image is the bottom left of the working area of the node, no resizing occurs */
- COM_SC_NO_RESIZE = NS_CR_NONE,
- /** @brief Fit the width of the input image to the width of the working area of the node */
- COM_SC_FIT_WIDTH = NS_CR_FIT_WIDTH,
- /** @brief Fit the height of the input image to the height of the working area of the node */
- COM_SC_FIT_HEIGHT = NS_CR_FIT_HEIGHT,
- /** @brief Fit the width or the height of the input image to the width or height of the working area of the node, image will be larger than the working area */
- COM_SC_FIT = NS_CR_FIT,
- /** @brief Fit the width and the height of the input image to the width and height of the working area of the node, image will be equally larger than the working area */
- COM_SC_STRETCH = NS_CR_STRETCH
-} InputSocketResizeMode;
-
-/**
- * @brief InputSocket are sockets that can receive data/input
- * @ingroup Model
- */
-class InputSocket : public Socket {
-private:
- /**
- * @brief connection connected to this InputSocket.
- * An input socket can only have a single connection
- */
- SocketConnection *m_connection;
-
- /**
- * @brief resize mode of this socket
- */
- InputSocketResizeMode m_resizeMode;
-
-
-public:
- InputSocket(DataType datatype);
- InputSocket(DataType datatype, InputSocketResizeMode resizeMode);
- InputSocket(InputSocket *from);
-
- void setConnection(SocketConnection *connection);
- SocketConnection *getConnection();
-
- const int isConnected() const;
- int isInputSocket() const;
-
- /**
- * @brief determine the resolution of this data going through this socket
- * @param resolution the result of this operation
- * @param preferredResolution the preferable resolution as no resolution could be determined
- */
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
-
- /**
- * @brief move all connections of this input socket to another socket
- * only use this method when already checked the availability of a SocketConnection
- * @param relinkToSocket the socket to move to connections to
- */
- void relinkConnections(InputSocket *relinkToSocket);
-
- /**
- * @brief move all connections of this input socket to another socket
- * @param relinkToSocket the socket to move to connections to
- * @param editorNodeInputSocketIndex index of the socket number of the bNode (used to retrieve the value for autoconnection)
- * @param system ExecutionSystem to update to
- */
- void relinkConnections(InputSocket *relinkToSocket, int editorNodeInputSocketIndex, ExecutionSystem *system);
-
- /**
- * @brief add a connection of this input socket to another socket
- * @warning make sure to remove the original connection with \a unlinkConnections afterward.
- * @param relinkToSocket the socket to move to connections to
- * @param editorNodeInputSocketIndex index of the socket number of the bNode (used to retrieve the value for autoconnection)
- * @param system ExecutionSystem to update to
- */
- void relinkConnectionsDuplicate(InputSocket *relinkToSocket, int editorNodeInputSocketIndex, ExecutionSystem *system);
-
- /**
- * @brief remove all connections of this input socket.
- * @warning \a relinkConnectionsDuplicate should be used to ensure this socket is still connected.
- * @param system ExecutionSystem to update to
- */
- void unlinkConnections(ExecutionSystem *system);
-
- /**
- * @brief set the resize mode
- * @param resizeMode the new resize mode.
- */
- void setResizeMode(InputSocketResizeMode resizeMode) {
- this->m_resizeMode = resizeMode;
- }
-
- /**
- * @brief get the resize mode of this socket
- * @return InputSocketResizeMode
- */
- InputSocketResizeMode getResizeMode() const {
- return this->m_resizeMode;
- }
-
- const ChannelInfo *getChannelInfo(const int channelnumber);
-
- bool isStatic();
-
- SocketReader *getReader();
- NodeOperation *getOperation() const;
-};
-
-#endif
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cpp b/source/blender/compositor/intern/COM_MemoryBuffer.cpp
index aa2a5475d38..04828bfe3f8 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.cpp
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.cpp
@@ -21,8 +21,11 @@
*/
#include "COM_MemoryBuffer.h"
+
#include "MEM_guardedalloc.h"
-//#include "BKE_global.h"
+
+using std::min;
+using std::max;
unsigned int MemoryBuffer::determineBufferSize()
{
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h
index 521e3c6231e..d6ef9cd673e 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.h
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.h
@@ -27,6 +27,7 @@ class MemoryBuffer;
#include "COM_ExecutionGroup.h"
#include "COM_MemoryProxy.h"
+#include "COM_SocketReader.h"
extern "C" {
# include "BLI_math.h"
diff --git a/source/blender/compositor/intern/COM_MemoryProxy.h b/source/blender/compositor/intern/COM_MemoryProxy.h
index 696c843e7c4..233b035a2d7 100644
--- a/source/blender/compositor/intern/COM_MemoryProxy.h
+++ b/source/blender/compositor/intern/COM_MemoryProxy.h
@@ -28,6 +28,7 @@ class MemoryProxy;
#include "COM_ExecutionGroup.h"
class ExecutionGroup;
+class WriteBufferOperation;
/**
* @brief A MemoryProxy is a unique identifier for a memory buffer.
diff --git a/source/blender/compositor/intern/COM_Node.cpp b/source/blender/compositor/intern/COM_Node.cpp
index b62e2d08d9a..67f4d2523f3 100644
--- a/source/blender/compositor/intern/COM_Node.cpp
+++ b/source/blender/compositor/intern/COM_Node.cpp
@@ -22,27 +22,32 @@
#include <string.h>
+extern "C" {
#include "BKE_node.h"
-#include "COM_Node.h"
-#include "COM_NodeOperation.h"
-#include "COM_SetValueOperation.h"
-#include "COM_SetVectorOperation.h"
-#include "COM_SetColorOperation.h"
-#include "COM_SocketConnection.h"
+#include "RNA_access.h"
+}
+
#include "COM_ExecutionSystem.h"
-#include "COM_PreviewOperation.h"
+#include "COM_NodeOperation.h"
#include "COM_TranslateOperation.h"
#include "COM_SocketProxyNode.h"
-//#include <stdio.h>
#include "COM_defines.h"
-Node::Node(bNode *editorNode, bool create_sockets) : NodeBase()
+#include "COM_Node.h" /* own include */
+
+/**************
+ **** Node ****
+ **************/
+
+Node::Node(bNode *editorNode, bool create_sockets) :
+ m_editorNodeTree(NULL),
+ m_editorNode(editorNode),
+ m_inActiveGroup(false),
+ m_instanceKey(NODE_INSTANCE_KEY_NONE)
{
- setbNode(editorNode);
-
if (create_sockets) {
bNodeSocket *input = (bNodeSocket *)editorNode->inputs.first;
while (input != NULL) {
@@ -50,7 +55,7 @@ Node::Node(bNode *editorNode, bool create_sockets) : NodeBase()
if (input->type == SOCK_RGBA) dt = COM_DT_COLOR;
if (input->type == SOCK_VECTOR) dt = COM_DT_VECTOR;
- this->addInputSocket(dt, (InputSocketResizeMode)input->resizemode, input);
+ this->addInputSocket(dt, input);
input = input->next;
}
bNodeSocket *output = (bNodeSocket *)editorNode->outputs.first;
@@ -65,102 +70,50 @@ Node::Node(bNode *editorNode, bool create_sockets) : NodeBase()
}
}
-void Node::addSetValueOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex)
+Node::~Node()
{
- InputSocket *input = getInputSocket(editorNodeInputSocketIndex);
- SetValueOperation *operation = new SetValueOperation();
- operation->setValue(input->getEditorValueFloat());
- this->addLink(graph, operation->getOutputSocket(), inputsocket);
- graph->addOperation(operation);
+ while (!this->m_outputsockets.empty()) {
+ delete (this->m_outputsockets.back());
+ this->m_outputsockets.pop_back();
+ }
+ while (!this->m_inputsockets.empty()) {
+ delete (this->m_inputsockets.back());
+ this->m_inputsockets.pop_back();
+ }
}
-void Node::addPreviewOperation(ExecutionSystem *system, CompositorContext *context, OutputSocket *outputSocket)
+void Node::addInputSocket(DataType datatype)
{
- if (this->isInActiveGroup()) {
- if (!(this->getbNode()->flag & NODE_HIDDEN)) { // do not calculate previews of hidden nodes.
- bNodeInstanceHash *previews = context->getPreviewHash();
- if (previews && (this->getbNode()->flag & NODE_PREVIEW)) {
- PreviewOperation *operation = new PreviewOperation(context->getViewSettings(), context->getDisplaySettings());
- system->addOperation(operation);
- operation->setbNode(this->getbNode());
- operation->setbNodeTree(system->getContext().getbNodeTree());
- operation->verifyPreview(previews, this->getInstanceKey());
- this->addLink(system, outputSocket, operation->getInputSocket(0));
- }
- }
- }
+ this->addInputSocket(datatype, NULL);
}
-void Node::addPreviewOperation(ExecutionSystem *system, CompositorContext *context, InputSocket *inputSocket)
+void Node::addInputSocket(DataType datatype, bNodeSocket *bSocket)
{
- if (inputSocket->isConnected() && this->isInActiveGroup()) {
- OutputSocket *outputsocket = inputSocket->getConnection()->getFromSocket();
- this->addPreviewOperation(system, context, outputsocket);
- }
+ NodeInput *socket = new NodeInput(this, bSocket, datatype);
+ this->m_inputsockets.push_back(socket);
}
-SocketConnection *Node::addLink(ExecutionSystem *graph, OutputSocket *outputSocket, InputSocket *inputsocket)
+void Node::addOutputSocket(DataType datatype)
{
- if (inputsocket->isConnected()) {
- return NULL;
- }
- SocketConnection *connection = new SocketConnection();
- connection->setFromSocket(outputSocket);
- outputSocket->addConnection(connection);
- connection->setToSocket(inputsocket);
- inputsocket->setConnection(connection);
- graph->addSocketConnection(connection);
- return connection;
-}
-
-void Node::addSetColorOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex)
-{
- InputSocket *input = getInputSocket(editorNodeInputSocketIndex);
- SetColorOperation *operation = new SetColorOperation();
- float col[4];
- input->getEditorValueColor(col);
- operation->setChannel1(col[0]);
- operation->setChannel2(col[1]);
- operation->setChannel3(col[2]);
- operation->setChannel4(col[3]);
- this->addLink(graph, operation->getOutputSocket(), inputsocket);
- graph->addOperation(operation);
-}
-
-void Node::addSetVectorOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex)
-{
- InputSocket *input = getInputSocket(editorNodeInputSocketIndex);
- SetVectorOperation *operation = new SetVectorOperation();
- float vec[3];
- input->getEditorValueVector(vec);
- operation->setX(vec[0]);
- operation->setY(vec[1]);
- operation->setZ(vec[2]);
- this->addLink(graph, operation->getOutputSocket(), inputsocket);
- graph->addOperation(operation);
-}
-
-NodeOperation *Node::convertToOperations_invalid_index(ExecutionSystem *graph, int index)
-{
- const float warning_color[4] = {1.0f, 0.0f, 1.0f, 1.0f};
- SetColorOperation *operation = new SetColorOperation();
- operation->setChannels(warning_color);
-
- /* link the operation */
- this->getOutputSocket(index)->relinkConnections(operation->getOutputSocket());
- graph->addOperation(operation);
- return operation;
-}
-
-/* when a node has no valid data (missing image / group pointer, or missing renderlayer from EXR) */
-void Node::convertToOperations_invalid(ExecutionSystem *graph, CompositorContext *context)
-{
- /* this is a really bad situation - bring on the pink! - so artists know this is bad */
- int index;
- vector<OutputSocket *> &outputsockets = this->getOutputSockets();
- for (index = 0; index < outputsockets.size(); index++) {
- convertToOperations_invalid_index(graph, index);
- }
+ this->addOutputSocket(datatype, NULL);
+
+}
+void Node::addOutputSocket(DataType datatype, bNodeSocket *bSocket)
+{
+ NodeOutput *socket = new NodeOutput(this, bSocket, datatype);
+ this->m_outputsockets.push_back(socket);
+}
+
+NodeOutput *Node::getOutputSocket(unsigned int index) const
+{
+ BLI_assert(index < this->m_outputsockets.size());
+ return this->m_outputsockets[index];
+}
+
+NodeInput *Node::getInputSocket(unsigned int index) const
+{
+ BLI_assert(index < this->m_inputsockets.size());
+ return this->m_inputsockets[index];
}
bNodeSocket *Node::getEditorInputSocket(int editorNodeInputSocketIndex)
@@ -190,28 +143,74 @@ bNodeSocket *Node::getEditorOutputSocket(int editorNodeInputSocketIndex)
return NULL;
}
-InputSocket *Node::findInputSocketBybNodeSocket(bNodeSocket *socket)
+
+/*******************
+ **** NodeInput ****
+ *******************/
+
+NodeInput::NodeInput(Node *node, bNodeSocket *b_socket, DataType datatype) :
+ m_node(node),
+ m_editorSocket(b_socket),
+ m_datatype(datatype),
+ m_link(NULL)
{
- vector<InputSocket *> &inputsockets = this->getInputSockets();
- unsigned int index;
- for (index = 0; index < inputsockets.size(); index++) {
- InputSocket *input = inputsockets[index];
- if (input->getbNodeSocket() == socket) {
- return input;
- }
- }
- return NULL;
}
-OutputSocket *Node::findOutputSocketBybNodeSocket(bNodeSocket *socket)
+void NodeInput::setLink(NodeOutput *link)
{
- vector<OutputSocket *> &outputsockets = this->getOutputSockets();
- unsigned int index;
- for (index = 0; index < outputsockets.size(); index++) {
- OutputSocket *output = outputsockets[index];
- if (output->getbNodeSocket() == socket) {
- return output;
- }
- }
- return NULL;
+ m_link = link;
+}
+
+float NodeInput::getEditorValueFloat()
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
+ return RNA_float_get(&ptr, "default_value");
+}
+
+void NodeInput::getEditorValueColor(float *value)
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
+ return RNA_float_get_array(&ptr, "default_value", value);
+}
+
+void NodeInput::getEditorValueVector(float *value)
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
+ return RNA_float_get_array(&ptr, "default_value", value);
+}
+
+
+/********************
+ **** NodeOutput ****
+ ********************/
+
+NodeOutput::NodeOutput(Node *node, bNodeSocket *b_socket, DataType datatype) :
+ m_node(node),
+ m_editorSocket(b_socket),
+ m_datatype(datatype)
+{
+}
+
+float NodeOutput::getEditorValueFloat()
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
+ return RNA_float_get(&ptr, "default_value");
+}
+
+void NodeOutput::getEditorValueColor(float *value)
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
+ return RNA_float_get_array(&ptr, "default_value", value);
+}
+
+void NodeOutput::getEditorValueVector(float *value)
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
+ return RNA_float_get_array(&ptr, "default_value", value);
}
diff --git a/source/blender/compositor/intern/COM_Node.h b/source/blender/compositor/intern/COM_Node.h
index c14a1973da5..6046af24c55 100644
--- a/source/blender/compositor/intern/COM_Node.h
+++ b/source/blender/compositor/intern/COM_Node.h
@@ -23,32 +23,50 @@
#ifndef __COM_NODE_H__
#define __COM_NODE_H__
-#include "COM_NodeBase.h"
-#include "COM_InputSocket.h"
-#include "COM_OutputSocket.h"
-#include "COM_CompositorContext.h"
#include "DNA_node_types.h"
#include "BKE_text.h"
-#include "COM_ExecutionSystem.h"
#include <vector>
#include <string>
#include <algorithm>
-using namespace std;
+/* common node includes
+ * added here so node files don't have to include themselves
+ */
+#include "COM_CompositorContext.h"
+#include "COM_NodeConverter.h"
class Node;
class NodeOperation;
-class ExecutionSystem;
-
-typedef vector<Node *> NodeList;
-typedef NodeList::iterator NodeIterator;
-typedef pair<NodeIterator, NodeIterator> NodeRange;
+class NodeConverter;
/**
* My node documentation.
*/
-class Node : public NodeBase {
+class Node {
+public:
+ typedef std::vector<NodeInput *> Inputs;
+ typedef std::vector<NodeOutput *> Outputs;
+
private:
+ /**
+ * @brief stores the reference to the SDNA bNode struct
+ */
+ bNodeTree *m_editorNodeTree;
+
+ /**
+ * @brief stores the reference to the SDNA bNode struct
+ */
+ bNode *m_editorNode;
+
+ /**
+ * @brief the list of actual inputsockets @see NodeInput
+ */
+ Inputs m_inputsockets;
+
+ /**
+ * @brief the list of actual outputsockets @see NodeOutput
+ */
+ Outputs m_outputsockets;
/**
* @brief Is this node part of the active group
@@ -60,10 +78,81 @@ private:
*/
bNodeInstanceKey m_instanceKey;
+protected:
+ /**
+ * @brief get access to the vector of input sockets
+ */
+ const Inputs &getInputSockets() const { return this->m_inputsockets; }
+
+ /**
+ * @brief get access to the vector of input sockets
+ */
+ const Outputs &getOutputSockets() const { return this->m_outputsockets; }
+
public:
Node(bNode *editorNode, bool create_sockets = true);
+ virtual ~Node();
+
+ /**
+ * @brief get the reference to the SDNA bNode struct
+ */
+ bNode *getbNode() const {return m_editorNode;}
/**
+ * @brief get the reference to the SDNA bNodeTree struct
+ */
+ bNodeTree *getbNodeTree() const {return m_editorNodeTree;}
+
+ /**
+ * @brief set the reference to the bNode
+ * @note used in Node instances to receive the storage/settings and complex node for highlight during execution
+ * @param bNode
+ */
+ void setbNode(bNode *node) {this->m_editorNode = node;}
+
+ /**
+ * @brief set the reference to the bNodeTree
+ * @param bNodeTree
+ */
+ void setbNodeTree(bNodeTree *nodetree) {this->m_editorNodeTree = nodetree;}
+
+ /**
+ * @brief Return the number of input sockets of this node.
+ */
+ const unsigned int getNumberOfInputSockets() const { return this->m_inputsockets.size(); }
+
+ /**
+ * @brief Return the number of output sockets of this node.
+ */
+ const unsigned int getNumberOfOutputSockets() const { return this->m_outputsockets.size(); }
+
+ /**
+ * get the reference to a certain outputsocket
+ * @param index
+ * the index of the needed outputsocket
+ */
+ NodeOutput *getOutputSocket(const unsigned int index) const;
+
+ /**
+ * get the reference to the first outputsocket
+ * @param index
+ * the index of the needed outputsocket
+ */
+ inline NodeOutput *getOutputSocket() const { return getOutputSocket(0); }
+
+ /**
+ * get the reference to a certain inputsocket
+ * @param index
+ * the index of the needed inputsocket
+ */
+ NodeInput *getInputSocket(const unsigned int index) const;
+
+ /** Check if this is an input node
+ * An input node is a node that only has output sockets and no input sockets
+ */
+ bool isInputNode() const { return m_inputsockets.empty(); }
+
+ /**
* @brief Is this node in the active group (the group that is being edited)
* @param isInActiveGroup
*/
@@ -75,7 +164,7 @@ public:
* the active group will be the main tree (all nodes that are not part of a group will be active)
* @return bool [false:true]
*/
- inline bool isInActiveGroup() { return this->m_inActiveGroup; }
+ inline bool isInActiveGroup() const { return this->m_inActiveGroup; }
/**
* @brief convert node to operation
@@ -85,76 +174,99 @@ public:
* @param system the ExecutionSystem where the operations need to be added
* @param context reference to the CompositorContext
*/
- virtual void convertToOperations(ExecutionSystem *system, CompositorContext *context) = 0;
-
- /**
- * this method adds a SetValueOperation as input of the input socket.
- * This can only be used from the convertToOperation method. all other usages are not allowed
- */
- void addSetValueOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex);
-
- /**
- * this method adds a SetColorOperation as input of the input socket.
- * This can only be used from the convertToOperation method. all other usages are not allowed
- */
- void addSetColorOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex);
-
- /**
- * this method adds a SetVectorOperation as input of the input socket.
- * This can only be used from the convertToOperation method. all other usages are not allowed
- */
- void addSetVectorOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex);
+ virtual void convertToOperations(NodeConverter &converter, const CompositorContext &context) const = 0;
/**
* Create dummy warning operation, use when we can't get the source data.
*/
- NodeOperation *convertToOperations_invalid_index(ExecutionSystem *graph, int index);
+ NodeOperation *convertToOperations_invalid_index(NodeConverter *compiler, int index) const;
/**
* when a node has no valid data (missing image or a group nodes ID pointer is NULL)
* call this function from #convertToOperations, this way the node sockets are converted
* into valid outputs, without this the compositor system gets confused and crashes, see [#32490]
*/
- void convertToOperations_invalid(ExecutionSystem *graph, CompositorContext *context);
-
- /**
- * Creates a new link between an outputSocket and inputSocket and registrates the link to the graph
- * @return the new created link
- */
- SocketConnection *addLink(ExecutionSystem *graph, OutputSocket *outputSocket, InputSocket *inputsocket);
+ void convertToOperations_invalid(NodeConverter *compiler) const;
+ void setInstanceKey(bNodeInstanceKey instance_key) { m_instanceKey = instance_key; }
+ bNodeInstanceKey getInstanceKey() const { return m_instanceKey; }
+
+protected:
/**
- * is this node a group node.
- */
- virtual bool isGroupNode() const { return false; }
- /**
- * is this node a proxy node.
+ * @brief add an NodeInput to the collection of inputsockets
+ * @note may only be called in an constructor
+ * @param socket the NodeInput to add
*/
- virtual bool isProxyNode() const { return false; }
+ void addInputSocket(DataType datatype);
+ void addInputSocket(DataType datatype, bNodeSocket *socket);
/**
- * @brief find the InputSocket by bNodeSocket
- *
- * @param socket
+ * @brief add an NodeOutput to the collection of outputsockets
+ * @note may only be called in an constructor
+ * @param socket the NodeOutput to add
*/
- InputSocket *findInputSocketBybNodeSocket(bNodeSocket *socket);
+ void addOutputSocket(DataType datatype);
+ void addOutputSocket(DataType datatype, bNodeSocket *socket);
+
+ bNodeSocket *getEditorInputSocket(int editorNodeInputSocketIndex);
+ bNodeSocket *getEditorOutputSocket(int editorNodeOutputSocketIndex);
+};
+
+
+/**
+ * @brief NodeInput are sockets that can receive data/input
+ * @ingroup Model
+ */
+class NodeInput {
+private:
+ Node *m_node;
+ bNodeSocket *m_editorSocket;
+
+ DataType m_datatype;
/**
- * @brief find the OutputSocket by bNodeSocket
- *
- * @param socket
+ * @brief link connected to this NodeInput.
+ * An input socket can only have a single link
*/
- OutputSocket *findOutputSocketBybNodeSocket(bNodeSocket *socket);
+ NodeOutput *m_link;
- void setInstanceKey(bNodeInstanceKey instance_key) { m_instanceKey = instance_key; }
- bNodeInstanceKey getInstanceKey() const { return m_instanceKey; }
+public:
+ NodeInput(Node *node, bNodeSocket *b_socket, DataType datatype);
-protected:
- void addPreviewOperation(ExecutionSystem *system, CompositorContext *context, InputSocket *inputSocket);
- void addPreviewOperation(ExecutionSystem *system, CompositorContext *context, OutputSocket *outputSocket);
+ Node *getNode() const { return this->m_node; }
+ DataType getDataType() const { return m_datatype; }
+ bNodeSocket *getbNodeSocket() const { return this->m_editorSocket; }
- bNodeSocket *getEditorInputSocket(int editorNodeInputSocketIndex);
- bNodeSocket *getEditorOutputSocket(int editorNodeOutputSocketIndex);
+ void setLink(NodeOutput *link);
+ bool isLinked() const { return m_link; }
+ NodeOutput *getLink() { return m_link; }
+
+ float getEditorValueFloat();
+ void getEditorValueColor(float *value);
+ void getEditorValueVector(float *value);
+};
+
+
+/**
+ * @brief NodeOutput are sockets that can send data/input
+ * @ingroup Model
+ */
+class NodeOutput {
private:
+ Node *m_node;
+ bNodeSocket *m_editorSocket;
+
+ DataType m_datatype;
+
+public:
+ NodeOutput(Node *node, bNodeSocket *b_socket, DataType datatype);
+
+ Node *getNode() const { return this->m_node; }
+ DataType getDataType() const { return m_datatype; }
+ bNodeSocket *getbNodeSocket() const { return this->m_editorSocket; }
+
+ float getEditorValueFloat();
+ void getEditorValueColor(float *value);
+ void getEditorValueVector(float *value);
};
#endif /* __COM_NODE_H__ */
diff --git a/source/blender/compositor/intern/COM_NodeBase.cpp b/source/blender/compositor/intern/COM_NodeBase.cpp
deleted file mode 100644
index 5c2ce37bdea..00000000000
--- a/source/blender/compositor/intern/COM_NodeBase.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2011, Blender Foundation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include <string.h>
-
-#include "BKE_node.h"
-
-#include "COM_NodeBase.h"
-#include "COM_NodeOperation.h"
-#include "COM_SetValueOperation.h"
-#include "COM_SetColorOperation.h"
-#include "COM_SocketConnection.h"
-#include "COM_ExecutionSystem.h"
-
-NodeBase::NodeBase()
-{
- this->m_editorNode = NULL;
-}
-
-
-NodeBase::~NodeBase()
-{
- while (!this->m_outputsockets.empty()) {
- delete (this->m_outputsockets.back());
- this->m_outputsockets.pop_back();
- }
- while (!this->m_inputsockets.empty()) {
- delete (this->m_inputsockets.back());
- this->m_inputsockets.pop_back();
- }
-}
-
-void NodeBase::addInputSocket(DataType datatype)
-{
- this->addInputSocket(datatype, COM_SC_CENTER, NULL);
-}
-
-void NodeBase::addInputSocket(DataType datatype, InputSocketResizeMode resizeMode)
-{
- this->addInputSocket(datatype, resizeMode, NULL);
-}
-void NodeBase::addInputSocket(DataType datatype, InputSocketResizeMode resizeMode, bNodeSocket *bSocket)
-{
- InputSocket *socket = new InputSocket(datatype, resizeMode);
- socket->setEditorSocket(bSocket);
- socket->setNode(this);
- this->m_inputsockets.push_back(socket);
-}
-
-void NodeBase::addOutputSocket(DataType datatype)
-{
- this->addOutputSocket(datatype, NULL);
-
-}
-void NodeBase::addOutputSocket(DataType datatype, bNodeSocket *bSocket)
-{
- OutputSocket *socket = new OutputSocket(datatype);
- socket->setEditorSocket(bSocket);
- socket->setNode(this);
- this->m_outputsockets.push_back(socket);
-}
-const bool NodeBase::isInputNode() const
-{
- return this->m_inputsockets.size() == 0;
-}
-
-OutputSocket *NodeBase::getOutputSocket(unsigned int index)
-{
- BLI_assert(index < this->m_outputsockets.size());
- return this->m_outputsockets[index];
-}
-
-InputSocket *NodeBase::getInputSocket(unsigned int index)
-{
- BLI_assert(index < this->m_inputsockets.size());
- return this->m_inputsockets[index];
-}
diff --git a/source/blender/compositor/intern/COM_NodeBase.h b/source/blender/compositor/intern/COM_NodeBase.h
deleted file mode 100644
index e2072575509..00000000000
--- a/source/blender/compositor/intern/COM_NodeBase.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright 2011, Blender Foundation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef __COM_NODEBASE_H__
-#define __COM_NODEBASE_H__
-
-#include "COM_InputSocket.h"
-#include "COM_OutputSocket.h"
-#include "DNA_node_types.h"
-#include "BKE_text.h"
-#include <vector>
-#include <string>
-
-using namespace std;
-
-
-class NodeOperation;
-class ExecutionSystem;
-
-/**
- * @brief The NodeBase class is the super-class of all node related objects like @see Node @see NodeOperation
- * the reason for the existence of this class is to support graph-nodes when using ExecutionSystem
- * the NodeBase also contains the reference to InputSocket and OutputSocket.
- * @ingroup Model
- */
-class NodeBase {
-private:
- /**
- * @brief the list of actual inputsockets @see InputSocket
- */
- vector<InputSocket *> m_inputsockets;
-
- /**
- * @brief the list of actual outputsockets @see OutputSocket
- */
- vector<OutputSocket *> m_outputsockets;
-
- /**
- * @brief stores the reference to the SDNA bNode struct
- */
- bNode *m_editorNode;
-
- /**
- * @brief stores the reference to the SDNA bNode struct
- */
- bNodeTree *m_editorNodeTree;
-
-protected:
- /**
- * @brief get access to the vector of input sockets
- */
- inline vector<InputSocket *>& getInputSockets() { return this->m_inputsockets; }
-
- /**
- * @brief get access to the vector of input sockets
- */
- inline vector<OutputSocket *>& getOutputSockets() { return this->m_outputsockets; }
-
-
-protected:
- /**
- * @brief destructor
- * clean up memory related to this NodeBase.
- */
- virtual ~NodeBase();
-
-public:
- /**
- * @brief get the reference to the SDNA bNode struct
- */
- bNode *getbNode() const {return m_editorNode;}
-
- /**
- * @brief get the reference to the SDNA bNodeTree struct
- */
- bNodeTree *getbNodeTree() const {return m_editorNodeTree;}
-
- /**
- * @brief set the reference to the bNode
- * @note used in Node instances to receive the storage/settings and complex node for highlight during execution
- * @param bNode
- */
- void setbNode(bNode *node) {this->m_editorNode = node;}
-
- /**
- * @brief set the reference to the bNodeTree
- * @param bNodeTree
- */
- void setbNodeTree(bNodeTree *nodetree) {this->m_editorNodeTree = nodetree;}
-
- /**
- * @brief is this node an operation?
- * This is true when the instance is of the subclass NodeOperation.
- * @return [true:false]
- * @see NodeOperation
- */
- virtual const bool isOperation() const { return false; }
-
- /**
- * @brief check if this is an input node
- * An input node is a node that only has output sockets and no input sockets
- * @return [false..true]
- */
- const bool isInputNode() const;
-
- /**
- * @brief Return the number of input sockets of this node.
- */
- const unsigned int getNumberOfInputSockets() const { return this->m_inputsockets.size(); }
-
- /**
- * @brief Return the number of output sockets of this node.
- */
- const unsigned int getNumberOfOutputSockets() const { return this->m_outputsockets.size(); }
-
- /**
- * get the reference to a certain outputsocket
- * @param index
- * the index of the needed outputsocket
- */
- OutputSocket *getOutputSocket(const unsigned int index);
-
- /**
- * get the reference to the first outputsocket
- * @param index
- * the index of the needed outputsocket
- */
- inline OutputSocket *getOutputSocket() { return getOutputSocket(0); }
-
- /**
- * get the reference to a certain inputsocket
- * @param index
- * the index of the needed inputsocket
- */
- InputSocket *getInputSocket(const unsigned int index);
-
- virtual bool isStatic() const { return false; }
- void getStaticValues(float *result) const { }
-
-protected:
- NodeBase();
-
- /**
- * @brief add an InputSocket to the collection of inputsockets
- * @note may only be called in an constructor
- * @param socket the InputSocket to add
- */
- void addInputSocket(DataType datatype);
- void addInputSocket(DataType datatype, InputSocketResizeMode resizeMode);
- void addInputSocket(DataType datatype, InputSocketResizeMode resizeMode, bNodeSocket *socket);
-
- /**
- * @brief add an OutputSocket to the collection of outputsockets
- * @note may only be called in an constructor
- * @param socket the OutputSocket to add
- */
- void addOutputSocket(DataType datatype);
- void addOutputSocket(DataType datatype, bNodeSocket *socket);
-
-
-#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeBase")
-#endif
-};
-
-#endif /* __COM_NODEBASE_H__ */
diff --git a/source/blender/compositor/intern/COM_NodeConverter.cpp b/source/blender/compositor/intern/COM_NodeConverter.cpp
new file mode 100644
index 00000000000..833fcedbc53
--- /dev/null
+++ b/source/blender/compositor/intern/COM_NodeConverter.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ * Lukas Toenne
+ */
+
+extern "C" {
+#include "BLI_utildefines.h"
+}
+
+#include "COM_Debug.h"
+
+#include "COM_NodeOperationBuilder.h"
+#include "COM_NodeOperation.h"
+#include "COM_SetValueOperation.h"
+#include "COM_SetVectorOperation.h"
+#include "COM_SetColorOperation.h"
+#include "COM_SocketProxyOperation.h"
+
+#include "COM_NodeConverter.h" /* own include */
+
+NodeConverter::NodeConverter(NodeOperationBuilder *builder) :
+ m_builder(builder)
+{
+}
+
+void NodeConverter::addOperation(NodeOperation *operation)
+{
+ m_builder->addOperation(operation);
+}
+
+void NodeConverter::mapInputSocket(NodeInput *node_socket, NodeOperationInput *operation_socket)
+{
+ m_builder->mapInputSocket(node_socket, operation_socket);
+}
+
+void NodeConverter::mapOutputSocket(NodeOutput *node_socket, NodeOperationOutput *operation_socket)
+{
+ m_builder->mapOutputSocket(node_socket, operation_socket);
+}
+
+void NodeConverter::addLink(NodeOperationOutput *from, NodeOperationInput *to)
+{
+ m_builder->addLink(from, to);
+}
+
+void NodeConverter::addPreview(NodeOperationOutput *output)
+{
+ m_builder->addPreview(output);
+}
+
+void NodeConverter::addNodeInputPreview(NodeInput *input)
+{
+ m_builder->addNodeInputPreview(input);
+}
+
+NodeOperation *NodeConverter::setInvalidOutput(NodeOutput *output)
+{
+ /* this is a really bad situation - bring on the pink! - so artists know this is bad */
+ const float warning_color[4] = {1.0f, 0.0f, 1.0f, 1.0f};
+
+ SetColorOperation *operation = new SetColorOperation();
+ operation->setChannels(warning_color);
+
+ m_builder->addOperation(operation);
+ m_builder->mapOutputSocket(output, operation->getOutputSocket());
+
+ return operation;
+}
+
+NodeOperationOutput *NodeConverter::addInputProxy(NodeInput *input)
+{
+ SocketProxyOperation *proxy = new SocketProxyOperation(input->getDataType());
+ m_builder->addOperation(proxy);
+
+ m_builder->mapInputSocket(input, proxy->getInputSocket(0));
+
+ return proxy->getOutputSocket();
+}
+
+NodeOperationInput *NodeConverter::addOutputProxy(NodeOutput *output)
+{
+ SocketProxyOperation *proxy = new SocketProxyOperation(output->getDataType());
+ m_builder->addOperation(proxy);
+
+ m_builder->mapOutputSocket(output, proxy->getOutputSocket());
+
+ return proxy->getInputSocket(0);
+}
+
+void NodeConverter::addOutputValue(NodeOutput *output, float value)
+{
+ SetValueOperation *operation = new SetValueOperation();
+ operation->setValue(value);
+
+ m_builder->addOperation(operation);
+ m_builder->mapOutputSocket(output, operation->getOutputSocket());
+}
+
+void NodeConverter::addOutputColor(NodeOutput *output, const float value[4])
+{
+ SetColorOperation *operation = new SetColorOperation();
+ operation->setChannels(value);
+
+ m_builder->addOperation(operation);
+ m_builder->mapOutputSocket(output, operation->getOutputSocket());
+}
+
+void NodeConverter::addOutputVector(NodeOutput *output, const float value[3])
+{
+ SetVectorOperation *operation = new SetVectorOperation();
+ operation->setVector(value);
+
+ m_builder->addOperation(operation);
+ m_builder->mapOutputSocket(output, operation->getOutputSocket());
+}
diff --git a/source/blender/compositor/intern/COM_NodeConverter.h b/source/blender/compositor/intern/COM_NodeConverter.h
new file mode 100644
index 00000000000..51a1a44cade
--- /dev/null
+++ b/source/blender/compositor/intern/COM_NodeConverter.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ * Lukas Toenne
+ */
+
+#ifndef _COM_NodeCompiler_h
+#define _COM_NodeCompiler_h
+
+class NodeInput;
+class NodeOutput;
+
+class NodeOperation;
+class NodeOperationInput;
+class NodeOperationOutput;
+class NodeOperationBuilder;
+
+/** Interface type for converting a \a Node into \a NodeOperation.
+ * This is passed to \a Node::convertToOperation methods and allows them
+ * to register any number of operations, create links between them,
+ * and map original node sockets to their inputs or outputs.
+ */
+class NodeConverter {
+public:
+ NodeConverter(NodeOperationBuilder *builder);
+
+ /** Insert a new operation into the operations graph.
+ * The operation must be created by the node.
+ */
+ void addOperation(NodeOperation *operation);
+
+ /** Map input socket of the node to an operation socket.
+ * Links between nodes will then generate equivalent links between
+ * the mapped operation sockets.
+ *
+ * \note A \a Node input can be mapped to multiple \a NodeOperation inputs.
+ */
+ void mapInputSocket(NodeInput *node_socket, NodeOperationInput *operation_socket);
+ /** Map output socket of the node to an operation socket.
+ * Links between nodes will then generate equivalent links between
+ * the mapped operation sockets.
+ *
+ * \note A \a Node output can only be mapped to one \a NodeOperation output.
+ * Any existing operation output mapping will be replaced.
+ */
+ void mapOutputSocket(NodeOutput *node_socket, NodeOperationOutput *operation_socket);
+
+ /** Create a proxy operation for a node input.
+ * This operation will be removed later and replaced
+ * by direct links between the connected operations.
+ */
+ NodeOperationOutput *addInputProxy(NodeInput *input);
+ /** Create a proxy operation for a node output.
+ * This operation will be removed later and replaced
+ * by direct links between the connected operations.
+ */
+ NodeOperationInput *addOutputProxy(NodeOutput *output);
+
+ /** Define a constant output value. */
+ void addOutputValue(NodeOutput *output, float value);
+ /** Define a constant output color. */
+ void addOutputColor(NodeOutput *output, const float value[4]);
+ /** Define a constant output vector. */
+ void addOutputVector(NodeOutput *output, const float value[3]);
+
+ /** Add an explicit link between two operations. */
+ void addLink(NodeOperationOutput *from, NodeOperationInput *to);
+
+ /** Add a preview operation for a operation output. */
+ void addPreview(NodeOperationOutput *output);
+ /** Add a preview operation for a node input. */
+ void addNodeInputPreview(NodeInput *input);
+
+ /** When a node has no valid data
+ * @note missing image / group pointer, or missing renderlayer from EXR
+ */
+ NodeOperation *setInvalidOutput(NodeOutput *output);
+
+private:
+ /** The internal builder for storing the results of the graph construction. */
+ NodeOperationBuilder *m_builder;
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeCompiler")
+#endif
+};
+
+#endif /* _COM_NodeCompiler_h */
diff --git a/source/blender/compositor/intern/COM_NodeGraph.cpp b/source/blender/compositor/intern/COM_NodeGraph.cpp
new file mode 100644
index 00000000000..d942d43befc
--- /dev/null
+++ b/source/blender/compositor/intern/COM_NodeGraph.cpp
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ * Lukas Toenne
+ */
+
+#include <cstring>
+
+extern "C" {
+#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_node_types.h"
+
+#include "BKE_node.h"
+}
+
+#include "COM_CompositorContext.h"
+#include "COM_Converter.h"
+#include "COM_Debug.h"
+#include "COM_Node.h"
+#include "COM_SocketProxyNode.h"
+
+#include "COM_NodeGraph.h" /* own include */
+
+/*******************
+ **** NodeGraph ****
+ *******************/
+
+NodeGraph::NodeGraph()
+{
+}
+
+NodeGraph::~NodeGraph()
+{
+ for (int index = 0; index < this->m_nodes.size(); index++) {
+ Node *node = this->m_nodes[index];
+ delete node;
+ }
+}
+
+void NodeGraph::from_bNodeTree(const CompositorContext &context, bNodeTree *tree)
+{
+ add_bNodeTree(context, 0, tree, NODE_INSTANCE_KEY_BASE);
+}
+
+bNodeSocket *NodeGraph::find_b_node_input(bNode *b_group_node, const char *identifier)
+{
+ for (bNodeSocket *b_sock = (bNodeSocket *)b_group_node->inputs.first; b_sock; b_sock = b_sock->next) {
+ if (STREQ(b_sock->identifier, identifier))
+ return b_sock;
+ }
+ return NULL;
+}
+
+bNodeSocket *NodeGraph::find_b_node_output(bNode *b_group_node, const char *identifier)
+{
+ for (bNodeSocket *b_sock = (bNodeSocket *)b_group_node->outputs.first; b_sock; b_sock = b_sock->next) {
+ if (STREQ(b_sock->identifier, identifier))
+ return b_sock;
+ }
+ return NULL;
+}
+
+void NodeGraph::add_node(Node *node, bNodeTree *b_ntree, bNodeInstanceKey key, bool is_active_group)
+{
+ node->setbNodeTree(b_ntree);
+ node->setInstanceKey(key);
+ node->setIsInActiveGroup(is_active_group);
+
+ m_nodes.push_back(node);
+
+ DebugInfo::node_added(node);
+}
+
+void NodeGraph::add_link(NodeOutput *fromSocket, NodeInput *toSocket)
+{
+ m_links.push_back(Link(fromSocket, toSocket));
+
+ /* register with the input */
+ toSocket->setLink(fromSocket);
+}
+
+void NodeGraph::add_bNodeTree(const CompositorContext &context, int nodes_start, bNodeTree *tree, bNodeInstanceKey parent_key)
+{
+ const bNodeTree *basetree = context.getbNodeTree();
+
+ /* update viewers in the active edittree as well the base tree (for backdrop) */
+ bool is_active_group = ((parent_key.value == basetree->active_viewer_key.value) ||
+ (tree == basetree));
+
+ /* add all nodes of the tree to the node list */
+ for (bNode *node = (bNode *)tree->nodes.first; node; node = node->next) {
+ bNodeInstanceKey key = BKE_node_instance_key(parent_key, tree, node);
+ add_bNode(context, tree, node, key, is_active_group);
+ }
+
+ NodeRange node_range(m_nodes.begin() + nodes_start, m_nodes.end());
+ /* add all nodelinks of the tree to the link list */
+ for (bNodeLink *nodelink = (bNodeLink *)tree->links.first; nodelink; nodelink = nodelink->next) {
+ add_bNodeLink(node_range, nodelink);
+ }
+}
+
+void NodeGraph::add_bNode(const CompositorContext &context, bNodeTree *b_ntree, bNode *b_node, bNodeInstanceKey key, bool is_active_group)
+{
+ /* replace muted nodes by proxies for internal links */
+ if (b_node->flag & NODE_MUTED) {
+ add_proxies_mute(b_ntree, b_node, key, is_active_group);
+ return;
+ }
+
+ /* replace slow nodes with proxies for fast execution */
+ if (context.isFastCalculation() && !Converter::is_fast_node(b_node)) {
+ add_proxies_skip(b_ntree, b_node, key, is_active_group);
+ return;
+ }
+
+ /* special node types */
+ if (b_node->type == NODE_GROUP) {
+ add_proxies_group(context, b_node, key);
+ return;
+ }
+
+ Node *node = Converter::convert(b_node);
+ if (node)
+ add_node(node, b_ntree, key, is_active_group);
+}
+
+NodeInput *NodeGraph::find_input(const NodeRange &node_range, bNodeSocket *b_socket)
+{
+ for (NodeGraph::NodeIterator it = node_range.first; it != node_range.second; ++it) {
+ Node *node = *it;
+ for (int index = 0; index < node->getNumberOfInputSockets(); index++) {
+ NodeInput *input = node->getInputSocket(index);
+ if (input->getbNodeSocket() == b_socket)
+ return input;
+ }
+ }
+ return NULL;
+}
+
+NodeOutput *NodeGraph::find_output(const NodeRange &node_range, bNodeSocket *b_socket)
+{
+ for (NodeGraph::NodeIterator it = node_range.first; it != node_range.second; ++it) {
+ Node *node = *it;
+ for (int index = 0; index < node->getNumberOfOutputSockets(); index++) {
+ NodeOutput *output = node->getOutputSocket(index);
+ if (output->getbNodeSocket() == b_socket)
+ return output;
+ }
+ }
+ return NULL;
+}
+
+void NodeGraph::add_bNodeLink(const NodeRange &node_range, bNodeLink *b_nodelink)
+{
+ /// @note: ignore invalid links
+ if (!(b_nodelink->flag & NODE_LINK_VALID))
+ return;
+
+ NodeInput *input = find_input(node_range, b_nodelink->tosock);
+ NodeOutput *output = find_output(node_range, b_nodelink->fromsock);
+ if (!input || !output)
+ return;
+ if (input->isLinked())
+ return;
+
+ add_link(output, input);
+}
+
+/* **** Special proxy node type conversions **** */
+
+void NodeGraph::add_proxies_mute(bNodeTree *b_ntree, bNode *b_node, bNodeInstanceKey key, bool is_active_group)
+{
+ for (bNodeLink *b_link = (bNodeLink *)b_node->internal_links.first; b_link; b_link = b_link->next) {
+ SocketProxyNode *proxy = new SocketProxyNode(b_node, b_link->fromsock, b_link->tosock);
+ add_node(proxy, b_ntree, key, is_active_group);
+ }
+}
+
+void NodeGraph::add_proxies_skip(bNodeTree *b_ntree, bNode *b_node, bNodeInstanceKey key, bool is_active_group)
+{
+ for (bNodeSocket *output = (bNodeSocket *)b_node->outputs.first; output; output = output->next) {
+ bNodeSocket *input;
+
+ /* look for first input with matching datatype for each output */
+ for (input = (bNodeSocket *)b_node->inputs.first; input; input = input->next) {
+ if (input->type == output->type)
+ break;
+ }
+
+ if (input) {
+ SocketProxyNode *proxy = new SocketProxyNode(b_node, input, output);
+ add_node(proxy, b_ntree, key, is_active_group);
+ }
+ }
+}
+
+void NodeGraph::add_proxies_group_inputs(bNode *b_node, bNode *b_node_io)
+{
+ bNodeTree *b_group_tree = (bNodeTree *)b_node->id;
+ BLI_assert(b_group_tree); /* should have been checked in advance */
+
+ /* not important for proxies */
+ bNodeInstanceKey key = NODE_INSTANCE_KEY_BASE;
+ bool is_active_group = false;
+
+ for (bNodeSocket *b_sock_io = (bNodeSocket *)b_node_io->outputs.first; b_sock_io; b_sock_io = b_sock_io->next) {
+ bNodeSocket *b_sock_group = find_b_node_input(b_node, b_sock_io->identifier);
+ if (b_sock_group) {
+ SocketProxyNode *proxy = new SocketProxyNode(b_node_io, b_sock_group, b_sock_io);
+ add_node(proxy, b_group_tree, key, is_active_group);
+ }
+ }
+}
+
+void NodeGraph::add_proxies_group_outputs(bNode *b_node, bNode *b_node_io, bool use_buffer)
+{
+ bNodeTree *b_group_tree = (bNodeTree *)b_node->id;
+ BLI_assert(b_group_tree); /* should have been checked in advance */
+
+ /* not important for proxies */
+ bNodeInstanceKey key = NODE_INSTANCE_KEY_BASE;
+ bool is_active_group = false;
+
+ for (bNodeSocket *b_sock_io = (bNodeSocket *)b_node_io->inputs.first; b_sock_io; b_sock_io = b_sock_io->next) {
+ bNodeSocket *b_sock_group = find_b_node_output(b_node, b_sock_io->identifier);
+ if (b_sock_group) {
+ if (use_buffer) {
+ SocketBufferNode *buffer = new SocketBufferNode(b_node_io, b_sock_io, b_sock_group);
+ add_node(buffer, b_group_tree, key, is_active_group);
+ }
+ else {
+ SocketProxyNode *proxy = new SocketProxyNode(b_node_io, b_sock_io, b_sock_group);
+ add_node(proxy, b_group_tree, key, is_active_group);
+ }
+ }
+ }
+}
+
+void NodeGraph::add_proxies_group(const CompositorContext &context, bNode *b_node, bNodeInstanceKey key)
+{
+ bNodeTree *b_group_tree = (bNodeTree *)b_node->id;
+
+ /* missing node group datablock can happen with library linking */
+ if (!b_group_tree) {
+ /* this error case its handled in convertToOperations() so we don't get un-convertred sockets */
+ return;
+ }
+
+ /* use node list size before adding proxies, so they can be connected in add_bNodeTree */
+ int nodes_start = m_nodes.size();
+
+ /* create proxy nodes for group input/output nodes */
+ for (bNode *b_node_io = (bNode *)b_group_tree->nodes.first; b_node_io; b_node_io = b_node_io->next) {
+ if (b_node_io->type == NODE_GROUP_INPUT)
+ add_proxies_group_inputs(b_node, b_node_io);
+
+ if (b_node_io->type == NODE_GROUP_OUTPUT && (b_node_io->flag & NODE_DO_OUTPUT))
+ add_proxies_group_outputs(b_node, b_node_io, context.isGroupnodeBufferEnabled());
+ }
+
+ add_bNodeTree(context, nodes_start, b_group_tree, key);
+}
diff --git a/source/blender/compositor/intern/COM_NodeGraph.h b/source/blender/compositor/intern/COM_NodeGraph.h
new file mode 100644
index 00000000000..6e2a46e3622
--- /dev/null
+++ b/source/blender/compositor/intern/COM_NodeGraph.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ * Lukas Toenne
+ */
+
+#ifndef _COM_NodeGraph_h
+#define _COM_NodeGraph_h
+
+#include <map>
+#include <set>
+#include <vector>
+
+extern "C" {
+#include "DNA_node_types.h"
+}
+
+class CompositorContext;
+class Node;
+class NodeInput;
+class NodeOutput;
+
+/** Internal representation of DNA node data.
+ * This structure is converted into operations by \a NodeCompiler.
+ */
+class NodeGraph {
+public:
+ class Link {
+ private:
+ NodeOutput *m_from;
+ NodeInput *m_to;
+
+ public:
+ Link(NodeOutput *from, NodeInput *to) :
+ m_from(from),
+ m_to(to)
+ {}
+
+ NodeOutput *getFromSocket() const { return m_from; }
+ NodeInput *getToSocket() const { return m_to; }
+ };
+
+ typedef std::vector<Node *> Nodes;
+ typedef Nodes::iterator NodeIterator;
+ typedef std::vector<Link> Links;
+
+private:
+ Nodes m_nodes;
+ Links m_links;
+
+public:
+ NodeGraph();
+ ~NodeGraph();
+
+ const Nodes &nodes() const { return m_nodes; }
+ const Links &links() const { return m_links; }
+
+ void from_bNodeTree(const CompositorContext &context, bNodeTree *tree);
+
+protected:
+ typedef std::pair<NodeIterator, NodeIterator> NodeRange;
+
+ static bNodeSocket *find_b_node_input(bNode *b_node, const char *identifier);
+ static bNodeSocket *find_b_node_output(bNode *b_node, const char *identifier);
+
+ void add_node(Node *node, bNodeTree *b_ntree, bNodeInstanceKey key, bool is_active_group);
+ void add_link(NodeOutput *fromSocket, NodeInput *toSocket);
+
+ void add_bNodeTree(const CompositorContext &context, int nodes_start, bNodeTree *tree, bNodeInstanceKey parent_key);
+
+ void add_bNode(const CompositorContext &context, bNodeTree *b_ntree, bNode *b_node, bNodeInstanceKey key, bool is_active_group);
+
+ NodeInput *find_input(const NodeRange &node_range, bNodeSocket *b_socket);
+ NodeOutput *find_output(const NodeRange &node_range, bNodeSocket *b_socket);
+ void add_bNodeLink(const NodeRange &node_range, bNodeLink *bNodeLink);
+
+ /* **** Special proxy node type conversions **** */
+ /* These nodes are not represented in the node graph themselves,
+ * but converted into a number of proxy links
+ */
+
+ void add_proxies_mute(bNodeTree *b_ntree, bNode *b_node, bNodeInstanceKey key, bool is_active_group);
+ void add_proxies_skip(bNodeTree *b_ntree, bNode *b_node, bNodeInstanceKey key, bool is_active_group);
+
+ void add_proxies_group_inputs(bNode *b_node, bNode *b_node_io);
+ void add_proxies_group_outputs(bNode *b_node, bNode *b_node_io, bool use_buffer);
+ void add_proxies_group(const CompositorContext &context, bNode *b_node, bNodeInstanceKey key);
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeGraph")
+#endif
+};
+
+#endif /* _COM_NodeGraph_h */
diff --git a/source/blender/compositor/intern/COM_NodeOperation.cpp b/source/blender/compositor/intern/COM_NodeOperation.cpp
index d33b8085022..f780c609dce 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.cpp
+++ b/source/blender/compositor/intern/COM_NodeOperation.cpp
@@ -23,12 +23,16 @@
#include <typeinfo>
#include <stdio.h>
-#include "COM_NodeOperation.h"
-#include "COM_InputSocket.h"
-#include "COM_SocketConnection.h"
#include "COM_defines.h"
+#include "COM_ExecutionSystem.h"
-NodeOperation::NodeOperation() : NodeBase()
+#include "COM_NodeOperation.h" /* own include */
+
+/*******************
+ **** NodeOperation ****
+ *******************/
+
+NodeOperation::NodeOperation()
{
this->m_resolutionInputSocketIndex = 0;
this->m_complex = false;
@@ -39,28 +43,63 @@ NodeOperation::NodeOperation() : NodeBase()
this->m_btree = NULL;
}
+NodeOperation::~NodeOperation()
+{
+ while (!this->m_outputs.empty()) {
+ delete (this->m_outputs.back());
+ this->m_outputs.pop_back();
+ }
+ while (!this->m_inputs.empty()) {
+ delete (this->m_inputs.back());
+ this->m_inputs.pop_back();
+ }
+}
+
+NodeOperationOutput *NodeOperation::getOutputSocket(unsigned int index) const
+{
+ BLI_assert(index < m_outputs.size());
+ return m_outputs[index];
+}
+
+NodeOperationInput *NodeOperation::getInputSocket(unsigned int index) const
+{
+ BLI_assert(index < m_inputs.size());
+ return m_inputs[index];
+}
+
+void NodeOperation::addInputSocket(DataType datatype, InputResizeMode resize_mode)
+{
+ NodeOperationInput *socket = new NodeOperationInput(this, datatype, resize_mode);
+ m_inputs.push_back(socket);
+}
+
+void NodeOperation::addOutputSocket(DataType datatype)
+{
+ NodeOperationOutput *socket = new NodeOperationOutput(this, datatype);
+ m_outputs.push_back(socket);
+}
+
void NodeOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
{
unsigned int temp[2];
unsigned int temp2[2];
- vector<InputSocket *> &inputsockets = this->getInputSockets();
- for (unsigned int index = 0; index < inputsockets.size(); index++) {
- InputSocket *inputSocket = inputsockets[index];
- if (inputSocket->isConnected()) {
+ for (unsigned int index = 0; index < m_inputs.size(); index++) {
+ NodeOperationInput *input = m_inputs[index];
+ if (input->isConnected()) {
if (index == this->m_resolutionInputSocketIndex) {
- inputSocket->determineResolution(resolution, preferredResolution);
+ input->determineResolution(resolution, preferredResolution);
temp2[0] = resolution[0];
temp2[1] = resolution[1];
break;
}
}
}
- for (unsigned int index = 0; index < inputsockets.size(); index++) {
- InputSocket *inputSocket = inputsockets[index];
- if (inputSocket->isConnected()) {
+ for (unsigned int index = 0; index < m_inputs.size(); index++) {
+ NodeOperationInput *input = m_inputs[index];
+ if (input->isConnected()) {
if (index != this->m_resolutionInputSocketIndex) {
- inputSocket->determineResolution(temp, temp2);
+ input->determineResolution(temp, temp2);
}
}
}
@@ -102,25 +141,29 @@ SocketReader *NodeOperation::getInputSocketReader(unsigned int inputSocketIndex)
{
return this->getInputSocket(inputSocketIndex)->getReader();
}
+
NodeOperation *NodeOperation::getInputOperation(unsigned int inputSocketIndex)
{
- return this->getInputSocket(inputSocketIndex)->getOperation();
+ NodeOperationInput *input = getInputSocket(inputSocketIndex);
+ if (input && input->isConnected())
+ return &input->getLink()->getOperation();
+ else
+ return NULL;
}
-void NodeOperation::getConnectedInputSockets(vector<InputSocket *> *sockets)
+void NodeOperation::getConnectedInputSockets(Inputs *sockets)
{
- vector<InputSocket *> &inputsockets = this->getInputSockets();
- for (vector<InputSocket *>::iterator iterator = inputsockets.begin(); iterator != inputsockets.end(); iterator++) {
- InputSocket *socket = *iterator;
- if (socket->isConnected()) {
- sockets->push_back(socket);
+ for (Inputs::const_iterator it = m_inputs.begin(); it != m_inputs.end(); ++it) {
+ NodeOperationInput *input = *it;
+ if (input->isConnected()) {
+ sockets->push_back(input);
}
}
}
bool NodeOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
{
- if (this->isInputNode()) {
+ if (isInputOperation()) {
BLI_rcti_init(output, input->xmin, input->xmax, input->ymin, input->ymax);
return false;
}
@@ -148,3 +191,56 @@ bool NodeOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOper
return !first;
}
}
+
+
+/*****************
+ **** OpInput ****
+ *****************/
+
+NodeOperationInput::NodeOperationInput(NodeOperation *op, DataType datatype, InputResizeMode resizeMode) :
+ m_operation(op),
+ m_datatype(datatype),
+ m_resizeMode(resizeMode),
+ m_link(NULL)
+{
+}
+
+SocketReader *NodeOperationInput::getReader()
+{
+ if (isConnected()) {
+ return &m_link->getOperation();
+ }
+ else {
+ return NULL;
+ }
+}
+
+void NodeOperationInput::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
+{
+ if (m_link)
+ m_link->determineResolution(resolution, preferredResolution);
+}
+
+
+/******************
+ **** OpOutput ****
+ ******************/
+
+NodeOperationOutput::NodeOperationOutput(NodeOperation *op, DataType datatype) :
+ m_operation(op),
+ m_datatype(datatype)
+{
+}
+
+void NodeOperationOutput::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
+{
+ NodeOperation &operation = getOperation();
+ if (operation.isResolutionSet()) {
+ resolution[0] = operation.getWidth();
+ resolution[1] = operation.getHeight();
+ }
+ else {
+ operation.determineResolution(resolution, preferredResolution);
+ operation.setResolution(resolution);
+ }
+}
diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h
index 160e493073e..3f636dff63c 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.h
+++ b/source/blender/compositor/intern/COM_NodeOperation.h
@@ -20,32 +20,72 @@
* Monique Dewanchand
*/
-#ifndef _COM_NodeOperation_h
-#define _COM_NodeOperation_h
-class OpenCLDevice;
-#include "COM_Node.h"
+#ifndef _COM_Operation_h
+#define _COM_Operation_h
+
+#include <list>
#include <string>
#include <sstream>
+
+extern "C" {
+#include "BLI_math_color.h"
+#include "BLI_math_vector.h"
+#include "BLI_threads.h"
+}
+
+#include "COM_Node.h"
#include "COM_MemoryBuffer.h"
#include "COM_MemoryProxy.h"
#include "COM_SocketReader.h"
+
#include "OCL_opencl.h"
-#include "list"
-#include "BLI_threads.h"
-#include "BLI_math_color.h"
-#include "BLI_math_vector.h"
+using std::list;
+using std::min;
+using std::max;
+class OpenCLDevice;
class ReadBufferOperation;
+class WriteBufferOperation;
+
+class NodeOperationInput;
+class NodeOperationOutput;
+
+/**
+ * @brief Resize modes of inputsockets
+ * How are the input and working resolutions matched
+ * @ingroup Model
+ */
+typedef enum InputResizeMode {
+ /** @brief Center the input image to the center of the working area of the node, no resizing occurs */
+ COM_SC_CENTER = NS_CR_CENTER,
+ /** @brief The bottom left of the input image is the bottom left of the working area of the node, no resizing occurs */
+ COM_SC_NO_RESIZE = NS_CR_NONE,
+ /** @brief Fit the width of the input image to the width of the working area of the node */
+ COM_SC_FIT_WIDTH = NS_CR_FIT_WIDTH,
+ /** @brief Fit the height of the input image to the height of the working area of the node */
+ COM_SC_FIT_HEIGHT = NS_CR_FIT_HEIGHT,
+ /** @brief Fit the width or the height of the input image to the width or height of the working area of the node, image will be larger than the working area */
+ COM_SC_FIT = NS_CR_FIT,
+ /** @brief Fit the width and the height of the input image to the width and height of the working area of the node, image will be equally larger than the working area */
+ COM_SC_STRETCH = NS_CR_STRETCH
+} InputResizeMode;
/**
- * @brief NodeOperation are contains calculation logic
+ * @brief NodeOperation contains calculation logic
*
* Subclasses needs to implement the execution method (defined in SocketReader) to implement logic.
* @ingroup Model
*/
-class NodeOperation : public NodeBase, public SocketReader {
+class NodeOperation : public SocketReader {
+public:
+ typedef std::vector<NodeOperationInput*> Inputs;
+ typedef std::vector<NodeOperationOutput*> Outputs;
+
private:
+ Inputs m_inputs;
+ Outputs m_outputs;
+
/**
* @brief the index of the input socket that will be used to determine the resolution
*/
@@ -85,15 +125,21 @@ private:
* @brief set to truth when resolution for this operation is set
*/
bool m_isResolutionSet;
+
public:
- /**
- * @brief is this node an operation?
- * This is true when the instance is of the subclass NodeOperation.
- * @return [true:false]
- * @see NodeBase
+ virtual ~NodeOperation();
+
+ unsigned int getNumberOfInputSockets() const { return m_inputs.size(); }
+ unsigned int getNumberOfOutputSockets() const { return m_outputs.size(); }
+ NodeOperationOutput *getOutputSocket(unsigned int index) const;
+ NodeOperationOutput *getOutputSocket() const { return getOutputSocket(0); }
+ NodeOperationInput *getInputSocket(unsigned int index) const;
+
+ /** Check if this is an input operation
+ * An input operation is an operation that only has output sockets and no input sockets
*/
- const bool isOperation() const { return true; }
-
+ bool isInputOperation() const { return m_inputs.empty(); }
+
/**
* @brief determine the resolution of this node
* @note this method will not set the resolution, this is the responsibility of the caller
@@ -117,15 +163,6 @@ public:
*/
virtual bool isOutputOperation(bool rendering) const { return false; }
- /**
- * isBufferOperation returns if this is an operation that work directly on buffers.
- *
- * there are only 2 implementation where this is true:
- * @see ReadBufferOperation
- * @see WriteBufferOperation
- * for all other operations this will result in false.
- */
- virtual int isBufferOperation() { return false; }
virtual int isSingleThreaded() { return false; }
void setbNodeTree(const bNodeTree *tree) { this->m_btree = tree; }
@@ -190,7 +227,7 @@ public:
}
- void getConnectedInputSockets(vector<InputSocket *> *sockets);
+ void getConnectedInputSockets(Inputs *sockets);
/**
* @brief is this operation complex
@@ -244,13 +281,14 @@ public:
* @see WorkScheduler.schedule
* @see ExecutionGroup.addOperation
*/
- bool isOpenCL() { return this->m_openCL; }
+ bool isOpenCL() const { return this->m_openCL; }
- virtual bool isViewerOperation() { return false; }
- virtual bool isPreviewOperation() { return false; }
- virtual bool isFileOutputOperation() { return false; }
+ virtual bool isViewerOperation() const { return false; }
+ virtual bool isPreviewOperation() const { return false; }
+ virtual bool isFileOutputOperation() const { return false; }
+ virtual bool isProxyOperation() const { return false; }
- inline bool isBreaked() {
+ inline bool isBreaked() const {
return this->m_btree->test_break(this->m_btree->tbh);
}
@@ -261,6 +299,9 @@ public:
protected:
NodeOperation();
+ void addInputSocket(DataType datatype, InputResizeMode resize_mode = COM_SC_CENTER);
+ void addOutputSocket(DataType datatype);
+
void setWidth(unsigned int width) { this->m_width = width; this->m_isResolutionSet = true; }
void setHeight(unsigned int height) { this->m_height = height; this->m_isResolutionSet = true; }
SocketReader *getInputSocketReader(unsigned int inputSocketindex);
@@ -271,7 +312,6 @@ protected:
void lockMutex();
void unlockMutex();
-
/**
* @brief set whether this operation is complex
*
@@ -285,6 +325,75 @@ protected:
*/
void setOpenCL(bool openCL) { this->m_openCL = openCL; }
+ /* allow the DebugInfo class to look at internals */
+ friend class DebugInfo;
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
+#endif
+};
+
+
+class NodeOperationInput {
+private:
+ NodeOperation *m_operation;
+
+ /** Datatype of this socket. Is used for automatically data transformation.
+ * @section data-conversion
+ */
+ DataType m_datatype;
+
+ /** Resize mode of this socket */
+ InputResizeMode m_resizeMode;
+
+ /** Connected output */
+ NodeOperationOutput *m_link;
+
+public:
+ NodeOperationInput(NodeOperation *op, DataType datatype, InputResizeMode resizeMode = COM_SC_CENTER);
+
+ NodeOperation &getOperation() const { return *m_operation; }
+ DataType getDataType() const { return m_datatype; }
+
+ void setLink(NodeOperationOutput *link) { m_link = link; }
+ NodeOperationOutput *getLink() const { return m_link; }
+ bool isConnected() const { return m_link; }
+
+ void setResizeMode(InputResizeMode resizeMode) { this->m_resizeMode = resizeMode; }
+ InputResizeMode getResizeMode() const { return this->m_resizeMode; }
+
+ SocketReader *getReader();
+
+ void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
+#endif
+};
+
+
+class NodeOperationOutput {
+private:
+ NodeOperation *m_operation;
+
+ /** Datatype of this socket. Is used for automatically data transformation.
+ * @section data-conversion
+ */
+ DataType m_datatype;
+
+public:
+ NodeOperationOutput(NodeOperation *op, DataType datatype);
+
+ NodeOperation &getOperation() const { return *m_operation; }
+ DataType getDataType() const { return m_datatype; }
+
+ /**
+ * @brief determine the resolution of this data going through this socket
+ * @param resolution the result of this operation
+ * @param preferredResolution the preferable resolution as no resolution could be determined
+ */
+ void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
#endif
diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp
new file mode 100644
index 00000000000..2807c25d7f5
--- /dev/null
+++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp
@@ -0,0 +1,661 @@
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ * Lukas Toenne
+ */
+
+extern "C" {
+#include "BLI_utildefines.h"
+}
+
+#include "COM_NodeConverter.h"
+#include "COM_Converter.h"
+#include "COM_Debug.h"
+#include "COM_ExecutionSystem.h"
+#include "COM_Node.h"
+#include "COM_SocketProxyNode.h"
+
+#include "COM_NodeOperation.h"
+#include "COM_PreviewOperation.h"
+#include "COM_SetValueOperation.h"
+#include "COM_SetVectorOperation.h"
+#include "COM_SetColorOperation.h"
+#include "COM_SocketProxyOperation.h"
+#include "COM_ReadBufferOperation.h"
+#include "COM_WriteBufferOperation.h"
+
+#include "COM_NodeOperationBuilder.h" /* own include */
+
+NodeOperationBuilder::NodeOperationBuilder(const CompositorContext *context, bNodeTree *b_nodetree) :
+ m_context(context),
+ m_current_node(NULL)
+{
+ m_graph.from_bNodeTree(*context, b_nodetree);
+}
+
+NodeOperationBuilder::~NodeOperationBuilder()
+{
+}
+
+void NodeOperationBuilder::convertToOperations(ExecutionSystem *system)
+{
+ /* interface handle for nodes */
+ NodeConverter converter(this);
+
+ for (int index = 0; index < m_graph.nodes().size(); index++) {
+ Node *node = (Node *)m_graph.nodes()[index];
+
+ m_current_node = node;
+
+ DebugInfo::node_to_operations(node);
+ node->convertToOperations(converter, *m_context);
+ }
+
+ 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);
+
+ 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);
+ 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);
+ }
+ }
+
+ add_datatype_conversions();
+
+ add_operation_input_constants();
+
+ resolve_proxies();
+
+ determineResolutions();
+
+ /* 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();
+
+ prune_operations();
+
+ /* ensure topological (link-based) order of nodes */
+ /*sort_operations();*/ /* not needed yet */
+
+ /* create execution groups */
+ group_operations();
+
+ /* transfer resulting operations to the system */
+ system->set_operations(m_operations, m_groups);
+}
+
+void NodeOperationBuilder::addOperation(NodeOperation *operation)
+{
+ m_operations.push_back(operation);
+}
+
+void NodeOperationBuilder::mapInputSocket(NodeInput *node_socket, NodeOperationInput *operation_socket)
+{
+ 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;
+}
+
+void NodeOperationBuilder::mapOutputSocket(NodeOutput *node_socket, NodeOperationOutput *operation_socket)
+{
+ BLI_assert(m_current_node);
+ BLI_assert(node_socket->getNode() == m_current_node);
+
+ m_output_map[node_socket] = operation_socket;
+}
+
+void NodeOperationBuilder::addLink(NodeOperationOutput *from, NodeOperationInput *to)
+{
+ if (to->isConnected())
+ return;
+
+ m_links.push_back(Link(from, to));
+
+ /* 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);
+
+ m_links.erase(it);
+ return;
+ }
+ }
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+PreviewOperation *NodeOperationBuilder::make_preview_operation() const
+{
+ 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;
+
+ 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;
+}
+
+void NodeOperationBuilder::addPreview(NodeOperationOutput *output)
+{
+ PreviewOperation *operation = make_preview_operation();
+ if (operation) {
+ addOperation(operation);
+
+ addLink(output, operation->getInputSocket(0));
+ }
+}
+
+void NodeOperationBuilder::addNodeInputPreview(NodeInput *input)
+{
+ PreviewOperation *operation = make_preview_operation();
+ if (operation) {
+ addOperation(operation);
+
+ mapInputSocket(input, operation->getInputSocket(0));
+ }
+}
+
+/****************************
+ **** Optimization Steps ****
+ ****************************/
+
+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;
+ 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());
+ }
+ }
+}
+
+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;
+ }
+ }
+}
+
+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);
+ }
+}
+
+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;
+}
+
+void NodeOperationBuilder::add_input_buffers(NodeOperation *operation, NodeOperationInput *input)
+{
+ if (!input->isConnected())
+ 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);
+
+ /* 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();
+ writeoperation->setbNodeTree(m_context->getbNodeTree());
+ addOperation(writeoperation);
+
+ addLink(output, writeoperation->getInputSocket(0));
+
+ writeoperation->readResolutionFromInputSocket();
+ }
+
+ /* add readbuffer op for the input */
+ ReadBufferOperation *readoperation = new ReadBufferOperation();
+ readoperation->setMemoryProxy(writeoperation->getMemoryProxy());
+ this->addOperation(readoperation);
+
+ addLink(readoperation->getOutputSocket(), input);
+
+ readoperation->readResolutionFromWriteBuffer();
+}
+
+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;
+
+ 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);
+ }
+ }
+
+ /* if no write buffer operation exists yet, create a new one */
+ if (!writeOperation) {
+ writeOperation = new WriteBufferOperation();
+ writeOperation->setbNodeTree(m_context->getbNodeTree());
+ addOperation(writeOperation);
+
+ addLink(output, writeOperation->getInputSocket(0));
+ }
+
+ 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 */
+
+ ReadBufferOperation *readoperation = new ReadBufferOperation();
+ readoperation->setMemoryProxy(writeOperation->getMemoryProxy());
+ addOperation(readoperation);
+
+ addLink(readoperation->getOutputSocket(), target);
+
+ 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);
+
+ for (Operations::const_iterator it = complex_ops.begin(); it != complex_ops.end(); ++it) {
+ NodeOperation *op = *it;
+
+ 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->getNumberOfOutputSockets(); index++)
+ add_output_buffers(op, op->getOutputSocket(index));
+ }
+}
+
+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);
+
+ 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());
+ }
+}
+
+void NodeOperationBuilder::prune_operations()
+{
+ 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);
+ }
+
+ /* 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;
+}
+
+/* topological (depth-first) sorting of operations */
+static void sort_operations_recursive(NodeOperationBuilder::Operations &sorted, Tags &visited, NodeOperation *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());
+ }
+
+ sorted.push_back(op);
+}
+
+void NodeOperationBuilder::sort_operations()
+{
+ 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);
+
+ 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 (!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);
+ }
+}
+
+ExecutionGroup *NodeOperationBuilder::make_group(NodeOperation *op)
+{
+ ExecutionGroup *group = new ExecutionGroup();
+ m_groups.push_back(group);
+
+ Tags visited;
+ add_group_operations_recursive(visited, op, 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);
+ }
+ }
+ }
+}
diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.h b/source/blender/compositor/intern/COM_NodeOperationBuilder.h
new file mode 100644
index 00000000000..ab890282bab
--- /dev/null
+++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ * Lukas Toenne
+ */
+
+#ifndef _COM_NodeCompilerImpl_h
+#define _COM_NodeCompilerImpl_h
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include "COM_NodeGraph.h"
+
+using std::vector;
+
+class CompositorContext;
+
+class Node;
+class NodeInput;
+class NodeOutput;
+
+class ExecutionSystem;
+class ExecutionGroup;
+class NodeOperation;
+class NodeOperationInput;
+class NodeOperationOutput;
+
+class PreviewOperation;
+class WriteBufferOperation;
+
+class NodeOperationBuilder {
+public:
+ class Link {
+ private:
+ NodeOperationOutput *m_from;
+ NodeOperationInput *m_to;
+
+ public:
+ Link(NodeOperationOutput *from, NodeOperationInput *to) :
+ m_from(from),
+ m_to(to)
+ {}
+
+ NodeOperationOutput *from() const { return m_from; }
+ NodeOperationInput *to() const { return m_to; }
+ };
+
+ typedef std::vector<NodeOperation *> Operations;
+ typedef std::vector<Link> Links;
+ typedef std::vector<ExecutionGroup *> Groups;
+
+ typedef std::map<NodeOperationInput *, NodeInput *> InputSocketMap;
+ typedef std::map<NodeOutput *, NodeOperationOutput *> OutputSocketMap;
+
+ typedef std::vector<NodeOperationInput *> OpInputs;
+ typedef std::map<NodeInput *, OpInputs> OpInputInverseMap;
+
+private:
+ const CompositorContext *m_context;
+ NodeGraph m_graph;
+
+ Operations m_operations;
+ Links m_links;
+ Groups m_groups;
+
+ /** Maps operation inputs to node inputs */
+ InputSocketMap m_input_map;
+ /** Maps node outputs to operation outputs */
+ OutputSocketMap m_output_map;
+
+ Node *m_current_node;
+
+public:
+ NodeOperationBuilder(const CompositorContext *context, bNodeTree *b_nodetree);
+ ~NodeOperationBuilder();
+
+ const CompositorContext &context() const { return *m_context; }
+
+ void convertToOperations(ExecutionSystem *system);
+
+ void addOperation(NodeOperation *operation);
+
+ /** Map input socket of the current node to an operation socket */
+ void mapInputSocket(NodeInput *node_socket, NodeOperationInput *operation_socket);
+ /** Map output socket of the current node to an operation socket */
+ void mapOutputSocket(NodeOutput *node_socket, NodeOperationOutput *operation_socket);
+
+ void addLink(NodeOperationOutput *from, NodeOperationInput *to);
+ void removeInputLink(NodeOperationInput *to);
+
+ /** Add a preview operation for a operation output */
+ void addPreview(NodeOperationOutput *output);
+ /** Add a preview operation for a node input */
+ void addNodeInputPreview(NodeInput *input);
+
+protected:
+ static NodeInput *find_node_input(const InputSocketMap &map, NodeOperationInput *op_input);
+ static const OpInputs &find_operation_inputs(const OpInputInverseMap &map, NodeInput *node_input);
+ static NodeOperationOutput *find_operation_output(const OutputSocketMap &map, NodeOutput *node_output);
+
+ /** Add datatype conversion where needed */
+ void add_datatype_conversions();
+
+ /** Construct a constant value operation for every unconnected input */
+ void add_operation_input_constants();
+ void add_input_constant_value(NodeOperationInput *input, NodeInput *node_input);
+
+ /** Replace proxy operations with direct links */
+ void resolve_proxies();
+
+ /** Calculate resolution for each operation */
+ void determineResolutions();
+
+ /** Helper function to store connected inputs for replacement */
+ OpInputs cache_output_links(NodeOperationOutput *output) const;
+ /** Find a connected write buffer operation to an OpOutput */
+ WriteBufferOperation *find_attached_write_buffer_operation(NodeOperationOutput *output) const;
+ /** Add read/write buffer operations around complex operations */
+ void add_complex_operation_buffers();
+ void add_input_buffers(NodeOperation *operation, NodeOperationInput *input);
+ void add_output_buffers(NodeOperation *operation, NodeOperationOutput *output);
+
+ /** Remove unreachable operations */
+ void prune_operations();
+
+ /** Sort operations by link dependencies */
+ void sort_operations();
+
+ /** Create execution groups */
+ void group_operations();
+ ExecutionGroup *make_group(NodeOperation *op);
+
+private:
+ PreviewOperation *make_preview_operation() const;
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeCompilerImpl")
+#endif
+};
+
+#endif /* _COM_NodeCompilerImpl_h */
diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.cpp b/source/blender/compositor/intern/COM_OpenCLDevice.cpp
index 30c1fb43999..2cfc10cff29 100644
--- a/source/blender/compositor/intern/COM_OpenCLDevice.cpp
+++ b/source/blender/compositor/intern/COM_OpenCLDevice.cpp
@@ -58,7 +58,7 @@ void OpenCLDevice::execute(WorkPackage *work)
MemoryBuffer **inputBuffers = executionGroup->getInputBuffersOpenCL(chunkNumber);
MemoryBuffer *outputBuffer = executionGroup->allocateOutputBuffer(chunkNumber, &rect);
- executionGroup->getOutputNodeOperation()->executeOpenCLRegion(this, &rect,
+ executionGroup->getOutputOperation()->executeOpenCLRegion(this, &rect,
chunkNumber, inputBuffers, outputBuffer);
delete outputBuffer;
diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.h b/source/blender/compositor/intern/COM_OpenCLDevice.h
index 2021cacabcc..50cc6f25f70 100644
--- a/source/blender/compositor/intern/COM_OpenCLDevice.h
+++ b/source/blender/compositor/intern/COM_OpenCLDevice.h
@@ -30,6 +30,8 @@ class OpenCLDevice;
#include "COM_WorkScheduler.h"
#include "COM_ReadBufferOperation.h"
+using std::list;
+
/**
* @brief device representing an GPU OpenCL device.
* an instance of this class represents a single cl_device
diff --git a/source/blender/compositor/intern/COM_OutputSocket.cpp b/source/blender/compositor/intern/COM_OutputSocket.cpp
deleted file mode 100644
index 50e9b75b072..00000000000
--- a/source/blender/compositor/intern/COM_OutputSocket.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright 2011, Blender Foundation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_Socket.h"
-#include "COM_Node.h"
-#include "COM_SocketConnection.h"
-#include "COM_NodeOperation.h"
-
-OutputSocket::OutputSocket(DataType datatype) : Socket(datatype)
-{
- /* pass */
-}
-
-int OutputSocket::isOutputSocket() const { return true; }
-const int OutputSocket::isConnected() const { return this->m_connections.size() != 0; }
-
-void OutputSocket::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
-{
- NodeBase *node = this->getNode();
- if (node->isOperation()) {
- NodeOperation *operation = (NodeOperation *)node;
- if (operation->isResolutionSet()) {
- resolution[0] = operation->getWidth();
- resolution[1] = operation->getHeight();
- }
- else {
- operation->determineResolution(resolution, preferredResolution);
- operation->setResolution(resolution);
- }
- }
-}
-
-void OutputSocket::addConnection(SocketConnection *connection)
-{
- this->m_connections.push_back(connection);
-}
-
-void OutputSocket::removeConnection(SocketConnection *connection)
-{
- for (vector<SocketConnection *>::iterator it = m_connections.begin(); it != m_connections.end(); ++it) {
- if (*it == connection) {
- m_connections.erase(it);
- return;
- }
- }
-}
-
-void OutputSocket::relinkConnections(OutputSocket *relinkToSocket, bool single)
-{
- if (isConnected()) {
- if (single) {
- SocketConnection *connection = this->m_connections[0];
- connection->setFromSocket(relinkToSocket);
- relinkToSocket->addConnection(connection);
- this->m_connections.erase(this->m_connections.begin());
- }
- else {
- unsigned int index;
- for (index = 0; index < this->m_connections.size(); index++) {
- SocketConnection *connection = this->m_connections[index];
- connection->setFromSocket(relinkToSocket);
- relinkToSocket->addConnection(connection);
- }
- this->m_connections.clear();
- }
- }
-}
-void OutputSocket::removeFirstConnection()
-{
- SocketConnection *connection = this->m_connections[0];
- InputSocket *inputSocket = connection->getToSocket();
- if (inputSocket != NULL) {
- inputSocket->setConnection(NULL);
- }
- this->m_connections.erase(this->m_connections.begin());
-}
-
-void OutputSocket::clearConnections()
-{
- while (this->isConnected()) {
- removeFirstConnection();
- }
-}
-
-WriteBufferOperation *OutputSocket::findAttachedWriteBufferOperation() const
-{
- unsigned int index;
- for (index = 0; index < this->m_connections.size(); index++) {
- SocketConnection *connection = this->m_connections[index];
- NodeBase *node = connection->getToNode();
- if (node->isOperation()) {
- NodeOperation *operation = (NodeOperation *)node;
- if (operation->isWriteBufferOperation()) {
- return (WriteBufferOperation *)operation;
- }
- }
- }
- return NULL;
-}
-
diff --git a/source/blender/compositor/intern/COM_OutputSocket.h b/source/blender/compositor/intern/COM_OutputSocket.h
deleted file mode 100644
index 709005a6de0..00000000000
--- a/source/blender/compositor/intern/COM_OutputSocket.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2011, Blender Foundation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_OutputSocket_h
-#define _COM_OutputSocket_h
-
-#include <vector>
-#include "COM_Socket.h"
-#include "COM_ChannelInfo.h"
-
-using namespace std;
-class SocketConnection;
-class Node;
-class InputSocket;
-class WriteBufferOperation;
-
-//#define COM_ST_INPUT 0
-//#define COM_ST_OUTPUT 1
-
-/**
- * @brief OutputSocket are sockets that can send data/input
- * @ingroup Model
- */
-class OutputSocket : public Socket {
-private:
- vector<SocketConnection *> m_connections;
-
- void removeFirstConnection();
-public:
- OutputSocket(DataType datatype);
- OutputSocket(DataType datatype, int inputSocketDataTypeDeterminatorIndex);
- OutputSocket(OutputSocket *from);
- void addConnection(SocketConnection *connection);
- void removeConnection(SocketConnection *connection);
- SocketConnection *getConnection(unsigned int index) { return this->m_connections[index]; }
- const int isConnected() const;
- int isOutputSocket() const;
-
- /**
- * @brief determine the resolution of this socket
- * @param resolution the result of this operation
- * @param preferredResolution the preferable resolution as no resolution could be determined
- */
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
-
- /**
- * @brief determine the actual data type and channel info.
- */
- void relinkConnections(OutputSocket *relinkToSocket) { this->relinkConnections(relinkToSocket, false); }
- void relinkConnections(OutputSocket *relinkToSocket, bool single);
- const int getNumberOfConnections() { return this->m_connections.size(); }
-
- void clearConnections();
-
- /**
- * @brief find a connected write buffer operation to this OutputSocket
- * @return WriteBufferOperation or NULL
- */
- WriteBufferOperation *findAttachedWriteBufferOperation() const;
- ChannelInfo *getChannelInfo(const int channelnumber);
-
-private:
-
-};
-#endif
diff --git a/source/blender/compositor/intern/COM_SingleThreadedNodeOperation.cpp b/source/blender/compositor/intern/COM_SingleThreadedOperation.cpp
index 7d1184cb356..c300a85bfa3 100644
--- a/source/blender/compositor/intern/COM_SingleThreadedNodeOperation.cpp
+++ b/source/blender/compositor/intern/COM_SingleThreadedOperation.cpp
@@ -20,25 +20,25 @@
* Monique Dewanchand
*/
-#include "COM_SingleThreadedNodeOperation.h"
+#include "COM_SingleThreadedOperation.h"
-SingleThreadedNodeOperation::SingleThreadedNodeOperation() : NodeOperation()
+SingleThreadedOperation::SingleThreadedOperation() : NodeOperation()
{
this->m_cachedInstance = NULL;
setComplex(true);
}
-void SingleThreadedNodeOperation::initExecution()
+void SingleThreadedOperation::initExecution()
{
initMutex();
}
-void SingleThreadedNodeOperation::executePixel(float output[4], int x, int y, void *data)
+void SingleThreadedOperation::executePixel(float output[4], int x, int y, void *data)
{
this->m_cachedInstance->readNoCheck(output, x, y);
}
-void SingleThreadedNodeOperation::deinitExecution()
+void SingleThreadedOperation::deinitExecution()
{
deinitMutex();
if (this->m_cachedInstance) {
@@ -46,7 +46,7 @@ void SingleThreadedNodeOperation::deinitExecution()
this->m_cachedInstance = NULL;
}
}
-void *SingleThreadedNodeOperation::initializeTileData(rcti *rect)
+void *SingleThreadedOperation::initializeTileData(rcti *rect)
{
if (this->m_cachedInstance) return this->m_cachedInstance;
diff --git a/source/blender/compositor/intern/COM_SingleThreadedNodeOperation.h b/source/blender/compositor/intern/COM_SingleThreadedOperation.h
index 45325be18a9..a6b2f777cb5 100644
--- a/source/blender/compositor/intern/COM_SingleThreadedNodeOperation.h
+++ b/source/blender/compositor/intern/COM_SingleThreadedOperation.h
@@ -20,11 +20,11 @@
* Monique Dewanchand
*/
-#ifndef _COM_SingleThreadedNodeOperation_h
-#define _COM_SingleThreadedNodeOperation_h
+#ifndef _COM_SingleThreadedOperation_h
+#define _COM_SingleThreadedOperation_h
#include "COM_NodeOperation.h"
-class SingleThreadedNodeOperation : public NodeOperation {
+class SingleThreadedOperation : public NodeOperation {
private:
MemoryBuffer *m_cachedInstance;
@@ -34,7 +34,7 @@ protected:
}
public:
- SingleThreadedNodeOperation();
+ SingleThreadedOperation();
/**
* the inner loop of this program
diff --git a/source/blender/compositor/intern/COM_Socket.cpp b/source/blender/compositor/intern/COM_Socket.cpp
deleted file mode 100644
index 3465fa6f56d..00000000000
--- a/source/blender/compositor/intern/COM_Socket.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2011, Blender Foundation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_Socket.h"
-#include "COM_Node.h"
-#include "COM_SocketConnection.h"
-
-extern "C" {
-#include "RNA_access.h"
-}
-
-Socket::Socket(DataType datatype)
-{
- this->m_datatype = datatype;
- this->m_editorSocket = NULL;
- this->m_node = NULL;
-}
-
-DataType Socket::getDataType() const
-{
- return this->m_datatype;
-}
-
-int Socket::isInputSocket() const { return false; }
-int Socket::isOutputSocket() const { return false; }
-const int Socket::isConnected() const { return false; }
-void Socket::setNode(NodeBase *node) { this->m_node = node; }
-NodeBase *Socket::getNode() const { return this->m_node; }
-
-float Socket::getEditorValueFloat()
-{
- PointerRNA ptr;
- RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
- return RNA_float_get(&ptr, "default_value");
-}
-
-void Socket::getEditorValueColor(float *value)
-{
- PointerRNA ptr;
- RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
- return RNA_float_get_array(&ptr, "default_value", value);
-}
-
-void Socket::getEditorValueVector(float *value)
-{
- PointerRNA ptr;
- RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
- return RNA_float_get_array(&ptr, "default_value", value);
-}
diff --git a/source/blender/compositor/intern/COM_Socket.h b/source/blender/compositor/intern/COM_Socket.h
deleted file mode 100644
index 6532864a4d9..00000000000
--- a/source/blender/compositor/intern/COM_Socket.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2011, Blender Foundation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_Socket_h
-#define _COM_Socket_h
-
-#include <vector>
-#include "BKE_text.h"
-#include <string>
-#include "DNA_node_types.h"
-#include "COM_defines.h"
-
-#ifdef WITH_CXX_GUARDEDALLOC
-#include "MEM_guardedalloc.h"
-#endif
-
-using namespace std;
-class SocketConnection;
-class NodeBase;
-struct PointerRNA;
-
-/**
- * @brief Base class for InputSocket and OutputSocket.
- *
- * A socket are the points on an node where the user can make a connection between.
- * Sockets are always part of a node or an operation.
- *
- * @see InputSocket
- * @see OutputSocket
- * @see SocketConnection - a connection between an InputSocket and an OutputSocket
- * @ingroup Model
- */
-class Socket {
-private:
- /**
- * Reference to the node where this Socket belongs to
- */
- NodeBase *m_node;
-
- /**
- * the datatype of this socket. Is used for automatically data transformation.
- * @section data-conversion
- */
- DataType m_datatype;
-
- bNodeSocket *m_editorSocket;
-
-protected:
- /**
- * @brief Declaration of the virtual destructor
- * @note resolve warning gcc 4.7
- */
- virtual ~Socket() {}
-
-public:
- Socket(DataType datatype);
-
- DataType getDataType() const;
- void setNode(NodeBase *node);
- NodeBase *getNode() const;
-
-
- const virtual int isConnected() const;
- int isInputSocket() const;
- int isOutputSocket() const;
- virtual void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) {}
-
- void setEditorSocket(bNodeSocket *editorSocket) { this->m_editorSocket = editorSocket; }
- bNodeSocket *getbNodeSocket() const { return this->m_editorSocket; }
-
- float getEditorValueFloat();
- void getEditorValueColor(float *value);
- void getEditorValueVector(float *value);
-
-#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:Socket")
-#endif
-};
-
-
-#endif
diff --git a/source/blender/compositor/intern/COM_SocketConnection.cpp b/source/blender/compositor/intern/COM_SocketConnection.cpp
deleted file mode 100644
index 1f2cba72dc0..00000000000
--- a/source/blender/compositor/intern/COM_SocketConnection.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2011, Blender Foundation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_SocketConnection.h"
-#include "COM_NodeOperation.h"
-
-SocketConnection::SocketConnection()
-{
- this->m_fromSocket = NULL;
- this->m_toSocket = NULL;
- this->setIgnoreResizeCheck(false);
-}
-
-void SocketConnection::setFromSocket(OutputSocket *fromsocket)
-{
- if (fromsocket == NULL) {
- throw "ERROR";
- }
- this->m_fromSocket = fromsocket;
-}
-
-OutputSocket *SocketConnection::getFromSocket() const { return this->m_fromSocket; }
-void SocketConnection::setToSocket(InputSocket *tosocket)
-{
- if (tosocket == NULL) {
- throw "ERROR";
- }
- this->m_toSocket = tosocket;
-}
-
-InputSocket *SocketConnection::getToSocket() const { return this->m_toSocket; }
-
-NodeBase *SocketConnection::getFromNode() const
-{
- if (this->getFromSocket() == NULL) {
- return NULL;
- }
- else {
- return this->getFromSocket()->getNode();
- }
-}
-NodeBase *SocketConnection::getToNode() const
-{
- if (this->getToSocket() == NULL) {
- return NULL;
- }
- else {
- return this->getToSocket()->getNode();
- }
-}
-bool SocketConnection::isValid() const
-{
- if ((this->getToSocket() != NULL && this->getFromSocket() != NULL)) {
- if (this->getFromNode()->isOperation() && this->getToNode()->isOperation()) {
- return true;
- }
- }
- return false;
-}
-
-bool SocketConnection::needsResolutionConversion() const
-{
- if (this->m_ignoreResizeCheck) { return false; }
- NodeOperation *fromOperation = (NodeOperation *)this->getFromNode();
- NodeOperation *toOperation = (NodeOperation *)this->getToNode();
- if (this->m_toSocket->getResizeMode() == COM_SC_NO_RESIZE) { return false; }
- const unsigned int fromWidth = fromOperation->getWidth();
- const unsigned int fromHeight = fromOperation->getHeight();
- const unsigned int toWidth = toOperation->getWidth();
- const unsigned int toHeight = toOperation->getHeight();
-
- if (fromWidth == toWidth && fromHeight == toHeight) {
- return false;
- }
- return true;
-}
diff --git a/source/blender/compositor/intern/COM_SocketConnection.h b/source/blender/compositor/intern/COM_SocketConnection.h
deleted file mode 100644
index 9777bd45be2..00000000000
--- a/source/blender/compositor/intern/COM_SocketConnection.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright 2011, Blender Foundation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_SocketConnection_h
-#define _COM_SocketConnection_h
-
-#include "DNA_node_types.h"
-#include "COM_Node.h"
-#include "COM_Socket.h"
-#include "COM_ChannelInfo.h"
-
-/**
- * @brief An SocketConnection is an connection between an InputSocket and an OutputSocket.
- *
- * <pre>
- * +----------+ To InputSocket +----------+
- * | From | SocketConnection \| To Node |
- * | Node *====================* |
- * | |\ | |
- * | | From OutputSocket +----------+
- * +----------+
- * </pre>
- * @ingroup Model
- * @see InputSocket
- * @see OutputSocket
- */
-class SocketConnection {
-private:
- /**
- * @brief Startpoint of the connection
- */
- OutputSocket *m_fromSocket;
-
- /**
- * @brief Endpoint of the connection
- */
- InputSocket *m_toSocket;
-
- /**
- * @brief has the resize already been done for this connection
- */
- bool m_ignoreResizeCheck;
-public:
- SocketConnection();
-
- /**
- * @brief set the startpoint of the connection
- * @param fromsocket
- */
- void setFromSocket(OutputSocket *fromsocket);
-
- /**
- * @brief get the startpoint of the connection
- * @return from OutputSocket
- */
- OutputSocket *getFromSocket() const;
-
- /**
- * @brief set the endpoint of the connection
- * @param tosocket
- */
- void setToSocket(InputSocket *tosocket);
-
- /**
- * @brief get the endpoint of the connection
- * @return to InputSocket
- */
- InputSocket *getToSocket() const;
-
- /**
- * @brief check if this connection is valid
- */
- bool isValid() const;
-
- /**
- * @brief return the Node where this connection is connected from
- */
- NodeBase *getFromNode() const;
-
- /**
- * @brief return the Node where this connection is connected to
- */
- NodeBase *getToNode() const;
-
- /**
- * @brief set, whether the resize has already been done for this SocketConnection
- */
- void setIgnoreResizeCheck(bool check) { this->m_ignoreResizeCheck = check; }
-
- /**
- * @brief has the resize already been done for this SocketConnection
- */
- bool isIgnoreResizeCheck() const { return this->m_ignoreResizeCheck; }
-
- /**
- * @brief does this SocketConnection need resolution conversion
- * @note PreviewOperation's will be ignored
- * @note Already converted SocketConnection's will be ignored
- * @return needs conversion [true:false]
- */
- bool needsResolutionConversion() const;
-
-#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("COM:SocketConnection")
-#endif
-};
-
-#endif
diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cpp b/source/blender/compositor/intern/COM_WorkScheduler.cpp
index 76a3d92eb6c..4bdc9b731b1 100644
--- a/source/blender/compositor/intern/COM_WorkScheduler.cpp
+++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp
@@ -81,12 +81,17 @@ static int g_highlightIndex;
static void **g_highlightedNodes;
static void **g_highlightedNodesRead;
+/* XXX highlighting disabled for now
+ * This requires pointers back to DNA data (bNodeTree/bNode) in operations, which is bad!
+ * Instead IF we want to keep this feature it should use a weak reference such as bNodeInstanceKey
+ */
+#if 0
#if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE
#define HIGHLIGHT(wp) \
{ \
ExecutionGroup *group = wp->getExecutionGroup(); \
if (group->isComplex()) { \
- NodeOperation *operation = group->getOutputNodeOperation(); \
+ NodeOperation *operation = group->getOutputOperation(); \
if (operation->isWriteBufferOperation()) { \
WriteBufferOperation *writeOperation = (WriteBufferOperation *)operation; \
NodeOperation *complexOperation = writeOperation->getInput(); \
@@ -105,6 +110,9 @@ static void **g_highlightedNodesRead;
} \
}
#endif /* COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE */
+#else
+#define HIGHLIGHT(wp) {}
+#endif
void COM_startReadHighlights()
{