diff options
author | Manuel Castilla <manzanillawork@gmail.com> | 2021-07-19 19:48:04 +0300 |
---|---|---|
committer | Manuel Castilla <manzanillawork@gmail.com> | 2021-07-19 23:05:39 +0300 |
commit | b35efa932e03232057e10a4c06291bd362d0cd56 (patch) | |
tree | 16433b2ff780efac44513796771b1dcbc59de179 /source/blender | |
parent | 300fe84bf0ad28b08ec3b5615d15d6b7352e3f7a (diff) |
Compositor: Full frame Mix node
Adds full frame implementation to this node operations.
No functional changes.
2.3x faster than tiled fallback on average.
Reviewed By: jbakker
Differential Revision: https://developer.blender.org/D11686
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/compositor/operations/COM_MixOperation.cc | 555 | ||||
-rw-r--r-- | source/blender/compositor/operations/COM_MixOperation.h | 89 |
2 files changed, 642 insertions, 2 deletions
diff --git a/source/blender/compositor/operations/COM_MixOperation.cc b/source/blender/compositor/operations/COM_MixOperation.cc index 58fa09fa2a8..77ecbf60356 100644 --- a/source/blender/compositor/operations/COM_MixOperation.cc +++ b/source/blender/compositor/operations/COM_MixOperation.cc @@ -35,6 +35,7 @@ MixBaseOperation::MixBaseOperation() this->m_inputColor2Operation = nullptr; this->setUseValueAlphaMultiply(false); this->setUseClamp(false); + flags.can_be_constant = true; } void MixBaseOperation::initExecution() @@ -97,6 +98,45 @@ void MixBaseOperation::deinitExecution() this->m_inputColor2Operation = nullptr; } +void MixBaseOperation::update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> inputs) +{ + const MemoryBuffer *input_value = inputs[0]; + const MemoryBuffer *input_color1 = inputs[1]; + const MemoryBuffer *input_color2 = inputs[2]; + const int width = BLI_rcti_size_x(&area); + PixelCursor p; + p.out_stride = output->elem_stride; + p.value_stride = input_value->elem_stride; + p.color1_stride = input_color1->elem_stride; + p.color2_stride = input_color2->elem_stride; + for (const int y : YRange(area)) { + p.out = output->get_elem(area.xmin, y); + p.row_end = p.out + width * output->elem_stride; + p.value = input_value->get_elem(area.xmin, y); + p.color1 = input_color1->get_elem(area.xmin, y); + p.color2 = input_color2->get_elem(area.xmin, y); + update_memory_buffer_row(p); + } +} + +void MixBaseOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + const float value_m = 1.0f - value; + p.out[0] = value_m * p.color1[0] + value * p.color2[0]; + p.out[1] = value_m * p.color1[1] + value * p.color2[1]; + p.out[2] = value_m * p.color1[2] + value * p.color2[2]; + p.out[3] = p.color1[3]; + p.next(); + } +} + /* ******** Mix Add Operation ******** */ void MixAddOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) @@ -121,6 +161,23 @@ void MixAddOperation::executePixelSampled(float output[4], float x, float y, Pix clampIfNeeded(output); } +void MixAddOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + p.out[0] = p.color1[0] + value * p.color2[0]; + p.out[1] = p.color1[1] + value * p.color2[1]; + p.out[2] = p.color1[2] + value * p.color2[2]; + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Blend Operation ******** */ void MixBlendOperation::executePixelSampled(float output[4], @@ -150,6 +207,24 @@ void MixBlendOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixBlendOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + float value_m = 1.0f - value; + p.out[0] = value_m * p.color1[0] + value * p.color2[0]; + p.out[1] = value_m * p.color1[1] + value * p.color2[1]; + p.out[2] = value_m * p.color1[2] + value * p.color2[2]; + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Burn Operation ******** */ void MixColorBurnOperation::executePixelSampled(float output[4], @@ -228,6 +303,48 @@ void MixColorBurnOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixColorBurnOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + const float value_m = 1.0f - value; + + float tmp = value_m + value * p.color2[0]; + if (tmp <= 0.0f) { + p.out[0] = 0.0f; + } + else { + tmp = 1.0f - (1.0f - p.color1[0]) / tmp; + p.out[0] = CLAMPIS(tmp, 0.0f, 1.0f); + } + + tmp = value_m + value * p.color2[1]; + if (tmp <= 0.0f) { + p.out[1] = 0.0f; + } + else { + tmp = 1.0f - (1.0f - p.color1[1]) / tmp; + p.out[1] = CLAMPIS(tmp, 0.0f, 1.0f); + } + + tmp = value_m + value * p.color2[2]; + if (tmp <= 0.0f) { + p.out[2] = 0.0f; + } + else { + tmp = 1.0f - (1.0f - p.color1[2]) / tmp; + p.out[2] = CLAMPIS(tmp, 0.0f, 1.0f); + } + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Color Operation ******** */ void MixColorOperation::executePixelSampled(float output[4], @@ -268,6 +385,36 @@ void MixColorOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixColorOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + const float value_m = 1.0f - value; + + float colH, colS, colV; + rgb_to_hsv(p.color2[0], p.color2[1], p.color2[2], &colH, &colS, &colV); + if (colS != 0.0f) { + float rH, rS, rV; + float tmpr, tmpg, tmpb; + rgb_to_hsv(p.color1[0], p.color1[1], p.color1[2], &rH, &rS, &rV); + hsv_to_rgb(colH, colS, rV, &tmpr, &tmpg, &tmpb); + p.out[0] = (value_m * p.color1[0]) + (value * tmpr); + p.out[1] = (value_m * p.color1[1]) + (value * tmpg); + p.out[2] = (value_m * p.color1[2]) + (value * tmpb); + } + else { + copy_v3_v3(p.out, p.color1); + } + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Darken Operation ******** */ void MixDarkenOperation::executePixelSampled(float output[4], @@ -296,6 +443,24 @@ void MixDarkenOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixDarkenOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + float value_m = 1.0f - value; + p.out[0] = min_ff(p.color1[0], p.color2[0]) * value + p.color1[0] * value_m; + p.out[1] = min_ff(p.color1[1], p.color2[1]) * value + p.color1[1] * value_m; + p.out[2] = min_ff(p.color1[2], p.color2[2]) * value + p.color1[2] * value_m; + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Difference Operation ******** */ void MixDifferenceOperation::executePixelSampled(float output[4], @@ -324,6 +489,24 @@ void MixDifferenceOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixDifferenceOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + const float value_m = 1.0f - value; + p.out[0] = value_m * p.color1[0] + value * fabsf(p.color1[0] - p.color2[0]); + p.out[1] = value_m * p.color1[1] + value * fabsf(p.color1[1] - p.color2[1]); + p.out[2] = value_m * p.color1[2] + value * fabsf(p.color1[2] - p.color2[2]); + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Difference Operation ******** */ void MixDivideOperation::executePixelSampled(float output[4], @@ -369,6 +552,41 @@ void MixDivideOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixDivideOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + const float value_m = 1.0f - value; + + if (p.color2[0] != 0.0f) { + p.out[0] = value_m * (p.color1[0]) + value * (p.color1[0]) / p.color2[0]; + } + else { + p.out[0] = 0.0f; + } + if (p.color2[1] != 0.0f) { + p.out[1] = value_m * (p.color1[1]) + value * (p.color1[1]) / p.color2[1]; + } + else { + p.out[1] = 0.0f; + } + if (p.color2[2] != 0.0f) { + p.out[2] = value_m * (p.color1[2]) + value * (p.color1[2]) / p.color2[2]; + } + else { + p.out[2] = 0.0f; + } + + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Dodge Operation ******** */ void MixDodgeOperation::executePixelSampled(float output[4], @@ -452,6 +670,64 @@ void MixDodgeOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixDodgeOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + + float tmp; + if (p.color1[0] != 0.0f) { + tmp = 1.0f - value * p.color2[0]; + if (tmp <= 0.0f) { + p.out[0] = 1.0f; + } + else { + p.out[0] = p.color1[0] / tmp; + CLAMP_MAX(p.out[0], 1.0f); + } + } + else { + p.out[0] = 0.0f; + } + + if (p.color1[1] != 0.0f) { + tmp = 1.0f - value * p.color2[1]; + if (tmp <= 0.0f) { + p.out[1] = 1.0f; + } + else { + p.out[1] = p.color1[1] / tmp; + CLAMP_MAX(p.out[1], 1.0f); + } + } + else { + p.out[1] = 0.0f; + } + + if (p.color1[2] != 0.0f) { + tmp = 1.0f - value * p.color2[2]; + if (tmp <= 0.0f) { + p.out[2] = 1.0f; + } + else { + p.out[2] = p.color1[2] / tmp; + CLAMP_MAX(p.out[2], 1.0f); + } + } + else { + p.out[2] = 0.0f; + } + + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Glare Operation ******** */ void MixGlareOperation::executePixelSampled(float output[4], @@ -487,6 +763,33 @@ void MixGlareOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixGlareOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + const float value = p.value[0]; + /* Linear interpolation between 3 cases: + * value=-1:output=input value=0:output=input+glare value=1:output=glare + */ + float input_weight; + float glare_weight; + if (value < 0.0f) { + input_weight = 1.0f; + glare_weight = 1.0f + value; + } + else { + input_weight = 1.0f - value; + glare_weight = 1.0f; + } + p.out[0] = input_weight * MAX2(p.color1[0], 0.0f) + glare_weight * p.color2[0]; + p.out[1] = input_weight * MAX2(p.color1[1], 0.0f) + glare_weight * p.color2[1]; + p.out[2] = input_weight * MAX2(p.color1[2], 0.0f) + glare_weight * p.color2[2]; + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Hue Operation ******** */ void MixHueOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) @@ -524,6 +827,36 @@ void MixHueOperation::executePixelSampled(float output[4], float x, float y, Pix clampIfNeeded(output); } +void MixHueOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + const float value_m = 1.0f - value; + + float colH, colS, colV; + rgb_to_hsv(p.color2[0], p.color2[1], p.color2[2], &colH, &colS, &colV); + if (colS != 0.0f) { + float rH, rS, rV; + float tmpr, tmpg, tmpb; + rgb_to_hsv(p.color1[0], p.color1[1], p.color1[2], &rH, &rS, &rV); + hsv_to_rgb(colH, rS, rV, &tmpr, &tmpg, &tmpb); + p.out[0] = value_m * p.color1[0] + value * tmpr; + p.out[1] = value_m * p.color1[1] + value * tmpg; + p.out[2] = value_m * p.color1[2] + value * tmpb; + } + else { + copy_v3_v3(p.out, p.color1); + } + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Lighten Operation ******** */ void MixLightenOperation::executePixelSampled(float output[4], @@ -570,6 +903,30 @@ void MixLightenOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixLightenOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + + float tmp = value * p.color2[0]; + p.out[0] = MAX2(tmp, p.color1[0]); + + tmp = value * p.color2[1]; + p.out[1] = MAX2(tmp, p.color1[1]); + + tmp = value * p.color2[2]; + p.out[2] = MAX2(tmp, p.color1[2]); + + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Linear Light Operation ******** */ void MixLinearLightOperation::executePixelSampled(float output[4], @@ -613,6 +970,39 @@ void MixLinearLightOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixLinearLightOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + if (p.color2[0] > 0.5f) { + p.out[0] = p.color1[0] + value * (2.0f * (p.color2[0] - 0.5f)); + } + else { + p.out[0] = p.color1[0] + value * (2.0f * (p.color2[0]) - 1.0f); + } + if (p.color2[1] > 0.5f) { + p.out[1] = p.color1[1] + value * (2.0f * (p.color2[1] - 0.5f)); + } + else { + p.out[1] = p.color1[1] + value * (2.0f * (p.color2[1]) - 1.0f); + } + if (p.color2[2] > 0.5f) { + p.out[2] = p.color1[2] + value * (2.0f * (p.color2[2] - 0.5f)); + } + else { + p.out[2] = p.color1[2] + value * (2.0f * (p.color2[2]) - 1.0f); + } + + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Multiply Operation ******** */ void MixMultiplyOperation::executePixelSampled(float output[4], @@ -641,6 +1031,25 @@ void MixMultiplyOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixMultiplyOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + const float value_m = 1.0f - value; + p.out[0] = p.color1[0] * (value_m + value * p.color2[0]); + p.out[1] = p.color1[1] * (value_m + value * p.color2[1]); + p.out[2] = p.color1[2] * (value_m + value * p.color2[2]); + + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Overlay Operation ******** */ void MixOverlayOperation::executePixelSampled(float output[4], @@ -686,6 +1095,40 @@ void MixOverlayOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixOverlayOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + const float value_m = 1.0f - value; + if (p.color1[0] < 0.5f) { + p.out[0] = p.color1[0] * (value_m + 2.0f * value * p.color2[0]); + } + else { + p.out[0] = 1.0f - (value_m + 2.0f * value * (1.0f - p.color2[0])) * (1.0f - p.color1[0]); + } + if (p.color1[1] < 0.5f) { + p.out[1] = p.color1[1] * (value_m + 2.0f * value * p.color2[1]); + } + else { + p.out[1] = 1.0f - (value_m + 2.0f * value * (1.0f - p.color2[1])) * (1.0f - p.color1[1]); + } + if (p.color1[2] < 0.5f) { + p.out[2] = p.color1[2] * (value_m + 2.0f * value * p.color2[2]); + } + else { + p.out[2] = 1.0f - (value_m + 2.0f * value * (1.0f - p.color2[2])) * (1.0f - p.color1[2]); + } + + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Saturation Operation ******** */ void MixSaturationOperation::executePixelSampled(float output[4], @@ -723,6 +1166,33 @@ void MixSaturationOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixSaturationOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + const float value_m = 1.0f - value; + + float rH, rS, rV; + rgb_to_hsv(p.color1[0], p.color1[1], p.color1[2], &rH, &rS, &rV); + if (rS != 0.0f) { + float colH, colS, colV; + rgb_to_hsv(p.color2[0], p.color2[1], p.color2[2], &colH, &colS, &colV); + hsv_to_rgb(rH, (value_m * rS + value * colS), rV, &p.out[0], &p.out[1], &p.out[2]); + } + else { + copy_v3_v3(p.out, p.color1); + } + + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Screen Operation ******** */ void MixScreenOperation::executePixelSampled(float output[4], @@ -752,6 +1222,25 @@ void MixScreenOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixScreenOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + const float value_m = 1.0f - value; + + p.out[0] = 1.0f - (value_m + value * (1.0f - p.color2[0])) * (1.0f - p.color1[0]); + p.out[1] = 1.0f - (value_m + value * (1.0f - p.color2[1])) * (1.0f - p.color1[1]); + p.out[2] = 1.0f - (value_m + value * (1.0f - p.color2[2])) * (1.0f - p.color1[2]); + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Soft Light Operation ******** */ void MixSoftLightOperation::executePixelSampled(float output[4], @@ -793,6 +1282,34 @@ void MixSoftLightOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixSoftLightOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + const float value_m = 1.0f - value; + float scr, scg, scb; + + /* First calculate non-fac based Screen mix. */ + scr = 1.0f - (1.0f - p.color2[0]) * (1.0f - p.color1[0]); + scg = 1.0f - (1.0f - p.color2[1]) * (1.0f - p.color1[1]); + scb = 1.0f - (1.0f - p.color2[2]) * (1.0f - p.color1[2]); + + p.out[0] = value_m * p.color1[0] + + value * ((1.0f - p.color1[0]) * p.color2[0] * p.color1[0] + p.color1[0] * scr); + p.out[1] = value_m * p.color1[1] + + value * ((1.0f - p.color1[1]) * p.color2[1] * p.color1[1] + p.color1[1] * scg); + p.out[2] = value_m * p.color1[2] + + value * ((1.0f - p.color1[2]) * p.color2[2] * p.color1[2] + p.color1[2] * scb); + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Subtract Operation ******** */ void MixSubtractOperation::executePixelSampled(float output[4], @@ -820,6 +1337,23 @@ void MixSubtractOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixSubtractOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + p.out[0] = p.color1[0] - value * p.color2[0]; + p.out[1] = p.color1[1] - value * p.color2[1]; + p.out[2] = p.color1[2] - value * p.color2[2]; + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + /* ******** Mix Value Operation ******** */ void MixValueOperation::executePixelSampled(float output[4], @@ -851,4 +1385,25 @@ void MixValueOperation::executePixelSampled(float output[4], clampIfNeeded(output); } +void MixValueOperation::update_memory_buffer_row(PixelCursor &p) +{ + while (p.out < p.row_end) { + float value = p.value[0]; + if (this->useValueAlphaMultiply()) { + value *= p.color2[3]; + } + float value_m = 1.0f - value; + + float rH, rS, rV; + float colH, colS, colV; + rgb_to_hsv(p.color1[0], p.color1[1], p.color1[2], &rH, &rS, &rV); + rgb_to_hsv(p.color2[0], p.color2[1], p.color2[2], &colH, &colS, &colV); + hsv_to_rgb(rH, rS, (value_m * rV + value * colV), &p.out[0], &p.out[1], &p.out[2]); + p.out[3] = p.color1[3]; + + clampIfNeeded(p.out); + p.next(); + } +} + } // namespace blender::compositor diff --git a/source/blender/compositor/operations/COM_MixOperation.h b/source/blender/compositor/operations/COM_MixOperation.h index 6c241bc5762..7ef9d78d58f 100644 --- a/source/blender/compositor/operations/COM_MixOperation.h +++ b/source/blender/compositor/operations/COM_MixOperation.h @@ -18,7 +18,7 @@ #pragma once -#include "COM_NodeOperation.h" +#include "COM_MultiThreadedOperation.h" namespace blender::compositor { @@ -27,8 +27,29 @@ namespace blender::compositor { * it assumes we are in sRGB color space. */ -class MixBaseOperation : public NodeOperation { +class MixBaseOperation : public MultiThreadedOperation { protected: + struct PixelCursor { + float *out; + const float *row_end; + const float *value; + const float *color1; + const float *color2; + int out_stride; + int value_stride; + int color1_stride; + int color2_stride; + + void next() + { + BLI_assert(out < row_end); + out += out_stride; + value += value_stride; + color1 += color1_stride; + color2 += color2_stride; + } + }; + /** * Prefetched reference to the inputProgram */ @@ -81,101 +102,165 @@ class MixBaseOperation : public NodeOperation { { this->m_useClamp = value; } + + void update_memory_buffer_partial(MemoryBuffer *output, + const rcti &area, + Span<MemoryBuffer *> inputs) final; + + protected: + virtual void update_memory_buffer_row(PixelCursor &p); }; class MixAddOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixBlendOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixColorBurnOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixColorOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixDarkenOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixDifferenceOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixDivideOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixDodgeOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixGlareOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixHueOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixLightenOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixLinearLightOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixMultiplyOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixOverlayOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixSaturationOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixScreenOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixSoftLightOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixSubtractOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; class MixValueOperation : public MixBaseOperation { public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override; + + protected: + void update_memory_buffer_row(PixelCursor &p) override; }; } // namespace blender::compositor |