From patchwork Thu May 21 15:59:02 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Mader X-Patchwork-Id: 26791 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 21B36BDCBD for ; Thu, 21 May 2026 15:59:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 43A7763022; Thu, 21 May 2026 17:59:28 +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="K10cwTNS"; 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 4971362FD3 for ; Thu, 21 May 2026 17:59:26 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; t=1779379162; cv=none; d=zohomail.com; s=zohoarc; b=QbTGWOUPo9T7CHz4A+J8l1+IeCXO9b8NBagAXvC1tOj7fkv2IKyErQ2Bb7QVhPz1blG8FlLniNcroWHkzWe8n84ggiT4PbJDd8DjkFmBRdTqpXtcu8BA3GrgVzN+OKZuca1/ZvrnuDcChJQQSRolXx+0x0Vge2ZBJvwWn1wFm+g= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779379162; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=9g6+4BlW5rkswl+pj4jxd4isr5d43gPyJDvHpbHA66I=; b=hYz+wH/DWInxK5vaxhJWSVbdlnLsmXmzL2PBm32bglrAcrz58lN45dVhtpk4M2tXHHv8gUpDHPWXqllGDc5iZfV/uj0c05qLF3YDFNhH2ZDBXtY/QuizaivllQmmd3sA5nl6vU+iYR35rPEV9uvtjafCfEXS7YNTn+QG1CvVUfY= 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=1779379162; s=zohomail; d=collabora.com; i=robert.mader@collabora.com; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=9g6+4BlW5rkswl+pj4jxd4isr5d43gPyJDvHpbHA66I=; b=K10cwTNSXnEqi8JwjxIVumXqBQaCxSjrEZ1bDpnfJH57YYzfag9NMsEyWpUWX+ld wt5t0Rz+u3gTEmdx6QkdhSF0audQBX72cbB3iKLe1ZNbgjJXkkZTIgRvjKZ6Nmq/wxG QrT2Ey7+s0+SMeNTxPd9jkAild9R8+8tZ6nMiRTM= Received: by mx.zohomail.com with SMTPS id 1779379161172108.60883392569076; Thu, 21 May 2026 08:59:21 -0700 (PDT) From: Robert Mader To: libcamera-devel@lists.libcamera.org Cc: Robert Mader Subject: [PATCH v4 1/5] egl: Add GL format parameter to eGLImage constructor Date: Thu, 21 May 2026 17:59:02 +0200 Message-ID: <20260521155906.120373-2-robert.mader@collabora.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521155906.120373-1-robert.mader@collabora.com> References: <20260521155906.120373-1-robert.mader@collabora.com> 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" In preparation for the following commits. This requires a minor reordering in DebayerEGL::start() as the value for the input texture is only known after initBayerShaders(). Signed-off-by: Robert Mader --- include/libcamera/internal/egl.h | 6 ++++-- src/libcamera/egl.cpp | 22 +++++++++++++++++++++- src/libcamera/software_isp/debayer_egl.cpp | 10 +++++----- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h index 0ec8ea6ec..825240dbb 100644 --- a/include/libcamera/internal/egl.h +++ b/include/libcamera/internal/egl.h @@ -51,14 +51,15 @@ class eGLImage public: /** * \brief Construct an eGLImage with explicit stride + * \param[in] format Image GL format * \param[in] width Image width in pixels * \param[in] height Image height in pixels * \param[in] stride Row stride in bytes * \param[in] texture_unit OpenGL texture unit * \param[in] texture_unit_uniform_id Shader uniform ID */ - eGLImage(uint32_t width, uint32_t height, uint32_t stride, GLenum texture_unit, uint32_t texture_unit_uniform_id) - : width_(width), height_(height), stride_(stride), + eGLImage(GLint format, uint32_t width, uint32_t height, uint32_t stride, GLenum texture_unit, uint32_t texture_unit_uniform_id) + : format_(format), width_(width), height_(height), stride_(stride), framesize_(stride * height), texture_unit_uniform_id_(texture_unit_uniform_id), texture_unit_(texture_unit) @@ -79,6 +80,7 @@ public: glDeleteTextures(1, &texture_); } + GLint format_; /**< Image GL format */ uint32_t width_; /**< Image width in pixels */ uint32_t height_; /**< Image height in pixels */ uint32_t stride_; /**< Row stride in bytes */ diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index 19ae92305..2aabfc2e0 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -20,6 +20,8 @@ #include +#include + namespace libcamera { LOG_DEFINE_CATEGORY(eGL) @@ -124,13 +126,31 @@ void eGL::flushOutput() */ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) { + EGLint drm_format; + ASSERT(tid_ == Thread::currentId()); + switch (eglImage.format_) { + case GL_RED: + case GL_LUMINANCE: + drm_format = DRM_FORMAT_R8; + break; + case GL_RG: + drm_format = DRM_FORMAT_RG88; + break; + case GL_RGBA: + drm_format = DRM_FORMAT_ARGB8888; + break; + default: + LOG(eGL, Error) << "unhandled GL format"; + return -ENODEV; + } + // clang-format off EGLint image_attrs[] = { EGL_WIDTH, (EGLint)eglImage.width_, EGL_HEIGHT, (EGLint)eglImage.height_, - EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_ARGB8888, + EGL_LINUX_DRM_FOURCC_EXT, drm_format, EGL_DMA_BUF_PLANE0_FD_EXT, fd, EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, EGL_DMA_BUF_PLANE0_PITCH_EXT, (EGLint)eglImage.stride_, diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 7b9e02d90..8c1f2074d 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -583,14 +583,14 @@ int DebayerEGL::start() LOG(Debayer, Debug) << "Available fragment shader texture units " << maxTextureImageUnits; + if (initBayerShaders(inputPixelFormat_, outputPixelFormat_)) + return -EINVAL; + /* Raw bayer input as texture */ - eglImageBayerIn_ = std::make_unique(width_, height_, inputConfig_.stride, GL_TEXTURE0, 0); + eglImageBayerIn_ = std::make_unique(glFormat_, width_, height_, inputConfig_.stride, GL_TEXTURE0, 0); /* Texture we will render to */ - eglImageBayerOut_ = std::make_unique(outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE1, 1); - - if (initBayerShaders(inputPixelFormat_, outputPixelFormat_)) - return -EINVAL; + eglImageBayerOut_ = std::make_unique(GL_RGBA, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE1, 1); return 0; } From patchwork Thu May 21 15:59:03 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Mader X-Patchwork-Id: 26793 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 58977BDCBD for ; Thu, 21 May 2026 15:59:34 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C31ED63025; Thu, 21 May 2026 17:59:32 +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="Z6VuYZTI"; 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 E557962FEC for ; Thu, 21 May 2026 17:59:27 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; t=1779379164; cv=none; d=zohomail.com; s=zohoarc; b=DexCRY3otuT53zXF6TO/JDFFcIeEzR5A+BRUHFgoVRQZxGv+vKiyO7E7ZSVtxm6kWnCMNbnu8P/qWkOATXRDbBzrlhUT1l1qKqqLBXSDML48wl/B1VWMTMenHuVaCKTDFzqNXzhDrOPiRoh4PO5womS1YeMAl5LDH2jJKbwvQrQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779379164; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=l7RjJAijFsQIL0xNq9BIdDwiEkWp3YMq2V3d/E0NjOg=; b=RYKtCeHNB9hbu9OT8Rj4FMDRy6VaABAYZ9HJ+juJfLBD/IAjPvvf22m+S6RtxCSNP/zRq9f3utr+sBELFCDSdsDOnc/L2X5kDEdByp2abW6wgOOlCgG2CHbMiEKMMIUDWav01GDjKY6O0PJ1gnxSrwftWsCbPEWRvg3DKS4wtJ4= 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=1779379164; s=zohomail; d=collabora.com; i=robert.mader@collabora.com; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=l7RjJAijFsQIL0xNq9BIdDwiEkWp3YMq2V3d/E0NjOg=; b=Z6VuYZTIJSjKWD119IbrfMzxKFiYcK9Ni8AQALnCk3aUusLbiSPC1H0+4mzjlN3I KQBzArxYZPdpYy0nlWFCm3PB8WLvphRaBrbE6K0RoWslNCQcVN0iXATTppf3jyYlnak Z2hKzGg/DiC92CrPolImypgXdd3XqJKnuUcEM+8o= Received: by mx.zohomail.com with SMTPS id 177937916250335.21624434893283; Thu, 21 May 2026 08:59:22 -0700 (PDT) From: Robert Mader To: libcamera-devel@lists.libcamera.org Cc: Robert Mader Subject: [PATCH v4 2/5] egl: Remove some parameters from createTexture2D() Date: Thu, 21 May 2026 17:59:03 +0200 Message-ID: <20260521155906.120373-3-robert.mader@collabora.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521155906.120373-1-robert.mader@collabora.com> References: <20260521155906.120373-1-robert.mader@collabora.com> 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" And use the values set in the constructor instead, bringing the function in line with createInputDMABufTexture2D() and createOutputDMABufTexture2D(). Adopt the value passed into the constructor accordingly, which previously was never used. Signed-off-by: Robert Mader --- include/libcamera/internal/egl.h | 2 +- src/libcamera/egl.cpp | 7 ++----- src/libcamera/software_isp/debayer_egl.cpp | 4 ++-- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h index 825240dbb..bcf09b475 100644 --- a/include/libcamera/internal/egl.h +++ b/include/libcamera/internal/egl.h @@ -105,7 +105,7 @@ public: int createInputDMABufTexture2D(eGLImage &eglImage, int fd); int createOutputDMABufTexture2D(eGLImage &eglImage, int fd); - void createTexture2D(eGLImage &eglImage, GLint format, uint32_t width, uint32_t height, void *data); + void createTexture2D(eGLImage &eglImage, void *data); void pushEnv(std::vector &shaderEnv, const char *str); void makeCurrent(); diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index 2aabfc2e0..267d22c8b 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -240,9 +240,6 @@ int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd) /** * \brief Create a 2D texture from a memory buffer * \param[in,out] eglImage EGL image to associate with the texture - * \param[in] format OpenGL internal format (e.g., GL_RGB, GL_RGBA) - * \param[in] width Texture width in pixels - * \param[in] height Texture height in pixels * \param[in] data Pointer to pixel data, or nullptr for uninitialised texture * * Creates a 2D texture from a CPU-accessible memory buffer. The texture @@ -250,7 +247,7 @@ int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd) * is useful for uploading static data like lookup tables or uniform color * matrices to the GPU. */ -void eGL::createTexture2D(eGLImage &eglImage, GLint format, uint32_t width, uint32_t height, void *data) +void eGL::createTexture2D(eGLImage &eglImage, void *data) { ASSERT(tid_ == Thread::currentId()); @@ -258,7 +255,7 @@ void eGL::createTexture2D(eGLImage &eglImage, GLint format, uint32_t width, uint glBindTexture(GL_TEXTURE_2D, eglImage.texture_); // Generate texture, bind, associate image to texture, configure, unbind - glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); + glTexImage2D(GL_TEXTURE_2D, 0, eglImage.format_, eglImage.width_, eglImage.height_, 0, eglImage.format_, GL_UNSIGNED_BYTE, data); // Nearest filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 8c1f2074d..696498a58 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -506,7 +506,7 @@ int DebayerEGL::debayerGPU(MappedFrameBuffer &in, int out_fd, const DebayerParam egl_.makeCurrent(); /* Create a standard texture input */ - egl_.createTexture2D(*eglImageBayerIn_, glFormat_, inputConfig_.stride / bytesPerPixel_, height_, in.planes()[0].data()); + egl_.createTexture2D(*eglImageBayerIn_, in.planes()[0].data()); /* Generate the output render framebuffer as render to texture */ egl_.createOutputDMABufTexture2D(*eglImageBayerOut_, out_fd); @@ -587,7 +587,7 @@ int DebayerEGL::start() return -EINVAL; /* Raw bayer input as texture */ - eglImageBayerIn_ = std::make_unique(glFormat_, width_, height_, inputConfig_.stride, GL_TEXTURE0, 0); + eglImageBayerIn_ = std::make_unique(glFormat_, inputConfig_.stride / bytesPerPixel_, height_, inputConfig_.stride, GL_TEXTURE0, 0); /* Texture we will render to */ eglImageBayerOut_ = std::make_unique(GL_RGBA, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE1, 1); From patchwork Thu May 21 15:59:04 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Mader X-Patchwork-Id: 26794 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 C3AD2C32F4 for ; Thu, 21 May 2026 15:59:35 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C174E63034; Thu, 21 May 2026 17:59:33 +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="Nalu40GD"; 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 B8CE56302B for ; Thu, 21 May 2026 17:59:28 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; t=1779379166; cv=none; d=zohomail.com; s=zohoarc; b=I5WGmPmgtefVh3aaXc3kZubfxQ99REuzQG6TDWl2s22hqLuphR16JP/Fi7NHjvcjSomDtoBKhuLa6PaZN/IyaVgYA1QOxPCsSn/A0bRVDTuEVVMe/bKmTTJRWSefvxEiBujui4+qvP4Br5IKm1cTt04JPsFGpc1iQfj+DIsGryw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779379166; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=TSUlafOf8ofK9Cb40XzZGWps5gzsOIEZPVA0qsbnC88=; b=MJrmJsy9niVaB3GXQZmyLad4JiXeDHugmQWSIjB9GWf1nHT2ZUJvs2KPDcOic4odwMiLojySUSV84OLgs6ePSfP+bg74XbWMvv4/pf0VvmRxI3e68XeDZevP9HFWLPYP0qaL4LeWRY+VZcaTGh9SZjHpvxUsaHr9cu6+x+xP6Rc= 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=1779379166; s=zohomail; d=collabora.com; i=robert.mader@collabora.com; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=TSUlafOf8ofK9Cb40XzZGWps5gzsOIEZPVA0qsbnC88=; b=Nalu40GDzfK1LdW1/mB2Bwfht+SJPEeee/DJmkw6EF4d0s7YJQJw9BKNFH6jNfPn pRYLyiURTU8Rsy6uR1z12b5E1eye4mRUDoUZa10zAoGzVQZ76cN3HNUhNTvSlwcP1oD TU9iedq8Q2qlCGAsFyc+5JB8YSMJf5od5IyL0vYQ= Received: by mx.zohomail.com with SMTPS id 1779379164141161.036932664887; Thu, 21 May 2026 08:59:24 -0700 (PDT) From: Robert Mader To: libcamera-devel@lists.libcamera.org Cc: Robert Mader Subject: [PATCH v4 3/5] egl: eGLImage: Add flag to remember dmabuf import fails Date: Thu, 21 May 2026 17:59:04 +0200 Message-ID: <20260521155906.120373-4-robert.mader@collabora.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521155906.120373-1-robert.mader@collabora.com> References: <20260521155906.120373-1-robert.mader@collabora.com> 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" In preparation of a following commit where we will start trying dmabuf import for input buffers. Also turn down error log in order to avoid flodding logs going forward. Signed-off-by: Robert Mader --- include/libcamera/internal/egl.h | 1 + src/libcamera/egl.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h index bcf09b475..57f90d93f 100644 --- a/include/libcamera/internal/egl.h +++ b/include/libcamera/internal/egl.h @@ -90,6 +90,7 @@ public: GLenum texture_unit_; /**< Texture unit associated with this image eg (GL_TEXTURE0) */ GLuint texture_; /**< OpenGL texture object ID */ GLuint fbo_; /**< OpenGL frame buffer object ID */ + bool dmabuf_import_failed_ = false; /**< Previous image import failed */ private: LIBCAMERA_DISABLE_COPY_AND_MOVE(eGLImage) diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index 267d22c8b..c185bb7ad 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -165,7 +165,8 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) NULL, image_attrs); if (image == EGL_NO_IMAGE_KHR) { - LOG(eGL, Error) << "eglCreateImageKHR fail"; + LOG(eGL, Debug) << "eglCreateImageKHR fail"; + eglImage.dmabuf_import_failed_ = true; return -ENODEV; } From patchwork Thu May 21 15:59:05 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Mader X-Patchwork-Id: 26796 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 D3E31C32F4 for ; Thu, 21 May 2026 15:59:38 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8446462FD3; Thu, 21 May 2026 17:59:38 +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="ZuAqKimJ"; 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 E7D2862FEC for ; Thu, 21 May 2026 17:59:31 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; t=1779379168; cv=none; d=zohomail.com; s=zohoarc; b=O8mxTUk8sKYUSSAPFUi8744otl+fsHGpI4txxX0E4tVkPiqA2av050p3GEugjZJZZ6sk72mdWfV1tuE3YDIF34XoponfAwazkz3sjfFY86RnqyIMo5sucZoqX6ihKwvySGeYcUZqNwnjLoW0RrD8YZcBWcspVd67HHhzKIpz0uc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779379168; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=fUuYJQIHRIATzbug2Vo9yV+BiNeQ9KLOui8BmEmgzxM=; b=KZICwWCD/h6n0Gme9wIzBsMcoHDzDh74k5r5PKh4Pn5QD1kHG6aXfSAqhgERUaaKoezU8DKjeilzeDN6PcYAlWy/Sve8l1eMF43Y5hLHSWbxpLhWjY2YlHjgxCC/6gWQgr9caT88IokEatMsuHcEncCEn3V7HJysFvtu6BlBj7c= 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=1779379168; s=zohomail; d=collabora.com; i=robert.mader@collabora.com; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=fUuYJQIHRIATzbug2Vo9yV+BiNeQ9KLOui8BmEmgzxM=; b=ZuAqKimJLiYMTFVL5l7Iu85iIjpbWjbCel8whGld++H+RzMYw9DEwEazDMSe67lb FxVW+pYZbnc3LpKx6Ws1U5SenaiXitPROYTkGh0hkjMkKFTP6SDRrH53tMGGad832DK J91E5fG3tlphyIHfDXyxqxJBqXRNks4vSZnTRJ7Q= Received: by mx.zohomail.com with SMTPS id 1779379165474836.5361585607891; Thu, 21 May 2026 08:59:25 -0700 (PDT) From: Robert Mader To: libcamera-devel@lists.libcamera.org Cc: Robert Mader Subject: [PATCH v4 4/5] libcamera: swstats_cpu: Take MappedFrameBuffer in processFrame() Date: Thu, 21 May 2026 17:59:05 +0200 Message-ID: <20260521155906.120373-5-robert.mader@collabora.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521155906.120373-1-robert.mader@collabora.com> References: <20260521155906.120373-1-robert.mader@collabora.com> 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" As the only current user - DebayerEGL::process() - already has the buffer mapped. Currently this shouldn't impact performance as the kernel should already avoid remapping the dmabuf - i.e. we implicitly benefit from the fact that the mentioned function holds its mapping during the runtime of processFrame(). In a following commit DebayerEGL::process() will change in a way that would make keeping the mapping counter-intuitive. Thus this change ensures we'll not accidentally start mapping the buffer twice per frame. Signed-off-by: Robert Mader --- .../libcamera/internal/software_isp/swstats_cpu.h | 2 +- src/libcamera/software_isp/debayer_egl.cpp | 2 +- src/libcamera/software_isp/swstats_cpu.cpp | 13 +++---------- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h index b5348c6fe..c9ed1d0a6 100644 --- a/include/libcamera/internal/software_isp/swstats_cpu.h +++ b/include/libcamera/internal/software_isp/swstats_cpu.h @@ -56,7 +56,7 @@ public: void setWindow(const Rectangle &window); void startFrame(uint32_t frame); void finishFrame(uint32_t frame, uint32_t bufferId); - void processFrame(uint32_t frame, uint32_t bufferId, FrameBuffer *input); + void processFrame(uint32_t frame, uint32_t bufferId, MappedFrameBuffer *input); void processLine0(uint32_t frame, unsigned int y, const uint8_t *src[], unsigned int statsBufferIndex = 0) { diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 696498a58..d15f3cd48 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -555,7 +555,7 @@ void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output metadata.planes()[0].bytesused = output->planes()[0].length; /* Calculate stats for the whole frame */ - stats_->processFrame(frame, 0, input); + stats_->processFrame(frame, 0, &in); dmaSyncers.clear(); egl_.syncOutput(); diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp index 0815ec9a3..b182a1a2b 100644 --- a/src/libcamera/software_isp/swstats_cpu.cpp +++ b/src/libcamera/software_isp/swstats_cpu.cpp @@ -543,23 +543,16 @@ void SwStatsCpu::processBayerFrame2(MappedFrameBuffer &in) * * This may only be called after a successful setWindow() call. */ -void SwStatsCpu::processFrame(uint32_t frame, uint32_t bufferId, FrameBuffer *input) +void SwStatsCpu::processFrame(uint32_t frame, uint32_t bufferId, MappedFrameBuffer *input) { - if (frame % kStatPerNumFrames) { + if (!input || frame % kStatPerNumFrames) { finishFrame(frame, bufferId); return; } bench_.startFrame(); startFrame(frame); - - MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read); - if (!in.isValid()) { - LOG(SwStatsCpu, Error) << "mmap-ing buffer(s) failed"; - return; - } - - (this->*processFrame_)(in); + (this->*processFrame_)(*input); finishFrame(frame, bufferId); bench_.finishFrame(); } From patchwork Thu May 21 15:59:06 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Mader X-Patchwork-Id: 26795 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 A6F65BDCBD for ; Thu, 21 May 2026 15:59:37 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 57EBF6302F; Thu, 21 May 2026 17:59:37 +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="i2n1OJJ1"; 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 0741D6301A for ; Thu, 21 May 2026 17:59:31 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; t=1779379168; cv=none; d=zohomail.com; s=zohoarc; b=FC+079oULQk0ZhXGvGlKHtzcNi3mWWYzLOEEs/qCUbVSfT6OC0U1FMCM4KOG0cDBO1rSwtHAWBJ4vDpHgUAcyYzKF1D6G5A9gDhi1NcxYz1SwXYG2l9TngiKUVbre6P74uw6cgF9lciW1KXlAyeiQSGye8CAyTTtbBFKD9jvo2w= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779379168; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=3ZVdjT7etSZl8Jh8qHUgc71mWn4BhMzSBY4rQpI1ORw=; b=Wo/11MOLvGvjmAgOvAWvnOSWDhcIDhBTEoWCM3NPwgv6a1H3JPR0IhF2GJJpNKs3OplWgMOYBCqp/cv43eCHo9hPVh63ArYwZ77Iw7IsKA8Qx/W3JVqesLd2johoRa3AbhAyXIBSnV1HlIpp/VJUDVETKqoRXCyNEvvtVuAzM90= 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=1779379168; s=zohomail; d=collabora.com; i=robert.mader@collabora.com; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=3ZVdjT7etSZl8Jh8qHUgc71mWn4BhMzSBY4rQpI1ORw=; b=i2n1OJJ1DwjGxnTIr/8sth3Cokr2m6bVM/eljng/gC78Pe2PYAdWoUjuKBuAYHCx 9VCDhXHhwrRVO3rRe/S8l2IFM7gkNgFlrbFnMODknEIP8okNNvv50S2pbO/BQAJN734 lxkpQBCABXagKhkzGb9gq8PJX3/4oTqCFZOtgKxg= Received: by mx.zohomail.com with SMTPS id 1779379166773721.2561804678149; Thu, 21 May 2026 08:59:26 -0700 (PDT) From: Robert Mader To: libcamera-devel@lists.libcamera.org Cc: Robert Mader Subject: [PATCH v4 5/5] debayer_egl: Implement dmabuf import for input buffers Date: Thu, 21 May 2026 17:59:06 +0200 Message-ID: <20260521155906.120373-6-robert.mader@collabora.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260521155906.120373-1-robert.mader@collabora.com> References: <20260521155906.120373-1-robert.mader@collabora.com> 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" In many cases we can import the GPU-ISP input buffers, dmabufs from v4l2, directly into EGL instead of mapping and uploading - i.e. copying - them. Doing so can have positive effects in multiple areas, including reducing memory bandwidth and CPU usage, as well as avoiding expensive dmabuf syncs and syscalls. The main reason direct imports may not work are the more demanding stride alignment requirements many GPUs have - often 128 or 256 bytes - compared to ISPs - apparently often closer to 32 bytes. Thus we first try to import buffers directly and - if that fails - fall back to the previous upload path. Failing imports should come at low cost as drivers know the limitations and can bail out early, without causing additional IO or context switches. In the future we might be able to request buffers with a matching stride from v4l2 drivers in many cases, making direct import the norm instead of a hit-or-miss. An optional kernel API for that exists, but doesn't seem to be implemented by any driver tested so far. Note that passing around MappedFrameBuffer and DmaSyncer variables ensures we don't do unnecessary mappings and dmabuf syncs. Below are some benchmark results. All where done using postmarketOS edge with updates from 21th May 2026 (Mesa 26.1.1). The mentioned pipelines where run five times each, with the mean value included here, which should be quite representive as the variance was rather small. All devices where using the powersave governor. - FairPhone 5 -- Back camera cam -c /base/soc@0/cci@ac4a000/i2c-bus@1/camera@29 -s width=1920,height=1080 --capture=60 Before: 14027 us/frame After: 12122 us/frame - OnePlus 6 -- Back camera (imx519) cam -c /base/soc@0/cci@ac4a000/i2c-bus@0/camera@10 -s width=1920,height=1080 --capture=60 Before: 30091 us/frame After: 19878 us/frame - Librem 5 -- Back camera cam -c /base/soc@0/bus@30800000/i2c@30a50000/camera@2d -s width=1280,height=720 --capture=60 Before: 69092 us/frame After: 41250 us/frame - PinePhone -- Front Camera cam -c /base/i2c-csi/front-camera@3c -s width=1280,height=720 --capture=60 Before: 173769 us/frame After: 143274 us/frame -- Back camera cam -c /base/i2c-csi/rear-camera@4c -s width=1280,height=720 --capture=60 Before: 174833 us/frame After: 144476 us/frame There is one case where performance regresses: - Pixel 3a -- Back camera cam -c /base/soc@0/cci@ac4a000/i2c-bus@1/camera@1a -s width=1920,height=1080 --capture=60 Before: 14257 us/frame After: 15161 us/frame To my knowledge this is likely caused by bad sampling performance from linear buffers. IMO this is a driver issue - if a copy to tiled format makes sampling faster, drivers should do so implicitly (like e.g. v3d already does). Signed-off-by: Robert Mader --- src/libcamera/software_isp/debayer_egl.cpp | 45 ++++++++++++++-------- src/libcamera/software_isp/debayer_egl.h | 2 +- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index d15f3cd48..c1075ac39 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -500,16 +500,30 @@ void DebayerEGL::setShaderVariableValues(const DebayerParams ¶ms) return; } -int DebayerEGL::debayerGPU(MappedFrameBuffer &in, int out_fd, const DebayerParams ¶ms) +int DebayerEGL::debayerGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms, std::optional *inMapped, std::optional *inDmaSyncer) { /* eGL context switch */ egl_.makeCurrent(); - /* Create a standard texture input */ - egl_.createTexture2D(*eglImageBayerIn_, in.planes()[0].data()); + /* Try to create texture for input buffer via dmabuf import */ + if (!eglImageBayerIn_->dmabuf_import_failed_) { + if (egl_.createInputDMABufTexture2D(*eglImageBayerIn_, input->planes()[0].fd.get()) != 0) + LOG(Debayer, Info) << "Importing input buffer with DMABuf import failed, falling back to upload"; + } + + /* Otherwise create texture for input buffer via upload from CPU */ + if (eglImageBayerIn_->dmabuf_import_failed_) { + inMapped->emplace(input, MappedFrameBuffer::MapFlag::Read); + inDmaSyncer->emplace(input->planes()[0].fd, DmaSyncer::SyncType::Read); + if (!inMapped->value().isValid()) { + LOG(Debayer, Error) << "mmap-ing buffer(s) failed"; + return -ENODEV; + } + egl_.createTexture2D(*eglImageBayerIn_, inMapped->value().planes()[0].data()); + } /* Generate the output render framebuffer as render to texture */ - egl_.createOutputDMABufTexture2D(*eglImageBayerOut_, out_fd); + egl_.createOutputDMABufTexture2D(*eglImageBayerOut_, output->planes()[0].fd.get()); setShaderVariableValues(params); glViewport(0, 0, width_, height_); @@ -531,23 +545,16 @@ void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output { bench_.startFrame(); - std::vector dmaSyncers; - - dmaSyncBegin(dmaSyncers, input, nullptr); - /* Copy metadata from the input buffer */ FrameMetadata &metadata = output->_d()->metadata(); metadata.status = input->metadata().status; metadata.sequence = input->metadata().sequence; metadata.timestamp = input->metadata().timestamp; - MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read); - if (!in.isValid()) { - LOG(Debayer, Error) << "mmap-ing buffer(s) failed"; - goto error; - } + std::optional inMapped; + std::optional inDmaSyncer; - if (debayerGPU(in, output->planes()[0].fd.get(), params)) { + if (debayerGPU(input, output, params, &inMapped, &inDmaSyncer)) { LOG(Debayer, Error) << "debayerGPU failed"; goto error; } @@ -555,8 +562,14 @@ void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output metadata.planes()[0].bytesused = output->planes()[0].length; /* Calculate stats for the whole frame */ - stats_->processFrame(frame, 0, &in); - dmaSyncers.clear(); + if ((frame % SwStatsCpu::kStatPerNumFrames) == 0) { + if (!inMapped) + inMapped.emplace(input, MappedFrameBuffer::MapFlag::Read); + if (!inDmaSyncer) + inDmaSyncer.emplace(input->planes()[0].fd, DmaSyncer::SyncType::Read); + } + stats_->processFrame(frame, 0, inMapped ? &inMapped.value() : nullptr); + inDmaSyncer.reset(); egl_.syncOutput(); bench_.finishFrame(); diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h index 141fb288f..875e7cfc5 100644 --- a/src/libcamera/software_isp/debayer_egl.h +++ b/src/libcamera/software_isp/debayer_egl.h @@ -65,7 +65,7 @@ private: int initBayerShaders(PixelFormat inputFormat, PixelFormat outputFormat); int getShaderVariableLocations(); void setShaderVariableValues(const DebayerParams ¶ms); - int debayerGPU(MappedFrameBuffer &in, int out_fd, const DebayerParams ¶ms); + int debayerGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms, std::optional *mappedInputBuffer, std::optional *inputBufferDmaSyncer); /* Shader program identifiers */ GLuint vertexShaderId_ = 0;