From patchwork Fri Jun 26 13:05:54 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Scally X-Patchwork-Id: 27067 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 2683FC3306 for ; Fri, 26 Jun 2026 13:06:22 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E9DD665F13; Fri, 26 Jun 2026 15:06:15 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="EMMo9yl2"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BDEF765EE7 for ; Fri, 26 Jun 2026 15:06:06 +0200 (CEST) Received: from [127.0.1.1] (chfd-03-b2-v4wan-176392-cust229.vm15.cable.virginm.net [82.19.20.230]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id C13AE1AE5; Fri, 26 Jun 2026 15:05:25 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1782479125; bh=MV1OudgVxwqKcw+PZWyvAFv5rAPA2Ey0KE5JXKGr7Os=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=EMMo9yl2H4szF7oOGBEbJAWatIOJgI5OoNjD6ji9Tu2Ot1mgM24az32wbF6p9R8eH oRV7ehQyROv7wZrT7velWu9ptDbSR9OlfBcVOQW66ObC541b9V+S9h3W7fMJZdKZ2O PO4g6q3GNPe64tFvm+tvopO8UEFOKL4PRFIdgR2Q= From: Daniel Scally Date: Fri, 26 Jun 2026 14:05:54 +0100 Subject: [PATCH v2 07/12] ipa: ipu3: ToneMapping: Convert to use GammaAlgorithm MIME-Version: 1.0 Message-Id: <20260626-ipu3-libipa-rework-v2-7-41546e23de3e@ideasonboard.com> References: <20260626-ipu3-libipa-rework-v2-0-41546e23de3e@ideasonboard.com> In-Reply-To: <20260626-ipu3-libipa-rework-v2-0-41546e23de3e@ideasonboard.com> To: libcamera-devel@lists.libcamera.org Cc: Daniel Scally , Jacopo Mondi , Kieran Bingham X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=8593; i=dan.scally@ideasonboard.com; h=from:subject:message-id; bh=MV1OudgVxwqKcw+PZWyvAFv5rAPA2Ey0KE5JXKGr7Os=; b=owEBbQKS/ZANAwAKAchJV3psRXUyAcsmYgBqPnk62xG6GoNzv874hDnaI3WUNoRnQZZpoPcc5 X+d3o6QHAyJAjMEAAEKAB0WIQQqyuwyDnZdb+mxmm/ISVd6bEV1MgUCaj55OgAKCRDISVd6bEV1 MkBqD/441lIw/ISxUkps4lFW9fNmRwQ8pOUvU0rMLoFVn10kpKlA9hQ3CZTqPRYGGyvQqQUxy9J KdbSLZQWkHpi023zK/rv09oNgW16r7KGDBBLOGUOaRErhRS1zRhlZhhZgDCodeJ+FVbcQ8m085W cQ/B+C1VRNUUK0ZBVSfWKRwgkTyk/sPFWPOY3syoA9Qq3dKZPsizrLRlF15pWB9e4RHl+/MWVhq acac8/zhcj+4+KOh4LVbte/8Ud0zsOW70lGSoAjoGBlkMSvC/T2Co4PCt1i2ZPnjDDvKdZ3Smpj peugQaoPPKTHN+zLu/Pl85DHA0ShZyrJ10omHgTNvjEa2CJtx81gMkYKbfF2BNvF7MtFr0MpHJP nsAjdVvodALZMJ5ebctPFHQ42eIvOd4ILsFoQeGOXpfT+wINV0mk/Nd7Xa/tsZk6ADrYEi5rgFO ttcqEbQGLI5EVl/QwlPZeuCpzgOioA24WYUz8jVK55fYeerxbvZnQVYrZE9T974hMKug6MzoDGA 2CgTWcHQ8qu7iggg3eGlZbAUgXMZS5oWgJRFCC/Fx6Z4e2zNp/YybzDz50TjFW2rb0+v6qaOo/y 092cY24IvD2bI6jDAN5wcJ9bxAvS6Qbh+dJsQMFlZlyNey5BCbhxHwwdjGosl5yyE+EKd+cdClk vuBEYB44BQKHzUA== X-Developer-Key: i=dan.scally@ideasonboard.com; a=openpgp; fpr=EEC699ACA1B7CB5D31330C0BBD501C2A3546CCF6 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" Convert the IPU3 ToneMapping algorithm to use the new GammaAlgorithm base class. This gives us configurable gamma via the tuning files and at runtime using the Gamma control. Reviewed-by: Jacopo Mondi Reviewed-by: Kieran Bingham Signed-off-by: Daniel Scally --- Changes in v2: - Fixed includes - Minor styling changes --- src/ipa/ipu3/algorithms/tone_mapping.cpp | 73 +++++++++++++++++--------------- src/ipa/ipu3/algorithms/tone_mapping.h | 12 +++++- src/ipa/ipu3/ipa_context.cpp | 24 +++++------ src/ipa/ipu3/ipa_context.h | 8 ++-- 4 files changed, 63 insertions(+), 54 deletions(-) diff --git a/src/ipa/ipu3/algorithms/tone_mapping.cpp b/src/ipa/ipu3/algorithms/tone_mapping.cpp index 160338c139448cc9a0bc1fe2400c335a96f68f73..ea17abff8167238dfc5d65f6bb64754e8a7834ef 100644 --- a/src/ipa/ipu3/algorithms/tone_mapping.cpp +++ b/src/ipa/ipu3/algorithms/tone_mapping.cpp @@ -10,6 +10,8 @@ #include #include +#include + /** * \file tone_mapping.h */ @@ -27,10 +29,17 @@ namespace ipa::ipu3::algorithms { */ ToneMapping::ToneMapping() - : gamma_(1.0) { } +/** + * \copydoc libcamera::ipa::Algorithm::init + */ +int ToneMapping::init(IPAContext &context, const ValueNode &tuningData) +{ + return gammaAlgo_.init(context.ctrlMap, tuningData); +} + /** * \brief Configure the tone mapping given a configInfo * \param[in] context The shared IPA context @@ -41,12 +50,21 @@ ToneMapping::ToneMapping() int ToneMapping::configure(IPAContext &context, [[maybe_unused]] const IPAConfigInfo &configInfo) { - /* Initialise tone mapping gamma value. */ - context.activeState.toneMapping.gamma = 0.0; - + gammaAlgo_.configure(context.activeState.gamma); return 0; } +/** + * \copydoc libcamera::ipa::Algorithm::queueRequest + */ +void ToneMapping::queueRequest(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, + const ControlList &controls) +{ + gammaAlgo_.queueRequest(context.activeState.gamma, frame, + frameContext.gamma, controls); +} + /** * \brief Fill in the parameter structure, and enable gamma control * \param[in] context The shared IPA context @@ -59,14 +77,21 @@ int ToneMapping::configure(IPAContext &context, */ void ToneMapping::prepare([[maybe_unused]] IPAContext &context, [[maybe_unused]] const uint32_t frame, - [[maybe_unused]] IPAFrameContext &frameContext, + IPAFrameContext &frameContext, ipu3_uapi_params *params) { - /* Copy the calculated LUT into the parameters buffer. */ - memcpy(params->acc_param.gamma.gc_lut.lut, - context.activeState.toneMapping.gammaCorrection.lut, - IPU3_UAPI_GAMMA_CORR_LUT_ENTRIES * - sizeof(params->acc_param.gamma.gc_lut.lut[0])); + if (!frameContext.gamma.update) + return; + + /* + * Unfortunately necessary given the IPU3's gamma uAPI struct has the + * __packed attribute. + */ + uint16_t *lutData = reinterpret_cast( + __builtin_assume_aligned(params->acc_param.gamma.gc_lut.lut, 16)); + Span lut{ lutData, kNumLutNodes }; + + gammaAlgo_.prepare(frameContext.gamma, lut); /* Enable the custom gamma table. */ params->use.acc_gamma = 1; @@ -84,33 +109,13 @@ void ToneMapping::prepare([[maybe_unused]] IPAContext &context, * The tone mapping look up table is generated as an inverse power curve from * our gamma setting. */ -void ToneMapping::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, - [[maybe_unused]] IPAFrameContext &frameContext, +void ToneMapping::process([[maybe_unused]] IPAContext &context, + [[maybe_unused]] const uint32_t frame, + IPAFrameContext &frameContext, [[maybe_unused]] const ipu3_uapi_stats_3a *stats, [[maybe_unused]] ControlList &metadata) { - /* - * Hardcode gamma to 1.1 as a default for now. - * - * \todo Expose gamma control setting through the libcamera control API - */ - gamma_ = 1.1; - - if (context.activeState.toneMapping.gamma == gamma_) - return; - - struct ipu3_uapi_gamma_corr_lut &lut = - context.activeState.toneMapping.gammaCorrection; - - for (uint32_t i = 0; i < std::size(lut.lut); i++) { - double j = static_cast(i) / (std::size(lut.lut) - 1); - double gamma = std::pow(j, 1.0 / gamma_); - - /* The output value is expressed on 13 bits. */ - lut.lut[i] = gamma * 8191; - } - - context.activeState.toneMapping.gamma = gamma_; + gammaAlgo_.process(frameContext.gamma, metadata); } REGISTER_IPA_ALGORITHM(ToneMapping, "ToneMapping") diff --git a/src/ipa/ipu3/algorithms/tone_mapping.h b/src/ipa/ipu3/algorithms/tone_mapping.h index b2b380108e014b3d5ee7b93bcdd948dea4d2302d..3437b7fcbbb70c9bbc895b514b354d26c1d707c6 100644 --- a/src/ipa/ipu3/algorithms/tone_mapping.h +++ b/src/ipa/ipu3/algorithms/tone_mapping.h @@ -7,6 +7,11 @@ #pragma once +#include + +#include +#include + #include "algorithm.h" namespace libcamera { @@ -18,7 +23,11 @@ class ToneMapping : public Algorithm public: ToneMapping(); + int init(IPAContext &context, const ValueNode &tuningData) override; int configure(IPAContext &context, const IPAConfigInfo &configInfo) override; + void queueRequest(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, + const ControlList &controls) override; void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, ipu3_uapi_params *params) override; void process(IPAContext &context, const uint32_t frame, @@ -27,7 +36,8 @@ public: ControlList &metadata) override; private: - double gamma_; + static constexpr unsigned int kNumLutNodes = IPU3_UAPI_GAMMA_CORR_LUT_ENTRIES; + GammaAlgorithm> gammaAlgo_; }; } /* namespace ipa::ipu3::algorithms */ diff --git a/src/ipa/ipu3/ipa_context.cpp b/src/ipa/ipu3/ipa_context.cpp index 469905a43c4300bfa7a7fee5777f4a51837cf4c6..d3bcd7a81fe010d17d1437bf7f6cedce83a9be5c 100644 --- a/src/ipa/ipu3/ipa_context.cpp +++ b/src/ipa/ipu3/ipa_context.cpp @@ -119,6 +119,11 @@ namespace libcamera::ipa::ipu3 { * \brief Active colour Correction Matrix parameters for the IPA */ +/** + * \var IPAActiveState::gamma + * \brief Active gamma correction parameters for the IPA + */ + /** * \var IPASessionConfiguration::sensor * \brief Sensor-specific configuration of the IPA @@ -149,20 +154,6 @@ namespace libcamera::ipa::ipu3 { * The gain should be adapted to the sensor specific gain code before applying. */ -/** - * \var IPAActiveState::toneMapping - * \brief Context for ToneMapping and Gamma control - * - * \var IPAActiveState::toneMapping.gamma - * \brief Gamma value for the LUT - * - * \var IPAActiveState::toneMapping.gammaCorrection - * \brief Per-pixel tone mapping implemented as a LUT - * - * The LUT structure is defined by the IPU3 kernel interface. See - * struct ipu3_uapi_gamma_corr_lut for further details. - */ - /** * \struct IPAFrameContext * \brief IPU3-specific FrameContext @@ -187,4 +178,9 @@ namespace libcamera::ipa::ipu3 { * \brief Per-frame colour Correction Matrix parameters for the IPA */ +/** + * \var IPAFrameContext::gamma + * \brief Per-frame gamma correction parameters for the IPA + */ + } /* namespace libcamera::ipa::ipu3 */ diff --git a/src/ipa/ipu3/ipa_context.h b/src/ipa/ipu3/ipa_context.h index 6445db2603645d804b6caa40cde65099c4e57511..ce496ed477f4cbe2653aedada3381258396d92c8 100644 --- a/src/ipa/ipu3/ipa_context.h +++ b/src/ipa/ipu3/ipa_context.h @@ -18,6 +18,7 @@ #include #include #include +#include namespace libcamera { @@ -64,11 +65,7 @@ struct IPAActiveState { ipa::awb::ActiveState awb; ipa::ccm::ActiveState ccm; - - struct { - double gamma; - struct ipu3_uapi_gamma_corr_lut gammaCorrection; - } toneMapping; + ipa::gamma::ActiveState gamma; }; struct IPAFrameContext : public FrameContext { @@ -79,6 +76,7 @@ struct IPAFrameContext : public FrameContext { ipa::awb::FrameContext awb; ipa::ccm::FrameContext ccm; + ipa::gamma::FrameContext gamma; }; struct IPAContext {