[Bf-blender-cvs] [35db01325f4] master: Compositor: Full frame Image node

Manuel Castilla noreply at git.blender.org
Wed Jun 23 17:55:42 CEST 2021


Commit: 35db01325f41da34e5a71d2b28cc717cddbdb996
Author: Manuel Castilla
Date:   Wed Jun 23 17:21:17 2021 +0200
Branches: master
https://developer.blender.org/rB35db01325f41da34e5a71d2b28cc717cddbdb996

Compositor: Full frame Image node

Adds full frame implementation to Image node operations.
Mostly refactored into buffer utility methods for reuse in other
operations.
No functional changes.
1.8x faster than tiled fallback.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D11559

===================================================================

M	source/blender/compositor/COM_defines.h
M	source/blender/compositor/intern/COM_MemoryBuffer.cc
M	source/blender/compositor/intern/COM_MemoryBuffer.h
M	source/blender/compositor/operations/COM_ImageOperation.cc
M	source/blender/compositor/operations/COM_ImageOperation.h
M	source/blender/compositor/operations/COM_MultilayerImageOperation.cc
M	source/blender/compositor/operations/COM_MultilayerImageOperation.h

===================================================================

diff --git a/source/blender/compositor/COM_defines.h b/source/blender/compositor/COM_defines.h
index 5a52d216117..857cbf0beee 100644
--- a/source/blender/compositor/COM_defines.h
+++ b/source/blender/compositor/COM_defines.h
@@ -62,6 +62,24 @@ constexpr int COM_data_type_num_channels(const DataType datatype)
 constexpr int COM_DATA_TYPE_VALUE_CHANNELS = COM_data_type_num_channels(DataType::Value);
 constexpr int COM_DATA_TYPE_COLOR_CHANNELS = COM_data_type_num_channels(DataType::Color);
 
+constexpr float COM_VALUE_ZERO[1] = {0.0f};
+
+/**
+ * Utility to get data type for given number of channels.
+ */
+constexpr DataType COM_num_channels_data_type(const int num_channels)
+{
+  switch (num_channels) {
+    case 1:
+      return DataType::Value;
+    case 3:
+      return DataType::Vector;
+    case 4:
+    default:
+      return DataType::Color;
+  }
+}
+
 // configurable items
 
 // chunk size determination
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cc b/source/blender/compositor/intern/COM_MemoryBuffer.cc
index 8c30d3215d7..44d3f059374 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.cc
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.cc
@@ -18,10 +18,31 @@
 
 #include "COM_MemoryBuffer.h"
 
+#include "IMB_colormanagement.h"
+#include "IMB_imbuf_types.h"
 #include "MEM_guardedalloc.h"
 
