From 1775ea74c152ba7cf27a8bc1f071b40992c89013 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Mon, 8 Mar 2021 13:41:52 +0100 Subject: Cleanup: Change extension .cpp to .cc --- .../blender/compositor/intern/COM_MemoryBuffer.cc | 227 +++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 source/blender/compositor/intern/COM_MemoryBuffer.cc (limited to 'source/blender/compositor/intern/COM_MemoryBuffer.cc') 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); +} -- cgit v1.2.3