compositor - EWA filter was blurring too much by default, this caused the displace...
[blender.git] / source / blender / compositor / intern / COM_MemoryBuffer.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 class MemoryBuffer;
24
25 #ifndef _COM_MemoryBuffer_h_
26 #define _COM_MemoryBuffer_h_
27
28 #include "COM_ExecutionGroup.h"
29 #include "COM_MemoryProxy.h"
30
31 extern "C" {
32         #include "BLI_math.h"
33         #include "BLI_rect.h"
34 }
35
36 /**
37  * @brief state of a memory buffer
38  * @ingroup Memory
39  */
40 typedef enum MemoryBufferState {
41         /** @brief memory has been allocated on creator device and CPU machine, but kernel has not been executed */
42         COM_MB_ALLOCATED = 1,
43         /** @brief memory is available for use, content has been created */
44         COM_MB_AVAILABLE = 2,
45         /** @brief chunk is consolidated from other chunks. special state.*/
46         COM_MB_TEMPORARILY = 6
47 } MemoryBufferState;
48
49 class MemoryProxy;
50
51 /**
52  * @brief a MemoryBuffer contains access to the data of a chunk
53  */
54 class MemoryBuffer {
55 private:
56         /**
57          * @brief proxy of the memory (same for all chunks in the same buffer)
58          */
59         MemoryProxy *m_memoryProxy;
60         
61         /**
62          * @brief the type of buffer COM_DT_VALUE, COM_DT_VECTOR, COM_DT_COLOR
63          */
64         DataType m_datatype;
65         
66         
67         /**
68          * @brief region of this buffer inside relative to the MemoryProxy
69          */
70         rcti m_rect;
71         
72         /**
73          * brief refers to the chunknumber within the executiongroup where related to the MemoryProxy
74          * @see memoryProxy
75          */
76         unsigned int m_chunkNumber;
77         
78         /**
79          * @brief width of the chunk
80          */
81         unsigned int m_chunkWidth;
82         
83         /**
84          * @brief state of the buffer
85          */
86         MemoryBufferState m_state;
87         
88         /**
89          * @brief the actual float buffer/data
90          */
91         float *m_buffer;
92
93 public:
94         /**
95          * @brief construct new MemoryBuffer for a chunk
96          */
97         MemoryBuffer(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect);
98         
99         /**
100          * @brief construct new temporarily MemoryBuffer for an area
101          */
102         MemoryBuffer(MemoryProxy *memoryProxy, rcti *rect);
103         
104         /**
105          * @brief destructor
106          */
107         ~MemoryBuffer();
108         
109         /**
110          * @brief read the ChunkNumber of this MemoryBuffer
111          */
112         unsigned int getChunkNumber() { return this->m_chunkNumber; }
113         
114         /**
115          * @brief get the data of this MemoryBuffer
116          * @note buffer should already be available in memory
117          */
118         float *getBuffer() { return this->m_buffer; }
119         
120         /**
121          * @brief after execution the state will be set to available by calling this method
122          */
123         void setCreatedState()
124         {
125                 this->m_state = COM_MB_AVAILABLE;
126         }
127         
128         inline void read(float result[4], int x, int y)
129         {
130                 if (x >= this->m_rect.xmin && x < this->m_rect.xmax &&
131                     y >= this->m_rect.ymin && y < this->m_rect.ymax)
132                 {
133                         const int dx = x - this->m_rect.xmin;
134                         const int dy = y - this->m_rect.ymin;
135                         const int offset = (this->m_chunkWidth * dy + dx) * COM_NUMBER_OF_CHANNELS;
136                         copy_v4_v4(result, &this->m_buffer[offset]);
137                 }
138                 else {
139                         zero_v4(result);
140                 }
141         }
142
143         inline void readNoCheck(float result[4], int x, int y)
144         {
145                 const int dx = x - this->m_rect.xmin;
146                 const int dy = y - this->m_rect.ymin;
147                 const int offset = (this->m_chunkWidth * dy + dx) * COM_NUMBER_OF_CHANNELS;
148
149                 BLI_assert(offset >= 0);
150                 BLI_assert(offset < this->determineBufferSize() * COM_NUMBER_OF_CHANNELS);
151                 BLI_assert(x >= this->m_rect.xmin && x < this->m_rect.xmax &&
152                            y >= this->m_rect.ymin && y < this->m_rect.ymax);
153
154 #if 0
155                 /* always true */
156                 BLI_assert((int)(MEM_allocN_len(this->m_buffer) / sizeof(*this->m_buffer)) ==
157                            (int)(this->determineBufferSize() * COM_NUMBER_OF_CHANNELS));
158 #endif
159
160                 copy_v4_v4(result, &this->m_buffer[offset]);
161         }
162         
163         void writePixel(int x, int y, const float color[4]);
164         void addPixel(int x, int y, const float color[4]);
165         inline void readCubic(float result[4], float x, float y)
166         {
167                 int x1 = floor(x);
168                 int x2 = x1 + 1;
169                 int y1 = floor(y);
170                 int y2 = y1 + 1;
171
172                 float valuex = x - x1;
173                 float valuey = y - y1;
174                 float mvaluex = 1.0f - valuex;
175                 float mvaluey = 1.0f - valuey;
176
177                 float color1[4];
178                 float color2[4];
179                 float color3[4];
180                 float color4[4];
181
182                 read(color1, x1, y1);
183                 read(color2, x1, y2);
184                 read(color3, x2, y1);
185                 read(color4, x2, y2);
186
187                 color1[0] = color1[0] * mvaluey + color2[0] * valuey;
188                 color1[1] = color1[1] * mvaluey + color2[1] * valuey;
189                 color1[2] = color1[2] * mvaluey + color2[2] * valuey;
190                 color1[3] = color1[3] * mvaluey + color2[3] * valuey;
191
192                 color3[0] = color3[0] * mvaluey + color4[0] * valuey;
193                 color3[1] = color3[1] * mvaluey + color4[1] * valuey;
194                 color3[2] = color3[2] * mvaluey + color4[2] * valuey;
195                 color3[3] = color3[3] * mvaluey + color4[3] * valuey;
196
197                 result[0] = color1[0] * mvaluex + color3[0] * valuex;
198                 result[1] = color1[1] * mvaluex + color3[1] * valuex;
199                 result[2] = color1[2] * mvaluex + color3[2] * valuex;
200                 result[3] = color1[3] * mvaluex + color3[3] * valuex;
201         }
202                 
203
204
205         void readEWA(float result[4], float fx, float fy, float dx, float dy, PixelSampler sampler);
206         
207         /**
208          * @brief is this MemoryBuffer a temporarily buffer (based on an area, not on a chunk)
209          */
210         inline const bool isTemporarily() const { return this->m_state == COM_MB_TEMPORARILY; }
211         
212         /**
213          * @brief add the content from otherBuffer to this MemoryBuffer
214          * @param otherBuffer source buffer
215          *
216          * @note take care when running this on a new buffer since it wont fill in
217          *       uninitialized values in areas where the buffers don't overlap.
218          */
219         void copyContentFrom(MemoryBuffer *otherBuffer);
220         
221         /**
222          * @brief get the rect of this MemoryBuffer
223          */
224         rcti *getRect() { return &this->m_rect; }
225         
226         /**
227          * @brief get the width of this MemoryBuffer
228          */
229         int getWidth() const;
230         
231         /**
232          * @brief get the height of this MemoryBuffer
233          */
234         int getHeight() const;
235         
236         /**
237          * @brief clear the buffer. Make all pixels black transparent.
238          */
239         void clear();
240         
241         MemoryBuffer *duplicate();
242         
243         float *convertToValueBuffer();
244         float getMaximumValue();
245         float getMaximumValue(rcti *rect);
246 private:
247         unsigned int determineBufferSize();
248
249 #ifdef WITH_CXX_GUARDEDALLOC
250         MEM_CXX_CLASS_ALLOC_FUNCS("COM:MemoryBuffer")
251 #endif
252 };
253
254 #endif