| Message ID | 20260616-ipu3-libipa-rework-v1-8-d4448b54f1d8@ideasonboard.com |
|---|---|
| State | Superseded |
| Headers | show |
| Series |
|
| Related | show |
Quoting Daniel Scally (2026-06-16 07:41:42) > 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. > > Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com> > --- > src/ipa/rkisp1/algorithms/goc.cpp | 49 +++++++++++---------------------------- > src/ipa/rkisp1/algorithms/goc.h | 5 +++- > src/ipa/rkisp1/ipa_context.h | 10 +++----- > 3 files changed, 21 insertions(+), 43 deletions(-) > > diff --git a/src/ipa/rkisp1/algorithms/goc.cpp b/src/ipa/rkisp1/algorithms/goc.cpp > index e8f64bf3d5e028c2013d37b7ef9fe90b737fad5f..1afd7fb9538d85f771c5b743b856a4963ec8665c 100644 > --- a/src/ipa/rkisp1/algorithms/goc.cpp > +++ b/src/ipa/rkisp1/algorithms/goc.cpp > @@ -9,7 +9,7 @@ > #include <cmath> > > #include <libcamera/base/log.h> > -#include <libcamera/base/utils.h> > +#include <libcamera/base/span.h> > > #include <libcamera/control_ids.h> > > @@ -44,6 +44,7 @@ namespace ipa::rkisp1::algorithms { > 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 +58,12 @@ int GammaOutCorrection::init(IPAContext &context, const ValueNode &tuningData) > return -EINVAL; > } > > - defaultGamma_ = tuningData["gamma"].get<double>(kDefaultGamma); > - context.ctrlMap[&controls::Gamma] = ControlInfo(0.1f, 10.0f, defaultGamma_); > + std::array<unsigned int, kNumLutSegments> 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 +72,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 +83,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 +98,14 @@ 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<unsigned int, RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10> segments = { > - 64, 64, 64, 64, 128, 128, 128, 128, 256, > - 256, 256, 512, 512, 512, 512, 512, 0 > - }; > - > auto config = params->block<BlockType::Goc>(); > 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<uint16_t> lut{ config->gamma_y }; > + gammaAlgo_.prepare(frameContext.gamma, lut); > config->mode = RKISP1_CIF_ISP_GOC_MODE_LOGARITHMIC; > } > > @@ -139,7 +118,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..f7059d206c935fa72195f36091cf953e5f2413e1 100644 > --- a/src/ipa/rkisp1/algorithms/goc.h > +++ b/src/ipa/rkisp1/algorithms/goc.h > @@ -9,6 +9,9 @@ > > #include "algorithm.h" > > +#include <libipa/fixedpoint.h> > +#include <libipa/gamma.h> > + > namespace libcamera { > > namespace ipa::rkisp1::algorithms { > @@ -35,7 +38,7 @@ public: > ControlList &metadata) override; > > private: > - float defaultGamma_; > + GammaAlgorithm<RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10, UQ<0, 10>> gammaAlgo_; Q and UQ seemed to hurt so much making them - so I'm /really/ glad to see how useful they're becoming as a way to convey units and precision through these types. > }; > > } /* namespace ipa::rkisp1::algorithms */ > diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h > index 005f4102b4f6d465fd370c20060331a4f3b3a943..03be79085052d5161ec57d97fe9600f4bf7e93c4 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 { > @@ -124,9 +125,7 @@ struct IPAActiveState { > uint8_t sharpness; > } filter; > > - struct { > - double gamma; > - } goc; > + ipa::gamma::ActiveState gamma; > > struct { > double lux; > @@ -190,10 +189,7 @@ struct IPAFrameContext : public FrameContext { > bool update; > } filter; > > - struct { > - double gamma; > - bool update; > - } goc; > + ipa::gamma::FrameContext gamma; Oh, I'm at the bottom already. Well that was easy ... Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> > > struct { > uint32_t exposure; > > -- > 2.43.0 >
Hi Dan On Tue, Jun 16, 2026 at 07:41:42AM +0100, Daniel Scally wrote: > 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. > > Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com> > --- > src/ipa/rkisp1/algorithms/goc.cpp | 49 +++++++++++---------------------------- > src/ipa/rkisp1/algorithms/goc.h | 5 +++- > src/ipa/rkisp1/ipa_context.h | 10 +++----- > 3 files changed, 21 insertions(+), 43 deletions(-) > > diff --git a/src/ipa/rkisp1/algorithms/goc.cpp b/src/ipa/rkisp1/algorithms/goc.cpp > index e8f64bf3d5e028c2013d37b7ef9fe90b737fad5f..1afd7fb9538d85f771c5b743b856a4963ec8665c 100644 > --- a/src/ipa/rkisp1/algorithms/goc.cpp > +++ b/src/ipa/rkisp1/algorithms/goc.cpp > @@ -9,7 +9,7 @@ > #include <cmath> > > #include <libcamera/base/log.h> > -#include <libcamera/base/utils.h> > +#include <libcamera/base/span.h> > > #include <libcamera/control_ids.h> > > @@ -44,6 +44,7 @@ namespace ipa::rkisp1::algorithms { I think the comment /** * \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 */ Can now be simplified/dropped > 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 +58,12 @@ int GammaOutCorrection::init(IPAContext &context, const ValueNode &tuningData) > return -EINVAL; > } > > - defaultGamma_ = tuningData["gamma"].get<double>(kDefaultGamma); > - context.ctrlMap[&controls::Gamma] = ControlInfo(0.1f, 10.0f, defaultGamma_); > + std::array<unsigned int, kNumLutSegments> 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 +72,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 +83,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 +98,14 @@ 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<unsigned int, RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10> segments = { > - 64, 64, 64, 64, 128, 128, 128, 128, 256, > - 256, 256, 512, 512, 512, 512, 512, 0 > - }; > - > auto config = params->block<BlockType::Goc>(); > 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<uint16_t> lut{ config->gamma_y }; > + gammaAlgo_.prepare(frameContext.gamma, lut); > config->mode = RKISP1_CIF_ISP_GOC_MODE_LOGARITHMIC; > } > > @@ -139,7 +118,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..f7059d206c935fa72195f36091cf953e5f2413e1 100644 > --- a/src/ipa/rkisp1/algorithms/goc.h > +++ b/src/ipa/rkisp1/algorithms/goc.h > @@ -9,6 +9,9 @@ > > #include "algorithm.h" > > +#include <libipa/fixedpoint.h> > +#include <libipa/gamma.h> > + Same comment as per the previous patch: please check headers > namespace libcamera { > > namespace ipa::rkisp1::algorithms { > @@ -35,7 +38,7 @@ public: > ControlList &metadata) override; > > private: > - float defaultGamma_; > + GammaAlgorithm<RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10, UQ<0, 10>> gammaAlgo_; > }; > > } /* namespace ipa::rkisp1::algorithms */ > diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h > index 005f4102b4f6d465fd370c20060331a4f3b3a943..03be79085052d5161ec57d97fe9600f4bf7e93c4 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 { > @@ -124,9 +125,7 @@ struct IPAActiveState { > uint8_t sharpness; > } filter; > > - struct { > - double gamma; > - } goc; > + ipa::gamma::ActiveState gamma; > > struct { > double lux; > @@ -190,10 +189,7 @@ struct IPAFrameContext : public FrameContext { > bool update; > } filter; > > - struct { > - double gamma; > - bool update; > - } goc; > + ipa::gamma::FrameContext gamma; > > struct { > uint32_t exposure; > All minors Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> > -- > 2.43.0 >
diff --git a/src/ipa/rkisp1/algorithms/goc.cpp b/src/ipa/rkisp1/algorithms/goc.cpp index e8f64bf3d5e028c2013d37b7ef9fe90b737fad5f..1afd7fb9538d85f771c5b743b856a4963ec8665c 100644 --- a/src/ipa/rkisp1/algorithms/goc.cpp +++ b/src/ipa/rkisp1/algorithms/goc.cpp @@ -9,7 +9,7 @@ #include <cmath> #include <libcamera/base/log.h> -#include <libcamera/base/utils.h> +#include <libcamera/base/span.h> #include <libcamera/control_ids.h> @@ -44,6 +44,7 @@ namespace ipa::rkisp1::algorithms { 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 +58,12 @@ int GammaOutCorrection::init(IPAContext &context, const ValueNode &tuningData) return -EINVAL; } - defaultGamma_ = tuningData["gamma"].get<double>(kDefaultGamma); - context.ctrlMap[&controls::Gamma] = ControlInfo(0.1f, 10.0f, defaultGamma_); + std::array<unsigned int, kNumLutSegments> 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 +72,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 +83,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 +98,14 @@ 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<unsigned int, RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10> segments = { - 64, 64, 64, 64, 128, 128, 128, 128, 256, - 256, 256, 512, 512, 512, 512, 512, 0 - }; - auto config = params->block<BlockType::Goc>(); 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<uint16_t> lut{ config->gamma_y }; + gammaAlgo_.prepare(frameContext.gamma, lut); config->mode = RKISP1_CIF_ISP_GOC_MODE_LOGARITHMIC; } @@ -139,7 +118,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..f7059d206c935fa72195f36091cf953e5f2413e1 100644 --- a/src/ipa/rkisp1/algorithms/goc.h +++ b/src/ipa/rkisp1/algorithms/goc.h @@ -9,6 +9,9 @@ #include "algorithm.h" +#include <libipa/fixedpoint.h> +#include <libipa/gamma.h> + namespace libcamera { namespace ipa::rkisp1::algorithms { @@ -35,7 +38,7 @@ public: ControlList &metadata) override; private: - float defaultGamma_; + GammaAlgorithm<RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10, UQ<0, 10>> gammaAlgo_; }; } /* namespace ipa::rkisp1::algorithms */ diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index 005f4102b4f6d465fd370c20060331a4f3b3a943..03be79085052d5161ec57d97fe9600f4bf7e93c4 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 { @@ -124,9 +125,7 @@ struct IPAActiveState { uint8_t sharpness; } filter; - struct { - double gamma; - } goc; + ipa::gamma::ActiveState gamma; struct { double lux; @@ -190,10 +189,7 @@ struct IPAFrameContext : public FrameContext { bool update; } filter; - struct { - double gamma; - bool update; - } goc; + ipa::gamma::FrameContext gamma; struct { uint32_t exposure;
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. Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com> --- src/ipa/rkisp1/algorithms/goc.cpp | 49 +++++++++++---------------------------- src/ipa/rkisp1/algorithms/goc.h | 5 +++- src/ipa/rkisp1/ipa_context.h | 10 +++----- 3 files changed, 21 insertions(+), 43 deletions(-)