code cleanup: remove paranoid NULL checks (these cases would crash earlier of the...
[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         Node *node = Converter::convert(b_node, fast);
83         node->setIsInActiveGroup(inActiveGroup);
84         addNode(nodes, node);
85         return node;
86 }
87 void ExecutionSystemHelper::addOperation(vector<NodeOperation *>& operations, NodeOperation *operation)
88 {
89         operations.push_back(operation);
90 }
91
92 void ExecutionSystemHelper::addExecutionGroup(vector<ExecutionGroup *>& executionGroups, ExecutionGroup *executionGroup)
93 {
94         executionGroups.push_back(executionGroup);
95 }
96
97 void ExecutionSystemHelper::findOutputNodeOperations(vector<NodeOperation *> *result, vector<NodeOperation *>& operations, bool rendering)
98 {
99         unsigned int index;
100
101         for (index = 0; index < operations.size(); index++) {
102                 NodeOperation *operation = operations[index];
103                 if (operation->isOutputOperation(rendering)) {
104                         result->push_back(operation);
105                 }
106         }
107 }
108
109 static InputSocket *find_input(NodeRange &node_range, bNode *bnode, bNodeSocket *bsocket)
110 {
111         if (bnode != NULL) {
112                 for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
113                         Node *node = *it;
114                         if (node->getbNode() == bnode)
115                                 return node->findInputSocketBybNodeSocket(bsocket);
116                 }
117         }
118         else {
119                 for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
120                         Node *node = *it;
121                         if (node->isProxyNode()) {
122                                 InputSocket *proxySocket = node->getInputSocket(0);
123                                 if (proxySocket->getbNodeSocket() == bsocket)
124                                         return proxySocket;
125                         }
126                 }
127         }
128         return NULL;
129 }
130 static OutputSocket *find_output(NodeRange &node_range, bNode *bnode, bNodeSocket *bsocket)
131 {
132         if (bnode != NULL) {
133                 for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
134                         Node *node = *it;
135                         if (node->getbNode() == bnode)
136                                 return node->findOutputSocketBybNodeSocket(bsocket);
137                 }
138         }
139         else {
140                 for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
141                         Node *node = *it;
142                         if (node->isProxyNode()) {
143                                 OutputSocket *proxySocket = node->getOutputSocket(0);
144                                 if (proxySocket->getbNodeSocket() == bsocket)
145                                         return proxySocket;
146                         }
147                 }
148         }
149         return NULL;
150 }
151 SocketConnection *ExecutionSystemHelper::addNodeLink(NodeRange &node_range, vector<SocketConnection *>& links, bNodeLink *b_nodelink)
152 {
153         /// @note: ignore invalid links
154         if (!(b_nodelink->flag & NODE_LINK_VALID))
155                 return NULL;
156
157         InputSocket *inputSocket = find_input(node_range, b_nodelink->tonode, b_nodelink->tosock);
158         OutputSocket *outputSocket = find_output(node_range, b_nodelink->fromnode, b_nodelink->fromsock);
159         if (inputSocket == NULL || outputSocket == NULL) {
160                 return NULL;
161         }
162         if (inputSocket->isConnected()) {
163                 return NULL;
164         }
165         SocketConnection *connection = addLink(links, outputSocket, inputSocket);
166         return connection;
167 }
168
169 SocketConnection *ExecutionSystemHelper::addLink(vector<SocketConnection *>& links, OutputSocket *fromSocket, InputSocket *toSocket)
170 {
171         SocketConnection *newconnection = new SocketConnection();
172         newconnection->setFromSocket(fromSocket);
173         newconnection->setToSocket(toSocket);
174         fromSocket->addConnection(newconnection);
175         toSocket->setConnection(newconnection);
176         links.push_back(newconnection);
177         return newconnection;
178 }
179
180 void ExecutionSystemHelper::debugDump(ExecutionSystem *system)
181 {
182         Node *node;
183         NodeOperation *operation;
184         ExecutionGroup *group;
185         SocketConnection *connection;
186         int tot, tot2;
187         printf("-- BEGIN COMPOSITOR DUMP --\r\n");
188         printf("digraph compositorexecution {\r\n");
189         tot = system->getNodes().size();
190         for (int i = 0; i < tot; i++) {
191                 node = system->getNodes()[i];
192                 printf("// NODE: %s\r\n", node->getbNode()->typeinfo->name);
193         }
194         tot = system->getOperations().size();
195         for (int i = 0; i < tot; i++) {
196                 operation = system->getOperations()[i];
197                 printf("// OPERATION: %p\r\n", operation);
198                 printf("\t\"O_%p\"", operation);
199                 printf(" [shape=record,label=\"{");
200                 tot2 = operation->getNumberOfInputSockets();
201                 if (tot2 != 0) {
202                         printf("{");
203                         for (int j = 0; j < tot2; j++) {
204                                 InputSocket *socket = operation->getInputSocket(j);
205                                 if (j != 0) {
206                                         printf("|");
207                                 }
208                                 printf("<IN_%p>", socket);
209                                 switch (socket->getDataType()) {
210                                         case COM_DT_VALUE:
211                                                 printf("Value");
212                                                 break;
213                                         case COM_DT_VECTOR:
214                                                 printf("Vector");
215                                                 break;
216                                         case COM_DT_COLOR:
217                                                 printf("Color");
218                                                 break;
219                                 }
220                         }
221                         printf("}");
222                         printf("|");
223                 }
224                 if (operation->isViewerOperation()) {
225                         ViewerBaseOperation *viewer = (ViewerBaseOperation *)operation;
226                         if (viewer->isActiveViewerOutput()) {
227                                 printf("Active viewer");
228                         }
229                         else {
230                                 printf("Viewer");
231                         }
232                 }
233                 else if (operation->isOutputOperation(system->getContext().isRendering())) {
234                         printf("Output");
235                 }
236                 else if (operation->isSetOperation()) {
237                         printf("Set");
238                 }
239                 else if (operation->isReadBufferOperation()) {
240                         printf("ReadBuffer");
241                 }
242                 else if (operation->isWriteBufferOperation()) {
243                         printf("WriteBuffer");
244                 }
245                 else {
246                         printf("O_%p", operation);
247                 }
248                 printf(" (%d,%d)", operation->getWidth(), operation->getHeight());
249                 tot2 = operation->getNumberOfOutputSockets();
250                 if (tot2 != 0) {
251                         printf("|");
252                         printf("{");
253                         for (int j = 0; j < tot2; j++) {
254                                 OutputSocket *socket = operation->getOutputSocket(j);
255                                 if (j != 0) {
256                                         printf("|");
257                                 }
258                                 printf("<OUT_%p>", socket);
259                                 switch (socket->getDataType()) {
260                                         case COM_DT_VALUE:
261                                                 printf("Value");
262                                                 break;
263                                         case COM_DT_VECTOR:
264                                                 printf("Vector");
265                                                 break;
266                                         case COM_DT_COLOR:
267                                                 printf("Color");
268                                                 break;
269                                 }
270                         }
271                         printf("}");
272                 }
273                 printf("}\"]");
274                 printf("\r\n");
275         }
276         tot = system->getExecutionGroups().size();
277         for (int i = 0; i < tot; i++) {
278                 group = system->getExecutionGroups()[i];
279                 printf("// GROUP: %d\r\n", i);
280                 printf("subgraph {\r\n");
281                 printf("//  OUTPUTOPERATION: %p\r\n", group->getOutputNodeOperation());
282                 printf(" O_%p\r\n", group->getOutputNodeOperation());
283                 printf("}\r\n");
284         }
285         tot = system->getOperations().size();
286         for (int i = 0; i < tot; i++) {
287                 operation = system->getOperations()[i];
288                 if (operation->isReadBufferOperation()) {
289                         ReadBufferOperation *read = (ReadBufferOperation *)operation;
290                         WriteBufferOperation *write = read->getMemoryProxy()->getWriteBufferOperation();
291                         printf("\t\"O_%p\" -> \"O_%p\" [style=dotted]\r\n", write, read);
292                 }
293         }
294         tot = system->getConnections().size();
295         for (int i = 0; i < tot; i++) {
296                 connection = system->getConnections()[i];
297                 printf("// CONNECTION: %p.%p -> %p.%p\r\n", connection->getFromNode(), connection->getFromSocket(), connection->getToNode(), connection->getToSocket());
298                 printf("\t\"O_%p\":\"OUT_%p\" -> \"O_%p\":\"IN_%p\"", connection->getFromNode(), connection->getFromSocket(), connection->getToNode(), connection->getToSocket());
299                 if (!connection->isValid()) {
300                         printf(" [color=red]");
301                 }
302                 else {
303                         switch (connection->getFromSocket()->getDataType()) {
304                                 case COM_DT_VALUE:
305                                         printf(" [color=grey]");
306                                         break;
307                                 case COM_DT_VECTOR:
308                                         printf(" [color=blue]");
309                                         break;
310                                 case COM_DT_COLOR:
311                                         printf(" [color=orange]");
312                                         break;
313                         }
314                 }
315                 printf("\r\n");
316         }
317         printf("}\r\n");
318         printf("-- END COMPOSITOR DUMP --\r\n");
319 }