From patchwork Mon May 4 18:26:50 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26616 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 7FF1FBE173 for ; Mon, 4 May 2026 18:27:18 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3454063021; Mon, 4 May 2026 20:27:18 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="Y1CrBbI9"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6160F62FE8 for ; Mon, 4 May 2026 20:27:17 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1777919236; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ZYUcLBxDJJZFaM+eJIF2fazWu3f+U030/Fs+/huHGlc=; b=Y1CrBbI9KnML0DRDA2SKRe3eZZ1aNnKmDVfcm85bIs5mwowpUSkwb9gBxDEy/VQJWV5V0L 9703ROC7aKOUUl7DOVZSZJ3Oaqb9HE7BPR/Q/Nb+djSfuKBZFdZiK25uQpEFoqqpHS0sKg aDZ0SkmbiyPyGJ+at9DDnagphzkQo+g= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-417-rxuJkIkpPcypTw8fINNPKw-1; Mon, 04 May 2026 14:27:13 -0400 X-MC-Unique: rxuJkIkpPcypTw8fINNPKw-1 X-Mimecast-MFC-AGG-ID: rxuJkIkpPcypTw8fINNPKw_1777919231 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id DC7AB180049F; Mon, 4 May 2026 18:27:10 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.69]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 4ACE91800480; Mon, 4 May 2026 18:27:07 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Xander Pronk , Bryan O'Donoghue , Hans de Goede , Laurent Pinchart , Bryan O'Donoghue , Rick ten Wolde , Milan Zamazal Subject: [RFC PATCH v4 1/7] libcamera: software_isp: egl: Add filter parameter to createTexture2D() Date: Mon, 4 May 2026 20:26:50 +0200 Message-ID: <20260504182658.590233-2-mzamazal@redhat.com> In-Reply-To: <20260504182658.590233-1-mzamazal@redhat.com> References: <20260504182658.590233-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: By_vW-jbAio2lG3Yvv306ZkJPbXA8BuWEVwB6n4A9Wg_1777919231 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true 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" From: Xander Pronk Add `filter' parameter to createTexture2D() to allow overriding the currently hardcoded GL_NEAREST value. This is needed for grid-based lens shading interpolation, which is implemented in followup patches. Reviewed-by: Bryan O'Donoghue Co-developed-by: Rick ten Wolde Signed-off-by: Rick ten Wolde Signed-off-by: Xander Pronk Signed-off-by: Milan Zamazal --- include/libcamera/internal/egl.h | 3 ++- src/libcamera/egl.cpp | 10 ++++++---- src/libcamera/software_isp/debayer_egl.cpp | 4 +++- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h index 0ad2320b1..6402dd5c7 100644 --- a/include/libcamera/internal/egl.h +++ b/include/libcamera/internal/egl.h @@ -103,7 +103,8 @@ 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, GLint format, uint32_t width, uint32_t height, + const void *data, GLint filter); void pushEnv(std::vector &shaderEnv, const char *str); void makeCurrent(); diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index f65929470..93778acb8 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -212,13 +212,15 @@ int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd) * \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 + * \param[in] filter GL texture filter setting * * Creates a 2D texture from a CPU-accessible memory buffer. The texture - * is configured with nearest filtering and clamp-to-edge wrapping. This + * is configured the specified filtering and clamp-to-edge wrapping. This * 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, GLint format, uint32_t width, uint32_t height, + const void *data, GLint filter) { ASSERT(tid_ == Thread::currentId()); @@ -229,8 +231,8 @@ void eGL::createTexture2D(eGLImage &eglImage, GLint format, uint32_t width, uint glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); // Nearest filtering - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); // Wrap to edge to avoid edge artifacts glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 8f0c229fd..f10f372c6 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -501,7 +501,9 @@ 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_, glFormat_, + inputConfig_.stride / bytesPerPixel_, height_, + in.planes()[0].data(), GL_NEAREST); /* Generate the output render framebuffer as render to texture */ egl_.createOutputDMABufTexture2D(*eglImageBayerOut_, out_fd); From patchwork Mon May 4 18:26:51 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26617 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 2DB54BE173 for ; Mon, 4 May 2026 18:27:23 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CED5A62FEC; Mon, 4 May 2026 20:27:22 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="YnM3Qnu/"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9BDB662FE8 for ; Mon, 4 May 2026 20:27:20 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1777919239; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=GMpTRJkAeYb5u4p7zVG3zTLovAUt5iXhXpZDwDhZzFI=; b=YnM3Qnu/nJ6QJPlq01r9u9/Y2ThC3EqzD7MGRDN/Zz6QrKcuggNjIRfKeaZg7jDsB5G1rQ zyzIpITXX4dms/b8VdRyvIalvyRTHzC6qkIhwV0plqT9T7D2cK6xZANIvE4CkKBaodgJGl YIai1RQtOooKLtl7UvRQClgwau4j0Xo= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-547--0QIuDOzPC6u6D39-L9m8Q-1; Mon, 04 May 2026 14:27:16 -0400 X-MC-Unique: -0QIuDOzPC6u6D39-L9m8Q-1 X-Mimecast-MFC-AGG-ID: -0QIuDOzPC6u6D39-L9m8Q_1777919234 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 6E96A1800348; Mon, 4 May 2026 18:27:14 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.69]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 4C07A180154B; Mon, 4 May 2026 18:27:11 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Xander Pronk , Bryan O'Donoghue , Hans de Goede , Laurent Pinchart , Rick ten Wolde , Milan Zamazal Subject: [RFC PATCH v4 2/7] libcamera: software_isp: Add LSC data to DebayerParams Date: Mon, 4 May 2026 20:26:51 +0200 Message-ID: <20260504182658.590233-3-mzamazal@redhat.com> In-Reply-To: <20260504182658.590233-1-mzamazal@redhat.com> References: <20260504182658.590233-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: N9TIk51VznXRz8UY-MqqznJM3IljFINLK-PGV0hu0go_1777919234 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true 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" From: Xander Pronk Add a lookup table for grid-based lens shading correction to debayer params. The lookup table is in the format of an RGB texture to be passed to debayering. The parameter is filled in by LSC algorithm implemented in a followup patch. If the algorithm is not enabled, the parameter content is arbitrary and the parameter may not be used. The parameter is currently unused, its handling is implemented in a followup patch. There is no special meaning about the selected grid size, it's just one of the smaller common sizes. Co-developed-by: Rick ten Wolde Signed-off-by: Rick ten Wolde Signed-off-by: Xander Pronk Signed-off-by: Milan Zamazal --- .../internal/software_isp/debayer_params.h | 8 ++++++ src/libcamera/software_isp/debayer.cpp | 28 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/include/libcamera/internal/software_isp/debayer_params.h b/include/libcamera/internal/software_isp/debayer_params.h index 6772b43bc..47f2c3ac2 100644 --- a/include/libcamera/internal/software_isp/debayer_params.h +++ b/include/libcamera/internal/software_isp/debayer_params.h @@ -10,6 +10,7 @@ #pragma once +#include #include #include "libcamera/internal/matrix.h" @@ -25,6 +26,13 @@ struct DebayerParams { float gamma = 1.0; float contrastExp = 1.0; RGB gains = RGB({ 1.0, 1.0, 1.0 }); + + static constexpr unsigned int kLscGridSize = 16; + static constexpr unsigned int kLscValuesPerCell = 3; + using LscValueType = float; + using LscLookupTable = + std::array; + LscLookupTable lscLut{}; }; } /* namespace libcamera */ diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp index 2d7abfb83..d91a7aff5 100644 --- a/src/libcamera/software_isp/debayer.cpp +++ b/src/libcamera/software_isp/debayer.cpp @@ -43,6 +43,34 @@ namespace libcamera { * \brief Contrast value to be used as an exponent */ +/** + * \var DebayerParams::kLscGridSize + * \brief Number of lens shading grid areas in one direction + */ + +/** + * \var DebayerParams::kLscValuesPerCell + * \brief Number of pixel values per each of the lens shading grid areas + */ + +/** + * \typedef DebayerParams::LscValueType + * \brief Type of LSC grid values + */ + +/** + * \typedef DebayerParams::LscLookupTable + * \brief Lookup table for lens shading correction + * + * It's an array of values to be later used as a texture. + * The values are in row - column - RGB order. + */ + +/** + * \var DebayerParams::lscLut + * \brief Lens shading lookup table + */ + /** * \class Debayer * \brief Base debayering class From patchwork Mon May 4 18:26:52 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26618 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 E7FF6C32F6 for ; Mon, 4 May 2026 18:27:24 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8857263025; Mon, 4 May 2026 20:27:24 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="jOX9oLI6"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F1CF063025 for ; Mon, 4 May 2026 20:27:22 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1777919241; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/4SRSFW2CabW6xnK7ScaXSfCdyrKnii9ObIH+MGlG4o=; b=jOX9oLI6eL4Yeg1vCqDIu/Jx0Cdyh+lOEVCvjMt9JqIjjaco6RqvS7pOEqX5Uh/jRLot6y LfsC5pDD52GwX0II3MtHHS5xeT5W/J5o5uzoAXsqz7mrgWXTrWBqtHqhR1m+JEVs7lsuQy OXIosSmEtTpUI33GpwMPOQC4HlbSO2A= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-465-ZSUQ5-VRO9upOYyD71qj0A-1; Mon, 04 May 2026 14:27:18 -0400 X-MC-Unique: ZSUQ5-VRO9upOYyD71qj0A-1 X-Mimecast-MFC-AGG-ID: ZSUQ5-VRO9upOYyD71qj0A_1777919237 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 36A20195605E; Mon, 4 May 2026 18:27:17 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.69]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id EC64A1800480; Mon, 4 May 2026 18:27:14 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Bryan O'Donoghue , Hans de Goede , Laurent Pinchart Subject: [RFC PATCH v4 3/7] ipa: simple: Introduce default temperature value Date: Mon, 4 May 2026 20:26:52 +0200 Message-ID: <20260504182658.590233-4-mzamazal@redhat.com> In-Reply-To: <20260504182658.590233-1-mzamazal@redhat.com> References: <20260504182658.590233-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: hVZbTnd6uD2BuYUyQ_H3FpkG5AiVvk8EpM2f1q5DArk_1777919237 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true 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" Some algorithms use interpolated values based on temperature. Temperature is computed in the AWB algorithm. Technically, the AWB algorithm can be disabled and then no temperature is computed. Let's avoid implicit assumptions and introduce a constant for a default temperature value and make the temperature value optional. This is currently used by the CCM algorithm. It will be used also by the LSC algorithm in the followup patch. The default temperature value of 6500 is just a common value, there is no special reason to use this or another value. Signed-off-by: Milan Zamazal --- src/ipa/simple/algorithms/awb.cpp | 4 ++-- src/ipa/simple/algorithms/awb.h | 4 +++- src/ipa/simple/algorithms/ccm.cpp | 5 ++++- src/ipa/simple/ipa_context.h | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp index f5c88ea6f..961126c0d 100644 --- a/src/ipa/simple/algorithms/awb.cpp +++ b/src/ipa/simple/algorithms/awb.cpp @@ -96,11 +96,11 @@ void Awb::process(IPAContext &context, RGB rgbGains{ { 1 / gains.r(), 1 / gains.g(), 1 / gains.b() } }; context.activeState.awb.temperatureK = estimateCCT(rgbGains); - metadata.set(controls::ColourTemperature, context.activeState.awb.temperatureK); + metadata.set(controls::ColourTemperature, context.activeState.awb.temperatureK.value_or(0)); LOG(IPASoftAwb, Debug) << "gain R/B: " << gains << "; temperature: " - << context.activeState.awb.temperatureK; + << context.activeState.awb.temperatureK.value_or(0); } REGISTER_IPA_ALGORITHM(Awb, "Awb") diff --git a/src/ipa/simple/algorithms/awb.h b/src/ipa/simple/algorithms/awb.h index ad993f39c..df46baee4 100644 --- a/src/ipa/simple/algorithms/awb.h +++ b/src/ipa/simple/algorithms/awb.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* - * Copyright (C) 2024-2025 Red Hat Inc. + * Copyright (C) 2024-2026 Red Hat Inc. * * Auto white balance */ @@ -13,6 +13,8 @@ namespace libcamera { namespace ipa::soft::algorithms { +constexpr unsigned int kDefaultTemperature = 6500; + class Awb : public Algorithm { public: diff --git a/src/ipa/simple/algorithms/ccm.cpp b/src/ipa/simple/algorithms/ccm.cpp index ace9c35dc..6f566ccdc 100644 --- a/src/ipa/simple/algorithms/ccm.cpp +++ b/src/ipa/simple/algorithms/ccm.cpp @@ -15,6 +15,8 @@ #include "libcamera/internal/matrix.h" +#include "awb.h" + namespace { constexpr unsigned int kTemperatureThreshold = 100; @@ -44,7 +46,8 @@ int Ccm::init([[maybe_unused]] IPAContext &context, const ValueNode &tuningData) void Ccm::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame, IPAFrameContext &frameContext, [[maybe_unused]] DebayerParams *params) { - const unsigned int ct = context.activeState.awb.temperatureK; + const unsigned int ct = + context.activeState.awb.temperatureK.value_or(kDefaultTemperature); /* Change CCM only on bigger temperature changes. */ if (!currentCcm_ || diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h index 34f7403a4..c4bd91bb0 100644 --- a/src/ipa/simple/ipa_context.h +++ b/src/ipa/simple/ipa_context.h @@ -50,7 +50,7 @@ struct IPAActiveState { struct { RGB gains; - unsigned int temperatureK; + std::optional temperatureK; } awb; Matrix combinedMatrix; From patchwork Mon May 4 18:26:53 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26619 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 864ECBE173 for ; Mon, 4 May 2026 18:27:28 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3E56E6302A; Mon, 4 May 2026 20:27:28 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="bUlOHPrI"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9172D62FEC for ; Mon, 4 May 2026 20:27:26 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1777919245; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=a67noJrZ3ozLkKiOFpPB4jmJ6gBaKZ5Bx2lPmVRj1as=; b=bUlOHPrIQd4Q5KVh/9hqeguTRil3hQc+7EcpDvscbhi9OD7SpR+otfDUe/HL6zxMhBd9id Pb28svJXeKUJNKN3PewmxZhGee6opdtFOJ0UAJ4e4vhrCPCERmAwIeFDUfSCpjySU9K+Xz NEuuYAB1GJ/9fPWIdn3Bt4xWglRyvmo= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-203-LujtyU_bPqyCTl1iIq_AzQ-1; Mon, 04 May 2026 14:27:22 -0400 X-MC-Unique: LujtyU_bPqyCTl1iIq_AzQ-1 X-Mimecast-MFC-AGG-ID: LujtyU_bPqyCTl1iIq_AzQ_1777919240 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 365F618001FA; Mon, 4 May 2026 18:27:20 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.69]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id AD47B1800480; Mon, 4 May 2026 18:27:17 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Xander Pronk , Bryan O'Donoghue , Hans de Goede , Laurent Pinchart , Rick ten Wolde , Milan Zamazal Subject: [RFC PATCH v4 4/7] ipa: simple: Add LSC algorithm Date: Mon, 4 May 2026 20:26:53 +0200 Message-ID: <20260504182658.590233-5-mzamazal@redhat.com> In-Reply-To: <20260504182658.590233-1-mzamazal@redhat.com> References: <20260504182658.590233-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: VSfyqAuWnmZi-dMO2QKoT88NgJ0ZyXRNXPx1miv41DI_1777919240 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true 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" From: Xander Pronk The lens shading algorithm uses grid-based interpolation. The grid values are specified in a tuning file as multiplication factors for each of the RGB colours. The interpolated grid is transformed to an array to be used as an RGB texture in debayering. Co-developed-by: Rick ten Wolde Signed-off-by: Rick ten Wolde Signed-off-by: Xander Pronk Signed-off-by: Milan Zamazal --- src/ipa/simple/algorithms/lsc.cpp | 63 +++++++++++++++++++++++++++ src/ipa/simple/algorithms/lsc.h | 41 +++++++++++++++++ src/ipa/simple/algorithms/meson.build | 1 + 3 files changed, 105 insertions(+) create mode 100644 src/ipa/simple/algorithms/lsc.cpp create mode 100644 src/ipa/simple/algorithms/lsc.h diff --git a/src/ipa/simple/algorithms/lsc.cpp b/src/ipa/simple/algorithms/lsc.cpp new file mode 100644 index 000000000..29c11ead3 --- /dev/null +++ b/src/ipa/simple/algorithms/lsc.cpp @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Lens shading correction + */ + +#include "lsc.h" + +#include + +#include "awb.h" + +namespace libcamera { + +namespace ipa::soft::algorithms { + +LOG_DEFINE_CATEGORY(IPASoftLsc) + +int Lsc::init([[maybe_unused]] IPAContext &context, const ValueNode &tuningData) +{ + int ret_r = lscR.readYaml(tuningData["grids"], "ct", "r"); + int ret_g = lscG.readYaml(tuningData["grids"], "ct", "g"); + int ret_b = lscB.readYaml(tuningData["grids"], "ct", "b"); + + if (ret_r < 0 || ret_g < 0 || ret_b < 0) { + LOG(IPASoftLsc, Error) + << "Failed to parse 'lsc' parameter from tuning file."; + return -EINVAL; + } + + return 0; +} + +int Lsc::configure([[maybe_unused]] IPAContext &context, + [[maybe_unused]] const IPAConfigInfo &configInfo) +{ + return 0; +} + +void Lsc::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame, + [[maybe_unused]] IPAFrameContext &frameContext, DebayerParams *params) +{ + unsigned int ct = + context.activeState.awb.temperatureK.value_or(kDefaultTemperature); + + const LscMatrix matrixR = lscR.getInterpolated(ct); + const LscMatrix matrixG = lscG.getInterpolated(ct); + const LscMatrix matrixB = lscB.getInterpolated(ct); + + DebayerParams::LscLookupTable lut; + constexpr unsigned int gridSize = DebayerParams::kLscGridSize; + for (unsigned int i = 0, j = 0; i < gridSize * gridSize; i++) { + lut[j++] = matrixR.data()[i]; + lut[j++] = matrixG.data()[i]; + lut[j++] = matrixB.data()[i]; + } + params->lscLut = lut; +} + +REGISTER_IPA_ALGORITHM(Lsc, "Lsc") + +} /* namespace ipa::soft::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/simple/algorithms/lsc.h b/src/ipa/simple/algorithms/lsc.h new file mode 100644 index 000000000..bed5a2c12 --- /dev/null +++ b/src/ipa/simple/algorithms/lsc.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Lens shading correction + */ + +#pragma once + +#include "libcamera/internal/matrix.h" + +#include + +#include "algorithm.h" + +namespace libcamera { + +namespace ipa::soft::algorithms { + +class Lsc : public Algorithm +{ +public: + Lsc() = default; + ~Lsc() = default; + + int init(IPAContext &context, const ValueNode &tuningData) override; + int configure(IPAContext &context, + const IPAConfigInfo &configInfo) override; + void prepare(IPAContext &context, + const uint32_t frame, + IPAFrameContext &frameContext, + DebayerParams *params) override; + +private: + using LscMatrix = Matrix; + Interpolator lscR; + Interpolator lscG; + Interpolator lscB; +}; + +} /* namespace ipa::soft::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/simple/algorithms/meson.build b/src/ipa/simple/algorithms/meson.build index 73c637220..c9f6e5590 100644 --- a/src/ipa/simple/algorithms/meson.build +++ b/src/ipa/simple/algorithms/meson.build @@ -6,4 +6,5 @@ soft_simple_ipa_algorithms = files([ 'agc.cpp', 'blc.cpp', 'ccm.cpp', + 'lsc.cpp', ]) From patchwork Mon May 4 18:26:54 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26621 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 47D03C32F6 for ; Mon, 4 May 2026 18:27:35 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CC66D6302E; Mon, 4 May 2026 20:27:34 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="RAvGEmHN"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 1946763026 for ; Mon, 4 May 2026 20:27:32 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1777919250; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=2rsZizSisUZJv1PcV/744BnSe5SnMGMSPYXMr4bGQKU=; b=RAvGEmHN2JZNUCK/FyliO779tOYmMWNkwgifMEaF6pxXf2m6jGzgWq+pDzyKk0LuryPQBt KNsx8F3f1TAsnoCXLUoOj5AbscRRj0QQNmvsQGkpURL1VgBRiOKV50TskfObymnXToXeN7 +FWgJBMMNRP6Co1IXJALLISz39dKa9w= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-558-Aie4HOHnMcykW9PUwxn_jg-1; Mon, 04 May 2026 14:27:25 -0400 X-MC-Unique: Aie4HOHnMcykW9PUwxn_jg-1 X-Mimecast-MFC-AGG-ID: Aie4HOHnMcykW9PUwxn_jg_1777919244 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D630118005A8; Mon, 4 May 2026 18:27:23 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.69]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id A87B41800370; Mon, 4 May 2026 18:27:20 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Xander Pronk , Bryan O'Donoghue , Hans de Goede , Laurent Pinchart , Rick ten Wolde , Milan Zamazal Subject: [RFC PATCH v4 5/7] libcamera: shaders: Add LSC support Date: Mon, 4 May 2026 20:26:54 +0200 Message-ID: <20260504182658.590233-6-mzamazal@redhat.com> In-Reply-To: <20260504182658.590233-1-mzamazal@redhat.com> References: <20260504182658.590233-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 4HdZKiIody0Nl29rwgOBuaQhYezwv3ZbWk-8ODLlg7M_1777919244 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true 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" From: Xander Pronk Lens shading correction should be applied after black level subtraction (in order to make the computations with meaningful values) and before white balance (especially before white balance stats are computed). Note that lens shading correction depends on temperature, which is computed from the preceding, rather than current, frame (this is due to how white balance is currently computed). Reviewed-by: Laurent Pinchart Co-developed-by: Rick ten Wolde Signed-off-by: Rick ten Wolde Signed-off-by: Xander Pronk Signed-off-by: Milan Zamazal --- src/libcamera/shaders/bayer_1x_packed.frag | 8 ++++++++ src/libcamera/shaders/bayer_unpacked.frag | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag index 23747f78a..228c72309 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -70,6 +70,10 @@ uniform vec3 blacklevel; uniform float gamma; uniform float contrastExp; +#if defined(APPLY_LSC) +uniform sampler2D lsc_tex; +#endif + float apply_contrast(float value) { // Apply simple S-curve @@ -227,6 +231,10 @@ void main(void) rgb = rgb - blacklevel; +#if defined(APPLY_LSC) + rgb = rgb * texture2D(lsc_tex, textureOut).rgb; +#endif + /* * CCM is a 3x3 in the format * diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag index 1b85196ae..af87bcc0f 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -29,6 +29,10 @@ uniform vec3 blacklevel; uniform float gamma; uniform float contrastExp; +#if defined(APPLY_LSC) +uniform sampler2D lsc_tex; +#endif + float apply_contrast(float value) { // Apply simple S-curve @@ -130,6 +134,10 @@ void main(void) { rgb = rgb - blacklevel; +#if defined(APPLY_LSC) + rgb = rgb * texture2D(lsc_tex, center.xy).rgb; +#endif + /* * CCM is a 3x3 in the format * From patchwork Mon May 4 18:26:55 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26620 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 6ED03BE173 for ; Mon, 4 May 2026 18:27:34 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 26BC363025; Mon, 4 May 2026 20:27:34 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="RC/sBZDY"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 84AA863025 for ; Mon, 4 May 2026 20:27:31 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1777919250; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=qpd3gZh5bCdnXU591IAzQ1ONhCm08sRV4+f7zj0j6i8=; b=RC/sBZDYsCvYxm6a+HpPZslImgWiEhKD8eS+XSAminiJfqQoZ93MWl4CuKpwrAM6rGPPbT D/Mj/dLgrURt/IomCmNFGZVy88LTF+Vb57FxuTYr32sJctfKedhaVeMv+J6oNtxJg5Nj9k Ek4W1fdnfybdN5fsQaGNK91vSN2tfK8= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-632-ueMRCt-rPW-Y8haZFPrrwA-1; Mon, 04 May 2026 14:27:27 -0400 X-MC-Unique: ueMRCt-rPW-Y8haZFPrrwA-1 X-Mimecast-MFC-AGG-ID: ueMRCt-rPW-Y8haZFPrrwA_1777919246 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 076351956095; Mon, 4 May 2026 18:27:26 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.69]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 5C1F31800480; Mon, 4 May 2026 18:27:24 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Bryan O'Donoghue , Hans de Goede , Laurent Pinchart Subject: [RFC PATCH v4 6/7] libcamera: software_isp: Pass LSC availability to debayering Date: Mon, 4 May 2026 20:26:55 +0200 Message-ID: <20260504182658.590233-7-mzamazal@redhat.com> In-Reply-To: <20260504182658.590233-1-mzamazal@redhat.com> References: <20260504182658.590233-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: tL71D2XHrxzk9RAVYTCjnlv-Y0EUfn3XCIahfuqfVp4_1777919246 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The lens shading algorithm may or may not be enabled in the tuning file. Debayering configuration needs this information to arrange things accordingly, e.g. to set up shader parameters. Let's add a corresponding flag that is set in the LSC algorithm (if present) and passed to Debayer::configure. This is similar to what we already do with CCM availability. The flag is ignored by CPU ISP, where LSC is not going to be implemented for now. Reviewed-by: Bryan O'Donoghue Signed-off-by: Milan Zamazal --- include/libcamera/internal/software_isp/software_isp.h | 1 + include/libcamera/ipa/soft.mojom | 4 +++- src/ipa/simple/algorithms/lsc.cpp | 4 +++- src/ipa/simple/ipa_context.h | 1 + src/ipa/simple/soft_simple.cpp | 7 +++++-- src/libcamera/software_isp/debayer.cpp | 1 + src/libcamera/software_isp/debayer.h | 3 ++- src/libcamera/software_isp/debayer_cpu.cpp | 3 ++- src/libcamera/software_isp/debayer_cpu.h | 3 ++- src/libcamera/software_isp/debayer_egl.cpp | 5 ++++- src/libcamera/software_isp/debayer_egl.h | 4 +++- src/libcamera/software_isp/software_isp.cpp | 5 +++-- 12 files changed, 30 insertions(+), 11 deletions(-) diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h index 585e0d6d9..f9bda25bd 100644 --- a/include/libcamera/internal/software_isp/software_isp.h +++ b/include/libcamera/internal/software_isp/software_isp.h @@ -100,6 +100,7 @@ private: DebayerParams debayerParams_; DmaBufAllocator dmaHeap_; bool ccmEnabled_; + bool lscEnabled_; std::unique_ptr ipa_; std::deque queuedInputBuffers_; diff --git a/include/libcamera/ipa/soft.mojom b/include/libcamera/ipa/soft.mojom index 77328c5fd..aaefd50c4 100644 --- a/include/libcamera/ipa/soft.mojom +++ b/include/libcamera/ipa/soft.mojom @@ -18,7 +18,9 @@ interface IPASoftInterface { libcamera.SharedFD fdParams, libcamera.IPACameraSensorInfo sensorInfo, libcamera.ControlInfoMap sensorControls) - => (int32 ret, libcamera.ControlInfoMap ipaControls, bool ccmEnabled); + => (int32 ret, + libcamera.ControlInfoMap ipaControls, + bool ccmEnabled, bool lscEnabled); start() => (int32 ret); stop(); configure(IPAConfigInfo configInfo) diff --git a/src/ipa/simple/algorithms/lsc.cpp b/src/ipa/simple/algorithms/lsc.cpp index 29c11ead3..efef2a904 100644 --- a/src/ipa/simple/algorithms/lsc.cpp +++ b/src/ipa/simple/algorithms/lsc.cpp @@ -15,7 +15,7 @@ namespace ipa::soft::algorithms { LOG_DEFINE_CATEGORY(IPASoftLsc) -int Lsc::init([[maybe_unused]] IPAContext &context, const ValueNode &tuningData) +int Lsc::init(IPAContext &context, const ValueNode &tuningData) { int ret_r = lscR.readYaml(tuningData["grids"], "ct", "r"); int ret_g = lscG.readYaml(tuningData["grids"], "ct", "g"); @@ -27,6 +27,8 @@ int Lsc::init([[maybe_unused]] IPAContext &context, const ValueNode &tuningData) return -EINVAL; } + context.lscEnabled = true; + return 0; } diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h index c4bd91bb0..d77bbc280 100644 --- a/src/ipa/simple/ipa_context.h +++ b/src/ipa/simple/ipa_context.h @@ -93,6 +93,7 @@ struct IPAContext { FCQueue frameContexts; ControlInfoMap::Map ctrlMap; bool ccmEnabled = false; + bool lscEnabled = false; }; } /* namespace ipa::soft */ diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp index 629e1a32d..4c724183a 100644 --- a/src/ipa/simple/soft_simple.cpp +++ b/src/ipa/simple/soft_simple.cpp @@ -57,7 +57,8 @@ public: const IPACameraSensorInfo &sensorInfo, const ControlInfoMap &sensorControls, ControlInfoMap *ipaControls, - bool *ccmEnabled) override; + bool *ccmEnabled, + bool *lscEnabled) override; int configure(const IPAConfigInfo &configInfo) override; int start() override; @@ -97,7 +98,8 @@ int IPASoftSimple::init(const IPASettings &settings, const IPACameraSensorInfo &sensorInfo, const ControlInfoMap &sensorControls, ControlInfoMap *ipaControls, - bool *ccmEnabled) + bool *ccmEnabled, + bool *lscEnabled) { camHelper_ = CameraSensorHelperFactoryBase::create(settings.sensorModel); if (!camHelper_) { @@ -136,6 +138,7 @@ int IPASoftSimple::init(const IPASettings &settings, return ret; *ccmEnabled = context_.ccmEnabled; + *lscEnabled = context_.lscEnabled; params_ = nullptr; stats_ = nullptr; diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp index d91a7aff5..76c66e55b 100644 --- a/src/libcamera/software_isp/debayer.cpp +++ b/src/libcamera/software_isp/debayer.cpp @@ -99,6 +99,7 @@ Debayer::~Debayer() * \param[in] inputCfg The input configuration * \param[in] outputCfgs The output configurations * \param[in] ccmEnabled Whether a color correction matrix is applied + * \param[in] lscEnabled Whether lens shading correction grid is provided * * \return 0 on success, a negative errno on failure */ diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h index a2a17ec18..f4e649417 100644 --- a/src/libcamera/software_isp/debayer.h +++ b/src/libcamera/software_isp/debayer.h @@ -40,7 +40,8 @@ public: virtual int configure(const StreamConfiguration &inputCfg, const std::vector> &outputCfgs, - bool ccmEnabled) = 0; + bool ccmEnabled, + bool lscEnabled) = 0; virtual std::vector formats(PixelFormat inputFormat) = 0; diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp index d9f5b3268..bff279c14 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -542,7 +542,8 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, int DebayerCpu::configure(const StreamConfiguration &inputCfg, const std::vector> &outputCfgs, - bool ccmEnabled) + bool ccmEnabled, + [[maybe_unused]] bool lscEnabled) { if (getInputConfig(inputCfg.pixelFormat, inputConfig_) != 0) return -EINVAL; diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h index 8c58775d5..4b5bc0194 100644 --- a/src/libcamera/software_isp/debayer_cpu.h +++ b/src/libcamera/software_isp/debayer_cpu.h @@ -36,7 +36,8 @@ public: int configure(const StreamConfiguration &inputCfg, const std::vector> &outputCfgs, - bool ccmEnabled) override; + bool ccmEnabled, + bool lscEnabled) override; Size patternSize(PixelFormat inputFormat) override; std::vector formats(PixelFormat input) override; std::tuple diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index f10f372c6..82c511976 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -277,7 +277,8 @@ int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputForm int DebayerEGL::configure(const StreamConfiguration &inputCfg, const std::vector> &outputCfgs, - [[maybe_unused]] bool ccmEnabled) + [[maybe_unused]] bool ccmEnabled, + bool lscEnabled) { if (getInputConfig(inputCfg.pixelFormat, inputConfig_) != 0) return -EINVAL; @@ -294,6 +295,8 @@ int DebayerEGL::configure(const StreamConfiguration &inputCfg, return -EINVAL; } + lscEnabled_ = lscEnabled; + inputConfig_.stride = inputCfg.stride; inputPixelFormat_ = inputCfg.pixelFormat; width_ = inputCfg.size.width; diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h index fcd281f4c..4d895b55d 100644 --- a/src/libcamera/software_isp/debayer_egl.h +++ b/src/libcamera/software_isp/debayer_egl.h @@ -45,7 +45,8 @@ public: int configure(const StreamConfiguration &inputCfg, const std::vector> &outputCfgs, - bool ccmEnabled) override; + bool ccmEnabled, + bool lscEnabled) override; Size patternSize(PixelFormat inputFormat) override; @@ -77,6 +78,7 @@ private: std::unique_ptr eglImageBayerIn_; std::unique_ptr eglImageBayerOut_; + bool lscEnabled_; /* Shader parameters */ float firstRed_x_; float firstRed_y_; diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index d227bd8e3..05eedc091 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -155,7 +155,8 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, sensorInfo, sensor->controls(), ipaControls, - &ccmEnabled_); + &ccmEnabled_, + &lscEnabled_); if (ret) { LOG(SoftwareIsp, Error) << "IPA init failed"; debayer_.reset(); @@ -271,7 +272,7 @@ int SoftwareIsp::configure(const StreamConfiguration &inputCfg, if (ret < 0) return ret; - ret = debayer_->configure(inputCfg, outputCfgs, ccmEnabled_); + ret = debayer_->configure(inputCfg, outputCfgs, ccmEnabled_, lscEnabled_); if (ret < 0) return ret; From patchwork Mon May 4 18:26:56 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 26622 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 083E9BE173 for ; Mon, 4 May 2026 18:27:39 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A09B563030; Mon, 4 May 2026 20:27:38 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="c2ncigSe"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 97AD663025 for ; Mon, 4 May 2026 20:27:37 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1777919256; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ynOwl6GxC/cT8MQLoXvoi+WePN9XgUSnYyZzzl16VhQ=; b=c2ncigSecYvJa8dwpC0h85v1uwZZW56l/1GbAs/S6CBFthTxTpVEUDGskafT9drhs0leP2 NKYaDGXPTg5YlAO9dXa+2jZagutZ+hbzLOpuhjPHahmlFPoFO5sIukTqdHkS3D0+unlTXO UuuPq6CyzZiMppFqDB5Qfcm3hyvZyOQ= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-382-rPYARek5POWHrdftOh_t2g-1; Mon, 04 May 2026 14:27:31 -0400 X-MC-Unique: rPYARek5POWHrdftOh_t2g-1 X-Mimecast-MFC-AGG-ID: rPYARek5POWHrdftOh_t2g_1777919249 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 4A6F8195608A; Mon, 4 May 2026 18:27:29 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.69]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 9728A1800480; Mon, 4 May 2026 18:27:26 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Xander Pronk , Bryan O'Donoghue , Hans de Goede , Laurent Pinchart , Rick ten Wolde , Milan Zamazal Subject: [RFC PATCH v4 7/7] libcamera: software_isp: debayer_egl: Add LSC support Date: Mon, 4 May 2026 20:26:56 +0200 Message-ID: <20260504182658.590233-8-mzamazal@redhat.com> In-Reply-To: <20260504182658.590233-1-mzamazal@redhat.com> References: <20260504182658.590233-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: qHCJApIbqehiEb4StqHFqfYwJIT7HL3Hi8GL4fMhVoc_1777919249 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true 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" From: Xander Pronk Add support for passing the LSC table from debayerParams to the shaders. The LSC table values are floats, we must add `type' parameter to createTexture2D to support this. Moreover, we use 16-bit internal format for the values, primarily because this works for me, unlike 32-bit floats. Co-developed-by: Rick ten Wolde Signed-off-by: Rick ten Wolde Signed-off-by: Xander Pronk Signed-off-by: Milan Zamazal --- include/libcamera/internal/egl.h | 10 +++++-- .../internal/software_isp/debayer_params.h | 2 ++ src/libcamera/egl.cpp | 16 ++++++++--- src/libcamera/software_isp/debayer.cpp | 5 ++++ src/libcamera/software_isp/debayer_egl.cpp | 28 +++++++++++++++++-- src/libcamera/software_isp/debayer_egl.h | 5 ++++ 6 files changed, 58 insertions(+), 8 deletions(-) diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h index 6402dd5c7..3de47d970 100644 --- a/include/libcamera/internal/egl.h +++ b/include/libcamera/internal/egl.h @@ -103,8 +103,14 @@ 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, - const void *data, GLint filter); + void createTexture2D(eGLImage &eglImage, + GLint internalFormat, + GLint format, + GLenum type, + uint32_t width, + uint32_t height, + const void *data, + GLint filter); void pushEnv(std::vector &shaderEnv, const char *str); void makeCurrent(); diff --git a/include/libcamera/internal/software_isp/debayer_params.h b/include/libcamera/internal/software_isp/debayer_params.h index 47f2c3ac2..5b1c8b508 100644 --- a/include/libcamera/internal/software_isp/debayer_params.h +++ b/include/libcamera/internal/software_isp/debayer_params.h @@ -30,6 +30,8 @@ struct DebayerParams { static constexpr unsigned int kLscGridSize = 16; static constexpr unsigned int kLscValuesPerCell = 3; using LscValueType = float; + static constexpr unsigned int kLscBytesPerCell = + kLscValuesPerCell * sizeof(LscValueType); using LscLookupTable = std::array; LscLookupTable lscLut{}; diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index 93778acb8..fb716429d 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -208,7 +208,9 @@ 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] internalFormat OpenGL internal storage format (e.g., GL_RGB8, GL_RGBA8) + * \param[in] format OpenGL pixel data format (e.g., GL_RGB, GL_RGBA) + * \param[in] type OpenGL pixel data type (e.g., GL_UNSIGNED_BYTE, GL_FLOAT) * \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 @@ -219,8 +221,14 @@ 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, - const void *data, GLint filter) +void eGL::createTexture2D(eGLImage &eglImage, + GLint internalFormat, + GLint format, + GLenum type, + uint32_t width, + uint32_t height, + const void *data, + GLint filter) { ASSERT(tid_ == Thread::currentId()); @@ -228,7 +236,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, internalFormat, width, height, 0, format, type, data); // Nearest filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp index 76c66e55b..cc1dbb2d0 100644 --- a/src/libcamera/software_isp/debayer.cpp +++ b/src/libcamera/software_isp/debayer.cpp @@ -58,6 +58,11 @@ namespace libcamera { * \brief Type of LSC grid values */ +/** + * \var DebayerParams::kLscBytesPerCell + * \brief Number of bytes per each of the lens shading grid areas + */ + /** * \typedef DebayerParams::LscLookupTable * \brief Lookup table for lens shading correction diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 82c511976..0a77a0b41 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -110,6 +110,8 @@ int DebayerEGL::getShaderVariableLocations(void) textureUniformBayerFirstRed_ = glGetUniformLocation(programId_, "tex_bayer_first_red"); textureUniformProjMatrix_ = glGetUniformLocation(programId_, "proj_matrix"); + textureUniformLsc_ = glGetUniformLocation(programId_, "lsc_tex"); + LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ << " tex_y " << textureUniformBayerDataIn_ << " ccm " << ccmUniformDataIn_ @@ -120,7 +122,8 @@ int DebayerEGL::getShaderVariableLocations(void) << " tex_size " << textureUniformSize_ << " stride_factor " << textureUniformStrideFactor_ << " tex_bayer_first_red " << textureUniformBayerFirstRed_ - << " proj_matrix " << textureUniformProjMatrix_; + << " proj_matrix " << textureUniformProjMatrix_ + << " lsc " << textureUniformLsc_; return 0; } @@ -139,6 +142,9 @@ int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputForm /* Specify GL_OES_EGL_image_external */ egl_.pushEnv(shaderEnv, "#extension GL_OES_EGL_image_external: enable"); + if (lscEnabled_) + egl_.pushEnv(shaderEnv, "#define APPLY_LSC"); + /* * Tell shaders how to re-order output taking account of how the pixels * are actually stored by EGL. @@ -338,6 +344,17 @@ int DebayerEGL::configure(const StreamConfiguration &inputCfg, */ stats_->setWindow(Rectangle(window_.size())); + if (lscEnabled_) { + constexpr unsigned int gridSize = DebayerParams::kLscGridSize; + const unsigned int stride = gridSize * DebayerParams::kLscBytesPerCell; + eglImageLscLookup_ = + std::make_unique(gridSize, + gridSize, + stride, + GL_TEXTURE2, + 2); + } + return 0; } @@ -477,6 +494,13 @@ void DebayerEGL::setShaderVariableValues(const DebayerParams ¶ms) glUniformMatrix3fv(ccmUniformDataIn_, 1, GL_FALSE, ccm); LOG(Debayer, Debug) << " ccmUniformDataIn_ " << ccmUniformDataIn_ << " data " << params.combinedMatrix; + if (lscEnabled_) { + egl_.createTexture2D(*eglImageLscLookup_, GL_RGB16F, GL_RGB, GL_FLOAT, + DebayerParams::kLscGridSize, DebayerParams::kLscGridSize, + params.lscLut.data(), GL_LINEAR); + glUniform1i(textureUniformLsc_, eglImageLscLookup_->texture_unit_uniform_id_); + } + /* * 0 = Red, 1 = Green, 2 = Blue */ @@ -504,7 +528,7 @@ int DebayerEGL::debayerGPU(MappedFrameBuffer &in, int out_fd, const DebayerParam egl_.makeCurrent(); /* Create a standard texture input */ - egl_.createTexture2D(*eglImageBayerIn_, glFormat_, + egl_.createTexture2D(*eglImageBayerIn_, glFormat_, glFormat_, GL_UNSIGNED_BYTE, inputConfig_.stride / bytesPerPixel_, height_, in.planes()[0].data(), GL_NEAREST); diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h index 4d895b55d..744efba61 100644 --- a/src/libcamera/software_isp/debayer_egl.h +++ b/src/libcamera/software_isp/debayer_egl.h @@ -78,7 +78,10 @@ private: std::unique_ptr eglImageBayerIn_; std::unique_ptr eglImageBayerOut_; + /* LSC lookup table */ + std::unique_ptr eglImageLscLookup_; bool lscEnabled_; + /* Shader parameters */ float firstRed_x_; float firstRed_y_; @@ -92,6 +95,8 @@ private: GLint textureUniformBayerDataIn_; + GLint textureUniformLsc_; + /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */ GLint ccmUniformDataIn_;