Cleanup and improvements of the compositor debug output.
[blender.git] / source / blender / compositor / intern / COM_NodeOperation.h
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 #ifndef _COM_NodeOperation_h
24 #define _COM_NodeOperation_h
25 class OpenCLDevice;
26 #include "COM_Node.h"
27 #include <string>
28 #include <sstream>
29 #include "COM_MemoryBuffer.h"
30 #include "COM_MemoryProxy.h"
31 #include "COM_SocketReader.h"
32 #include "OCL_opencl.h"
33 #include "list"
34 #include "BLI_threads.h"
35
36 #include "BLI_math_color.h"
37 #include "BLI_math_vector.h"
38
39 class ReadBufferOperation;
40
41 /**
42  * @brief NodeOperation are contains calculation logic
43  *
44  * Subclasses needs to implement the execution method (defined in SocketReader) to implement logic.
45  * @ingroup Model
46  */
47 class NodeOperation : public NodeBase, public SocketReader {
48 private:
49         /**
50          * @brief the index of the input socket that will be used to determine the resolution
51          */
52         unsigned int m_resolutionInputSocketIndex;
53
54         /**
55          * @brief is this operation a complex one.
56          *
57          * Complex operations are typically doing many reads to calculate the output of a single pixel.
58          * Mostly Filter types (Blurs, Convolution, Defocus etc) need this to be set to true.
59          */
60         bool m_complex;
61
62         /**
63          * @brief can this operation be scheduled on an OpenCL device.
64          * @note Only applicable if complex is True
65          */
66         bool m_openCL;
67
68         /**
69          * @brief mutex reference for very special node initializations
70          * @note only use when you really know what you are doing.
71          * this mutex is used to share data among chunks in the same operation
72          * @see TonemapOperation for an example of usage
73          * @see NodeOperation.initMutex initializes this mutex
74          * @see NodeOperation.deinitMutex deinitializes this mutex
75          * @see NodeOperation.getMutex retrieve a pointer to this mutex.
76          */
77         ThreadMutex m_mutex;
78         
79         /**
80          * @brief reference to the editing bNodeTree, used for break and update callback
81          */
82         const bNodeTree *m_btree;
83
84         /**
85          * @brief set to truth when resolution for this operation is set
86          */
87         bool m_isResolutionSet;
88 public:
89         /**
90          * @brief is this node an operation?
91          * This is true when the instance is of the subclass NodeOperation.
92          * @return [true:false]
93          * @see NodeBase
94          */
95         const bool isOperation() const { return true; }
96
97         /**
98          * @brief determine the resolution of this node
99          * @note this method will not set the resolution, this is the responsibility of the caller
100          * @param resolution the result of this operation
101          * @param preferredResolution the preferable resolution as no resolution could be determined
102          */
103         virtual void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
104
105         /**
106          * @brief isOutputOperation determines whether this operation is an output of the ExecutionSystem during rendering or editing.
107          *
108          * Default behaviour if not overridden, this operation will not be evaluated as being an output of the ExecutionSystem.
109          *
110          * @see ExecutionSystem
111          * @group check
112          * @param rendering [true false]
113          *  true: rendering
114          *  false: editing
115          *
116          * @return bool the result of this method
117          */
118         virtual bool isOutputOperation(bool rendering) const { return false; }
119
120         /**
121          * isBufferOperation returns if this is an operation that work directly on buffers.
122          *
123          * there are only 2 implementation where this is true:
124          * @see ReadBufferOperation
125          * @see WriteBufferOperation
126          * for all other operations this will result in false.
127          */
128         virtual int isBufferOperation() { return false; }
129         virtual int isSingleThreaded() { return false; }
130
131         void setbNodeTree(const bNodeTree *tree) { this->m_btree = tree; }
132         virtual void initExecution();
133         
134         /**
135          * @brief when a chunk is executed by a CPUDevice, this method is called
136          * @ingroup execution
137          * @param rect the rectangle of the chunk (location and size)
138          * @param chunkNumber the chunkNumber to be calculated
139          * @param memoryBuffers all input MemoryBuffer's needed
140          */
141         virtual void executeRegion(rcti *rect, unsigned int chunkNumber) {}
142
143         /**
144          * @brief when a chunk is executed by an OpenCLDevice, this method is called
145          * @ingroup execution
146          * @note this method is only implemented in WriteBufferOperation
147          * @param context the OpenCL context
148          * @param program the OpenCL program containing all compositor kernels
149          * @param queue the OpenCL command queue of the device the chunk is executed on
150          * @param rect the rectangle of the chunk (location and size)
151          * @param chunkNumber the chunkNumber to be calculated
152          * @param memoryBuffers all input MemoryBuffer's needed
153          * @param outputBuffer the outputbuffer to write to
154          */
155         virtual void executeOpenCLRegion(OpenCLDevice *device, rcti *rect,
156                                          unsigned int chunkNumber, MemoryBuffer **memoryBuffers, MemoryBuffer *outputBuffer) {}
157
158         /**
159          * @brief custom handle to add new tasks to the OpenCL command queue in order to execute a chunk on an GPUDevice
160          * @ingroup execution
161          * @param context the OpenCL context
162          * @param program the OpenCL program containing all compositor kernels
163          * @param queue the OpenCL command queue of the device the chunk is executed on
164          * @param outputMemoryBuffer the allocated memory buffer in main CPU memory
165          * @param clOutputBuffer the allocated memory buffer in OpenCLDevice memory
166          * @param inputMemoryBuffers all input MemoryBuffer's needed
167          * @param clMemToCleanUp all created cl_mem references must be added to this list. Framework will clean this after execution
168          * @param clKernelsToCleanUp all created cl_kernel references must be added to this list. Framework will clean this after execution
169          */
170         virtual void executeOpenCL(OpenCLDevice *device,
171                                    MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer,
172                                    MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp,
173                                    list<cl_kernel> *clKernelsToCleanUp) {}
174         virtual void deinitExecution();
175
176         bool isResolutionSet() {
177                 return this->m_isResolutionSet;
178         }
179
180         /**
181          * @brief set the resolution
182          * @param resolution the resolution to set
183          */
184         void setResolution(unsigned int resolution[2]) {
185                 if (!isResolutionSet()) {
186                         this->m_width = resolution[0];
187                         this->m_height = resolution[1];
188                         this->m_isResolutionSet = true;
189                 }
190         }
191         
192
193         void getConnectedInputSockets(vector<InputSocket *> *sockets);
194
195         /**
196          * @brief is this operation complex
197          *
198          * Complex operations are typically doing many reads to calculate the output of a single pixel.
199          * Mostly Filter types (Blurs, Convolution, Defocus etc) need this to be set to true.
200          */
201         const bool isComplex() const { return this->m_complex; }
202
203         virtual bool isSetOperation() const { return false; }
204
205         /**
206          * @brief is this operation of type ReadBufferOperation
207          * @return [true:false]
208          * @see ReadBufferOperation
209          */
210         virtual const bool isReadBufferOperation() const { return false; }
211
212         /**
213          * @brief is this operation of type WriteBufferOperation
214          * @return [true:false]
215          * @see WriteBufferOperation
216          */
217         virtual const bool isWriteBufferOperation() const { return false; }
218
219         /**
220          * @brief is this operation the active viewer output
221          * user can select an ViewerNode to be active (the result of this node will be drawn on the backdrop)
222          * @return [true:false]
223          * @see BaseViewerOperation
224          */
225         virtual const bool isActiveViewerOutput() const { return false; }
226
227         virtual bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
228
229         /**
230          * @brief set the index of the input socket that will determine the resolution of this operation
231          * @param index the index to set
232          */
233         void setResolutionInputSocketIndex(unsigned int index);
234
235         /**
236          * @brief get the render priority of this node.
237          * @note only applicable for output operations like ViewerOperation
238          * @return CompositorPriority
239          */
240         virtual const CompositorPriority getRenderPriority() const { return COM_PRIORITY_LOW; }
241
242         /**
243          * @brief can this NodeOperation be scheduled on an OpenCLDevice
244          * @see WorkScheduler.schedule
245          * @see ExecutionGroup.addOperation
246          */
247         bool isOpenCL() { return this->m_openCL; }
248         
249         virtual bool isViewerOperation() { return false; }
250         virtual bool isPreviewOperation() { return false; }
251         virtual bool isFileOutputOperation() { return false; }
252         
253         inline bool isBreaked() {
254                 return this->m_btree->test_break(this->m_btree->tbh);
255         }
256
257         inline void updateDraw() {
258                 if (this->m_btree->update_draw)
259                         this->m_btree->update_draw(this->m_btree->udh);
260         }
261 protected:
262         NodeOperation();
263
264         void setWidth(unsigned int width) { this->m_width = width; this->m_isResolutionSet = true; }
265         void setHeight(unsigned int height) { this->m_height = height; this->m_isResolutionSet = true; }
266         SocketReader *getInputSocketReader(unsigned int inputSocketindex);
267         NodeOperation *getInputOperation(unsigned int inputSocketindex);
268
269         void deinitMutex();
270         void initMutex();
271         void lockMutex();
272         void unlockMutex();
273         
274
275         /**
276          * @brief set whether this operation is complex
277          *
278          * Complex operations are typically doing many reads to calculate the output of a single pixel.
279          * Mostly Filter types (Blurs, Convolution, Defocus etc) need this to be set to true.
280          */
281         void setComplex(bool complex) { this->m_complex = complex; }
282
283         /**
284          * @brief set if this NodeOperation can be scheduled on a OpenCLDevice
285          */
286         void setOpenCL(bool openCL) { this->m_openCL = openCL; }
287
288 #ifdef WITH_CXX_GUARDEDALLOC
289         MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
290 #endif
291 };
292
293 #endif