From patchwork Wed May 27 08:15:30 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Mader X-Patchwork-Id: 26804 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 E66FBC328C for ; Wed, 27 May 2026 08:16:11 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8DDDF63026; Wed, 27 May 2026 10:16:11 +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="fkx0rjeV"; 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 929C462FEA for ; Wed, 27 May 2026 10:16:08 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; t=1779869764; cv=none; d=zohomail.com; s=zohoarc; b=AJByEXEMJ4A8BY6B5C39O7VtgOJw8lpiihA3gDvoqIvAeVZjLyrgp9xDksGRlAH4OXtEOUWXyB6tAEnUeEZiGeu0e0Ce+krrZBTQqgyNSjSSqAiOMQcMjGAHZidCZu+swfJQs27ZY8HclU/HSEePcW/uBwPaafH0iyoWY1Li67M= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779869764; 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=g1xRZFNPtIbnWKNO7/gV2bhcBzXwE07VvEMR0YwQiOY=; b=cqdEgOgD981R+/qStEPF0IVKii6FdJISKZO4pyX2Ctw5hy3BbvB2u8WCfRxwpRgAU/EVP+AOQ8BwjvKYM2tRd1vDuVXA43sHCtVZsKD0aDTeiSZ86fbcMbHCpe5FZt9aQ0P2sUeWnoAUajL8/laqXkJkkjWub+MIAb8hm4RflO8= 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=1779869764; 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=g1xRZFNPtIbnWKNO7/gV2bhcBzXwE07VvEMR0YwQiOY=; b=fkx0rjeVLnv4kd9E12SU5WOcOq51/iXSdpApKN4vJ99maknR2YNkL9qIydbGqhcE YZ1mrs6KSi50VjYlcVAzz1A0TdGu9oC6pMMmZ03SeM07GDMNc5YH4FGyIz0OA4nTaTp rv2z+Zs2pqbEtEVwE/lR7E1Lm91AgBvsAujTLtjE= Received: by mx.zohomail.com with SMTPS id 1779869761853723.2668974939996; Wed, 27 May 2026 01:16:01 -0700 (PDT) From: Robert Mader To: libcamera-devel@lists.libcamera.org Cc: Robert Mader , Bryan O'Donoghue Subject: [PATCH v5 1/5] egl: Add GL format parameter to eGLImage constructor Date: Wed, 27 May 2026 10:15:30 +0200 Message-ID: <20260527081534.20245-2-robert.mader@collabora.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260527081534.20245-1-robert.mader@collabora.com> References: <20260527081534.20245-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 Reviewed-by: Bryan O'Donoghue --- 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 Wed May 27 08:15:31 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Mader X-Patchwork-Id: 26807 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 E01D8C328C for ; Wed, 27 May 2026 08:16:18 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 570AF6302D; Wed, 27 May 2026 10:16:18 +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="jXeWtG6t"; 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 3C00C63020 for ; Wed, 27 May 2026 10:16:13 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; t=1779869764; cv=none; d=zohomail.com; s=zohoarc; b=HYXsPn5kJAEcQi8ae+PARReoGhFSqsg9m0kx1ZQ8Ha4DjkkXeOPNASyFE0GcWtQzbITgvqvV+dWRzs7OIWtL1J34nTFXm+Ci51FyqaVyAEWS9cMDxeAVSn2r2ajMYpy/YYXGeOdqbMDvg4B71rFZVHVZpW2EZTDEuhyLgXHTIlQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779869764; 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=R+2EyhiJ6pjX/K8134QcDfk0sNoxJKHVttczy7LTcFqcz5AQuWSgHTMeV9Cz90OTYysDrJuwf9AytGJhJI2BsnBwQ8uAzZUpnofO57txNqx5IatCfgoAyBkY91+OnQ7Sv26bumvjKuiapQhgChH4damr//OM216IbMHgPa+LALc= 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=1779869764; 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=jXeWtG6tSQy/aZLespliWmG3TacY3yeyOMv4Hgm24uvt8kFY/fe9h4OFTQr6Gu7R 0eJArRdpggAGtIq0bethVYz16fRj0ApIcxg3k+iqDu/Swu0tEy+WSZbCDGQFtX1GJFB WixwBOytcGcDGio4n3fOiCJpqnThFyWAKeK9aoyk= Received: by mx.zohomail.com with SMTPS id 1779869763224499.1927884765007; Wed, 27 May 2026 01:16:03 -0700 (PDT) From: Robert Mader To: libcamera-devel@lists.libcamera.org Cc: Robert Mader Subject: [PATCH v5 2/5] egl: Remove some parameters from createTexture2D() Date: Wed, 27 May 2026 10:15:31 +0200 Message-ID: <20260527081534.20245-3-robert.mader@collabora.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260527081534.20245-1-robert.mader@collabora.com> References: <20260527081534.20245-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 Wed May 27 08:15:32 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Mader X-Patchwork-Id: 26808 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 56556C32A9 for ; Wed, 27 May 2026 08:16:20 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 41F2563021; Wed, 27 May 2026 10:16:19 +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="DBKzBBdq"; 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 A99D363021 for ; Wed, 27 May 2026 10:16:13 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; t=1779869766; cv=none; d=zohomail.com; s=zohoarc; b=RQI90qS993DBzetFE8czL8VMlOTxBv+tNEy0Ptn8k09UYw+9Rsb9qBQ4V/a1wjgqu58qWI6sNdqlK/M+B2q95GITv1rszmZ+AUs3cF+hphcsY4oVJdU0D8vzKvAseRjj/Uez6NszIXlDfp+2jVaUSBnck00QbdgcYB2Nr2w0tJs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779869766; 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=XPeAw77/VqBYWO1QKVLeFzkm8QTD+ZIhsTwTCcqUn64=; b=DyVp9aIfPf9cTjLs/b9JJTpeLc4xJS0yhzv8+Gy4yFQSJs7Z6vO2igh+zPJhpzXxN0IjnqzU1yT9BHB1zhxRs5WWkO0ilWLnGkDiIDb2Jku3ZsLtUxOW5IbWb2z/wA/1LchT+mNvcPb1tR7n5EoZ8PvWcTQXeHhvTKwJ7KYZZqQ= 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=1779869766; 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=XPeAw77/VqBYWO1QKVLeFzkm8QTD+ZIhsTwTCcqUn64=; b=DBKzBBdqIYnwDGoFzHJt4J3xhtCJb+ZUWa7CJsg1y7DBClWSaSU/nD6TRp+//Guf 2dsOXZbedTyF7OepMiMTyjm03vczUv9tARk0Dw3xKYf4uNL9AYNcENdVCbIdDdH/Bk1 FFnKRLA2wTfu8c3+sp2IZElMRQirNbNrgyDPzzI0= Received: by mx.zohomail.com with SMTPS id 1779869764635638.4647018928291; Wed, 27 May 2026 01:16:04 -0700 (PDT) From: Robert Mader To: libcamera-devel@lists.libcamera.org Cc: Robert Mader , Bryan O'Donoghue Subject: [PATCH v5 3/5] egl: eGLImage: Add flag to remember dmabuf import fails Date: Wed, 27 May 2026 10:15:32 +0200 Message-ID: <20260527081534.20245-4-robert.mader@collabora.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260527081534.20245-1-robert.mader@collabora.com> References: <20260527081534.20245-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 Reviewed-by: Bryan O'Donoghue --- 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 Wed May 27 08:15:33 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Mader X-Patchwork-Id: 26806 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 F1105C32A9 for ; Wed, 27 May 2026 08:16:16 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5361663020; Wed, 27 May 2026 10:16:16 +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="lYaUs2lS"; 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 D595A62FEA for ; Wed, 27 May 2026 10:16:12 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; t=1779869768; cv=none; d=zohomail.com; s=zohoarc; b=BdpieltnWQjPQBl3yQgpvlm9RjeN8a8JVNMD+pwBx/GwCfRdM/rDpC6ZJ+21moCdW5QPu+3i+v2Jwn19nuWGhniQEvKOOKFQaD6ZiCMFqOf15DgJRkOKTWF8x+deWx3vKdC7x9chwS5My8UIPM9u96RIksVB+nbaWwSUuN8YtpA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779869768; 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=HQFVe0WHEecuvCj3juzh2dxW1YQisx+9AOio+6PxKlQ=; b=lgrf0o6Hh3YwhJQsKOw/uZJ8wwhefEYGIaU+Q4yADiwD0GZT3B7/30HspAM10J/l5ULsDEjQIGSCRvPp1Z/HdbKtQ0/kJcIo4gcbhKBaqWcorbeBmbbJNT807BbHGb69GPQmwRDbg3lCscyi5z44slKAF5rph//dMtqhuPnOvv0= 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=1779869768; 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=HQFVe0WHEecuvCj3juzh2dxW1YQisx+9AOio+6PxKlQ=; b=lYaUs2lSzfFUBAXNZHqO4nGHKYxjoIZJ+HlqzQlg/xrgB5jsuSnfXbE6cd/cxYgP AHHPU/kXllmvtrr7p7ZYbFIesiZ3pP5ID+woria7Q4bORmy+ZWUUTpb/+OB9N6KFO0O xk1wvmWXYagnVCYwAqx52soSF53SBmXOzyqjJrwk= Received: by mx.zohomail.com with SMTPS id 1779869766003903.0619894579684; Wed, 27 May 2026 01:16:06 -0700 (PDT) From: Robert Mader To: libcamera-devel@lists.libcamera.org Cc: Robert Mader Subject: [PATCH v5 4/5] libcamera: swstats_cpu: Take MappedFrameBuffer in processFrame() Date: Wed, 27 May 2026 10:15:33 +0200 Message-ID: <20260527081534.20245-5-robert.mader@collabora.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260527081534.20245-1-robert.mader@collabora.com> References: <20260527081534.20245-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 Reviewed-by: Kieran Bingham --- include/libcamera/internal/software_isp/swstats_cpu.h | 2 +- src/libcamera/software_isp/debayer_egl.cpp | 2 +- src/libcamera/software_isp/swstats_cpu.cpp | 11 ++--------- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h index b5348c6fe..686e3d981 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..d08634640 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..fb7a5301d 100644 --- a/src/libcamera/software_isp/swstats_cpu.cpp +++ b/src/libcamera/software_isp/swstats_cpu.cpp @@ -543,7 +543,7 @@ 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) { finishFrame(frame, bufferId); @@ -552,14 +552,7 @@ void SwStatsCpu::processFrame(uint32_t frame, uint32_t bufferId, FrameBuffer *in 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 Wed May 27 08:15:34 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Mader X-Patchwork-Id: 26805 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 7C917C328C for ; Wed, 27 May 2026 08:16:15 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 41F3E63030; Wed, 27 May 2026 10:16:15 +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="Xx5ZhvTO"; 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 A67CA62FD3 for ; Wed, 27 May 2026 10:16:12 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; t=1779869768; cv=none; d=zohomail.com; s=zohoarc; b=EJq/gfujxM2c/omsSpXzzvxcO9AZuVhlNV9yYG8a4JKucO72eALlCkhZ+W/PXj+l2PRETzPQfNN+wepxVIt7ZT+7spcbp4l3p+8tmkpfMRWfXsfZ9WrlsAZN/nMjeJRhVzM/5aConX2AROXIaNoeBYHmaLjYntLS4T7C7Si9RPk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779869768; 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=GLFy6yooih8jdmRuaoK+D5lh6st2WpFO/Mjagn3sRIk=; b=dC+8EPrMVGjwUtwv1Fl47u2IGWmEyFJjpFMX0PADLqTRGMZn9QiZfpdkghwvOLPVoEqJUtglMiW5G8nhnGLb+fFjIeYc9yM73oQQZ9RysJKTwW0qQ4G6vyfCWFIJ2W2zLE/6rzF/FLim/9xD/Z2GVvxI7zwGkA6vC2hbHbRhaPI= 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=1779869768; 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=GLFy6yooih8jdmRuaoK+D5lh6st2WpFO/Mjagn3sRIk=; b=Xx5ZhvTOg6f+KrNvkjTCYregm77qUA3ObXbWR23cL1pnhdHDg+0bSj7jKhlRtYXd mVNMU7tk1khpOI2GkwzoBJ65ZPAKuG+44KgKdDT4qL+L1swRiMa3n/OtA8cXyCKSNkf 1L8sb3SXYPqqE9Oz6/41F/uy4RRx1QLs2rZVQwDo= Received: by mx.zohomail.com with SMTPS id 1779869767189707.2228837095331; Wed, 27 May 2026 01:16:07 -0700 (PDT) From: Robert Mader To: libcamera-devel@lists.libcamera.org Cc: Robert Mader Subject: [PATCH v5 5/5] debayer_egl: Implement dmabuf import for input buffers Date: Wed, 27 May 2026 10:15:34 +0200 Message-ID: <20260527081534.20245-6-robert.mader@collabora.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260527081534.20245-1-robert.mader@collabora.com> References: <20260527081534.20245-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 | 58 ++++++++++++++++------ src/libcamera/software_isp/debayer_egl.h | 2 +- 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index d08634640..e83a68a97 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -10,6 +10,7 @@ #include "debayer_egl.h" #include +#include #include #include #include @@ -500,16 +501,34 @@ 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) { + bool dmabuf_import_succeeded = false; + /* 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) + dmabuf_import_succeeded = true; + else + 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 (!dmabuf_import_succeeded) { + inDmaSyncer->emplace(input->planes()[0].fd, DmaSyncer::SyncType::Read); + inMapped->emplace(input, MappedFrameBuffer::MapFlag::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 +550,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 +567,22 @@ 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) { + stats_->finishFrame(frame, 0); + } else { + if (!inMapped) { + /* + * The buffer was directly imported into EGL and thus + * not mapped for texture upload. Do it now for the + * CPU-based stats calculation. + */ + assert(!inDmaSyncer); + inDmaSyncer.emplace(input->planes()[0].fd, DmaSyncer::SyncType::Read); + inMapped.emplace(input, MappedFrameBuffer::MapFlag::Read); + } + stats_->processFrame(frame, 0, inMapped.value()); + } + 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;