Structural cleanup and improvements for the compositor.

Many parts of the compositor are unnecessarily complicated. This patch
aims at reducing the complexity of writing nodes and making the code
more transparent.

== Separating Nodes and Operations ==

Currently these are both mixed in the same graph, even though they have
very different purposes and are used at distinct stages in the
compositing process. The patch introduces dedicated graph classes for
nodes and for operations.

This removes the need for a lot of special case checks (isOperation etc.)
and explicit type casts. It simplifies the code since it becomes clear
at every stage what type of node we are dealing with. The compiler can
use static typing to avoid common bugs from mixing up these types and
fewer runtime sanity checks are needed.

== Simplified Node Conversion ==

Converting nodes to operations was previously based on "relinking", i.e.
nodes would start with by mirroring links in the Blender DNA node trees,
then add operations and redirect these links to them. This was very hard
to follow in many cases and required a lot of attention to avoid invalid
states.

Now there is a helper class called the NodeConverter, which is passed to
nodes and implements a much simpler API for this process. Nodes can add
operations and explicit connections as before, but defining "external"
links to the inputs/outputs of the original node now uses mapping
instead of directly modifying link data. Input data (node graph) and
result (operations graph) are cleanly separated.

== Removed Redundant Data Structures ==

A few redundant data structures have been removed, notably the
SocketConnection. These are only needed temporarily during graph
construction. For executing the compositor operations it is perfectly
sufficient to store only the direct input link pointers. A common
pointer indirection is avoided this way (which might also give a little
performance improvement).

== Avoid virtual recursive functions ==

Recursive virtual functions are evil. They are very hard to follow
during debugging. At least in the parts this patch is concerned with
these functions have been replaced by a non-virtual recursive core
function (which might then call virtual non-recursive functions if
needed). See for example NodeOperationBuilder::group_operations.
This commit is contained in:
Lukas Tönne 2014-04-15 16:06:12 +02:00
parent 28a829893c
commit 09874df135
251 changed files with 4242 additions and 5361 deletions

View File

@ -54,28 +54,22 @@ set(SRC
intern/COM_compositor.cpp
intern/COM_ExecutionSystem.cpp
intern/COM_ExecutionSystem.h
intern/COM_ExecutionSystemHelper.cpp
intern/COM_ExecutionSystemHelper.h
intern/COM_NodeConverter.cpp
intern/COM_NodeConverter.h
intern/COM_NodeOperationBuilder.cpp
intern/COM_NodeOperationBuilder.h
intern/COM_NodeGraph.cpp
intern/COM_NodeGraph.h
intern/COM_Converter.cpp
intern/COM_Converter.h
intern/COM_ExecutionGroup.cpp
intern/COM_ExecutionGroup.h
intern/COM_Node.cpp
intern/COM_Node.h
intern/COM_NodeBase.cpp
intern/COM_NodeBase.h
intern/COM_NodeOperation.cpp
intern/COM_NodeOperation.h
intern/COM_Socket.cpp
intern/COM_Socket.h
intern/COM_SocketReader.cpp
intern/COM_SocketReader.h
intern/COM_InputSocket.cpp
intern/COM_InputSocket.h
intern/COM_OutputSocket.cpp
intern/COM_OutputSocket.h
intern/COM_SocketConnection.cpp
intern/COM_SocketConnection.h
intern/COM_MemoryProxy.cpp
intern/COM_MemoryProxy.h
intern/COM_MemoryBuffer.cpp
@ -98,8 +92,8 @@ set(SRC
intern/COM_CompositorContext.h
intern/COM_ChannelInfo.cpp
intern/COM_ChannelInfo.h
intern/COM_SingleThreadedNodeOperation.cpp
intern/COM_SingleThreadedNodeOperation.h
intern/COM_SingleThreadedOperation.cpp
intern/COM_SingleThreadedOperation.h
intern/COM_Debug.cpp
intern/COM_Debug.h
@ -107,10 +101,6 @@ set(SRC
operations/COM_QualityStepHelper.cpp
# Internal nodes
nodes/COM_MuteNode.cpp
nodes/COM_MuteNode.h
nodes/COM_GroupNode.cpp
nodes/COM_GroupNode.h
nodes/COM_SocketProxyNode.cpp
nodes/COM_SocketProxyNode.h
@ -245,22 +235,10 @@ set(SRC
# converter nodes
nodes/COM_IDMaskNode.cpp
nodes/COM_IDMaskNode.h
nodes/COM_SeparateRGBANode.cpp
nodes/COM_SeparateRGBANode.h
nodes/COM_CombineRGBANode.cpp
nodes/COM_CombineRGBANode.h
nodes/COM_SeparateHSVANode.cpp
nodes/COM_SeparateHSVANode.h
nodes/COM_CombineHSVANode.cpp
nodes/COM_CombineHSVANode.h
nodes/COM_SeparateYUVANode.cpp
nodes/COM_SeparateYUVANode.h
nodes/COM_CombineYUVANode.cpp
nodes/COM_CombineYUVANode.h
nodes/COM_SeparateYCCANode.cpp
nodes/COM_SeparateYCCANode.h
nodes/COM_CombineYCCANode.cpp
nodes/COM_CombineYCCANode.h
nodes/COM_SeparateColorNode.cpp
nodes/COM_SeparateColorNode.h
nodes/COM_CombineColorNode.cpp
nodes/COM_CombineColorNode.h
nodes/COM_NormalNode.cpp
nodes/COM_NormalNode.h

View File

@ -213,8 +213,8 @@ extern "C" {
* (is called from [@ref ExecutionGroup.scheduleChunkWhenPossible])
* @see ExecutionGroup.scheduleChunk Schedule a chunk on the WorkScheduler
* @see NodeOperation.determineDependingAreaOfInterest Influence the area of interest of a chunk.
* @see WriteBufferOperation NodeOperation to write to a MemoryProxy/MemoryBuffer
* @see ReadBufferOperation NodeOperation to read from a MemoryProxy/MemoryBuffer
* @see WriteBufferOperation Operation to write to a MemoryProxy/MemoryBuffer
* @see ReadBufferOperation Operation to read from a MemoryProxy/MemoryBuffer
* @see MemoryProxy proxy for information about memory image (a image consist out of multiple chunks)
* @see MemoryBuffer Allocated memory for a single chunk
*

View File

@ -24,7 +24,7 @@
#define __COM_DEFINES_H__
/**
* @brief possible data types for SocketConnection
* @brief possible data types for sockets
* @ingroup Model
*/
typedef enum DataType {

View File

@ -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);
}

View File

@ -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; }

View File

@ -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; }
};

View File

@ -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,31 +116,25 @@
#include "COM_PixelateNode.h"
#include "COM_PlaneTrackDeformNode.h"
Node *Converter::convert(bNode *b_node, bool fast)
bool Converter::is_fast_node(bNode *b_node)
{
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);
}
Node *Converter::convert(bNode *b_node)
{
Node *node = NULL;
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);
}
}
switch (b_node->type) {
case CMP_NODE_COMPOSITE:
node = new CompositorNode(b_node);
@ -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);
}

View File

@ -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")

View File

@ -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 "";
}
void DebugInfo::convert_started()
std::string DebugInfo::operation_name(const NodeOperation *op)
{
m_node_names.clear();
OpNameMap::const_iterator it = m_op_names.find(op);
if (it != m_op_names.end())
return it->second;
else
return "";
}
void DebugInfo::execute_started(ExecutionSystem *system)
void DebugInfo::convert_started()
{
m_op_names.clear();
}
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

View File

