[v11,01/24] libcamera: software_isp: debayer: Latch contrastExp not contrast to debayer parameters
diff mbox series

Message ID 20260106170059.56193-2-bryan.odonoghue@linaro.org
State Accepted
Commit a1a6253ff93ebff81984e2eac778bad32f8c88c3
Headers show
Series
  • Add GLES 2.0 GPUISP to libcamera
Related show

Commit Message

Bryan O'Donoghue Jan. 6, 2026, 5 p.m. UTC
Pass contrastExp as calculated in lut to debayer params not the raw
contrast. This way we calculate contrastExp once per frame in lut and pass
the calculated value into the shaders, instead of passing contrast and
calculating contrastExp once per pixel in the shaders.

Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
 include/libcamera/internal/software_isp/debayer_params.h | 2 +-
 src/ipa/simple/algorithms/lut.cpp                        | 7 ++++---
 src/ipa/simple/ipa_context.h                             | 1 +
 src/libcamera/software_isp/debayer.cpp                   | 2 +-
 4 files changed, 7 insertions(+), 5 deletions(-)

Comments

Milan Zamazal Jan. 6, 2026, 8:34 p.m. UTC | #1
Bryan O'Donoghue <bryan.odonoghue@linaro.org> writes:

> Pass contrastExp as calculated in lut to debayer params not the raw
> contrast. This way we calculate contrastExp once per frame in lut and pass
> the calculated value into the shaders, instead of passing contrast and
> calculating contrastExp once per pixel in the shaders.
>
> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>

From v10:

Reviewed-by: Milan Zamazal <mzamazal@redhat.com>

