Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/compositor/intern/COM_MemoryBuffer.cc')
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.cc227
1 files changed, 227 insertions, 0 deletions
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cc b/source/blender/compositor/intern/COM_MemoryBuffer.cc
new file mode 100644
index 00000000000..17a73efeab2
--- /dev/null
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.cc
@@ -0,0 +1,227 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2011, Blender Foundation.
+ */
+
+#include "COM_MemoryBuffer.h"
+
+#include "MEM_guardedalloc.h"
+
+static unsigned int determine_num_channels(DataType datatype)
+{
+ switch (datatype) {
+ case COM_DT_VALUE:
+ return COM_NUM_CHANNELS_VALUE;
+ case COM_DT_VECTOR:
+ return COM_NUM_CHANNELS_VECTOR;
+ case COM_DT_COLOR:
+ default:
+ return COM_NUM_CHANNELS_COLOR;
+ }
+}
+
+unsigned int MemoryBuffer::determineBufferSize()
+{
+ return getWidth() * getHeight();
+}
+
+int MemoryBuffer::getWidth() const
+{
+ return this->m_width;
+}
+int MemoryBuffer::getHeight() const
+{
+ return this->m_height;
+}
+
+MemoryBuffer::MemoryBuffer(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect)
+{
+ BLI_rcti_init(&this->m_rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax);
+ this->m_width = BLI_rcti_size_x(&this->m_rect);
+ this->m_height = BLI_rcti_size_y(&this->m_rect);
+ this->m_memoryProxy = memoryProxy;
+ this->m_chunkNumber = chunkNumber;
+ this->m_num_channels = determine_num_channels(memoryProxy->getDataType());
+ this->m_buffer = (float *)MEM_mallocN_aligned(
+ sizeof(float) * determineBufferSize() * this->m_num_channels, 16, "COM_MemoryBuffer");
+ this->m_state = COM_MB_ALLOCATED;
+ this->m_datatype = memoryProxy->getDataType();
+}
+
+MemoryBuffer::MemoryBuffer(MemoryProxy *memoryProxy, rcti *rect)
+{
+ BLI_rcti_init(&this->m_rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax);
+ this->m_width = BLI_rcti_size_x(&this->m_rect);
+ this->m_height = BLI_rcti_size_y(&this->m_rect);
+ this->m_memoryProxy = memoryProxy;
+ this->m_chunkNumber = -1;
+ this->m_num_channels = determine_num_channels(memoryProxy->getDataType());
+ this->m_buffer = (float *)MEM_mallocN_aligned(
+ sizeof(float) * determineBufferSize() * this->m_num_channels, 16, "COM_MemoryBuffer");
+ this->m_state = COM_MB_TEMPORARILY;
+ this->m_datatype = memoryProxy->getDataType();
+}
+MemoryBuffer::MemoryBuffer(DataType dataType, rcti *rect)
+{
+ BLI_rcti_init(&this->m_rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax);
+ this->m_width = BLI_rcti_size_x(&this->m_rect);
+ this->m_height = BLI_rcti_size_y(&this->m_rect);
+ this->m_height = this->m_rect.ymax - this->m_rect.ymin;
+ this->m_memoryProxy = nullptr;
+ this->m_chunkNumber = -1;
+ this->m_num_channels = determine_num_channels(dataType);
+ this->m_buffer = (float *)MEM_mallocN_aligned(
+ sizeof(float) * determineBufferSize() * this->m_num_channels, 16, "COM_MemoryBuffer");
+ this->m_state = COM_MB_TEMPORARILY;
+ this->m_datatype = dataType;
+}
+MemoryBuffer *MemoryBuffer::duplicate()
+{
+ MemoryBuffer *result = new MemoryBuffer(this->m_memoryProxy, &this->m_rect);
+ memcpy(result->m_buffer,
+ this->m_buffer,
+ this->determineBufferSize() * this->m_num_channels * sizeof(float));
+ return result;
+}
+void MemoryBuffer::clear()
+{
+ memset(this->m_buffer, 0, this->determineBufferSize() * this->m_num_channels * sizeof(float));
+}
+
+float MemoryBuffer::getMaximumValue()
+{
+ float result = this->m_buffer[0];
+ const unsigned int size = this->determineBufferSize();
+ unsigned int i;
+
+ const float *fp_src = this->m_buffer;
+
+ for (i = 0; i < size; i++, fp_src += this->m_num_channels) {
+ float value = *fp_src;
+ if (value > result) {
+ result = value;
+ }
+ }
+
+ return result;
+}
+
+float MemoryBuffer::getMaximumValue(rcti *rect)
+{
+ rcti rect_clamp;
+
+ /* first clamp the rect by the bounds or we get un-initialized values */
+ BLI_rcti_isect(rect, &this->m_rect, &rect_clamp);
+
+ if (!BLI_rcti_is_empty(&rect_clamp)) {
+ MemoryBuffer *temp = new MemoryBuffer(this->m_datatype, &rect_clamp);
+ temp->copyContentFrom(this);
+ float result = temp->getMaximumValue();
+ delete temp;
+ return result;
+ }
+
+ BLI_assert(0);
+ return 0.0f;
+}
+
+MemoryBuffer::~MemoryBuffer()
+{
+ if (this->m_buffer) {
+ MEM_freeN(this->m_buffer);
+ this->m_buffer = nullptr;
+ }
+}
+
+void MemoryBuffer::copyContentFrom(MemoryBuffer *otherBuffer)
+{
+ if (!otherBuffer) {
+ BLI_assert(0);
+ return;
+ }
+ unsigned int otherY;
+ unsigned int minX = MAX2(this->m_rect.xmin, otherBuffer->m_rect.xmin);
+ unsigned int maxX = MIN2(this->m_rect.xmax, otherBuffer->m_rect.xmax);
+ unsigned int minY = MAX2(this->m_rect.ymin, otherBuffer->m_rect.ymin);
+ unsigned int maxY = MIN2(this->m_rect.ymax, otherBuffer->m_rect.ymax);
+ int offset;
+ int otherOffset;
+
+ for (otherY = minY; otherY < maxY; otherY++) {
+ otherOffset = ((otherY - otherBuffer->m_rect.ymin) * otherBuffer->m_width + minX -
+ otherBuffer->m_rect.xmin) *
+ this->m_num_channels;
+ offset = ((otherY - this->m_rect.ymin) * this->m_width + minX - this->m_rect.xmin) *
+ this->m_num_channels;
+ memcpy(&this->m_buffer[offset],
+ &otherBuffer->m_buffer[otherOffset],
+ (maxX - minX) * this->m_num_channels * sizeof(float));
+ }
+}
+
+void MemoryBuffer::writePixel(int x, int y, const float color[4])
+{
+ if (x >= this->m_rect.xmin && x < this->m_rect.xmax && y >= this->m_rect.ymin &&
+ y < this->m_rect.ymax) {
+ const int offset = (this->m_width * (y - this->m_rect.ymin) + x - this->m_rect.xmin) *
+ this->m_num_channels;
+ memcpy(&this->m_buffer[offset], color, sizeof(float) * this->m_num_channels);
+ }
+}
+
+void MemoryBuffer::addPixel(int x, int y, const float color[4])
+{
+ if (x >= this->m_rect.xmin && x < this->m_rect.xmax && y >= this->m_rect.ymin &&
+ y < this->m_rect.ymax) {
+ const int offset = (this->m_width * (y - this->m_rect.ymin) + x - this->m_rect.xmin) *
+ this->m_num_channels;
+ float *dst = &this->m_buffer[offset];
+ const float *src = color;
+ for (int i = 0; i < this->m_num_channels; i++, dst++, src++) {
+ *dst += *src;
+ }
+ }
+}
+
+static void read_ewa_pixel_sampled(void *userdata, int x, int y, float result[4])
+{
+ MemoryBuffer *buffer = (MemoryBuffer *)userdata;
+ buffer->read(result, x, y);
+}
+
+void MemoryBuffer::readEWA(float *result, const float uv[2], const float derivatives[2][2])
+{
+ BLI_assert(this->m_datatype == COM_DT_COLOR);
+ float inv_width = 1.0f / (float)this->getWidth(), inv_height = 1.0f / (float)this->getHeight();
+ /* TODO(sergey): Render pipeline uses normalized coordinates and derivatives,
+ * but compositor uses pixel space. For now let's just divide the values and
+ * switch compositor to normalized space for EWA later.
+ */
+ float uv_normal[2] = {uv[0] * inv_width, uv[1] * inv_height};
+ float du_normal[2] = {derivatives[0][0] * inv_width, derivatives[0][1] * inv_height};
+ float dv_normal[2] = {derivatives[1][0] * inv_width, derivatives[1][1] * inv_height};
+
+ BLI_ewa_filter(this->getWidth(),
+ this->getHeight(),
+ false,
+ true,
+ uv_normal,
+ du_normal,
+ dv_normal,
+ read_ewa_pixel_sampled,
+ this,
+ result);
+}