Patch Detail
Show a patch.
GET /api/patches/25711/?format=api
{ "id": 25711, "url": "https://patchwork.libcamera.org/api/patches/25711/?format=api", "web_url": "https://patchwork.libcamera.org/patch/25711/", "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": "<20260110210930.123920-1-robert.mader@collabora.com>", "date": "2026-01-10T21:09:30", "name": "RFC: egl: Implement DMABuf import for input buffers", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "549e969c1a3e35ae2eaee2dd665bfdcf9f81a4ac", "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/25711/mbox/", "series": [ { "id": 5699, "url": "https://patchwork.libcamera.org/api/series/5699/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5699", "date": "2026-01-10T21:09:30", "name": "RFC: egl: Implement DMABuf import for input buffers", "version": 1, "mbox": "https://patchwork.libcamera.org/series/5699/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/25711/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/25711/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 94E1ABE08B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSat, 10 Jan 2026 21:09:56 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id C457061FA0;\n\tSat, 10 Jan 2026 22:09:55 +0100 (CET)", "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 9BE0161A35\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 10 Jan 2026 22:09:53 +0100 (CET)", "by mx.zohomail.com with SMTPS id 1768079388831202.18040813299058; \n\tSat, 10 Jan 2026 13:09:48 -0800 (PST)" ], "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=\"YTRKD5lH\"; \n\tdkim-atps=neutral", "ARC-Seal": "i=1; a=rsa-sha256; t=1768079390; cv=none; \n\td=zohomail.com; s=zohoarc; \n\tb=hPJLqyivoDeoe/gpet85nwlFZH4Y6TruMuudgUCWHx/GVCkkmVYuXWhy6sbUFj2H/7mlhY/1puYiC2Ot1u2gsH/onXoC6gF8+ELJqlFGHC8YDk45+/ggoPIuhCkGvGzEWBdgWgC2l8h405S1Qe4XjD2OYI6jdbTOvwJsdzk5pXI=", "ARC-Message-Signature": "i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; \n\ts=zohoarc; t=1768079390;\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=HAlaZ9YrlOiWZQaawaiKN9sNV7/yLS4yNislAg+ZmG0=; \n\tb=VVItXbp4tFAeoLH8lNcftZ8gbq68jue/B9xpRemoldW3fmMTdJxW9YJ+ZLx24ZEytnjvfnsjwuHhuF9u/J3cY5ND0bEfWdCHxUQ409MBmCaiUsLxSHFm8SDlH2XFNgPPhgB+jgodUr7jmtNCx3PjIre3VW6GvSE1fAJ1rR3lUII=", "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=1768079390;\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=HAlaZ9YrlOiWZQaawaiKN9sNV7/yLS4yNislAg+ZmG0=;\n\tb=YTRKD5lHBmZHeiaBvV9nzxlhidJQL+emWIEHJOT1CYT2A+jHrwG6Q+7FEO++xTlb\n\tJpwQX5r+ipYid75ZWykKobOrOKyEYBVPi5UlSi1ay+qE0NEescM0z74TzK2MTxpxSmc\n\t13SULdxWaMq1EeUcdQZffmwJ6h07TMA61OF9hSbU=", "From": "Robert Mader <robert.mader@collabora.com>", "To": "libcamera-devel@lists.libcamera.org", "Cc": "Robert Mader <robert.mader@collabora.com>", "Subject": "[PATCH] RFC: egl: Implement DMABuf import for input buffers", "Date": "Sat, 10 Jan 2026 22:09:30 +0100", "Message-ID": "<20260110210930.123920-1-robert.mader@collabora.com>", "X-Mailer": "git-send-email 2.52.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": "In many cases we can import the GPU-ISP input buffer, a dmabuf from v4l2,\ndirectly into EGL instead of mapping and uploading - i.e. copying - it.\nThis reduces memory bandwith usage and can even slightly improve\nlatency.\nThis main reason this doesn't work in many cases is the stride\nalignment, as GPUs often have stricter requirements (often 128 or even\n256 bytes) than hardware ISPs.\n\nThus try to import buffer directly and - if that fails - fall back to\nthe previous upload path. To do so, adjust some function parameters and\nturn down error messages. Failing imports should come at low cost as\ndrivers know the limitations and can bail out early, without causing\nadditional IO or context switches.\n\nIn the future we might be able to request buffers with a matching stride\nfrom v4l2 drivers in many cases, making direct import the norm instead\nof a hit-or-miss. An optional kernel API for that exists, but doesn't\nseem to be implemented by any driver tested so far.\n\nSigned-off-by: Robert Mader <robert.mader@collabora.com>\n\n---\n\nThis patch should be applied on top of\nhttps://patchwork.libcamera.org/cover/25706/\n---\n include/libcamera/internal/egl.h | 4 +--\n src/libcamera/egl.cpp | 37 +++++++++++++++++-----\n src/libcamera/software_isp/debayer_egl.cpp | 21 ++++++------\n src/libcamera/software_isp/debayer_egl.h | 2 +-\n 4 files changed, 44 insertions(+), 20 deletions(-)", "diff": "diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h\nindex f007f448a..b61769542 100644\n--- a/include/libcamera/internal/egl.h\n+++ b/include/libcamera/internal/egl.h\n@@ -98,7 +98,7 @@ public:\n \n \tint initEGLContext(GBM *gbmContext);\n \n-\tint createInputDMABufTexture2D(eGLImage &eglImage, int fd);\n+\tint createInputDMABufTexture2D(eGLImage &eglImage, int fd, GLint format, uint32_t width, uint32_t height);\n \tint createOutputDMABufTexture2D(eGLImage &eglImage, int fd);\n \tvoid destroyDMABufTexture(eGLImage &eglImage);\n \tvoid createTexture2D(eGLImage &eglImage, GLint format, uint32_t width, uint32_t height, void *data);\n@@ -131,7 +131,7 @@ private:\n \t\t\t unsigned int shaderDataLen,\n \t\t\t Span<const std::string> shaderEnv);\n \n-\tint createDMABufTexture2D(eGLImage &eglImage, int fd, bool output);\n+\tint createDMABufTexture2D(eGLImage &eglImage, int fd, uint32_t drm_format, uint32_t width, uint32_t height, bool output);\n \n \tPFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;\n \tPFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;\ndiff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp\nindex 0ffd008c7..2853be7c0 100644\n--- a/src/libcamera/egl.cpp\n+++ b/src/libcamera/egl.cpp\n@@ -19,6 +19,7 @@\n \n #include <libcamera/base/thread.h>\n \n+#include <GLES3/gl32.h>\n #include <libdrm/drm_fourcc.h>\n \n namespace libcamera {\n@@ -102,6 +103,9 @@ void eGL::syncOutput()\n * \\brief Create a DMA-BUF backed 2D texture\n * \\param[in,out] eglImage EGL image to associate with the DMA-BUF\n * \\param[in] fd DMA-BUF file descriptor\n+ * \\param[in] drm_format the DRM fourcc\n+ * \\param[in] width the buffer width\n+ * \\param[in] height the buffer height\n * \\param[in] output If true, create framebuffer for render target\n *\n * Internal implementation for creating DMA-BUF textures. Creates an EGL\n@@ -110,7 +114,7 @@ void eGL::syncOutput()\n *\n * \\return 0 on success, or -ENODEV on failure\n */\n-int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output)\n+int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, uint32_t drm_format, uint32_t width, uint32_t height, bool output)\n {\n \tint ret = 0;\n \n@@ -118,9 +122,9 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output)\n \n \t// clang-format off\n \tEGLint image_attrs[] = {\n-\t\tEGL_WIDTH, (EGLint)eglImage.width_,\n-\t\tEGL_HEIGHT, (EGLint)eglImage.height_,\n-\t\tEGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_ARGB8888,\n+\t\tEGL_WIDTH, (EGLint)width,\n+\t\tEGL_HEIGHT, (EGLint)height,\n+\t\tEGL_LINUX_DRM_FOURCC_EXT, (EGLint)drm_format,\n \t\tEGL_DMA_BUF_PLANE0_FD_EXT, fd,\n \t\tEGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,\n \t\tEGL_DMA_BUF_PLANE0_PITCH_EXT, (EGLint)eglImage.stride_,\n@@ -135,7 +139,7 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output)\n \t\t\t\t\t NULL, image_attrs);\n \n \tif (eglImage.image_ == EGL_NO_IMAGE_KHR) {\n-\t\tLOG(eGL, Error) << \"eglCreateImageKHR fail\";\n+\t\tLOG(eGL, Debug) << \"eglCreateImageKHR fail\";\n \t\tret = -ENODEV;\n \t\tgoto done;\n \t}\n@@ -176,6 +180,9 @@ done:\n * \\brief Create an input DMA-BUF backed texture\n * \\param[in,out] eglImage EGL image to associate with the DMA-BUF\n * \\param[in] fd DMA-BUF file descriptor\n+ * \\param[in] format the GL format\n+ * \\param[in] width the buffer width\n+ * \\param[in] height the buffer height\n *\n * Creates an EGL image from a DMA-BUF file descriptor and binds it to\n * a 2D texture for use as an input texture in shaders. The texture is\n@@ -183,11 +190,25 @@ done:\n *\n * \\return 0 on success, or -ENODEV on failure\n */\n-int eGL::createInputDMABufTexture2D(eGLImage &eglImage, int fd)\n+int eGL::createInputDMABufTexture2D(eGLImage &eglImage, int fd, GLint format, uint32_t width, uint32_t height)\n {\n+\tEGLint drm_format;\n+\n \tASSERT(tid_ == Thread::currentId());\n \n-\treturn createDMABufTexture2D(eglImage, fd, false);\n+\tswitch (format) {\n+\tcase GL_LUMINANCE:\n+\t\tdrm_format = DRM_FORMAT_R8;\n+\t\tbreak;\n+\tcase GL_RG:\n+\t\tdrm_format = DRM_FORMAT_RG88;\n+\t\tbreak;\n+\tdefault:\n+\t\tLOG(eGL, Error) << \"unhandled GL format\";\n+\t\treturn -ENODEV;\n+\t}\n+\n+\treturn createDMABufTexture2D(eglImage, fd, drm_format, width, height, false);\n }\n \n /**\n@@ -206,7 +227,7 @@ int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd)\n {\n \tASSERT(tid_ == Thread::currentId());\n \n-\treturn createDMABufTexture2D(eglImage, fd, true);\n+\treturn createDMABufTexture2D(eglImage, fd, DRM_FORMAT_ARGB8888, eglImage.width_, eglImage.height_, true);\n }\n \n /**\ndiff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp\nindex 9693d7252..e6387c851 100644\n--- a/src/libcamera/software_isp/debayer_egl.cpp\n+++ b/src/libcamera/software_isp/debayer_egl.cpp\n@@ -509,13 +509,22 @@ void DebayerEGL::setShaderVariableValues(DebayerParams ¶ms)\n \treturn;\n }\n \n-int DebayerEGL::debayerGPU(MappedFrameBuffer &in, int out_fd, DebayerParams ¶ms)\n+int DebayerEGL::debayerGPU(FrameBuffer *input, int out_fd, DebayerParams ¶ms)\n {\n \t/* eGL context switch */\n \tegl_.makeCurrent();\n \n \t/* Create a standard texture input */\n-\tegl_.createTexture2D(*eglImageBayerIn_, glFormat_, inputConfig_.stride / bytesPerPixel_, height_, in.planes()[0].data());\n+\tif (egl_.createInputDMABufTexture2D(*eglImageBayerIn_, input->planes()[0].fd.get(), glFormat_, inputConfig_.stride / bytesPerPixel_, height_) != 0) {\n+\t\tMappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read);\n+\t\tif (!in.isValid()) {\n+\t\t\tLOG(Debayer, Error) << \"mmap-ing buffer(s) failed\";\n+\t\t\treturn -ENODEV;\n+\t\t}\n+\n+\t\tLOG(Debayer, Debug) << \"Importing input buffer with DMABuf import failed, falling back to upload\";\n+\t\tegl_.createTexture2D(*eglImageBayerIn_, glFormat_, inputConfig_.stride / bytesPerPixel_, height_, in.planes()[0].data());\n+\t}\n \n \t/* Generate the output render framebuffer as render to texture */\n \tegl_.createOutputDMABufTexture2D(*eglImageBayerOut_, out_fd);\n@@ -552,13 +561,7 @@ void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output\n \tmetadata.sequence = input->metadata().sequence;\n \tmetadata.timestamp = input->metadata().timestamp;\n \n-\tMappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read);\n-\tif (!in.isValid()) {\n-\t\tLOG(Debayer, Error) << \"mmap-ing buffer(s) failed\";\n-\t\tgoto error;\n-\t}\n-\n-\tif (debayerGPU(in, output->planes()[0].fd.get(), params)) {\n+\tif (debayerGPU(input, output->planes()[0].fd.get(), params)) {\n \t\tLOG(Debayer, Error) << \"debayerGPU failed\";\n \t\tgoto error;\n \t}\ndiff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h\nindex a5033bc63..4b2cf448f 100644\n--- a/src/libcamera/software_isp/debayer_egl.h\n+++ b/src/libcamera/software_isp/debayer_egl.h\n@@ -74,7 +74,7 @@ private:\n \tint getShaderVariableLocations();\n \tvoid setShaderVariableValues(DebayerParams ¶ms);\n \tvoid configureTexture(GLuint &texture);\n-\tint debayerGPU(MappedFrameBuffer &in, int out_fd, DebayerParams ¶ms);\n+\tint debayerGPU(FrameBuffer *input, int out_fd, DebayerParams ¶ms);\n \n \t/* Shader program identifiers */\n \tGLuint vertexShaderId_ = 0;\n", "prefixes": [] }