[03/11] softisp: Split AWB from Combined Matrix
diff mbox series

Message ID 20260615-libipa-algorithms-v1-3-e949c937422e@ideasonboard.com
State New
Headers show
Series
  • ipa: libipa: Introduce libipa algorithms
Related show

Commit Message

Jacopo Mondi June 15, 2026, 2:05 p.m. UTC
From: Kieran Bingham <kieran.bingham@ideasonboard.com>

Move the AWB gains out of the combined matrix and pass
them directly to the EGL shaders.

Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
 src/ipa/simple/algorithms/awb.cpp          | 16 +++-------------
 src/ipa/simple/ipa_context.h               |  5 +----
 src/libcamera/shaders/bayer_1x_packed.frag |  4 ++++
 src/libcamera/shaders/bayer_unpacked.frag  |  4 ++++
 src/libcamera/software_isp/debayer_egl.cpp |  5 +++++
 src/libcamera/software_isp/debayer_egl.h   |  3 +++
 6 files changed, 20 insertions(+), 17 deletions(-)

Comments

Barnabás Pőcze June 15, 2026, 2:29 p.m. UTC | #1
Hi

2026. 06. 15. 16:05 keltezéssel, Jacopo Mondi írta:
> From: Kieran Bingham <kieran.bingham@ideasonboard.com>
> 
> Move the AWB gains out of the combined matrix and pass
> them directly to the EGL shaders.

It would be nice to have some explanation as to why
this is desirable/needed, what issue it solves (if any), etc.


> 
> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> ---
>   src/ipa/simple/algorithms/awb.cpp          | 16 +++-------------
>   src/ipa/simple/ipa_context.h               |  5 +----
>   src/libcamera/shaders/bayer_1x_packed.frag |  4 ++++
>   src/libcamera/shaders/bayer_unpacked.frag  |  4 ++++
>   src/libcamera/software_isp/debayer_egl.cpp |  5 +++++
>   src/libcamera/software_isp/debayer_egl.h   |  3 +++
>   6 files changed, 20 insertions(+), 17 deletions(-)
> 
> diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp
> index f5c88ea6f896..05155c83d172 100644
> --- a/src/ipa/simple/algorithms/awb.cpp
> +++ b/src/ipa/simple/algorithms/awb.cpp
> @@ -38,15 +38,8 @@ void Awb::prepare(IPAContext &context,
>   		  DebayerParams *params)
>   {
>   	auto &gains = context.activeState.awb.gains;
> -	Matrix<float, 3, 3> gainMatrix = { { gains.r(), 0, 0,
> -					     0, gains.g(), 0,
> -					     0, 0, gains.b() } };
> -	context.activeState.combinedMatrix =
> -		gainMatrix * context.activeState.combinedMatrix;
> -
> -	frameContext.gains.red = gains.r();
> -	frameContext.gains.blue = gains.b();
>   
> +	frameContext.gains = gains;
>   	params->gains = gains;
>   }
>   
> @@ -59,11 +52,8 @@ void Awb::process(IPAContext &context,
>   	const SwIspStats::Histogram &histogram = stats->yHistogram;
>   	const uint8_t blackLevel = context.activeState.blc.level;
>   
> -	const float mdGains[] = {
> -		static_cast<float>(frameContext.gains.red),
> -		static_cast<float>(frameContext.gains.blue)
> -	};
> -	metadata.set(controls::ColourGains, mdGains);
> +	metadata.set(controls::ColourGains, { frameContext.gains.r(),
> +					      frameContext.gains.b() });
>   
>   	if (!stats->valid)
>   		return;
> diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h
> index 34f7403a41d6..8ccfacb46a59 100644
> --- a/src/ipa/simple/ipa_context.h
> +++ b/src/ipa/simple/ipa_context.h
> @@ -71,10 +71,7 @@ struct IPAFrameContext : public FrameContext {
>   		double gain;
>   	} sensor;
>   
> -	struct {
> -		double red;
> -		double blue;
> -	} gains;
> +	RGB<float> gains;
>   
>   	float gamma;
>   	std::optional<float> contrast;
> diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag
> index 23747f78a631..9a1992e219dd 100644
> --- a/src/libcamera/shaders/bayer_1x_packed.frag
> +++ b/src/libcamera/shaders/bayer_1x_packed.frag
> @@ -65,6 +65,7 @@ uniform vec2 tex_step;
>   uniform vec2 tex_bayer_first_red;
>   
>   uniform sampler2D tex_y;
> +uniform vec3 awb;
>   uniform mat3 ccm;
>   uniform vec3 blacklevel;
>   uniform float gamma;
> @@ -227,6 +228,9 @@ void main(void)
>   
>   	rgb = rgb - blacklevel;
>   
> +	/* Apply AWB gains, and saturate each channel at sensor range */
> +	rgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel);
> +
>   	/*
>   	 *   CCM is a 3x3 in the format
>   	 *
> diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag
> index 1b85196ae161..2def33c82c8e 100644
> --- a/src/libcamera/shaders/bayer_unpacked.frag
> +++ b/src/libcamera/shaders/bayer_unpacked.frag
> @@ -24,6 +24,7 @@ uniform sampler2D       tex_y;
>   varying vec4            center;
>   varying vec4            yCoord;
>   varying vec4            xCoord;
> +uniform vec3            awb;
>   uniform mat3            ccm;
>   uniform vec3            blacklevel;
>   uniform float           gamma;
> @@ -130,6 +131,9 @@ void main(void) {
>   
>       rgb = rgb - blacklevel;
>   
> +    /* Apply AWB gains, and saturate each channel at sensor range */
> +    rgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel);
> +
>       /*
>        *   CCM is a 3x3 in the format
>        *
> diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp
> index fd8de3942aa3..227f698a1fac 100644
> --- a/src/libcamera/software_isp/debayer_egl.cpp
> +++ b/src/libcamera/software_isp/debayer_egl.cpp
> @@ -115,6 +115,7 @@ int DebayerEGL::getShaderVariableLocations(void)
>   	attributeTexture_ = glGetAttribLocation(programId_, "textureIn");
>   
>   	textureUniformBayerDataIn_ = glGetUniformLocation(programId_, "tex_y");
> +	awbUniformDataIn_ = glGetUniformLocation(programId_, "awb");
>   	ccmUniformDataIn_ = glGetUniformLocation(programId_, "ccm");
>   	blackLevelUniformDataIn_ = glGetUniformLocation(programId_, "blacklevel");
>   	gammaUniformDataIn_ = glGetUniformLocation(programId_, "gamma");
> @@ -128,6 +129,7 @@ int DebayerEGL::getShaderVariableLocations(void)
>   
>   	LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_
>   			    << " tex_y " << textureUniformBayerDataIn_
> +			    << " awb " << awbUniformDataIn_
>   			    << " ccm " << ccmUniformDataIn_
>   			    << " blacklevel " << blackLevelUniformDataIn_
>   			    << " gamma " << gammaUniformDataIn_
> @@ -502,6 +504,9 @@ void DebayerEGL::setShaderVariableValues(const DebayerParams &params)
>   	glUniform3f(blackLevelUniformDataIn_, params.blackLevel[0], params.blackLevel[1], params.blackLevel[2]);
>   	LOG(Debayer, Debug) << " blackLevelUniformDataIn_ " << blackLevelUniformDataIn_ << " data " << params.blackLevel;
>   
> +	glUniform3f(awbUniformDataIn_, params.gains[0], params.gains[1], params.gains[2]);
> +	LOG(Debayer, Debug) << " awbUniformDataIn_ " << awbUniformDataIn_ << " data " << params.gains;
> +
>   	/*
>   	 * Gamma
>   	 */
> diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h
> index 943410fdd1fc..43038b45a109 100644
> --- a/src/libcamera/software_isp/debayer_egl.h
> +++ b/src/libcamera/software_isp/debayer_egl.h
> @@ -90,6 +90,9 @@ private:
>   
>   	GLint textureUniformBayerDataIn_;
>   
> +	/* Per-frame AWB gains */
> +	GLint awbUniformDataIn_;
> +
>   	/* Represent per-frame CCM as a uniform vector of floats 3 x 3 */
>   	GLint ccmUniformDataIn_;
>   
>

Patch
diff mbox series

diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp
index f5c88ea6f896..05155c83d172 100644
--- a/src/ipa/simple/algorithms/awb.cpp
+++ b/src/ipa/simple/algorithms/awb.cpp
@@ -38,15 +38,8 @@  void Awb::prepare(IPAContext &context,
 		  DebayerParams *params)
 {
 	auto &gains = context.activeState.awb.gains;
-	Matrix<float, 3, 3> gainMatrix = { { gains.r(), 0, 0,
-					     0, gains.g(), 0,
-					     0, 0, gains.b() } };
-	context.activeState.combinedMatrix =
-		gainMatrix * context.activeState.combinedMatrix;
-
-	frameContext.gains.red = gains.r();
-	frameContext.gains.blue = gains.b();
 
+	frameContext.gains = gains;
 	params->gains = gains;
 }
 
@@ -59,11 +52,8 @@  void Awb::process(IPAContext &context,
 	const SwIspStats::Histogram &histogram = stats->yHistogram;
 	const uint8_t blackLevel = context.activeState.blc.level;
 
-	const float mdGains[] = {
-		static_cast<float>(frameContext.gains.red),
-		static_cast<float>(frameContext.gains.blue)
-	};
-	metadata.set(controls::ColourGains, mdGains);
+	metadata.set(controls::ColourGains, { frameContext.gains.r(),
+					      frameContext.gains.b() });
 
 	if (!stats->valid)
 		return;
diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h
index 34f7403a41d6..8ccfacb46a59 100644
--- a/src/ipa/simple/ipa_context.h
+++ b/src/ipa/simple/ipa_context.h
@@ -71,10 +71,7 @@  struct IPAFrameContext : public FrameContext {
 		double gain;
 	} sensor;
 
-	struct {
-		double red;
-		double blue;
-	} gains;
+	RGB<float> gains;
 
 	float gamma;
 	std::optional<float> contrast;
diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag
index 23747f78a631..9a1992e219dd 100644
--- a/src/libcamera/shaders/bayer_1x_packed.frag
+++ b/src/libcamera/shaders/bayer_1x_packed.frag
@@ -65,6 +65,7 @@  uniform vec2 tex_step;
 uniform vec2 tex_bayer_first_red;
 
 uniform sampler2D tex_y;
+uniform vec3 awb;
 uniform mat3 ccm;
 uniform vec3 blacklevel;
 uniform float gamma;
@@ -227,6 +228,9 @@  void main(void)
 
 	rgb = rgb - blacklevel;
 
+	/* Apply AWB gains, and saturate each channel at sensor range */
+	rgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel);
+
 	/*
 	 *   CCM is a 3x3 in the format
 	 *
diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag
index 1b85196ae161..2def33c82c8e 100644
--- a/src/libcamera/shaders/bayer_unpacked.frag
+++ b/src/libcamera/shaders/bayer_unpacked.frag
@@ -24,6 +24,7 @@  uniform sampler2D       tex_y;
 varying vec4            center;
 varying vec4            yCoord;
 varying vec4            xCoord;
+uniform vec3            awb;
 uniform mat3            ccm;
 uniform vec3            blacklevel;
 uniform float           gamma;
@@ -130,6 +131,9 @@  void main(void) {
 
     rgb = rgb - blacklevel;
 
+    /* Apply AWB gains, and saturate each channel at sensor range */
+    rgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel);
+
     /*
      *   CCM is a 3x3 in the format
      *
diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp
index fd8de3942aa3..227f698a1fac 100644
--- a/src/libcamera/software_isp/debayer_egl.cpp
+++ b/src/libcamera/software_isp/debayer_egl.cpp
@@ -115,6 +115,7 @@  int DebayerEGL::getShaderVariableLocations(void)
 	attributeTexture_ = glGetAttribLocation(programId_, "textureIn");
 
 	textureUniformBayerDataIn_ = glGetUniformLocation(programId_, "tex_y");
+	awbUniformDataIn_ = glGetUniformLocation(programId_, "awb");
 	ccmUniformDataIn_ = glGetUniformLocation(programId_, "ccm");
 	blackLevelUniformDataIn_ = glGetUniformLocation(programId_, "blacklevel");
 	gammaUniformDataIn_ = glGetUniformLocation(programId_, "gamma");
@@ -128,6 +129,7 @@  int DebayerEGL::getShaderVariableLocations(void)
 
 	LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_
 			    << " tex_y " << textureUniformBayerDataIn_
+			    << " awb " << awbUniformDataIn_
 			    << " ccm " << ccmUniformDataIn_
 			    << " blacklevel " << blackLevelUniformDataIn_
 			    << " gamma " << gammaUniformDataIn_
@@ -502,6 +504,9 @@  void DebayerEGL::setShaderVariableValues(const DebayerParams &params)
 	glUniform3f(blackLevelUniformDataIn_, params.blackLevel[0], params.blackLevel[1], params.blackLevel[2]);
 	LOG(Debayer, Debug) << " blackLevelUniformDataIn_ " << blackLevelUniformDataIn_ << " data " << params.blackLevel;
 
+	glUniform3f(awbUniformDataIn_, params.gains[0], params.gains[1], params.gains[2]);
+	LOG(Debayer, Debug) << " awbUniformDataIn_ " << awbUniformDataIn_ << " data " << params.gains;
+
 	/*
 	 * Gamma
 	 */
diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h
index 943410fdd1fc..43038b45a109 100644
--- a/src/libcamera/software_isp/debayer_egl.h
+++ b/src/libcamera/software_isp/debayer_egl.h
@@ -90,6 +90,9 @@  private:
 
 	GLint textureUniformBayerDataIn_;
 
+	/* Per-frame AWB gains */
+	GLint awbUniformDataIn_;
+
 	/* Represent per-frame CCM as a uniform vector of floats 3 x 3 */
 	GLint ccmUniformDataIn_;