diff options
Diffstat (limited to 'source/blender/compositor/intern/COM_MemoryBuffer.h')
-rw-r--r-- | source/blender/compositor/intern/COM_MemoryBuffer.h | 563 |
1 files changed, 300 insertions, 263 deletions
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h index 63897da0b8a..12cd55c95a3 100644 --- a/source/blender/compositor/intern/COM_MemoryBuffer.h +++ b/source/blender/compositor/intern/COM_MemoryBuffer.h @@ -26,8 +26,8 @@ class MemoryBuffer; #include "COM_SocketReader.h" extern "C" { -# include "BLI_math.h" -# include "BLI_rect.h" +#include "BLI_math.h" +#include "BLI_rect.h" } /** @@ -35,18 +35,18 @@ extern "C" { * \ingroup Memory */ typedef enum MemoryBufferState { - /** \brief memory has been allocated on creator device and CPU machine, but kernel has not been executed */ - COM_MB_ALLOCATED = 1, - /** \brief memory is available for use, content has been created */ - COM_MB_AVAILABLE = 2, - /** \brief chunk is consolidated from other chunks. special state.*/ - COM_MB_TEMPORARILY = 6, + /** \brief memory has been allocated on creator device and CPU machine, but kernel has not been executed */ + COM_MB_ALLOCATED = 1, + /** \brief memory is available for use, content has been created */ + COM_MB_AVAILABLE = 2, + /** \brief chunk is consolidated from other chunks. special state.*/ + COM_MB_TEMPORARILY = 6, } MemoryBufferState; typedef enum MemoryBufferExtend { - COM_MB_CLIP, - COM_MB_EXTEND, - COM_MB_REPEAT, + COM_MB_CLIP, + COM_MB_EXTEND, + COM_MB_REPEAT, } MemoryBufferExtend; class MemoryProxy; @@ -55,262 +55,299 @@ class MemoryProxy; * \brief a MemoryBuffer contains access to the data of a chunk */ class MemoryBuffer { -private: - /** - * \brief proxy of the memory (same for all chunks in the same buffer) - */ - MemoryProxy *m_memoryProxy; - - /** - * \brief the type of buffer COM_DT_VALUE, COM_DT_VECTOR, COM_DT_COLOR - */ - DataType m_datatype; - - - /** - * \brief region of this buffer inside relative to the MemoryProxy - */ - rcti m_rect; - - /** - * brief refers to the chunknumber within the executiongroup where related to the MemoryProxy - * \see memoryProxy - */ - unsigned int m_chunkNumber; - - /** - * \brief state of the buffer - */ - MemoryBufferState m_state; - - /** - * \brief the actual float buffer/data - */ - float *m_buffer; - - /** - * \brief the number of channels of a single value in the buffer. - * For value buffers this is 1, vector 3 and color 4 - */ - unsigned int m_num_channels; - - int m_width; - int m_height; - -public: - /** - * \brief construct new MemoryBuffer for a chunk - */ - MemoryBuffer(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect); - - /** - * \brief construct new temporarily MemoryBuffer for an area - */ - MemoryBuffer(MemoryProxy *memoryProxy, rcti *rect); - - /** - * \brief construct new temporarily MemoryBuffer for an area - */ - MemoryBuffer(DataType datatype, rcti *rect); - - /** - * \brief destructor - */ - ~MemoryBuffer(); - - /** - * \brief read the ChunkNumber of this MemoryBuffer - */ - unsigned int getChunkNumber() { return this->m_chunkNumber; } - - unsigned int get_num_channels() { return this->m_num_channels; } - - /** - * \brief get the data of this MemoryBuffer - * \note buffer should already be available in memory - */ - float *getBuffer() { return this->m_buffer; } - - /** - * \brief after execution the state will be set to available by calling this method - */ - void setCreatedState() - { - this->m_state = COM_MB_AVAILABLE; - } - - inline void wrap_pixel(int &x, int &y, MemoryBufferExtend extend_x, MemoryBufferExtend extend_y) - { - int w = this->m_width; - int h = this->m_height; - x = x - m_rect.xmin; - y = y - m_rect.ymin; - - switch (extend_x) { - case COM_MB_CLIP: - break; - case COM_MB_EXTEND: - if (x < 0) x = 0; - if (x >= w) x = w; - break; - case COM_MB_REPEAT: - x = (x >= 0.0f ? (x % w) : (x % w) + w); - break; - } - - switch (extend_y) { - case COM_MB_CLIP: - break; - case COM_MB_EXTEND: - if (y < 0) y = 0; - if (y >= h) y = h; - break; - case COM_MB_REPEAT: - y = (y >= 0.0f ? (y % h) : (y % h) + h); - break; - } - } - - inline void wrap_pixel(float &x, float &y, MemoryBufferExtend extend_x, MemoryBufferExtend extend_y) - { - float w = (float)this->m_width; - float h = (float)this->m_height; - x = x - m_rect.xmin; - y = y - m_rect.ymin; - - switch (extend_x) { - case COM_MB_CLIP: - break; - case COM_MB_EXTEND: - if (x < 0) x = 0.0f; - if (x >= w) x = w; - break; - case COM_MB_REPEAT: - x = fmodf(x, w); - break; - } - - switch (extend_y) { - case COM_MB_CLIP: - break; - case COM_MB_EXTEND: - if (y < 0) y = 0.0f; - if (y >= h) y = h; - break; - case COM_MB_REPEAT: - y = fmodf(y, h); - break; - } - } - - inline void read(float *result, int x, int y, - MemoryBufferExtend extend_x = COM_MB_CLIP, - MemoryBufferExtend extend_y = COM_MB_CLIP) - { - bool clip_x = (extend_x == COM_MB_CLIP && (x < m_rect.xmin || x >= m_rect.xmax)); - bool clip_y = (extend_y == COM_MB_CLIP && (y < m_rect.ymin || y >= m_rect.ymax)); - if (clip_x || clip_y) { - /* clip result outside rect is zero */ - memset(result, 0, this->m_num_channels * sizeof(float)); - } - else { - int u = x; - int v = y; - this->wrap_pixel(u, v, extend_x, extend_y); - const int offset = (this->m_width * y + x) * this->m_num_channels; - float *buffer = &this->m_buffer[offset]; - memcpy(result, buffer, sizeof(float) * this->m_num_channels); - } - } - - inline void readNoCheck(float *result, int x, int y, - MemoryBufferExtend extend_x = COM_MB_CLIP, - MemoryBufferExtend extend_y = COM_MB_CLIP) - { - int u = x; - int v = y; - - this->wrap_pixel(u, v, extend_x, extend_y); - const int offset = (this->m_width * v + u) * this->m_num_channels; - - BLI_assert(offset >= 0); - BLI_assert(offset < this->determineBufferSize() * this->m_num_channels); - BLI_assert(!(extend_x == COM_MB_CLIP && (u < m_rect.xmin || u >= m_rect.xmax)) && - !(extend_y == COM_MB_CLIP && (v < m_rect.ymin || v >= m_rect.ymax))); + private: + /** + * \brief proxy of the memory (same for all chunks in the same buffer) + */ + MemoryProxy *m_memoryProxy; + + /** + * \brief the type of buffer COM_DT_VALUE, COM_DT_VECTOR, COM_DT_COLOR + */ + DataType m_datatype; + + /** + * \brief region of this buffer inside relative to the MemoryProxy + */ + rcti m_rect; + + /** + * brief refers to the chunknumber within the executiongroup where related to the MemoryProxy + * \see memoryProxy + */ + unsigned int m_chunkNumber; + + /** + * \brief state of the buffer + */ + MemoryBufferState m_state; + + /** + * \brief the actual float buffer/data + */ + float *m_buffer; + + /** + * \brief the number of channels of a single value in the buffer. + * For value buffers this is 1, vector 3 and color 4 + */ + unsigned int m_num_channels; + + int m_width; + int m_height; + + public: + /** + * \brief construct new MemoryBuffer for a chunk + */ + MemoryBuffer(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect); + + /** + * \brief construct new temporarily MemoryBuffer for an area + */ + MemoryBuffer(MemoryProxy *memoryProxy, rcti *rect); + + /** + * \brief construct new temporarily MemoryBuffer for an area + */ + MemoryBuffer(DataType datatype, rcti *rect); + + /** + * \brief destructor + */ + ~MemoryBuffer(); + + /** + * \brief read the ChunkNumber of this MemoryBuffer + */ + unsigned int getChunkNumber() + { + return this->m_chunkNumber; + } + + unsigned int get_num_channels() + { + return this->m_num_channels; + } + + /** + * \brief get the data of this MemoryBuffer + * \note buffer should already be available in memory + */ + float *getBuffer() + { + return this->m_buffer; + } + + /** + * \brief after execution the state will be set to available by calling this method + */ + void setCreatedState() + { + this->m_state = COM_MB_AVAILABLE; + } + + inline void wrap_pixel(int &x, int &y, MemoryBufferExtend extend_x, MemoryBufferExtend extend_y) + { + int w = this->m_width; + int h = this->m_height; + x = x - m_rect.xmin; + y = y - m_rect.ymin; + + switch (extend_x) { + case COM_MB_CLIP: + break; + case COM_MB_EXTEND: + if (x < 0) + x = 0; + if (x >= w) + x = w; + break; + case COM_MB_REPEAT: + x = (x >= 0.0f ? (x % w) : (x % w) + w); + break; + } + + switch (extend_y) { + case COM_MB_CLIP: + break; + case COM_MB_EXTEND: + if (y < 0) + y = 0; + if (y >= h) + y = h; + break; + case COM_MB_REPEAT: + y = (y >= 0.0f ? (y % h) : (y % h) + h); + break; + } + } + + inline void wrap_pixel(float &x, + float &y, + MemoryBufferExtend extend_x, + MemoryBufferExtend extend_y) + { + float w = (float)this->m_width; + float h = (float)this->m_height; + x = x - m_rect.xmin; + y = y - m_rect.ymin; + + switch (extend_x) { + case COM_MB_CLIP: + break; + case COM_MB_EXTEND: + if (x < 0) + x = 0.0f; + if (x >= w) + x = w; + break; + case COM_MB_REPEAT: + x = fmodf(x, w); + break; + } + + switch (extend_y) { + case COM_MB_CLIP: + break; + case COM_MB_EXTEND: + if (y < 0) + y = 0.0f; + if (y >= h) + y = h; + break; + case COM_MB_REPEAT: + y = fmodf(y, h); + break; + } + } + + inline void read(float *result, + int x, + int y, + MemoryBufferExtend extend_x = COM_MB_CLIP, + MemoryBufferExtend extend_y = COM_MB_CLIP) + { + bool clip_x = (extend_x == COM_MB_CLIP && (x < m_rect.xmin || x >= m_rect.xmax)); + bool clip_y = (extend_y == COM_MB_CLIP && (y < m_rect.ymin || y >= m_rect.ymax)); + if (clip_x || clip_y) { + /* clip result outside rect is zero */ + memset(result, 0, this->m_num_channels * sizeof(float)); + } + else { + int u = x; + int v = y; + this->wrap_pixel(u, v, extend_x, extend_y); + const int offset = (this->m_width * y + x) * this->m_num_channels; + float *buffer = &this->m_buffer[offset]; + memcpy(result, buffer, sizeof(float) * this->m_num_channels); + } + } + + inline void readNoCheck(float *result, + int x, + int y, + MemoryBufferExtend extend_x = COM_MB_CLIP, + MemoryBufferExtend extend_y = COM_MB_CLIP) + { + int u = x; + int v = y; + + this->wrap_pixel(u, v, extend_x, extend_y); + const int offset = (this->m_width * v + u) * this->m_num_channels; + + BLI_assert(offset >= 0); + BLI_assert(offset < this->determineBufferSize() * this->m_num_channels); + BLI_assert(!(extend_x == COM_MB_CLIP && (u < m_rect.xmin || u >= m_rect.xmax)) && + !(extend_y == COM_MB_CLIP && (v < m_rect.ymin || v >= m_rect.ymax))); #if 0 - /* always true */ - BLI_assert((int)(MEM_allocN_len(this->m_buffer) / sizeof(*this->m_buffer)) == - (int)(this->determineBufferSize() * COM_NUMBER_OF_CHANNELS)); + /* always true */ + BLI_assert((int)(MEM_allocN_len(this->m_buffer) / sizeof(*this->m_buffer)) == + (int)(this->determineBufferSize() * COM_NUMBER_OF_CHANNELS)); #endif - float *buffer = &this->m_buffer[offset]; - memcpy(result, buffer, sizeof(float) * this->m_num_channels); - } - - void writePixel(int x, int y, const float color[4]); - void addPixel(int x, int y, const float color[4]); - inline void readBilinear(float *result, float x, float y, - MemoryBufferExtend extend_x = COM_MB_CLIP, - MemoryBufferExtend extend_y = COM_MB_CLIP) - { - float u = x; - float v = y; - this->wrap_pixel(u, v, extend_x, extend_y); - if ((extend_x != COM_MB_REPEAT && (u < 0.0f || u >= this->m_width)) || - (extend_y != COM_MB_REPEAT && (v < 0.0f || v >= this->m_height))) - { - copy_vn_fl(result, this->m_num_channels, 0.0f); - return; - } - BLI_bilinear_interpolation_wrap_fl( - this->m_buffer, result, this->m_width, this->m_height, this->m_num_channels, u, v, - extend_x == COM_MB_REPEAT, extend_y == COM_MB_REPEAT); - } - - void readEWA(float *result, const float uv[2], const float derivatives[2][2]); - - /** - * \brief is this MemoryBuffer a temporarily buffer (based on an area, not on a chunk) - */ - inline bool isTemporarily() const { return this->m_state == COM_MB_TEMPORARILY; } - - /** - * \brief add the content from otherBuffer to this MemoryBuffer - * \param otherBuffer: source buffer - * - * \note take care when running this on a new buffer since it wont fill in - * uninitialized values in areas where the buffers don't overlap. - */ - void copyContentFrom(MemoryBuffer *otherBuffer); - - /** - * \brief get the rect of this MemoryBuffer - */ - rcti *getRect() { return &this->m_rect; } - - /** - * \brief get the width of this MemoryBuffer - */ - int getWidth() const; - - /** - * \brief get the height of this MemoryBuffer - */ - int getHeight() const; - - /** - * \brief clear the buffer. Make all pixels black transparent. - */ - void clear(); - - MemoryBuffer *duplicate(); - - float getMaximumValue(); - float getMaximumValue(rcti *rect); -private: - unsigned int determineBufferSize(); + float *buffer = &this->m_buffer[offset]; + memcpy(result, buffer, sizeof(float) * this->m_num_channels); + } + + void writePixel(int x, int y, const float color[4]); + void addPixel(int x, int y, const float color[4]); + inline void readBilinear(float *result, + float x, + float y, + MemoryBufferExtend extend_x = COM_MB_CLIP, + MemoryBufferExtend extend_y = COM_MB_CLIP) + { + float u = x; + float v = y; + this->wrap_pixel(u, v, extend_x, extend_y); + if ((extend_x != COM_MB_REPEAT && (u < 0.0f || u >= this->m_width)) || + (extend_y != COM_MB_REPEAT && (v < 0.0f || v >= this->m_height))) { + copy_vn_fl(result, this->m_num_channels, 0.0f); + return; + } + BLI_bilinear_interpolation_wrap_fl(this->m_buffer, + result, + this->m_width, + this->m_height, + this->m_num_channels, + u, + v, + extend_x == COM_MB_REPEAT, + extend_y == COM_MB_REPEAT); + } + + void readEWA(float *result, const float uv[2], const float derivatives[2][2]); + + /** + * \brief is this MemoryBuffer a temporarily buffer (based on an area, not on a chunk) + */ + inline bool isTemporarily() const + { + return this->m_state == COM_MB_TEMPORARILY; + } + + /** + * \brief add the content from otherBuffer to this MemoryBuffer + * \param otherBuffer: source buffer + * + * \note take care when running this on a new buffer since it wont fill in + * uninitialized values in areas where the buffers don't overlap. + */ + void copyContentFrom(MemoryBuffer *otherBuffer); + + /** + * \brief get the rect of this MemoryBuffer + */ + rcti *getRect() + { + return &this->m_rect; + } + + /** + * \brief get the width of this MemoryBuffer + */ + int getWidth() const; + + /** + * \brief get the height of this MemoryBuffer + */ + int getHeight() const; + + /** + * \brief clear the buffer. Make all pixels black transparent. + */ + void clear(); + + MemoryBuffer *duplicate(); + + float getMaximumValue(); + float getMaximumValue(rcti *rect); + + private: + unsigned int determineBufferSize(); #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("COM:MemoryBuffer") + MEM_CXX_CLASS_ALLOC_FUNCS("COM:MemoryBuffer") #endif }; |