[PATCH v2] libcamera: debayer_cpu: Sync DMABUFs
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Fri Sep 13 14:38:44 CEST 2024
On Fri, Sep 13, 2024 at 01:31:11PM +0100, Kieran Bingham wrote:
> Quoting Robert Mader (2024-09-13 13:04:16)
> > 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;
>
> We can't use 'errno' directly on our error messages because the LOG()
> implementations or other processing of the log statement (not in this
> case, but in others it could be possible) could affect errno.
>
> So we use the style
>
> src/libcamera/dma_buf_allocator.cpp- if (ret < 0) {
> src/libcamera/dma_buf_allocator.cpp: ret = errno;
> src/libcamera/dma_buf_allocator.cpp- LOG(DmaBufAllocator, Error)
> src/libcamera/dma_buf_allocator.cpp- << "Failed to create dma buf for " << name
> src/libcamera/dma_buf_allocator.cpp- << ": " << strerror(ret);
> src/libcamera/dma_buf_allocator.cpp- return {};
> src/libcamera/dma_buf_allocator.cpp- }
>
> Where we store the errno immediately and then use it in the log. It's
> also helpful to use strerror too.
>
> > + }
> > +
> > + 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;
> > + }
>
> (jumping back up from below) And this likewise could then be:
>
> intput->sync(DMA_BUF_SYNC_START | DMA_BUF_SYNC_READ);
> output->sync(DMA_BUF_SYNC_START | DMA_BUF_SYNC_WRITE);
>
> > +
> > 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;
>
> That's four iterations of very similar code. I think we could add a
> helper directly into FrameBuffer directly as a preceeding patch, that
> would allow something more like:
>
> output->sync(DMA_BUF_SYNC_END | DMA_BUF_SYNC_WRITE);
> input->sync(DMA_BUF_SYNC_END | DMA_BUF_SYNC_READ);
>
> We could probably do that using our Flags class too ... but the above
> would be a good start.
I'd like a helper too, but I don't think it should be part of the public
API, so the FrameBuffer class isn't the right place.
> > + }
> > +
> > /* Measure before emitting signals */
> > if (measuredFrames_ < DebayerCpu::kLastFrameToMeasure &&
> > ++measuredFrames_ > DebayerCpu::kFramesToSkip) {
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list