diff options
Diffstat (limited to 'source/blender/compositor/intern/COM_MemoryBuffer.h')
-rw-r--r-- | source/blender/compositor/intern/COM_MemoryBuffer.h | 254 |
1 files changed, 134 insertions, 120 deletions
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h index 9e173f73f63..1765fb93035 100644 --- a/source/blender/compositor/intern/COM_MemoryBuffer.h +++ b/source/blender/compositor/intern/COM_MemoryBuffer.h @@ -21,12 +21,15 @@ #include "COM_BufferArea.h" #include "COM_BufferRange.h" #include "COM_BuffersIterator.h" -#include "COM_ExecutionGroup.h" -#include "COM_MemoryProxy.h" +#include "COM_Enums.h" -#include "BLI_math.h" +#include "BLI_math_interp.h" #include "BLI_rect.h" +#include "IMB_colormanagement.h" + +struct ImBuf; + namespace blender::compositor { /** @@ -76,38 +79,38 @@ class MemoryBuffer { /** * \brief proxy of the memory (same for all chunks in the same buffer) */ - MemoryProxy *m_memoryProxy; + MemoryProxy *memory_proxy_; /** * \brief the type of buffer DataType::Value, DataType::Vector, DataType::Color */ - DataType m_datatype; + DataType datatype_; /** * \brief region of this buffer inside relative to the MemoryProxy */ - rcti m_rect; + rcti rect_; /** * \brief state of the buffer */ - MemoryBufferState m_state; + MemoryBufferState state_; /** * \brief the actual float buffer/data */ - float *m_buffer; + float *buffer_; /** * \brief the number of channels of a single value in the buffer. * For value buffers this is 1, vector 3 and color 4 */ - uint8_t m_num_channels; + uint8_t num_channels_; /** * Whether buffer is a single element in memory. */ - bool m_is_a_single_elem; + bool is_a_single_elem_; /** * Whether MemoryBuffer owns buffer data. @@ -124,16 +127,24 @@ class MemoryBuffer { /** * \brief construct new temporarily MemoryBuffer for an area */ - MemoryBuffer(MemoryProxy *memoryProxy, const rcti &rect, MemoryBufferState state); + MemoryBuffer(MemoryProxy *memory_proxy, const rcti &rect, MemoryBufferState state); /** * \brief construct new temporarily MemoryBuffer for an area */ - MemoryBuffer(DataType datatype, const rcti &rect, bool is_a_single_elem = false); + MemoryBuffer(DataType data_type, const rcti &rect, bool is_a_single_elem = false); + /** + * Construct MemoryBuffer from a float buffer. MemoryBuffer is not responsible for + * freeing it. + */ MemoryBuffer( float *buffer, int num_channels, int width, int height, bool is_a_single_elem = false); + /** + * Construct MemoryBuffer from a float buffer area. MemoryBuffer is not responsible for + * freeing given buffer. + */ MemoryBuffer(float *buffer, int num_channels, const rcti &rect, bool is_a_single_elem = false); /** @@ -152,21 +163,21 @@ class MemoryBuffer { */ bool is_a_single_elem() const { - return m_is_a_single_elem; + return is_a_single_elem_; } float &operator[](int index) { - BLI_assert(m_is_a_single_elem ? index < m_num_channels : - index < get_coords_offset(getWidth(), getHeight())); - return m_buffer[index]; + BLI_assert(is_a_single_elem_ ? index < num_channels_ : + index < get_coords_offset(get_width(), get_height())); + return buffer_[index]; } const float &operator[](int index) const { - BLI_assert(m_is_a_single_elem ? index < m_num_channels : - index < get_coords_offset(getWidth(), getHeight())); - return m_buffer[index]; + BLI_assert(is_a_single_elem_ ? index < num_channels_ : + index < get_coords_offset(get_width(), get_height())); + return buffer_[index]; } /** @@ -174,7 +185,7 @@ class MemoryBuffer { */ intptr_t get_coords_offset(int x, int y) const { - return ((intptr_t)y - m_rect.ymin) * row_stride + ((intptr_t)x - m_rect.xmin) * elem_stride; + return ((intptr_t)y - rect_.ymin) * row_stride + ((intptr_t)x - rect_.xmin) * elem_stride; } /** @@ -183,7 +194,7 @@ class MemoryBuffer { float *get_elem(int x, int y) { BLI_assert(has_coords(x, y)); - return m_buffer + get_coords_offset(x, y); + return buffer_ + get_coords_offset(x, y); } /** @@ -192,7 +203,7 @@ class MemoryBuffer { const float *get_elem(int x, int y) const { BLI_assert(has_coords(x, y)); - return m_buffer + get_coords_offset(x, y); + return buffer_ + get_coords_offset(x, y); } void read_elem(int x, int y, float *out) const @@ -218,21 +229,19 @@ class MemoryBuffer { void read_elem_bilinear(float x, float y, float *out) const { /* Only clear past +/-1 borders to be able to smooth edges. */ - if (x <= m_rect.xmin - 1.0f || x >= m_rect.xmax || y <= m_rect.ymin - 1.0f || - y >= m_rect.ymax) { + if (x <= rect_.xmin - 1.0f || x >= rect_.xmax || y <= rect_.ymin - 1.0f || y >= rect_.ymax) { clear_elem(out); return; } - if (m_is_a_single_elem) { - if (x >= m_rect.xmin && x < m_rect.xmax - 1.0f && y >= m_rect.ymin && - y < m_rect.ymax - 1.0f) { - memcpy(out, m_buffer, get_elem_bytes_len()); + if (is_a_single_elem_) { + if (x >= rect_.xmin && x < rect_.xmax - 1.0f && y >= rect_.ymin && y < rect_.ymax - 1.0f) { + memcpy(out, buffer_, get_elem_bytes_len()); return; } /* Do sampling at borders to smooth edges. */ - const float last_x = getWidth() - 1.0f; + const float last_x = get_width() - 1.0f; const float rel_x = get_relative_x(x); float single_x = 0.0f; if (rel_x < 0.0f) { @@ -242,7 +251,7 @@ class MemoryBuffer { single_x = rel_x - last_x; } - const float last_y = getHeight() - 1.0f; + const float last_y = get_height() - 1.0f; const float rel_y = get_relative_y(y); float single_y = 0.0f; if (rel_y < 0.0f) { @@ -252,15 +261,15 @@ class MemoryBuffer { single_y = rel_y - last_y; } - BLI_bilinear_interpolation_fl(m_buffer, out, 1, 1, m_num_channels, single_x, single_y); + BLI_bilinear_interpolation_fl(buffer_, out, 1, 1, num_channels_, single_x, single_y); return; } - BLI_bilinear_interpolation_fl(m_buffer, + BLI_bilinear_interpolation_fl(buffer_, out, - getWidth(), - getHeight(), - m_num_channels, + get_width(), + get_height(), + num_channels_, get_relative_x(x), get_relative_y(y)); } @@ -279,16 +288,15 @@ class MemoryBuffer { } } - void read_elem_filtered( - const float x, const float y, float dx[2], float dy[2], float *out) const; + void read_elem_filtered(float x, float y, float dx[2], float dy[2], float *out) const; /** * Get channel value at given coordinates. */ float &get_value(int x, int y, int channel) { - BLI_assert(has_coords(x, y) && channel >= 0 && channel < m_num_channels); - return m_buffer[get_coords_offset(x, y) + channel]; + BLI_assert(has_coords(x, y) && channel >= 0 && channel < num_channels_); + return buffer_[get_coords_offset(x, y) + channel]; } /** @@ -296,8 +304,8 @@ class MemoryBuffer { */ const float &get_value(int x, int y, int channel) const { - BLI_assert(has_coords(x, y) && channel >= 0 && channel < m_num_channels); - return m_buffer[get_coords_offset(x, y) + channel]; + BLI_assert(has_coords(x, y) && channel >= 0 && channel < num_channels_); + return buffer_[get_coords_offset(x, y) + channel]; } /** @@ -306,7 +314,7 @@ class MemoryBuffer { const float *get_row_end(int y) const { BLI_assert(has_y(y)); - return m_buffer + (is_a_single_elem() ? m_num_channels : get_coords_offset(getWidth(), y)); + return buffer_ + (is_a_single_elem() ? num_channels_ : get_coords_offset(get_width(), y)); } /** @@ -315,7 +323,7 @@ class MemoryBuffer { */ int get_memory_width() const { - return is_a_single_elem() ? 1 : getWidth(); + return is_a_single_elem() ? 1 : get_width(); } /** @@ -324,17 +332,17 @@ class MemoryBuffer { */ int get_memory_height() const { - return is_a_single_elem() ? 1 : getHeight(); + return is_a_single_elem() ? 1 : get_height(); } uint8_t get_num_channels() const { - return this->m_num_channels; + return num_channels_; } uint8_t get_elem_bytes_len() const { - return this->m_num_channels * sizeof(float); + return num_channels_ * sizeof(float); } /** @@ -342,22 +350,22 @@ class MemoryBuffer { */ BufferRange<float> as_range() { - return BufferRange<float>(m_buffer, 0, buffer_len(), elem_stride); + return BufferRange<float>(buffer_, 0, buffer_len(), elem_stride); } BufferRange<const float> as_range() const { - return BufferRange<const float>(m_buffer, 0, buffer_len(), elem_stride); + return BufferRange<const float>(buffer_, 0, buffer_len(), elem_stride); } BufferArea<float> get_buffer_area(const rcti &area) { - return BufferArea<float>(m_buffer, getWidth(), area, elem_stride); + return BufferArea<float>(buffer_, get_width(), area, elem_stride); } BufferArea<const float> get_buffer_area(const rcti &area) const { - return BufferArea<const float>(m_buffer, getWidth(), area, elem_stride); + return BufferArea<const float>(buffer_, get_width(), area, elem_stride); } BuffersIterator<float> iterate_with(Span<MemoryBuffer *> inputs); @@ -367,25 +375,29 @@ class MemoryBuffer { * \brief get the data of this MemoryBuffer * \note buffer should already be available in memory */ - float *getBuffer() + float *get_buffer() { - return this->m_buffer; + return buffer_; } float *release_ownership_buffer() { owns_data_ = false; - return this->m_buffer; + return buffer_; } + /** + * Converts a single elem buffer to a full size buffer (allocates memory for all + * elements in resolution). + */ MemoryBuffer *inflate() const; inline void wrap_pixel(int &x, int &y, MemoryBufferExtend extend_x, MemoryBufferExtend extend_y) { - const int w = getWidth(); - const int h = getHeight(); - x = x - m_rect.xmin; - y = y - m_rect.ymin; + const int w = get_width(); + const int h = get_height(); + x = x - rect_.xmin; + y = y - rect_.ymin; switch (extend_x) { case MemoryBufferExtend::Clip: @@ -425,8 +437,8 @@ class MemoryBuffer { break; } - x = x + m_rect.xmin; - y = y + m_rect.ymin; + x = x + rect_.xmin; + y = y + rect_.ymin; } inline void wrap_pixel(float &x, @@ -434,10 +446,10 @@ class MemoryBuffer { MemoryBufferExtend extend_x, MemoryBufferExtend extend_y) const { - const float w = (float)getWidth(); - const float h = (float)getHeight(); - x = x - m_rect.xmin; - y = y - m_rect.ymin; + const float w = (float)get_width(); + const float h = (float)get_height(); + x = x - rect_.xmin; + y = y - rect_.ymin; switch (extend_x) { case MemoryBufferExtend::Clip: @@ -477,8 +489,8 @@ class MemoryBuffer { break; } - x = x + m_rect.xmin; - y = y + m_rect.ymin; + x = x + rect_.xmin; + y = y + rect_.ymin; } /* TODO(manzanilla): to be removed with tiled implementation. For applying #MemoryBufferExtend @@ -489,28 +501,28 @@ class MemoryBuffer { MemoryBufferExtend extend_x = MemoryBufferExtend::Clip, MemoryBufferExtend extend_y = MemoryBufferExtend::Clip) { - bool clip_x = (extend_x == MemoryBufferExtend::Clip && (x < m_rect.xmin || x >= m_rect.xmax)); - bool clip_y = (extend_y == MemoryBufferExtend::Clip && (y < m_rect.ymin || y >= m_rect.ymax)); + bool clip_x = (extend_x == MemoryBufferExtend::Clip && (x < rect_.xmin || x >= rect_.xmax)); + bool clip_y = (extend_y == MemoryBufferExtend::Clip && (y < rect_.ymin || y >= rect_.ymax)); if (clip_x || clip_y) { /* clip result outside rect is zero */ - memset(result, 0, this->m_num_channels * sizeof(float)); + memset(result, 0, num_channels_ * sizeof(float)); } else { int u = x; int v = y; this->wrap_pixel(u, v, extend_x, extend_y); const int offset = get_coords_offset(u, v); - float *buffer = &this->m_buffer[offset]; - memcpy(result, buffer, sizeof(float) * this->m_num_channels); + float *buffer = &buffer_[offset]; + memcpy(result, buffer, sizeof(float) * num_channels_); } } /* TODO(manzanilla): to be removed with tiled implementation. */ - inline void readNoCheck(float *result, - int x, - int y, - MemoryBufferExtend extend_x = MemoryBufferExtend::Clip, - MemoryBufferExtend extend_y = MemoryBufferExtend::Clip) + inline void read_no_check(float *result, + int x, + int y, + MemoryBufferExtend extend_x = MemoryBufferExtend::Clip, + MemoryBufferExtend extend_y = MemoryBufferExtend::Clip) { int u = x; int v = y; @@ -519,38 +531,38 @@ class MemoryBuffer { const int offset = get_coords_offset(u, v); BLI_assert(offset >= 0); - BLI_assert(offset < this->buffer_len() * this->m_num_channels); - BLI_assert(!(extend_x == MemoryBufferExtend::Clip && (u < m_rect.xmin || u >= m_rect.xmax)) && - !(extend_y == MemoryBufferExtend::Clip && (v < m_rect.ymin || v >= m_rect.ymax))); - float *buffer = &this->m_buffer[offset]; - memcpy(result, buffer, sizeof(float) * this->m_num_channels); + BLI_assert(offset < this->buffer_len() * num_channels_); + BLI_assert(!(extend_x == MemoryBufferExtend::Clip && (u < rect_.xmin || u >= rect_.xmax)) && + !(extend_y == MemoryBufferExtend::Clip && (v < rect_.ymin || v >= rect_.ymax))); + float *buffer = &buffer_[offset]; + memcpy(result, buffer, sizeof(float) * 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 = MemoryBufferExtend::Clip, - MemoryBufferExtend extend_y = MemoryBufferExtend::Clip) const + void write_pixel(int x, int y, const float color[4]); + void add_pixel(int x, int y, const float color[4]); + inline void read_bilinear(float *result, + float x, + float y, + MemoryBufferExtend extend_x = MemoryBufferExtend::Clip, + MemoryBufferExtend extend_y = MemoryBufferExtend::Clip) const { float u = x; float v = y; this->wrap_pixel(u, v, extend_x, extend_y); - if ((extend_x != MemoryBufferExtend::Repeat && (u < 0.0f || u >= getWidth())) || - (extend_y != MemoryBufferExtend::Repeat && (v < 0.0f || v >= getHeight()))) { - copy_vn_fl(result, this->m_num_channels, 0.0f); + if ((extend_x != MemoryBufferExtend::Repeat && (u < 0.0f || u >= get_width())) || + (extend_y != MemoryBufferExtend::Repeat && (v < 0.0f || v >= get_height()))) { + copy_vn_fl(result, num_channels_, 0.0f); return; } - if (m_is_a_single_elem) { - memcpy(result, m_buffer, sizeof(float) * this->m_num_channels); + if (is_a_single_elem_) { + memcpy(result, buffer_, sizeof(float) * num_channels_); } else { - BLI_bilinear_interpolation_wrap_fl(this->m_buffer, + BLI_bilinear_interpolation_wrap_fl(buffer_, result, - getWidth(), - getHeight(), - this->m_num_channels, + get_width(), + get_height(), + num_channels_, u, v, extend_x == MemoryBufferExtend::Repeat, @@ -563,11 +575,16 @@ class MemoryBuffer { /** * \brief is this MemoryBuffer a temporarily buffer (based on an area, not on a chunk) */ - inline bool isTemporarily() const + inline bool is_temporarily() const { - return this->m_state == MemoryBufferState::Temporary; + return state_ == MemoryBufferState::Temporary; } + /** + * \brief Apply a color processor on the given area. + */ + void apply_processor(ColormanageProcessor &processor, const rcti area); + void copy_from(const MemoryBuffer *src, const rcti &area); void copy_from(const MemoryBuffer *src, const rcti &area, int to_x, int to_y); void copy_from(const MemoryBuffer *src, @@ -618,8 +635,8 @@ class MemoryBuffer { void fill(const rcti &area, const float *value); void fill(const rcti &area, int channel_offset, const float *value, int value_size); /** - * \brief add the content from otherBuffer to this MemoryBuffer - * \param otherBuffer: source buffer + * \brief add the content from other_buffer to this MemoryBuffer + * \param other_buffer: source buffer * * \note take care when running this on a new buffer since it won't fill in * uninitialized values in areas where the buffers don't overlap. @@ -631,23 +648,23 @@ class MemoryBuffer { */ const rcti &get_rect() const { - return this->m_rect; + return rect_; } /** * \brief get the width of this MemoryBuffer */ - const int getWidth() const + const int get_width() const { - return BLI_rcti_size_x(&m_rect); + return BLI_rcti_size_x(&rect_); } /** * \brief get the height of this MemoryBuffer */ - const int getHeight() const + const int get_height() const { - return BLI_rcti_size_y(&m_rect); + return BLI_rcti_size_y(&rect_); } /** @@ -667,17 +684,17 @@ class MemoryBuffer { void clear_elem(float *out) const { - memset(out, 0, this->m_num_channels * sizeof(float)); + memset(out, 0, num_channels_ * sizeof(float)); } template<typename T> T get_relative_x(T x) const { - return x - m_rect.xmin; + return x - rect_.xmin; } template<typename T> T get_relative_y(T y) const { - return y - m_rect.ymin; + return y - rect_.ymin; } template<typename T> bool has_coords(T x, T y) const @@ -687,12 +704,12 @@ class MemoryBuffer { template<typename T> bool has_x(T x) const { - return x >= m_rect.xmin && x < m_rect.xmax; + return x >= rect_.xmin && x < rect_.xmax; } template<typename T> bool has_y(T y) const { - return y >= m_rect.ymin && y < m_rect.ymax; + return y >= rect_.ymin && y < rect_.ymax; } /* Fast `floor(..)` functions. The caller should check result is within buffer bounds. @@ -711,18 +728,15 @@ class MemoryBuffer { void copy_single_elem_from(const MemoryBuffer *src, int channel_offset, int elem_size, - const int to_channel_offset); - void copy_rows_from(const MemoryBuffer *src, - const rcti &src_area, - const int to_x, - const int to_y); + int to_channel_offset); + void copy_rows_from(const MemoryBuffer *src, const rcti &src_area, int to_x, int to_y); void copy_elems_from(const MemoryBuffer *src, const rcti &area, - const int channel_offset, - const int elem_size, - const int to_x, - const int to_y, - const int to_channel_offset); + int channel_offset, + int elem_size, + int to_x, + int to_y, + int to_channel_offset); #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("COM:MemoryBuffer") |