svn merge ^/trunk/blender -r48638:48658
[blender.git] / source / blender / compositor / intern / COM_ExecutionSystemHelper.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor: 
19  *              Jeroen Bakker 
20  *              Monique Dewanchand
21  */
22
23 #include "COM_ExecutionSystemHelper.h"
24
25 #include <sstream>
26 #include <stdio.h>
27
28 #include "PIL_time.h"
29 #include "BKE_node.h"
30
31 #include "COM_Converter.h"
32 #include "COM_NodeOperation.h"
33 #include "COM_ExecutionGroup.h"
34 #include "COM_NodeBase.h"
35 #include "COM_WorkScheduler.h"
36 #include "COM_ReadBufferOperation.h"
37 #include "COM_GroupNode.h"
38 #include "COM_WriteBufferOperation.h"
39 #include "COM_ReadBufferOperation.h"
40 #include "COM_ViewerBaseOperation.h"
41
42 void ExecutionSystemHelper::addbNodeTree(ExecutionSystem &system, int nodes_start, bNodeTree *tree, bNode *groupnode)
43 {
44         vector<Node *>& nodes = system.getNodes();
45         vector<SocketConnection *>& links = system.getConnections();
46         const bNode *activeGroupNode = system.getContext().getActivegNode();
47         bool isActiveGroup = activeGroupNode == groupnode;
48         
49         /* add all nodes of the tree to the node list */
50         bNode *node = (bNode *)tree->nodes.first;
51         while (node != NULL) {
52                 addNode(nodes, node, isActiveGroup, system.getContext().isFastCalculation());
53                 node = (bNode *)node->next;
54         }
55
56         NodeRange node_range(nodes.begin() + nodes_start, nodes.end());
57
58         /* add all nodelinks of the tree to the link list */
59         bNodeLink *nodelink = (bNodeLink *)tree->links.first;
60         while (nodelink != NULL) {
61                 addNodeLink(node_range, links, nodelink);
62                 nodelink = (bNodeLink *)nodelink->next;
63         }
64
65         /* Expand group nodes */
66         for (unsigned int i = nodes_start; i < nodes.size(); ++i) {
67                 Node *execnode = nodes[i];
68                 if (execnode->isGroupNode()) {
69                         GroupNode *groupNode = (GroupNode *)execnode;
70                         groupNode->ungroup(system);
71                 }
72         }
73 }
74
75 void ExecutionSystemHelper::addNode(vector<Node *>& nodes, Node *node)
76 {
77         nodes.push_back(node);
78 }
79
80 Node *ExecutionSystemHelper::addNode(vector<Node *>& nodes, bNode *b_node, bool inActiveGroup, bool fast)
81 {
82         Converter converter;
83         Node *node;
84         node = converter.convert(b_node, fast);
85         node->setIsInActiveGroup(inActiveGroup);
86         if (node != NULL) {
87                 addNode(nodes, node);
88                 return node;
89         }
90         return NULL;
91 }
92 void ExecutionSystemHelper::addOperation(vector<NodeOperation *>& operations, NodeOperation *operation)
93 {
94         operations.push_back(operation);
95 }
96
97 void ExecutionSystemHelper::addExecutionGroup(vector<ExecutionGroup *>& executionGroups, ExecutionGroup *executionGroup)
98 {
99         executionGroups.push_back(executionGroup);
100 }
101
102 void ExecutionSystemHelper::findOutputNodeOperations(vector<NodeOperation *> *result, vector<NodeOperation *>& operations, bool rendering)
103 {
104         unsigned int index;
105
106         for (index = 0; index < operations.size(); index++) {
107                 NodeOperation *operation = operations[index];
108                 if (operation->isOutputOperation(rendering)) {
109                         result->push_back(operation);
110                 }
111         }
112 }
113
114 static InputSocket *find_input(NodeRange &node_range, bNode *bnode, bNodeSocket *bsocket)
115 {
116         if (bnode != NULL) {
117                 for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
118                         Node *node = *it;
119                         if (node->getbNode() == bnode)
120                                 return node->findInputSocketBybNodeSocket(bsocket);
121                 }
122         }
123         else {
124                 for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
125                         Node *node = *it;
126                         if (node->isProxyNode()) {
127                                 InputSocket *proxySocket = node->getInputSocket(0);
128                                 if (proxySocket->getbNodeSocket() == bsocket)
129                                         return proxySocket;
130                         }
131                 }
132         }
133         return NULL;
134 }
135 static OutputSocket *find_output(NodeRange &node_range, bNode *bnode, bNodeSocket *bsocket)
136 {
137         if (bnode != NULL) {
138                 for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
139                         Node *node = *it;
140                         if (node->getbNode() == bnode)
141                                 return node->findOutputSocketBybNodeSocket(bsocket);
142                 }
143         }
144         else {
145                 for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
146                         Node *node = *it;
147                         if (node->isProxyNode()) {
148                                 OutputSocket *proxySocket = node->getOutputSocket(0);
149                                 if (proxySocket->getbNodeSocket() == bsocket)
150                                         return proxySocket;
151                         }
152                 }
153         }
154         return NULL;
155 }
156 SocketConnection *ExecutionSystemHelper::addNodeLink(NodeRange &node_range, vector<SocketConnection *>& links, bNodeLink *b_nodelink)
157 {
158         /// @note: cyclic lines will be ignored. This has been copied from node.c
159         if (b_nodelink->tonode != 0 && b_nodelink->fromnode != 0) {
160                 if (!(b_nodelink->fromnode->level >= b_nodelink->tonode->level && b_nodelink->tonode->level != 0xFFF)) { // only add non cyclic lines! so execution will procede
161                         return NULL;
162                 }
163         }
164
165         InputSocket *inputSocket = find_input(node_range, b_nodelink->tonode, b_nodelink->tosock);
166         OutputSocket *outputSocket = find_output(node_range, b_nodelink->fromnode, b_nodelink->fromsock);
167         if (inputSocket == NULL || outputSocket == NULL) {
168                 return NULL;
169         }
170         if (inputSocket->isConnected()) {
171                 return NULL;
172         }
173         SocketConnection *connection = addLink(links, outputSocket, inputSocket);
174         return connection;
175 }
176
177 SocketConnection *ExecutionSystemHelper::addLink(vector<SocketConnection *>& links, OutputSocket *fromSocket, InputSocket *toSocket)
178 {
179         SocketConnection *newconnection = new SocketConnection();
180         newconnection->setFromSocket(fromSocket);
181         newconnection->setToSocket(toSocket);
182         fromSocket->addConnection(newconnection);
183         toSocket->setConnection(newconnection);
184         links.push_back(newconnection);
185         return newconnection;
186 }
187
188 void ExecutionSystemHelper::debugDump(ExecutionSystem *system)
189 {
190         Node *node;
191         NodeOperation *operation;
192         ExecutionGroup *group;
193         SocketConnection *connection;
194         int tot, tot2;
195         printf("-- BEGIN COMPOSITOR DUMP --\r\n");
196         printf("digraph compositorexecution {\r\n");
197         tot = system->getNodes().size();
198         for (int i = 0; i < tot; i++) {
199                 node = system->getNodes()[i];
200                 printf("// NODE: %s\r\n", node->getbNode()->typeinfo->name);
201         }
202         tot = system->getOperations().size();
203         for (int i = 0; i < tot; i++) {
204                 operation = system->getOperations()[i];
205                 printf("// OPERATION: %p\r\n", operation);
206                 printf("\t\"O_%p\"", operation);
207                 printf(" [shape=record,label=\"{");
208                 tot2 = operation->getNumberOfInputSockets();
209                 if (tot2 != 0) {
210                         printf("{");
211                         for (int j = 0; j < tot2; j++) {
212                                 InputSocket *socket = operation->getInputSocket(j);
213                                 if (j != 0) {
214                                         printf("|");
215                                 }
216                                 printf("<IN_%p>", socket);
217                                 switch (socket->getDataType()) {
218                                         case COM_DT_VALUE:
219                                                 printf("Value");
220                                                 break;
221                                         case COM_DT_VECTOR:
222                                                 printf("Vector");
223                                                 break;
224                                         case COM_DT_COLOR:
225                                                 printf("Color");
226                                                 break;
227                                 }
228                         }
229                         printf("}");
230                         printf("|");
231                 }
232                 if (operation->isViewerOperation()) {
233                         ViewerBaseOperation *viewer = (ViewerBaseOperation *)operation;
234                         if (viewer->isActiveViewerOutput()) {
235                                 printf("Active viewer");
236                         }
237                         else {
238                                 printf("Viewer");
239                         }
240                 }
241                 else if (operation->isOutputOperation(system->getContext().isRendering())) {
242                         printf("Output");
243                 }
244                 else if (operation->isSetOperation()) {
245                         printf("Set");
246                 }
247                 else if (operation->isReadBufferOperation()) {
248                         printf("ReadBuffer");
249                 }
250                 else if (operation->isWriteBufferOperation()) {
251                         printf("WriteBuffer");
252                 }
253                 else {
254                         printf("O_%p", operation);
255                 }
256                 printf(" (%d,%d)", operation->getWidth(), operation->getHeight());
257                 tot2 = operation->getNumberOfOutputSockets();
258                 if (tot2 != 0) {
259                         printf("|");
260                         printf("{");
261                         for (int j = 0; j < tot2; j++) {
262                                 OutputSocket *socket = operation->getOutputSocket(j);
263                                 if (j != 0) {
264                                         printf("|");
265                                 }
266                                 printf("<OUT_%p>", socket);
267                                 switch (socket->getDataType()) {
268                                         case COM_DT_VALUE:
269                                                 printf("Value");
270                                                 break;
271                                         case COM_DT_VECTOR:
272                                                 printf("Vector");
273                                                 break;
274                                         case COM_DT_COLOR:
275                                                 printf("Color");
276                                                 break;
277                                 }
278                         }
279                         printf("}");
280                 }
281                 printf("}\"]");
282                 printf("\r\n");
283         }
284         tot = system->getExecutionGroups().size();
285         for (int i = 0; i < tot; i++) {
286                 group = system->getExecutionGroups()[i];
287                 printf("// GROUP: %d\r\n", i);
288                 printf("subgraph {\r\n");
289                 printf("//  OUTPUTOPERATION: %p\r\n", group->getOutputNodeOperation());
290                 printf(" O_%p\r\n", group->getOutputNodeOperation());
291                 printf("}\r\n");
292         }
293         tot = system->getOperations().size();
294         for (int i = 0; i < tot; i++) {
295                 operation = system->getOperations()[i];
296                 if (operation->isReadBufferOperation()) {
297                         ReadBufferOperation *read = (ReadBufferOperation *)operation;
298                         WriteBufferOperation *write = read->getMemoryProxy()->getWriteBufferOperation();
299                         printf("\t\"O_%p\" -> \"O_%p\" [style=dotted]\r\n", write, read);
300                 }
301         }
302         tot = system->getConnections().size();
303         for (int i = 0; i < tot; i++) {
304                 connection = system->getConnections()[i];
305                 printf("// CONNECTION: %p.%p -> %p.%p\r\n", connection->getFromNode(), connection->getFromSocket(), connection->getToNode(), connection->getToSocket());
306                 printf("\t\"O_%p\":\"OUT_%p\" -> \"O_%p\":\"IN_%p\"", connection->getFromNode(), connection->getFromSocket(), connection->getToNode(), connection->getToSocket());
307                 if (!connection->isValid()) {
308                         printf(" [color=red]");
309                 }
310                 else {
311                         switch (connection->getFromSocket()->getDataType()) {
312                                 case COM_DT_VALUE:
313                                         printf(" [color=grey]");
314                                         break;
315                                 case COM_DT_VECTOR:
316                                         printf(" [color=blue]");
317                                         break;
318                                 case COM_DT_COLOR:
319                                         printf(" [color=orange]");
320                                         break;
321                         }
322                 }
323                 printf("\r\n");
324         }
325         printf("}\r\n");
326         printf("-- END COMPOSITOR DUMP --\r\n");
327 }