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