@ -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
};

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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,40 +114,27 @@ 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
*/
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
*/
@ -175,6 +161,7 @@ public:
*/
~ExecutionSystem();
void set_operations(const Operations &operations, const Groups &groups);
/**
* @brief execute this system
@ -184,71 +171,17 @@ 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

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;
}
}

View File

@ -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

View File

@ -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()
{

View File

@ -27,6 +27,7 @@ class MemoryBuffer;
#include "COM_ExecutionGroup.h"
#include "COM_MemoryProxy.h"
#include "COM_SocketReader.h"
extern "C" {
# include "BLI_math.h"

View File

@ -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.

View File

@ -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);
}
void Node::addPreviewOperation(ExecutionSystem *system, CompositorContext *context, OutputSocket *outputSocket)
{
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));
}
}
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, InputSocket *inputSocket)
void Node::addInputSocket(DataType datatype)
{
if (inputSocket->isConnected() && this->isInActiveGroup()) {
OutputSocket *outputsocket = inputSocket->getConnection()->getFromSocket();
this->addPreviewOperation(system, context, outputsocket);
}
this->addInputSocket(datatype, NULL);
}
SocketConnection *Node::addLink(ExecutionSystem *graph, OutputSocket *outputSocket, InputSocket *inputsocket)
void Node::addInputSocket(DataType datatype, bNodeSocket *bSocket)
{
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;
NodeInput *socket = new NodeInput(this, bSocket, datatype);
this->m_inputsockets.push_back(socket);
}
void Node::addSetColorOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex)
void Node::addOutputSocket(DataType datatype)
{
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);
this->addOutputSocket(datatype, NULL);
}
void Node::addOutputSocket(DataType datatype, bNodeSocket *bSocket)
{
NodeOutput *socket = new NodeOutput(this, bSocket, datatype);
this->m_outputsockets.push_back(socket);
}
void Node::addSetVectorOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex)
NodeOutput *Node::getOutputSocket(unsigned int index) const
{
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);
BLI_assert(index < this->m_outputsockets.size());
return this->m_outputsockets[index];
}
NodeOperation *Node::convertToOperations_invalid_index(ExecutionSystem *graph, int index)
NodeInput *Node::getInputSocket(unsigned int index) const
{
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);
}
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);
}

View File

@ -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,9 +78,80 @@ 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);
/**
* is this node a group node.
*/
virtual bool isGroupNode() const { return false; }
/**
* is this node a proxy node.
*/
virtual bool isProxyNode() const { return false; }
/**
* @brief find the InputSocket by bNodeSocket
*
* @param socket
*/
InputSocket *findInputSocketBybNodeSocket(bNodeSocket *socket);
/**
* @brief find the OutputSocket by bNodeSocket
*
* @param socket
*/
OutputSocket *findOutputSocketBybNodeSocket(bNodeSocket *socket);
void convertToOperations_invalid(NodeConverter *compiler) const;
void setInstanceKey(bNodeInstanceKey instance_key) { m_instanceKey = instance_key; }
bNodeInstanceKey getInstanceKey() const { return m_instanceKey; }
protected:
void addPreviewOperation(ExecutionSystem *system, CompositorContext *context, InputSocket *inputSocket);
void addPreviewOperation(ExecutionSystem *system, CompositorContext *context, OutputSocket *outputSocket);
/**
* @brief add an NodeInput to the collection of inputsockets
* @note may only be called in an constructor
* @param socket the NodeInput to add
*/
void addInputSocket(DataType datatype);
void addInputSocket(DataType datatype, bNodeSocket *socket);
/**
* @brief add an NodeOutput to the collection of outputsockets
* @note may only be called in an constructor
* @param socket the NodeOutput to add
*/
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 link connected to this NodeInput.
* An input socket can only have a single link
*/
NodeOutput *m_link;
public:
NodeInput(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; }
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__ */

View File

@ -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];
}

View File

@ -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__ */

View File

@ -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());
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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 */

View File

@ -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);
}
}

View File

@ -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 NodeOperation are contains calculation logic
* @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 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

View File

@ -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);
}
}
}
}

View File

@ -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 */

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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()
{

View File

@ -27,16 +27,13 @@
#include "COM_AlphaOverMixedOperation.h"
#include "COM_AlphaOverPremultiplyOperation.h"
#include "COM_ExecutionSystem.h"
#include "COM_SetValueOperation.h"
#include "DNA_material_types.h" // the ramp types
void AlphaOverNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void AlphaOverNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
InputSocket *valueSocket = this->getInputSocket(0);
InputSocket *color1Socket = this->getInputSocket(1);
InputSocket *color2Socket = this->getInputSocket(2);
OutputSocket *outputSocket = this->getOutputSocket(0);
NodeInput *color1Socket = this->getInputSocket(1);
NodeInput *color2Socket = this->getInputSocket(2);
bNode *editorNode = this->getbNode();
MixBaseOperation *convertProg;
@ -55,18 +52,19 @@ void AlphaOverNode::convertToOperations(ExecutionSystem *graph, CompositorContex
}
convertProg->setUseValueAlphaMultiply(false);
if (color1Socket->isConnected()) {
if (color1Socket->isLinked()) {
convertProg->setResolutionInputSocketIndex(1);
}
else if (color2Socket->isConnected()) {
else if (color2Socket->isLinked()) {
convertProg->setResolutionInputSocketIndex(2);
}
else {
convertProg->setResolutionInputSocketIndex(0);
}
valueSocket->relinkConnections(convertProg->getInputSocket(0), 0, graph);
color1Socket->relinkConnections(convertProg->getInputSocket(1), 1, graph);
color2Socket->relinkConnections(convertProg->getInputSocket(2), 2, graph);
outputSocket->relinkConnections(convertProg->getOutputSocket(0));
graph->addOperation(convertProg);
converter.addOperation(convertProg);
converter.mapInputSocket(getInputSocket(0), convertProg->getInputSocket(0));
converter.mapInputSocket(getInputSocket(1), convertProg->getInputSocket(1));
converter.mapInputSocket(getInputSocket(2), convertProg->getInputSocket(2));
converter.mapOutputSocket(getOutputSocket(0), convertProg->getOutputSocket(0));
}

View File

@ -32,7 +32,7 @@
class AlphaOverNode : public Node {
public:
AlphaOverNode(bNode *editorNode) : Node(editorNode) {}
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif

View File

@ -30,15 +30,15 @@ BilateralBlurNode::BilateralBlurNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
void BilateralBlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void BilateralBlurNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
NodeBilateralBlurData *data = (NodeBilateralBlurData *)this->getbNode()->storage;
BilateralBlurOperation *operation = new BilateralBlurOperation();
operation->setbNode(this->getbNode());
operation->setQuality(context->getQuality());
operation->setQuality(context.getQuality());
operation->setData(data);
this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph);
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
graph->addOperation(operation);
converter.addOperation(operation);
converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));
converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0));
}

View File

