From 8f4730e66f45c300bb64fb185118f7d66355bf95 Mon Sep 17 00:00:00 2001 From: Manuel Castilla Date: Mon, 23 Aug 2021 15:28:08 +0200 Subject: Compositor: Full frame convert nodes Adds full frame implementation to all nodes in "Converter" sub-menu except "ID Mask" which is implemented separately. No functional changes. Part of T88150. Reviewed By: jbakker Differential Revision: https://developer.blender.org/D12095 --- .../operations/COM_ColorRampOperation.cc | 10 + .../compositor/operations/COM_ColorRampOperation.h | 8 +- .../compositor/operations/COM_ConvertOperation.cc | 164 +++++++++++ .../compositor/operations/COM_ConvertOperation.h | 68 ++++- .../compositor/operations/COM_MathBaseOperation.cc | 322 +++++++++++++++++++++ .../compositor/operations/COM_MathBaseOperation.h | 154 +++++++++- .../operations/COM_SetAlphaMultiplyOperation.cc | 12 + .../operations/COM_SetAlphaMultiplyOperation.h | 8 +- .../operations/COM_SetAlphaReplaceOperation.cc | 13 + .../operations/COM_SetAlphaReplaceOperation.h | 8 +- 10 files changed, 750 insertions(+), 17 deletions(-) (limited to 'source') diff --git a/source/blender/compositor/operations/COM_ColorRampOperation.cc b/source/blender/compositor/operations/COM_ColorRampOperation.cc index 0ee65a6529e..6c1b23ea731 100644 --- a/source/blender/compositor/operations/COM_ColorRampOperation.cc +++ b/source/blender/compositor/operations/COM_ColorRampOperation.cc @@ -29,6 +29,7 @@ ColorRampOperation::ColorRampOperation() this->m_inputProgram = nullptr; this->m_colorBand = nullptr; + this->flags.can_be_constant = true; } void ColorRampOperation::initExecution() { @@ -51,4 +52,13 @@ void ColorRampOperation::deinitExecution() this->m_inputProgram = nullptr; } +void ColorRampOperation::update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span inputs) +{ + for (BuffersIterator it = output->iterate_with(inputs, area); !it.is_end(); ++it) { + BKE_colorband_evaluate(m_colorBand, *it.in(0), it.out); + } +} + } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_ColorRampOperation.h b/source/blender/compositor/operations/COM_ColorRampOperation.h index d32af9bea24..ab64b9928fd 100644 --- a/source/blender/compositor/operations/COM_ColorRampOperation.h +++ b/source/blender/compositor/operations/COM_ColorRampOperation.h @@ -18,12 +18,12 @@ #pragma once -#include "COM_NodeOperation.h" +#include "COM_MultiThreadedOperation.h" #include "DNA_texture_types.h" namespace blender::compositor { -class ColorRampOperation : public NodeOperation { +class ColorRampOperation : public MultiThreadedOperation { private: /** * Cached reference to the inputProgram @@ -53,6 +53,10 @@ class ColorRampOperation : public NodeOperation { { this->m_colorBand = colorBand; } + + void update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span inputs) override; }; } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_ConvertOperation.cc b/source/blender/compositor/operations/COM_ConvertOperation.cc index 384936533c7..d377903efea 100644 --- a/source/blender/compositor/operations/COM_ConvertOperation.cc +++ b/source/blender/compositor/operations/COM_ConvertOperation.cc @@ -27,6 +27,7 @@ namespace blender::compositor { ConvertBaseOperation::ConvertBaseOperation() { this->m_inputOperation = nullptr; + this->flags.can_be_constant = true; } void ConvertBaseOperation::initExecution() @@ -39,6 +40,14 @@ void ConvertBaseOperation::deinitExecution() this->m_inputOperation = nullptr; } +void ConvertBaseOperation::update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span inputs) +{ + BuffersIterator it = output->iterate_with(inputs, area); + update_memory_buffer_partial(it); +} + /* ******** Value to Color ******** */ ConvertValueToColorOperation::ConvertValueToColorOperation() : ConvertBaseOperation() @@ -58,6 +67,14 @@ void ConvertValueToColorOperation::executePixelSampled(float output[4], output[3] = 1.0f; } +void ConvertValueToColorOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + it.out[0] = it.out[1] = it.out[2] = *it.in(0); + it.out[3] = 1.0f; + } +} + /* ******** Color to Value ******** */ ConvertColorToValueOperation::ConvertColorToValueOperation() : ConvertBaseOperation() @@ -76,6 +93,14 @@ void ConvertColorToValueOperation::executePixelSampled(float output[4], output[0] = (inputColor[0] + inputColor[1] + inputColor[2]) / 3.0f; } +void ConvertColorToValueOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + const float *in = it.in(0); + it.out[0] = (in[0] + in[1] + in[2]) / 3.0f; + } +} + /* ******** Color to BW ******** */ ConvertColorToBWOperation::ConvertColorToBWOperation() : ConvertBaseOperation() @@ -94,6 +119,13 @@ void ConvertColorToBWOperation::executePixelSampled(float output[4], output[0] = IMB_colormanagement_get_luminance(inputColor); } +void ConvertColorToBWOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + it.out[0] = IMB_colormanagement_get_luminance(it.in(0)); + } +} + /* ******** Color to Vector ******** */ ConvertColorToVectorOperation::ConvertColorToVectorOperation() : ConvertBaseOperation() @@ -112,6 +144,13 @@ void ConvertColorToVectorOperation::executePixelSampled(float output[4], copy_v3_v3(output, color); } +void ConvertColorToVectorOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + copy_v3_v3(it.out, it.in(0)); + } +} + /* ******** Value to Vector ******** */ ConvertValueToVectorOperation::ConvertValueToVectorOperation() : ConvertBaseOperation() @@ -130,6 +169,13 @@ void ConvertValueToVectorOperation::executePixelSampled(float output[4], output[0] = output[1] = output[2] = value; } +void ConvertValueToVectorOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + it.out[0] = it.out[1] = it.out[2] = *it.in(0); + } +} + /* ******** Vector to Color ******** */ ConvertVectorToColorOperation::ConvertVectorToColorOperation() : ConvertBaseOperation() @@ -147,6 +193,14 @@ void ConvertVectorToColorOperation::executePixelSampled(float output[4], output[3] = 1.0f; } +void ConvertVectorToColorOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + copy_v3_v3(it.out, it.in(0)); + it.out[3] = 1.0f; + } +} + /* ******** Vector to Value ******** */ ConvertVectorToValueOperation::ConvertVectorToValueOperation() : ConvertBaseOperation() @@ -165,6 +219,14 @@ void ConvertVectorToValueOperation::executePixelSampled(float output[4], output[0] = (input[0] + input[1] + input[2]) / 3.0f; } +void ConvertVectorToValueOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + const float *in = it.in(0); + it.out[0] = (in[0] + in[1] + in[2]) / 3.0f; + } +} + /* ******** RGB to YCC ******** */ ConvertRGBToYCCOperation::ConvertRGBToYCCOperation() : ConvertBaseOperation() @@ -207,6 +269,18 @@ void ConvertRGBToYCCOperation::executePixelSampled(float output[4], output[3] = inputColor[3]; } +void ConvertRGBToYCCOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + const float *in = it.in(0); + rgb_to_ycc(in[0], in[1], in[2], &it.out[0], &it.out[1], &it.out[2], this->m_mode); + + /* Normalize for viewing (#rgb_to_ycc returns 0-255 values). */ + mul_v3_fl(it.out, 1.0f / 255.0f); + it.out[3] = in[3]; + } +} + /* ******** YCC to RGB ******** */ ConvertYCCToRGBOperation::ConvertYCCToRGBOperation() : ConvertBaseOperation() @@ -253,6 +327,22 @@ void ConvertYCCToRGBOperation::executePixelSampled(float output[4], output[3] = inputColor[3]; } +void ConvertYCCToRGBOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + const float *in = it.in(0); + /* Multiply by 255 to un-normalize (#ycc_to_rgb needs input values in 0-255 range). */ + ycc_to_rgb(in[0] * 255.0f, + in[1] * 255.0f, + in[2] * 255.0f, + &it.out[0], + &it.out[1], + &it.out[2], + this->m_mode); + it.out[3] = in[3]; + } +} + /* ******** RGB to YUV ******** */ ConvertRGBToYUVOperation::ConvertRGBToYUVOperation() : ConvertBaseOperation() @@ -278,6 +368,15 @@ void ConvertRGBToYUVOperation::executePixelSampled(float output[4], output[3] = inputColor[3]; } +void ConvertRGBToYUVOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + const float *in = it.in(0); + rgb_to_yuv(in[0], in[1], in[2], &it.out[0], &it.out[1], &it.out[2], BLI_YUV_ITU_BT709); + it.out[3] = in[3]; + } +} + /* ******** YUV to RGB ******** */ ConvertYUVToRGBOperation::ConvertYUVToRGBOperation() : ConvertBaseOperation() @@ -303,6 +402,15 @@ void ConvertYUVToRGBOperation::executePixelSampled(float output[4], output[3] = inputColor[3]; } +void ConvertYUVToRGBOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + const float *in = it.in(0); + yuv_to_rgb(in[0], in[1], in[2], &it.out[0], &it.out[1], &it.out[2], BLI_YUV_ITU_BT709); + it.out[3] = in[3]; + } +} + /* ******** RGB to HSV ******** */ ConvertRGBToHSVOperation::ConvertRGBToHSVOperation() : ConvertBaseOperation() @@ -322,6 +430,15 @@ void ConvertRGBToHSVOperation::executePixelSampled(float output[4], output[3] = inputColor[3]; } +void ConvertRGBToHSVOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + const float *in = it.in(0); + rgb_to_hsv_v(in, it.out); + it.out[3] = in[3]; + } +} + /* ******** HSV to RGB ******** */ ConvertHSVToRGBOperation::ConvertHSVToRGBOperation() : ConvertBaseOperation() @@ -344,6 +461,18 @@ void ConvertHSVToRGBOperation::executePixelSampled(float output[4], output[3] = inputColor[3]; } +void ConvertHSVToRGBOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + const float *in = it.in(0); + hsv_to_rgb_v(in, it.out); + it.out[0] = max_ff(it.out[0], 0.0f); + it.out[1] = max_ff(it.out[1], 0.0f); + it.out[2] = max_ff(it.out[2], 0.0f); + it.out[3] = in[3]; + } +} + /* ******** Premul to Straight ******** */ ConvertPremulToStraightOperation::ConvertPremulToStraightOperation() : ConvertBaseOperation() @@ -363,6 +492,13 @@ void ConvertPremulToStraightOperation::executePixelSampled(float output[4], copy_v4_v4(output, converted); } +void ConvertPremulToStraightOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + copy_v4_v4(it.out, ColorSceneLinear4f(it.in(0)).unpremultiply_alpha()); + } +} + /* ******** Straight to Premul ******** */ ConvertStraightToPremulOperation::ConvertStraightToPremulOperation() : ConvertBaseOperation() @@ -382,6 +518,13 @@ void ConvertStraightToPremulOperation::executePixelSampled(float output[4], copy_v4_v4(output, converted); } +void ConvertStraightToPremulOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + copy_v4_v4(it.out, ColorSceneLinear4f(it.in(0)).premultiply_alpha()); + } +} + /* ******** Separate Channels ******** */ SeparateChannelOperation::SeparateChannelOperation() @@ -410,6 +553,15 @@ void SeparateChannelOperation::executePixelSampled(float output[4], output[0] = input[this->m_channel]; } +void SeparateChannelOperation::update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span inputs) +{ + for (BuffersIterator it = output->iterate_with(inputs, area); !it.is_end(); ++it) { + it.out[0] = it.in(0)[this->m_channel]; + } +} + /* ******** Combine Channels ******** */ CombineChannelsOperation::CombineChannelsOperation() @@ -466,4 +618,16 @@ void CombineChannelsOperation::executePixelSampled(float output[4], } } +void CombineChannelsOperation::update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span inputs) +{ + for (BuffersIterator it = output->iterate_with(inputs, area); !it.is_end(); ++it) { + it.out[0] = *it.in(0); + it.out[1] = *it.in(1); + it.out[2] = *it.in(2); + it.out[3] = *it.in(3); + } +} + } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_ConvertOperation.h b/source/blender/compositor/operations/COM_ConvertOperation.h index 7a726e35c7c..0334959ae7e 100644 --- a/source/blender/compositor/operations/COM_ConvertOperation.h +++ b/source/blender/compositor/operations/COM_ConvertOperation.h @@ -18,11 +18,11 @@ #pragma once -#include "COM_NodeOperation.h" +#include "COM_MultiThreadedOperation.h" namespace blender::compositor { -class ConvertBaseOperation : public NodeOperation { +class ConvertBaseOperation : public MultiThreadedOperation { protected: SocketReader *m_inputOperation; @@ -31,6 +31,13 @@ class ConvertBaseOperation : public NodeOperation { void initExecution() override; void deinitExecution() override; + + void update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span inputs) final; + + protected: + virtual void update_memory_buffer_partial(BuffersIterator &it) = 0; }; class ConvertValueToColorOperation : public ConvertBaseOperation { @@ -38,6 +45,9 @@ class ConvertValueToColorOperation : public ConvertBaseOperation { ConvertValueToColorOperation(); void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class ConvertColorToValueOperation : public ConvertBaseOperation { @@ -45,6 +55,9 @@ class ConvertColorToValueOperation : public ConvertBaseOperation { ConvertColorToValueOperation(); void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class ConvertColorToBWOperation : public ConvertBaseOperation { @@ -52,6 +65,9 @@ class ConvertColorToBWOperation : public ConvertBaseOperation { ConvertColorToBWOperation(); void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class ConvertColorToVectorOperation : public ConvertBaseOperation { @@ -59,6 +75,9 @@ class ConvertColorToVectorOperation : public ConvertBaseOperation { ConvertColorToVectorOperation(); void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class ConvertValueToVectorOperation : public ConvertBaseOperation { @@ -66,6 +85,9 @@ class ConvertValueToVectorOperation : public ConvertBaseOperation { ConvertValueToVectorOperation(); void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class ConvertVectorToColorOperation : public ConvertBaseOperation { @@ -73,6 +95,9 @@ class ConvertVectorToColorOperation : public ConvertBaseOperation { ConvertVectorToColorOperation(); void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class ConvertVectorToValueOperation : public ConvertBaseOperation { @@ -80,6 +105,9 @@ class ConvertVectorToValueOperation : public ConvertBaseOperation { ConvertVectorToValueOperation(); void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class ConvertRGBToYCCOperation : public ConvertBaseOperation { @@ -94,6 +122,9 @@ class ConvertRGBToYCCOperation : public ConvertBaseOperation { /** Set the YCC mode */ void setMode(int mode); + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class ConvertYCCToRGBOperation : public ConvertBaseOperation { @@ -108,6 +139,9 @@ class ConvertYCCToRGBOperation : public ConvertBaseOperation { /** Set the YCC mode */ void setMode(int mode); + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class ConvertRGBToYUVOperation : public ConvertBaseOperation { @@ -115,6 +149,9 @@ class ConvertRGBToYUVOperation : public ConvertBaseOperation { ConvertRGBToYUVOperation(); void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class ConvertYUVToRGBOperation : public ConvertBaseOperation { @@ -122,6 +159,9 @@ class ConvertYUVToRGBOperation : public ConvertBaseOperation { ConvertYUVToRGBOperation(); void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class ConvertRGBToHSVOperation : public ConvertBaseOperation { @@ -129,6 +169,9 @@ class ConvertRGBToHSVOperation : public ConvertBaseOperation { ConvertRGBToHSVOperation(); void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class ConvertHSVToRGBOperation : public ConvertBaseOperation { @@ -136,6 +179,9 @@ class ConvertHSVToRGBOperation : public ConvertBaseOperation { ConvertHSVToRGBOperation(); void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class ConvertPremulToStraightOperation : public ConvertBaseOperation { @@ -143,6 +189,9 @@ class ConvertPremulToStraightOperation : public ConvertBaseOperation { ConvertPremulToStraightOperation(); void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class ConvertStraightToPremulOperation : public ConvertBaseOperation { @@ -150,9 +199,12 @@ class ConvertStraightToPremulOperation : public ConvertBaseOperation { ConvertStraightToPremulOperation(); void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; -class SeparateChannelOperation : public NodeOperation { +class SeparateChannelOperation : public MultiThreadedOperation { private: SocketReader *m_inputOperation; int m_channel; @@ -168,9 +220,13 @@ class SeparateChannelOperation : public NodeOperation { { this->m_channel = channel; } + + void update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span inputs) override; }; -class CombineChannelsOperation : public NodeOperation { +class CombineChannelsOperation : public MultiThreadedOperation { private: SocketReader *m_inputChannel1Operation; SocketReader *m_inputChannel2Operation; @@ -183,6 +239,10 @@ class CombineChannelsOperation : public NodeOperation { void initExecution() override; void deinitExecution() override; + + void update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span inputs) override; }; } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.cc b/source/blender/compositor/operations/COM_MathBaseOperation.cc index a94c14347fb..2256dce011b 100644 --- a/source/blender/compositor/operations/COM_MathBaseOperation.cc +++ b/source/blender/compositor/operations/COM_MathBaseOperation.cc @@ -24,6 +24,8 @@ namespace blender::compositor { MathBaseOperation::MathBaseOperation() { + /* TODO(manzanilla): after removing tiled implementation, template this class to only add needed + * number of inputs. */ this->addInputSocket(DataType::Value); this->addInputSocket(DataType::Value); this->addInputSocket(DataType::Value); @@ -32,6 +34,7 @@ MathBaseOperation::MathBaseOperation() this->m_inputValue2Operation = nullptr; this->m_inputValue3Operation = nullptr; this->m_useClamp = false; + this->flags.can_be_constant = true; } void MathBaseOperation::initExecution() @@ -73,6 +76,14 @@ void MathBaseOperation::clampIfNeeded(float *color) } } +void MathBaseOperation::update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span inputs) +{ + BuffersIterator it = output->iterate_with(inputs, area); + update_memory_buffer_partial(it); +} + void MathAddOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { float inputValue1[4]; @@ -139,6 +150,14 @@ void MathDivideOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathDivideOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + const float divisor = *it.in(1); + *it.out = clamp_when_enabled((divisor == 0) ? 0 : *it.in(0) / divisor); + } +} + void MathSineOperation::executePixelSampled(float output[4], float x, float y, @@ -155,6 +174,14 @@ void MathSineOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathSineOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = sin(*it.in(0)); + clamp_when_enabled(it.out); + } +} + void MathCosineOperation::executePixelSampled(float output[4], float x, float y, @@ -171,6 +198,14 @@ void MathCosineOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathCosineOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = cos(*it.in(0)); + clamp_when_enabled(it.out); + } +} + void MathTangentOperation::executePixelSampled(float output[4], float x, float y, @@ -187,6 +222,14 @@ void MathTangentOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathTangentOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = tan(*it.in(0)); + clamp_when_enabled(it.out); + } +} + void MathHyperbolicSineOperation::executePixelSampled(float output[4], float x, float y, @@ -203,6 +246,14 @@ void MathHyperbolicSineOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathHyperbolicSineOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = sinh(*it.in(0)); + clamp_when_enabled(it.out); + } +} + void MathHyperbolicCosineOperation::executePixelSampled(float output[4], float x, float y, @@ -219,6 +270,14 @@ void MathHyperbolicCosineOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathHyperbolicCosineOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = cosh(*it.in(0)); + clamp_when_enabled(it.out); + } +} + void MathHyperbolicTangentOperation::executePixelSampled(float output[4], float x, float y, @@ -235,6 +294,14 @@ void MathHyperbolicTangentOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathHyperbolicTangentOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = tanh(*it.in(0)); + clamp_when_enabled(it.out); + } +} + void MathArcSineOperation::executePixelSampled(float output[4], float x, float y, @@ -256,6 +323,14 @@ void MathArcSineOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathArcSineOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + float value1 = *it.in(0); + *it.out = clamp_when_enabled((value1 <= 1 && value1 >= -1) ? asin(value1) : 0.0f); + } +} + void MathArcCosineOperation::executePixelSampled(float output[4], float x, float y, @@ -277,6 +352,14 @@ void MathArcCosineOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathArcCosineOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + float value1 = *it.in(0); + *it.out = clamp_when_enabled((value1 <= 1 && value1 >= -1) ? acos(value1) : 0.0f); + } +} + void MathArcTangentOperation::executePixelSampled(float output[4], float x, float y, @@ -293,6 +376,14 @@ void MathArcTangentOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathArcTangentOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = atan(*it.in(0)); + clamp_when_enabled(it.out); + } +} + void MathPowerOperation::executePixelSampled(float output[4], float x, float y, @@ -321,6 +412,29 @@ void MathPowerOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathPowerOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + const float value1 = *it.in(0); + const float value2 = *it.in(1); + if (value1 >= 0) { + *it.out = pow(value1, value2); + } + else { + const float y_mod_1 = fmod(value2, 1); + /* If input value is not nearly an integer, fall back to zero, nicer than straight rounding. + */ + if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) { + *it.out = pow(value1, floorf(value2 + 0.5f)); + } + else { + *it.out = 0.0f; + } + } + clamp_when_enabled(it.out); + } +} + void MathLogarithmOperation::executePixelSampled(float output[4], float x, float y, @@ -342,6 +456,21 @@ void MathLogarithmOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathLogarithmOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + const float value1 = *it.in(0); + const float value2 = *it.in(1); + if (value1 > 0 && value2 > 0) { + *it.out = log(value1) / log(value2); + } + else { + *it.out = 0.0; + } + clamp_when_enabled(it.out); + } +} + void MathMinimumOperation::executePixelSampled(float output[4], float x, float y, @@ -358,6 +487,14 @@ void MathMinimumOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathMinimumOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = MIN2(*it.in(0), *it.in(1)); + clamp_when_enabled(it.out); + } +} + void MathMaximumOperation::executePixelSampled(float output[4], float x, float y, @@ -374,6 +511,14 @@ void MathMaximumOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathMaximumOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = MAX2(*it.in(0), *it.in(1)); + clamp_when_enabled(it.out); + } +} + void MathRoundOperation::executePixelSampled(float output[4], float x, float y, @@ -390,6 +535,14 @@ void MathRoundOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathRoundOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = round(*it.in(0)); + clamp_when_enabled(it.out); + } +} + void MathLessThanOperation::executePixelSampled(float output[4], float x, float y, @@ -443,6 +596,15 @@ void MathModuloOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathModuloOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + const float value2 = *it.in(1); + *it.out = (value2 == 0) ? 0 : fmod(*it.in(0), value2); + clamp_when_enabled(it.out); + } +} + void MathAbsoluteOperation::executePixelSampled(float output[4], float x, float y, @@ -457,6 +619,14 @@ void MathAbsoluteOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathAbsoluteOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = fabs(*it.in(0)); + clamp_when_enabled(it.out); + } +} + void MathRadiansOperation::executePixelSampled(float output[4], float x, float y, @@ -471,6 +641,14 @@ void MathRadiansOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathRadiansOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = DEG2RADF(*it.in(0)); + clamp_when_enabled(it.out); + } +} + void MathDegreesOperation::executePixelSampled(float output[4], float x, float y, @@ -485,6 +663,14 @@ void MathDegreesOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathDegreesOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = RAD2DEGF(*it.in(0)); + clamp_when_enabled(it.out); + } +} + void MathArcTan2Operation::executePixelSampled(float output[4], float x, float y, @@ -501,6 +687,14 @@ void MathArcTan2Operation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathArcTan2Operation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = atan2(*it.in(0), *it.in(1)); + clamp_when_enabled(it.out); + } +} + void MathFloorOperation::executePixelSampled(float output[4], float x, float y, @@ -515,6 +709,14 @@ void MathFloorOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathFloorOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = floor(*it.in(0)); + clamp_when_enabled(it.out); + } +} + void MathCeilOperation::executePixelSampled(float output[4], float x, float y, @@ -529,6 +731,14 @@ void MathCeilOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathCeilOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = ceil(*it.in(0)); + clamp_when_enabled(it.out); + } +} + void MathFractOperation::executePixelSampled(float output[4], float x, float y, @@ -543,6 +753,14 @@ void MathFractOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathFractOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + const float value = *it.in(0); + *it.out = clamp_when_enabled(value - floor(value)); + } +} + void MathSqrtOperation::executePixelSampled(float output[4], float x, float y, @@ -562,6 +780,14 @@ void MathSqrtOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathSqrtOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + const float value = *it.in(0); + *it.out = clamp_when_enabled(value > 0 ? sqrt(value) : 0.0f); + } +} + void MathInverseSqrtOperation::executePixelSampled(float output[4], float x, float y, @@ -581,6 +807,14 @@ void MathInverseSqrtOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathInverseSqrtOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + const float value = *it.in(0); + *it.out = clamp_when_enabled(value > 0 ? 1.0f / sqrt(value) : 0.0f); + } +} + void MathSignOperation::executePixelSampled(float output[4], float x, float y, @@ -595,6 +829,14 @@ void MathSignOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathSignOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = compatible_signf(*it.in(0)); + clamp_when_enabled(it.out); + } +} + void MathExponentOperation::executePixelSampled(float output[4], float x, float y, @@ -609,6 +851,14 @@ void MathExponentOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathExponentOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = expf(*it.in(0)); + clamp_when_enabled(it.out); + } +} + void MathTruncOperation::executePixelSampled(float output[4], float x, float y, @@ -623,6 +873,15 @@ void MathTruncOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathTruncOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + const float value = *it.in(0); + *it.out = (value >= 0.0f) ? floor(value) : ceil(value); + clamp_when_enabled(it.out); + } +} + void MathSnapOperation::executePixelSampled(float output[4], float x, float y, @@ -644,6 +903,21 @@ void MathSnapOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathSnapOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + const float value1 = *it.in(0); + const float value2 = *it.in(1); + if (value1 == 0 || value2 == 0) { /* Avoid dividing by zero. */ + *it.out = 0.0f; + } + else { + *it.out = floorf(value1 / value2) * value2; + } + clamp_when_enabled(it.out); + } +} + void MathWrapOperation::executePixelSampled(float output[4], float x, float y, @@ -662,6 +936,14 @@ void MathWrapOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathWrapOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = wrapf(*it.in(0), *it.in(1), *it.in(2)); + clamp_when_enabled(it.out); + } +} + void MathPingpongOperation::executePixelSampled(float output[4], float x, float y, @@ -678,6 +960,14 @@ void MathPingpongOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathPingpongOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = pingpongf(*it.in(0), *it.in(1)); + clamp_when_enabled(it.out); + } +} + void MathCompareOperation::executePixelSampled(float output[4], float x, float y, @@ -697,6 +987,14 @@ void MathCompareOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathCompareOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = (fabsf(*it.in(0) - *it.in(1)) <= MAX2(*it.in(2), 1e-5f)) ? 1.0f : 0.0f; + clamp_when_enabled(it.out); + } +} + void MathMultiplyAddOperation::executePixelSampled(float output[4], float x, float y, @@ -715,6 +1013,14 @@ void MathMultiplyAddOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathMultiplyAddOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = it.in(0)[0] * it.in(1)[0] + it.in(2)[0]; + clamp_when_enabled(it.out); + } +} + void MathSmoothMinOperation::executePixelSampled(float output[4], float x, float y, @@ -733,6 +1039,14 @@ void MathSmoothMinOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathSmoothMinOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = smoothminf(*it.in(0), *it.in(1), *it.in(2)); + clamp_when_enabled(it.out); + } +} + void MathSmoothMaxOperation::executePixelSampled(float output[4], float x, float y, @@ -751,4 +1065,12 @@ void MathSmoothMaxOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MathSmoothMaxOperation::update_memory_buffer_partial(BuffersIterator &it) +{ + for (; !it.is_end(); ++it) { + *it.out = -smoothminf(-it.in(0)[0], -it.in(1)[0], it.in(2)[0]); + clamp_when_enabled(it.out); + } +} + } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.h b/source/blender/compositor/operations/COM_MathBaseOperation.h index 08794c8db22..d2da05db68e 100644 --- a/source/blender/compositor/operations/COM_MathBaseOperation.h +++ b/source/blender/compositor/operations/COM_MathBaseOperation.h @@ -18,7 +18,7 @@ #pragma once -#include "COM_NodeOperation.h" +#include "COM_MultiThreadedOperation.h" namespace blender::compositor { @@ -26,7 +26,7 @@ namespace blender::compositor { * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ -class MathBaseOperation : public NodeOperation { +class MathBaseOperation : public MultiThreadedOperation { protected: /** * Prefetched reference to the inputProgram @@ -43,8 +43,24 @@ class MathBaseOperation : public NodeOperation { */ MathBaseOperation(); + /* TODO(manzanilla): to be removed with tiled implementation. */ void clampIfNeeded(float color[4]); + float clamp_when_enabled(float value) + { + if (this->m_useClamp) { + return CLAMPIS(value, 0.0f, 1.0f); + } + return value; + } + + void clamp_when_enabled(float *out) + { + if (this->m_useClamp) { + CLAMP(*out, 0.0f, 1.0f); + } + } + public: /** * Initialize the execution @@ -66,87 +82,151 @@ class MathBaseOperation : public NodeOperation { { this->m_useClamp = value; } + + void update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span inputs) final; + + protected: + virtual void update_memory_buffer_partial(BuffersIterator &it) = 0; }; -class MathAddOperation : public MathBaseOperation { +template typename TFunctor> +class MathFunctor2Operation : public MathBaseOperation { + void update_memory_buffer_partial(BuffersIterator &it) final + { + TFunctor functor; + for (; !it.is_end(); ++it) { + *it.out = functor(*it.in(0), *it.in(1)); + clamp_when_enabled(it.out); + } + } +}; + +class MathAddOperation : public MathFunctor2Operation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; }; -class MathSubtractOperation : public MathBaseOperation { +class MathSubtractOperation : public MathFunctor2Operation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; }; -class MathMultiplyOperation : public MathBaseOperation { +class MathMultiplyOperation : public MathFunctor2Operation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; }; class MathDivideOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathSineOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathCosineOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathTangentOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathHyperbolicSineOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathHyperbolicCosineOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathHyperbolicTangentOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathArcSineOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathArcCosineOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathArcTangentOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathPowerOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathLogarithmOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathMinimumOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathMaximumOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathRoundOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; -class MathLessThanOperation : public MathBaseOperation { +class MathLessThanOperation : public MathFunctor2Operation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; }; -class MathGreaterThanOperation : public MathBaseOperation { +class MathGreaterThanOperation : public MathFunctor2Operation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; }; @@ -154,101 +234,161 @@ class MathGreaterThanOperation : public MathBaseOperation { class MathModuloOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathAbsoluteOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathRadiansOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathDegreesOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathArcTan2Operation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathFloorOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathCeilOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathFractOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathSqrtOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathInverseSqrtOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathSignOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathExponentOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathTruncOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathSnapOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathWrapOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathPingpongOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathCompareOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathMultiplyAddOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathSmoothMinOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; class MathSmoothMaxOperation : public MathBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_partial(BuffersIterator &it) override; }; } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.cc b/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.cc index 24edbc61d40..e4686ffa76d 100644 --- a/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.cc +++ b/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.cc @@ -28,6 +28,7 @@ SetAlphaMultiplyOperation::SetAlphaMultiplyOperation() this->m_inputColor = nullptr; this->m_inputAlpha = nullptr; + this->flags.can_be_constant = true; } void SetAlphaMultiplyOperation::initExecution() @@ -56,4 +57,15 @@ void SetAlphaMultiplyOperation::deinitExecution() this->m_inputAlpha = nullptr; } +void SetAlphaMultiplyOperation::update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span inputs) +{ + for (BuffersIterator it = output->iterate_with(inputs, area); !it.is_end(); ++it) { + const float *color = it.in(0); + const float alpha = *it.in(1); + mul_v4_v4fl(it.out, color, alpha); + } +} + } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.h b/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.h index b4eea659fa2..44885318901 100644 --- a/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.h +++ b/source/blender/compositor/operations/COM_SetAlphaMultiplyOperation.h @@ -18,7 +18,7 @@ #pragma once -#include "COM_NodeOperation.h" +#include "COM_MultiThreadedOperation.h" namespace blender::compositor { @@ -27,7 +27,7 @@ namespace blender::compositor { * * `output color.rgba = input color.rgba * input alpha` */ -class SetAlphaMultiplyOperation : public NodeOperation { +class SetAlphaMultiplyOperation : public MultiThreadedOperation { private: SocketReader *m_inputColor; SocketReader *m_inputAlpha; @@ -39,6 +39,10 @@ class SetAlphaMultiplyOperation : public NodeOperation { void initExecution() override; void deinitExecution() override; + + void update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span inputs) override; }; } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.cc b/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.cc index 90bfc814b09..434f5d9b63c 100644 --- a/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.cc +++ b/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.cc @@ -28,6 +28,7 @@ SetAlphaReplaceOperation::SetAlphaReplaceOperation() this->m_inputColor = nullptr; this->m_inputAlpha = nullptr; + this->flags.can_be_constant = true; } void SetAlphaReplaceOperation::initExecution() @@ -54,4 +55,16 @@ void SetAlphaReplaceOperation::deinitExecution() this->m_inputAlpha = nullptr; } +void SetAlphaReplaceOperation::update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span inputs) +{ + for (BuffersIterator it = output->iterate_with(inputs, area); !it.is_end(); ++it) { + const float *color = it.in(0); + const float alpha = *it.in(1); + copy_v3_v3(it.out, color); + it.out[3] = alpha; + } +} + } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.h b/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.h index c84299b6d82..2c2d4cddf5b 100644 --- a/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.h +++ b/source/blender/compositor/operations/COM_SetAlphaReplaceOperation.h @@ -18,7 +18,7 @@ #pragma once -#include "COM_NodeOperation.h" +#include "COM_MultiThreadedOperation.h" namespace blender::compositor { @@ -26,7 +26,7 @@ namespace blender::compositor { * this program converts an input color to an output value. * it assumes we are in sRGB color space. */ -class SetAlphaReplaceOperation : public NodeOperation { +class SetAlphaReplaceOperation : public MultiThreadedOperation { private: SocketReader *m_inputColor; SocketReader *m_inputAlpha; @@ -44,6 +44,10 @@ class SetAlphaReplaceOperation : public NodeOperation { void initExecution() override; void deinitExecution() override; + + void update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span inputs) override; }; } // namespace blender::compositor -- cgit v1.2.3