[{"id":39142,"web_url":"https://patchwork.libcamera.org/comment/39142/","msgid":"<178163515285.3598163.13835821380159104172@ping.linuxembedded.co.uk>","date":"2026-06-16T18:39:12","subject":"Re: [PATCH 06/10] ipa: ipu3: ToneMapping: Convert to use\n\tGammaAlgorithm","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Daniel Scally (2026-06-16 07:41:40)\n> Convert the IPU3 ToneMapping algorithm to use the new GammaAlgorithm\n> base class. This gives us configurable gamma via the tuning files and\n> at runtime using the Gamma control.\n\nI'm curious that we're handling gamma in a tone mapping block, but\nthat's where it was so lets not change that in this patch anyway.\n\n> \n> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>\n> ---\n>  src/ipa/ipu3/algorithms/tone_mapping.cpp | 73 +++++++++++++++++---------------\n>  src/ipa/ipu3/algorithms/tone_mapping.h   |  9 +++-\n>  src/ipa/ipu3/ipa_context.cpp             | 24 +++++------\n>  src/ipa/ipu3/ipa_context.h               |  8 ++--\n>  4 files changed, 60 insertions(+), 54 deletions(-)\n> \n> diff --git a/src/ipa/ipu3/algorithms/tone_mapping.cpp b/src/ipa/ipu3/algorithms/tone_mapping.cpp\n> index 160338c139448cc9a0bc1fe2400c335a96f68f73..2bc29bb9124dd8bd327ca3064b52c55637f56e7b 100644\n> --- a/src/ipa/ipu3/algorithms/tone_mapping.cpp\n> +++ b/src/ipa/ipu3/algorithms/tone_mapping.cpp\n> @@ -10,6 +10,8 @@\n>  #include <cmath>\n>  #include <string.h>\n>  \n> +#include <libcamera/base/span.h>\n> +\n>  /**\n>   * \\file tone_mapping.h\n>   */\n> @@ -27,10 +29,17 @@ namespace ipa::ipu3::algorithms {\n>   */\n>  \n>  ToneMapping::ToneMapping()\n> -       : gamma_(1.0)\n>  {\n>  }\n>  \n> +/**\n> + * \\copydoc libcamera::ipa::Algorithm::init\n> + */\n> +int ToneMapping::init(IPAContext &context, const ValueNode &tuningData)\n> +{\n> +       return gammaAlgo_.init(context.ctrlMap, tuningData);\n> +}\n> +\n>  /**\n>   * \\brief Configure the tone mapping given a configInfo\n>   * \\param[in] context The shared IPA context\n> @@ -41,12 +50,21 @@ ToneMapping::ToneMapping()\n>  int ToneMapping::configure(IPAContext &context,\n>                            [[maybe_unused]] const IPAConfigInfo &configInfo)\n>  {\n> -       /* Initialise tone mapping gamma value. */\n> -       context.activeState.toneMapping.gamma = 0.0;\n> -\n> +       gammaAlgo_.configure(context.activeState.gamma);\n>         return 0;\n>  }\n>  \n> +/**\n> + * \\copydoc libcamera::ipa::Algorithm::queueRequest\n> + */\n> +void ToneMapping::queueRequest(IPAContext &context, const uint32_t frame,\n> +                              IPAFrameContext &frameContext,\n> +                              const ControlList &controls)\n> +{\n> +       gammaAlgo_.queueRequest(context.activeState.gamma, frame,\n> +                               frameContext.gamma, controls);\n> +}\n> +\n>  /**\n>   * \\brief Fill in the parameter structure, and enable gamma control\n>   * \\param[in] context The shared IPA context\n> @@ -59,14 +77,21 @@ int ToneMapping::configure(IPAContext &context,\n>   */\n>  void ToneMapping::prepare([[maybe_unused]] IPAContext &context,\n>                           [[maybe_unused]] const uint32_t frame,\n> -                         [[maybe_unused]] IPAFrameContext &frameContext,\n> +                         IPAFrameContext &frameContext,\n>                           ipu3_uapi_params *params)\n>  {\n> -       /* Copy the calculated LUT into the parameters buffer. */\n> -       memcpy(params->acc_param.gamma.gc_lut.lut,\n> -              context.activeState.toneMapping.gammaCorrection.lut,\n> -              IPU3_UAPI_GAMMA_CORR_LUT_ENTRIES *\n> -              sizeof(params->acc_param.gamma.gc_lut.lut[0]));\n> +       if (!frameContext.gamma.update)\n> +               return;\n> +\n> +       /*\n> +        * Unfortunately necessary given the IPU3's gamma uAPI struct has the\n> +        * __packed attribute.\n> +        */\n> +       uint16_t *lutData = reinterpret_cast<uint16_t *>(\n> +               __builtin_assume_aligned(params->acc_param.gamma.gc_lut.lut, 16));\n> +       Span<uint16_t> lut {lutData, kNumLutNodes};\n> +\n> +       gammaAlgo_.prepare(frameContext.gamma, lut);\n>  \n>         /* Enable the custom gamma table. */\n>         params->use.acc_gamma = 1;\n> @@ -84,33 +109,13 @@ void ToneMapping::prepare([[maybe_unused]] IPAContext &context,\n>   * The tone mapping look up table is generated as an inverse power curve from\n>   * our gamma setting.\n>   */\n> -void ToneMapping::process(IPAContext &context, [[maybe_unused]] const uint32_t frame,\n> -                         [[maybe_unused]] IPAFrameContext &frameContext,\n> +void ToneMapping::process([[maybe_unused]] IPAContext &context,\n> +                         [[maybe_unused]] const uint32_t frame,\n> +                         IPAFrameContext &frameContext,\n>                           [[maybe_unused]] const ipu3_uapi_stats_3a *stats,\n>                           [[maybe_unused]] ControlList &metadata)\n>  {\n> -       /*\n> -        * Hardcode gamma to 1.1 as a default for now.\n> -        *\n> -        * \\todo Expose gamma control setting through the libcamera control API\n> -        */\n> -       gamma_ = 1.1;\n\nSooooooo good to drop all this.\n\n> -\n> -       if (context.activeState.toneMapping.gamma == gamma_)\n> -               return;\n> -\n> -       struct ipu3_uapi_gamma_corr_lut &lut =\n> -               context.activeState.toneMapping.gammaCorrection;\n> -\n> -       for (uint32_t i = 0; i < std::size(lut.lut); i++) {\n> -               double j = static_cast<double>(i) / (std::size(lut.lut) - 1);\n> -               double gamma = std::pow(j, 1.0 / gamma_);\n> -\n> -               /* The output value is expressed on 13 bits. */\n> -               lut.lut[i] = gamma * 8191;\n> -       }\n> -\n> -       context.activeState.toneMapping.gamma = gamma_;\n> +       gammaAlgo_.process(frameContext.gamma, metadata);\n>  }\n>  \n>  REGISTER_IPA_ALGORITHM(ToneMapping, \"ToneMapping\")\n> diff --git a/src/ipa/ipu3/algorithms/tone_mapping.h b/src/ipa/ipu3/algorithms/tone_mapping.h\n> index b2b380108e014b3d5ee7b93bcdd948dea4d2302d..db351a32b4383c4d607a2d6ee6a8fa3994a1d436 100644\n> --- a/src/ipa/ipu3/algorithms/tone_mapping.h\n> +++ b/src/ipa/ipu3/algorithms/tone_mapping.h\n> @@ -7,6 +7,8 @@\n>  \n>  #pragma once\n>  \n> +#include <libipa/gamma.h>\n> +\n>  #include \"algorithm.h\"\n>  \n>  namespace libcamera {\n> @@ -18,7 +20,11 @@ class ToneMapping : public Algorithm\n>  public:\n>         ToneMapping();\n>  \n> +       int init(IPAContext &context, const ValueNode &tuningData) override;\n>         int configure(IPAContext &context, const IPAConfigInfo &configInfo) override;\n> +       void queueRequest(IPAContext &context, const uint32_t frame,\n> +                         IPAFrameContext &frameContext,\n> +                         const ControlList &controls) override;\n>         void prepare(IPAContext &context, const uint32_t frame,\n>                      IPAFrameContext &frameContext, ipu3_uapi_params *params) override;\n>         void process(IPAContext &context, const uint32_t frame,\n> @@ -27,7 +33,8 @@ public:\n>                      ControlList &metadata) override;\n>  \n>  private:\n> -       double gamma_;\n> +       static constexpr unsigned int kNumLutNodes = IPU3_UAPI_GAMMA_CORR_LUT_ENTRIES;\n> +       GammaAlgorithm<kNumLutNodes, UQ<0, 13>> gammaAlgo_;\n\nWell, that all looks pretty clean to me.\n\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n>  };\n>  \n>  } /* namespace ipa::ipu3::algorithms */\n> diff --git a/src/ipa/ipu3/ipa_context.cpp b/src/ipa/ipu3/ipa_context.cpp\n> index dc43bc0877ed5c2e7287414e12667374f5ee1c80..7152d070d3ab1bc463fdaad437d5e1c1b87ce25c 100644\n> --- a/src/ipa/ipu3/ipa_context.cpp\n> +++ b/src/ipa/ipu3/ipa_context.cpp\n> @@ -119,6 +119,11 @@ namespace libcamera::ipa::ipu3 {\n>   * \\brief Active colour Correction Matrix parameters for the IPA\n>   */\n>  \n> +/**\n> + * \\var IPAActiveState::gamma\n> + * \\brief Active gamma correction parameters for the IPA\n> + */\n> +\n>  /**\n>   * \\var IPASessionConfiguration::sensor\n>   * \\brief Sensor-specific configuration of the IPA\n> @@ -154,20 +159,6 @@ namespace libcamera::ipa::ipu3 {\n>   * The gain should be adapted to the sensor specific gain code before applying.\n>   */\n>  \n> -/**\n> - * \\var IPAActiveState::toneMapping\n> - * \\brief Context for ToneMapping and Gamma control\n> - *\n> - * \\var IPAActiveState::toneMapping.gamma\n> - * \\brief Gamma value for the LUT\n> - *\n> - * \\var IPAActiveState::toneMapping.gammaCorrection\n> - * \\brief Per-pixel tone mapping implemented as a LUT\n> - *\n> - * The LUT structure is defined by the IPU3 kernel interface. See\n> - * <linux/intel-ipu3.h> struct ipu3_uapi_gamma_corr_lut for further details.\n> - */\n> -\n>  /**\n>   * \\struct IPAFrameContext\n>   * \\brief IPU3-specific FrameContext\n> @@ -192,4 +183,9 @@ namespace libcamera::ipa::ipu3 {\n>   * \\brief Per-frame colour Correction Matrix parameters for the IPA\n>   */\n>  \n> +/**\n> + * \\var IPAFrameContext::gamma\n> + * \\brief Per-frame gamma correction parameters for the IPA\n> + */\n> +\n>  } /* namespace libcamera::ipa::ipu3 */\n> diff --git a/src/ipa/ipu3/ipa_context.h b/src/ipa/ipu3/ipa_context.h\n> index be626d30d966b1bdaa322e5154f95f745f799976..1eaaac82da0e3ad5bed0749c39d9dad8c585cab0 100644\n> --- a/src/ipa/ipu3/ipa_context.h\n> +++ b/src/ipa/ipu3/ipa_context.h\n> @@ -18,6 +18,7 @@\n>  #include <libipa/awb.h>\n>  #include <libipa/ccm.h>\n>  #include <libipa/fc_queue.h>\n> +#include <libipa/gamma.h>\n>  \n>  namespace libcamera {\n>  \n> @@ -66,11 +67,7 @@ struct IPAActiveState {\n>  \n>         ipa::awb::ActiveState awb;\n>         ipa::ccm::ActiveState ccm;\n> -\n> -       struct {\n> -               double gamma;\n> -               struct ipu3_uapi_gamma_corr_lut gammaCorrection;\n> -       } toneMapping;\n> +       ipa::gamma::ActiveState gamma;\n>  };\n>  \n>  struct IPAFrameContext : public FrameContext {\n> @@ -81,6 +78,7 @@ struct IPAFrameContext : public FrameContext {\n>  \n>         ipa::awb::FrameContext awb;\n>         ipa::ccm::FrameContext ccm;\n> +       ipa::gamma::FrameContext gamma;\n>  };\n>  \n>  struct IPAContext {\n> \n> -- \n> 2.43.0\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id E1E4ABF415\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 16 Jun 2026 18:39:18 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 2A2B9626E0;\n\tTue, 16 Jun 2026 20:39:18 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 29BFD623CC\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 16 Jun 2026 20:39:16 +0200 (CEST)","from monstersaurus.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 5439F2EC;\n\tTue, 16 Jun 2026 20:38:42 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"QTwj6Ta2\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1781635122;\n\tbh=K4pU0ABe2xpZSnyaUUK1QCt9+opd3zMkBjFrBD/RVqQ=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=QTwj6Ta2Z0OJRIrhcacQtj0IkqSL0J1XkgUwuFEBkOeZXgG50QzfdPmpKUe1ZGqnW\n\t/MA1rY4CIfRqSpYUdt4m0sJZnBIaP1DuUd0E8UWuI6Pxm5Sx3rDbRPdX47Q19aKPbi\n\tr/vCqOdtoY/U9//77NkAhWHx1mYKnhkMMeEqyAgw=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20260616-ipu3-libipa-rework-v1-6-d4448b54f1d8@ideasonboard.com>","References":"<20260616-ipu3-libipa-rework-v1-0-d4448b54f1d8@ideasonboard.com>\n\t<20260616-ipu3-libipa-rework-v1-6-d4448b54f1d8@ideasonboard.com>","Subject":"Re: [PATCH 06/10] ipa: ipu3: ToneMapping: Convert to use\n\tGammaAlgorithm","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Daniel Scally <dan.scally@ideasonboard.com>","To":"Daniel Scally <dan.scally@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Tue, 16 Jun 2026 19:39:12 +0100","Message-ID":"<178163515285.3598163.13835821380159104172@ping.linuxembedded.co.uk>","User-Agent":"alot/0.9.1","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":39154,"web_url":"https://patchwork.libcamera.org/comment/39154/","msgid":"<ajJthrgmYwkJHhox@zed>","date":"2026-06-17T09:49:23","subject":"Re: [PATCH 06/10] ipa: ipu3: ToneMapping: Convert to use\n\tGammaAlgorithm","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"Hi Dan\n\nOn Tue, Jun 16, 2026 at 07:41:40AM +0100, Daniel Scally wrote:\n> Convert the IPU3 ToneMapping algorithm to use the new GammaAlgorithm\n> base class. This gives us configurable gamma via the tuning files and\n> at runtime using the Gamma control.\n>\n> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>\n> ---\n>  src/ipa/ipu3/algorithms/tone_mapping.cpp | 73 +++++++++++++++++---------------\n>  src/ipa/ipu3/algorithms/tone_mapping.h   |  9 +++-\n>  src/ipa/ipu3/ipa_context.cpp             | 24 +++++------\n>  src/ipa/ipu3/ipa_context.h               |  8 ++--\n>  4 files changed, 60 insertions(+), 54 deletions(-)\n>\n> diff --git a/src/ipa/ipu3/algorithms/tone_mapping.cpp b/src/ipa/ipu3/algorithms/tone_mapping.cpp\n> index 160338c139448cc9a0bc1fe2400c335a96f68f73..2bc29bb9124dd8bd327ca3064b52c55637f56e7b 100644\n> --- a/src/ipa/ipu3/algorithms/tone_mapping.cpp\n> +++ b/src/ipa/ipu3/algorithms/tone_mapping.cpp\n> @@ -10,6 +10,8 @@\n>  #include <cmath>\n>  #include <string.h>\n\nPlease check if headers inclusion has to be adjusted here and in the\nheader\n\nReviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n\n>\n> +#include <libcamera/base/span.h>\n> +\n>  /**\n>   * \\file tone_mapping.h\n>   */\n> @@ -27,10 +29,17 @@ namespace ipa::ipu3::algorithms {\n>   */\n>\n>  ToneMapping::ToneMapping()\n> -\t: gamma_(1.0)\n>  {\n>  }\n>\n> +/**\n> + * \\copydoc libcamera::ipa::Algorithm::init\n> + */\n> +int ToneMapping::init(IPAContext &context, const ValueNode &tuningData)\n> +{\n> +\treturn gammaAlgo_.init(context.ctrlMap, tuningData);\n> +}\n> +\n>  /**\n>   * \\brief Configure the tone mapping given a configInfo\n>   * \\param[in] context The shared IPA context\n> @@ -41,12 +50,21 @@ ToneMapping::ToneMapping()\n>  int ToneMapping::configure(IPAContext &context,\n>  \t\t\t   [[maybe_unused]] const IPAConfigInfo &configInfo)\n>  {\n> -\t/* Initialise tone mapping gamma value. */\n> -\tcontext.activeState.toneMapping.gamma = 0.0;\n> -\n> +\tgammaAlgo_.configure(context.activeState.gamma);\n>  \treturn 0;\n>  }\n>\n> +/**\n> + * \\copydoc libcamera::ipa::Algorithm::queueRequest\n> + */\n> +void ToneMapping::queueRequest(IPAContext &context, const uint32_t frame,\n> +\t\t\t       IPAFrameContext &frameContext,\n> +\t\t\t       const ControlList &controls)\n> +{\n> +\tgammaAlgo_.queueRequest(context.activeState.gamma, frame,\n> +\t\t\t\tframeContext.gamma, controls);\n> +}\n> +\n>  /**\n>   * \\brief Fill in the parameter structure, and enable gamma control\n>   * \\param[in] context The shared IPA context\n> @@ -59,14 +77,21 @@ int ToneMapping::configure(IPAContext &context,\n>   */\n>  void ToneMapping::prepare([[maybe_unused]] IPAContext &context,\n>  \t\t\t  [[maybe_unused]] const uint32_t frame,\n> -\t\t\t  [[maybe_unused]] IPAFrameContext &frameContext,\n> +\t\t\t  IPAFrameContext &frameContext,\n>  \t\t\t  ipu3_uapi_params *params)\n>  {\n> -\t/* Copy the calculated LUT into the parameters buffer. */\n> -\tmemcpy(params->acc_param.gamma.gc_lut.lut,\n> -\t       context.activeState.toneMapping.gammaCorrection.lut,\n> -\t       IPU3_UAPI_GAMMA_CORR_LUT_ENTRIES *\n> -\t       sizeof(params->acc_param.gamma.gc_lut.lut[0]));\n> +\tif (!frameContext.gamma.update)\n> +\t\treturn;\n> +\n> +\t/*\n> +\t * Unfortunately necessary given the IPU3's gamma uAPI struct has the\n> +\t * __packed attribute.\n> +\t */\n> +\tuint16_t *lutData = reinterpret_cast<uint16_t *>(\n> +\t\t__builtin_assume_aligned(params->acc_param.gamma.gc_lut.lut, 16));\n> +\tSpan<uint16_t> lut {lutData, kNumLutNodes};\n> +\n> +\tgammaAlgo_.prepare(frameContext.gamma, lut);\n>\n>  \t/* Enable the custom gamma table. */\n>  \tparams->use.acc_gamma = 1;\n> @@ -84,33 +109,13 @@ void ToneMapping::prepare([[maybe_unused]] IPAContext &context,\n>   * The tone mapping look up table is generated as an inverse power curve from\n>   * our gamma setting.\n>   */\n> -void ToneMapping::process(IPAContext &context, [[maybe_unused]] const uint32_t frame,\n> -\t\t\t  [[maybe_unused]] IPAFrameContext &frameContext,\n> +void ToneMapping::process([[maybe_unused]] IPAContext &context,\n> +\t\t\t  [[maybe_unused]] const uint32_t frame,\n> +\t\t\t  IPAFrameContext &frameContext,\n>  \t\t\t  [[maybe_unused]] const ipu3_uapi_stats_3a *stats,\n>  \t\t\t  [[maybe_unused]] ControlList &metadata)\n>  {\n> -\t/*\n> -\t * Hardcode gamma to 1.1 as a default for now.\n> -\t *\n> -\t * \\todo Expose gamma control setting through the libcamera control API\n> -\t */\n> -\tgamma_ = 1.1;\n> -\n> -\tif (context.activeState.toneMapping.gamma == gamma_)\n> -\t\treturn;\n> -\n> -\tstruct ipu3_uapi_gamma_corr_lut &lut =\n> -\t\tcontext.activeState.toneMapping.gammaCorrection;\n> -\n> -\tfor (uint32_t i = 0; i < std::size(lut.lut); i++) {\n> -\t\tdouble j = static_cast<double>(i) / (std::size(lut.lut) - 1);\n> -\t\tdouble gamma = std::pow(j, 1.0 / gamma_);\n> -\n> -\t\t/* The output value is expressed on 13 bits. */\n> -\t\tlut.lut[i] = gamma * 8191;\n> -\t}\n> -\n> -\tcontext.activeState.toneMapping.gamma = gamma_;\n> +\tgammaAlgo_.process(frameContext.gamma, metadata);\n>  }\n>\n>  REGISTER_IPA_ALGORITHM(ToneMapping, \"ToneMapping\")\n> diff --git a/src/ipa/ipu3/algorithms/tone_mapping.h b/src/ipa/ipu3/algorithms/tone_mapping.h\n> index b2b380108e014b3d5ee7b93bcdd948dea4d2302d..db351a32b4383c4d607a2d6ee6a8fa3994a1d436 100644\n> --- a/src/ipa/ipu3/algorithms/tone_mapping.h\n> +++ b/src/ipa/ipu3/algorithms/tone_mapping.h\n> @@ -7,6 +7,8 @@\n>\n>  #pragma once\n>\n> +#include <libipa/gamma.h>\n> +\n>  #include \"algorithm.h\"\n>\n>  namespace libcamera {\n> @@ -18,7 +20,11 @@ class ToneMapping : public Algorithm\n>  public:\n>  \tToneMapping();\n>\n> +\tint init(IPAContext &context, const ValueNode &tuningData) override;\n>  \tint configure(IPAContext &context, const IPAConfigInfo &configInfo) override;\n> +\tvoid queueRequest(IPAContext &context, const uint32_t frame,\n> +\t\t\t  IPAFrameContext &frameContext,\n> +\t\t\t  const ControlList &controls) override;\n>  \tvoid prepare(IPAContext &context, const uint32_t frame,\n>  \t\t     IPAFrameContext &frameContext, ipu3_uapi_params *params) override;\n>  \tvoid process(IPAContext &context, const uint32_t frame,\n> @@ -27,7 +33,8 @@ public:\n>  \t\t     ControlList &metadata) override;\n>\n>  private:\n> -\tdouble gamma_;\n> +\tstatic constexpr unsigned int kNumLutNodes = IPU3_UAPI_GAMMA_CORR_LUT_ENTRIES;\n> +\tGammaAlgorithm<kNumLutNodes, UQ<0, 13>> gammaAlgo_;\n>  };\n>\n>  } /* namespace ipa::ipu3::algorithms */\n> diff --git a/src/ipa/ipu3/ipa_context.cpp b/src/ipa/ipu3/ipa_context.cpp\n> index dc43bc0877ed5c2e7287414e12667374f5ee1c80..7152d070d3ab1bc463fdaad437d5e1c1b87ce25c 100644\n> --- a/src/ipa/ipu3/ipa_context.cpp\n> +++ b/src/ipa/ipu3/ipa_context.cpp\n> @@ -119,6 +119,11 @@ namespace libcamera::ipa::ipu3 {\n>   * \\brief Active colour Correction Matrix parameters for the IPA\n>   */\n>\n> +/**\n> + * \\var IPAActiveState::gamma\n> + * \\brief Active gamma correction parameters for the IPA\n> + */\n> +\n>  /**\n>   * \\var IPASessionConfiguration::sensor\n>   * \\brief Sensor-specific configuration of the IPA\n> @@ -154,20 +159,6 @@ namespace libcamera::ipa::ipu3 {\n>   * The gain should be adapted to the sensor specific gain code before applying.\n>   */\n>\n> -/**\n> - * \\var IPAActiveState::toneMapping\n> - * \\brief Context for ToneMapping and Gamma control\n> - *\n> - * \\var IPAActiveState::toneMapping.gamma\n> - * \\brief Gamma value for the LUT\n> - *\n> - * \\var IPAActiveState::toneMapping.gammaCorrection\n> - * \\brief Per-pixel tone mapping implemented as a LUT\n> - *\n> - * The LUT structure is defined by the IPU3 kernel interface. See\n> - * <linux/intel-ipu3.h> struct ipu3_uapi_gamma_corr_lut for further details.\n> - */\n> -\n>  /**\n>   * \\struct IPAFrameContext\n>   * \\brief IPU3-specific FrameContext\n> @@ -192,4 +183,9 @@ namespace libcamera::ipa::ipu3 {\n>   * \\brief Per-frame colour Correction Matrix parameters for the IPA\n>   */\n>\n> +/**\n> + * \\var IPAFrameContext::gamma\n> + * \\brief Per-frame gamma correction parameters for the IPA\n> + */\n> +\n>  } /* namespace libcamera::ipa::ipu3 */\n> diff --git a/src/ipa/ipu3/ipa_context.h b/src/ipa/ipu3/ipa_context.h\n> index be626d30d966b1bdaa322e5154f95f745f799976..1eaaac82da0e3ad5bed0749c39d9dad8c585cab0 100644\n> --- a/src/ipa/ipu3/ipa_context.h\n> +++ b/src/ipa/ipu3/ipa_context.h\n> @@ -18,6 +18,7 @@\n>  #include <libipa/awb.h>\n>  #include <libipa/ccm.h>\n>  #include <libipa/fc_queue.h>\n> +#include <libipa/gamma.h>\n>\n>  namespace libcamera {\n>\n> @@ -66,11 +67,7 @@ struct IPAActiveState {\n>\n>  \tipa::awb::ActiveState awb;\n>  \tipa::ccm::ActiveState ccm;\n> -\n> -\tstruct {\n> -\t\tdouble gamma;\n> -\t\tstruct ipu3_uapi_gamma_corr_lut gammaCorrection;\n> -\t} toneMapping;\n> +\tipa::gamma::ActiveState gamma;\n>  };\n>\n>  struct IPAFrameContext : public FrameContext {\n> @@ -81,6 +78,7 @@ struct IPAFrameContext : public FrameContext {\n>\n>  \tipa::awb::FrameContext awb;\n>  \tipa::ccm::FrameContext ccm;\n> +\tipa::gamma::FrameContext gamma;\n>  };\n>\n>  struct IPAContext {\n>\n> --\n> 2.43.0\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id BAE58BF415\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 17 Jun 2026 09:49:28 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id DAC1362720;\n\tWed, 17 Jun 2026 11:49:27 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 8333B60579\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 17 Jun 2026 11:49:26 +0200 (CEST)","from ideasonboard.com (mob-109-113-4-199.net.vodafone.it\n\t[109.113.4.199])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 5055A2F8;\n\tWed, 17 Jun 2026 11:48:52 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"oROw23UY\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1781689732;\n\tbh=Dw+1lVIjZVw7pXGdUGwkDkPsT7SaPchiN9/HvWXMgIY=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=oROw23UYgDzMJ7SvNPyY+VREU54VeKvUbkbMd6qUeB1KvXKA+5hr/OGvZTsuBk3/1\n\tz7F6EyJyfh+GDgvDundOoHM46Gi1d0IOtCB4FcnDiJosGpj15tsbjrD2WyWyntjdXX\n\t7KoQRtDPeks2dQRPEowZC4iRkQCx9LZaWiBE3ms4=","Date":"Wed, 17 Jun 2026 11:49:23 +0200","From":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","To":"Daniel Scally <dan.scally@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH 06/10] ipa: ipu3: ToneMapping: Convert to use\n\tGammaAlgorithm","Message-ID":"<ajJthrgmYwkJHhox@zed>","References":"<20260616-ipu3-libipa-rework-v1-0-d4448b54f1d8@ideasonboard.com>\n\t<20260616-ipu3-libipa-rework-v1-6-d4448b54f1d8@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20260616-ipu3-libipa-rework-v1-6-d4448b54f1d8@ideasonboard.com>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]