From patchwork Thu Jun 4 10:14:48 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Mader X-Patchwork-Id: 26843 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 59F0CC324C for ; Thu, 4 Jun 2026 10:15:23 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 447AA63400; Thu, 4 Jun 2026 12:15:22 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=collabora.com header.i=robert.mader@collabora.com header.b="ZgvHmh7Y"; dkim-atps=neutral Received: from sender4-pp-f112.zoho.com (sender4-pp-f112.zoho.com [136.143.188.112]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2884A62DC4 for ; Thu, 4 Jun 2026 12:15:20 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; t=1780568115; cv=none; d=zohomail.com; s=zohoarc; b=fvoMatQ+cKqMCjmPs17EjUMPpO0ZYz/m85yvre7oYFSl2IfvPRuYjDvBBk9Qis51Op7UEpOBn6ilcvpJx6aaaf0YEfwyCBfpcU78D2OHWrkfVI3ReJX/O3WNEXQeOlk7lwGhyXs71Fnck/ryMxx1Nk1mkw6+GNMPkm3pJcbxN8s= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1780568115; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:MIME-Version:Message-ID:Subject:Subject:To:To:Message-Id:Reply-To; bh=zZvPsOapnFuI0owyWSdx57LdZt/4M1yi2gbZCCOVIJc=; b=WWAGAEicqYVxVIZXI63fm08ezjetH8b7V3O4g3fpOQVVpvu2Pd+OptZPjDcpxdm3NSKpcBAXq1DKQInhil003q0VYeNp6lIXqxzgKciUhgBGRfTy3qUwL5lXrcvzZ1FfX6LFt+go00r44AgfV5POaNzM1JmoYwuNv+ucXIR5wFM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=collabora.com; spf=pass smtp.mailfrom=robert.mader@collabora.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1780568115; s=zohomail; d=collabora.com; i=robert.mader@collabora.com; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=zZvPsOapnFuI0owyWSdx57LdZt/4M1yi2gbZCCOVIJc=; b=ZgvHmh7Y08r4g0GB5TWGlz/Pm0keKPlzaqJixaNdwUf3Z2NqRTgHgSo4Ji+BnVEw 4cz760WZTX72uyTLFx3xYx61a+3EIQh2sI7Xa48XY0+nF9k41yHiFBr5rOiHUcWC5f6 6YI+tVyaNDuYgWaKzdvVHFtyOqPg1MUQWzBhhyh0= Received: by mx.zohomail.com with SMTPS id 1780568112556394.48059806099945; Thu, 4 Jun 2026 03:15:12 -0700 (PDT) From: Robert Mader To: libcamera-devel@lists.libcamera.org Cc: Robert Mader Subject: [PATCH v2] software_isp: debayer_egl: Request input buffer alignment of 256 bytes Date: Thu, 4 Jun 2026 12:14:48 +0200 Message-ID: <20260604101448.45378-1-robert.mader@collabora.com> X-Mailer: git-send-email 2.54.0 MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The most common reason dmabuf import with createInputDMABufTexture2D() fails is that V4L2 drivers use stride alignments that are not sufficient (too small) for GPUs, preventing the later from directly using input buffers and forcing us to do relatively expensive uploads (i.e. copies) of the buffer contents. Thus let's request a compatible stride alignment from the V4L2 driver, which may or may not respect the value. From the v4l2_pix_format -> bytesperline docs: > Both applications and drivers can set this field to request padding > bytes at the end of each line. Drivers however may ignore the value > requested by the application, returning width times bytes per pixel > or a larger value required by the hardware. That implies applications > can just set this field to zero to get a reasonable default. The approach works as follows: 1. Before setting the input format, query into the debayer class for a preferred stride based on the bayer format and width. For DebayerCpu this returns 0, i.e. let the V4L2 driver decide, while for DebayerEGL the "magic" stride alignment of 256 bytes is used, which is known to work with all known/common GPUs and already used for output buffers. Right now there doesn't exist any API to query the correct value - in many cases it is 64 or 128 - however if e.g. a new EGL extension will provide it in the future, we can easily implement it in the new function. Alternatively a config value or env var could be added there if the need arises. 2. Pass the calculated stride to V4L2VideoDevice::setFormat(), which again sets it as the bytesperline value. 3. The V4L2 driver will update bytesperline with the value it actually chose to use. Compare the requested and actual strides and log a info message if the driver did not honor the request, hinting users at what could be improved about the kernel driver. Signed-off-by: Robert Mader --- Changes in V2: - Updated the commit message to be much more verbose and hopefully easy to understand. - Minor cleanups and fixes for docs and CI. Previous version: https://patchwork.libcamera.org/patch/26810/ --- .../libcamera/internal/software_isp/software_isp.h | 1 + src/libcamera/pipeline/simple/simple.cpp | 12 ++++++++++++ src/libcamera/software_isp/debayer.cpp | 8 ++++++++ src/libcamera/software_isp/debayer.h | 1 + src/libcamera/software_isp/debayer_egl.cpp | 7 +++++++ src/libcamera/software_isp/debayer_egl.h | 1 + src/libcamera/software_isp/software_isp.cpp | 13 +++++++++++++ 7 files changed, 43 insertions(+) diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h index 86cb8f8de..7440937c2 100644 --- a/include/libcamera/internal/software_isp/software_isp.h +++ b/include/libcamera/internal/software_isp/software_isp.h @@ -61,6 +61,7 @@ public: std::tuple strideAndFrameSize(const PixelFormat &outputFormat, const Size &size); + uint32_t getPreferredInputStride(const PixelFormat &inputFormat, const Size &size); int configure(const StreamConfiguration &inputCfg, const std::vector> &outputCfgs, diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index c6fe12d65..0de2fe695 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -1542,6 +1542,11 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) captureFormat.fourcc = videoFormat; captureFormat.size = pipeConfig->captureSize; + uint32_t requested_bpl = 0; + if (data->swIsp_) + requested_bpl = data->swIsp_->getPreferredInputStride(videoFormat.toPixelFormat(), pipeConfig->captureSize); + captureFormat.planes[0].bpl = requested_bpl; + ret = video->setFormat(&captureFormat); if (ret) return ret; @@ -1561,6 +1566,13 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) return -EINVAL; } + if (requested_bpl && captureFormat.planes[0].bpl != requested_bpl) { + LOG(SimplePipeline, Info) + << "Input buffer stride ignored by the driver. " + << "Requested " << requested_bpl + << ", got " << captureFormat.planes[0].bpl; + } + /* Configure the converter if needed. */ std::vector> outputCfgs; data->useConversion_ = config->needConversion(); diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp index 2d7abfb83..befed51df 100644 --- a/src/libcamera/software_isp/debayer.cpp +++ b/src/libcamera/software_isp/debayer.cpp @@ -103,6 +103,14 @@ Debayer::~Debayer() * there is no valid output config */ +/** + * \fn uint32_t Debayer::getPreferredInputStride(const PixelFormat &inputFormat, const Size &size) + * Get the preferred input stride in bytes for the given input format and size + * \param[in] inputFormat The input format + * \param[in] size The input size (width and height in pixels) + * \return The preferred input stride in bytes or 0 if there is no preference + */ + /** * \fn void Debayer::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, DebayerParams params) * \brief Process the bayer data into the requested format diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h index a2a17ec18..ddb4988a8 100644 --- a/src/libcamera/software_isp/debayer.h +++ b/src/libcamera/software_isp/debayer.h @@ -46,6 +46,7 @@ public: virtual std::tuple strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) = 0; + virtual uint32_t getPreferredInputStride([[maybe_unused]] const PixelFormat &inputFormat, [[maybe_unused]] const Size &size) { return 0; } virtual void process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms) = 0; virtual int start() { return 0; } diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 99825d49e..fc995cd0c 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -21,6 +21,7 @@ #include +#include "libcamera/internal/formats.h" #include "libcamera/internal/framebuffer.h" #include "../glsl_shaders.h" @@ -378,6 +379,12 @@ DebayerEGL::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size return std::make_tuple(stride, stride * size.height); } +uint32_t DebayerEGL::getPreferredInputStride(const PixelFormat &inputFormat, const Size &size) +{ + const PixelFormatInfo &info = PixelFormatInfo::info(inputFormat); + return info.stride(size.width, 0, 256); +} + void DebayerEGL::setShaderVariableValues(const DebayerParams ¶ms) { /* diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h index 875e7cfc5..0f673e82f 100644 --- a/src/libcamera/software_isp/debayer_egl.h +++ b/src/libcamera/software_isp/debayer_egl.h @@ -50,6 +50,7 @@ public: std::vector formats(PixelFormat input) override; std::tuple strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) override; + uint32_t getPreferredInputStride(const PixelFormat &inputFormat, const Size &size) override; void process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms) override; int start() override; diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index 781cf02f8..b54233fb0 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -255,6 +255,19 @@ SoftwareIsp::strideAndFrameSize(const PixelFormat &outputFormat, const Size &siz return debayer_->strideAndFrameSize(outputFormat, size); } +/** + * Get the preferred input stride in bytes for the given input format and size + * \param[in] inputFormat The input format + * \param[in] size The input size (width and height in pixels) + * \return The preferred input stride in bytes or 0 if there is no preference + */ +uint32_t SoftwareIsp::getPreferredInputStride(const PixelFormat &inputFormat, const Size &size) +{ + ASSERT(debayer_); + + return debayer_->getPreferredInputStride(inputFormat, size); +} + /** * \brief Configure the SoftwareIsp object according to the passed in parameters * \param[in] inputCfg The input configuration