Compositor: Full frame Translate node

Adds full frame implementation to this node operation.
No functional changes.
This commit is contained in:
Manuel Castilla 2021-07-13 21:29:45 +02:00
parent 2ea47057d3
commit 538f452ea9
Notes: blender-bot 2023-02-14 01:57:12 +01:00
Referenced by issue #88150, Full Frame Compositor
3 changed files with 90 additions and 11 deletions

View File

@ -42,6 +42,7 @@ void TranslateNode::convertToOperations(NodeConverter &converter,
NodeOutput *outputSocket = this->getOutputSocket(0);
TranslateOperation *operation = new TranslateOperation();
operation->set_wrapping(data->wrap_axis);
if (data->relative) {
const RenderData *rd = context.getRenderData();
const float render_size_factor = context.getRenderPercentageAsFactor();
@ -55,11 +56,8 @@ void TranslateNode::convertToOperations(NodeConverter &converter,
converter.mapInputSocket(inputXSocket, operation->getInputSocket(1));
converter.mapInputSocket(inputYSocket, operation->getInputSocket(2));
converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));
/* FullFrame does not support using WriteBufferOperation.
* TODO: Implement TranslateOperation with wrap support in FullFrame.
*/
if (data->wrap_axis && context.get_execution_model() != eExecutionModel::FullFrame) {
/* TODO: To be removed with tiled implementation. */
WriteBufferOperation *writeOperation = new WriteBufferOperation(DataType::Color);
WrapOperation *wrapOperation = new WrapOperation(DataType::Color);
wrapOperation->setMemoryProxy(writeOperation->getMemoryProxy());

View File

@ -36,6 +36,8 @@ TranslateOperation::TranslateOperation(DataType data_type)
this->m_isDeltaSet = false;
this->m_factorX = 1.0f;
this->m_factorY = 1.0f;
this->x_extend_mode_ = MemoryBufferExtend::Clip;
this->y_extend_mode_ = MemoryBufferExtend::Clip;
}
void TranslateOperation::initExecution()
{
@ -86,4 +88,58 @@ void TranslateOperation::setFactorXY(float factorX, float factorY)
m_factorY = factorY;
}
void TranslateOperation::set_wrapping(int wrapping_type)
{
switch (wrapping_type) {
case CMP_NODE_WRAP_X:
x_extend_mode_ = MemoryBufferExtend::Repeat;
break;
case CMP_NODE_WRAP_Y:
y_extend_mode_ = MemoryBufferExtend::Repeat;
break;
case CMP_NODE_WRAP_XY:
x_extend_mode_ = MemoryBufferExtend::Repeat;
y_extend_mode_ = MemoryBufferExtend::Repeat;
break;
default:
break;
}
}
void TranslateOperation::get_area_of_interest(const int input_idx,
const rcti &output_area,
rcti &r_input_area)
{
if (input_idx == 0) {
ensureDelta();
r_input_area = output_area;
if (x_extend_mode_ == MemoryBufferExtend::Clip) {
const int delta_x = this->getDeltaX();
BLI_rcti_translate(&r_input_area, -delta_x, 0);
}
if (y_extend_mode_ == MemoryBufferExtend::Clip) {
const int delta_y = this->getDeltaY();
BLI_rcti_translate(&r_input_area, 0, -delta_y);
}
}
}
void TranslateOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
MemoryBuffer *input = inputs[0];
const int delta_x = this->getDeltaX();
const int delta_y = this->getDeltaY();
for (int y = area.ymin; y < area.ymax; y++) {
float *out = output->get_elem(area.xmin, y);
for (int x = area.xmin; x < area.xmax; x++) {
const int input_x = x - delta_x;
const int input_y = y - delta_y;
input->read(out, input_x, input_y, x_extend_mode_, y_extend_mode_);
out += output->elem_stride;
}
}
}
} // namespace blender::compositor

View File

@ -18,11 +18,12 @@
#pragma once
#include "COM_NodeOperation.h"
#include "COM_ConstantOperation.h"
#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
class TranslateOperation : public NodeOperation {
class TranslateOperation : public MultiThreadedOperation {
private:
SocketReader *m_inputOperation;
SocketReader *m_inputXOperation;
@ -32,6 +33,8 @@ class TranslateOperation : public NodeOperation {
bool m_isDeltaSet;
float m_factorX;
float m_factorY;
MemoryBufferExtend x_extend_mode_;
MemoryBufferExtend y_extend_mode_;
public:
TranslateOperation();
@ -56,16 +59,38 @@ class TranslateOperation : public NodeOperation {
inline void ensureDelta()
{
if (!this->m_isDeltaSet) {
float tempDelta[4];
this->m_inputXOperation->readSampled(tempDelta, 0, 0, PixelSampler::Nearest);
this->m_deltaX = tempDelta[0];
this->m_inputYOperation->readSampled(tempDelta, 0, 0, PixelSampler::Nearest);
this->m_deltaY = tempDelta[0];
if (execution_model_ == eExecutionModel::Tiled) {
float tempDelta[4];
this->m_inputXOperation->readSampled(tempDelta, 0, 0, PixelSampler::Nearest);
this->m_deltaX = tempDelta[0];
this->m_inputYOperation->readSampled(tempDelta, 0, 0, PixelSampler::Nearest);
this->m_deltaY = tempDelta[0];
}
else {
this->m_deltaX = 0;
NodeOperation *x_op = getInputOperation(1);
if (x_op->get_flags().is_constant_operation) {
this->m_deltaX = ((ConstantOperation *)x_op)->get_constant_elem()[0];
}
this->m_deltaY = 0;
NodeOperation *y_op = getInputOperation(2);
if (y_op->get_flags().is_constant_operation) {
this->m_deltaY = ((ConstantOperation *)y_op)->get_constant_elem()[0];
}
}
this->m_isDeltaSet = true;
}
}
void setFactorXY(float factorX, float factorY);
void set_wrapping(int wrapping_type);
void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor