From 0563280bff35652a599ff5758f76a7ac5048d728 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 15 Apr 2014 19:11:05 +0200 Subject: Compositor squashed patch reapplied Started with the MemoryBufferValue still a lot needs to be done stopped at testing the dilate/erode TILES: did some fixed for value buffer Determine image format of OpenCL device TILES: TextureNode fix TILES: moved buffer sizes to constants for easy access. TILES: fixed some nodes. still working on the defocus node TILES: fixed glare, keying, defocus, normalize, vector curves --- source/blender/compositor/CMakeLists.txt | 7 +- source/blender/compositor/COM_defines.h | 4 +- .../blender/compositor/intern/COM_ChannelInfo.cpp | 35 --- source/blender/compositor/intern/COM_ChannelInfo.h | 121 -------- .../compositor/intern/COM_ExecutionGroup.cpp | 4 +- .../compositor/intern/COM_ExecutionSystem.cpp | 10 +- .../blender/compositor/intern/COM_MemoryBuffer.cpp | 310 +++++++-------------- .../blender/compositor/intern/COM_MemoryBuffer.h | 174 +++++------- .../compositor/intern/COM_MemoryBufferColor.cpp | 291 +++++++++++++++++++ .../compositor/intern/COM_MemoryBufferColor.h | 71 +++++ .../compositor/intern/COM_MemoryBufferValue.cpp | 152 ++++++++++ .../compositor/intern/COM_MemoryBufferValue.h | 68 +++++ .../compositor/intern/COM_MemoryBufferVector.cpp | 144 ++++++++++ .../compositor/intern/COM_MemoryBufferVector.h | 67 +++++ .../blender/compositor/intern/COM_MemoryProxy.cpp | 5 +- source/blender/compositor/intern/COM_MemoryProxy.h | 16 +- .../blender/compositor/intern/COM_OpenCLDevice.cpp | 34 ++- .../blender/compositor/intern/COM_OpenCLDevice.h | 7 + .../blender/compositor/intern/COM_OutputSocket.h | 1 - .../compositor/intern/COM_SocketConnection.h | 1 - .../compositor/nodes/COM_SocketProxyNode.cpp | 9 +- .../blender/compositor/nodes/COM_TranslateNode.cpp | 4 +- .../operations/COM_AntiAliasOperation.cpp | 2 +- .../operations/COM_CompositorOperation.cpp | 6 +- .../compositor/operations/COM_ConvertOperation.cpp | 22 +- .../operations/COM_DilateErodeOperation.cpp | 28 +- .../operations/COM_FastGaussianBlurOperation.cpp | 35 ++- .../operations/COM_GaussianAlphaXBlurOperation.cpp | 7 +- .../operations/COM_GaussianAlphaYBlurOperation.cpp | 4 +- .../operations/COM_GaussianBokehBlurOperation.cpp | 6 +- .../operations/COM_GlareBaseOperation.cpp | 2 +- .../operations/COM_GlareFogGlowOperation.cpp | 18 +- .../operations/COM_GlareGhostOperation.cpp | 6 +- .../operations/COM_GlareStreaksOperation.cpp | 2 +- .../compositor/operations/COM_InpaintOperation.cpp | 4 +- .../operations/COM_KeyingBlurOperation.cpp | 4 +- .../operations/COM_KeyingClipOperation.cpp | 4 +- .../compositor/operations/COM_MapUVOperation.cpp | 12 +- .../operations/COM_NormalizeOperation.cpp | 2 +- .../operations/COM_QualityStepHelper.cpp | 26 +- .../operations/COM_ReadBufferOperation.cpp | 4 +- .../operations/COM_ReadBufferOperation.h | 2 +- .../compositor/operations/COM_RenderLayersProg.cpp | 31 +-- .../operations/COM_SetVectorOperation.cpp | 2 +- .../compositor/operations/COM_TextureOperation.cpp | 17 +- .../COM_VariableSizeBokehBlurOperation.cpp | 26 +- .../operations/COM_VectorBlurOperation.cpp | 6 +- .../operations/COM_VectorCurveOperation.cpp | 1 - .../compositor/operations/COM_WrapOperation.cpp | 2 +- .../compositor/operations/COM_WrapOperation.h | 2 +- .../operations/COM_WriteBufferOperation.cpp | 22 +- .../operations/COM_WriteBufferOperation.h | 2 +- 52 files changed, 1175 insertions(+), 667 deletions(-) delete mode 100644 source/blender/compositor/intern/COM_ChannelInfo.cpp delete mode 100644 source/blender/compositor/intern/COM_ChannelInfo.h create mode 100644 source/blender/compositor/intern/COM_MemoryBufferColor.cpp create mode 100644 source/blender/compositor/intern/COM_MemoryBufferColor.h create mode 100644 source/blender/compositor/intern/COM_MemoryBufferValue.cpp create mode 100644 source/blender/compositor/intern/COM_MemoryBufferValue.h create mode 100644 source/blender/compositor/intern/COM_MemoryBufferVector.cpp create mode 100644 source/blender/compositor/intern/COM_MemoryBufferVector.h diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index cbb1017facd..1ab0820bd76 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -80,7 +80,10 @@ set(SRC intern/COM_MemoryProxy.h intern/COM_MemoryBuffer.cpp intern/COM_MemoryBuffer.h - intern/COM_WorkScheduler.cpp + intern/COM_MemoryBufferColor + intern/COM_MemoryBufferVector + intern/COM_MemoryBufferValue + intern/COM_WorkScheduler.cpp intern/COM_WorkScheduler.h intern/COM_WorkPackage.cpp intern/COM_WorkPackage.h @@ -96,8 +99,6 @@ set(SRC intern/COM_OpenCLDevice.h intern/COM_CompositorContext.cpp intern/COM_CompositorContext.h - intern/COM_ChannelInfo.cpp - intern/COM_ChannelInfo.h intern/COM_SingleThreadedNodeOperation.cpp intern/COM_SingleThreadedNodeOperation.h intern/COM_Debug.cpp diff --git a/source/blender/compositor/COM_defines.h b/source/blender/compositor/COM_defines.h index 6c07aadc3aa..f3e224a3601 100644 --- a/source/blender/compositor/COM_defines.h +++ b/source/blender/compositor/COM_defines.h @@ -105,7 +105,9 @@ typedef enum OrderOfChunks { #define COM_RULE_OF_THIRDS_DIVIDER 100.0f -#define COM_NUMBER_OF_CHANNELS 4 +#define COM_NO_CHANNELS_VALUE 1 +#define COM_NO_CHANNELS_VECTOR 3 +#define COM_NO_CHANNELS_COLOR 4 #define COM_BLUR_BOKEH_PIXELS 512 diff --git a/source/blender/compositor/intern/COM_ChannelInfo.cpp b/source/blender/compositor/intern/COM_ChannelInfo.cpp deleted file mode 100644 index 557075cdc80..00000000000 --- a/source/blender/compositor/intern/COM_ChannelInfo.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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. - * - * Contributor: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_ChannelInfo.h" -#include "COM_defines.h" -#include - -/** - * @brief create new ChannelInfo instance and sets the defaults. - */ -ChannelInfo::ChannelInfo() -{ - this->m_number = 0; - this->m_premultiplied = true; - this->m_type = COM_CT_UNUSED; -} diff --git a/source/blender/compositor/intern/COM_ChannelInfo.h b/source/blender/compositor/intern/COM_ChannelInfo.h deleted file mode 100644 index 44664442359..00000000000 --- a/source/blender/compositor/intern/COM_ChannelInfo.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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. - * - * Contributor: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_ChannelInfo_h -#define _COM_ChannelInfo_h - -#include -#include "BKE_text.h" -#include -#include "DNA_node_types.h" -#include "BLI_rect.h" - -using namespace std; - -/** - * @brief List of possible channel types - * @ingroup Model - */ -typedef enum ChannelType { - COM_CT_ColorComponent /** @brief this channel is contains color information. Specific used is determined by channelnumber, and in the future color space */, - COM_CT_Alpha /** @brief this channel is contains transparency value */, - COM_CT_Value /** @brief this channel is contains a value */, - COM_CT_X /** @brief this channel is contains a X value */, - COM_CT_Y /** @brief this channel is contains a Y value */, - COM_CT_Z /** @brief this channel is contains a Z value */, - COM_CT_W /** @brief this channel is contains a W value */, - COM_CT_UNUSED /** @brief this channel is unused */ -} ChannelType; - -/** - * @brief ChannelInfo holds information about a channel. - * - * Channels are transported from node to node via a SocketConnection. - * ChannelInfo holds specific setting of these channels in order that the to-node of the connection - * Can handle specific logic per channel setting. - * - * @note currently this is not used, but a future place to implement color spacing and other things. - * @ingroup Model - */ -class ChannelInfo { -private: - /** - * @brief the channel number, in the connection. [0-3] - */ - int m_number; - - /** - * @brief type of channel - */ - ChannelType m_type; - - /** - * @brieg Is this value in this channel premultiplied with its alpha - * @note only valid if type = ColorComponent; - */ - bool m_premultiplied; - -// /** -// * Color space of this value. -// * only valid when type = ColorComponent; -// */ -// string colorspacename; - -public: - /** - * @brief creates a new ChannelInfo and set default values - */ - ChannelInfo(); - - /** - * @brief set the index of this channel in the SocketConnection - */ - void setNumber(const int number) { this->m_number = number; } - - /** - * @brief get the index of this channel in the SocketConnection - */ - const int getNumber() const { return this->m_number; } - - /** - * @brief set the type of channel - */ - void setType(const ChannelType type) { this->m_type = type; } - - /** - * @brief get the type of channel - */ - const ChannelType getType() const { return this->m_type; } - - /** - * @brief set the premultiplicatioin of this channel - */ - void setPremultiplied(const bool premultiplied) { this->m_premultiplied = premultiplied; } - - /** - * @brief is this channel premultiplied - */ - const bool isPremultiplied() const { return this->m_premultiplied; } -}; - - -#endif diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cpp b/source/blender/compositor/intern/COM_ExecutionGroup.cpp index a2e4e809a3d..a8cd9284087 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.cpp +++ b/source/blender/compositor/intern/COM_ExecutionGroup.cpp @@ -416,7 +416,7 @@ MemoryBuffer **ExecutionGroup::getInputBuffersOpenCL(int chunkNumber) MemoryBuffer *ExecutionGroup::constructConsolidatedMemoryBuffer(MemoryProxy *memoryProxy, rcti *rect) { MemoryBuffer *imageBuffer = memoryProxy->getBuffer(); - MemoryBuffer *result = new MemoryBuffer(memoryProxy, rect); + MemoryBuffer *result = MemoryBuffer::create(memoryProxy, rect); result->copyContentFrom(imageBuffer); return result; } @@ -509,7 +509,7 @@ MemoryBuffer *ExecutionGroup::allocateOutputBuffer(int chunkNumber, rcti *rect) NodeOperation *operation = this->getOutputNodeOperation(); if (operation->isWriteBufferOperation()) { WriteBufferOperation *writeOperation = (WriteBufferOperation *)operation; - MemoryBuffer *buffer = new MemoryBuffer(writeOperation->getMemoryProxy(), rect); + MemoryBuffer *buffer = MemoryBuffer::create(writeOperation->getMemoryProxy(), rect); return buffer; } return NULL; diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp index 088232481d0..7bdec355a95 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp @@ -101,7 +101,7 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, Scene *scene, bNodeTree *editin } } -// DebugInfo::graphviz(this); + DebugInfo::graphviz(this); } ExecutionSystem::~ExecutionSystem() @@ -219,13 +219,13 @@ void ExecutionSystem::addReadWriteBufferOperations(NodeOperation *operation) OutputSocket *fromsocket = connection->getFromSocket(); WriteBufferOperation *writeoperation = fromsocket->findAttachedWriteBufferOperation(); if (writeoperation == NULL) { - writeoperation = new WriteBufferOperation(); + writeoperation = new WriteBufferOperation(fromsocket->getDataType()); writeoperation->setbNodeTree(this->getContext().getbNodeTree()); this->addOperation(writeoperation); ExecutionSystemHelper::addLink(this->getConnections(), fromsocket, writeoperation->getInputSocket(0)); writeoperation->readResolutionFromInputSocket(); } - ReadBufferOperation *readoperation = new ReadBufferOperation(); + ReadBufferOperation *readoperation = new ReadBufferOperation(fromsocket->getDataType()); readoperation->setMemoryProxy(writeoperation->getMemoryProxy()); connection->setFromSocket(readoperation->getOutputSocket()); readoperation->getOutputSocket()->addConnection(connection); @@ -256,7 +256,7 @@ void ExecutionSystem::addReadWriteBufferOperations(NodeOperation *operation) } /* if no write buffer operation exists yet, create a new one */ if (!writeOperation) { - writeOperation = new WriteBufferOperation(); + writeOperation = new WriteBufferOperation(outputsocket->getDataType()); writeOperation->setbNodeTree(this->getContext().getbNodeTree()); this->addOperation(writeOperation); ExecutionSystemHelper::addLink(this->getConnections(), outputsocket, writeOperation->getInputSocket(0)); @@ -269,7 +269,7 @@ void ExecutionSystem::addReadWriteBufferOperations(NodeOperation *operation) if (connection->getToNode() == writeOperation) continue; - ReadBufferOperation *readoperation = new ReadBufferOperation(); + ReadBufferOperation *readoperation = new ReadBufferOperation(outputsocket->getDataType()); readoperation->setMemoryProxy(writeOperation->getMemoryProxy()); connection->setFromSocket(readoperation->getOutputSocket()); readoperation->getOutputSocket()->addConnection(connection); diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cpp b/source/blender/compositor/intern/COM_MemoryBuffer.cpp index 65cd74a971f..32229e2d912 100644 --- a/source/blender/compositor/intern/COM_MemoryBuffer.cpp +++ b/source/blender/compositor/intern/COM_MemoryBuffer.cpp @@ -23,8 +23,11 @@ #include "COM_MemoryBuffer.h" #include "MEM_guardedalloc.h" //#include "BKE_global.h" +#include "COM_MemoryBufferColor.h" +#include "COM_MemoryBufferVector.h" +#include "COM_MemoryBufferValue.h" -unsigned int MemoryBuffer::determineBufferSize() +unsigned int MemoryBuffer::determineBufferSize() const { return getWidth() * getHeight(); } @@ -38,38 +41,109 @@ int MemoryBuffer::getHeight() const return this->m_rect.ymax - this->m_rect.ymin; } -MemoryBuffer::MemoryBuffer(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect) +MemoryBuffer* MemoryBuffer::create(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect) { + DataType type; + type = memoryProxy->getDataType(); + + if (type == COM_DT_VALUE) { + return new MemoryBufferValue(memoryProxy, chunkNumber, rect); + } + else if (type == COM_DT_VECTOR) { + return new MemoryBufferVector(memoryProxy, chunkNumber, rect); + } + else { + return new MemoryBufferColor(memoryProxy, chunkNumber, rect); + } +} + +MemoryBuffer* MemoryBuffer::create(MemoryProxy *memoryProxy, rcti *rect) { + DataType type; + type = memoryProxy->getDataType(); + + if (type==COM_DT_VALUE){ + return new MemoryBufferValue(memoryProxy, rect); + } + else if (type == COM_DT_VECTOR) { + return new MemoryBufferVector(memoryProxy, rect); + } + else { + return new MemoryBufferColor(memoryProxy, rect); + } +} + +MemoryBuffer* MemoryBuffer::create(DataType datatype, rcti *rect) { + if (datatype==COM_DT_VALUE){ + return new MemoryBufferValue(datatype, rect); + } + else if (datatype == COM_DT_VECTOR) { + return new MemoryBufferVector(datatype, rect); + } + else { + return new MemoryBufferColor(datatype, rect); + } +} + +MemoryBuffer::MemoryBuffer(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect, unsigned int no_channels) { BLI_rcti_init(&this->m_rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax); this->m_memoryProxy = memoryProxy; this->m_chunkNumber = chunkNumber; - this->m_buffer = (float *)MEM_mallocN(sizeof(float) * determineBufferSize() * COM_NUMBER_OF_CHANNELS, "COM_MemoryBuffer"); + this->m_buffer = (float *)MEM_mallocN(sizeof(float) * determineBufferSize() * no_channels, "COM_MemoryBuffer"); this->m_state = COM_MB_ALLOCATED; - this->m_datatype = COM_DT_COLOR; this->m_chunkWidth = this->m_rect.xmax - this->m_rect.xmin; + this->m_no_channels = no_channels; } -MemoryBuffer::MemoryBuffer(MemoryProxy *memoryProxy, rcti *rect) +MemoryBuffer::MemoryBuffer(MemoryProxy *memoryProxy, rcti *rect, unsigned int no_channels) { BLI_rcti_init(&this->m_rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax); this->m_memoryProxy = memoryProxy; this->m_chunkNumber = -1; - this->m_buffer = (float *)MEM_mallocN(sizeof(float) * determineBufferSize() * COM_NUMBER_OF_CHANNELS, "COM_MemoryBuffer"); + this->m_buffer = (float *)MEM_mallocN(sizeof(float) * determineBufferSize() * no_channels, "COM_MemoryBuffer"); this->m_state = COM_MB_TEMPORARILY; - this->m_datatype = COM_DT_COLOR; this->m_chunkWidth = this->m_rect.xmax - this->m_rect.xmin; + this->m_no_channels = no_channels; } -MemoryBuffer *MemoryBuffer::duplicate() -{ - MemoryBuffer *result = new MemoryBuffer(this->m_memoryProxy, &this->m_rect); - memcpy(result->m_buffer, this->m_buffer, this->determineBufferSize() * COM_NUMBER_OF_CHANNELS * sizeof(float)); - return result; + +MemoryBuffer::MemoryBuffer(DataType datatype, rcti *rect, unsigned int no_channels) { + BLI_rcti_init(&this->m_rect, rect->xmin, rect->xmax, rect->ymin, rect->ymax); + this->m_memoryProxy = NULL; + this->m_chunkNumber = -1; + this->m_buffer = (float *)MEM_mallocN(sizeof(float) * determineBufferSize() * no_channels, "COM_MemoryBuffer"); + this->m_state = COM_MB_TEMPORARILY; + this->m_chunkWidth = this->m_rect.xmax - this->m_rect.xmin; + this->m_no_channels = no_channels; } + void MemoryBuffer::clear() { - memset(this->m_buffer, 0, this->determineBufferSize() * COM_NUMBER_OF_CHANNELS * sizeof(float)); + memset(this->m_buffer, 0, this->determineBufferSize() * this->m_no_channels * sizeof(float)); } +void MemoryBuffer::copyContentFrom(MemoryBuffer *otherBuffer) +{ + if (!otherBuffer) { + BLI_assert(0); + return; + } + unsigned int otherY; + unsigned int minX = max(this->m_rect.xmin, otherBuffer->m_rect.xmin); + unsigned int maxX = min(this->m_rect.xmax, otherBuffer->m_rect.xmax); + unsigned int minY = max(this->m_rect.ymin, otherBuffer->m_rect.ymin); + unsigned int maxY = min(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_chunkWidth + minX - otherBuffer->m_rect.xmin) * this->m_no_channels; + offset = ((otherY - this->m_rect.ymin) * this->m_chunkWidth + minX - this->m_rect.xmin) * this->m_no_channels; + memcpy(&this->m_buffer[offset], &otherBuffer->m_buffer[otherOffset], (maxX - minX) * this->m_no_channels * sizeof(float)); + } +} + + +// TODO: this method needs to be checked! At Mind 2014 float *MemoryBuffer::convertToValueBuffer() { const unsigned int size = this->determineBufferSize(); @@ -80,29 +154,16 @@ float *MemoryBuffer::convertToValueBuffer() const float *fp_src = this->m_buffer; float *fp_dst = result; - for (i = 0; i < size; i++, fp_dst++, fp_src += COM_NUMBER_OF_CHANNELS) { + for (i = 0; i < size; i++, fp_dst++, fp_src += COM_NO_CHANNELS_COLOR) { *fp_dst = *fp_src; } return result; } -float MemoryBuffer::getMaximumValue() +float MemoryBuffer::getMaximumValue() const { - 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 += COM_NUMBER_OF_CHANNELS) { - float value = *fp_src; - if (value > result) { - result = value; - } - } - - return result; + return 0.0f; } float MemoryBuffer::getMaximumValue(rcti *rect) @@ -113,7 +174,7 @@ float MemoryBuffer::getMaximumValue(rcti *rect) BLI_rcti_isect(rect, &this->m_rect, &rect_clamp); if (!BLI_rcti_is_empty(&rect_clamp)) { - MemoryBuffer *temp = new MemoryBuffer(NULL, &rect_clamp); + MemoryBuffer *temp = MemoryBuffer::create(COM_DT_VALUE, &rect_clamp); temp->copyContentFrom(this); float result = temp->getMaximumValue(); delete temp; @@ -128,195 +189,12 @@ float MemoryBuffer::getMaximumValue(rcti *rect) MemoryBuffer::~MemoryBuffer() { if (this->m_buffer) { - MEM_freeN(this->m_buffer); + MEM_freeN(this->m_buffer); this->m_buffer = NULL; } } -void MemoryBuffer::copyContentFrom(MemoryBuffer *otherBuffer) -{ - if (!otherBuffer) { - BLI_assert(0); - return; - } - unsigned int otherY; - unsigned int minX = max(this->m_rect.xmin, otherBuffer->m_rect.xmin); - unsigned int maxX = min(this->m_rect.xmax, otherBuffer->m_rect.xmax); - unsigned int minY = max(this->m_rect.ymin, otherBuffer->m_rect.ymin); - unsigned int maxY = min(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_chunkWidth + minX - otherBuffer->m_rect.xmin) * COM_NUMBER_OF_CHANNELS; - offset = ((otherY - this->m_rect.ymin) * this->m_chunkWidth + minX - this->m_rect.xmin) * COM_NUMBER_OF_CHANNELS; - memcpy(&this->m_buffer[offset], &otherBuffer->m_buffer[otherOffset], (maxX - minX) * COM_NUMBER_OF_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_chunkWidth * (y - this->m_rect.ymin) + x - this->m_rect.xmin) * COM_NUMBER_OF_CHANNELS; - copy_v4_v4(&this->m_buffer[offset], color); - } -} - -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_chunkWidth * (y - this->m_rect.ymin) + x - this->m_rect.xmin) * COM_NUMBER_OF_CHANNELS; - add_v4_v4(&this->m_buffer[offset], color); - } +const int MemoryBuffer::get_no_channels() const { + return this->m_no_channels; } - -// table of (exp(ar) - exp(a)) / (1 - exp(a)) for r in range [0, 1] and a = -2 -// used instead of actual gaussian, otherwise at high texture magnifications circular artifacts are visible -#define EWA_MAXIDX 255 -static const float EWA_WTS[EWA_MAXIDX + 1] = { - 1.f, 0.990965f, 0.982f, 0.973105f, 0.96428f, 0.955524f, 0.946836f, 0.938216f, 0.929664f, - 0.921178f, 0.912759f, 0.904405f, 0.896117f, 0.887893f, 0.879734f, 0.871638f, 0.863605f, - 0.855636f, 0.847728f, 0.839883f, 0.832098f, 0.824375f, 0.816712f, 0.809108f, 0.801564f, - 0.794079f, 0.786653f, 0.779284f, 0.771974f, 0.76472f, 0.757523f, 0.750382f, 0.743297f, - 0.736267f, 0.729292f, 0.722372f, 0.715505f, 0.708693f, 0.701933f, 0.695227f, 0.688572f, - 0.68197f, 0.67542f, 0.66892f, 0.662471f, 0.656073f, 0.649725f, 0.643426f, 0.637176f, - 0.630976f, 0.624824f, 0.618719f, 0.612663f, 0.606654f, 0.600691f, 0.594776f, 0.588906f, - 0.583083f, 0.577305f, 0.571572f, 0.565883f, 0.56024f, 0.55464f, 0.549084f, 0.543572f, - 0.538102f, 0.532676f, 0.527291f, 0.521949f, 0.516649f, 0.511389f, 0.506171f, 0.500994f, - 0.495857f, 0.490761f, 0.485704f, 0.480687f, 0.475709f, 0.470769f, 0.465869f, 0.461006f, - 0.456182f, 0.451395f, 0.446646f, 0.441934f, 0.437258f, 0.432619f, 0.428017f, 0.42345f, - 0.418919f, 0.414424f, 0.409963f, 0.405538f, 0.401147f, 0.39679f, 0.392467f, 0.388178f, - 0.383923f, 0.379701f, 0.375511f, 0.371355f, 0.367231f, 0.363139f, 0.359079f, 0.355051f, - 0.351055f, 0.347089f, 0.343155f, 0.339251f, 0.335378f, 0.331535f, 0.327722f, 0.323939f, - 0.320186f, 0.316461f, 0.312766f, 0.3091f, 0.305462f, 0.301853f, 0.298272f, 0.294719f, - 0.291194f, 0.287696f, 0.284226f, 0.280782f, 0.277366f, 0.273976f, 0.270613f, 0.267276f, - 0.263965f, 0.26068f, 0.257421f, 0.254187f, 0.250979f, 0.247795f, 0.244636f, 0.241502f, - 0.238393f, 0.235308f, 0.232246f, 0.229209f, 0.226196f, 0.223206f, 0.220239f, 0.217296f, - 0.214375f, 0.211478f, 0.208603f, 0.20575f, 0.20292f, 0.200112f, 0.197326f, 0.194562f, - 0.191819f, 0.189097f, 0.186397f, 0.183718f, 0.18106f, 0.178423f, 0.175806f, 0.17321f, - 0.170634f, 0.168078f, 0.165542f, 0.163026f, 0.16053f, 0.158053f, 0.155595f, 0.153157f, - 0.150738f, 0.148337f, 0.145955f, 0.143592f, 0.141248f, 0.138921f, 0.136613f, 0.134323f, - 0.132051f, 0.129797f, 0.12756f, 0.125341f, 0.123139f, 0.120954f, 0.118786f, 0.116635f, - 0.114501f, 0.112384f, 0.110283f, 0.108199f, 0.106131f, 0.104079f, 0.102043f, 0.100023f, - 0.0980186f, 0.09603f, 0.094057f, 0.0920994f, 0.0901571f, 0.08823f, 0.0863179f, 0.0844208f, - 0.0825384f, 0.0806708f, 0.0788178f, 0.0769792f, 0.0751551f, 0.0733451f, 0.0715493f, 0.0697676f, - 0.0679997f, 0.0662457f, 0.0645054f, 0.0627786f, 0.0610654f, 0.0593655f, 0.0576789f, 0.0560055f, - 0.0543452f, 0.0526979f, 0.0510634f, 0.0494416f, 0.0478326f, 0.0462361f, 0.0446521f, 0.0430805f, - 0.0415211f, 0.039974f, 0.0384389f, 0.0369158f, 0.0354046f, 0.0339052f, 0.0324175f, 0.0309415f, - 0.029477f, 0.0280239f, 0.0265822f, 0.0251517f, 0.0237324f, 0.0223242f, 0.020927f, 0.0195408f, - 0.0181653f, 0.0168006f, 0.0154466f, 0.0141031f, 0.0127701f, 0.0114476f, 0.0101354f, 0.00883339f, - 0.00754159f, 0.00625989f, 0.00498819f, 0.00372644f, 0.00247454f, 0.00123242f, 0.f -}; - -static void ellipse_bounds(float A, float B, float C, float F, float &xmax, float &ymax) -{ - float denom = 4.0f * A * C - B * B; - if (denom > 0.0f && A != 0.0f && C != 0.0f) { - xmax = sqrtf(F) / (2.0f * A) * (sqrtf(F * (4.0f * A - B * B / C)) + B * B * sqrtf(F / (C * denom))); - ymax = sqrtf(F) / (2.0f * C) * (sqrtf(F * (4.0f * C - B * B / A)) + B * B * sqrtf(F / (A * denom))); - } - else { - xmax = 0.0f; - ymax = 0.0f; - } -} - -static void ellipse_params(float Ux, float Uy, float Vx, float Vy, - float &A, float &B, float &C, float &F, float &umax, float &vmax) -{ - A = Vx * Vx + Vy * Vy; - B = -2.0f * (Ux * Vx + Uy * Vy); - C = Ux * Ux + Uy * Uy; - F = A * C - B * B * 0.25f; - - float factor = (F != 0.0f ? (float)(EWA_MAXIDX + 1) / F : 0.0f); - A *= factor; - B *= factor; - C *= factor; - F = (float)(EWA_MAXIDX + 1); - - ellipse_bounds(A, B, C, sqrtf(F), umax, vmax); -} - -/** - * Filtering method based on - * "Creating raster omnimax images from multiple perspective views using the elliptical weighted average filter" - * by Ned Greene and Paul S. Heckbert (1986) - */ -void MemoryBuffer::readEWA(float result[4], const float uv[2], const float derivatives[2][2], PixelSampler sampler) -{ - zero_v4(result); - int width = this->getWidth(), height = this->getHeight(); - if (width == 0 || height == 0) - return; - - float u = uv[0], v = uv[1]; - float Ux = derivatives[0][0], Vx = derivatives[1][0], Uy = derivatives[0][1], Vy = derivatives[1][1]; - float A, B, C, F, ue, ve; - ellipse_params(Ux, Uy, Vx, Vy, A, B, C, F, ue, ve); - - /* Note: highly eccentric ellipses can lead to large texture space areas to filter! - * This is limited somewhat by the EWA_WTS size in the loop, but a nicer approach - * could be the one found in - * "High Quality Elliptical Texture Filtering on GPU" - * by Pavlos Mavridis and Georgios Papaioannou - * in which the eccentricity of the ellipse is clamped. - */ - - int U0 = (int)u; - int V0 = (int)v; - /* pixel offset for interpolation */ - float ufac = u - floorf(u), vfac = v - floorf(v); - /* filter size */ - int u1 = (int)(u - ue); - int u2 = (int)(u + ue); - int v1 = (int)(v - ve); - int v2 = (int)(v + ve); - - /* sane clamping to avoid unnecessarily huge loops */ - /* note: if eccentricity gets clamped (see above), - * the ue/ve limits can also be lowered accordingly - */ - if (U0 - u1 > EWA_MAXIDX) u1 = U0 - EWA_MAXIDX; - if (u2 - U0 > EWA_MAXIDX) u2 = U0 + EWA_MAXIDX; - if (V0 - v1 > EWA_MAXIDX) v1 = V0 - EWA_MAXIDX; - if (v2 - V0 > EWA_MAXIDX) v2 = V0 + EWA_MAXIDX; - - float DDQ = 2.0f * A; - float U = u1 - U0; - float ac1 = A * (2.0f * U + 1.0f); - float ac2 = A * U * U; - float BU = B * U; - - float sum = 0.0f; - for (int v = v1; v <= v2; ++v) { - float V = v - V0; - - float DQ = ac1 + B * V; - float Q = (C * V + BU) * V + ac2; - for (int u = u1; u <= u2; ++u) { - if (Q < F) { - float tc[4]; - const float wt = EWA_WTS[CLAMPIS((int)Q, 0, EWA_MAXIDX)]; - switch (sampler) { - case COM_PS_NEAREST: read(tc, u, v); break; - case COM_PS_BILINEAR: readBilinear(tc, (float)u + ufac, (float)v + vfac); break; - case COM_PS_BICUBIC: readBilinear(tc, (float)u + ufac, (float)v + vfac); break; /* XXX no readBicubic method yet */ - default: zero_v4(tc); break; - } - madd_v4_v4fl(result, tc, wt); - sum += wt; - } - Q += DQ; - DQ += DDQ; - } - } - - mul_v4_fl(result, (sum != 0.0f ? 1.0f / sum : 0.0f)); -} diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h index 521e3c6231e..83889c96f55 100644 --- a/source/blender/compositor/intern/COM_MemoryBuffer.h +++ b/source/blender/compositor/intern/COM_MemoryBuffer.h @@ -60,57 +60,84 @@ class MemoryProxy; 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 + * brief refers to the chunknumber within the executiongroup where related to the MemoryProxy + * @see memoryProxy */ - DataType m_datatype; + unsigned int m_chunkNumber; /** - * @brief region of this buffer inside relative to the MemoryProxy + * @brief state of the buffer */ - rcti m_rect; - + MemoryBufferState m_state; + /** - * brief refers to the chunknumber within the executiongroup where related to the MemoryProxy - * @see memoryProxy + * @brief the number of channels that form a single pixel in this buffer */ - unsigned int m_chunkNumber; + unsigned int m_no_channels; + +protected: /** * @brief width of the chunk */ unsigned int m_chunkWidth; - + /** - * @brief state of the buffer + * @brief region of this buffer inside relative to the MemoryProxy */ - MemoryBufferState m_state; + rcti m_rect; + /** + * @brief proxy of the memory (same for all chunks in the same buffer) + */ + MemoryProxy *m_memoryProxy; + /** * @brief the actual float buffer/data */ float *m_buffer; -public: /** * @brief construct new MemoryBuffer for a chunk + * + * @param no_channels Number of channels that must be allocated for every pixel */ - MemoryBuffer(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect); + MemoryBuffer(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect, unsigned int no_channels); /** * @brief construct new temporarily MemoryBuffer for an area + * + * @param no_channels Number of channels that must be allocated for every pixel */ - MemoryBuffer(MemoryProxy *memoryProxy, rcti *rect); - + MemoryBuffer(MemoryProxy *memoryProxy, rcti *rect, unsigned int no_channels); + + /** + * @brief construct new temporarily MemoryBuffer for an area + * + * @param no_channels Number of channels that must be allocated for every pixel + */ + MemoryBuffer(DataType datatype, rcti *rect, unsigned int no_channels); +public: + /** + * @brief factory method for the constructor, selecting the right subclass + */ + static MemoryBuffer* create(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect); + /** + * @brief factory method for the constructor, selecting the right subclass, creating a temporarily buffer + */ + static MemoryBuffer* create(MemoryProxy *memoryProxy, rcti *rect); + + /** + * @brief factory method for the constructor, selecting the right subclass, creating a temporarily buffer + */ + static MemoryBuffer* create(DataType datatype, rcti *rect); + + /** * @brief destructor */ - ~MemoryBuffer(); + virtual ~MemoryBuffer(); /** * @brief read the ChunkNumber of this MemoryBuffer @@ -163,89 +190,24 @@ public: } } - inline void read(float result[4], int x, int y, + virtual 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 */ - zero_v4(result); - } - else { - wrap_pixel(x, y, extend_x, extend_y); - const int offset = (this->m_chunkWidth * y + x) * COM_NUMBER_OF_CHANNELS; - copy_v4_v4(result, &this->m_buffer[offset]); - } - } - - inline void readNoCheck(float result[4], int x, int y, - MemoryBufferExtend extend_x = COM_MB_CLIP, - MemoryBufferExtend extend_y = COM_MB_CLIP) - { - wrap_pixel(x, y, extend_x, extend_y); - const int offset = (this->m_chunkWidth * y + x) * COM_NUMBER_OF_CHANNELS; + MemoryBufferExtend extend_y = COM_MB_CLIP) = 0; - BLI_assert(offset >= 0); - BLI_assert(offset < this->determineBufferSize() * COM_NUMBER_OF_CHANNELS); - BLI_assert(!(extend_x == COM_MB_CLIP && (x < m_rect.xmin || x >= m_rect.xmax)) && - !(extend_y == COM_MB_CLIP && (y < m_rect.ymin || y >= 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)); -#endif + virtual void readNoCheck(float *result, int x, int y, + MemoryBufferExtend extend_x = COM_MB_CLIP, + MemoryBufferExtend extend_y = COM_MB_CLIP) = 0; - copy_v4_v4(result, &this->m_buffer[offset]); - } - - 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[4], float x, float y, + + virtual void writePixel(int x, int y, const float *color) = 0; + virtual void addPixel(int x, int y, const float *color) = 0; + virtual void readBilinear(float *result, float x, float y, MemoryBufferExtend extend_x = COM_MB_CLIP, - MemoryBufferExtend extend_y = COM_MB_CLIP) - { - int x1 = floor(x); - int y1 = floor(y); - int x2 = x1 + 1; - int y2 = y1 + 1; - wrap_pixel(x1, y1, extend_x, extend_y); - wrap_pixel(x2, y2, extend_x, extend_y); - - float valuex = x - x1; - float valuey = y - y1; - float mvaluex = 1.0f - valuex; - float mvaluey = 1.0f - valuey; - - float color1[4]; - float color2[4]; - float color3[4]; - float color4[4]; - - read(color1, x1, y1); - read(color2, x1, y2); - read(color3, x2, y1); - read(color4, x2, y2); - - color1[0] = color1[0] * mvaluey + color2[0] * valuey; - color1[1] = color1[1] * mvaluey + color2[1] * valuey; - color1[2] = color1[2] * mvaluey + color2[2] * valuey; - color1[3] = color1[3] * mvaluey + color2[3] * valuey; + MemoryBufferExtend extend_y = COM_MB_CLIP) = 0; - color3[0] = color3[0] * mvaluey + color4[0] * valuey; - color3[1] = color3[1] * mvaluey + color4[1] * valuey; - color3[2] = color3[2] * mvaluey + color4[2] * valuey; - color3[3] = color3[3] * mvaluey + color4[3] * valuey; - result[0] = color1[0] * mvaluex + color3[0] * valuex; - result[1] = color1[1] * mvaluex + color3[1] * valuex; - result[2] = color1[2] * mvaluex + color3[2] * valuex; - result[3] = color1[3] * mvaluex + color3[3] * valuex; - } - - void readEWA(float result[4], const float uv[2], const float derivatives[2][2], PixelSampler sampler); + virtual void readEWA(float result[4], const float uv[2], const float derivatives[2][2], PixelSampler sampler) {} /** * @brief is this MemoryBuffer a temporarily buffer (based on an area, not on a chunk) @@ -281,13 +243,23 @@ public: */ void clear(); - MemoryBuffer *duplicate(); + virtual MemoryBuffer *duplicate() = 0; float *convertToValueBuffer(); - float getMaximumValue(); + virtual float getMaximumValue() const; float getMaximumValue(rcti *rect); -private: - unsigned int determineBufferSize(); + + /** + * @brief return the number of channels that form a single pixel. + * + * Value = 1 + * Vector= 3 + * Color = 4 + */ + const int get_no_channels() const; + +protected: + unsigned int determineBufferSize() const; #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("COM:MemoryBuffer") diff --git a/source/blender/compositor/intern/COM_MemoryBufferColor.cpp b/source/blender/compositor/intern/COM_MemoryBufferColor.cpp new file mode 100644 index 00000000000..82ea320ce77 --- /dev/null +++ b/source/blender/compositor/intern/COM_MemoryBufferColor.cpp @@ -0,0 +1,291 @@ +/* + * Copyright 2014, Blender Foundation. + * + * 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. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + */ + +#include "COM_MemoryBufferColor.h" + +#define NUMBER_OF_CHANNELS COM_NO_CHANNELS_COLOR + +MemoryBufferColor::MemoryBufferColor(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect): + MemoryBuffer(memoryProxy, chunkNumber, rect, NUMBER_OF_CHANNELS) +{ +} + +MemoryBufferColor::MemoryBufferColor(MemoryProxy *memoryProxy, rcti *rect) : + MemoryBuffer(memoryProxy, rect, NUMBER_OF_CHANNELS) +{ +} + +MemoryBufferColor::MemoryBufferColor(DataType datatype, rcti *rect) : + MemoryBuffer(datatype, rect, NUMBER_OF_CHANNELS) { +} + + +MemoryBuffer *MemoryBufferColor::duplicate() +{ + MemoryBufferColor *result = new MemoryBufferColor(this->m_memoryProxy, &this->m_rect); + memcpy(result->getBuffer(), this->getBuffer(), this->determineBufferSize() * NUMBER_OF_CHANNELS * sizeof(float)); + return result; +} + +// --- write pixels --- +void MemoryBufferColor::writePixel(int x, int y, const float *color) +{ + 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_chunkWidth * (y - this->m_rect.ymin) + x - this->m_rect.xmin) * NUMBER_OF_CHANNELS; + copy_v4_v4(&this->m_buffer[offset], color); + } +} + +void MemoryBufferColor::addPixel(int x, int y, const float *color) +{ + 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_chunkWidth * (y - this->m_rect.ymin) + x - this->m_rect.xmin) * NUMBER_OF_CHANNELS; + add_v4_v4(&this->m_buffer[offset], color); + } +} + +// --- SAMPLERS --- +inline void MemoryBufferColor::read(float *result, int x, int y, + MemoryBufferExtend extend_x, + MemoryBufferExtend extend_y) +{ + 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 */ + zero_v4(result); + } + else + { + wrap_pixel(x, y, extend_x, extend_y); + const int offset = (this->m_chunkWidth * y + x) * NUMBER_OF_CHANNELS; + copy_v4_v4(result, &this->m_buffer[offset]); + } +} + +inline void MemoryBufferColor::readNoCheck(float *result, int x, int y, + MemoryBufferExtend extend_x, + MemoryBufferExtend extend_y) +{ + + wrap_pixel(x, y, extend_x, extend_y); + const int offset = (this->m_chunkWidth * y + x) * NUMBER_OF_CHANNELS; + + BLI_assert(offset >= 0); + BLI_assert(offset < this->determineBufferSize() * NUMBER_OF_CHANNELS); + BLI_assert(!(extend_x == COM_MB_CLIP && (x < m_rect.xmin || x >= m_rect.xmax)) && + !(extend_y == COM_MB_CLIP && (y < m_rect.ymin || y >= m_rect.ymax))); + + copy_v4_v4(result, &this->m_buffer[offset]); +} + +inline void MemoryBufferColor::readBilinear(float *result, float x, float y, + MemoryBufferExtend extend_x, + MemoryBufferExtend extend_y) +{ + int x1 = floor(x); + int y1 = floor(y); + int x2 = x1 + 1; + int y2 = y1 + 1; + wrap_pixel(x1, y1, extend_x, extend_y); + wrap_pixel(x2, y2, extend_x, extend_y); + + float valuex = x - x1; + float valuey = y - y1; + float mvaluex = 1.0f - valuex; + float mvaluey = 1.0f - valuey; + + float color1[4]; + float color2[4]; + float color3[4]; + float color4[4]; + + read(color1, x1, y1); + read(color2, x1, y2); + read(color3, x2, y1); + read(color4, x2, y2); + + color1[0] = color1[0] * mvaluey + color2[0] * valuey; + color1[1] = color1[1] * mvaluey + color2[1] * valuey; + color1[2] = color1[2] * mvaluey + color2[2] * valuey; + color1[3] = color1[3] * mvaluey + color2[3] * valuey; + + color3[0] = color3[0] * mvaluey + color4[0] * valuey; + color3[1] = color3[1] * mvaluey + color4[1] * valuey; + color3[2] = color3[2] * mvaluey + color4[2] * valuey; + color3[3] = color3[3] * mvaluey + color4[3] * valuey; + + result[0] = color1[0] * mvaluex + color3[0] * valuex; + result[1] = color1[1] * mvaluex + color3[1] * valuex; + result[2] = color1[2] * mvaluex + color3[2] * valuex; + result[3] = color1[3] * mvaluex + color3[3] * valuex; +} + +// --- EWA Filtering --- +// table of (exp(ar) - exp(a)) / (1 - exp(a)) for r in range [0, 1] and a = -2 +// used instead of actual gaussian, otherwise at high texture magnifications circular artifacts are visible +#define EWA_MAXIDX 255 +static const float EWA_WTS[EWA_MAXIDX + 1] = { + 1.f, 0.990965f, 0.982f, 0.973105f, 0.96428f, 0.955524f, 0.946836f, 0.938216f, 0.929664f, + 0.921178f, 0.912759f, 0.904405f, 0.896117f, 0.887893f, 0.879734f, 0.871638f, 0.863605f, + 0.855636f, 0.847728f, 0.839883f, 0.832098f, 0.824375f, 0.816712f, 0.809108f, 0.801564f, + 0.794079f, 0.786653f, 0.779284f, 0.771974f, 0.76472f, 0.757523f, 0.750382f, 0.743297f, + 0.736267f, 0.729292f, 0.722372f, 0.715505f, 0.708693f, 0.701933f, 0.695227f, 0.688572f, + 0.68197f, 0.67542f, 0.66892f, 0.662471f, 0.656073f, 0.649725f, 0.643426f, 0.637176f, + 0.630976f, 0.624824f, 0.618719f, 0.612663f, 0.606654f, 0.600691f, 0.594776f, 0.588906f, + 0.583083f, 0.577305f, 0.571572f, 0.565883f, 0.56024f, 0.55464f, 0.549084f, 0.543572f, + 0.538102f, 0.532676f, 0.527291f, 0.521949f, 0.516649f, 0.511389f, 0.506171f, 0.500994f, + 0.495857f, 0.490761f, 0.485704f, 0.480687f, 0.475709f, 0.470769f, 0.465869f, 0.461006f, + 0.456182f, 0.451395f, 0.446646f, 0.441934f, 0.437258f, 0.432619f, 0.428017f, 0.42345f, + 0.418919f, 0.414424f, 0.409963f, 0.405538f, 0.401147f, 0.39679f, 0.392467f, 0.388178f, + 0.383923f, 0.379701f, 0.375511f, 0.371355f, 0.367231f, 0.363139f, 0.359079f, 0.355051f, + 0.351055f, 0.347089f, 0.343155f, 0.339251f, 0.335378f, 0.331535f, 0.327722f, 0.323939f, + 0.320186f, 0.316461f, 0.312766f, 0.3091f, 0.305462f, 0.301853f, 0.298272f, 0.294719f, + 0.291194f, 0.287696f, 0.284226f, 0.280782f, 0.277366f, 0.273976f, 0.270613f, 0.267276f, + 0.263965f, 0.26068f, 0.257421f, 0.254187f, 0.250979f, 0.247795f, 0.244636f, 0.241502f, + 0.238393f, 0.235308f, 0.232246f, 0.229209f, 0.226196f, 0.223206f, 0.220239f, 0.217296f, + 0.214375f, 0.211478f, 0.208603f, 0.20575f, 0.20292f, 0.200112f, 0.197326f, 0.194562f, + 0.191819f, 0.189097f, 0.186397f, 0.183718f, 0.18106f, 0.178423f, 0.175806f, 0.17321f, + 0.170634f, 0.168078f, 0.165542f, 0.163026f, 0.16053f, 0.158053f, 0.155595f, 0.153157f, + 0.150738f, 0.148337f, 0.145955f, 0.143592f, 0.141248f, 0.138921f, 0.136613f, 0.134323f, + 0.132051f, 0.129797f, 0.12756f, 0.125341f, 0.123139f, 0.120954f, 0.118786f, 0.116635f, + 0.114501f, 0.112384f, 0.110283f, 0.108199f, 0.106131f, 0.104079f, 0.102043f, 0.100023f, + 0.0980186f, 0.09603f, 0.094057f, 0.0920994f, 0.0901571f, 0.08823f, 0.0863179f, 0.0844208f, + 0.0825384f, 0.0806708f, 0.0788178f, 0.0769792f, 0.0751551f, 0.0733451f, 0.0715493f, 0.0697676f, + 0.0679997f, 0.0662457f, 0.0645054f, 0.0627786f, 0.0610654f, 0.0593655f, 0.0576789f, 0.0560055f, + 0.0543452f, 0.0526979f, 0.0510634f, 0.0494416f, 0.0478326f, 0.0462361f, 0.0446521f, 0.0430805f, + 0.0415211f, 0.039974f, 0.0384389f, 0.0369158f, 0.0354046f, 0.0339052f, 0.0324175f, 0.0309415f, + 0.029477f, 0.0280239f, 0.0265822f, 0.0251517f, 0.0237324f, 0.0223242f, 0.020927f, 0.0195408f, + 0.0181653f, 0.0168006f, 0.0154466f, 0.0141031f, 0.0127701f, 0.0114476f, 0.0101354f, 0.00883339f, + 0.00754159f, 0.00625989f, 0.00498819f, 0.00372644f, 0.00247454f, 0.00123242f, 0.f +}; + +static void ellipse_bounds(float A, float B, float C, float F, float &xmax, float &ymax) +{ + float denom = 4.0f * A * C - B * B; + if (denom > 0.0f && A != 0.0f && C != 0.0f) { + xmax = sqrtf(F) / (2.0f * A) * (sqrtf(F * (4.0f * A - B * B / C)) + B * B * sqrtf(F / (C * denom))); + ymax = sqrtf(F) / (2.0f * C) * (sqrtf(F * (4.0f * C - B * B / A)) + B * B * sqrtf(F / (A * denom))); + } + else { + xmax = 0.0f; + ymax = 0.0f; + } +} + +static void ellipse_params(float Ux, float Uy, float Vx, float Vy, + float &A, float &B, float &C, float &F, float &umax, float &vmax) +{ + A = Vx * Vx + Vy * Vy; + B = -2.0f * (Ux * Vx + Uy * Vy); + C = Ux * Ux + Uy * Uy; + F = A * C - B * B * 0.25f; + + float factor = (F != 0.0f ? (float)(EWA_MAXIDX + 1) / F : 0.0f); + A *= factor; + B *= factor; + C *= factor; + F = (float)(EWA_MAXIDX + 1); + + ellipse_bounds(A, B, C, sqrtf(F), umax, vmax); +} + +/** + * Filtering method based on + * "Creating raster omnimax images from multiple perspective views using the elliptical weighted average filter" + * by Ned Greene and Paul S. Heckbert (1986) + */ +void MemoryBufferColor::readEWA(float result[4], const float uv[2], const float derivatives[2][2], PixelSampler sampler) +{ + zero_v4(result); + int width = this->getWidth(), height = this->getHeight(); + if (width == 0 || height == 0) + return; + + float u = uv[0], v = uv[1]; + float Ux = derivatives[0][0], Vx = derivatives[1][0], Uy = derivatives[0][1], Vy = derivatives[1][1]; + float A, B, C, F, ue, ve; + ellipse_params(Ux, Uy, Vx, Vy, A, B, C, F, ue, ve); + + /* Note: highly eccentric ellipses can lead to large texture space areas to filter! + * This is limited somewhat by the EWA_WTS size in the loop, but a nicer approach + * could be the one found in + * "High Quality Elliptical Texture Filtering on GPU" + * by Pavlos Mavridis and Georgios Papaioannou + * in which the eccentricity of the ellipse is clamped. + */ + + int U0 = (int)u; + int V0 = (int)v; + /* pixel offset for interpolation */ + float ufac = u - floorf(u), vfac = v - floorf(v); + /* filter size */ + int u1 = (int)(u - ue); + int u2 = (int)(u + ue); + int v1 = (int)(v - ve); + int v2 = (int)(v + ve); + + /* sane clamping to avoid unnecessarily huge loops */ + /* note: if eccentricity gets clamped (see above), + * the ue/ve limits can also be lowered accordingly + */ + if (U0 - u1 > EWA_MAXIDX) u1 = U0 - EWA_MAXIDX; + if (u2 - U0 > EWA_MAXIDX) u2 = U0 + EWA_MAXIDX; + if (V0 - v1 > EWA_MAXIDX) v1 = V0 - EWA_MAXIDX; + if (v2 - V0 > EWA_MAXIDX) v2 = V0 + EWA_MAXIDX; + + float DDQ = 2.0f * A; + float U = u1 - U0; + float ac1 = A * (2.0f * U + 1.0f); + float ac2 = A * U * U; + float BU = B * U; + + float sum = 0.0f; + for (int v = v1; v <= v2; ++v) { + float V = v - V0; + + float DQ = ac1 + B * V; + float Q = (C * V + BU) * V + ac2; + for (int u = u1; u <= u2; ++u) { + if (Q < F) { + float tc[4]; + const float wt = EWA_WTS[CLAMPIS((int)Q, 0, EWA_MAXIDX)]; + switch (sampler) { + case COM_PS_NEAREST: read(tc, u, v); break; + case COM_PS_BILINEAR: readBilinear(tc, (float)u + ufac, (float)v + vfac); break; + case COM_PS_BICUBIC: readBilinear(tc, (float)u + ufac, (float)v + vfac); break; /* XXX no readBicubic method yet */ + default: zero_v4(tc); break; + } + madd_v4_v4fl(result, tc, wt); + sum += wt; + } + Q += DQ; + DQ += DDQ; + } + } + + mul_v4_fl(result, (sum != 0.0f ? 1.0f / sum : 0.0f)); +} diff --git a/source/blender/compositor/intern/COM_MemoryBufferColor.h b/source/blender/compositor/intern/COM_MemoryBufferColor.h new file mode 100644 index 00000000000..9195d083620 --- /dev/null +++ b/source/blender/compositor/intern/COM_MemoryBufferColor.h @@ -0,0 +1,71 @@ +/* + * Copyright 2014, Blender Foundation. + * + * 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. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + */ + +class MemoryBufferColor; + +#ifndef _COM_MemoryBufferColor_h_ +#define _COM_MemoryBufferColor_h_ + +#include "COM_MemoryBuffer.h" + +class MemoryBufferColor: MemoryBuffer +{ +protected: + /** + * @brief construct new MemoryBuffer for a chunk + */ + MemoryBufferColor(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect); + + /** + * @brief construct new temporarily MemoryBuffer for an area + */ + MemoryBufferColor(MemoryProxy *memoryProxy, rcti *rect); + + MemoryBufferColor(DataType datatype, rcti *rect); +public: + void writePixel(int x, int y, const float *color); + void addPixel(int x, int y, const float *color); + void read(float *result, int x, int y, + MemoryBufferExtend extend_x = COM_MB_CLIP, + MemoryBufferExtend extend_y = COM_MB_CLIP); + + void readNoCheck(float *result, int x, int y, + MemoryBufferExtend extend_x = COM_MB_CLIP, + MemoryBufferExtend extend_y = COM_MB_CLIP); + + void readBilinear(float *result, float x, float y, + MemoryBufferExtend extend_x = COM_MB_CLIP, + MemoryBufferExtend extend_y = COM_MB_CLIP); + + void readEWA(float result[4], const float uv[2], const float derivatives[2][2], PixelSampler sampler); + + MemoryBuffer *duplicate(); + + + friend class MemoryBuffer; + +#ifdef WITH_CXX_GUARDEDALLOC + MEM_CXX_CLASS_ALLOC_FUNCS("COM:MemoryBufferColor") +#endif +}; + +#endif diff --git a/source/blender/compositor/intern/COM_MemoryBufferValue.cpp b/source/blender/compositor/intern/COM_MemoryBufferValue.cpp new file mode 100644 index 00000000000..5b7920e0b01 --- /dev/null +++ b/source/blender/compositor/intern/COM_MemoryBufferValue.cpp @@ -0,0 +1,152 @@ +/* + * Copyright 2014, Blender Foundation. + * + * 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. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + */ + +#include "COM_MemoryBufferValue.h" + +#define NUMBER_OF_CHANNELS COM_NO_CHANNELS_VALUE + +MemoryBufferValue::MemoryBufferValue(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect): + MemoryBuffer(memoryProxy, chunkNumber, rect, NUMBER_OF_CHANNELS) +{ +} + +MemoryBufferValue::MemoryBufferValue(MemoryProxy *memoryProxy, rcti *rect) : + MemoryBuffer(memoryProxy, rect, NUMBER_OF_CHANNELS) +{ +} + +MemoryBufferValue::MemoryBufferValue(DataType datatype, rcti *rect) : + MemoryBuffer(datatype, rect, NUMBER_OF_CHANNELS) { +} + +MemoryBuffer *MemoryBufferValue::duplicate() +{ + MemoryBufferValue *result = new MemoryBufferValue(this->m_memoryProxy, &this->m_rect); + memcpy(result->getBuffer(), this->getBuffer(), this->determineBufferSize() * NUMBER_OF_CHANNELS * sizeof(float)); + return result; +} + + +// --- write pixels --- +void MemoryBufferValue::writePixel(int x, int y, const float *color) +{ + 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_chunkWidth * (y - this->m_rect.ymin) + x - this->m_rect.xmin) * NUMBER_OF_CHANNELS; + copy_v4_v4(&this->m_buffer[offset], color); + } +} + +void MemoryBufferValue::addPixel(int x, int y, const float *color) +{ + 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_chunkWidth * (y - this->m_rect.ymin) + x - this->m_rect.xmin) * NUMBER_OF_CHANNELS; + this->m_buffer[offset] = color[0]; + } +} + +// --- SAMPLERS --- +inline void MemoryBufferValue::read(float *result, int x, int y, + MemoryBufferExtend extend_x, + MemoryBufferExtend extend_y) +{ + 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 */ + zero_v4(result); + } + else + { + wrap_pixel(x, y, extend_x, extend_y); + const int offset = (this->m_chunkWidth * y + x) * NUMBER_OF_CHANNELS; + result[0] = this->m_buffer[offset]; + } +} + +inline void MemoryBufferValue::readNoCheck(float *result, int x, int y, + MemoryBufferExtend extend_x, + MemoryBufferExtend extend_y) +{ + + wrap_pixel(x, y, extend_x, extend_y); + const int offset = (this->m_chunkWidth * y + x) * NUMBER_OF_CHANNELS; + + BLI_assert(offset >= 0); + BLI_assert(offset < this->determineBufferSize() * NUMBER_OF_CHANNELS); + BLI_assert(!(extend_x == COM_MB_CLIP && (x < m_rect.xmin || x >= m_rect.xmax)) && + !(extend_y == COM_MB_CLIP && (y < m_rect.ymin || y >= m_rect.ymax))); + + result[0] = this->m_buffer[offset]; +} + +inline void MemoryBufferValue::readBilinear(float *result, float x, float y, + MemoryBufferExtend extend_x, + MemoryBufferExtend extend_y) +{ + int x1 = floor(x); + int y1 = floor(y); + int x2 = x1 + 1; + int y2 = y1 + 1; + wrap_pixel(x1, y1, extend_x, extend_y); + wrap_pixel(x2, y2, extend_x, extend_y); + + float valuex = x - x1; + float valuey = y - y1; + float mvaluex = 1.0f - valuex; + float mvaluey = 1.0f - valuey; + + float value1; + float value2; + float value3; + float value4; + + read(&value1, x1, y1); + read(&value2, x1, y2); + read(&value3, x2, y1); + read(&value4, x2, y2); + + value1 = value1 * mvaluey + value2 * valuey; + value3 = value3 * mvaluey + value4 * valuey; + result[0] = value1 * mvaluex + value3 * valuex; +} + +float MemoryBufferValue::getMaximumValue() const +{ + 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 += NUMBER_OF_CHANNELS) { + float value = *fp_src; + if (value > result) { + result = value; + } + } + + return result; +} diff --git a/source/blender/compositor/intern/COM_MemoryBufferValue.h b/source/blender/compositor/intern/COM_MemoryBufferValue.h new file mode 100644 index 00000000000..fac376bdf17 --- /dev/null +++ b/source/blender/compositor/intern/COM_MemoryBufferValue.h @@ -0,0 +1,68 @@ +/* + * Copyright 2014, Blender Foundation. + * + * 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. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + */ + +class MemoryBufferValue; + +#ifndef _COM_MemoryBufferValue_h_ +#define _COM_MemoryBufferValue_h_ + +#include "COM_MemoryBuffer.h" + +class MemoryBufferValue: public MemoryBuffer +{ +protected: + /** + * @brief construct new MemoryBuffer for a chunk + */ + MemoryBufferValue(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect); + + /** + * @brief construct new temporarily MemoryBuffer for an area + */ + MemoryBufferValue(MemoryProxy *memoryProxy, rcti *rect); + MemoryBufferValue(DataType datatype, rcti *rect); + +public: + void writePixel(int x, int y, const float *color); + void addPixel(int x, int y, const float *color); + void read(float *result, int x, int y, + MemoryBufferExtend extend_x = COM_MB_CLIP, + MemoryBufferExtend extend_y = COM_MB_CLIP); + + void readNoCheck(float *result, int x, int y, + MemoryBufferExtend extend_x = COM_MB_CLIP, + MemoryBufferExtend extend_y = COM_MB_CLIP); + + void readBilinear(float *result, float x, float y, + MemoryBufferExtend extend_x = COM_MB_CLIP, + MemoryBufferExtend extend_y = COM_MB_CLIP); + + float getMaximumValue() const; + MemoryBuffer *duplicate(); + + friend class MemoryBuffer; + +#ifdef WITH_CXX_GUARDEDALLOC + MEM_CXX_CLASS_ALLOC_FUNCS("COM:MemoryBufferValue") +#endif +}; +#endif diff --git a/source/blender/compositor/intern/COM_MemoryBufferVector.cpp b/source/blender/compositor/intern/COM_MemoryBufferVector.cpp new file mode 100644 index 00000000000..51feb061749 --- /dev/null +++ b/source/blender/compositor/intern/COM_MemoryBufferVector.cpp @@ -0,0 +1,144 @@ +/* + * Copyright 2014, Blender Foundation. + * + * 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. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + */ + +#include "COM_MemoryBufferVector.h" + +#define NUMBER_OF_CHANNELS COM_NO_CHANNELS_VECTOR + +MemoryBufferVector::MemoryBufferVector(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect): + MemoryBuffer(memoryProxy, chunkNumber, rect, NUMBER_OF_CHANNELS) +{ +} + +MemoryBufferVector::MemoryBufferVector(MemoryProxy *memoryProxy, rcti *rect) : + MemoryBuffer(memoryProxy, rect, NUMBER_OF_CHANNELS) +{ +} + +MemoryBufferVector::MemoryBufferVector(DataType datatype, rcti *rect) : + MemoryBuffer(datatype, rect, NUMBER_OF_CHANNELS) { +} + + +MemoryBuffer *MemoryBufferVector::duplicate() +{ + MemoryBufferVector *result = new MemoryBufferVector(this->m_memoryProxy, &this->m_rect); + memcpy(result->getBuffer(), this->getBuffer(), this->determineBufferSize() * NUMBER_OF_CHANNELS * sizeof(float)); + return result; +} + + +// --- write pixels --- +void MemoryBufferVector::writePixel(int x, int y, const float *color) +{ + 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_chunkWidth * (y - this->m_rect.ymin) + x - this->m_rect.xmin) * NUMBER_OF_CHANNELS; + copy_v4_v4(&this->m_buffer[offset], color); + } +} + +void MemoryBufferVector::addPixel(int x, int y, const float *color) +{ + 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_chunkWidth * (y - this->m_rect.ymin) + x - this->m_rect.xmin) * NUMBER_OF_CHANNELS; + add_v4_v4(&this->m_buffer[offset], color); + } +} + +// --- SAMPLERS --- +inline void MemoryBufferVector::read(float *result, int x, int y, + MemoryBufferExtend extend_x, + MemoryBufferExtend extend_y) +{ + 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 */ + zero_v4(result); + } + else + { + wrap_pixel(x, y, extend_x, extend_y); + const int offset = (this->m_chunkWidth * y + x) * NUMBER_OF_CHANNELS; + copy_v4_v4(result, &this->m_buffer[offset]); + } +} + +inline void MemoryBufferVector::readNoCheck(float *result, int x, int y, + MemoryBufferExtend extend_x, + MemoryBufferExtend extend_y) +{ + + wrap_pixel(x, y, extend_x, extend_y); + const int offset = (this->m_chunkWidth * y + x) * NUMBER_OF_CHANNELS; + + BLI_assert(offset >= 0); + BLI_assert(offset < this->determineBufferSize() * NUMBER_OF_CHANNELS); + BLI_assert(!(extend_x == COM_MB_CLIP && (x < m_rect.xmin || x >= m_rect.xmax)) && + !(extend_y == COM_MB_CLIP && (y < m_rect.ymin || y >= m_rect.ymax))); + + copy_v4_v4(result, &this->m_buffer[offset]); +} + +inline void MemoryBufferVector::readBilinear(float *result, float x, float y, + MemoryBufferExtend extend_x, + MemoryBufferExtend extend_y) +{ + int x1 = floor(x); + int y1 = floor(y); + int x2 = x1 + 1; + int y2 = y1 + 1; + wrap_pixel(x1, y1, extend_x, extend_y); + wrap_pixel(x2, y2, extend_x, extend_y); + + float valuex = x - x1; + float valuey = y - y1; + float mvaluex = 1.0f - valuex; + float mvaluey = 1.0f - valuey; + + float vector1[NUMBER_OF_CHANNELS]; + float vector2[NUMBER_OF_CHANNELS]; + float vector3[NUMBER_OF_CHANNELS]; + float vector4[NUMBER_OF_CHANNELS]; + + read(vector1, x1, y1); + read(vector2, x1, y2); + read(vector3, x2, y1); + read(vector4, x2, y2); + + vector1[0] = vector1[0] * mvaluey + vector2[0] * valuey; + vector1[1] = vector1[1] * mvaluey + vector2[1] * valuey; + vector1[2] = vector1[2] * mvaluey + vector2[2] * valuey; + + vector3[0] = vector3[0] * mvaluey + vector4[0] * valuey; + vector3[1] = vector3[1] * mvaluey + vector4[1] * valuey; + vector3[2] = vector3[2] * mvaluey + vector4[2] * valuey; + + result[0] = vector1[0] * mvaluex + vector3[0] * valuex; + result[1] = vector1[1] * mvaluex + vector3[1] * valuex; + result[2] = vector1[2] * mvaluex + vector3[2] * valuex; +} + diff --git a/source/blender/compositor/intern/COM_MemoryBufferVector.h b/source/blender/compositor/intern/COM_MemoryBufferVector.h new file mode 100644 index 00000000000..7c280ad0da9 --- /dev/null +++ b/source/blender/compositor/intern/COM_MemoryBufferVector.h @@ -0,0 +1,67 @@ +/* + * Copyright 2014, Blender Foundation. + * + * 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. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + */ + +class MemoryBufferVector; + +#ifndef _COM_MemoryBufferVector_h_ +#define _COM_MemoryBufferVector_h_ + +#include "COM_MemoryBuffer.h" + +class MemoryBufferVector: public MemoryBuffer +{ +protected: + /** + * @brief construct new MemoryBuffer for a chunk + */ + MemoryBufferVector(MemoryProxy *memoryProxy, unsigned int chunkNumber, rcti *rect); + + /** + * @brief construct new temporarily MemoryBuffer for an area + */ + MemoryBufferVector(MemoryProxy *memoryProxy, rcti *rect); + MemoryBufferVector(DataType datatype, rcti *rect); + +public: + void writePixel(int x, int y, const float *color); + void addPixel(int x, int y, const float *color); + void read(float *result, int x, int y, + MemoryBufferExtend extend_x = COM_MB_CLIP, + MemoryBufferExtend extend_y = COM_MB_CLIP); + + void readNoCheck(float *result, int x, int y, + MemoryBufferExtend extend_x = COM_MB_CLIP, + MemoryBufferExtend extend_y = COM_MB_CLIP); + + void readBilinear(float *result, float x, float y, + MemoryBufferExtend extend_x = COM_MB_CLIP, + MemoryBufferExtend extend_y = COM_MB_CLIP); + + MemoryBuffer *duplicate(); + + friend class MemoryBuffer; + +#ifdef WITH_CXX_GUARDEDALLOC + MEM_CXX_CLASS_ALLOC_FUNCS("COM:MemoryBufferVector") +#endif +}; +#endif diff --git a/source/blender/compositor/intern/COM_MemoryProxy.cpp b/source/blender/compositor/intern/COM_MemoryProxy.cpp index 90ca0baea06..18bc2bf6b42 100644 --- a/source/blender/compositor/intern/COM_MemoryProxy.cpp +++ b/source/blender/compositor/intern/COM_MemoryProxy.cpp @@ -23,10 +23,11 @@ #include "COM_MemoryProxy.h" -MemoryProxy::MemoryProxy() +MemoryProxy::MemoryProxy(DataType type) { this->m_writeBufferOperation = NULL; this->m_executor = NULL; + this->m_datatype = type; } void MemoryProxy::allocate(unsigned int width, unsigned int height) @@ -37,7 +38,7 @@ void MemoryProxy::allocate(unsigned int width, unsigned int height) result.ymin = 0; result.ymax = height; - this->m_buffer = new MemoryBuffer(this, 1, &result); + this->m_buffer = MemoryBuffer::create(this, 1, &result); } void MemoryProxy::free() diff --git a/source/blender/compositor/intern/COM_MemoryProxy.h b/source/blender/compositor/intern/COM_MemoryProxy.h index 696c843e7c4..55bc5837b3a 100644 --- a/source/blender/compositor/intern/COM_MemoryProxy.h +++ b/source/blender/compositor/intern/COM_MemoryProxy.h @@ -46,12 +46,7 @@ private: * @brief reference to the executor. the Execution group that can fill a chunk */ ExecutionGroup *m_executor; - - /** - * @brief datatype of this MemoryProxy - */ - /* DataType m_datatype; */ /* UNUSED */ - + /** * @brief channel information of this buffer */ @@ -62,8 +57,13 @@ private: */ MemoryBuffer *m_buffer; + /** + * @brief datatype of this MemoryProxy + */ + DataType m_datatype; + public: - MemoryProxy(); + MemoryProxy(DataType type); /** * @brief set the ExecutionGroup that can be scheduled to calculate a certain chunk. @@ -103,6 +103,8 @@ public: */ inline MemoryBuffer *getBuffer() { return this->m_buffer; } + inline DataType getDataType() { return this->m_datatype; } + #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("COM:MemoryProxy") #endif diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.cpp b/source/blender/compositor/intern/COM_OpenCLDevice.cpp index bb60a629812..58cc8584ffd 100644 --- a/source/blender/compositor/intern/COM_OpenCLDevice.cpp +++ b/source/blender/compositor/intern/COM_OpenCLDevice.cpp @@ -24,6 +24,18 @@ #include "COM_WorkScheduler.h" typedef enum COM_VendorID {NVIDIA = 0x10DE, AMD = 0x1002} COM_VendorID; +const cl_image_format IMAGE_FORMAT_COLOR = { + CL_RGBA, + CL_FLOAT +}; +const cl_image_format IMAGE_FORMAT_VECTOR = { + CL_RGB, + CL_FLOAT +}; +const cl_image_format IMAGE_FORMAT_VALUE = { + CL_R, + CL_FLOAT +}; OpenCLDevice::OpenCLDevice(cl_context context, cl_device_id device, cl_program program, cl_int vendorId) { @@ -72,6 +84,21 @@ cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel, return COM_clAttachMemoryBufferToKernelParameter(kernel, parameterIndex, offsetIndex, cleanup, inputMemoryBuffers, (ReadBufferOperation *)reader); } +const cl_image_format* OpenCLDevice::determineImageFormat(MemoryBuffer *memoryBuffer) +{ + const cl_image_format *imageFormat; + int no_channels = memoryBuffer->get_no_channels(); + if (no_channels == 1) { + imageFormat = &IMAGE_FORMAT_VALUE; + } else if (no_channels == 3) { + imageFormat = &IMAGE_FORMAT_VECTOR; + } else { + imageFormat = &IMAGE_FORMAT_COLOR; + } + + return imageFormat; +} + cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel, int parameterIndex, int offsetIndex, list *cleanup, MemoryBuffer **inputMemoryBuffers, ReadBufferOperation *reader) @@ -80,12 +107,9 @@ cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel, MemoryBuffer *result = reader->getInputMemoryBuffer(inputMemoryBuffers); - const cl_image_format imageFormat = { - CL_RGBA, - CL_FLOAT - }; + const cl_image_format *imageFormat = determineImageFormat(result); - cl_mem clBuffer = clCreateImage2D(this->m_context, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, &imageFormat, result->getWidth(), + cl_mem clBuffer = clCreateImage2D(this->m_context, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, imageFormat, result->getWidth(), result->getHeight(), 0, result->getBuffer(), &error); if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.h b/source/blender/compositor/intern/COM_OpenCLDevice.h index 2021cacabcc..1c2a204689d 100644 --- a/source/blender/compositor/intern/COM_OpenCLDevice.h +++ b/source/blender/compositor/intern/COM_OpenCLDevice.h @@ -92,6 +92,13 @@ public: */ void execute(WorkPackage *work); + /** + * @brief determine an image format + * @param memorybuffer + */ + + static const cl_image_format* determineImageFormat(MemoryBuffer *memoryBuffer); + cl_context getContext() { return this->m_context; } cl_command_queue getQueue() { return this->m_queue; } diff --git a/source/blender/compositor/intern/COM_OutputSocket.h b/source/blender/compositor/intern/COM_OutputSocket.h index 709005a6de0..f6fc4c8cb83 100644 --- a/source/blender/compositor/intern/COM_OutputSocket.h +++ b/source/blender/compositor/intern/COM_OutputSocket.h @@ -25,7 +25,6 @@ #include #include "COM_Socket.h" -#include "COM_ChannelInfo.h" using namespace std; class SocketConnection; diff --git a/source/blender/compositor/intern/COM_SocketConnection.h b/source/blender/compositor/intern/COM_SocketConnection.h index 9777bd45be2..1ed87487ab9 100644 --- a/source/blender/compositor/intern/COM_SocketConnection.h +++ b/source/blender/compositor/intern/COM_SocketConnection.h @@ -26,7 +26,6 @@ #include "DNA_node_types.h" #include "COM_Node.h" #include "COM_Socket.h" -#include "COM_ChannelInfo.h" /** * @brief An SocketConnection is an connection between an InputSocket and an OutputSocket. diff --git a/source/blender/compositor/nodes/COM_SocketProxyNode.cpp b/source/blender/compositor/nodes/COM_SocketProxyNode.cpp index c822d2107ec..f8f11a6c72f 100644 --- a/source/blender/compositor/nodes/COM_SocketProxyNode.cpp +++ b/source/blender/compositor/nodes/COM_SocketProxyNode.cpp @@ -57,12 +57,13 @@ void SocketProxyNode::convertToOperations(ExecutionSystem *graph, CompositorCont graph->addOperation(operation); if (m_buffer) { - WriteBufferOperation *writeOperation = new WriteBufferOperation(); - ReadBufferOperation *readOperation = new ReadBufferOperation(); + OutputSocket * osocket = operation->getOutputSocket(); + WriteBufferOperation *writeOperation = new WriteBufferOperation(osocket->getDataType()); + ReadBufferOperation *readOperation = new ReadBufferOperation(osocket->getDataType()); readOperation->setMemoryProxy(writeOperation->getMemoryProxy()); - operation->getOutputSocket()->relinkConnections(readOperation->getOutputSocket()); - addLink(graph, operation->getOutputSocket(), writeOperation->getInputSocket(0)); + osocket->relinkConnections(readOperation->getOutputSocket()); + addLink(graph, osocket, writeOperation->getInputSocket(0)); graph->addOperation(writeOperation); graph->addOperation(readOperation); diff --git a/source/blender/compositor/nodes/COM_TranslateNode.cpp b/source/blender/compositor/nodes/COM_TranslateNode.cpp index d2cd009449c..8d8c663375b 100644 --- a/source/blender/compositor/nodes/COM_TranslateNode.cpp +++ b/source/blender/compositor/nodes/COM_TranslateNode.cpp @@ -44,8 +44,8 @@ void TranslateNode::convertToOperations(ExecutionSystem *graph, CompositorContex NodeTranslateData *data = (NodeTranslateData *)bnode->storage; if (data->wrap_axis) { - WriteBufferOperation *writeOperation = new WriteBufferOperation(); - WrapOperation *wrapOperation = new WrapOperation(); + WriteBufferOperation *writeOperation = new WriteBufferOperation(COM_DT_COLOR); + WrapOperation *wrapOperation = new WrapOperation(COM_DT_COLOR); wrapOperation->setMemoryProxy(writeOperation->getMemoryProxy()); wrapOperation->setWrapping(data->wrap_axis); diff --git a/source/blender/compositor/operations/COM_AntiAliasOperation.cpp b/source/blender/compositor/operations/COM_AntiAliasOperation.cpp index 995c61589cc..b32401e1968 100644 --- a/source/blender/compositor/operations/COM_AntiAliasOperation.cpp +++ b/source/blender/compositor/operations/COM_AntiAliasOperation.cpp @@ -95,7 +95,7 @@ void *AntiAliasOperation::initializeTileData(rcti *rect) float *input = tile->getBuffer(); char *valuebuffer = (char *)MEM_mallocN(sizeof(char) * size, __func__); for (int i = 0; i < size; i++) { - float in = input[i * COM_NUMBER_OF_CHANNELS]; + float in = input[i]; valuebuffer[i] = FTOCHAR(in); } antialias_tagbuf(tile->getWidth(), tile->getHeight(), valuebuffer); diff --git a/source/blender/compositor/operations/COM_CompositorOperation.cpp b/source/blender/compositor/operations/COM_CompositorOperation.cpp index d4629a8d527..9bb653c1319 100644 --- a/source/blender/compositor/operations/COM_CompositorOperation.cpp +++ b/source/blender/compositor/operations/COM_CompositorOperation.cpp @@ -139,7 +139,7 @@ void CompositorOperation::executeRegion(rcti *rect, unsigned int tileNumber) int y2 = rect->ymax; int offset = (y1 * this->getWidth() + x1); int add = (this->getWidth() - (x2 - x1)); - int offset4 = offset * COM_NUMBER_OF_CHANNELS; + int offset4 = offset * COM_NO_CHANNELS_COLOR; int x; int y; bool breaked = false; @@ -204,14 +204,14 @@ void CompositorOperation::executeRegion(rcti *rect, unsigned int tileNumber) this->m_depthInput->readSampled(color, input_x, input_y, COM_PS_NEAREST); zbuffer[offset] = color[0]; } - offset4 += COM_NUMBER_OF_CHANNELS; + offset4 += COM_NO_CHANNELS_COLOR; offset++; if (isBreaked()) { breaked = true; } } offset += add; - offset4 += add * COM_NUMBER_OF_CHANNELS; + offset4 += add * COM_NO_CHANNELS_COLOR; } } diff --git a/source/blender/compositor/operations/COM_ConvertOperation.cpp b/source/blender/compositor/operations/COM_ConvertOperation.cpp index 6b3e4067b18..70f0a8c570a 100644 --- a/source/blender/compositor/operations/COM_ConvertOperation.cpp +++ b/source/blender/compositor/operations/COM_ConvertOperation.cpp @@ -22,7 +22,6 @@ #include "COM_ConvertOperation.h" - ConvertBaseOperation::ConvertBaseOperation() { this->m_inputOperation = NULL; @@ -49,9 +48,9 @@ ConvertValueToColorOperation::ConvertValueToColorOperation() : ConvertBaseOperat void ConvertValueToColorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { - float inputValue[4]; - this->m_inputOperation->readSampled(inputValue, x, y, sampler); - output[0] = output[1] = output[2] = inputValue[0]; + float value; + this->m_inputOperation->readSampled(&value, x, y, sampler); + output[0] = output[1] = output[2] = value; output[3] = 1.0f; } @@ -98,7 +97,9 @@ ConvertColorToVectorOperation::ConvertColorToVectorOperation() : ConvertBaseOper void ConvertColorToVectorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { - this->m_inputOperation->readSampled(output, x, y, sampler); + float color[4]; + this->m_inputOperation->readSampled(color, x, y, sampler); + copy_v3_v3(output, color); } @@ -112,12 +113,9 @@ ConvertValueToVectorOperation::ConvertValueToVectorOperation() : ConvertBaseOper void ConvertValueToVectorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { - float input[4]; - this->m_inputOperation->readSampled(input, x, y, sampler); - output[0] = input[0]; - output[1] = input[0]; - output[2] = input[0]; - output[3] = 0.0f; + float value; + this->m_inputOperation->readSampled(&value, x, y, sampler); + output[0] = output[1] = output[2] = value; } @@ -131,7 +129,7 @@ ConvertVectorToColorOperation::ConvertVectorToColorOperation() : ConvertBaseOper void ConvertVectorToColorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { - this->m_inputOperation->readSampled(output, x, y, sampler); + this->m_inputOperation->readSampled(output, x, y, sampler); output[3] = 1.0f; } diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp index b54e47c136d..d5c66364c27 100644 --- a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp +++ b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp @@ -82,18 +82,18 @@ void DilateErodeThresholdOperation::executePixel(float output[4], int x, int y, const int bufferWidth = BLI_rcti_size_x(rect); int offset; - this->m_inputProgram->read(inputValue, x, y, NULL); - if (inputValue[0] > sw) { + inputBuffer->read(inputValue, x, y); + if (inputValue[0] > sw) { for (int yi = miny; yi < maxy; yi++) { const float dy = yi - y; - offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin)) * 4; + offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin)); for (int xi = minx; xi < maxx; xi++) { if (buffer[offset] < sw) { const float dx = xi - x; const float dis = dx * dx + dy * dy; mindist = min(mindist, dis); } - offset += 4; + offset ++; } } pixelvalue = -sqrtf(mindist); @@ -101,14 +101,14 @@ void DilateErodeThresholdOperation::executePixel(float output[4], int x, int y, else { for (int yi = miny; yi < maxy; yi++) { const float dy = yi - y; - offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin)) * 4; + offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin)); for (int xi = minx; xi < maxx; xi++) { if (buffer[offset] > sw) { const float dx = xi - x; const float dis = dx * dx + dy * dy; mindist = min(mindist, dis); } - offset += 4; + offset ++; } } @@ -193,7 +193,7 @@ void DilateDistanceOperation::executePixel(float output[4], int x, int y, void * const float mindist = distance * distance; MemoryBuffer *inputBuffer = (MemoryBuffer *)data; - float *buffer = inputBuffer->getBuffer(); + float *buffer = inputBuffer->getBuffer(); rcti *rect = inputBuffer->getRect(); const int minx = max(x - this->m_scope, rect->xmin); const int miny = max(y - this->m_scope, rect->ymin); @@ -206,17 +206,17 @@ void DilateDistanceOperation::executePixel(float output[4], int x, int y, void * for (int yi = miny; yi < maxy; yi++) { const float dy = yi - y; - offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin)) * 4; + offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin)); for (int xi = minx; xi < maxx; xi++) { const float dx = xi - x; const float dis = dx * dx + dy * dy; if (dis <= mindist) { value = max(buffer[offset], value); } - offset += 4; + offset ++; } } - output[0] = value; + output[0] = value; } void DilateDistanceOperation::deinitExecution() @@ -280,14 +280,14 @@ void ErodeDistanceOperation::executePixel(float output[4], int x, int y, void *d for (int yi = miny; yi < maxy; yi++) { const float dy = yi - y; - offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin)) * 4; + offset = ((yi - rect->ymin) * bufferWidth + (minx - rect->xmin)); for (int xi = minx; xi < maxx; xi++) { const float dx = xi - x; const float dis = dx * dx + dy * dy; if (dis <= mindist) { value = min(buffer[offset], value); } - offset += 4; + offset ++; } } output[0] = value; @@ -383,7 +383,7 @@ void *DilateStepOperation::initializeTileData(rcti *rect) buf[x] = -MAXFLOAT; } for (x = xmin; x < xmax; ++x) { - buf[x - rect->xmin + window - 1] = buffer[4 * (y * width + x)]; + buf[x - rect->xmin + window - 1] = buffer[(y * width + x)]; } for (i = 0; i < (bwidth + 3 * half_window) / window; i++) { @@ -510,7 +510,7 @@ void *ErodeStepOperation::initializeTileData(rcti *rect) buf[x] = MAXFLOAT; } for (x = xmin; x < xmax; ++x) { - buf[x - rect->xmin + window - 1] = buffer[4 * (y * width + x)]; + buf[x - rect->xmin + window - 1] = buffer[(y * width + x)]; } for (i = 0; i < (bwidth + 3 * half_window) / window; i++) { diff --git a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp index ff53ef22e29..4e1195bf731 100644 --- a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp @@ -129,16 +129,16 @@ void *FastGaussianBlurOperation::initializeTileData(rcti *rect) this->m_sy = this->m_data->sizey * this->m_size / 2.0f; if ((this->m_sx == this->m_sy) && (this->m_sx > 0.f)) { - for (c = 0; c < COM_NUMBER_OF_CHANNELS; ++c) + for (c = 0; c < COM_NO_CHANNELS_COLOR; ++c) IIR_gauss(copy, this->m_sx, c, 3); } else { if (this->m_sx > 0.0f) { - for (c = 0; c < COM_NUMBER_OF_CHANNELS; ++c) + for (c = 0; c < COM_NO_CHANNELS_COLOR; ++c) IIR_gauss(copy, this->m_sx, c, 1); } if (this->m_sy > 0.0f) { - for (c = 0; c < COM_NUMBER_OF_CHANNELS; ++c) + for (c = 0; c < COM_NO_CHANNELS_COLOR; ++c) IIR_gauss(copy, this->m_sy, c, 2); } } @@ -170,7 +170,7 @@ void *FastGaussianBlurOperation::initializeTileData(rcti *rect) dai.ymin = max(dai.ymin, buf_rect->ymin); dai.ymax = min(dai.ymax, buf_rect->ymax); - MemoryBuffer *tile = new MemoryBuffer(NULL, &dai); + MemoryBuffer *tile = MemoryBuffer::create(COM_DT_COLOR, &dai); tile->copyContentFrom(buffer); int c; @@ -178,16 +178,16 @@ void *FastGaussianBlurOperation::initializeTileData(rcti *rect) float sy = this->m_data->sizey * this->m_size / 2.0f; if ((sx == sy) && (sx > 0.f)) { - for (c = 0; c < COM_NUMBER_OF_CHANNELS; ++c) + for (c = 0; c < COM_NO_CHANNELS_COLOR; ++c) IIR_gauss(tile, sx, c, 3); } else { if (sx > 0.0f) { - for (c = 0; c < COM_NUMBER_OF_CHANNELS; ++c) + for (c = 0; c < COM_NO_CHANNELS_COLOR; ++c) IIR_gauss(tile, sx, c, 1); } if (sy > 0.0f) { - for (c = 0; c < COM_NUMBER_OF_CHANNELS; ++c) + for (c = 0; c < COM_NO_CHANNELS_COLOR; ++c) IIR_gauss(tile, sy, c, 2); } } @@ -217,6 +217,7 @@ void FastGaussianBlurOperation::IIR_gauss(MemoryBuffer *src, float sigma, unsign unsigned int x, y, sz; unsigned int i; float *buffer = src->getBuffer(); + const unsigned int no_channels = src->get_no_channels(); // <0.5 not valid, though can have a possibly useful sort of sharpening effect if (sigma < 0.5f) return; @@ -295,31 +296,31 @@ void FastGaussianBlurOperation::IIR_gauss(MemoryBuffer *src, float sigma, unsign int offset; for (y = 0; y < src_height; ++y) { const int yx = y * src_width; - offset = yx * COM_NUMBER_OF_CHANNELS + chan; + offset = yx * no_channels + chan; for (x = 0; x < src_width; ++x) { X[x] = buffer[offset]; - offset += COM_NUMBER_OF_CHANNELS; + offset += no_channels; } YVV(src_width); - offset = yx * COM_NUMBER_OF_CHANNELS + chan; + offset = yx * no_channels + chan; for (x = 0; x < src_width; ++x) { buffer[offset] = Y[x]; - offset += COM_NUMBER_OF_CHANNELS; + offset += no_channels; } } } if (xy & 2) { // V int offset; - const int add = src_width * COM_NUMBER_OF_CHANNELS; + const int add = src_width * no_channels; for (x = 0; x < src_width; ++x) { - offset = x * COM_NUMBER_OF_CHANNELS + chan; + offset = x * no_channels + chan; for (y = 0; y < src_height; ++y) { X[y] = buffer[offset]; offset += add; } YVV(src_height); - offset = x * COM_NUMBER_OF_CHANNELS + chan; + offset = x * no_channels + chan; for (y = 0; y < src_height; ++y) { buffer[offset] = Y[y]; offset += add; @@ -395,7 +396,7 @@ void *FastGaussianBlurValueOperation::initializeTileData(rcti *rect) if (this->m_overlay == FAST_GAUSS_OVERLAY_MIN) { float *src = newBuf->getBuffer(); float *dst = copy->getBuffer(); - for (int i = copy->getWidth() * copy->getHeight(); i != 0; i--, src += COM_NUMBER_OF_CHANNELS, dst += COM_NUMBER_OF_CHANNELS) { + for (int i = copy->getWidth() * copy->getHeight(); i != 0; i--, src += COM_NO_CHANNELS_VALUE, dst += COM_NO_CHANNELS_VALUE) { if (*src < *dst) { *dst = *src; } @@ -404,15 +405,13 @@ void *FastGaussianBlurValueOperation::initializeTileData(rcti *rect) else if (this->m_overlay == FAST_GAUSS_OVERLAY_MAX) { float *src = newBuf->getBuffer(); float *dst = copy->getBuffer(); - for (int i = copy->getWidth() * copy->getHeight(); i != 0; i--, src += COM_NUMBER_OF_CHANNELS, dst += COM_NUMBER_OF_CHANNELS) { + for (int i = copy->getWidth() * copy->getHeight(); i != 0; i--, src += COM_NO_CHANNELS_VALUE, dst += COM_NO_CHANNELS_VALUE) { if (*src > *dst) { *dst = *src; } } } -// newBuf-> - this->m_iirgaus = copy; } unlockMutex(); diff --git a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp index 4ae0b4e78b2..1709d1feba3 100644 --- a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp @@ -102,15 +102,14 @@ void GaussianAlphaXBlurOperation::executePixel(float output[4], int x, int y, vo /* *** this is the main part which is different to 'GaussianXBlurOperation' *** */ int step = getStep(); - int offsetadd = getOffsetAdd(); - int bufferindex = ((xmin - bufferstartx) * 4) + ((ymin - bufferstarty) * 4 * bufferwidth); + int bufferindex = ((xmin - bufferstartx)) + ((ymin - bufferstarty) * bufferwidth); /* gauss */ float alpha_accum = 0.0f; float multiplier_accum = 0.0f; /* dilate */ - float value_max = finv_test(buffer[(x * 4) + (y * 4 * bufferwidth)], do_invert); /* init with the current color to avoid unneeded lookups */ + float value_max = finv_test(buffer[(x) + (y * bufferwidth)], do_invert); /* init with the current color to avoid unneeded lookups */ float distfacinv_max = 1.0f; /* 0 to 1 */ for (int nx = xmin; nx < xmax; nx += step) { @@ -134,7 +133,7 @@ void GaussianAlphaXBlurOperation::executePixel(float output[4], int x, int y, vo distfacinv_max = multiplier; } } - bufferindex += offsetadd; + bufferindex += step; } /* blend between the max value and gauss blue - gives nice feather */ diff --git a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp index fb407bf9ee4..30e4d7b77fb 100644 --- a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp @@ -108,11 +108,11 @@ void GaussianAlphaYBlurOperation::executePixel(float output[4], int x, int y, vo float multiplier_accum = 0.0f; /* dilate */ - float value_max = finv_test(buffer[(x * 4) + (y * 4 * bufferwidth)], do_invert); /* init with the current color to avoid unneeded lookups */ + float value_max = finv_test(buffer[(x) + (y * bufferwidth)], do_invert); /* init with the current color to avoid unneeded lookups */ float distfacinv_max = 1.0f; /* 0 to 1 */ for (int ny = ymin; ny < ymax; ny += step) { - int bufferindex = ((xmin - bufferstartx) * 4) + ((ny - bufferstarty) * 4 * bufferwidth); + int bufferindex = ((xmin - bufferstartx)) + ((ny - bufferstarty) * bufferwidth); const int index = (ny - y) + this->m_filtersize; float value = finv_test(buffer[bufferindex], do_invert); diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp index 1d02f5389b1..476ec9fc043 100644 --- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp @@ -293,7 +293,7 @@ void GaussianBlurReferenceOperation::executePixel(float output[4], int x, int y, int minyr = y - refrady < 0 ? -y : -refrady; int maxyr = y + refrady > imgy ? imgy - y : refrady; - float *srcd = buffer + COM_NUMBER_OF_CHANNELS * ( (y + minyr) * imgx + x + minxr); + float *srcd = buffer + COM_NO_CHANNELS_COLOR * ( (y + minyr) * imgx + x + minxr); gausstabx = m_maintabs[refradx - 1]; gausstabcentx = gausstabx + refradx; @@ -301,9 +301,9 @@ void GaussianBlurReferenceOperation::executePixel(float output[4], int x, int y, gausstabcenty = gausstaby + refrady; sum = gval = rval = bval = aval = 0.0f; - for (i = minyr; i < maxyr; i++, srcd += COM_NUMBER_OF_CHANNELS * imgx) { + for (i = minyr; i < maxyr; i++, srcd += COM_NO_CHANNELS_COLOR * imgx) { src = srcd; - for (j = minxr; j < maxxr; j++, src += COM_NUMBER_OF_CHANNELS) { + for (j = minxr; j < maxxr; j++, src += COM_NO_CHANNELS_COLOR) { val = gausstabcenty[i] * gausstabcentx[j]; sum += val; diff --git a/source/blender/compositor/operations/COM_GlareBaseOperation.cpp b/source/blender/compositor/operations/COM_GlareBaseOperation.cpp index 8bfc3e436df..e2d6e2c8a16 100644 --- a/source/blender/compositor/operations/COM_GlareBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareBaseOperation.cpp @@ -49,7 +49,7 @@ MemoryBuffer *GlareBaseOperation::createMemoryBuffer(rcti *rect2) rect.ymin = 0; rect.xmax = getWidth(); rect.ymax = getHeight(); - MemoryBuffer *result = new MemoryBuffer(NULL, &rect); + MemoryBuffer *result = MemoryBuffer::create(COM_DT_COLOR, &rect); float *data = result->getBuffer(); this->generateGlare(data, tile, this->m_settings); return result; diff --git a/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp b/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp index 99a7c5b64c4..78337bc1a0b 100644 --- a/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp @@ -259,8 +259,8 @@ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2) float *kernelBuffer = in2->getBuffer(); float *imageBuffer = in1->getBuffer(); - MemoryBuffer *rdst = new MemoryBuffer(NULL, in1->getRect()); - memset(rdst->getBuffer(), 0, rdst->getWidth() * rdst->getHeight() * COM_NUMBER_OF_CHANNELS * sizeof(float)); + MemoryBuffer *rdst = MemoryBuffer::create(COM_DT_COLOR, in1->getRect()); + memset(rdst->getBuffer(), 0, rdst->getWidth() * rdst->getHeight() * COM_NO_CHANNELS_COLOR * sizeof(float)); // convolution result width & height w2 = 2 * kernelWidth - 1; @@ -276,7 +276,7 @@ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2) // normalize convolutor wt[0] = wt[1] = wt[2] = 0.f; for (y = 0; y < kernelHeight; y++) { - colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_NUMBER_OF_CHANNELS]; + colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_NO_CHANNELS_COLOR]; for (x = 0; x < kernelWidth; x++) add_v3_v3(wt, colp[x]); } @@ -284,7 +284,7 @@ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2) if (wt[1] != 0.f) wt[1] = 1.f / wt[1]; if (wt[2] != 0.f) wt[2] = 1.f / wt[2]; for (y = 0; y < kernelHeight; y++) { - colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_NUMBER_OF_CHANNELS]; + colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_NO_CHANNELS_COLOR]; for (x = 0; x < kernelWidth; x++) mul_v3_v3(colp[x], wt); } @@ -313,7 +313,7 @@ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2) // in2, channel ch -> data1 for (y = 0; y < kernelHeight; y++) { fp = &data1ch[y * w2]; - colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_NUMBER_OF_CHANNELS]; + colp = (fRGB *)&kernelBuffer[y * kernelWidth * COM_NO_CHANNELS_COLOR]; for (x = 0; x < kernelWidth; x++) fp[x] = colp[x][ch]; } @@ -325,7 +325,7 @@ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2) int yy = ybl * ybsz + y; if (yy >= imageHeight) continue; fp = &data2[y * w2]; - colp = (fRGB *)&imageBuffer[yy * imageWidth * COM_NUMBER_OF_CHANNELS]; + colp = (fRGB *)&imageBuffer[yy * imageWidth * COM_NO_CHANNELS_COLOR]; for (x = 0; x < xbsz; x++) { int xx = xbl * xbsz + x; if (xx >= imageWidth) continue; @@ -349,7 +349,7 @@ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2) const int yy = ybl * ybsz + y - hh; if ((yy < 0) || (yy >= imageHeight)) continue; fp = &data2[y * w2]; - colp = (fRGB *)&rdst->getBuffer()[yy * imageWidth * COM_NUMBER_OF_CHANNELS]; + colp = (fRGB *)&rdst->getBuffer()[yy * imageWidth * COM_NO_CHANNELS_COLOR]; for (x = 0; x < (int)w2; x++) { const int xx = xbl * xbsz + x - hw; if ((xx < 0) || (xx >= imageWidth)) continue; @@ -364,7 +364,7 @@ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2) MEM_freeN(data2); MEM_freeN(data1); - memcpy(dst, rdst->getBuffer(), sizeof(float) * imageWidth * imageHeight * COM_NUMBER_OF_CHANNELS); + memcpy(dst, rdst->getBuffer(), sizeof(float) * imageWidth * imageHeight * COM_NO_CHANNELS_COLOR); delete(rdst); } @@ -381,7 +381,7 @@ void GlareFogGlowOperation::generateGlare(float *data, MemoryBuffer *inputTile, // make the convolution kernel rcti kernelRect; BLI_rcti_init(&kernelRect, 0, sz, 0, sz); - ckrn = new MemoryBuffer(NULL, &kernelRect); + ckrn = MemoryBuffer::create(COM_DT_COLOR, &kernelRect); scale = 0.25f * sqrtf((float)(sz * sz)); diff --git a/source/blender/compositor/operations/COM_GlareGhostOperation.cpp b/source/blender/compositor/operations/COM_GlareGhostOperation.cpp index 8854be52ded..6cd25cfc1af 100644 --- a/source/blender/compositor/operations/COM_GlareGhostOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareGhostOperation.cpp @@ -97,7 +97,7 @@ void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, No } - memset(tbuf1->getBuffer(), 0, tbuf1->getWidth() * tbuf1->getHeight() * COM_NUMBER_OF_CHANNELS * sizeof(float)); + memset(tbuf1->getBuffer(), 0, tbuf1->getWidth() * tbuf1->getHeight() * COM_NO_CHANNELS_COLOR * sizeof(float)); for (n = 1; n < settings->iter && (!breaked); n++) { for (y = 0; y < gbuf->getHeight() && (!breaked); y++) { v = ((float)y + 0.5f) / (float)gbuf->getHeight(); @@ -117,9 +117,9 @@ void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, No } if (isBreaked()) breaked = true; } - memcpy(gbuf->getBuffer(), tbuf1->getBuffer(), tbuf1->getWidth() * tbuf1->getHeight() * COM_NUMBER_OF_CHANNELS * sizeof(float)); + memcpy(gbuf->getBuffer(), tbuf1->getBuffer(), tbuf1->getWidth() * tbuf1->getHeight() * COM_NO_CHANNELS_COLOR * sizeof(float)); } - memcpy(data, gbuf->getBuffer(), gbuf->getWidth() * gbuf->getHeight() * COM_NUMBER_OF_CHANNELS * sizeof(float)); + memcpy(data, gbuf->getBuffer(), gbuf->getWidth() * gbuf->getHeight() * COM_NO_CHANNELS_COLOR * sizeof(float)); delete gbuf; delete tbuf1; diff --git a/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp b/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp index 5644ff30ef3..cfd62fbd7ea 100644 --- a/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp @@ -36,7 +36,7 @@ void GlareStreaksOperation::generateGlare(float *data, MemoryBuffer *inputTile, bool breaked = false; MemoryBuffer *tsrc = inputTile->duplicate(); - MemoryBuffer *tdst = new MemoryBuffer(NULL, inputTile->getRect()); + MemoryBuffer *tdst = MemoryBuffer::create(COM_DT_COLOR, inputTile->getRect()); tdst->clear(); memset(data, 0, size4 * sizeof(float)); diff --git a/source/blender/compositor/operations/COM_InpaintOperation.cpp b/source/blender/compositor/operations/COM_InpaintOperation.cpp index b64c98be0c7..de8d999be80 100644 --- a/source/blender/compositor/operations/COM_InpaintOperation.cpp +++ b/source/blender/compositor/operations/COM_InpaintOperation.cpp @@ -83,8 +83,8 @@ float *InpaintSimpleOperation::get_pixel(int x, int y) ASSERT_XY_RANGE(x, y); return &this->m_cached_buffer[ - y * width * COM_NUMBER_OF_CHANNELS + - x * COM_NUMBER_OF_CHANNELS]; + y * width * COM_NO_CHANNELS_COLOR + + x * COM_NO_CHANNELS_COLOR]; } int InpaintSimpleOperation::mdist(int x, int y) diff --git a/source/blender/compositor/operations/COM_KeyingBlurOperation.cpp b/source/blender/compositor/operations/COM_KeyingBlurOperation.cpp index 9fb9efe4fc7..df34b298e7e 100644 --- a/source/blender/compositor/operations/COM_KeyingBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingBlurOperation.cpp @@ -63,7 +63,7 @@ void KeyingBlurOperation::executePixel(float output[4], int x, int y, void *data int cx = x + i; if (cx >= 0 && cx < bufferWidth) { - int bufferIndex = (y * bufferWidth + cx) * 4; + int bufferIndex = (y * bufferWidth + cx); average += buffer[bufferIndex]; count++; @@ -75,7 +75,7 @@ void KeyingBlurOperation::executePixel(float output[4], int x, int y, void *data int cy = y + i; if (cy >= 0 && cy < bufferHeight) { - int bufferIndex = (cy * bufferWidth + x) * 4; + int bufferIndex = (cy * bufferWidth + x); average += buffer[bufferIndex]; count++; diff --git a/source/blender/compositor/operations/COM_KeyingClipOperation.cpp b/source/blender/compositor/operations/COM_KeyingClipOperation.cpp index 909eeed8937..148b75a4eeb 100644 --- a/source/blender/compositor/operations/COM_KeyingClipOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingClipOperation.cpp @@ -64,7 +64,7 @@ void KeyingClipOperation::executePixel(float output[4], int x, int y, void *data int i, j, count = 0, totalCount = 0; - float value = buffer[(y * bufferWidth + x) * 4]; + float value = buffer[(y * bufferWidth + x)]; bool ok = false; @@ -76,7 +76,7 @@ void KeyingClipOperation::executePixel(float output[4], int x, int y, void *data continue; if (cx >= 0 && cx < bufferWidth && cy >= 0 && cy < bufferHeight) { - int bufferIndex = (cy * bufferWidth + cx) * 4; + int bufferIndex = (cy * bufferWidth + cx); float currentValue = buffer[bufferIndex]; if (fabsf(currentValue - value) < tolerance) { diff --git a/source/blender/compositor/operations/COM_MapUVOperation.cpp b/source/blender/compositor/operations/COM_MapUVOperation.cpp index 87ad1d6afa4..f2b333887ec 100644 --- a/source/blender/compositor/operations/COM_MapUVOperation.cpp +++ b/source/blender/compositor/operations/COM_MapUVOperation.cpp @@ -77,17 +77,17 @@ bool MapUVOperation::read_uv(float x, float y, float &r_u, float &r_v, float &r_ float width = m_inputUVProgram->getWidth(); float height = m_inputUVProgram->getHeight(); if (x < 0.0f || x >= width || y < 0.0f || y >= height) { - r_u = 0.0f; + r_u = 0.0f; r_v = 0.0f; r_alpha = 0.0f; return false; } else { - float col[4]; - m_inputUVProgram->readSampled(col, x, y, COM_PS_BILINEAR); - r_u = col[0] * m_inputColorProgram->getWidth(); - r_v = col[1] * m_inputColorProgram->getHeight(); - r_alpha = col[2]; + float vector[3]; + m_inputUVProgram->readSampled(vector, x, y, COM_PS_BILINEAR); + r_u = vector[0] * m_inputColorProgram->getWidth(); + r_v = vector[1] * m_inputColorProgram->getHeight(); + r_alpha = vector[2]; return true; } } diff --git a/source/blender/compositor/operations/COM_NormalizeOperation.cpp b/source/blender/compositor/operations/COM_NormalizeOperation.cpp index f81b50e6836..aeafe8e162d 100644 --- a/source/blender/compositor/operations/COM_NormalizeOperation.cpp +++ b/source/blender/compositor/operations/COM_NormalizeOperation.cpp @@ -104,7 +104,7 @@ void *NormalizeOperation::initializeTileData(rcti *rect) if ((value < minv) && (value >= -BLENDER_ZMAX)) { minv = value; } - bc += 4; + bc += COM_NO_CHANNELS_VALUE; } minmult->x = minv; diff --git a/source/blender/compositor/operations/COM_QualityStepHelper.cpp b/source/blender/compositor/operations/COM_QualityStepHelper.cpp index d99d6f28eff..6b62f30c98a 100644 --- a/source/blender/compositor/operations/COM_QualityStepHelper.cpp +++ b/source/blender/compositor/operations/COM_QualityStepHelper.cpp @@ -26,7 +26,7 @@ QualityStepHelper::QualityStepHelper() { this->m_quality = COM_QUALITY_HIGH; this->m_step = 1; - this->m_offsetadd = 4; + this->m_offsetadd = 4; } void QualityStepHelper::initExecution(QualityHelper helper) @@ -37,16 +37,16 @@ void QualityStepHelper::initExecution(QualityHelper helper) case COM_QUALITY_HIGH: default: this->m_step = 1; - this->m_offsetadd = 4; - break; + this->m_offsetadd = 1; + break; case COM_QUALITY_MEDIUM: this->m_step = 2; - this->m_offsetadd = 8; - break; + this->m_offsetadd = 2; + break; case COM_QUALITY_LOW: this->m_step = 3; - this->m_offsetadd = 12; - break; + this->m_offsetadd = 3; + break; } break; case COM_QH_MULTIPLY: @@ -54,16 +54,16 @@ void QualityStepHelper::initExecution(QualityHelper helper) case COM_QUALITY_HIGH: default: this->m_step = 1; - this->m_offsetadd = 4; - break; + this->m_offsetadd = 4; + break; case COM_QUALITY_MEDIUM: this->m_step = 2; - this->m_offsetadd = 8; - break; + this->m_offsetadd = 8; + break; case COM_QUALITY_LOW: this->m_step = 4; - this->m_offsetadd = 16; - break; + this->m_offsetadd = 16; + break; } break; } diff --git a/source/blender/compositor/operations/COM_ReadBufferOperation.cpp b/source/blender/compositor/operations/COM_ReadBufferOperation.cpp index 47d5fc6bcca..131fb7f01ab 100644 --- a/source/blender/compositor/operations/COM_ReadBufferOperation.cpp +++ b/source/blender/compositor/operations/COM_ReadBufferOperation.cpp @@ -24,9 +24,9 @@ #include "COM_WriteBufferOperation.h" #include "COM_defines.h" -ReadBufferOperation::ReadBufferOperation() : NodeOperation() +ReadBufferOperation::ReadBufferOperation(DataType type) : NodeOperation() { - this->addOutputSocket(COM_DT_COLOR); + this->addOutputSocket(type); this->m_single_value = false; this->m_offset = 0; this->m_buffer = NULL; diff --git a/source/blender/compositor/operations/COM_ReadBufferOperation.h b/source/blender/compositor/operations/COM_ReadBufferOperation.h index cce519c6eb3..819d7d057fd 100644 --- a/source/blender/compositor/operations/COM_ReadBufferOperation.h +++ b/source/blender/compositor/operations/COM_ReadBufferOperation.h @@ -33,7 +33,7 @@ private: unsigned int m_offset; MemoryBuffer *m_buffer; public: - ReadBufferOperation(); + ReadBufferOperation(DataType type); int isBufferOperation() { return true; } void setMemoryProxy(MemoryProxy *memoryProxy) { this->m_memoryProxy = memoryProxy; } MemoryProxy *getMemoryProxy() { return this->m_memoryProxy; } diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.cpp b/source/blender/compositor/operations/COM_RenderLayersProg.cpp index e7cda208319..672a9c24ef3 100644 --- a/source/blender/compositor/operations/COM_RenderLayersProg.cpp +++ b/source/blender/compositor/operations/COM_RenderLayersProg.cpp @@ -103,15 +103,6 @@ void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, Pi BLI_bicubic_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); break; } - - if (this->m_elementsize == 1) { - output[1] = 0.0f; - output[2] = 0.0f; - output[3] = 0.0f; - } - else if (this->m_elementsize == 3) { - output[3] = 1.0f; - } } void RenderLayersBaseProg::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) @@ -140,7 +131,15 @@ void RenderLayersBaseProg::executePixelSampled(float output[4], float x, float y #endif if (this->m_inputBuffer == NULL) { - zero_v4(output); + int elemsize = this->m_elementsize; + if (elemsize == 1) { + output[0] = 0.0f; + } + else if (elemsize == 3) { + zero_v3(output); + } else { + zero_v4(output); + } } else { doInterpolation(output, ix, iy, sampler); @@ -202,16 +201,10 @@ void RenderLayersAlphaProg::executePixelSampled(float output[4], float x, float if (inputBuffer == NULL || ix < 0 || iy < 0 || ix >= (int)this->getWidth() || iy >= (int)this->getHeight() ) { output[0] = 0.0f; - output[1] = 0.0f; - output[2] = 0.0f; - output[3] = 0.0f; } else { unsigned int offset = (iy * this->getWidth() + ix) * 4; output[0] = inputBuffer[offset + 3]; - output[1] = 0.0f; - output[2] = 0.0f; - output[3] = 0.0f; } } @@ -244,16 +237,10 @@ void RenderLayersDepthProg::executePixelSampled(float output[4], float x, float if (inputBuffer == NULL || ix < 0 || iy < 0 || ix >= (int)this->getWidth() || iy >= (int)this->getHeight() ) { output[0] = 0.0f; - output[1] = 0.0f; - output[2] = 0.0f; - output[3] = 0.0f; } else { unsigned int offset = (iy * this->getWidth() + ix); output[0] = inputBuffer[offset]; - output[1] = 0.0f; - output[2] = 0.0f; - output[3] = 0.0f; } } diff --git a/source/blender/compositor/operations/COM_SetVectorOperation.cpp b/source/blender/compositor/operations/COM_SetVectorOperation.cpp index 17212d78e15..33dddb616bb 100644 --- a/source/blender/compositor/operations/COM_SetVectorOperation.cpp +++ b/source/blender/compositor/operations/COM_SetVectorOperation.cpp @@ -33,7 +33,7 @@ void SetVectorOperation::executePixelSampled(float output[4], float x, float y, output[0] = this->m_x; output[1] = this->m_y; output[2] = this->m_z; - output[3] = this->m_w; +// output[3] = this->m_w; not supported anymore? } void SetVectorOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) diff --git a/source/blender/compositor/operations/COM_TextureOperation.cpp b/source/blender/compositor/operations/COM_TextureOperation.cpp index 96aea56050f..20d527fe70b 100644 --- a/source/blender/compositor/operations/COM_TextureOperation.cpp +++ b/source/blender/compositor/operations/COM_TextureOperation.cpp @@ -77,11 +77,9 @@ void TextureBaseOperation::determineResolution(unsigned int resolution[2], unsig void TextureAlphaOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { - TextureBaseOperation::executePixelSampled(output, x, y, sampler); - output[0] = output[3]; - output[1] = 0.0f; - output[2] = 0.0f; - output[3] = 0.0f; + float color[4]; + TextureBaseOperation::executePixelSampled(color, x, y, sampler); + output[0] = color[3]; } void TextureBaseOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) @@ -124,18 +122,23 @@ MemoryBuffer *TextureBaseOperation::createMemoryBuffer(rcti *rect2) { int height = getHeight(); int width = getWidth(); + DataType datatype = this->getOutputSocket()->getDataType(); + int add = 4; + if (datatype == COM_DT_VALUE) { + add = 1; + } rcti rect; rect.xmin = 0; rect.ymin = 0; rect.xmax = width; rect.ymax = height; - MemoryBuffer *result = new MemoryBuffer(NULL, &rect); + MemoryBuffer *result = MemoryBuffer::create(datatype, &rect); float *data = result->getBuffer(); for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++, data += 4) { + for (int x = 0; x < width; x++, data += add) { this->executePixelSampled(data, x, y, COM_PS_NEAREST); } } diff --git a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp index 4b81001fdab..f2a30ceae16 100644 --- a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp @@ -137,16 +137,19 @@ void VariableSizeBokehBlurOperation::executePixel(float output[4], int x, int y, copy_v4_fl(multiplier_accum, 1.0f); float size_center = tempSize[0] * scalar; - const int addXStep = QualityStepHelper::getStep() * COM_NUMBER_OF_CHANNELS; - + const int addXStepValue = QualityStepHelper::getStep(); + const int addYStepValue = addXStepValue; + const int addXStepColor = addXStepValue * COM_NO_CHANNELS_COLOR; + if (size_center > this->m_threshold) { - for (int ny = miny; ny < maxy; ny += QualityStepHelper::getStep()) { + for (int ny = miny; ny < maxy; ny += addYStepValue) { float dy = ny - y; - int offsetNy = ny * inputSizeBuffer->getWidth() * COM_NUMBER_OF_CHANNELS; - int offsetNxNy = offsetNy + (minx * COM_NUMBER_OF_CHANNELS); - for (int nx = minx; nx < maxx; nx += QualityStepHelper::getStep()) { + int offsetValueNy = ny * inputSizeBuffer->getWidth(); + int offsetValueNxNy = offsetValueNy + (minx); + int offsetColorNxNy = offsetValueNxNy * COM_NO_CHANNELS_COLOR; + for (int nx = minx; nx < maxx; nx += addXStepValue) { if (nx != x || ny != y) { - float size = min(inputSizeFloatBuffer[offsetNxNy] * scalar, size_center); + float size = min(inputSizeFloatBuffer[offsetValueNxNy] * scalar, size_center); if (size > this->m_threshold) { float dx = nx - x; if (size > fabsf(dx) && size > fabsf(dy)) { @@ -154,13 +157,14 @@ void VariableSizeBokehBlurOperation::executePixel(float output[4], int x, int y, (float)(COM_BLUR_BOKEH_PIXELS / 2) + (dx / size) * (float)((COM_BLUR_BOKEH_PIXELS / 2) - 1), (float)(COM_BLUR_BOKEH_PIXELS / 2) + (dy / size) * (float)((COM_BLUR_BOKEH_PIXELS / 2) - 1)}; inputBokehBuffer->readNoCheck(bokeh, uv[0], uv[1]); - madd_v4_v4v4(color_accum, bokeh, &inputProgramFloatBuffer[offsetNxNy]); + madd_v4_v4v4(color_accum, bokeh, &inputProgramFloatBuffer[offsetColorNxNy]); add_v4_v4(multiplier_accum, bokeh); } } } - offsetNxNy += addXStep; - } + offsetColorNxNy += addXStepColor; + offsetValueNxNy += addXStepValue; + } } } @@ -286,7 +290,7 @@ void InverseSearchRadiusOperation::initExecution() voi *InverseSearchRadiusOperation::initializeTileData(rcti *rect) { - MemoryBuffer * data = new MemoryBuffer(NULL, rect); + MemoryBuffer * data = MemoryBuffer::(NULL, rect); float *buffer = data->getBuffer(); int x, y; int width = this->m_inputRadius->getWidth(); diff --git a/source/blender/compositor/operations/COM_VectorBlurOperation.cpp b/source/blender/compositor/operations/COM_VectorBlurOperation.cpp index f5890157440..6fcb3ac1142 100644 --- a/source/blender/compositor/operations/COM_VectorBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_VectorBlurOperation.cpp @@ -57,7 +57,7 @@ void VectorBlurOperation::initExecution() void VectorBlurOperation::executePixel(float output[4], int x, int y, void *data) { float *buffer = (float *) data; - int index = (y * this->getWidth() + x) * COM_NUMBER_OF_CHANNELS; + int index = (y * this->getWidth() + x) * COM_NO_CHANNELS_COLOR; copy_v4_v4(output, &buffer[index]); } @@ -108,14 +108,12 @@ bool VectorBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBuff void VectorBlurOperation::generateVectorBlur(float *data, MemoryBuffer *inputImage, MemoryBuffer *inputSpeed, MemoryBuffer *inputZ) { - float *zbuf = inputZ->convertToValueBuffer(); NodeBlurData blurdata; blurdata.samples = this->m_settings->samples / QualityStepHelper::getStep(); blurdata.maxspeed = this->m_settings->maxspeed; blurdata.minspeed = this->m_settings->minspeed; blurdata.curved = this->m_settings->curved; blurdata.fac = this->m_settings->fac; - RE_zbuf_accumulate_vecblur(&blurdata, this->getWidth(), this->getHeight(), data, inputImage->getBuffer(), inputSpeed->getBuffer(), zbuf); - MEM_freeN((void *)zbuf); + RE_zbuf_accumulate_vecblur(&blurdata, this->getWidth(), this->getHeight(), data, inputImage->getBuffer(), inputSpeed->getBuffer(), inputZ->getBuffer()); return; } diff --git a/source/blender/compositor/operations/COM_VectorCurveOperation.cpp b/source/blender/compositor/operations/COM_VectorCurveOperation.cpp index fedc8c6db7d..dfdc54012a8 100644 --- a/source/blender/compositor/operations/COM_VectorCurveOperation.cpp +++ b/source/blender/compositor/operations/COM_VectorCurveOperation.cpp @@ -51,7 +51,6 @@ void VectorCurveOperation::executePixelSampled(float output[4], float x, float y this->m_inputProgram->readSampled(input, x, y, sampler); curvemapping_evaluate_premulRGBF(this->m_curveMapping, output, input); - output[3] = input[3]; } void VectorCurveOperation::deinitExecution() diff --git a/source/blender/compositor/operations/COM_WrapOperation.cpp b/source/blender/compositor/operations/COM_WrapOperation.cpp index e6cde05eae2..a48ca1acd9d 100644 --- a/source/blender/compositor/operations/COM_WrapOperation.cpp +++ b/source/blender/compositor/operations/COM_WrapOperation.cpp @@ -23,7 +23,7 @@ #include "COM_WrapOperation.h" -WrapOperation::WrapOperation() : ReadBufferOperation() +WrapOperation::WrapOperation(DataType type) : ReadBufferOperation(type) { this->m_wrappingType = CMP_NODE_WRAP_NONE; } diff --git a/source/blender/compositor/operations/COM_WrapOperation.h b/source/blender/compositor/operations/COM_WrapOperation.h index 33ea1280564..0697f89e3e7 100644 --- a/source/blender/compositor/operations/COM_WrapOperation.h +++ b/source/blender/compositor/operations/COM_WrapOperation.h @@ -29,7 +29,7 @@ class WrapOperation : public ReadBufferOperation { private: int m_wrappingType; public: - WrapOperation(); + WrapOperation(DataType type); bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp index 832864b399d..05ee13f8341 100644 --- a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp +++ b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp @@ -25,10 +25,10 @@ #include #include "COM_OpenCLDevice.h" -WriteBufferOperation::WriteBufferOperation() : NodeOperation() +WriteBufferOperation::WriteBufferOperation(DataType type) : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); - this->m_memoryProxy = new MemoryProxy(); + this->addInputSocket(type); + this->m_memoryProxy = new MemoryProxy(type); this->m_memoryProxy->setWriteBufferOperation(this); this->m_memoryProxy->setExecutor(NULL); } @@ -61,6 +61,7 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int tileNumber) { MemoryBuffer *memoryBuffer = this->m_memoryProxy->getBuffer(); float *buffer = memoryBuffer->getBuffer(); + const int no_channels = memoryBuffer->get_no_channels(); if (this->m_input->isComplex()) { void *data = this->m_input->initializeTileData(rect); int x1 = rect->xmin; @@ -71,10 +72,10 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int tileNumber) int y; bool breaked = false; for (y = y1; y < y2 && (!breaked); y++) { - int offset4 = (y * memoryBuffer->getWidth() + x1) * COM_NUMBER_OF_CHANNELS; + int offset4 = (y * memoryBuffer->getWidth() + x1) * no_channels; for (x = x1; x < x2; x++) { this->m_input->read(&(buffer[offset4]), x, y, data); - offset4 += COM_NUMBER_OF_CHANNELS; + offset4 += no_channels; } if (isBreaked()) { breaked = true; @@ -96,10 +97,10 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int tileNumber) int y; bool breaked = false; for (y = y1; y < y2 && (!breaked); y++) { - int offset4 = (y * memoryBuffer->getWidth() + x1) * COM_NUMBER_OF_CHANNELS; + int offset4 = (y * memoryBuffer->getWidth() + x1) * no_channels; for (x = x1; x < x2; x++) { this->m_input->readSampled(&(buffer[offset4]), x, y, COM_PS_NEAREST); - offset4 += COM_NUMBER_OF_CHANNELS; + offset4 += no_channels; } if (isBreaked()) { breaked = true; @@ -126,12 +127,9 @@ void WriteBufferOperation::executeOpenCLRegion(OpenCLDevice *device, rcti *rect, const unsigned int outputBufferWidth = outputBuffer->getWidth(); const unsigned int outputBufferHeight = outputBuffer->getHeight(); - const cl_image_format imageFormat = { - CL_RGBA, - CL_FLOAT - }; + const cl_image_format *imageFormat = device->determineImageFormat(outputBuffer); - cl_mem clOutputBuffer = clCreateImage2D(device->getContext(), CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, &imageFormat, outputBufferWidth, outputBufferHeight, 0, outputFloatBuffer, &error); + cl_mem clOutputBuffer = clCreateImage2D(device->getContext(), CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, imageFormat, outputBufferWidth, outputBufferHeight, 0, outputFloatBuffer, &error); if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } // STEP 2 diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.h b/source/blender/compositor/operations/COM_WriteBufferOperation.h index 1f1f58b18f1..2b677d23dad 100644 --- a/source/blender/compositor/operations/COM_WriteBufferOperation.h +++ b/source/blender/compositor/operations/COM_WriteBufferOperation.h @@ -35,7 +35,7 @@ class WriteBufferOperation : public NodeOperation { bool m_single_value; /* single value stored in buffer */ NodeOperation *m_input; public: - WriteBufferOperation(); + WriteBufferOperation(DataType type); ~WriteBufferOperation(); int isBufferOperation() { return true; } MemoryProxy *getMemoryProxy() { return this->m_memoryProxy; } -- cgit v1.2.3 From 815c99938210a5bf72f8202dcdefd6d11df65c0b Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Mon, 12 May 2014 18:21:45 +0200 Subject: Initialize colors, vectors and values in RenderLayersProg --- source/blender/compositor/operations/COM_RenderLayersProg.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.cpp b/source/blender/compositor/operations/COM_RenderLayersProg.cpp index 672a9c24ef3..f4137349e22 100644 --- a/source/blender/compositor/operations/COM_RenderLayersProg.cpp +++ b/source/blender/compositor/operations/COM_RenderLayersProg.cpp @@ -81,8 +81,15 @@ void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, Pi case COM_PS_NEAREST: { int ix = x; int iy = y; - if (ix < 0 || iy < 0 || ix >= width || iy >= height) + if (ix < 0 || iy < 0 || ix >= width || iy >= height) { + if (this->m_elementsize == 1) + output[0] = 0.0f; + else if (this->m_elementsize == 3) + zero_v3(output); + else + zero_v4(output); break; + } offset = (iy * width + ix) * this->m_elementsize; -- cgit v1.2.3