@ -32,7 +32,7 @@
class BilateralBlurNode : public Node {
public:
BilateralBlurNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif

View File

@ -38,84 +38,85 @@ BlurNode::BlurNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void BlurNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
bNode *editorNode = this->getbNode();
NodeBlurData *data = (NodeBlurData *)editorNode->storage;
InputSocket *inputSizeSocket = this->getInputSocket(1);
bool connectedSizeSocket = inputSizeSocket->isConnected();
NodeInput *inputSizeSocket = this->getInputSocket(1);
bool connectedSizeSocket = inputSizeSocket->isLinked();
const float size = this->getInputSocket(1)->getEditorValueFloat();
CompositorQuality quality = context->getQuality();
CompositorQuality quality = context.getQuality();
NodeOperation *input_operation = NULL, *output_operation = NULL;
if (data->filtertype == R_FILTER_FAST_GAUSS) {
FastGaussianBlurOperation *operationfgb = new FastGaussianBlurOperation();
operationfgb->setData(data);
operationfgb->setChunksize(context->getChunksize());
operationfgb->setbNode(editorNode);
this->getInputSocket(1)->relinkConnections(operationfgb->getInputSocket(1), 1, graph);
graph->addOperation(operationfgb);
operationfgb->setChunksize(context.getChunksize());
converter.addOperation(operationfgb);
converter.mapInputSocket(getInputSocket(1), operationfgb->getInputSocket(1));
input_operation = operationfgb;
output_operation = operationfgb;
}
else if (editorNode->custom1 & CMP_NODEFLAG_BLUR_VARIABLE_SIZE) {
MathAddOperation *clamp = new MathAddOperation();
SetValueOperation *zero = new SetValueOperation();
addLink(graph, zero->getOutputSocket(), clamp->getInputSocket(1));
this->getInputSocket(1)->relinkConnections(clamp->getInputSocket(0), 1, graph);
zero->setValue(0.0f);
clamp->setUseClamp(true);
graph->addOperation(clamp);
graph->addOperation(zero);
converter.addOperation(clamp);
converter.addOperation(zero);
converter.mapInputSocket(getInputSocket(1), clamp->getInputSocket(0));
converter.addLink(zero->getOutputSocket(), clamp->getInputSocket(1));
GaussianAlphaXBlurOperation *operationx = new GaussianAlphaXBlurOperation();
operationx->setData(data);
operationx->setbNode(editorNode);
operationx->setQuality(quality);
operationx->setSize(1.0f);
operationx->setFalloff(PROP_SMOOTH);
operationx->setSubtract(false);
addLink(graph, clamp->getOutputSocket(), operationx->getInputSocket(0));
graph->addOperation(operationx);
converter.addOperation(operationx);
converter.addLink(clamp->getOutputSocket(), operationx->getInputSocket(0));
GaussianAlphaYBlurOperation *operationy = new GaussianAlphaYBlurOperation();
operationy->setData(data);
operationy->setbNode(editorNode);
operationy->setQuality(quality);
operationy->setSize(1.0f);
operationy->setFalloff(PROP_SMOOTH);
operationy->setSubtract(false);
addLink(graph, operationx->getOutputSocket(), operationy->getInputSocket(0));
graph->addOperation(operationy);
converter.addOperation(operationy);
converter.addLink(operationx->getOutputSocket(), operationy->getInputSocket(0));
GaussianBlurReferenceOperation *operation = new GaussianBlurReferenceOperation();
operation->setData(data);
operation->setbNode(editorNode);
operation->setQuality(quality);
addLink(graph, operationy->getOutputSocket(), operation->getInputSocket(1));
graph->addOperation(operation);
converter.addOperation(operation);
converter.addLink(operationy->getOutputSocket(), operation->getInputSocket(1));
output_operation = operation;
input_operation = operation;
}
else if (!data->bokeh) {
GaussianXBlurOperation *operationx = new GaussianXBlurOperation();
operationx->setData(data);
operationx->setbNode(editorNode);
operationx->setQuality(quality);
this->getInputSocket(1)->relinkConnections(operationx->getInputSocket(1), 1, graph);
graph->addOperation(operationx);
converter.addOperation(operationx);
converter.mapInputSocket(getInputSocket(1), operationx->getInputSocket(1));
GaussianYBlurOperation *operationy = new GaussianYBlurOperation();
operationy->setData(data);
operationy->setbNode(editorNode);
operationy->setQuality(quality);
graph->addOperation(operationy);
addLink(graph, operationx->getOutputSocket(), operationy->getInputSocket(0));
addLink(graph, operationx->getInputSocket(1)->getConnection()->getFromSocket(), operationy->getInputSocket(1));
converter.addOperation(operationy);
converter.mapInputSocket(getInputSocket(1), operationy->getInputSocket(1));
converter.addLink(operationx->getOutputSocket(), operationy->getInputSocket(0));
if (!connectedSizeSocket) {
operationx->setSize(size);
@ -128,10 +129,10 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co
else {
GaussianBokehBlurOperation *operation = new GaussianBokehBlurOperation();
operation->setData(data);
operation->setbNode(editorNode);
this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph);
operation->setQuality(quality);
graph->addOperation(operation);
converter.addOperation(operation);
converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
if (!connectedSizeSocket) {
operation->setSize(size);
@ -144,19 +145,20 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co
if (data->gamma) {
GammaCorrectOperation *correct = new GammaCorrectOperation();
GammaUncorrectOperation *inverse = new GammaUncorrectOperation();
this->getInputSocket(0)->relinkConnections(correct->getInputSocket(0), 0, graph);
addLink(graph, correct->getOutputSocket(), input_operation->getInputSocket(0));
addLink(graph, output_operation->getOutputSocket(), inverse->getInputSocket(0));
this->getOutputSocket()->relinkConnections(inverse->getOutputSocket());
graph->addOperation(correct);
graph->addOperation(inverse);
addPreviewOperation(graph, context, inverse->getOutputSocket());
converter.addOperation(correct);
converter.addOperation(inverse);
converter.mapInputSocket(getInputSocket(0), correct->getInputSocket(0));
converter.addLink(correct->getOutputSocket(), input_operation->getInputSocket(0));
converter.addLink(output_operation->getOutputSocket(), inverse->getInputSocket(0));
converter.mapOutputSocket(getOutputSocket(), inverse->getOutputSocket());
converter.addPreview(inverse->getOutputSocket());
}
else {
this->getInputSocket(0)->relinkConnections(input_operation->getInputSocket(0), 0, graph);
this->getOutputSocket()->relinkConnections(output_operation->getOutputSocket());
addPreviewOperation(graph, context, output_operation->getOutputSocket());
converter.mapInputSocket(getInputSocket(0), input_operation->getInputSocket(0));
converter.mapOutputSocket(getOutputSocket(), output_operation->getOutputSocket());
converter.addPreview(output_operation->getOutputSocket());
}
}

View File

@ -32,7 +32,7 @@
class BlurNode : public Node {
public:
BlurNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif

View File

@ -34,40 +34,37 @@ BokehBlurNode::BokehBlurNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
void BokehBlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void BokehBlurNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
bNode *b_node = this->getbNode();
InputSocket *inputSizeSocket = this->getInputSocket(2);
NodeInput *inputSizeSocket = this->getInputSocket(2);
bool connectedSizeSocket = inputSizeSocket->isConnected();
bool connectedSizeSocket = inputSizeSocket->isLinked();
if ((b_node->custom1 & CMP_NODEFLAG_BLUR_VARIABLE_SIZE) && connectedSizeSocket) {
VariableSizeBokehBlurOperation *operation = new VariableSizeBokehBlurOperation();
this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph);
this->getInputSocket(2)->relinkConnections(operation->getInputSocket(2), 2, graph);
operation->setQuality(context->getQuality());
operation->setbNode(this->getbNode());
graph->addOperation(operation);
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
operation->setQuality(context.getQuality());
operation->setThreshold(0.0f);
operation->setMaxBlur(b_node->custom4);
operation->setDoScaleSize(true);
converter.addOperation(operation);
converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));
converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
converter.mapInputSocket(getInputSocket(2), operation->getInputSocket(2));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket());
}
else {
BokehBlurOperation *operation = new BokehBlurOperation();
this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph);
this->getInputSocket(2)->relinkConnections(operation->getInputSocket(3), 2, graph);
this->getInputSocket(3)->relinkConnections(operation->getInputSocket(2), 3, graph);
operation->setQuality(context->getQuality());
operation->setbNode(this->getbNode());
graph->addOperation(operation);
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
operation->setQuality(context.getQuality());
converter.addOperation(operation);
converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));
converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
converter.mapInputSocket(getInputSocket(2), operation->getInputSocket(2));
converter.mapInputSocket(getInputSocket(3), operation->getInputSocket(3));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket());
if (!connectedSizeSocket) {
operation->setSize(this->getInputSocket(2)->getEditorValueFloat());

View File

@ -32,7 +32,7 @@
class BokehBlurNode : public Node {
public:
BokehBlurNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif

View File

@ -29,11 +29,13 @@ BokehImageNode::BokehImageNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
void BokehImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void BokehImageNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
BokehImageOperation *operation = new BokehImageOperation();
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket(0));
graph->addOperation(operation);
operation->setData((NodeBokehImage *)this->getbNode()->storage);
addPreviewOperation(graph, context, operation->getOutputSocket(0));
converter.addOperation(operation);
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0));
converter.addPreview(operation->getOutputSocket(0));
}

View File

@ -32,7 +32,7 @@
class BokehImageNode : public Node {
public:
BokehImageNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif

View File

@ -32,47 +32,43 @@ BoxMaskNode::BoxMaskNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
void BoxMaskNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void BoxMaskNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
NodeInput *inputSocket = this->getInputSocket(0);
NodeOutput *outputSocket = this->getOutputSocket(0);
BoxMaskOperation *operation;
operation = new BoxMaskOperation();
operation->setData((NodeBoxMask *)this->getbNode()->storage);
InputSocket *inputSocket = this->getInputSocket(0);
OutputSocket *outputSocket = this->getOutputSocket(0);
if (inputSocket->isConnected()) {
inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph);
outputSocket->relinkConnections(operation->getOutputSocket());
operation->setMaskType(this->getbNode()->custom1);
converter.addOperation(operation);
if (inputSocket->isLinked()) {
converter.mapInputSocket(inputSocket, operation->getInputSocket(0));
converter.mapOutputSocket(outputSocket, operation->getOutputSocket());
}
else {
/* Value operation to produce original transparent image */
SetValueOperation *valueOperation = new SetValueOperation();
valueOperation->setValue(0.0f);
graph->addOperation(valueOperation);
converter.addOperation(valueOperation);
/* Scale that image up to render resolution */
const RenderData *rd = context->getRenderData();
const RenderData *rd = context.getRenderData();
ScaleFixedSizeOperation *scaleOperation = new ScaleFixedSizeOperation();
scaleOperation->setIsAspect(false);
scaleOperation->setIsCrop(false);
scaleOperation->setOffset(0.0f, 0.0f);
scaleOperation->setNewWidth(rd->xsch * rd->size / 100.0f);
scaleOperation->setNewHeight(rd->ysch * rd->size / 100.0f);
scaleOperation->getInputSocket(0)->setResizeMode(COM_SC_NO_RESIZE);
converter.addOperation(scaleOperation);
addLink(graph, valueOperation->getOutputSocket(0), scaleOperation->getInputSocket(0));
addLink(graph, scaleOperation->getOutputSocket(0), operation->getInputSocket(0));
outputSocket->relinkConnections(operation->getOutputSocket(0));
scaleOperation->getInputSocket(0)->getConnection()->setIgnoreResizeCheck(true);
graph->addOperation(scaleOperation);
converter.addLink(valueOperation->getOutputSocket(0), scaleOperation->getInputSocket(0));
converter.addLink(scaleOperation->getOutputSocket(0), operation->getInputSocket(0));
converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));
}
this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph);
operation->setMaskType(this->getbNode()->custom1);
graph->addOperation(operation);
converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
}

