| Message ID | 20260615-libipa-algorithms-v1-3-e949c937422e@ideasonboard.com |
|---|---|
| State | Superseded |
| Headers | show |
| Series |
|
| Related | show |
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 ¶ms) > 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_; > >
Quoting Barnabás Pőcze (2026-06-15 15:29:44) > 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. Lets try a full commit message here: The AWB and CCM are currently combined into a single matrix which gets passed to the GPU and CPU ISP implementations. This unfortunately can cause saturation bugs between the AWB and CCM in areas of high brightness in a given scene, where one colour channel will saturate before the others unevenly. Remove AWB gains from the combined Matrix to allow a specific AWB Gain stage to be applied, which is then clamped equally on all channels according to the valid range of sensitivity from the sensor when the black level is removed. > > 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 ¶ms) > > 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_; > > > > >
Kieran Bingham <kieran.bingham@ideasonboard.com> writes: > Quoting Barnabás Pőcze (2026-06-15 15:29:44) >> 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. > > Lets try a full commit message here: > > > The AWB and CCM are currently combined into a single matrix which gets > passed to the GPU and CPU ISP implementations. This unfortunately can > cause saturation bugs between the AWB and CCM in areas of high > brightness in a given scene, where one colour channel will saturate > before the others unevenly. > > Remove AWB gains from the combined Matrix to allow a specific AWB Gain > stage to be applied, which is then clamped equally on all channels > according to the valid range of sensitivity from the sensor when the > black level is removed. With this added: Reviewed-by: Milan Zamazal <mzamazal@redhat.com> >> > 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 ¶ms) >> > 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_; >> > >> > >>
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 ¶ms) 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_;