Fix for #34739 and #35060, avoid ambiguity in compositor viewer nodes.
[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
30 #include "COM_Converter.h"
31 #include "COM_NodeOperation.h"
32 #include "COM_ExecutionGroup.h"
33 #include "COM_NodeBase.h"
34 #include "COM_WorkScheduler.h"
35 #include "COM_ReadBufferOperation.h"
36 #include "COM_GroupNode.h"
37 #include "COM_WriteBufferOperation.h"
38 #include "COM_ReadBufferOperation.h"
39 #include "COM_ViewerBaseOperation.h"
40
41 extern "C" {
42 #include "BKE_node.h"
43 }
44
45 void ExecutionSystemHelper::addbNodeTree(ExecutionSystem &system, int nodes_start, bNodeTree *tree, bNodeInstanceKey parent_key)
46 {
47         vector<Node *>& nodes = system.getNodes();
48         vector<SocketConnection *>& links = system.getConnections();
49         
50         bool is_active_group = (parent_key.value == system.getContext().getbNodeTree()->active_viewer_key.value);
51         
52         /* add all nodes of the tree to the node list */
53         bNode *node = (bNode *)tree->nodes.first;
54         while (node != NULL) {
55                 Node *nnode = addNode(nodes, node, is_active_group, system.getContext().isFastCalculation());
56                 if (nnode) {
57                         nnode->setbNodeTree(tree);
58                         nnode->setInstanceKey(BKE_node_instance_key(parent_key, tree, node));
59                 }
60                 node = node->next;
61         }
62
63         NodeRange node_range(nodes.begin() + nodes_start, nodes.end());
64
65         /* add all nodelinks of the tree to the link list */
66         bNodeLink *nodelink = (bNodeLink *)tree->links.first;
67         while (nodelink != NULL) {
68                 addNodeLink(node_range, links, nodelink);
69                 nodelink = nodelink->next;
70         }
71
72         /* Expand group nodes
73          * Only go up to nodes_end, to avoid ungrouping nested node groups repeatedly.
74          */
75         int nodes_end = nodes.size();
76         for (unsigned int i = nodes_start; i < nodes_end; ++i) {
77                 Node *execnode = nodes[i];
78                 if (execnode->isGroupNode()) {
79                         GroupNode *groupNode = (GroupNode *)execnode;
80                         groupNode->ungroup(system);
81                 }
82         }
83 }
84
85 void ExecutionSystemHelper::addNode(vector<Node *>& nodes, Node *node)
86 {
87         nodes.push_back(node);
88 }
89
90 Node *ExecutionSystemHelper::addNode(vector<Node *>& nodes, bNode *b_node, bool inActiveGroup, bool fast)
91 {
92         Node *node = Converter::convert(b_node, fast);
93         if (node) {
94                 node->setIsInActiveGroup(inActiveGroup);
95                 addNode(nodes, node);
96         }
97         return node;
98 }
99 void ExecutionSystemHelper::addOperation(vector<NodeOperation *>& operations, NodeOperation *operation)
100 {
101         operations.push_back(operation);
102 }
103
104 void ExecutionSystemHelper::addExecutionGroup(vector<ExecutionGroup *>& executionGroups, ExecutionGroup *executionGroup)
105 {
106         executionGroups.push_back(executionGroup);
107 }
108
109 void ExecutionSystemHelper::findOutputNodeOperations(vector<NodeOperation *> *result, vector<NodeOperation *>& operations, bool rendering)
110 {
111         unsigned int index;
112
113         for (index = 0; index < operations.size(); index++) {
114                 NodeOperation *operation = operations[index];
115                 if (operation->isOutputOperation(rendering)) {
116                         result->push_back(operation);
117                 }
118         }
119 }
120
121 static InputSocket *find_input(NodeRange &node_range, bNode *bnode, bNodeSocket *bsocket)
122 {
123         for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
124                 Node *node = *it;
125                 InputSocket *input = node->findInputSocketBybNodeSocket(bsocket);
126                 if (input)
127                         return input;
128         }
129         return NULL;
130 }
131 static OutputSocket *find_output(NodeRange &node_range, bNode *bnode, bNodeSocket *bsocket)
132 {
133         for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
134                 Node *node = *it;
135                 OutputSocket *output = node->findOutputSocketBybNodeSocket(bsocket);
136                 if (output)
137                         return output;
138         }
139         return NULL;
140 }
141 SocketConnection *ExecutionSystemHelper::addNodeLink(NodeRange &node_range, vector<SocketConnection *>& links, bNodeLink *b_nodelink)
142 {
143         /// @note: ignore invalid links
144         if (!(b_nodelink->flag & NODE_LINK_VALID))
145                 return NULL;
146
147         InputSocket *inputSocket = find_input(node_range, b_nodelink->tonode, b_nodelink->tosock);
148         OutputSocket *outputSocket = find_output(node_range, b_nodelink->fromnode, b_nodelink->fromsock);
149         if (inputSocket == NULL || outputSocket == NULL) {
150                 return NULL;
151         }
152         if (inputSocket->isConnected()) {
153                 return NULL;
154         }
155         SocketConnection *connection = addLink(links, outputSocket, inputSocket);
156         return connection;
157 }
158
159 SocketConnection *ExecutionSystemHelper::addLink(vector<SocketConnection *>& links, OutputSocket *fromSocket, InputSocket *toSocket)
160 {
161         SocketConnection *newconnection = new SocketConnection();
162         newconnection->setFromSocket(fromSocket);
163         newconnection->setToSocket(toSocket);
164         fromSocket->addConnection(newconnection);
165         toSocket->setConnection(newconnection);
166         links.push_back(newconnection);
167         return newconnection;
168 }
169
170 void ExecutionSystemHelper::debugDump(ExecutionSystem *system)
171 {
172         Node *node;
173         NodeOperation *operation;
174         ExecutionGroup *group;
175         SocketConnection *connection;
176         int tot, tot2;
177         printf("-- BEGIN COMPOSITOR DUMP --\r\n");
178         printf("digraph compositorexecution {\r\n");
179         tot = system->getNodes().size();
180         for (int i = 0; i < tot; i++) {
181                 node = system->getNodes()[i];
182                 printf("// NODE: %s\r\n", node->getbNode()->typeinfo->ui_name);
183         }
184         tot = system->getOperations().size();
185         for (int i = 0; i < tot; i++) {
186                 operation = system->getOperations()[i];
187                 printf("// OPERATION: %p\r\n", operation);
188                 printf("\t\"O_%p\"", operation);
189                 printf(" [shape=record,label=\"{");
190                 tot2 = operation->getNumberOfInputSockets();
191                 if (tot2 != 0) {
192                         printf("{");
193                         for (int j = 0; j < tot2; j++) {
194                                 InputSocket *socket = operation->getInputSocket(j);
195                                 if (j != 0) {
196                                         printf("|");
197                                 }
198                                 printf("<IN_%p>", socket);
199                                 switch (socket->getDataType()) {
200                                         case COM_DT_VALUE:
201                                                 printf("Value");
202                                                 break;
203                                         case COM_DT_VECTOR:
204                                                 printf("Vector");
205                                                 break;
206                                         case COM_DT_COLOR:
207                                                 printf("Color");
208                                                 break;
209                                 }
210                         }
211                         printf("}");
212                         printf("|");
213                 }
214                 if (operation->isViewerOperation()) {
215                         ViewerBaseOperation *viewer = (ViewerBaseOperation *)operation;
216                         if (viewer->isActiveViewerOutput()) {
217                                 printf("Active viewer");
218                         }
219                         else {
220                                 printf("Viewer");
221                         }
222                 }
223                 else if (operation->isOutputOperation(system->getContext().isRendering())) {
224                         printf("Output");
225                 }
226                 else if (operation->isSetOperation()) {
227                         printf("Set");
228                 }
229                 else if (operation->isReadBufferOperation()) {
230                         printf("ReadBuffer");
231                 }
232                 else if (operation->isWriteBufferOperation()) {
233                         printf("WriteBuffer");
234                 }
235                 else {
236                         printf("O_%p", operation);
237                 }
238                 printf(" (%d,%d)", operation->getWidth(), operation->getHeight());
239                 tot2 = operation->getNumberOfOutputSockets();
240                 if (tot2 != 0) {
241                         printf("|");
242                         printf("{");
243                         for (int j = 0; j < tot2; j++) {
244                                 OutputSocket *socket = operation->getOutputSocket(j);
245                                 if (j != 0) {
246                                         printf("|");
247                                 }
248                                 printf("<OUT_%p>", socket);
249                                 switch (socket->getDataType()) {
250                                         case COM_DT_VALUE:
251                                                 printf("Value");
252                                                 break;
253                                         case COM_DT_VECTOR:
254                                                 printf("Vector");
255                                                 break;
256                                         case COM_DT_COLOR:
257                                                 printf("Color");
258                                                 break;
259                                 }
260                         }
261                         printf("}");
262                 }
263                 printf("}\"]");
264                 printf("\r\n");
265         }
266         tot = system->getExecutionGroups().size();
267         for (int i = 0; i < tot; i++) {
268                 group = system->getExecutionGroups()[i];
269                 printf("// GROUP: %d\r\n", i);
270                 printf("subgraph {\r\n");
271                 printf("//  OUTPUTOPERATION: %p\r\n", group->getOutputNodeOperation());
272                 printf(" O_%p\r\n", group->getOutputNodeOperation());
273                 printf("}\r\n");
274         }
275         tot = system->getOperations().size();
276         for (int i = 0; i < tot; i++) {
277                 operation = system->getOperations()[i];
278                 if (operation->isReadBufferOperation()) {
279                         ReadBufferOperation *read = (ReadBufferOperation *)operation;
280                         WriteBufferOperation *write = read->getMemoryProxy()->getWriteBufferOperation();
281                         printf("\t\"O_%p\" -> \"O_%p\" [style=dotted]\r\n", write, read);
282                 }
283         }
284         tot = system->getConnections().size();
285         for (int i = 0; i < tot; i++) {
286                 connection = system->getConnections()[i];
287                 printf("// CONNECTION: %p.%p -> %p.%p\r\n", connection->getFromNode(), connection->getFromSocket(), connection->getToNode(), connection->getToSocket());
288                 printf("\t\"O_%p\":\"OUT_%p\" -> \"O_%p\":\"IN_%p\"", connection->getFromNode(), connection->getFromSocket(), connection->getToNode(), connection->getToSocket());
289                 if (!connection->isValid()) {
290                         printf(" [color=red]");
291                 }
292                 else {
293                         switch (connection->getFromSocket()->getDataType()) {
294                                 case COM_DT_VALUE:
295                                         printf(" [color=grey]");
296                                         break;
297                                 case COM_DT_VECTOR:
298                                         printf(" [color=blue]");
299                                         break;
300                                 case COM_DT_COLOR:
301                                         printf(" [color=orange]");
302                                         break;
303                         }
304                 }
305                 printf("\r\n");
306         }
307         printf("}\r\n");
308         printf("-- END COMPOSITOR DUMP --\r\n");
309 }