[PATCH v2] libcamera: debayer_cpu: Sync DMABUFs

Robert Mader robert.mader at collabora.com
Fri Sep 13 14:04:16 CEST 2024


Using `DMA_BUF_IOCTL_SYNC` is required for DMABUFs in order to ensure
correct output. Not doing so currently results in occasional tearing
and/or backlashes in GL/VK clients that use the buffers directly for
rendering.

An alternative approach to have the sync code in `MappedFrameBuffer` was
considered but rejected for now, in order to allow clients more
flexibility.

Signed-off-by: Robert Mader <robert.mader at collabora.com>

---

Changes in v2:
 - sync input buffer as well
 - update commit title accordingly
 - small changes to the commit message
 - linting fixes, should pass now
---
 src/libcamera/software_isp/debayer_cpu.cpp | 35 ++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp
index 077f7f4b..a3b4851c 100644
--- a/src/libcamera/software_isp/debayer_cpu.cpp
+++ b/src/libcamera/software_isp/debayer_cpu.cpp
@@ -12,8 +12,11 @@
 #include "debayer_cpu.h"
 
 #include <stdlib.h>
+#include <sys/ioctl.h>
 #include <time.h>
 
+#include <linux/dma-buf.h>
+
 #include <libcamera/formats.h>
 
 #include "libcamera/internal/bayer_format.h"
@@ -733,6 +736,22 @@ void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams
 		clock_gettime(CLOCK_MONOTONIC_RAW, &frameStartTime);
 	}
 
+	for (const FrameBuffer::Plane &plane : input->planes()) {
+		const int fd = plane.fd.get();
+		struct dma_buf_sync sync = { DMA_BUF_SYNC_START | DMA_BUF_SYNC_READ };
+
+		if (ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync) < 0)
+			LOG(Debayer, Error) << "Syncing buffer FD " << fd << "failed: " << errno;
+	}
+
+	for (const FrameBuffer::Plane &plane : output->planes()) {
+		const int fd = plane.fd.get();
+		struct dma_buf_sync sync = { DMA_BUF_SYNC_START | DMA_BUF_SYNC_WRITE };
+
+		if (ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync) < 0)
+			LOG(Debayer, Error) << "Syncing buffer FD " << fd << "failed: " << errno;
+	}
+
 	green_ = params.green;
 	red_ = swapRedBlueGains_ ? params.blue : params.red;
 	blue_ = swapRedBlueGains_ ? params.red : params.blue;
@@ -760,6 +779,22 @@ void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams
 
 	metadata.planes()[0].bytesused = out.planes()[0].size();
 
+	for (const FrameBuffer::Plane &plane : output->planes()) {
+		const int fd = plane.fd.get();
+		struct dma_buf_sync sync = { DMA_BUF_SYNC_END | DMA_BUF_SYNC_WRITE };
+
+		if (ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync) < 0)
+			LOG(Debayer, Error) << "Syncing buffer FD " << fd << "failed: " << errno;
+	}
+
+	for (const FrameBuffer::Plane &plane : input->planes()) {
+		const int fd = plane.fd.get();
+		struct dma_buf_sync sync = { DMA_BUF_SYNC_END | DMA_BUF_SYNC_READ };
+
+		if (ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync) < 0)
+			LOG(Debayer, Error) << "Syncing buffer FD " << fd << "failed: " << errno;
+	}
+
 	/* Measure before emitting signals */
 	if (measuredFrames_ < DebayerCpu::kLastFrameToMeasure &&
 	    ++measuredFrames_ > DebayerCpu::kFramesToSkip) {
-- 
2.46.0



More information about the libcamera-devel mailing list