View File

@ -32,7 +32,7 @@
class BoxMaskNode : public Node {
public:
BoxMaskNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif

View File

@ -29,12 +29,13 @@ BrightnessNode::BrightnessNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
void BrightnessNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void BrightnessNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
BrightnessOperation *operation = new BrightnessOperation();
this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph);
this->getInputSocket(2)->relinkConnections(operation->getInputSocket(2), 2, graph);
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket(0));
graph->addOperation(operation);
converter.addOperation(operation);
converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));
converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
converter.mapInputSocket(getInputSocket(2), operation->getInputSocket(2));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0));
}

View File

@ -32,7 +32,7 @@
class BrightnessNode : public Node {
public:
BrightnessNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif

View File

@ -30,15 +30,15 @@ ChannelMatteNode::ChannelMatteNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
void ChannelMatteNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void ChannelMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
InputSocket *inputSocketImage = this->getInputSocket(0);
OutputSocket *outputSocketImage = this->getOutputSocket(0);
OutputSocket *outputSocketMatte = this->getOutputSocket(1);
NodeOperation *convert = NULL;
bNode *node = this->getbNode();
NodeInput *inputSocketImage = this->getInputSocket(0);
NodeOutput *outputSocketImage = this->getOutputSocket(0);
NodeOutput *outputSocketMatte = this->getOutputSocket(1);
NodeOperation *convert = NULL;
/* colorspace */
switch (node->custom1) {
case CMP_NODE_CHANNEL_MATTE_CS_RGB:
@ -56,35 +56,31 @@ void ChannelMatteNode::convertToOperations(ExecutionSystem *graph, CompositorCon
default:
break;
}
ChannelMatteOperation *operation = new ChannelMatteOperation();
/* pass the ui properties to the operation */
operation->setSettings((NodeChroma *)node->storage, node->custom2);
converter.addOperation(operation);
SetAlphaOperation *operationAlpha = new SetAlphaOperation();
converter.addOperation(operationAlpha);
if (convert) {
inputSocketImage->relinkConnections(convert->getInputSocket(0), 0, graph);
addLink(graph, convert->getOutputSocket(), operation->getInputSocket(0));
addLink(graph, convert->getInputSocket(0)->getConnection()->getFromSocket(), operationAlpha->getInputSocket(0));
graph->addOperation(convert);
converter.addOperation(convert);
converter.mapInputSocket(inputSocketImage, convert->getInputSocket(0));
converter.addLink(convert->getOutputSocket(), operation->getInputSocket(0));
converter.addLink(convert->getOutputSocket(), operationAlpha->getInputSocket(0));
}
else {
inputSocketImage->relinkConnections(operation->getInputSocket(0), 0, graph);
addLink(graph, operation->getInputSocket(0)->getConnection()->getFromSocket(), operationAlpha->getInputSocket(0));
}
if (outputSocketMatte->isConnected()) {
outputSocketMatte->relinkConnections(operation->getOutputSocket(0));
}
graph->addOperation(operation);
graph->addOperation(operationAlpha);
addLink(graph, operation->getOutputSocket(), operationAlpha->getInputSocket(1));
addPreviewOperation(graph, context, operationAlpha->getOutputSocket());
if (outputSocketImage->isConnected()) {
outputSocketImage->relinkConnections(operationAlpha->getOutputSocket());
converter.mapInputSocket(inputSocketImage, operation->getInputSocket(0));
converter.mapInputSocket(inputSocketImage, operationAlpha->getInputSocket(0));
}
converter.mapOutputSocket(outputSocketMatte, operation->getOutputSocket(0));
converter.addLink(operation->getOutputSocket(), operationAlpha->getInputSocket(1));
converter.mapOutputSocket(outputSocketImage, operationAlpha->getOutputSocket());
converter.addPreview(operationAlpha->getOutputSocket());
}

View File

@ -31,7 +31,7 @@
class ChannelMatteNode : public Node {
public:
ChannelMatteNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif /* COM_ChannelMatteNODE_H */

View File

@ -30,44 +30,38 @@ ChromaMatteNode::ChromaMatteNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
void ChromaMatteNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void ChromaMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
InputSocket *inputSocketImage = this->getInputSocket(0);
InputSocket *inputSocketKey = this->getInputSocket(1);
OutputSocket *outputSocketImage = this->getOutputSocket(0);
OutputSocket *outputSocketMatte = this->getOutputSocket(1);
bNode *editorsnode = getbNode();
NodeInput *inputSocketImage = this->getInputSocket(0);
NodeInput *inputSocketKey = this->getInputSocket(1);
NodeOutput *outputSocketImage = this->getOutputSocket(0);
NodeOutput *outputSocketMatte = this->getOutputSocket(1);
ConvertRGBToYCCOperation *operationRGBToYCC_Image = new ConvertRGBToYCCOperation();
ConvertRGBToYCCOperation *operationRGBToYCC_Key = new ConvertRGBToYCCOperation();
operationRGBToYCC_Image->setMode(0); /* BLI_YCC_ITU_BT601 */
operationRGBToYCC_Key->setMode(0); /* BLI_YCC_ITU_BT601 */
converter.addOperation(operationRGBToYCC_Image);
converter.addOperation(operationRGBToYCC_Key);
ChromaMatteOperation *operation = new ChromaMatteOperation();
bNode *editorsnode = getbNode();
operation->setSettings((NodeChroma *)editorsnode->storage);
inputSocketImage->relinkConnections(operationRGBToYCC_Image->getInputSocket(0), 0, graph);
inputSocketKey->relinkConnections(operationRGBToYCC_Key->getInputSocket(0), 1, graph);
addLink(graph, operationRGBToYCC_Image->getOutputSocket(), operation->getInputSocket(0));
addLink(graph, operationRGBToYCC_Key->getOutputSocket(), operation->getInputSocket(1));
graph->addOperation(operationRGBToYCC_Image);
graph->addOperation(operationRGBToYCC_Key);
graph->addOperation(operation);
if (outputSocketMatte->isConnected()) {
outputSocketMatte->relinkConnections(operation->getOutputSocket());
}
converter.addOperation(operation);
SetAlphaOperation *operationAlpha = new SetAlphaOperation();
addLink(graph, operationRGBToYCC_Image->getInputSocket(0)->getConnection()->getFromSocket(), operationAlpha->getInputSocket(0));
addLink(graph, operation->getOutputSocket(), operationAlpha->getInputSocket(1));
graph->addOperation(operationAlpha);
addPreviewOperation(graph, context, operationAlpha->getOutputSocket());
if (outputSocketImage->isConnected()) {
outputSocketImage->relinkConnections(operationAlpha->getOutputSocket());
}
converter.addOperation(operationAlpha);
converter.mapInputSocket(inputSocketImage, operationRGBToYCC_Image->getInputSocket(0));
converter.mapInputSocket(inputSocketKey, operationRGBToYCC_Key->getInputSocket(0));
converter.addLink(operationRGBToYCC_Image->getOutputSocket(), operation->getInputSocket(0));
converter.addLink(operationRGBToYCC_Key->getOutputSocket(), operation->getInputSocket(1));
converter.mapOutputSocket(outputSocketMatte, operation->getOutputSocket());
converter.mapInputSocket(inputSocketImage, operationAlpha->getInputSocket(0));
converter.addLink(operation->getOutputSocket(), operationAlpha->getInputSocket(1));
converter.mapOutputSocket(outputSocketImage, operationAlpha->getOutputSocket());
converter.addPreview(operationAlpha->getOutputSocket());
}

View File

@ -31,7 +31,7 @@
class ChromaMatteNode : public Node {
public:
ChromaMatteNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif /* COM_ChromaMatteNODE_H */

View File

@ -32,14 +32,15 @@ ColorBalanceNode::ColorBalanceNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
void ColorBalanceNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void ColorBalanceNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
InputSocket *inputSocket = this->getInputSocket(0);
InputSocket *inputImageSocket = this->getInputSocket(1);
OutputSocket *outputSocket = this->getOutputSocket(0);
bNode *node = this->getbNode();
NodeColorBalance *n = (NodeColorBalance *)node->storage;
NodeInput *inputSocket = this->getInputSocket(0);
NodeInput *inputImageSocket = this->getInputSocket(1);
NodeOutput *outputSocket = this->getOutputSocket(0);
NodeOperation *operation;
if (node->custom1 == 0) {
ColorBalanceLGGOperation *operationLGG = new ColorBalanceLGGOperation();
@ -62,9 +63,9 @@ void ColorBalanceNode::convertToOperations(ExecutionSystem *graph, CompositorCon
operationCDL->setSlope(n->slope);
operation = operationCDL;
}
converter.addOperation(operation);
inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph);
inputImageSocket->relinkConnections(operation->getInputSocket(1), 1, graph);
outputSocket->relinkConnections(operation->getOutputSocket(0));
graph->addOperation(operation);
converter.mapInputSocket(inputSocket, operation->getInputSocket(0));
converter.mapInputSocket(inputImageSocket, operation->getInputSocket(1));
converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));
}

