Compositor: Full frame Scale node
Adds full frame implementation to this node operations. No functional changes. Includes a new operation method `init_data` used to initialize any data needed after operations are linked and resolutions determined. Once tiled implementation is removed `initExecution` may be renamed to `init_rendering` and `init_data` to `init_execution`. Reviewed By: jbakker Differential Revision: https://developer.blender.org/D11944
This commit is contained in:
parent
cf74cd9367
commit
a117794f8c
|
@ -94,6 +94,7 @@ ConstantOperation *ConstantFolder::fold_operation(NodeOperation *operation)
|
|||
const DataType data_type = operation->getOutputSocket()->getDataType();
|
||||
MemoryBuffer fold_buf(data_type, first_elem_area_);
|
||||
Vector<MemoryBuffer *> input_bufs = get_constant_input_buffers(operation);
|
||||
operation->init_data();
|
||||
operation->render(&fold_buf, {first_elem_area_}, input_bufs);
|
||||
|
||||
MemoryBuffer *constant_buf = create_constant_buffer(data_type);
|
||||
|
|
|
@ -518,7 +518,7 @@ void COM_convert_resolution(NodeOperationBuilder &builder,
|
|||
NodeOperation *first = nullptr;
|
||||
ScaleOperation *scaleOperation = nullptr;
|
||||
if (doScale) {
|
||||
scaleOperation = new ScaleOperation(fromSocket->getDataType());
|
||||
scaleOperation = new ScaleRelativeOperation(fromSocket->getDataType());
|
||||
scaleOperation->getInputSocket(1)->setResizeMode(ResizeMode::None);
|
||||
scaleOperation->getInputSocket(2)->setResizeMode(ResizeMode::None);
|
||||
first = scaleOperation;
|
||||
|
|
|
@ -17,9 +17,28 @@
|
|||
*/
|
||||
|
||||
#include "COM_Enums.h"
|
||||
#include "BLI_rect.h"
|
||||
|
||||
namespace blender::compositor {
|
||||
|
||||
void expand_area_for_sampler(rcti &area, PixelSampler sampler)
|
||||
{
|
||||
switch (sampler) {
|
||||
case PixelSampler::Nearest:
|
||||
break;
|
||||
case PixelSampler::Bilinear:
|
||||
area.xmax += 1;
|
||||
area.ymax += 1;
|
||||
break;
|
||||
case PixelSampler::Bicubic:
|
||||
area.xmin -= 1;
|
||||
area.xmax += 2;
|
||||
area.ymin -= 1;
|
||||
area.ymax += 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const eCompositorPriority &priority)
|
||||
{
|
||||
switch (priority) {
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
#include <ostream>
|
||||
|
||||
struct rcti;
|
||||
|
||||
namespace blender::compositor {
|
||||
|
||||
/**
|
||||
|
@ -85,6 +87,13 @@ enum class eWorkPackageType {
|
|||
CustomFunction = 1
|
||||
};
|
||||
|
||||
enum class PixelSampler {
|
||||
Nearest = 0,
|
||||
Bilinear = 1,
|
||||
Bicubic = 2,
|
||||
};
|
||||
void expand_area_for_sampler(rcti &area, PixelSampler sampler);
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const eCompositorPriority &priority);
|
||||
std::ostream &operator<<(std::ostream &os, const eWorkPackageState &execution_state);
|
||||
|
||||
|
|
|
@ -112,6 +112,9 @@ void ExecutionSystem::set_operations(const Vector<NodeOperation *> &operations,
|
|||
void ExecutionSystem::execute()
|
||||
{
|
||||
DebugInfo::execute_started(this);
|
||||
for (NodeOperation *op : m_operations) {
|
||||
op->init_data();
|
||||
}
|
||||
execution_model_->execute(*this);
|
||||
}
|
||||
|
||||
|
|
|
@ -189,6 +189,25 @@ class MemoryBuffer {
|
|||
return m_buffer + get_coords_offset(x, y);
|
||||
}
|
||||
|
||||
void read_elem(int x, int y, float *out) const
|
||||
{
|
||||
memcpy(out, get_elem(x, y), m_num_channels * sizeof(float));
|
||||
}
|
||||
|
||||
void read_elem_sampled(float x, float y, PixelSampler sampler, float *out) const
|
||||
{
|
||||
switch (sampler) {
|
||||
case PixelSampler::Nearest:
|
||||
this->read_elem(x, y, out);
|
||||
break;
|
||||
case PixelSampler::Bilinear:
|
||||
case PixelSampler::Bicubic:
|
||||
/* No bicubic. Current implementation produces fuzzy results. */
|
||||
this->readBilinear(out, x, y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get channel value at given coordinates.
|
||||
*/
|
||||
|
@ -330,7 +349,7 @@ class MemoryBuffer {
|
|||
inline void wrap_pixel(float &x,
|
||||
float &y,
|
||||
MemoryBufferExtend extend_x,
|
||||
MemoryBufferExtend extend_y)
|
||||
MemoryBufferExtend extend_y) const
|
||||
{
|
||||
const float w = (float)getWidth();
|
||||
const float h = (float)getHeight();
|
||||
|
@ -427,7 +446,7 @@ class MemoryBuffer {
|
|||
float x,
|
||||
float y,
|
||||
MemoryBufferExtend extend_x = MemoryBufferExtend::Clip,
|
||||
MemoryBufferExtend extend_y = MemoryBufferExtend::Clip)
|
||||
MemoryBufferExtend extend_y = MemoryBufferExtend::Clip) const
|
||||
{
|
||||
float u = x;
|
||||
float v = y;
|
||||
|
|
|
@ -100,6 +100,11 @@ void NodeOperation::setResolutionInputSocketIndex(unsigned int index)
|
|||
{
|
||||
this->m_resolutionInputSocketIndex = index;
|
||||
}
|
||||
|
||||
void NodeOperation::init_data()
|
||||
{
|
||||
/* Pass. */
|
||||
}
|
||||
void NodeOperation::initExecution()
|
||||
{
|
||||
/* pass */
|
||||
|
|
|
@ -75,12 +75,6 @@ enum class ResizeMode {
|
|||
Stretch = NS_CR_STRETCH,
|
||||
};
|
||||
|
||||
enum class PixelSampler {
|
||||
Nearest = 0,
|
||||
Bilinear = 1,
|
||||
Bicubic = 2,
|
||||
};
|
||||
|
||||
class NodeOperationInput {
|
||||
private:
|
||||
NodeOperation *m_operation;
|
||||
|
@ -424,6 +418,12 @@ class NodeOperation {
|
|||
exec_system_ = system;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes operation data needed after operations are linked and resolutions determined. For
|
||||
* rendering heap memory data use initExecution().
|
||||
*/
|
||||
virtual void init_data();
|
||||
|
||||
virtual void initExecution();
|
||||
|
||||
/**
|
||||
|
|
|
@ -43,7 +43,7 @@ void ScaleNode::convertToOperations(NodeConverter &converter,
|
|||
|
||||
switch (bnode->custom1) {
|
||||
case CMP_SCALE_RELATIVE: {
|
||||
ScaleOperation *operation = new ScaleOperation();
|
||||
ScaleRelativeOperation *operation = new ScaleRelativeOperation();
|
||||
converter.addOperation(operation);
|
||||
|
||||
converter.mapInputSocket(inputSocket, operation->getInputSocket(0));
|
||||
|
@ -59,7 +59,7 @@ void ScaleNode::convertToOperations(NodeConverter &converter,
|
|||
scaleFactorOperation->setValue(context.getRenderPercentageAsFactor());
|
||||
converter.addOperation(scaleFactorOperation);
|
||||
|
||||
ScaleOperation *operation = new ScaleOperation();
|
||||
ScaleRelativeOperation *operation = new ScaleRelativeOperation();
|
||||
converter.addOperation(operation);
|
||||
|
||||
converter.mapInputSocket(inputSocket, operation->getInputSocket(0));
|
||||
|
|
|
@ -43,7 +43,7 @@ void Stabilize2dNode::convertToOperations(NodeConverter &converter,
|
|||
MovieClip *clip = (MovieClip *)editorNode->id;
|
||||
bool invert = (editorNode->custom2 & CMP_NODEFLAG_STABILIZE_INVERSE) != 0;
|
||||
|
||||
ScaleOperation *scaleOperation = new ScaleOperation();
|
||||
ScaleRelativeOperation *scaleOperation = new ScaleRelativeOperation();
|
||||
scaleOperation->setSampler((PixelSampler)editorNode->custom1);
|
||||
RotateOperation *rotateOperation = new RotateOperation();
|
||||
rotateOperation->setDoDegree2RadConversion(false);
|
||||
|
|
|
@ -40,7 +40,7 @@ void TransformNode::convertToOperations(NodeConverter &converter,
|
|||
NodeInput *angleInput = this->getInputSocket(3);
|
||||
NodeInput *scaleInput = this->getInputSocket(4);
|
||||
|
||||
ScaleOperation *scaleOperation = new ScaleOperation();
|
||||
ScaleRelativeOperation *scaleOperation = new ScaleRelativeOperation();
|
||||
converter.addOperation(scaleOperation);
|
||||
|
||||
RotateOperation *rotateOperation = new RotateOperation();
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
|
||||
#include "COM_ScaleOperation.h"
|
||||
#include "COM_ConstantOperation.h"
|
||||
|
||||
namespace blender::compositor {
|
||||
|
||||
|
@ -52,13 +53,60 @@ ScaleOperation::ScaleOperation(DataType data_type) : BaseScaleOperation()
|
|||
this->m_inputXOperation = nullptr;
|
||||
this->m_inputYOperation = nullptr;
|
||||
}
|
||||
|
||||
static std::optional<float> get_constant_scale(NodeOperation *op)
|
||||
{
|
||||
if (op->get_flags().is_constant_operation) {
|
||||
return ((ConstantOperation *)op)->get_constant_elem()[0];
|
||||
}
|
||||
|
||||
return std::optional<float>();
|
||||
}
|
||||
|
||||
float ScaleOperation::get_constant_scale_x()
|
||||
{
|
||||
std::optional<float> scale_x = get_constant_scale(getInputOperation(1));
|
||||
if (scale_x.has_value()) {
|
||||
return scale_x.value() * get_relative_scale_x_factor();
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
float ScaleOperation::get_constant_scale_y()
|
||||
{
|
||||
std::optional<float> scale_y = get_constant_scale(getInputOperation(2));
|
||||
if (scale_y.has_value()) {
|
||||
return scale_y.value() * get_relative_scale_y_factor();
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
BLI_INLINE float scale_coord(const int coord, const float center, const float relative_scale)
|
||||
{
|
||||
return center + (coord - center) / relative_scale;
|
||||
}
|
||||
|
||||
void ScaleOperation::scale_area(rcti &rect, float scale_x, float scale_y)
|
||||
{
|
||||
rect.xmin = scale_coord(rect.xmin, m_centerX, scale_x);
|
||||
rect.xmax = scale_coord(rect.xmax, m_centerX, scale_x);
|
||||
rect.ymin = scale_coord(rect.ymin, m_centerY, scale_y);
|
||||
rect.ymax = scale_coord(rect.ymax, m_centerY, scale_y);
|
||||
}
|
||||
|
||||
void ScaleOperation::init_data()
|
||||
{
|
||||
m_centerX = getWidth() / 2.0f;
|
||||
m_centerY = getHeight() / 2.0f;
|
||||
}
|
||||
|
||||
void ScaleOperation::initExecution()
|
||||
{
|
||||
this->m_inputOperation = this->getInputSocketReader(0);
|
||||
this->m_inputXOperation = this->getInputSocketReader(1);
|
||||
this->m_inputYOperation = this->getInputSocketReader(2);
|
||||
this->m_centerX = this->getWidth() / 2.0;
|
||||
this->m_centerY = this->getHeight() / 2.0;
|
||||
}
|
||||
|
||||
void ScaleOperation::deinitExecution()
|
||||
|
@ -68,7 +116,52 @@ void ScaleOperation::deinitExecution()
|
|||
this->m_inputYOperation = nullptr;
|
||||
}
|
||||
|
||||
void ScaleOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
|
||||
void ScaleOperation::get_area_of_interest(const int input_idx,
|
||||
const rcti &output_area,
|
||||
rcti &r_input_area)
|
||||
{
|
||||
r_input_area = output_area;
|
||||
if (input_idx != 0 || m_variable_size) {
|
||||
return;
|
||||
}
|
||||
|
||||
float scale_x = get_constant_scale_x();
|
||||
float scale_y = get_constant_scale_y();
|
||||
scale_area(r_input_area, scale_x, scale_y);
|
||||
expand_area_for_sampler(r_input_area, (PixelSampler)m_sampler);
|
||||
}
|
||||
|
||||
void ScaleOperation::update_memory_buffer_partial(MemoryBuffer *output,
|
||||
const rcti &area,
|
||||
Span<MemoryBuffer *> inputs)
|
||||
{
|
||||
const MemoryBuffer *input_img = inputs[0];
|
||||
MemoryBuffer *input_x = inputs[1];
|
||||
MemoryBuffer *input_y = inputs[2];
|
||||
const float scale_x_factor = get_relative_scale_x_factor();
|
||||
const float scale_y_factor = get_relative_scale_y_factor();
|
||||
BuffersIterator<float> it = output->iterate_with({input_x, input_y}, area);
|
||||
for (; !it.is_end(); ++it) {
|
||||
const float rel_scale_x = *it.in(0) * scale_x_factor;
|
||||
const float rel_scale_y = *it.in(1) * scale_y_factor;
|
||||
const float scaled_x = scale_coord(it.x, m_centerX, rel_scale_x);
|
||||
const float scaled_y = scale_coord(it.y, m_centerY, rel_scale_y);
|
||||
input_img->read_elem_sampled(scaled_x, scaled_y, (PixelSampler)m_sampler, it.out);
|
||||
}
|
||||
}
|
||||
|
||||
ScaleRelativeOperation::ScaleRelativeOperation() : ScaleOperation()
|
||||
{
|
||||
}
|
||||
|
||||
ScaleRelativeOperation::ScaleRelativeOperation(DataType data_type) : ScaleOperation(data_type)
|
||||
{
|
||||
}
|
||||
|
||||
void ScaleRelativeOperation::executePixelSampled(float output[4],
|
||||
float x,
|
||||
float y,
|
||||
PixelSampler sampler)
|
||||
{
|
||||
PixelSampler effective_sampler = getEffectiveSampler(sampler);
|
||||
|
||||
|
@ -86,9 +179,9 @@ void ScaleOperation::executePixelSampled(float output[4], float x, float y, Pixe
|
|||
this->m_inputOperation->readSampled(output, nx, ny, effective_sampler);
|
||||
}
|
||||
|
||||
bool ScaleOperation::determineDependingAreaOfInterest(rcti *input,
|
||||
ReadBufferOperation *readOperation,
|
||||
rcti *output)
|
||||
bool ScaleRelativeOperation::determineDependingAreaOfInterest(rcti *input,
|
||||
ReadBufferOperation *readOperation,
|
||||
rcti *output)
|
||||
{
|
||||
rcti newInput;
|
||||
if (!m_variable_size) {
|
||||
|
@ -115,34 +208,6 @@ bool ScaleOperation::determineDependingAreaOfInterest(rcti *input,
|
|||
return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
|
||||
}
|
||||
|
||||
// SCALE ABSOLUTE
|
||||
ScaleAbsoluteOperation::ScaleAbsoluteOperation() : BaseScaleOperation()
|
||||
{
|
||||
this->addInputSocket(DataType::Color);
|
||||
this->addInputSocket(DataType::Value);
|
||||
this->addInputSocket(DataType::Value);
|
||||
this->addOutputSocket(DataType::Color);
|
||||
this->setResolutionInputSocketIndex(0);
|
||||
this->m_inputOperation = nullptr;
|
||||
this->m_inputXOperation = nullptr;
|
||||
this->m_inputYOperation = nullptr;
|
||||
}
|
||||
void ScaleAbsoluteOperation::initExecution()
|
||||
{
|
||||
this->m_inputOperation = this->getInputSocketReader(0);
|
||||
this->m_inputXOperation = this->getInputSocketReader(1);
|
||||
this->m_inputYOperation = this->getInputSocketReader(2);
|
||||
this->m_centerX = this->getWidth() / 2.0;
|
||||
this->m_centerY = this->getHeight() / 2.0;
|
||||
}
|
||||
|
||||
void ScaleAbsoluteOperation::deinitExecution()
|
||||
{
|
||||
this->m_inputOperation = nullptr;
|
||||
this->m_inputXOperation = nullptr;
|
||||
this->m_inputYOperation = nullptr;
|
||||
}
|
||||
|
||||
void ScaleAbsoluteOperation::executePixelSampled(float output[4],
|
||||
float x,
|
||||
float y,
|
||||
|
@ -202,8 +267,7 @@ bool ScaleAbsoluteOperation::determineDependingAreaOfInterest(rcti *input,
|
|||
newInput.ymax = this->getHeight();
|
||||
newInput.ymin = 0;
|
||||
}
|
||||
|
||||
return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
|
||||
return ScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
|
||||
}
|
||||
|
||||
// Absolute fixed size
|
||||
|
@ -215,11 +279,12 @@ ScaleFixedSizeOperation::ScaleFixedSizeOperation() : BaseScaleOperation()
|
|||
this->m_inputOperation = nullptr;
|
||||
this->m_is_offset = false;
|
||||
}
|
||||
void ScaleFixedSizeOperation::initExecution()
|
||||
|
||||
void ScaleFixedSizeOperation::init_data()
|
||||
{
|
||||
this->m_inputOperation = this->getInputSocketReader(0);
|
||||
this->m_relX = this->m_inputOperation->getWidth() / (float)this->m_newWidth;
|
||||
this->m_relY = this->m_inputOperation->getHeight() / (float)this->m_newHeight;
|
||||
const NodeOperation *input_op = getInputOperation(0);
|
||||
this->m_relX = input_op->getWidth() / (float)this->m_newWidth;
|
||||
this->m_relY = input_op->getHeight() / (float)this->m_newHeight;
|
||||
|
||||
/* *** all the options below are for a fairly special case - camera framing *** */
|
||||
if (this->m_offsetX != 0.0f || this->m_offsetY != 0.0f) {
|
||||
|
@ -237,8 +302,8 @@ void ScaleFixedSizeOperation::initExecution()
|
|||
|
||||
if (this->m_is_aspect) {
|
||||
/* apply aspect from clip */
|
||||
const float w_src = this->m_inputOperation->getWidth();
|
||||
const float h_src = this->m_inputOperation->getHeight();
|
||||
const float w_src = input_op->getWidth();
|
||||
const float h_src = input_op->getHeight();
|
||||
|
||||
/* destination aspect is already applied from the camera frame */
|
||||
const float w_dst = this->m_newWidth;
|
||||
|
@ -267,6 +332,11 @@ void ScaleFixedSizeOperation::initExecution()
|
|||
/* *** end framing options *** */
|
||||
}
|
||||
|
||||
void ScaleFixedSizeOperation::initExecution()
|
||||
{
|
||||
this->m_inputOperation = this->getInputSocketReader(0);
|
||||
}
|
||||
|
||||
void ScaleFixedSizeOperation::deinitExecution()
|
||||
{
|
||||
this->m_inputOperation = nullptr;
|
||||
|
@ -315,4 +385,38 @@ void ScaleFixedSizeOperation::determineResolution(unsigned int resolution[2],
|
|||
resolution[1] = this->m_newHeight;
|
||||
}
|
||||
|
||||
void ScaleFixedSizeOperation::get_area_of_interest(const int input_idx,
|
||||
const rcti &output_area,
|
||||
rcti &r_input_area)
|
||||
{
|
||||
BLI_assert(input_idx == 0);
|
||||
UNUSED_VARS_NDEBUG(input_idx);
|
||||
r_input_area.xmax = (output_area.xmax - m_offsetX) * this->m_relX;
|
||||
r_input_area.xmin = (output_area.xmin - m_offsetX) * this->m_relX;
|
||||
r_input_area.ymax = (output_area.ymax - m_offsetY) * this->m_relY;
|
||||
r_input_area.ymin = (output_area.ymin - m_offsetY) * this->m_relY;
|
||||
expand_area_for_sampler(r_input_area, (PixelSampler)m_sampler);
|
||||
}
|
||||
|
||||
void ScaleFixedSizeOperation::update_memory_buffer_partial(MemoryBuffer *output,
|
||||
const rcti &area,
|
||||
Span<MemoryBuffer *> inputs)
|
||||
{
|
||||
const MemoryBuffer *input_img = inputs[0];
|
||||
PixelSampler sampler = (PixelSampler)m_sampler;
|
||||
BuffersIterator<float> it = output->iterate_with({}, area);
|
||||
if (this->m_is_offset) {
|
||||
for (; !it.is_end(); ++it) {
|
||||
const float nx = (it.x - this->m_offsetX) * this->m_relX;
|
||||
const float ny = (it.y - this->m_offsetY) * this->m_relY;
|
||||
input_img->read_elem_sampled(nx, ny, sampler, it.out);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (; !it.is_end(); ++it) {
|
||||
input_img->read_elem_sampled(it.x * this->m_relX, it.y * this->m_relY, sampler, it.out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::compositor
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "COM_NodeOperation.h"
|
||||
#include "COM_MultiThreadedOperation.h"
|
||||
|
||||
namespace blender::compositor {
|
||||
|
||||
class BaseScaleOperation : public NodeOperation {
|
||||
class BaseScaleOperation : public MultiThreadedOperation {
|
||||
public:
|
||||
void setSampler(PixelSampler sampler)
|
||||
{
|
||||
|
@ -46,7 +46,7 @@ class BaseScaleOperation : public NodeOperation {
|
|||
};
|
||||
|
||||
class ScaleOperation : public BaseScaleOperation {
|
||||
private:
|
||||
protected:
|
||||
SocketReader *m_inputOperation;
|
||||
SocketReader *m_inputXOperation;
|
||||
SocketReader *m_inputYOperation;
|
||||
|
@ -56,31 +56,58 @@ class ScaleOperation : public BaseScaleOperation {
|
|||
public:
|
||||
ScaleOperation();
|
||||
ScaleOperation(DataType data_type);
|
||||
bool determineDependingAreaOfInterest(rcti *input,
|
||||
ReadBufferOperation *readOperation,
|
||||
rcti *output) override;
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
void init_data() override;
|
||||
void initExecution() override;
|
||||
void deinitExecution() override;
|
||||
|
||||
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;
|
||||
|
||||
protected:
|
||||
virtual float get_relative_scale_x_factor() = 0;
|
||||
virtual float get_relative_scale_y_factor() = 0;
|
||||
|
||||
private:
|
||||
float get_constant_scale_x();
|
||||
float get_constant_scale_y();
|
||||
void scale_area(rcti &rect, float scale_x, float scale_y);
|
||||
};
|
||||
|
||||
class ScaleAbsoluteOperation : public BaseScaleOperation {
|
||||
SocketReader *m_inputOperation;
|
||||
SocketReader *m_inputXOperation;
|
||||
SocketReader *m_inputYOperation;
|
||||
float m_centerX;
|
||||
float m_centerY;
|
||||
|
||||
class ScaleRelativeOperation : public ScaleOperation {
|
||||
public:
|
||||
ScaleAbsoluteOperation();
|
||||
ScaleRelativeOperation();
|
||||
ScaleRelativeOperation(DataType data_type);
|
||||
bool determineDependingAreaOfInterest(rcti *input,
|
||||
ReadBufferOperation *readOperation,
|
||||
rcti *output) override;
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
float get_relative_scale_x_factor() override
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
float get_relative_scale_y_factor() override
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
};
|
||||
|
||||
void initExecution() override;
|
||||
void deinitExecution() override;
|
||||
class ScaleAbsoluteOperation : public ScaleOperation {
|
||||
public:
|
||||
bool determineDependingAreaOfInterest(rcti *input,
|
||||
ReadBufferOperation *readOperation,
|
||||
rcti *output) override;
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
float get_relative_scale_x_factor() override
|
||||
{
|
||||
return 1.0f / getWidth();
|
||||
}
|
||||
float get_relative_scale_y_factor() override
|
||||
{
|
||||
return 1.0f / getHeight();
|
||||
}
|
||||
};
|
||||
|
||||
class ScaleFixedSizeOperation : public BaseScaleOperation {
|
||||
|
@ -108,6 +135,7 @@ class ScaleFixedSizeOperation : public BaseScaleOperation {
|
|||
unsigned int preferredResolution[2]) override;
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
void init_data() override;
|
||||
void initExecution() override;
|
||||
void deinitExecution() override;
|
||||
void setNewWidth(int width)
|
||||
|
@ -131,6 +159,11 @@ class ScaleFixedSizeOperation : public BaseScaleOperation {
|
|||
this->m_offsetX = x;
|
||||
this->m_offsetY = y;
|
||||
}
|
||||
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue