Patch Detail
Show a patch.
GET /api/patches/26863/?format=api
{ "id": 26863, "url": "https://patchwork.libcamera.org/api/patches/26863/?format=api", "web_url": "https://patchwork.libcamera.org/patch/26863/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/projects/1/?format=api", "name": "libcamera", "link_name": "libcamera", "list_id": "libcamera_core", "list_email": "libcamera-devel@lists.libcamera.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20260609225356.23383-1-robert.mader@collabora.com>", "date": "2026-06-09T22:53:56", "name": "[v3] software_isp: debayer_egl: Request input buffer alignment of 256 bytes", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "9b818df04679616f4816ff1152859dd212268d9b", "submitter": { "id": 140, "url": "https://patchwork.libcamera.org/api/people/140/?format=api", "name": "Robert Mader", "email": "robert.mader@collabora.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/26863/mbox/", "series": [ { "id": 5984, "url": "https://patchwork.libcamera.org/api/series/5984/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5984", "date": "2026-06-09T22:53:56", "name": "[v3] software_isp: debayer_egl: Request input buffer alignment of 256 bytes", "version": 3, "mbox": "https://patchwork.libcamera.org/series/5984/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/26863/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/26863/checks/", "tags": {}, "headers": { "Return-Path": "<libcamera-devel-bounces@lists.libcamera.org>", "X-Original-To": "parsemail@patchwork.libcamera.org", "Delivered-To": "parsemail@patchwork.libcamera.org", "Received": [ "from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id B36D7C324C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 9 Jun 2026 22:54:28 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 9CFB161F04;\n\tWed, 10 Jun 2026 00:54:27 +0200 (CEST)", "from sender4-pp-f112.zoho.com (sender4-pp-f112.zoho.com\n\t[136.143.188.112])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 5A1F361E74\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 10 Jun 2026 00:54:25 +0200 (CEST)", "by mx.zohomail.com with SMTPS id 1781045658211847.558637378632;\n\tTue, 9 Jun 2026 15:54:18 -0700 (PDT)" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=collabora.com\n\theader.i=robert.mader@collabora.com header.b=\"OOM9HXBI\"; \n\tdkim-atps=neutral", "ARC-Seal": "i=1; a=rsa-sha256; t=1781045659; cv=none; \n\td=zohomail.com; s=zohoarc; \n\tb=M5vDYzQifst2j/5B2OUUfvlifeOzgHJ1HBwNiG83MPYTC5NMc6bXbky3f5KUZFL8s2pEyKduDDz1ExpHqX8lXpwypZrBkNOZHmMmfLVPit1VkCqWHxDZJaj+Bbns41iAlTo0gkZbmhVdLOeQJAuaa2jt6eaXglb7ivyFQlBuqtk=", "ARC-Message-Signature": "i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; \n\ts=zohoarc; t=1781045659;\n\th=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:MIME-Version:Message-ID:Subject:Subject:To:To:Message-Id:Reply-To;\n\tbh=QXnbk/urw/c44ajrWzhHMA1U8gHc0TkrpUFxnOrwUHc=; \n\tb=QddPE8Zh7h8/o1t/CJsX9KblAZekCreHhBesMp8DxXtNAsA1MJOYigJ8wkBNx6BIEQiT4rO+Y3BqlyAND6ztfltJH/lqmrzACXL3Jhz5hv8o1Nma9ffbldklTTm1qu1HlXOWQxLpCpQ3g38OEPmF6kiT/Sxs73otKCLJ0dVAzv8=", "ARC-Authentication-Results": "i=1; mx.zohomail.com;\n\tdkim=pass header.i=collabora.com;\n\tspf=pass smtp.mailfrom=robert.mader@collabora.com;\n\tdmarc=pass header.from=<robert.mader@collabora.com>", "DKIM-Signature": "v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1781045659;\n\ts=zohomail; d=collabora.com; i=robert.mader@collabora.com;\n\th=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To;\n\tbh=QXnbk/urw/c44ajrWzhHMA1U8gHc0TkrpUFxnOrwUHc=;\n\tb=OOM9HXBIFWUQNPQBEch4xfblP6a7AS9fYxW99FGPEYDuO1msQNsHVB4bqhcdxC0i\n\tLCk7eTRhTlREP8eNiRah5KegT1JlV6m4tCetvn4+5gNKS/+a6NJMdzMaSzw3KzqOqsC\n\tUvZPkKl18eP9xqSrqXPpDccvafSXfxHDlzDXaYgw=", "From": "Robert Mader <robert.mader@collabora.com>", "To": "libcamera-devel@lists.libcamera.org", "Cc": "Robert Mader <robert.mader@collabora.com>", "Subject": "[PATCH v3] software_isp: debayer_egl: Request input buffer alignment\n\tof 256 bytes", "Date": "Wed, 10 Jun 2026 00:53:56 +0200", "Message-ID": "<20260609225356.23383-1-robert.mader@collabora.com>", "X-Mailer": "git-send-email 2.54.0", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "X-BeenThere": "libcamera-devel@lists.libcamera.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "<libcamera-devel.lists.libcamera.org>", "List-Unsubscribe": "<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>", "List-Archive": "<https://lists.libcamera.org/pipermail/libcamera-devel/>", "List-Post": "<mailto:libcamera-devel@lists.libcamera.org>", "List-Help": "<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>", "List-Subscribe": "<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>", "Errors-To": "libcamera-devel-bounces@lists.libcamera.org", "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>" }, "content": "The most common reason dmabuf import with createInputDMABufTexture2D()\nfails is that V4L2 drivers use stride alignments that are not sufficient\n(too small) for GPUs, preventing the later from directly using input\nbuffers and forcing us to do relatively expensive uploads (i.e. copies)\nof the buffer contents.\n\nThus let's request a compatible stride alignment from the V4L2 driver,\nwhich may or may not respect the value. From the v4l2_pix_format ->\nbytesperline docs:\n> Both applications and drivers can set this field to request padding\n> bytes at the end of each line. Drivers however may ignore the value\n> requested by the application, returning width times bytes per pixel\n> or a larger value required by the hardware. That implies applications\n> can just set this field to zero to get a reasonable default.\n\nThe approach works as follows:\n1. Before setting the input format, query into the debayer class for a\n preferred stride based on the bayer format and width. For DebayerCpu\n this returns 0, i.e. let the V4L2 driver decide, while for DebayerEGL\n the \"magic\" stride alignment of 256 bytes is used, which is known\n to work with all known/common GPUs and already used for output\n buffers. Right now there doesn't exist any API to query the correct\n value - in many cases it is 64 or 128 - however if e.g. a new EGL\n extension will provide it in the future, we can easily implement it\n in the new function. Alternatively a config value or env var could be\n added there if the need arises.\n2. Pass the calculated stride to V4L2VideoDevice::setFormat(), which\n again sets it as the bytesperline value.\n3. The V4L2 driver will update bytesperline with the value it actually\n chose to use. Compare the requested and actual strides and log an info\n message if the driver did not honor the request, hinting users at what\n could be improved about the kernel driver.\n\nSigned-off-by: Robert Mader <robert.mader@collabora.com>\n\n---\n\nChanges in V3:\n - Renamed getPreferredInputStride() to preferredInputStride()\n\nChanges in V2:\n - Updated the commit message to be much more verbose and hopefully easy\n to understand.\n - Minor cleanups and fixes for docs and CI.\n\nPrevious version: https://patchwork.libcamera.org/patch/26810/\n---\n .../libcamera/internal/software_isp/software_isp.h | 1 +\n src/libcamera/pipeline/simple/simple.cpp | 12 ++++++++++++\n src/libcamera/software_isp/debayer.cpp | 8 ++++++++\n src/libcamera/software_isp/debayer.h | 1 +\n src/libcamera/software_isp/debayer_egl.cpp | 7 +++++++\n src/libcamera/software_isp/debayer_egl.h | 1 +\n src/libcamera/software_isp/software_isp.cpp | 13 +++++++++++++\n 7 files changed, 43 insertions(+)", "diff": "diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h\nindex 86cb8f8de..4f72dce9b 100644\n--- a/include/libcamera/internal/software_isp/software_isp.h\n+++ b/include/libcamera/internal/software_isp/software_isp.h\n@@ -61,6 +61,7 @@ public:\n \n \tstd::tuple<unsigned int, unsigned int>\n \tstrideAndFrameSize(const PixelFormat &outputFormat, const Size &size);\n+\tuint32_t preferredInputStride(const PixelFormat &inputFormat, const Size &size);\n \n \tint configure(const StreamConfiguration &inputCfg,\n \t\t const std::vector<std::reference_wrapper<const StreamConfiguration>> &outputCfgs,\ndiff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\nindex c6fe12d65..e26f438d9 100644\n--- a/src/libcamera/pipeline/simple/simple.cpp\n+++ b/src/libcamera/pipeline/simple/simple.cpp\n@@ -1542,6 +1542,11 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)\n \tcaptureFormat.fourcc = videoFormat;\n \tcaptureFormat.size = pipeConfig->captureSize;\n \n+\tuint32_t requested_bpl = 0;\n+\tif (data->swIsp_)\n+\t\trequested_bpl = data->swIsp_->preferredInputStride(videoFormat.toPixelFormat(), pipeConfig->captureSize);\n+\tcaptureFormat.planes[0].bpl = requested_bpl;\n+\n \tret = video->setFormat(&captureFormat);\n \tif (ret)\n \t\treturn ret;\n@@ -1561,6 +1566,13 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)\n \t\treturn -EINVAL;\n \t}\n \n+\tif (requested_bpl && captureFormat.planes[0].bpl != requested_bpl) {\n+\t\tLOG(SimplePipeline, Info)\n+\t\t\t<< \"Input buffer stride ignored by the driver. \"\n+\t\t\t<< \"Requested \" << requested_bpl\n+\t\t\t<< \", got \" << captureFormat.planes[0].bpl;\n+\t}\n+\n \t/* Configure the converter if needed. */\n \tstd::vector<std::reference_wrapper<const StreamConfiguration>> outputCfgs;\n \tdata->useConversion_ = config->needConversion();\ndiff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp\nindex 2d7abfb83..56446f55d 100644\n--- a/src/libcamera/software_isp/debayer.cpp\n+++ b/src/libcamera/software_isp/debayer.cpp\n@@ -103,6 +103,14 @@ Debayer::~Debayer()\n * there is no valid output config\n */\n \n+/**\n+ * \\fn uint32_t Debayer::preferredInputStride(const PixelFormat &inputFormat, const Size &size)\n+ * Get the preferred input stride in bytes for the given input format and size\n+ * \\param[in] inputFormat The input format\n+ * \\param[in] size The input size (width and height in pixels)\n+ * \\return The preferred input stride in bytes or 0 if there is no preference\n+ */\n+\n /**\n * \\fn void Debayer::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, DebayerParams params)\n * \\brief Process the bayer data into the requested format\ndiff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h\nindex a2a17ec18..28f1b857b 100644\n--- a/src/libcamera/software_isp/debayer.h\n+++ b/src/libcamera/software_isp/debayer.h\n@@ -46,6 +46,7 @@ public:\n \n \tvirtual std::tuple<unsigned int, unsigned int>\n \tstrideAndFrameSize(const PixelFormat &outputFormat, const Size &size) = 0;\n+\tvirtual uint32_t preferredInputStride([[maybe_unused]] const PixelFormat &inputFormat, [[maybe_unused]] const Size &size) { return 0; }\n \n \tvirtual void process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms) = 0;\n \tvirtual int start() { return 0; }\ndiff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp\nindex 8e52b45ae..fd8de3942 100644\n--- a/src/libcamera/software_isp/debayer_egl.cpp\n+++ b/src/libcamera/software_isp/debayer_egl.cpp\n@@ -21,6 +21,7 @@\n \n #include <libcamera/formats.h>\n \n+#include \"libcamera/internal/formats.h\"\n #include \"libcamera/internal/framebuffer.h\"\n \n #include \"../glsl_shaders.h\"\n@@ -387,6 +388,12 @@ DebayerEGL::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size\n \treturn std::make_tuple(stride, stride * size.height);\n }\n \n+uint32_t DebayerEGL::preferredInputStride(const PixelFormat &inputFormat, const Size &size)\n+{\n+\tconst PixelFormatInfo &info = PixelFormatInfo::info(inputFormat);\n+\treturn info.stride(size.width, 0, 256);\n+}\n+\n void DebayerEGL::setShaderVariableValues(const DebayerParams ¶ms)\n {\n \t/*\ndiff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h\nindex 875e7cfc5..943410fdd 100644\n--- a/src/libcamera/software_isp/debayer_egl.h\n+++ b/src/libcamera/software_isp/debayer_egl.h\n@@ -50,6 +50,7 @@ public:\n \n \tstd::vector<PixelFormat> formats(PixelFormat input) override;\n \tstd::tuple<unsigned int, unsigned int> strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) override;\n+\tuint32_t preferredInputStride(const PixelFormat &inputFormat, const Size &size) override;\n \n \tvoid process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms) override;\n \tint start() override;\ndiff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp\nindex 781cf02f8..19f83e611 100644\n--- a/src/libcamera/software_isp/software_isp.cpp\n+++ b/src/libcamera/software_isp/software_isp.cpp\n@@ -255,6 +255,19 @@ SoftwareIsp::strideAndFrameSize(const PixelFormat &outputFormat, const Size &siz\n \treturn debayer_->strideAndFrameSize(outputFormat, size);\n }\n \n+/**\n+ * Get the preferred input stride in bytes for the given input format and size\n+ * \\param[in] inputFormat The input format\n+ * \\param[in] size The input size (width and height in pixels)\n+ * \\return The preferred input stride in bytes or 0 if there is no preference\n+ */\n+uint32_t SoftwareIsp::preferredInputStride(const PixelFormat &inputFormat, const Size &size)\n+{\n+\tASSERT(debayer_);\n+\n+\treturn debayer_->preferredInputStride(inputFormat, size);\n+}\n+\n /**\n * \\brief Configure the SoftwareIsp object according to the passed in parameters\n * \\param[in] inputCfg The input configuration\n", "prefixes": [ "v3" ] }