View File

@ -32,7 +32,7 @@
class ColorBalanceNode : public Node {
public:
ColorBalanceNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif /* COM_ColorBalanceNODE_H */

View File

@ -29,16 +29,18 @@ ColorCorrectionNode::ColorCorrectionNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
void ColorCorrectionNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void ColorCorrectionNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
ColorCorrectionOperation *operation = new ColorCorrectionOperation();
bNode *editorNode = getbNode();
this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph);
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket(0));
ColorCorrectionOperation *operation = new ColorCorrectionOperation();
operation->setData((NodeColorCorrection *)editorNode->storage);
operation->setRedChannelEnabled((editorNode->custom1 & 1) > 0);
operation->setGreenChannelEnabled((editorNode->custom1 & 2) > 0);
operation->setBlueChannelEnabled((editorNode->custom1 & 4) > 0);
graph->addOperation(operation);
converter.addOperation(operation);
converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));
converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0));
}

View File

@ -32,7 +32,7 @@
class ColorCorrectionNode : public Node {
public:
ColorCorrectionNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif

View File

@ -29,36 +29,32 @@ ColorCurveNode::ColorCurveNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
void ColorCurveNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void ColorCurveNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
if (this->getInputSocket(2)->isConnected() || this->getInputSocket(3)->isConnected()) {
if (this->getInputSocket(2)->isLinked() || this->getInputSocket(3)->isLinked()) {
ColorCurveOperation *operation = new ColorCurveOperation();
this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph);
this->getInputSocket(2)->relinkConnections(operation->getInputSocket(2), 2, graph);
this->getInputSocket(3)->relinkConnections(operation->getInputSocket(3), 3, graph);
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
operation->setCurveMapping((CurveMapping *)this->getbNode()->storage);
graph->addOperation(operation);
converter.addOperation(operation);
converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));
converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
converter.mapInputSocket(getInputSocket(2), operation->getInputSocket(2));
converter.mapInputSocket(getInputSocket(3), operation->getInputSocket(3));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket());
}
else {
ConstantLevelColorCurveOperation *operation = new ConstantLevelColorCurveOperation();
this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph);
float col[4];
this->getInputSocket(2)->getEditorValueColor(col);
operation->setBlackLevel(col);
this->getInputSocket(3)->getEditorValueColor(col);
operation->setWhiteLevel(col);
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
operation->setCurveMapping((CurveMapping *)this->getbNode()->storage);
graph->addOperation(operation);
converter.addOperation(operation);
converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));
converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket());
}
}

View File

@ -32,7 +32,7 @@
class ColorCurveNode : public Node {
public:
ColorCurveNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif

View File

@ -30,41 +30,36 @@ ColorMatteNode::ColorMatteNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
void ColorMatteNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void ColorMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
InputSocket *inputSocketImage = this->getInputSocket(0);
InputSocket *inputSocketKey = this->getInputSocket(1);
OutputSocket *outputSocketImage = this->getOutputSocket(0);
OutputSocket *outputSocketMatte = this->getOutputSocket(1);
bNode *editorsnode = getbNode();
NodeInput *inputSocketImage = this->getInputSocket(0);
NodeInput *inputSocketKey = this->getInputSocket(1);
NodeOutput *outputSocketImage = this->getOutputSocket(0);
NodeOutput *outputSocketMatte = this->getOutputSocket(1);
ConvertRGBToHSVOperation *operationRGBToHSV_Image = new ConvertRGBToHSVOperation();
ConvertRGBToHSVOperation *operationRGBToHSV_Key = new ConvertRGBToHSVOperation();
converter.addOperation(operationRGBToHSV_Image);
converter.addOperation(operationRGBToHSV_Key);
ColorMatteOperation *operation = new ColorMatteOperation();
bNode *editorsnode = getbNode();
operation->setSettings((NodeChroma *)editorsnode->storage);
inputSocketImage->relinkConnections(operationRGBToHSV_Image->getInputSocket(0), 0, graph);
inputSocketKey->relinkConnections(operationRGBToHSV_Key->getInputSocket(0), 1, graph);
addLink(graph, operationRGBToHSV_Image->getOutputSocket(), operation->getInputSocket(0));
addLink(graph, operationRGBToHSV_Key->getOutputSocket(), operation->getInputSocket(1));
if (outputSocketMatte->isConnected()) {
outputSocketMatte->relinkConnections(operation->getOutputSocket(0));
}
graph->addOperation(operationRGBToHSV_Image);
graph->addOperation(operationRGBToHSV_Key);
graph->addOperation(operation);
converter.addOperation(operation);
SetAlphaOperation *operationAlpha = new SetAlphaOperation();
addLink(graph, operationRGBToHSV_Image->getInputSocket(0)->getConnection()->getFromSocket(), operationAlpha->getInputSocket(0));
addLink(graph, operation->getOutputSocket(), operationAlpha->getInputSocket(1));
graph->addOperation(operationAlpha);
addPreviewOperation(graph, context, operationAlpha->getOutputSocket());
if (outputSocketImage->isConnected()) {
outputSocketImage->relinkConnections(operationAlpha->getOutputSocket());
}
converter.addOperation(operationAlpha);
converter.mapInputSocket(inputSocketImage, operationRGBToHSV_Image->getInputSocket(0));
converter.mapInputSocket(inputSocketKey, operationRGBToHSV_Key->getInputSocket(0));
converter.addLink(operationRGBToHSV_Image->getOutputSocket(), operation->getInputSocket(0));
converter.addLink(operationRGBToHSV_Key->getOutputSocket(), operation->getInputSocket(1));
converter.mapOutputSocket(outputSocketMatte, operation->getOutputSocket(0));
converter.mapInputSocket(inputSocketImage, operationAlpha->getInputSocket(0));
converter.addLink(operation->getOutputSocket(), operationAlpha->getInputSocket(1));
converter.mapOutputSocket(outputSocketImage, operationAlpha->getOutputSocket());
converter.addPreview(operationAlpha->getOutputSocket());
}

View File

@ -31,7 +31,7 @@
class ColorMatteNode : public Node {
public:
ColorMatteNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif /* COM_ColorMatteNODE_H */

View File

@ -29,13 +29,14 @@ ColorNode::ColorNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
void ColorNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void ColorNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
SetColorOperation *operation = new SetColorOperation();
OutputSocket *output = this->getOutputSocket(0);
output->relinkConnections(operation->getOutputSocket());
NodeOutput *output = this->getOutputSocket(0);
float col[4];
output->getEditorValueColor(col);
operation->setChannels(col);
graph->addOperation(operation);
converter.addOperation(operation);
converter.mapOutputSocket(output, operation->getOutputSocket());
}

View File

@ -32,7 +32,7 @@
class ColorNode : public Node {
public:
ColorNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif

View File

@ -32,23 +32,24 @@ ColorRampNode::ColorRampNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
void ColorRampNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void ColorRampNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
InputSocket *inputSocket = this->getInputSocket(0);
OutputSocket *outputSocket = this->getOutputSocket(0);
OutputSocket *outputSocketAlpha = this->getOutputSocket(1);
NodeInput *inputSocket = this->getInputSocket(0);
NodeOutput *outputSocket = this->getOutputSocket(0);
NodeOutput *outputSocketAlpha = this->getOutputSocket(1);
bNode *editorNode = this->getbNode();
ColorRampOperation *operation = new ColorRampOperation();
outputSocket->relinkConnections(operation->getOutputSocket(0));
if (outputSocketAlpha->isConnected()) {
SeparateChannelOperation *operation2 = new SeparateChannelOperation();
outputSocketAlpha->relinkConnections(operation2->getOutputSocket());
addLink(graph, operation->getOutputSocket(), operation2->getInputSocket(0));
operation2->setChannel(3);
graph->addOperation(operation2);
}
operation->setColorBand((ColorBand *)editorNode->storage);
inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph);
graph->addOperation(operation);
converter.addOperation(operation);
converter.mapInputSocket(inputSocket, operation->getInputSocket(0));
converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));
SeparateChannelOperation *operation2 = new SeparateChannelOperation();
operation2->setChannel(3);
converter.addOperation(operation2);
converter.addLink(operation->getOutputSocket(), operation2->getInputSocket(0));
converter.mapOutputSocket(outputSocketAlpha, operation2->getOutputSocket());
}

View File

