Fix/Cleanup: I18N: Bad usage of IFACE_ instead of TIP_.
[blender.git] / source / blender / compositor / intern / COM_ExecutionSystem.cpp
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 2011, Blender Foundation.
17  */
18
19 #include "COM_ExecutionSystem.h"
20
21 #include "PIL_time.h"
22 #include "BLI_utildefines.h"
23 extern "C" {
24 #include "BKE_node.h"
25 }
26
27 #include "BLT_translation.h"
28
29 #include "COM_Converter.h"
30 #include "COM_NodeOperationBuilder.h"
31 #include "COM_NodeOperation.h"
32 #include "COM_ExecutionGroup.h"
33 #include "COM_WorkScheduler.h"
34 #include "COM_ReadBufferOperation.h"
35 #include "COM_Debug.h"
36
37 #ifdef WITH_CXX_GUARDEDALLOC
38 #  include "MEM_guardedalloc.h"
39 #endif
40
41 ExecutionSystem::ExecutionSystem(RenderData *rd,
42                                  Scene *scene,
43                                  bNodeTree *editingtree,
44                                  bool rendering,
45                                  bool fastcalculation,
46                                  const ColorManagedViewSettings *viewSettings,
47                                  const ColorManagedDisplaySettings *displaySettings,
48                                  const char *viewName)
49 {
50   this->m_context.setViewName(viewName);
51   this->m_context.setScene(scene);
52   this->m_context.setbNodeTree(editingtree);
53   this->m_context.setPreviewHash(editingtree->previews);
54   this->m_context.setFastCalculation(fastcalculation);
55   /* initialize the CompositorContext */
56   if (rendering) {
57     this->m_context.setQuality((CompositorQuality)editingtree->render_quality);
58   }
59   else {
60     this->m_context.setQuality((CompositorQuality)editingtree->edit_quality);
61   }
62   this->m_context.setRendering(rendering);
63   this->m_context.setHasActiveOpenCLDevices(WorkScheduler::hasGPUDevices() &&
64                                             (editingtree->flag & NTREE_COM_OPENCL));
65
66   this->m_context.setRenderData(rd);
67   this->m_context.setViewSettings(viewSettings);
68   this->m_context.setDisplaySettings(displaySettings);
69
70   {
71     NodeOperationBuilder builder(&m_context, editingtree);
72     builder.convertToOperations(this);
73   }
74
75   unsigned int index;
76   unsigned int resolution[2];
77
78   rctf *viewer_border = &editingtree->viewer_border;
79   bool use_viewer_border = (editingtree->flag & NTREE_VIEWER_BORDER) &&
80                            viewer_border->xmin < viewer_border->xmax &&
81                            viewer_border->ymin < viewer_border->ymax;
82
83   editingtree->stats_draw(editingtree->sdh, TIP_("Compositing | Determining resolution"));
84
85   for (index = 0; index < this->m_groups.size(); index++) {
86     resolution[0] = 0;
87     resolution[1] = 0;
88     ExecutionGroup *executionGroup = this->m_groups[index];
89     executionGroup->determineResolution(resolution);
90
91     if (rendering) {
92       /* case when cropping to render border happens is handled in
93        * compositor output and render layer nodes
94        */
95       if ((rd->mode & R_BORDER) && !(rd->mode & R_CROP)) {
96         executionGroup->setRenderBorder(
97             rd->border.xmin, rd->border.xmax, rd->border.ymin, rd->border.ymax);
98       }
99     }
100
101     if (use_viewer_border) {
102       executionGroup->setViewerBorder(
103           viewer_border->xmin, viewer_border->xmax, viewer_border->ymin, viewer_border->ymax);
104     }
105   }
106
107   //  DebugInfo::graphviz(this);
108 }
109
110 ExecutionSystem::~ExecutionSystem()
111 {
112   unsigned int index;
113   for (index = 0; index < this->m_operations.size(); index++) {
114     NodeOperation *operation = this->m_operations[index];
115     delete operation;
116   }
117   this->m_operations.clear();
118   for (index = 0; index < this->m_groups.size(); index++) {
119     ExecutionGroup *group = this->m_groups[index];
120     delete group;
121   }
122   this->m_groups.clear();
123 }
124
125 void ExecutionSystem::set_operations(const Operations &operations, const Groups &groups)
126 {
127   m_operations = operations;
128   m_groups = groups;
129 }
130
131 void ExecutionSystem::execute()
132 {
133   const bNodeTree *editingtree = this->m_context.getbNodeTree();
134   editingtree->stats_draw(editingtree->sdh, TIP_("Compositing | Initializing execution"));
135
136   DebugInfo::execute_started(this);
137
138   unsigned int order = 0;
139   for (vector<NodeOperation *>::iterator iter = this->m_operations.begin();
140        iter != this->m_operations.end();
141        ++iter) {
142     NodeOperation *operation = *iter;
143     if (operation->isReadBufferOperation()) {
144       ReadBufferOperation *readOperation = (ReadBufferOperation *)operation;
145       readOperation->setOffset(order);
146       order++;
147     }
148   }
149   unsigned int index;
150
151   // First allocale all write buffer
152   for (index = 0; index < this->m_operations.size(); index++) {
153     NodeOperation *operation = this->m_operations[index];
154     if (operation->isWriteBufferOperation()) {
155       operation->setbNodeTree(this->m_context.getbNodeTree());
156       operation->initExecution();
157     }
158   }
159   // Connect read buffers to their write buffers
160   for (index = 0; index < this->m_operations.size(); index++) {
161     NodeOperation *operation = this->m_operations[index];
162     if (operation->isReadBufferOperation()) {
163       ReadBufferOperation *readOperation = (ReadBufferOperation *)operation;
164       readOperation->updateMemoryBuffer();
165     }
166   }
167   // initialize other operations
168   for (index = 0; index < this->m_operations.size(); index++) {
169     NodeOperation *operation = this->m_operations[index];
170     if (!operation->isWriteBufferOperation()) {
171       operation->setbNodeTree(this->m_context.getbNodeTree());
172       operation->initExecution();
173     }
174   }
175   for (index = 0; index < this->m_groups.size(); index++) {
176     ExecutionGroup *executionGroup = this->m_groups[index];
177     executionGroup->setChunksize(this->m_context.getChunksize());
178     executionGroup->initExecution();
179   }
180
181   WorkScheduler::start(this->m_context);
182
183   executeGroups(COM_PRIORITY_HIGH);
184   if (!this->getContext().isFastCalculation()) {
185     executeGroups(COM_PRIORITY_MEDIUM);
186     executeGroups(COM_PRIORITY_LOW);
187   }
188
189   WorkScheduler::finish();
190   WorkScheduler::stop();
191
192   editingtree->stats_draw(editingtree->sdh, TIP_("Compositing | De-initializing execution"));
193   for (index = 0; index < this->m_operations.size(); index++) {
194     NodeOperation *operation = this->m_operations[index];
195     operation->deinitExecution();
196   }
197   for (index = 0; index < this->m_groups.size(); index++) {
198     ExecutionGroup *executionGroup = this->m_groups[index];
199     executionGroup->deinitExecution();
200   }
201 }
202
203 void ExecutionSystem::executeGroups(CompositorPriority priority)
204 {
205   unsigned int index;
206   vector<ExecutionGroup *> executionGroups;
207   this->findOutputExecutionGroup(&executionGroups, priority);
208
209   for (index = 0; index < executionGroups.size(); index++) {
210     ExecutionGroup *group = executionGroups[index];
211     group->execute(this);
212   }
213 }
214
215 void ExecutionSystem::findOutputExecutionGroup(vector<ExecutionGroup *> *result,
216                                                CompositorPriority priority) const
217 {
218   unsigned int index;
219   for (index = 0; index < this->m_groups.size(); index++) {
220     ExecutionGroup *group = this->m_groups[index];
221     if (group->isOutputExecutionGroup() && group->getRenderPriotrity() == priority) {
222       result->push_back(group);
223     }
224   }
225 }
226
227 void ExecutionSystem::findOutputExecutionGroup(vector<ExecutionGroup *> *result) const
228 {
229   unsigned int index;
230   for (index = 0; index < this->m_groups.size(); index++) {
231     ExecutionGroup *group = this->m_groups[index];
232     if (group->isOutputExecutionGroup()) {
233       result->push_back(group);
234     }
235   }
236 }