CD_PROP_COL datalayer
[blender.git] / source / blender / compositor / intern / COM_NodeOperation.h
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 2011, Blender Foundation.
17  */
18
19 #ifndef __COM_NODEOPERATION_H__
20 #define __COM_NODEOPERATION_H__
21
22 #include <list>
23 #include <sstream>
24 #include <string>
25
26 #include "BLI_math_color.h"
27 #include "BLI_math_vector.h"
28 #include "BLI_threads.h"
29
30 #include "COM_MemoryBuffer.h"
31 #include "COM_MemoryProxy.h"
32 #include "COM_Node.h"
33 #include "COM_SocketReader.h"
34
35 #include "clew.h"
36
37 using std::list;
38 using std::max;
39 using std::min;
40
41 class OpenCLDevice;
42 class ReadBufferOperation;
43 class WriteBufferOperation;
44
45 class NodeOperationInput;
46 class NodeOperationOutput;
47
48 /**
49  * \brief Resize modes of inputsockets
50  * How are the input and working resolutions matched
51  * \ingroup Model
52  */
53 typedef enum InputResizeMode {
54   /** \brief Center the input image to the center of the working area of the node, no resizing
55      occurs */
56   COM_SC_CENTER = NS_CR_CENTER,
57   /** \brief The bottom left of the input image is the bottom left of the working area of the node,
58      no resizing occurs */
59   COM_SC_NO_RESIZE = NS_CR_NONE,
60   /** \brief Fit the width of the input image to the width of the working area of the node */
61   COM_SC_FIT_WIDTH = NS_CR_FIT_WIDTH,
62   /** \brief Fit the height of the input image to the height of the working area of the node */
63   COM_SC_FIT_HEIGHT = NS_CR_FIT_HEIGHT,
64   /** \brief Fit the width or the height of the input image to the width or height of the working
65      area of the node, image will be larger than the working area */
66   COM_SC_FIT = NS_CR_FIT,
67   /** \brief Fit the width and the height of the input image to the width and height of the working
68      area of the node, image will be equally larger than the working area */
69   COM_SC_STRETCH = NS_CR_STRETCH,
70 } InputResizeMode;
71
72 /**
73  * \brief NodeOperation contains calculation logic
74  *
75  * Subclasses needs to implement the execution method (defined in SocketReader) to implement logic.
76  * \ingroup Model
77  */
78 class NodeOperation : public SocketReader {
79  public:
80   typedef std::vector<NodeOperationInput *> Inputs;
81   typedef std::vector<NodeOperationOutput *> Outputs;
82
83  private:
84   Inputs m_inputs;
85   Outputs m_outputs;
86
87   /**
88    * \brief the index of the input socket that will be used to determine the resolution
89    */
90   unsigned int m_resolutionInputSocketIndex;
91
92   /**
93    * \brief is this operation a complex one.
94    *
95    * Complex operations are typically doing many reads to calculate the output of a single pixel.
96    * Mostly Filter types (Blurs, Convolution, Defocus etc) need this to be set to true.
97    */
98   bool m_complex;
99
100   /**
101    * \brief can this operation be scheduled on an OpenCL device.
102    * \note Only applicable if complex is True
103    */
104   bool m_openCL;
105
106   /**
107    * \brief mutex reference for very special node initializations
108    * \note only use when you really know what you are doing.
109    * this mutex is used to share data among chunks in the same operation
110    * \see TonemapOperation for an example of usage
111    * \see NodeOperation.initMutex initializes this mutex
112    * \see NodeOperation.deinitMutex deinitializes this mutex
113    * \see NodeOperation.getMutex retrieve a pointer to this mutex.
114    */
115   ThreadMutex m_mutex;
116
117   /**
118    * \brief reference to the editing bNodeTree, used for break and update callback
119    */
120   const bNodeTree *m_btree;
121
122   /**
123    * \brief set to truth when resolution for this operation is set
124    */
125   bool m_isResolutionSet;
126
127  public:
128   virtual ~NodeOperation();
129
130   unsigned int getNumberOfInputSockets() const
131   {
132     return m_inputs.size();
133   }
134   unsigned int getNumberOfOutputSockets() const
135   {
136     return m_outputs.size();
137   }
138   NodeOperationOutput *getOutputSocket(unsigned int index) const;
139   NodeOperationOutput *getOutputSocket() const
140   {
141     return getOutputSocket(0);
142   }
143   NodeOperationInput *getInputSocket(unsigned int index) const;
144
145   /** Check if this is an input operation
146    * An input operation is an operation that only has output sockets and no input sockets
147    */
148   bool isInputOperation() const
149   {
150     return m_inputs.empty();
151   }
152
153   /**
154    * \brief determine the resolution of this node
155    * \note this method will not set the resolution, this is the responsibility of the caller
156    * \param resolution: the result of this operation
157    * \param preferredResolution: the preferable resolution as no resolution could be determined
158    */
159   virtual void determineResolution(unsigned int resolution[2],
160                                    unsigned int preferredResolution[2]);
161
162   /**
163    * \brief isOutputOperation determines whether this operation is an output of the ExecutionSystem
164    * during rendering or editing.
165    *
166    * Default behavior if not overridden, this operation will not be evaluated as being an output of
167    * the ExecutionSystem.
168    *
169    * \see ExecutionSystem
170    * \group check
171    * \param rendering: [true false]
172    *  true: rendering
173    *  false: editing
174    *
175    * \return bool the result of this method
176    */
177   virtual bool isOutputOperation(bool /*rendering*/) const
178   {
179     return false;
180   }
181
182   virtual int isSingleThreaded()
183   {
184     return false;
185   }
186
187   void setbNodeTree(const bNodeTree *tree)
188   {
189     this->m_btree = tree;
190   }
191   virtual void initExecution();
192
193   /**
194    * \brief when a chunk is executed by a CPUDevice, this method is called
195    * \ingroup execution
196    * \param rect: the rectangle of the chunk (location and size)
197    * \param chunkNumber: the chunkNumber to be calculated
198    * \param memoryBuffers: all input MemoryBuffer's needed
199    */
200   virtual void executeRegion(rcti * /*rect*/, unsigned int /*chunkNumber*/)
201   {
202   }
203
204   /**
205    * \brief when a chunk is executed by an OpenCLDevice, this method is called
206    * \ingroup execution
207    * \note this method is only implemented in WriteBufferOperation
208    * \param context: the OpenCL context
209    * \param program: the OpenCL program containing all compositor kernels
210    * \param queue: the OpenCL command queue of the device the chunk is executed on
211    * \param rect: the rectangle of the chunk (location and size)
212    * \param chunkNumber: the chunkNumber to be calculated
213    * \param memoryBuffers: all input MemoryBuffer's needed
214    * \param outputBuffer: the outputbuffer to write to
215    */
216   virtual void executeOpenCLRegion(OpenCLDevice * /*device*/,
217                                    rcti * /*rect*/,
218                                    unsigned int /*chunkNumber*/,
219                                    MemoryBuffer ** /*memoryBuffers*/,
220                                    MemoryBuffer * /*outputBuffer*/)
221   {
222   }
223
224   /**
225    * \brief custom handle to add new tasks to the OpenCL command queue
226    * in order to execute a chunk on an GPUDevice.
227    * \ingroup execution
228    * \param context: the OpenCL context
229    * \param program: the OpenCL program containing all compositor kernels
230    * \param queue: the OpenCL command queue of the device the chunk is executed on
231    * \param outputMemoryBuffer: the allocated memory buffer in main CPU memory
232    * \param clOutputBuffer: the allocated memory buffer in OpenCLDevice memory
233    * \param inputMemoryBuffers: all input MemoryBuffer's needed
234    * \param clMemToCleanUp: all created cl_mem references must be added to this list.
235    * Framework will clean this after execution
236    * \param clKernelsToCleanUp: all created cl_kernel references must be added to this list.
237    * Framework will clean this after execution
238    */
239   virtual void executeOpenCL(OpenCLDevice * /*device*/,
240                              MemoryBuffer * /*outputMemoryBuffer*/,
241                              cl_mem /*clOutputBuffer*/,
242                              MemoryBuffer ** /*inputMemoryBuffers*/,
243                              list<cl_mem> * /*clMemToCleanUp*/,
244                              list<cl_kernel> * /*clKernelsToCleanUp*/)
245   {
246   }
247   virtual void deinitExecution();
248
249   bool isResolutionSet()
250   {
251     return this->m_isResolutionSet;
252   }
253
254   /**
255    * \brief set the resolution
256    * \param resolution: the resolution to set
257    */
258   void setResolution(unsigned int resolution[2])
259   {
260     if (!isResolutionSet()) {
261       this->m_width = resolution[0];
262       this->m_height = resolution[1];
263       this->m_isResolutionSet = true;
264     }
265   }
266
267   void getConnectedInputSockets(Inputs *sockets);
268
269   /**
270    * \brief is this operation complex
271    *
272    * Complex operations are typically doing many reads to calculate the output of a single pixel.
273    * Mostly Filter types (Blurs, Convolution, Defocus etc) need this to be set to true.
274    */
275   bool isComplex() const
276   {
277     return this->m_complex;
278   }
279
280   virtual bool isSetOperation() const
281   {
282     return false;
283   }
284
285   /**
286    * \brief is this operation of type ReadBufferOperation
287    * \return [true:false]
288    * \see ReadBufferOperation
289    */
290   virtual bool isReadBufferOperation() const
291   {
292     return false;
293   }
294
295   /**
296    * \brief is this operation of type WriteBufferOperation
297    * \return [true:false]
298    * \see WriteBufferOperation
299    */
300   virtual bool isWriteBufferOperation() const
301   {
302     return false;
303   }
304
305   /**
306    * \brief is this operation the active viewer output
307    * user can select an ViewerNode to be active
308    * (the result of this node will be drawn on the backdrop).
309    * \return [true:false]
310    * \see BaseViewerOperation
311    */
312   virtual bool isActiveViewerOutput() const
313   {
314     return false;
315   }
316
317   virtual bool determineDependingAreaOfInterest(rcti *input,
318                                                 ReadBufferOperation *readOperation,
319                                                 rcti *output);
320
321   /**
322    * \brief set the index of the input socket that will determine the resolution of this operation
323    * \param index: the index to set
324    */
325   void setResolutionInputSocketIndex(unsigned int index);
326
327   /**
328    * \brief get the render priority of this node.
329    * \note only applicable for output operations like ViewerOperation
330    * \return CompositorPriority
331    */
332   virtual CompositorPriority getRenderPriority() const
333   {
334     return COM_PRIORITY_LOW;
335   }
336
337   /**
338    * \brief can this NodeOperation be scheduled on an OpenCLDevice
339    * \see WorkScheduler.schedule
340    * \see ExecutionGroup.addOperation
341    */
342   bool isOpenCL() const
343   {
344     return this->m_openCL;
345   }
346
347   virtual bool isViewerOperation() const
348   {
349     return false;
350   }
351   virtual bool isPreviewOperation() const
352   {
353     return false;
354   }
355   virtual bool isFileOutputOperation() const
356   {
357     return false;
358   }
359   virtual bool isProxyOperation() const
360   {
361     return false;
362   }
363
364   virtual bool useDatatypeConversion() const
365   {
366     return true;
367   }
368
369   inline bool isBraked() const
370   {
371     return this->m_btree->test_break(this->m_btree->tbh);
372   }
373
374   inline void updateDraw()
375   {
376     if (this->m_btree->update_draw) {
377       this->m_btree->update_draw(this->m_btree->udh);
378     }
379   }
380
381  protected:
382   NodeOperation();
383
384   void addInputSocket(DataType datatype, InputResizeMode resize_mode = COM_SC_CENTER);
385   void addOutputSocket(DataType datatype);
386
387   void setWidth(unsigned int width)
388   {
389     this->m_width = width;
390     this->m_isResolutionSet = true;
391   }
392   void setHeight(unsigned int height)
393   {
394     this->m_height = height;
395     this->m_isResolutionSet = true;
396   }
397   SocketReader *getInputSocketReader(unsigned int inputSocketindex);
398   NodeOperation *getInputOperation(unsigned int inputSocketindex);
399
400   void deinitMutex();
401   void initMutex();
402   void lockMutex();
403   void unlockMutex();
404
405   /**
406    * \brief set whether this operation is complex
407    *
408    * Complex operations are typically doing many reads to calculate the output of a single pixel.
409    * Mostly Filter types (Blurs, Convolution, Defocus etc) need this to be set to true.
410    */
411   void setComplex(bool complex)
412   {
413     this->m_complex = complex;
414   }
415
416   /**
417    * \brief set if this NodeOperation can be scheduled on a OpenCLDevice
418    */
419   void setOpenCL(bool openCL)
420   {
421     this->m_openCL = openCL;
422   }
423
424   /* allow the DebugInfo class to look at internals */
425   friend class DebugInfo;
426
427 #ifdef WITH_CXX_GUARDEDALLOC
428   MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
429 #endif
430 };
431
432 class NodeOperationInput {
433  private:
434   NodeOperation *m_operation;
435
436   /** Datatype of this socket. Is used for automatically data transformation.
437    * \section data-conversion
438    */
439   DataType m_datatype;
440
441   /** Resize mode of this socket */
442   InputResizeMode m_resizeMode;
443
444   /** Connected output */
445   NodeOperationOutput *m_link;
446
447  public:
448   NodeOperationInput(NodeOperation *op,
449                      DataType datatype,
450                      InputResizeMode resizeMode = COM_SC_CENTER);
451
452   NodeOperation &getOperation() const
453   {
454     return *m_operation;
455   }
456   DataType getDataType() const
457   {
458     return m_datatype;
459   }
460
461   void setLink(NodeOperationOutput *link)
462   {
463     m_link = link;
464   }
465   NodeOperationOutput *getLink() const
466   {
467     return m_link;
468   }
469   bool isConnected() const
470   {
471     return m_link;
472   }
473
474   void setResizeMode(InputResizeMode resizeMode)
475   {
476     this->m_resizeMode = resizeMode;
477   }
478   InputResizeMode getResizeMode() const
479   {
480     return this->m_resizeMode;
481   }
482
483   SocketReader *getReader();
484
485   void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
486
487 #ifdef WITH_CXX_GUARDEDALLOC
488   MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
489 #endif
490 };
491
492 class NodeOperationOutput {
493  private:
494   NodeOperation *m_operation;
495
496   /** Datatype of this socket. Is used for automatically data transformation.
497    * \section data-conversion
498    */
499   DataType m_datatype;
500
501  public:
502   NodeOperationOutput(NodeOperation *op, DataType datatype);
503
504   NodeOperation &getOperation() const
505   {
506     return *m_operation;
507   }
508   DataType getDataType() const
509   {
510     return m_datatype;
511   }
512
513   /**
514    * \brief determine the resolution of this data going through this socket
515    * \param resolution: the result of this operation
516    * \param preferredResolution: the preferable resolution as no resolution could be determined
517    */
518   void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
519
520 #ifdef WITH_CXX_GUARDEDALLOC
521   MEM_CXX_CLASS_ALLOC_FUNCS("COM:NodeOperation")
522 #endif
523 };
524
525 #endif