@ -32,7 +32,7 @@
class ColorRampNode : public Node {
public:
ColorRampNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif /* COM_ColorRampNODE_H */

View File

@ -29,14 +29,13 @@ ColorSpillNode::ColorSpillNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
void ColorSpillNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void ColorSpillNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
InputSocket *inputSocketImage = this->getInputSocket(0);
InputSocket *inputSocketFac = this->getInputSocket(1);
OutputSocket *outputSocketImage = this->getOutputSocket(0);
bNode *editorsnode = getbNode();
NodeInput *inputSocketImage = this->getInputSocket(0);
NodeInput *inputSocketFac = this->getInputSocket(1);
NodeOutput *outputSocketImage = this->getOutputSocket(0);
ColorSpillOperation *operation;
if (editorsnode->custom2 == 0) {
@ -49,11 +48,9 @@ void ColorSpillNode::convertToOperations(ExecutionSystem *graph, CompositorConte
}
operation->setSettings((NodeColorspill *)editorsnode->storage);
operation->setSpillChannel(editorsnode->custom1 - 1); // Channel for spilling
converter.addOperation(operation);
inputSocketImage->relinkConnections(operation->getInputSocket(0), 0, graph);
inputSocketFac->relinkConnections(operation->getInputSocket(1), 1, graph);
outputSocketImage->relinkConnections(operation->getOutputSocket());
graph->addOperation(operation);
converter.mapInputSocket(inputSocketImage, operation->getInputSocket(0));
converter.mapInputSocket(inputSocketFac, operation->getInputSocket(1));
converter.mapOutputSocket(outputSocketImage, operation->getOutputSocket());
}

View File

@ -32,7 +32,7 @@
class ColorSpillNode : public Node {
public:
ColorSpillNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif /* COM_ColorSpillNODE_H */

View File

@ -30,13 +30,14 @@ ColorToBWNode::ColorToBWNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
void ColorToBWNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void ColorToBWNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
InputSocket *colorSocket = this->getInputSocket(0);
OutputSocket *valueSocket = this->getOutputSocket(0);
NodeInput *colorSocket = this->getInputSocket(0);
NodeOutput *valueSocket = this->getOutputSocket(0);
ConvertColorToBWOperation *convertProg = new ConvertColorToBWOperation();
colorSocket->relinkConnections(convertProg->getInputSocket(0), 0, graph);
valueSocket->relinkConnections(convertProg->getOutputSocket(0));
graph->addOperation(convertProg);
converter.addOperation(convertProg);
converter.mapInputSocket(colorSocket, convertProg->getInputSocket(0));
converter.mapOutputSocket(valueSocket, convertProg->getOutputSocket(0));
}

View File

@ -32,6 +32,6 @@
class ColorToBWNode : public Node {
public:
ColorToBWNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif

View File

@ -0,0 +1,93 @@
/*
* 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
* Lukas Toenne
*/
#include "COM_CombineColorNode.h"
#include "COM_ConvertOperation.h"
CombineColorNode::CombineColorNode(bNode *editorNode) :
Node(editorNode)
{
}
void CombineColorNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
NodeInput *inputRSocket = this->getInputSocket(0);
NodeInput *inputGSocket = this->getInputSocket(1);
NodeInput *inputBSocket = this->getInputSocket(2);
NodeInput *inputASocket = this->getInputSocket(3);
NodeOutput *outputSocket = this->getOutputSocket(0);
CombineChannelsOperation *operation = new CombineChannelsOperation();
if (inputRSocket->isLinked()) {
operation->setResolutionInputSocketIndex(0);
}
else if (inputGSocket->isLinked()) {
operation->setResolutionInputSocketIndex(1);
}
else if (inputBSocket->isLinked()) {
operation->setResolutionInputSocketIndex(2);
}
else {
operation->setResolutionInputSocketIndex(3);
}
converter.addOperation(operation);
converter.mapInputSocket(inputRSocket, operation->getInputSocket(0));
converter.mapInputSocket(inputGSocket, operation->getInputSocket(1));
converter.mapInputSocket(inputBSocket, operation->getInputSocket(2));
converter.mapInputSocket(inputASocket, operation->getInputSocket(3));
NodeOperation *color_conv = getColorConverter(context);
if (color_conv) {
converter.addOperation(color_conv);
converter.addLink(operation->getOutputSocket(), color_conv->getInputSocket(0));
converter.mapOutputSocket(outputSocket, color_conv->getOutputSocket());
}
else {
converter.mapOutputSocket(outputSocket, operation->getOutputSocket());
}
}
NodeOperation *CombineRGBANode::getColorConverter(const CompositorContext &context) const
{
return NULL; /* no conversion needed */
}
NodeOperation *CombineHSVANode::getColorConverter(const CompositorContext &context) const
{
return new ConvertHSVToRGBOperation();
}
NodeOperation *CombineYCCANode::getColorConverter(const CompositorContext &context) const
{
return new ConvertYCCToRGBOperation();
}
NodeOperation *CombineYUVANode::getColorConverter(const CompositorContext &context) const
{
return new ConvertYUVToRGBOperation();
}

View File

@ -0,0 +1,74 @@
/*
* 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
* Lukas Toenne
*/
#ifndef _COM_CombineColorNode_h_
#define _COM_CombineColorNode_h_
#include "COM_Node.h"
class CombineColorNode : public Node {
public:
CombineColorNode(bNode *editorNode);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
protected:
virtual NodeOperation *getColorConverter(const CompositorContext &context) const = 0;
};
class CombineRGBANode : public CombineColorNode {
public:
CombineRGBANode(bNode *editorNode) :
CombineColorNode(editorNode)
{}
NodeOperation *getColorConverter(const CompositorContext &context) const;
};
class CombineHSVANode : public CombineColorNode {
public:
CombineHSVANode(bNode *editorNode) :
CombineColorNode(editorNode)
{}
NodeOperation *getColorConverter(const CompositorContext &context) const;
};
class CombineYCCANode : public CombineColorNode {
public:
CombineYCCANode(bNode *editorNode) :
CombineColorNode(editorNode)
{}
NodeOperation *getColorConverter(const CompositorContext &context) const;
};
class CombineYUVANode : public CombineColorNode {
public:
CombineYUVANode(bNode *editorNode) :
CombineColorNode(editorNode)
{}
NodeOperation *getColorConverter(const CompositorContext &context) const;
};
#endif

View File

@ -1,46 +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_CombineHSVANode.h"
#include "COM_ConvertOperation.h"
#include "COM_ExecutionSystem.h"
#include "COM_SetValueOperation.h"
#include "COM_ConvertOperation.h"
CombineHSVANode::CombineHSVANode(bNode *editorNode) : CombineRGBANode(editorNode)
{
/* pass */
}
void CombineHSVANode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
ConvertHSVToRGBOperation *operation = new ConvertHSVToRGBOperation();
OutputSocket *outputSocket = this->getOutputSocket(0);
if (outputSocket->isConnected()) {
outputSocket->relinkConnections(operation->getOutputSocket());
addLink(graph, outputSocket, operation->getInputSocket(0));
}
graph->addOperation(operation);
CombineRGBANode::convertToOperations(graph, context);
}

View File

@ -1,38 +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_CombineHSVANode_h_
#define _COM_CombineHSVANode_h_
#include "COM_Node.h"
#include "DNA_node_types.h"
#include "COM_CombineRGBANode.h"
/**
* @brief CombineHSVANode
* @ingroup Node
*/
class CombineHSVANode : public CombineRGBANode {
public:
CombineHSVANode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
};
#endif

View File

@ -1,64 +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_CombineRGBANode.h"
#include "COM_ConvertOperation.h"
#include "COM_ExecutionSystem.h"
#include "COM_SetValueOperation.h"
#include "DNA_material_types.h" // the ramp types
CombineRGBANode::CombineRGBANode(bNode *editorNode) : Node(editorNode)
{
/* pass */
}
void CombineRGBANode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
InputSocket *inputRSocket = this->getInputSocket(0);
InputSocket *inputGSocket = this->getInputSocket(1);
InputSocket *inputBSocket = this->getInputSocket(2);
InputSocket *inputASocket = this->getInputSocket(3);
OutputSocket *outputSocket = this->getOutputSocket(0);
CombineChannelsOperation *operation = new CombineChannelsOperation();
if (inputRSocket->isConnected()) {
operation->setResolutionInputSocketIndex(0);
}
else if (inputGSocket->isConnected()) {
operation->setResolutionInputSocketIndex(1);
}
else if (inputBSocket->isConnected()) {
operation->setResolutionInputSocketIndex(2);
}
else {
operation->setResolutionInputSocketIndex(3);
}
inputRSocket->relinkConnections(operation->getInputSocket(0), 0, graph);
inputGSocket->relinkConnections(operation->getInputSocket(1), 1, graph);
inputBSocket->relinkConnections(operation->getInputSocket(2), 2, graph);
inputASocket->relinkConnections(operation->getInputSocket(3), 3, graph);
outputSocket->relinkConnections(operation->getOutputSocket(0));
graph->addOperation(operation);
}

View File

@ -1,37 +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_CombineRGBANode_h_
#define _COM_CombineRGBANode_h_
#include "COM_Node.h"
#include "DNA_node_types.h"
/**
* @brief CombineRGBANode
* @ingroup Node
*/
class CombineRGBANode : public Node {
public:
CombineRGBANode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
};
#endif

View File

@ -1,45 +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:
* Dalai Felinto
*/
#include "COM_CombineYCCANode.h"
#include "COM_ConvertOperation.h"
CombineYCCANode::CombineYCCANode(bNode *editorNode) : CombineRGBANode(editorNode)
{
/* pass */
}
void CombineYCCANode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
ConvertYCCToRGBOperation *operation = new ConvertYCCToRGBOperation();
OutputSocket *outputSocket = this->getOutputSocket(0);
bNode *node = this->getbNode();
operation->setMode(node->custom1);
if (outputSocket->isConnected()) {
outputSocket->relinkConnections(operation->getOutputSocket());
addLink(graph, outputSocket, operation->getInputSocket(0));
}
graph->addOperation(operation);
CombineRGBANode::convertToOperations(graph, context);
}

View File

@ -1,37 +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:
* Dalai Felinto
*/
#ifndef _COM_CombineYCCANode_h_
#define _COM_CombineYCCANode_h_
#include "COM_Node.h"
#include "DNA_node_types.h"
#include "COM_CombineRGBANode.h"
/**
* @brief CombineYCCANode
* @ingroup Node
*/
class CombineYCCANode : public CombineRGBANode {
public:
CombineYCCANode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
};
#endif

View File

@ -1,40 +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:
* Dalai Felinto
*/
#include "COM_CombineYUVANode.h"
#include "COM_ConvertOperation.h"
CombineYUVANode::CombineYUVANode(bNode *editorNode) : CombineRGBANode(editorNode)
{
/* pass */
}
void CombineYUVANode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
ConvertYUVToRGBOperation *operation = new ConvertYUVToRGBOperation();
OutputSocket *outputSocket = this->getOutputSocket(0);
if (outputSocket->isConnected()) {
outputSocket->relinkConnections(operation->getOutputSocket());
addLink(graph, outputSocket, operation->getInputSocket(0));
}
graph->addOperation(operation);
CombineRGBANode::convertToOperations(graph, context);
}

View File

@ -1,37 +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:
* Dalai Felinto
*/
#ifndef _COM_CombineYUVANode_h_
#define _COM_CombineYUVANode_h_
#include "COM_Node.h"
#include "DNA_node_types.h"
#include "COM_CombineRGBANode.h"
/**
* @brief CombineYUVANode
* @ingroup Node
*/
class CombineYUVANode : public CombineRGBANode {
public:
CombineYUVANode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
};
#endif

View File

@ -29,26 +29,27 @@ CompositorNode::CompositorNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
void CompositorNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void CompositorNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
bNode *editorNode = this->getbNode();
bool is_active = (editorNode->flag & NODE_DO_OUTPUT_RECALC) ||
context->isRendering();
context.isRendering();
InputSocket *imageSocket = this->getInputSocket(0);
InputSocket *alphaSocket = this->getInputSocket(1);
InputSocket *depthSocket = this->getInputSocket(2);
NodeInput *imageSocket = this->getInputSocket(0);
NodeInput *alphaSocket = this->getInputSocket(1);
NodeInput *depthSocket = this->getInputSocket(2);
CompositorOperation *compositorOperation = new CompositorOperation();
compositorOperation->setSceneName(context->getScene()->id.name);
compositorOperation->setRenderData(context->getRenderData());
compositorOperation->setbNodeTree(context->getbNodeTree());
compositorOperation->setSceneName(context.getScene()->id.name);
compositorOperation->setRenderData(context.getRenderData());
compositorOperation->setbNodeTree(context.getbNodeTree());
compositorOperation->setIgnoreAlpha(editorNode->custom2 & CMP_NODE_OUTPUT_IGNORE_ALPHA);
compositorOperation->setActive(is_active);
imageSocket->relinkConnections(compositorOperation->getInputSocket(0), 0, graph);
alphaSocket->relinkConnections(compositorOperation->getInputSocket(1));
depthSocket->relinkConnections(compositorOperation->getInputSocket(2));
graph->addOperation(compositorOperation);
addPreviewOperation(graph, context, compositorOperation->getInputSocket(0));
converter.addOperation(compositorOperation);
converter.mapInputSocket(imageSocket, compositorOperation->getInputSocket(0));
converter.mapInputSocket(alphaSocket, compositorOperation->getInputSocket(1));
converter.mapInputSocket(depthSocket, compositorOperation->getInputSocket(2));
converter.addNodeInputPreview(imageSocket);
}

View File

@ -32,6 +32,6 @@
class CompositorNode : public Node {
public:
CompositorNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif

View File

@ -23,7 +23,7 @@
#include "COM_ConvertOperation.h"
#include "COM_ExecutionSystem.h"
void ConvertAlphaNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void ConvertAlphaNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
NodeOperation *operation = NULL;
bNode *node = this->getbNode();
@ -35,9 +35,9 @@ void ConvertAlphaNode::convertToOperations(ExecutionSystem *graph, CompositorCon
else {
operation = new ConvertStraightToPremulOperation();
}
this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
graph->addOperation(operation);
converter.addOperation(operation);
converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket());
}

View File

@ -31,7 +31,7 @@
class ConvertAlphaNode : public Node {
public:
ConvertAlphaNode(bNode *editorNode) : Node(editorNode) {}
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif

View File

@ -28,9 +28,9 @@ CornerPinNode::CornerPinNode(bNode *editorNode) : Node(editorNode)
{
}
void CornerPinNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void CornerPinNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
InputSocket *input_image = this->getInputSocket(0);
NodeInput *input_image = this->getInputSocket(0);
/* note: socket order differs between UI node and operations:
* bNode uses intuitive order following top-down layout:
* upper-left, upper-right, lower-left, lower-right
@ -39,29 +39,20 @@ void CornerPinNode::convertToOperations(ExecutionSystem *graph, CompositorContex
*/
const int node_corner_index[4] = { 3, 4, 2, 1 };
OutputSocket *output_warped_image = this->getOutputSocket(0);
OutputSocket *output_plane = this->getOutputSocket(1);
NodeOutput *output_warped_image = this->getOutputSocket(0);
NodeOutput *output_plane = this->getOutputSocket(1);
PlaneCornerPinWarpImageOperation *warp_image_operation = new PlaneCornerPinWarpImageOperation();
input_image->relinkConnections(warp_image_operation->getInputSocket(0), 0, graph);
for (int i = 0; i < 4; ++i) {
int node_index = node_corner_index[i];
getInputSocket(node_index)->relinkConnections(warp_image_operation->getInputSocket(i + 1),
node_index, graph);
}
output_warped_image->relinkConnections(warp_image_operation->getOutputSocket());
graph->addOperation(warp_image_operation);
converter.addOperation(warp_image_operation);
PlaneCornerPinMaskOperation *plane_mask_operation = new PlaneCornerPinMaskOperation();
converter.addOperation(plane_mask_operation);
/* connect mask op inputs to the same sockets as the warp image op */
for (int i = 0; i < 4; ++i)
addLink(graph,
warp_image_operation->getInputSocket(i + 1)->getConnection()->getFromSocket(),
plane_mask_operation->getInputSocket(i));
output_plane->relinkConnections(plane_mask_operation->getOutputSocket());
graph->addOperation(plane_mask_operation);
converter.mapInputSocket(input_image, warp_image_operation->getInputSocket(0));
for (int i = 0; i < 4; ++i) {
NodeInput *corner_input = getInputSocket(node_corner_index[i]);
converter.mapInputSocket(corner_input, warp_image_operation->getInputSocket(i + 1));
converter.mapInputSocket(corner_input, plane_mask_operation->getInputSocket(i));
}
converter.mapOutputSocket(output_warped_image, warp_image_operation->getOutputSocket());
converter.mapOutputSocket(output_plane, plane_mask_operation->getOutputSocket());
}

View File

@ -35,7 +35,7 @@ extern "C" {
class CornerPinNode : public Node {
public:
CornerPinNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif /* _COM_CornerPinNode_h */

View File

@ -29,7 +29,7 @@ CropNode::CropNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
void CropNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void CropNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
bNode *node = getbNode();
NodeTwoXYs *cropSettings = (NodeTwoXYs *)node->storage;
@ -44,7 +44,8 @@ void CropNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co
}
operation->setCropSettings(cropSettings);
operation->setRelative(relative);
this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
this->getOutputSocket()->relinkConnections(operation->getOutputSocket());
graph->addOperation(operation);
converter.addOperation(operation);
converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));
converter.mapOutputSocket(getOutputSocket(), operation->getOutputSocket());
}

View File

@ -32,7 +32,7 @@
class CropNode : public Node {
public:
CropNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif

View File

@ -39,11 +39,11 @@ DefocusNode::DefocusNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
void DefocusNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void DefocusNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
bNode *node = this->getbNode();
NodeDefocus *data = (NodeDefocus *)node->storage;
Scene *scene = node->id ? (Scene *)node->id : context->getScene();
Scene *scene = node->id ? (Scene *)node->id : context.getScene();
Object *camob = scene ? scene->camera : NULL;
NodeOperation *radiusOperation;
@ -54,36 +54,39 @@ void DefocusNode::convertToOperations(ExecutionSystem *graph, CompositorContext
SetValueOperation *maxRadius = new SetValueOperation();
maxRadius->setValue(data->maxblur);
MathMinimumOperation *minimize = new MathMinimumOperation();
this->getInputSocket(1)->relinkConnections(multiply->getInputSocket(0), 1, graph);
addLink(graph, multiplier->getOutputSocket(), multiply->getInputSocket(1));
addLink(graph, maxRadius->getOutputSocket(), minimize->getInputSocket(1));
addLink(graph, multiply->getOutputSocket(), minimize->getInputSocket(0));
graph->addOperation(multiply);
graph->addOperation(multiplier);
graph->addOperation(maxRadius);
graph->addOperation(minimize);
converter.addOperation(multiply);
converter.addOperation(multiplier);
converter.addOperation(maxRadius);
converter.addOperation(minimize);
converter.mapInputSocket(getInputSocket(1), multiply->getInputSocket(0));
converter.addLink(multiplier->getOutputSocket(), multiply->getInputSocket(1));
converter.addLink(multiply->getOutputSocket(), minimize->getInputSocket(0));
converter.addLink(maxRadius->getOutputSocket(), minimize->getInputSocket(1));
radiusOperation = minimize;
}
else {
ConvertDepthToRadiusOperation *converter = new ConvertDepthToRadiusOperation();
converter->setCameraObject(camob);
converter->setfStop(data->fstop);
converter->setMaxRadius(data->maxblur);
this->getInputSocket(1)->relinkConnections(converter->getInputSocket(0), 1, graph);
graph->addOperation(converter);
ConvertDepthToRadiusOperation *radius_op = new ConvertDepthToRadiusOperation();
radius_op->setCameraObject(camob);
radius_op->setfStop(data->fstop);
radius_op->setMaxRadius(data->maxblur);
converter.addOperation(radius_op);
converter.mapInputSocket(getInputSocket(1), radius_op->getInputSocket(0));
FastGaussianBlurValueOperation *blur = new FastGaussianBlurValueOperation();
addLink(graph, converter->getOutputSocket(0), blur->getInputSocket(0));
graph->addOperation(blur);
radiusOperation = blur;
converter->setPostBlur(blur);
/* maintain close pixels so far Z values don't bleed into the foreground */
blur->setOverlay(FAST_GAUSS_OVERLAY_MIN);
converter.addOperation(blur);
converter.addLink(radius_op->getOutputSocket(0), blur->getInputSocket(0));
radius_op->setPostBlur(blur);
radiusOperation = blur;
}
BokehImageOperation *bokeh = new BokehImageOperation();
NodeBokehImage *bokehdata = new NodeBokehImage();
bokehdata->angle = data->rotation;
bokehdata->rounding = 0.0f;
@ -95,44 +98,47 @@ void DefocusNode::convertToOperations(ExecutionSystem *graph, CompositorContext
bokehdata->catadioptric = 0.0f;
bokehdata->lensshift = 0.0f;
BokehImageOperation *bokeh = new BokehImageOperation();
bokeh->setData(bokehdata);
bokeh->deleteDataOnFinish();
graph->addOperation(bokeh);
#ifdef COM_DEFOCUS_SEARCH
InverseSearchRadiusOperation *search = new InverseSearchRadiusOperation();
addLink(graph, radiusOperation->getOutputSocket(0), search->getInputSocket(0));
search->setMaxBlur(data->maxblur);
graph->addOperation(search);
#endif
VariableSizeBokehBlurOperation *operation = new VariableSizeBokehBlurOperation();
if (data->preview) {
operation->setQuality(COM_QUALITY_LOW);
}
else {
operation->setQuality(context->getQuality());
}
operation->setMaxBlur(data->maxblur);
operation->setbNode(node);
operation->setThreshold(data->bthresh);
addLink(graph, bokeh->getOutputSocket(), operation->getInputSocket(1));
addLink(graph, radiusOperation->getOutputSocket(), operation->getInputSocket(2));
converter.addOperation(bokeh);
#ifdef COM_DEFOCUS_SEARCH
addLink(graph, search->getOutputSocket(), operation->getInputSocket(3));
InverseSearchRadiusOperation *search = new InverseSearchRadiusOperation();
search->setMaxBlur(data->maxblur);
converter.addOperation(search);
converter.addLink(radiusOperation->getOutputSocket(0), search->getInputSocket(0));
#endif
VariableSizeBokehBlurOperation *operation = new VariableSizeBokehBlurOperation();
if (data->preview)
operation->setQuality(COM_QUALITY_LOW);
else
operation->setQuality(context.getQuality());
operation->setMaxBlur(data->maxblur);
operation->setThreshold(data->bthresh);
converter.addOperation(operation);
converter.addLink(bokeh->getOutputSocket(), operation->getInputSocket(1));
converter.addLink(radiusOperation->getOutputSocket(), operation->getInputSocket(2));
#ifdef COM_DEFOCUS_SEARCH
converter.addLink(search->getOutputSocket(), operation->getInputSocket(3));
#endif
if (data->gamco) {
GammaCorrectOperation *correct = new GammaCorrectOperation();
converter.addOperation(correct);
GammaUncorrectOperation *inverse = new GammaUncorrectOperation();
this->getInputSocket(0)->relinkConnections(correct->getInputSocket(0), 0, graph);
addLink(graph, correct->getOutputSocket(), operation->getInputSocket(0));
addLink(graph, operation->getOutputSocket(), inverse->getInputSocket(0));
this->getOutputSocket()->relinkConnections(inverse->getOutputSocket());
graph->addOperation(correct);
graph->addOperation(inverse);
converter.addOperation(inverse);
converter.mapInputSocket(getInputSocket(0), correct->getInputSocket(0));
converter.addLink(correct->getOutputSocket(), operation->getInputSocket(0));
converter.addLink(operation->getOutputSocket(), inverse->getInputSocket(0));
converter.mapOutputSocket(getOutputSocket(), inverse->getOutputSocket());
}
else {
this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
this->getOutputSocket()->relinkConnections(operation->getOutputSocket());
converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));
converter.mapOutputSocket(getOutputSocket(), operation->getOutputSocket());
}
graph->addOperation(operation);
}

View File

@ -32,7 +32,7 @@
class DefocusNode : public Node {
public:
DefocusNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif

View File

@ -29,22 +29,21 @@ DespeckleNode::DespeckleNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
void DespeckleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
void DespeckleNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
bNode *editorNode = this->getbNode();
InputSocket *inputSocket = this->getInputSocket(0);
InputSocket *inputImageSocket = this->getInputSocket(1);
OutputSocket *outputSocket = this->getOutputSocket(0);
NodeInput *inputSocket = this->getInputSocket(0);
NodeInput *inputImageSocket = this->getInputSocket(1);
NodeOutput *outputSocket = this->getOutputSocket(0);
DespeckleOperation *operation = new DespeckleOperation();
operation->setbNode(editorNode);
operation->setThreshold(editorNode->custom3);
operation->setThresholdNeighbor(editorNode->custom4);
inputImageSocket->relinkConnections(operation->getInputSocket(0), 1, graph);
inputSocket->relinkConnections(operation->getInputSocket(1), 0, graph);
outputSocket->relinkConnections(operation->getOutputSocket());
addPreviewOperation(graph, context, operation->getOutputSocket(0));
graph->addOperation(operation);
converter.addOperation(operation);
converter.mapInputSocket(inputImageSocket, operation->getInputSocket(0));
converter.mapInputSocket(inputSocket, operation->getInputSocket(1));
converter.mapOutputSocket(outputSocket, operation->getOutputSocket());
converter.addPreview(operation->getOutputSocket(0));
}

View File

@ -30,7 +30,7 @@
class DespeckleNode : public Node {
public:
DespeckleNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
};
#endif

Some files were not shown because too many files have changed in this diff Show More