Merged changes in the trunk up to revision 55546.
[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         virtual const bool isSetOperation() const { return false; }
203
204         /**
205          * @brief is this operation of type ReadBufferOperation
206          * @return [true:false]
207          * @see ReadBufferOperation
208          */
209         virtual const bool isReadBufferOperation() const { return false; }
210
211         /**
212          * @brief is this operation of type WriteBufferOperation
213          * @return [true:false]
214          * @see WriteBufferOperation
215          */
216         virtual const bool isWriteBufferOperation() const { return false; }
217
218         /**
219          * @brief is this operation the active viewer output
220          * user can select an ViewerNode to be active (the result of this node will be drawn on the backdrop)
221          * @return [true:false]
222          * @see BaseViewerOperation
223          */
224         virtual const bool isActiveViewerOutput() const { return false; }
225
226         virtual bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
227
228         /**
229          * @brief set the index of the input socket that will determine the resolution of this operation
230          * @param index the index to set
231          */
232         void setResolutionInputSocketIndex(unsigned int index);
233
234         /**
235          * @brief get the render priority of this node.
236          * @note only applicable for output operations like ViewerOperation
237          * @return CompositorPriority
238          */
239         virtual const CompositorPriority getRenderPriority() const { return COM_PRIORITY_LOW; }
240
241         /**
242          * @brief can this NodeOperation be scheduled on an OpenCLDevice
243          * @see WorkScheduler.schedule
244          * @see ExecutionGroup.addOperation
245          */
246         bool isOpenCL() { return this->m_openCL; }
247         
248         virtual bool isViewerOperation() { return false; }
249         virtual bool isPreviewOperation() { return false; }
250         
251         inline bool isBreaked() {
252                 return this->m_btree->test_break(this->m_btree->tbh);
253         }
254
255         inline void updateDraw() {
256                 if (this->m_btree->update_draw)
257                         this->m_btree->update_draw(this->m_btree->udh);
258         }
259 protected:
260         NodeOperation();
261
262         void setWidth(unsigned int width) { this->m_width = width; this->m_isResolutionSet = true; }
263         void setHeight(unsigned int height) { this->m_height = height; this->m_isResolutionSet = true; }
264         SocketReader *getInputSocketReader(unsigned int inputSocketindex);
265         NodeOperation *getInputOperation(unsigned int inputSocketindex);
266
267         void deinitMutex();
268         void initMutex();
269         void lockMutex();
270         void unlockMutex();
271         
272
273         /**
274          * @brief set whether this operation is complex
275          *
276          * Complex operations are typically doing many reads to calculate the output of a single pixel.
277          * Mostly Filter types (Blurs, Convolution, Defocus etc) need this to be set to true.
278          */
279         void setComplex(bool complex) { this->m_complex = complex; }
280
281         /**
282          * @brief set if this NodeOperation can be scheduled on a OpenCLDevice
283          */
284         void setOpenCL(bool openCL) { this->m_openCL = openCL; }
285
286 #ifdef WITH_CXX_GUARDEDALLOC
287         MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
288 #endif
289 };
290
291 #endif