Merging r51923 through r52851 from trunk into soc-2011-tomato
[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 public:
85         /**
86          * @brief is this node an operation?
87          * This is true when the instance is of the subclass NodeOperation.
88          * @return [true:false]
89          * @see NodeBase
90          */
91         const bool isOperation() const { return true; }
92
93         /**
94          * @brief determine the resolution of this node
95          * @note this method will not set the resolution, this is the responsibility of the caller
96          * @param resolution the result of this operation
97          * @param preferredResolution the preferable resolution as no resolution could be determined
98          */
99         virtual void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
100
101         /**
102          * @brief isOutputOperation determines whether this operation is an output of the ExecutionSystem during rendering or editing.
103          *
104          * Default behaviour if not overridden, this operation will not be evaluated as being an output of the ExecutionSystem.
105          *
106          * @see ExecutionSystem
107          * @group check
108          * @param rendering [true false]
109          *  true: rendering
110          *  false: editing
111          *
112          * @return bool the result of this method
113          */
114         virtual bool isOutputOperation(bool rendering) const { return false; }
115
116         /**
117          * isBufferOperation returns if this is an operation that work directly on buffers.
118          *
119          * there are only 2 implementation where this is true:
120          * @see ReadBufferOperation
121          * @see WriteBufferOperation
122          * for all other operations this will result in false.
123          */
124         virtual int isBufferOperation() { return false; }
125         virtual int isSingleThreaded() { return false; }
126
127         void setbNodeTree(const bNodeTree *tree) { this->m_btree = tree; }
128         virtual void initExecution();
129         
130         /**
131          * @brief when a chunk is executed by a CPUDevice, this method is called
132          * @ingroup execution
133          * @param rect the rectangle of the chunk (location and size)
134          * @param chunkNumber the chunkNumber to be calculated
135          * @param memoryBuffers all input MemoryBuffer's needed
136          */
137         virtual void executeRegion(rcti *rect, unsigned int chunkNumber) {}
138
139         /**
140          * @brief when a chunk is executed by an OpenCLDevice, this method is called
141          * @ingroup execution
142          * @note this method is only implemented in WriteBufferOperation
143          * @param context the OpenCL context
144          * @param program the OpenCL program containing all compositor kernels
145          * @param queue the OpenCL command queue of the device the chunk is executed on
146          * @param rect the rectangle of the chunk (location and size)
147          * @param chunkNumber the chunkNumber to be calculated
148          * @param memoryBuffers all input MemoryBuffer's needed
149          * @param outputBuffer the outputbuffer to write to
150          */
151         virtual void executeOpenCLRegion(OpenCLDevice *device, rcti *rect,
152                                          unsigned int chunkNumber, MemoryBuffer **memoryBuffers, MemoryBuffer *outputBuffer) {}
153
154         /**
155          * @brief custom handle to add new tasks to the OpenCL command queue in order to execute a chunk on an GPUDevice
156          * @ingroup execution
157          * @param context the OpenCL context
158          * @param program the OpenCL program containing all compositor kernels
159          * @param queue the OpenCL command queue of the device the chunk is executed on
160          * @param outputMemoryBuffer the allocated memory buffer in main CPU memory
161          * @param clOutputBuffer the allocated memory buffer in OpenCLDevice memory
162          * @param inputMemoryBuffers all input MemoryBuffer's needed
163          * @param clMemToCleanUp all created cl_mem references must be added to this list. Framework will clean this after execution
164          * @param clKernelsToCleanUp all created cl_kernel references must be added to this list. Framework will clean this after execution
165          */
166         virtual void executeOpenCL(OpenCLDevice *device,
167                                    MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer,
168                                    MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp,
169                                    list<cl_kernel> *clKernelsToCleanUp) {}
170         virtual void deinitExecution();
171
172         bool isResolutionSet() {
173                 return this->m_width != 0 && this->m_height != 0;
174         }
175
176         /**
177          * @brief set the resolution
178          * @param resolution the resolution to set
179          */
180         void setResolution(unsigned int resolution[2]) {
181                 if (!isResolutionSet()) {
182                         this->m_width = resolution[0];
183                         this->m_height = resolution[1];
184                 }
185         }
186         
187
188         void getConnectedInputSockets(vector<InputSocket *> *sockets);
189
190         /**
191          * @brief is this operation complex
192          *
193          * Complex operations are typically doing many reads to calculate the output of a single pixel.
194          * Mostly Filter types (Blurs, Convolution, Defocus etc) need this to be set to true.
195          */
196         const bool isComplex() const { return this->m_complex; }
197         virtual const bool isSetOperation() const { return false; }
198
199         /**
200          * @brief is this operation of type ReadBufferOperation
201          * @return [true:false]
202          * @see ReadBufferOperation
203          */
204         virtual const bool isReadBufferOperation() const { return false; }
205
206         /**
207          * @brief is this operation of type WriteBufferOperation
208          * @return [true:false]
209          * @see WriteBufferOperation
210          */
211         virtual const bool isWriteBufferOperation() const { return false; }
212
213         /**
214          * @brief is this operation the active viewer output
215          * user can select an ViewerNode to be active (the result of this node will be drawn on the backdrop)
216          * @return [true:false]
217          * @see BaseViewerOperation
218          */
219         virtual const bool isActiveViewerOutput() const { return false; }
220
221         virtual bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
222
223         /**
224          * @brief set the index of the input socket that will determine the resolution of this operation
225          * @param index the index to set
226          */
227         void setResolutionInputSocketIndex(unsigned int index);
228
229         /**
230          * @brief get the render priority of this node.
231          * @note only applicable for output operations like ViewerOperation
232          * @return CompositorPriority
233          */
234         virtual const CompositorPriority getRenderPriority() const { return COM_PRIORITY_LOW; }
235
236         /**
237          * @brief can this NodeOperation be scheduled on an OpenCLDevice
238          * @see WorkScheduler.schedule
239          * @see ExecutionGroup.addOperation
240          */
241         bool isOpenCL() { return this->m_openCL; }
242         
243         virtual bool isViewerOperation() { return false; }
244         virtual bool isPreviewOperation() { return false; }
245         
246         inline bool isBreaked() {
247                 return this->m_btree->test_break(this->m_btree->tbh);
248         }
249
250         inline void updateDraw() {
251                 if (this->m_btree->update_draw)
252                         this->m_btree->update_draw(this->m_btree->udh);
253         }
254 protected:
255         NodeOperation();
256
257         void setWidth(unsigned int width) { this->m_width = width; }
258         void setHeight(unsigned int height) { this->m_height = height; }
259         SocketReader *getInputSocketReader(unsigned int inputSocketindex);
260         NodeOperation *getInputOperation(unsigned int inputSocketindex);
261
262         void deinitMutex();
263         void initMutex();
264         void lockMutex();
265         void unlockMutex();
266         
267
268         /**
269          * @brief set whether this operation is complex
270          *
271          * Complex operations are typically doing many reads to calculate the output of a single pixel.
272          * Mostly Filter types (Blurs, Convolution, Defocus etc) need this to be set to true.
273          */
274         void setComplex(bool complex) { this->m_complex = complex; }
275
276         /**
277          * @brief set if this NodeOperation can be scheduled on a OpenCLDevice
278          */
279         void setOpenCL(bool openCL) { this->m_openCL = openCL; }
280
281 #ifdef WITH_CXX_GUARDEDALLOC
282         MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
283 #endif
284 };
285
286 #endif