+#define ASSERT_BUFFER_CONTAINS_AREA(buf, area) \
+  BLI_assert(BLI_rcti_inside_rcti(&(buf)->get_rect(), &(area)))
+
+#define ASSERT_BUFFER_CONTAINS_AREA_AT_COORDS(buf, area, x, y) \
+  BLI_assert((buf)->get_rect().xmin <= (x)); \
+  BLI_assert((buf)->get_rect().ymin <= (y)); \
+  BLI_assert((buf)->get_rect().xmax >= (x) + BLI_rcti_size_x(&(area))); \
+  BLI_assert((buf)->get_rect().ymax >= (y) + BLI_rcti_size_y(&(area)))
+
+#define ASSERT_VALID_ELEM_SIZE(buf, channel_offset, elem_size) \
+  BLI_assert((buf)->get_num_channels() <= (channel_offset) + (elem_size))
+
 namespace blender::compositor {
 
+static rcti create_rect(const int width, const int height)
+{
+  rcti rect;
+  BLI_rcti_init(&rect, 0, width, 0, height);
+  return rect;
+}
+
 MemoryBuffer::MemoryBuffer(MemoryProxy *memoryProxy, const rcti &rect, MemoryBufferState state)
 {
   m_rect = rect;
@@ -30,6 +51,7 @@ MemoryBuffer::MemoryBuffer(MemoryProxy *memoryProxy, const rcti &rect, MemoryBuf
   this->m_num_channels = COM_data_type_num_channels(memoryProxy->getDataType());
   this->m_buffer = (float *)MEM_mallocN_aligned(
       sizeof(float) * buffer_len() * this->m_num_channels, 16, "COM_MemoryBuffer");
+  owns_data_ = true;
   this->m_state = state;
   this->m_datatype = memoryProxy->getDataType();
 
@@ -44,12 +66,44 @@ MemoryBuffer::MemoryBuffer(DataType dataType, const rcti &rect, bool is_a_single
   this->m_num_channels = COM_data_type_num_channels(dataType);
   this->m_buffer = (float *)MEM_mallocN_aligned(
       sizeof(float) * buffer_len() * this->m_num_channels, 16, "COM_MemoryBuffer");
+  owns_data_ = true;
   this->m_state = MemoryBufferState::Temporary;
   this->m_datatype = dataType;
 
   set_strides();
 }
 
+/**
+ * Construct MemoryBuffer from a float buffer. MemoryBuffer is not responsible for
+ * freeing it.
+ */
+MemoryBuffer::MemoryBuffer(
+    float *buffer, int num_channels, int width, int height, bool is_a_single_elem)
+    : MemoryBuffer(buffer, num_channels, create_rect(width, height), is_a_single_elem)
+{
+}
+
+/**
+ * Construct MemoryBuffer from a float buffer area. MemoryBuffer is not responsible for
+ * freeing given buffer.
+ */
+MemoryBuffer::MemoryBuffer(float *buffer,
+                           const int num_channels,
+                           const rcti &rect,
+                           const bool is_a_single_elem)
+{
+  m_rect = rect;
+  m_is_a_single_elem = is_a_single_elem;
+  m_memoryProxy = nullptr;
+  m_num_channels = num_channels;
+  m_datatype = COM_num_channels_data_type(num_channels);
+  m_buffer = buffer;
+  owns_data_ = false;
+  m_state = MemoryBufferState::Temporary;
+
+  set_strides();
+}
+
 MemoryBuffer::MemoryBuffer(const MemoryBuffer &src)
     : MemoryBuffer(src.m_datatype, src.m_rect, false)
 {
@@ -112,31 +166,195 @@ float MemoryBuffer::get_max_value(const rcti &rect) const
 
 MemoryBuffer::~MemoryBuffer()
 {
-  if (this->m_buffer) {
+  if (this->m_buffer && owns_data_) {
     MEM_freeN(this->m_buffer);
     this->m_buffer = nullptr;
   }
 }
 
-void MemoryBuffer::fill_from(const MemoryBuffer &src)
+void MemoryBuffer::copy_from(const MemoryBuffer *src, const rcti &area)
 {
-  BLI_assert(!this->is_a_single_elem());
+  copy_from(src, area, area.xmin, area.ymin);
+}
+
+void MemoryBuffer::copy_from(const MemoryBuffer *src,
+                             const rcti &area,
+                             const int to_x,
+                             const int to_y)
+{
+  BLI_assert(this->get_num_channels() == src->get_num_channels());
+  copy_from(src, area, 0, src->get_num_channels(), to_x, to_y, 0);
+}
+
+void MemoryBuffer::copy_from(const MemoryBuffer *src,
+                             const rcti &area,
+                             const int channel_offset,
+                             const int elem_size,
+                             const int to_channel_offset)
+{
+  copy_from(src, area, channel_offset, elem_size, area.xmin, area.ymin, to_channel_offset);
+}
+
+void MemoryBuffer::copy_from(const MemoryBuffer *src,
+                             const rcti &area,
+                             const int channel_offset,
+                             const int elem_size,
+                             const int to_x,
+                             const int to_y,
+                             const int to_channel_offset)
+{
+  if (this->is_a_single_elem()) {
+    copy_single_elem_from(src, channel_offset, elem_size, to_channel_offset);
+  }
+  else if (!src->is_a_single_elem() && elem_size == src->get_num_channels() &&
+           elem_size == this->get_num_channels()) {
+    BLI_assert(to_channel_offset == 0);
+    BLI_assert(channel_offset == 0);
+    copy_rows_from(src, area, to_x, to_y);
+  }
+  else {
+    copy_elems_from(src, area, channel_offset, elem_size, to_x, to_y, to_channel_offset);
+  }
+}
+
+void MemoryBuffer::copy_from(const uchar *src, const rcti &area)
+{
+  copy_from(src, area, 0, this->get_num_channels(), this->get_num_channels(), 0);
+}
+
+void MemoryBuffer::copy_from(const uchar *src,
+                             const rcti &area,
+                             const int channel_offset,
+                             const int elem_size,
+                             const int elem_stride,
+                             const int to_channel_offset)
+{
+  copy_from(
+      src, area, channel_offset, elem_size, elem_stride, area.xmin, area.ymin, to_channel_offset);
+}
+
+void MemoryBuffer::copy_from(const uchar *src,
+                             const rcti &area,
+                             const int channel_offset,
+                             const int elem_size,
+                             const int elem_stride,
+                             const int to_x,
+                             const int to_y,
+                             const int to_channel_offset)
+{
+  ASSERT_BUFFER_CONTAINS_AREA_AT_COORDS(this, area, to_x, to_y);
+  ASSERT_VALID_ELEM_SIZE(this, to_channel_offset, elem_size);
+
+  const int width = BLI_rcti_size_x(&area);
+  const int height = BLI_rcti_size_y(&area);
+  const int src_row_stride = width * elem_stride;
+  const uchar *const src_start = src + area.ymin * src_row_stride + channel_offset;
+  for (int y = 0; y < height; y++) {
+    const uchar *from_elem = src_start + y * src_row_stride;
+    float *to_elem = &this->get_value(to_x, to_y + y, to_channel_offset);
+    const float *row_end = to_elem + width * this->elem_stride;
+    while (to_elem < row_end) {
+      for (int i = 0; i < elem_size; i++) {
+        to_elem[i] = ((float)from_elem[i]) * (1.0f / 255.0f);
+      }
+      to_elem += this->elem_stride;
+      from_elem += elem_stride;
+    }
+  }
+}
+
+static void colorspace_to_scene_linear(MemoryBuffer *buf, const rcti &area, ColorSpace *colorspace)
+{
+  const int width = BLI_rcti_size_x(&area);
+  const int height = BLI_rcti_size_y(&area);
+  float *out = buf->get_elem(area.xmin, area.ymin);
+  /* If area allows continuous memory do conversion in one step. Otherwise per row. */
+  if (buf->getWidth() == width) {
+    IMB_colormanagement_colorspace_to_scene_linear(
+        out, width, height, buf->get_num_channels(), colorspace, false);
+  }
+  else {
+    for (int y = 0; y < height; y++) {
+      IMB_colormanagement_colorspace_to_scene_linear(
+          out, width, 1, buf->get_num_channels(), colorspace, false);
+      out += buf->row_stride;
+    }
+  }
+}
+
+void MemoryBuffer::copy_from(const ImBuf *src, const rcti &area, const bool ensure_linear_space)
+{
+  copy_from(src, area, 0, this->get_num_channels(), 0, ensure_linear_space);
+}
 
-  unsigned int otherY;
-  unsigned int minX = MAX2(this->m_rect.xmin, src.m_rect.xmin);
-  unsigned int maxX = MIN2(this->m_rect.xmax, src.m_rect.xmax);
-  unsigned int minY = MAX2(this->m_rect.ymin, src.m_rect.ymin);
-  unsigned int maxY = MIN2(this->m_rect.ymax, src.m_rect.ymax);
-  int offset;
-  int otherOffset;
+void MemoryBuffer::copy_from(const ImBuf *src,
+                             const rcti &area,
+                             const int channel_offset,
+                             const int elem_size,
+                             const int to_channel_offset,
+                             const bool ensure_linear_space)
+{
+  copy_from(src,
+            area,
+            channel_offset,
+            elem_size,
+            area.xmin,
+            area.ymin,
+            to_channel_offset,
+            ensure_linear_space);
+}
 
-  for (otherY = minY; otherY < maxY; otherY++) {
-    otherOffset = src.get_coords_offset(minX, otherY);
-    offset = this->get_coords_offset(minX, otherY);
-    memcpy(&this->m_buffer[offset],
-           &src.m_buffer[otherOffset],
-           (maxX - minX) * this->m_num_channels * sizeof(float));
+void MemoryBuffer::copy_from(const ImBuf *src,
+                             const rcti &area,
+                             const int channel_offset,
+                       

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list