> ---
>  include/libcamera/internal/software_isp/debayer_params.h | 2 +-
>  src/ipa/simple/algorithms/lut.cpp                        | 7 ++++---
>  src/ipa/simple/ipa_context.h                             | 1 +
>  src/libcamera/software_isp/debayer.cpp                   | 2 +-
>  4 files changed, 7 insertions(+), 5 deletions(-)
>
> diff --git a/include/libcamera/internal/software_isp/debayer_params.h b/include/libcamera/internal/software_isp/debayer_params.h
> index 8033f7d5b..256c7d43d 100644
> --- a/include/libcamera/internal/software_isp/debayer_params.h
> +++ b/include/libcamera/internal/software_isp/debayer_params.h
> @@ -59,7 +59,7 @@ struct DebayerParams {
>  	Matrix<float, 3, 3> ccm;
>  	RGB<float> blackLevel;
>  	float gamma;
> -	float contrast;
> +	double contrastExp;
>  };
>  
>  } /* namespace libcamera */
> diff --git a/src/ipa/simple/algorithms/lut.cpp b/src/ipa/simple/algorithms/lut.cpp
> index 9aaab54f1..7d015ac89 100644
> --- a/src/ipa/simple/algorithms/lut.cpp
> +++ b/src/ipa/simple/algorithms/lut.cpp
> @@ -60,12 +60,13 @@ void Lut::updateGammaTable(IPAContext &context)
>  	const auto blackLevel = context.activeState.blc.level;
>  	const unsigned int blackIndex = blackLevel * gammaTable.size() / 256;
>  	const auto contrast = context.activeState.knobs.contrast.value_or(1.0);
> +	/* Convert 0..2 to 0..infinity; avoid actual inifinity at tan(pi/2) */
> +	double contrastExp = tan(std::clamp(contrast * M_PI_4, 0.0, M_PI_2 - 0.00001));
>  
>  	const float divisor = gammaTable.size() - blackIndex - 1.0;
>  	for (unsigned int i = blackIndex; i < gammaTable.size(); i++) {
>  		double normalized = (i - blackIndex) / divisor;
>  		/* Convert 0..2 to 0..infinity; avoid actual inifinity at tan(pi/2) */
> -		double contrastExp = tan(std::clamp(contrast * M_PI_4, 0.0, M_PI_2 - 0.00001));
>  		/* Apply simple S-curve */
>  		if (normalized < 0.5)
>  			normalized = 0.5 * std::pow(normalized / 0.5, contrastExp);
> @@ -84,7 +85,7 @@ void Lut::updateGammaTable(IPAContext &context)
>  		  gammaTable[blackIndex]);
>  
>  	context.activeState.gamma.blackLevel = blackLevel;
> -	context.activeState.gamma.contrast = contrast;
> +	context.activeState.gamma.contrastExp = contrastExp;
>  }
>  
>  int16_t Lut::ccmValue(unsigned int i, float ccm) const
> @@ -149,7 +150,7 @@ void Lut::prepare(IPAContext &context,
>  	}
>  
>  	params->gamma = context.configuration.gamma;
> -	params->contrast = context.activeState.gamma.contrast;
> +	params->contrastExp = context.activeState.gamma.contrastExp;
>  }
>  
>  void Lut::process([[maybe_unused]] IPAContext &context,
> diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h
> index 26b60fb68..7837bb4dd 100644
> --- a/src/ipa/simple/ipa_context.h
> +++ b/src/ipa/simple/ipa_context.h
> @@ -59,6 +59,7 @@ struct IPAActiveState {
>  		std::array<double, kGammaLookupSize> gammaTable;
>  		uint8_t blackLevel;
>  		double contrast;
> +		double contrastExp;
>  	} gamma;
>  
>  	struct {
> diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp
> index b33f818a7..4cb5b4da4 100644
> --- a/src/libcamera/software_isp/debayer.cpp
> +++ b/src/libcamera/software_isp/debayer.cpp
> @@ -116,7 +116,7 @@ namespace libcamera {
>   */
>  
>  /**
> - * \var DebayerParams::contrast
> + * \var DebayerParams::contrastExp
>   * \brief Contrast value for GPUISP
>   */

Patch
diff mbox series

diff --git a/include/libcamera/internal/software_isp/debayer_params.h b/include/libcamera/internal/software_isp/debayer_params.h
index 8033f7d5b..256c7d43d 100644
--- a/include/libcamera/internal/software_isp/debayer_params.h
+++ b/include/libcamera/internal/software_isp/debayer_params.h
@@ -59,7 +59,7 @@  struct DebayerParams {
 	Matrix<float, 3, 3> ccm;
 	RGB<float> blackLevel;
 	float gamma;
-	float contrast;
+	double contrastExp;
 };
 
 } /* namespace libcamera */
diff --git a/src/ipa/simple/algorithms/lut.cpp b/src/ipa/simple/algorithms/lut.cpp
index 9aaab54f1..7d015ac89 100644
--- a/src/ipa/simple/algorithms/lut.cpp
+++ b/src/ipa/simple/algorithms/lut.cpp
@@ -60,12 +60,13 @@  void Lut::updateGammaTable(IPAContext &context)
 	const auto blackLevel = context.activeState.blc.level;
 	const unsigned int blackIndex = blackLevel * gammaTable.size() / 256;
 	const auto contrast = context.activeState.knobs.contrast.value_or(1.0);
+	/* Convert 0..2 to 0..infinity; avoid actual inifinity at tan(pi/2) */
+	double contrastExp = tan(std::clamp(contrast * M_PI_4, 0.0, M_PI_2 - 0.00001));
 
 	const float divisor = gammaTable.size() - blackIndex - 1.0;
 	for (unsigned int i = blackIndex; i < gammaTable.size(); i++) {
 		double normalized = (i - blackIndex) / divisor;
 		/* Convert 0..2 to 0..infinity; avoid actual inifinity at tan(pi/2) */
-		double contrastExp = tan(std::clamp(contrast * M_PI_4, 0.0, M_PI_2 - 0.00001));
 		/* Apply simple S-curve */
 		if (normalized < 0.5)
 			normalized = 0.5 * std::pow(normalized / 0.5, contrastExp);
@@ -84,7 +85,7 @@  void Lut::updateGammaTable(IPAContext &context)
 		  gammaTable[blackIndex]);
 
 	context.activeState.gamma.blackLevel = blackLevel;
-	context.activeState.gamma.contrast = contrast;
+	context.activeState.gamma.contrastExp = contrastExp;
 }
 
 int16_t Lut::ccmValue(unsigned int i, float ccm) const
@@ -149,7 +150,7 @@  void Lut::prepare(IPAContext &context,
 	}
 
 	params->gamma = context.configuration.gamma;
-	params->contrast = context.activeState.gamma.contrast;
+	params->contrastExp = context.activeState.gamma.contrastExp;
 }
 
 void Lut::process([[maybe_unused]] IPAContext &context,
diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h
index 26b60fb68..7837bb4dd 100644
--- a/src/ipa/simple/ipa_context.h
+++ b/src/ipa/simple/ipa_context.h
@@ -59,6 +59,7 @@  struct IPAActiveState {
 		std::array<double, kGammaLookupSize> gammaTable;
 		uint8_t blackLevel;
 		double contrast;
+		double contrastExp;
 	} gamma;
 
 	struct {
diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp
index b33f818a7..4cb5b4da4 100644
--- a/src/libcamera/software_isp/debayer.cpp
+++ b/src/libcamera/software_isp/debayer.cpp
@@ -116,7 +116,7 @@  namespace libcamera {
  */
 
 /**
- * \var DebayerParams::contrast
+ * \var DebayerParams::contrastExp
  * \brief Contrast value for GPUISP
  */