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