From patchwork Wed Sep 2 09:07:27 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Scally X-Patchwork-Id: 28171 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 3B218C334A for ; Wed, 2 Sep 2026 09:07:51 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3AA88685B0; Wed, 2 Sep 2026 11:07:47 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="nXNKMqHz"; 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 C60B6685A8 for ; Wed, 2 Sep 2026 11:07:36 +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 C4E8E2821; Wed, 2 Sep 2026 11:06:05 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1788339965; bh=uJ/h3KM1E6DFxQFTUTEN1y8pPZHfIAQybtcZ3ek7JzI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=nXNKMqHzNvTmBkY34jtyeWZpGKt7SoS90jjhJ4ZiM6iHDNsiL1oH9NXckhZ/hEg4X DsYjFW10PVaRQXhxUBK92Ghd4LNMtTJ/3SuZSYncXf7vTIuo00adSXrmuc9dCI4nV7 Ir/FShLVK7GE8NblT2EOQTBAL35YRtx4NEiLIZJI= From: Daniel Scally Date: Wed, 02 Sep 2026 10:07:27 +0100 Subject: [PATCH v3 09/10] ipa: rkisp1: goc: Re-work to use GammaAlgorithm class MIME-Version: 1.0 Message-Id: <20260902-ipu3-libipa-rework-v3-9-b7da9b062326@ideasonboard.com> References: <20260902-ipu3-libipa-rework-v3-0-b7da9b062326@ideasonboard.com> In-Reply-To: <20260902-ipu3-libipa-rework-v3-0-b7da9b062326@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=6828; i=dan.scally@ideasonboard.com; h=from:subject:message-id; bh=uJ/h3KM1E6DFxQFTUTEN1y8pPZHfIAQybtcZ3ek7JzI=; b=owEBbQKS/ZANAwAKAchJV3psRXUyAcsmYgBql+dV6MSmXfU8uQC2dtmi1ILJaRXxkOS507BMJ QtvjYRC0oaJAjMEAAEKAB0WIQQqyuwyDnZdb+mxmm/ISVd6bEV1MgUCapfnVQAKCRDISVd6bEV1 MhQKEACBwk5rmo2Gs3K0sOetw5RYQQZr6a2D9u73kauEwOiuprHDTNzp1E5x2Ixcf1Ma0ra1cmp v2TD7xz4BbqG4k0Odbc5FW/Czrx3ZuhWbyeZt1Of6u2kPbOUMNeMUaPHXKn2rKefegI5v/bdb2H OxSd/kvgEfSTX5qs8VleLV5IQeVMDWq5E6v+comcuGOzGsqfJC4bZ9MoYGyqUcve5KOoJq12Tjo MJgajzSvvRuqKUv0+ICooQegAPCrH+OfBAwODGDE9c3cuL/0uA/mtsXwJ6Ry8Y0SuigQkTOoCHP pafesOlI27obDuusxTgv/0TNaRf25/+uZi0/KkJXGfH71Nl26j1AxVDxt02PejAxQ7tL98ERaeM yWCOQDwLLN5ye0YFKyZkE2FWwPIf7nvnATAKi4omFWijoVEalYDZne/M+idBsI6Xu0DNvk7D6fp hPG1RmvlrWanfdB8j+aikUoP4Nr8zzzRubchQ2lLoFq17OtFpTpGlOz0PxtRw683sDr9uHr1GXB zpv8jAGbDF2P0TfnFFvCUC/eTpX6JAozz5fOMaCLMjE66MwSNBXuf+nLKuIq95iLDhF5PxxoD3u ovrfH9nzbi3lyYMIp+71mUJ8dDRvh66t6xuTcPVQL8XlOKN1DoXW4uz9MgOIumLOcoAXol9d9/u Bmg3/Tb5pQhfaPg== 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" Re-work the RkISP1 Gamma Out Correction algorithm to use the new GammaAlgorithm class from libipa, which allows us to share an implementation with the other IPAs. Reviewed-by: Jacopo Mondi Reviewed-by: Kieran Bingham Signed-off-by: Daniel Scally --- Changes in v3: - None Changes in v2: - Fixed includes - Dropped the comment explaining how gamma correction is implemented - it's on libipa gamma now - Dropped unused variable kDefaultGamma --- src/ipa/rkisp1/algorithms/goc.cpp | 65 ++++++++++++--------------------------- src/ipa/rkisp1/algorithms/goc.h | 7 ++++- src/ipa/rkisp1/ipa_context.h | 10 ++---- 3 files changed, 28 insertions(+), 54 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/goc.cpp b/src/ipa/rkisp1/algorithms/goc.cpp index e8f64bf3d5e028c2013d37b7ef9fe90b737fad5f..dc08b6ba972e3f3390bdae862b4935396313c4a7 100644 --- a/src/ipa/rkisp1/algorithms/goc.cpp +++ b/src/ipa/rkisp1/algorithms/goc.cpp @@ -6,10 +6,11 @@ */ #include "goc.h" +#include #include #include -#include +#include #include @@ -29,21 +30,13 @@ namespace ipa::rkisp1::algorithms { * \class GammaOutCorrection * \brief RkISP1 Gamma out correction * - * This algorithm implements the gamma out curve for the RkISP1. It defaults to - * a gamma value of 2.2. - * - * As gamma is internally represented as a piecewise linear function with only - * 17 knots, the difference between gamma=2.2 and sRGB gamma is minimal. - * Therefore sRGB gamma was not implemented as special case. - * - * Useful links: - * - https://www.cambridgeincolour.com/tutorials/gamma-correction.htm - * - https://en.wikipedia.org/wiki/SRGB + * This algorithm implements the gamma out curve for the RkISP1 using the + * libipa GammaAlgorithm class. */ LOG_DEFINE_CATEGORY(RkISP1Gamma) -const float kDefaultGamma = 2.2f; +static constexpr unsigned int kNumLutSegments = RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10 - 1; /** * \copydoc libcamera::ipa::Algorithm::init @@ -57,10 +50,12 @@ int GammaOutCorrection::init(IPAContext &context, const ValueNode &tuningData) return -EINVAL; } - defaultGamma_ = tuningData["gamma"].get(kDefaultGamma); - context.ctrlMap[&controls::Gamma] = ControlInfo(0.1f, 10.0f, defaultGamma_); + std::array segments = { + 64, 64, 64, 64, 128, 128, 128, 128, + 256, 256, 256, 512, 512, 512, 512, 512 + }; - return 0; + return gammaAlgo_.init(context.ctrlMap, tuningData, segments); } /** @@ -69,7 +64,7 @@ int GammaOutCorrection::init(IPAContext &context, const ValueNode &tuningData) int GammaOutCorrection::configure(IPAContext &context, [[maybe_unused]] const IPACameraSensorInfo &configInfo) { - context.activeState.goc.gamma = defaultGamma_; + gammaAlgo_.configure(context.activeState.gamma); return 0; } @@ -80,17 +75,8 @@ void GammaOutCorrection::queueRequest(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, const ControlList &controls) { - if (frame == 0) - frameContext.goc.update = true; - - const auto &gamma = controls.get(controls::Gamma); - if (gamma) { - context.activeState.goc.gamma = *gamma; - frameContext.goc.update = true; - LOG(RkISP1Gamma, Debug) << "Set gamma to " << *gamma; - } - - frameContext.goc.gamma = context.activeState.goc.gamma; + gammaAlgo_.queueRequest(context.activeState.gamma, frame, + frameContext.gamma, controls); } /** @@ -104,29 +90,16 @@ void GammaOutCorrection::prepare(IPAContext &context, ASSERT(context.hw.numGammaOutSamples == RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10); - if (!frameContext.goc.update) + if (!frameContext.gamma.update) return; - /* - * The logarithmic segments as specified in the reference. - * Plus an additional 0 to make the loop easier - */ - static constexpr std::array segments = { - 64, 64, 64, 64, 128, 128, 128, 128, 256, - 256, 256, 512, 512, 512, 512, 512, 0 - }; - auto config = params->block(); config.setEnabled(true); - __u16 *gamma_y = config->gamma_y; - - unsigned x = 0; - for (const auto [i, size] : utils::enumerate(segments)) { - gamma_y[i] = std::pow(x / 4096.0, 1.0 / frameContext.goc.gamma) * 1023.0; - x += size; - } - + Span lut{ + config->gamma_y, RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10 + }; + gammaAlgo_.prepare(frameContext.gamma, lut); config->mode = RKISP1_CIF_ISP_GOC_MODE_LOGARITHMIC; } @@ -139,7 +112,7 @@ void GammaOutCorrection::process([[maybe_unused]] IPAContext &context, [[maybe_unused]] const rkisp1_stat_buffer *stats, ControlList &metadata) { - metadata.set(controls::Gamma, frameContext.goc.gamma); + gammaAlgo_.process(frameContext.gamma, metadata); } REGISTER_IPA_ALGORITHM(GammaOutCorrection, "GammaOutCorrection") diff --git a/src/ipa/rkisp1/algorithms/goc.h b/src/ipa/rkisp1/algorithms/goc.h index bd79fe19cc86b8aefa2603e98e9d7130b44105d9..767d707b2758a89db286ab62d8f20d7a01912a2a 100644 --- a/src/ipa/rkisp1/algorithms/goc.h +++ b/src/ipa/rkisp1/algorithms/goc.h @@ -9,6 +9,11 @@ #include "algorithm.h" +#include + +#include +#include + namespace libcamera { namespace ipa::rkisp1::algorithms { @@ -35,7 +40,7 @@ public: ControlList &metadata) override; private: - float defaultGamma_; + GammaAlgorithm> gammaAlgo_; }; } /* namespace ipa::rkisp1::algorithms */ diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index cc07bb9462d7a9d2c5e3f4dd1e89165b664116a4..a6db004c16a5d067110786d84b26a6b86b3b0639 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -30,6 +30,7 @@ #include "libipa/ccm.h" #include "libipa/fc_queue.h" #include "libipa/fixedpoint.h" +#include "libipa/gamma.h" #include "libipa/lsc.h" namespace libcamera { @@ -102,9 +103,7 @@ struct IPAActiveState { uint8_t sharpness; } filter; - struct { - double gamma; - } goc; + ipa::gamma::ActiveState gamma; struct { double lux; @@ -154,10 +153,7 @@ struct IPAFrameContext : public FrameContext { bool update; } filter; - struct { - double gamma; - bool update; - } goc; + ipa::gamma::FrameContext gamma; struct { uint32_t exposure;