Compositor: Full frame output nodes

Adds full frame implementation to "Composite", "File Output" and
"Split Viewer" nodes.
The other nodes in "Output" submenu are implemented separately.
No functional changes.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D12091
This commit is contained in:
Manuel Castilla 2021-08-10 15:25:26 +02:00
parent d481c6651d
commit eb03529ab9
7 changed files with 90 additions and 7 deletions

View File

@ -62,6 +62,11 @@ constexpr int COM_data_type_num_channels(const DataType datatype)
}
}
constexpr int COM_data_type_bytes_len(DataType data_type)
{
return COM_data_type_num_channels(data_type) * sizeof(float);
}
constexpr int COM_DATA_TYPE_VALUE_CHANNELS = COM_data_type_num_channels(DataType::Value);
constexpr int COM_DATA_TYPE_VECTOR_CHANNELS = COM_data_type_num_channels(DataType::Vector);
constexpr int COM_DATA_TYPE_COLOR_CHANNELS = COM_data_type_num_channels(DataType::Color);

View File

@ -220,6 +220,22 @@ void CompositorOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/)
}
}
void CompositorOperation::update_memory_buffer_partial(MemoryBuffer *UNUSED(output),
const rcti &area,
Span<MemoryBuffer *> inputs)
{
if (!m_outputBuffer) {
return;
}
MemoryBuffer output_buf(m_outputBuffer, COM_DATA_TYPE_COLOR_CHANNELS, getWidth(), getHeight());
output_buf.copy_from(inputs[0], area);
if (this->m_useAlphaInput) {
output_buf.copy_from(inputs[1], area, 0, COM_DATA_TYPE_VALUE_CHANNELS, 3);
}
MemoryBuffer depth_buf(m_depthBuffer, COM_DATA_TYPE_VALUE_CHANNELS, getWidth(), getHeight());
depth_buf.copy_from(inputs[2], area);
}
void CompositorOperation::determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2])
{

View File

@ -20,7 +20,7 @@
#include "BLI_rect.h"
#include "BLI_string.h"
#include "COM_NodeOperation.h"
#include "COM_MultiThreadedOperation.h"
struct Scene;
@ -29,7 +29,7 @@ namespace blender::compositor {
/**
* \brief Compositor output operation
*/
class CompositorOperation : public NodeOperation {
class CompositorOperation : public MultiThreadedOperation {
private:
const struct Scene *m_scene;
/**
@ -125,6 +125,10 @@ class CompositorOperation : public NodeOperation {
{
this->m_active = active;
}
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor

View File

@ -294,6 +294,22 @@ void OutputSingleLayerOperation::deinitExecution()
this->m_imageInput = nullptr;
}
void OutputSingleLayerOperation::update_memory_buffer_partial(MemoryBuffer *UNUSED(output),
const rcti &area,
Span<MemoryBuffer *> inputs)
{
if (!m_outputBuffer) {
return;
}
MemoryBuffer output_buf(m_outputBuffer,
COM_data_type_num_channels(this->m_datatype),
this->getWidth(),
this->getHeight());
const MemoryBuffer *input_image = inputs[0];
output_buf.copy_from(input_image, area);
}
/******************************* MultiLayer *******************************/
OutputOpenExrLayer::OutputOpenExrLayer(const char *name_, DataType datatype_, bool use_layer_)
@ -444,4 +460,21 @@ void OutputOpenExrMultiLayerOperation::deinitExecution()
}
}
void OutputOpenExrMultiLayerOperation::update_memory_buffer_partial(MemoryBuffer *UNUSED(output),
const rcti &area,
Span<MemoryBuffer *> inputs)
{
const MemoryBuffer *input_image = inputs[0];
for (int i = 0; i < this->m_layers.size(); i++) {
OutputOpenExrLayer &layer = this->m_layers[i];
if (layer.outputBuffer) {
MemoryBuffer output_buf(layer.outputBuffer,
COM_data_type_num_channels(layer.datatype),
this->getWidth(),
this->getHeight());
output_buf.copy_from(input_image, area);
}
}
}
} // namespace blender::compositor

View File

@ -18,7 +18,7 @@
#pragma once
#include "COM_NodeOperation.h"
#include "COM_MultiThreadedOperation.h"
#include "BLI_path_util.h"
#include "BLI_rect.h"
@ -30,7 +30,7 @@
namespace blender::compositor {
/* Writes the image to a single-layer file. */
class OutputSingleLayerOperation : public NodeOperation {
class OutputSingleLayerOperation : public MultiThreadedOperation {
protected:
const RenderData *m_rd;
const bNodeTree *m_tree;
@ -70,6 +70,10 @@ class OutputSingleLayerOperation : public NodeOperation {
{
return eCompositorPriority::Low;
}
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
/* extra info for OpenEXR layers */
@ -86,7 +90,7 @@ struct OutputOpenExrLayer {
};
/* Writes inputs into OpenEXR multilayer channels. */
class OutputOpenExrMultiLayerOperation : public NodeOperation {
class OutputOpenExrMultiLayerOperation : public MultiThreadedOperation {
protected:
const Scene *m_scene;
const RenderData *m_rd;
@ -122,6 +126,10 @@ class OutputOpenExrMultiLayerOperation : public NodeOperation {
{
return eCompositorPriority::Low;
}
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
void add_exr_channels(void *exrhandle,

View File

@ -79,4 +79,17 @@ void SplitOperation::determineResolution(unsigned int resolution[2],
NodeOperation::determineResolution(resolution, preferredResolution);
}
void SplitOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs)
{
const int percent = this->m_xSplit ? this->m_splitPercentage * this->getWidth() / 100.0f :
this->m_splitPercentage * this->getHeight() / 100.0f;
const size_t elem_bytes = COM_data_type_bytes_len(getOutputSocket()->getDataType());
for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
const bool is_image1 = this->m_xSplit ? it.x > percent : it.y > percent;
memcpy(it.out, it.in(is_image1 ? 0 : 1), elem_bytes);
}
}
} // namespace blender::compositor

View File

@ -18,11 +18,11 @@
#pragma once
#include "COM_NodeOperation.h"
#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
class SplitOperation : public NodeOperation {
class SplitOperation : public MultiThreadedOperation {
private:
SocketReader *m_image1Input;
SocketReader *m_image2Input;
@ -45,6 +45,10 @@ class SplitOperation : public NodeOperation {
{
this->m_xSplit = xsplit;
}
void update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor