/* * 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 "BKE_node.h" #include "COM_Converter.h" #include #include "COM_NodeOperation.h" #include "COM_ExecutionGroup.h" #include "COM_NodeBase.h" #include "COM_WorkScheduler.h" #include "COM_ReadBufferOperation.h" #include "COM_MemoryManager.h" #include "stdio.h" #include "COM_GroupNode.h" #include "COM_WriteBufferOperation.h" #include "COM_ReadBufferOperation.h" Node* ExecutionSystemHelper::addbNodeTree(ExecutionSystem &system, int nodes_start, bNodeTree *tree) { vector& nodes = system.getNodes(); vector& links = system.getConnections(); Node* mainnode = NULL; /* add all nodes of the tree to the node list */ bNode* node = (bNode*)tree->nodes.first; while (node != NULL) { Node* execnode = addNode(nodes, node); if (node->type == CMP_NODE_COMPOSITE) { mainnode = execnode; } node = (bNode*)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 = (bNodeLink*)nodelink->next; } /* Expand group nodes */ for (int i=nodes_start; i < nodes.size(); ++i) { Node *execnode = nodes[i]; if (execnode->isGroupNode()) { GroupNode * groupNode = (GroupNode*)execnode; groupNode->ungroup(system); } } return mainnode; } void ExecutionSystemHelper::addNode(vector& nodes, Node *node) { nodes.push_back(node); } Node* ExecutionSystemHelper::addNode(vector& nodes, bNode *bNode) { Converter converter; Node * node; node = converter.convert(bNode); if (node != NULL) { addNode(nodes, node); return node; } return NULL; } void ExecutionSystemHelper::addOperation(vector& operations, NodeOperation *operation) { operations.push_back(operation); } void ExecutionSystemHelper::addExecutionGroup(vector& executionGroups, ExecutionGroup *executionGroup) { executionGroups.push_back(executionGroup); } void ExecutionSystemHelper::findOutputNodeOperations(vector* result, vector& 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) { if (bnode != NULL) { for (NodeIterator it=node_range.first; it!=node_range.second; ++it) { Node* node = *it; if (node->getbNode() == bnode) return node->findInputSocketBybNodeSocket(bsocket); } } else { for (NodeIterator it=node_range.first; it!=node_range.second; ++it) { Node* node = *it; if (node->isProxyNode()) { InputSocket *proxySocket = node->getInputSocket(0); if (proxySocket->getbNodeSocket()==bsocket) return proxySocket; } } } return NULL; } static OutputSocket* find_output(NodeRange &node_range, bNode *bnode, bNodeSocket* bsocket) { if (bnode != NULL) { for (NodeIterator it=node_range.first; it!=node_range.second; ++it) { Node* node = *it; if (node->getbNode() == bnode) return node->findOutputSocketBybNodeSocket(bsocket); } } else { for (NodeIterator it=node_range.first; it!=node_range.second; ++it) { Node* node = *it; if (node->isProxyNode()) { OutputSocket *proxySocket = node->getOutputSocket(0); if (proxySocket->getbNodeSocket()==bsocket) return proxySocket; } } } return NULL; } SocketConnection* ExecutionSystemHelper::addNodeLink(NodeRange &node_range, vector& links, bNodeLink *bNodeLink) { /// @note: cyclic lines will be ignored. This has been copied from node.c if (bNodeLink->tonode != 0 && bNodeLink->fromnode != 0) { if (!(bNodeLink->fromnode->level >= bNodeLink->tonode->level && bNodeLink->tonode->level!=0xFFF)) { // only add non cyclic lines! so execution will procede return NULL; } } InputSocket *inputSocket = find_input(node_range, bNodeLink->tonode, bNodeLink->tosock); OutputSocket *outputSocket = find_output(node_range, bNodeLink->fromnode, bNodeLink->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& 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; } void ExecutionSystemHelper::debugDump(ExecutionSystem* system) { Node* node; NodeOperation* operation; ExecutionGroup* group; SocketConnection* connection; int tot, tot2; printf("-- BEGIN COMPOSITOR DUMP --\r\n"); printf("digraph compositorexecution {\r\n"); tot = system->getNodes().size(); for (int i = 0 ; i < tot ; i ++) { node = system->getNodes()[i]; printf("// NODE: %s\r\n", node->getbNode()->typeinfo->name); } tot = system->getOperations().size(); for (int i = 0 ; i < tot ; i ++) { operation = system->getOperations()[i]; printf("// OPERATION: %p\r\n", operation); printf("\t\"O_%p\"", operation); printf(" [shape=record,label=\"{"); tot2 = operation->getNumberOfInputSockets(); if (tot2 != 0) { printf("{"); for (int j = 0 ; j < tot2 ; j ++) { InputSocket *socket = operation->getInputSocket(j); if (j != 0) { printf("|"); } printf("", socket); switch (socket->getActualDataType()) { case COM_DT_VALUE: printf("Value"); break; case COM_DT_VECTOR: printf("Vector"); break; case COM_DT_COLOR: printf("Color"); break; case COM_DT_UNKNOWN: printf("Unknown"); break; } } printf("}"); printf("|"); } if (operation->isViewerOperation()) { printf("Viewer"); } else if (operation->isOutputOperation(system->getContext().isRendering())) { printf("Output"); } else if (operation->isSetOperation()) { printf("Set"); } else if (operation->isReadBufferOperation()) { printf("ReadBuffer"); } else if (operation->isWriteBufferOperation()) { printf("WriteBuffer"); } else { printf("O_%p", operation); } tot2 = operation->getNumberOfOutputSockets(); if (tot2 != 0) { printf("|"); printf("{"); for (int j = 0 ; j < tot2 ; j ++) { OutputSocket *socket = operation->getOutputSocket(j); if (j != 0) { printf("|"); } printf("", socket); switch (socket->getActualDataType()) { case COM_DT_VALUE: printf("Value"); break; case COM_DT_VECTOR: printf("Vector"); break; case COM_DT_COLOR: printf("Color"); break; case COM_DT_UNKNOWN: printf("Unknown"); break; } } printf("}"); } printf("}\"]"); printf("\r\n"); } tot = system->getExecutionGroups().size(); for (int i = 0 ; i < tot ; i ++) { group = system->getExecutionGroups()[i]; printf("// GROUP: %d\r\n", i); printf("subgraph {\r\n"); printf("// OUTPUTOPERATION: %p\r\n", group->getOutputNodeOperation()); printf(" O_%p\r\n", group->getOutputNodeOperation()); printf("}\r\n"); } tot = system->getOperations().size(); for (int i = 0 ; i < tot ; i ++) { operation = system->getOperations()[i]; if (operation->isReadBufferOperation()) { ReadBufferOperation * read = (ReadBufferOperation*)operation; WriteBufferOperation * write= read->getMemoryProxy()->getWriteBufferOperation(); printf("\t\"O_%p\" -> \"O_%p\" [style=dotted]\r\n", write, read); } } tot = system->getConnections().size(); for (int i = 0 ; i < tot ; i ++) { connection = system->getConnections()[i]; printf("// CONNECTION: %p.%p -> %p.%p\r\n", connection->getFromNode(), connection->getFromSocket(), connection->getToNode(), connection->getToSocket()); printf("\t\"O_%p\":\"OUT_%p\" -> \"O_%p\":\"IN_%p\"", connection->getFromNode(), connection->getFromSocket(), connection->getToNode(), connection->getToSocket()); if (!connection->isValid()) { printf(" [color=red]"); } else { switch (connection->getFromSocket()->getActualDataType()) { case COM_DT_VALUE: printf(" [color=grey]"); break; case COM_DT_VECTOR: printf(" [color=blue]"); break; case COM_DT_COLOR: printf(" [color=orange]"); break; case COM_DT_UNKNOWN: printf(" [color=black]"); break; } } printf("\r\n"); } printf("}\r\n"); printf("-- END COMPOSITOR DUMP --\r\n"); }