| Message ID | 20260407-kbingham-awb-split-v1-2-a39af3f4dc20@ideasonboard.com |
|---|---|
| State | New |
| Headers | show |
| Series |
|
| Related | show |
On Tue, Apr 07, 2026 at 11:01:05PM +0100, Kieran Bingham wrote: > 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> > --- > 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 f5c88ea6f896ff8a7ffdc328e09a4d4aa99df5e4..05155c83d172d64609053ba940a4c12a2248bb04 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; The combined matrix is used by the CPU implementation too, aren't you breaking AWB there ? > - > - 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 34f7403a41d690cb3f0c271827ae2e915b6ea49d..8ccfacb46a59cedb5a0ad051d67f7c1f40af4b52 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 23747f78a6313503a46b61ed5bae6e7c178c5745..9a1992e219dd066945b3f46ec509f47a31590385 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; I'd name this wbGains or colourGains, that's more explicit. Same below. > 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 76ffc47a8a29f242c1fba88f32bd8db731edeee0..87e4e4915fe19679943fdcc3d213a0224b89065e 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 2ad258bca69fb8dff19e35d9239ebd7d350590ae..738036e649224f370bdf9a0cc59b399f8b1066de 100644 > --- a/src/libcamera/software_isp/debayer_egl.cpp > +++ b/src/libcamera/software_isp/debayer_egl.cpp > @@ -100,6 +100,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"); > @@ -113,6 +114,7 @@ int DebayerEGL::getShaderVariableLocations(void) > > LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ > << " tex_y " << textureUniformBayerDataIn_ > + << " awb " << awbUniformDataIn_ > << " ccm " << ccmUniformDataIn_ > << " blacklevel " << blackLevelUniformDataIn_ > << " gamma " << gammaUniformDataIn_ > @@ -481,6 +483,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 bdde676f2394e7298006c88bbec75917800af4ad..23ef99117fbd209246ae565141a2365c6a7b0a63 100644 > --- a/src/libcamera/software_isp/debayer_egl.h > +++ b/src/libcamera/software_isp/debayer_egl.h > @@ -97,6 +97,9 @@ private: > > GLint textureUniformBayerDataIn_; > > + /* Per-frame AWB gains */ All the uniforms below are per-frame parameters, I'd drop the "per-frame". Sorting the members in processing block order (in a separate patch) would make it easier to follow the code. > + GLint awbUniformDataIn_; > + > /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */ > GLint ccmUniformDataIn_; > >
Laurent Pinchart <laurent.pinchart@ideasonboard.com> writes: > On Tue, Apr 07, 2026 at 11:01:05PM +0100, Kieran Bingham wrote: >> 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> >> --- >> 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 f5c88ea6f896ff8a7ffdc328e09a4d4aa99df5e4..05155c83d172d64609053ba940a4c12a2248bb04 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; > > The combined matrix is used by the CPU implementation too, aren't you > breaking AWB there ? Yes, AWB is not applied in CPU ISP after this change. It gets applied again in "Apply gains in CPU ISP" patch; should the two be squashed? Other than that, the change itself looks good to me. >> - >> - 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 34f7403a41d690cb3f0c271827ae2e915b6ea49d..8ccfacb46a59cedb5a0ad051d67f7c1f40af4b52 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 23747f78a6313503a46b61ed5bae6e7c178c5745..9a1992e219dd066945b3f46ec509f47a31590385 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; > > I'd name this wbGains or colourGains, that's more explicit. Same below. > >> 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 76ffc47a8a29f242c1fba88f32bd8db731edeee0..87e4e4915fe19679943fdcc3d213a0224b89065e 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 2ad258bca69fb8dff19e35d9239ebd7d350590ae..738036e649224f370bdf9a0cc59b399f8b1066de 100644 >> --- a/src/libcamera/software_isp/debayer_egl.cpp >> +++ b/src/libcamera/software_isp/debayer_egl.cpp >> @@ -100,6 +100,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"); >> @@ -113,6 +114,7 @@ int DebayerEGL::getShaderVariableLocations(void) >> >> LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ >> << " tex_y " << textureUniformBayerDataIn_ >> + << " awb " << awbUniformDataIn_ >> << " ccm " << ccmUniformDataIn_ >> << " blacklevel " << blackLevelUniformDataIn_ >> << " gamma " << gammaUniformDataIn_ >> @@ -481,6 +483,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 bdde676f2394e7298006c88bbec75917800af4ad..23ef99117fbd209246ae565141a2365c6a7b0a63 100644 >> --- a/src/libcamera/software_isp/debayer_egl.h >> +++ b/src/libcamera/software_isp/debayer_egl.h >> @@ -97,6 +97,9 @@ private: >> >> GLint textureUniformBayerDataIn_; >> >> + /* Per-frame AWB gains */ > > All the uniforms below are per-frame parameters, I'd drop the > "per-frame". > > Sorting the members in processing block order (in a separate patch) > would make it easier to follow the code. > >> + GLint awbUniformDataIn_; >> + >> /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */ >> GLint ccmUniformDataIn_; >> >>
Quoting Milan Zamazal (2026-04-08 12:10:56) > Laurent Pinchart <laurent.pinchart@ideasonboard.com> writes: > > > On Tue, Apr 07, 2026 at 11:01:05PM +0100, Kieran Bingham wrote: > >> 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> > >> --- > >> 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 f5c88ea6f896ff8a7ffdc328e09a4d4aa99df5e4..05155c83d172d64609053ba940a4c12a2248bb04 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; > > > > The combined matrix is used by the CPU implementation too, aren't you > > breaking AWB there ? > > Yes, AWB is not applied in CPU ISP after this change. It gets applied > again in "Apply gains in CPU ISP" patch; should the two be squashed? > > Other than that, the change itself looks good to me. Is it safe to swap the order and put your patches first to maintain 'correctness' in bisection? > > >> - > >> - 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 34f7403a41d690cb3f0c271827ae2e915b6ea49d..8ccfacb46a59cedb5a0ad051d67f7c1f40af4b52 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 23747f78a6313503a46b61ed5bae6e7c178c5745..9a1992e219dd066945b3f46ec509f47a31590385 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; > > > > I'd name this wbGains or colourGains, that's more explicit. Same below. I'd like to introduce a full 'DigitalGain' control at somepoint (soon) which will be where/how awb will be applied. So I think it would get renamed then too. I could accept colourGains already for that I guess... > > > >> 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 76ffc47a8a29f242c1fba88f32bd8db731edeee0..87e4e4915fe19679943fdcc3d213a0224b89065e 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 2ad258bca69fb8dff19e35d9239ebd7d350590ae..738036e649224f370bdf9a0cc59b399f8b1066de 100644 > >> --- a/src/libcamera/software_isp/debayer_egl.cpp > >> +++ b/src/libcamera/software_isp/debayer_egl.cpp > >> @@ -100,6 +100,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"); > >> @@ -113,6 +114,7 @@ int DebayerEGL::getShaderVariableLocations(void) > >> > >> LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ > >> << " tex_y " << textureUniformBayerDataIn_ > >> + << " awb " << awbUniformDataIn_ > >> << " ccm " << ccmUniformDataIn_ > >> << " blacklevel " << blackLevelUniformDataIn_ > >> << " gamma " << gammaUniformDataIn_ > >> @@ -481,6 +483,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 bdde676f2394e7298006c88bbec75917800af4ad..23ef99117fbd209246ae565141a2365c6a7b0a63 100644 > >> --- a/src/libcamera/software_isp/debayer_egl.h > >> +++ b/src/libcamera/software_isp/debayer_egl.h > >> @@ -97,6 +97,9 @@ private: > >> > >> GLint textureUniformBayerDataIn_; > >> > >> + /* Per-frame AWB gains */ > > > > All the uniforms below are per-frame parameters, I'd drop the > > "per-frame". > > > > Sorting the members in processing block order (in a separate patch) > > would make it easier to follow the code. Yes, I think processing order is the most useful ordering. > > > >> + GLint awbUniformDataIn_; > >> + > >> /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */ > >> GLint ccmUniformDataIn_; > >> > >> >
On Wed, Apr 08, 2026 at 06:26:50PM +0100, Kieran Bingham wrote: > Quoting Milan Zamazal (2026-04-08 12:10:56) > > Laurent Pinchart <laurent.pinchart@ideasonboard.com> writes: > > > On Tue, Apr 07, 2026 at 11:01:05PM +0100, Kieran Bingham wrote: > > >> 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> > > >> --- > > >> 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 f5c88ea6f896ff8a7ffdc328e09a4d4aa99df5e4..05155c83d172d64609053ba940a4c12a2248bb04 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; > > > > > > The combined matrix is used by the CPU implementation too, aren't you > > > breaking AWB there ? > > > > Yes, AWB is not applied in CPU ISP after this change. It gets applied > > again in "Apply gains in CPU ISP" patch; should the two be squashed? > > > > Other than that, the change itself looks good to me. > > Is it safe to swap the order and put your patches first to maintain > 'correctness' in bisection? Then you will apply them twice. > > >> - > > >> - 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 34f7403a41d690cb3f0c271827ae2e915b6ea49d..8ccfacb46a59cedb5a0ad051d67f7c1f40af4b52 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 23747f78a6313503a46b61ed5bae6e7c178c5745..9a1992e219dd066945b3f46ec509f47a31590385 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; > > > > > > I'd name this wbGains or colourGains, that's more explicit. Same below. > > I'd like to introduce a full 'DigitalGain' control at somepoint (soon) > which will be where/how awb will be applied. So I think it would get > renamed then too. > > I could accept colourGains already for that I guess... > > > >> 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 76ffc47a8a29f242c1fba88f32bd8db731edeee0..87e4e4915fe19679943fdcc3d213a0224b89065e 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 2ad258bca69fb8dff19e35d9239ebd7d350590ae..738036e649224f370bdf9a0cc59b399f8b1066de 100644 > > >> --- a/src/libcamera/software_isp/debayer_egl.cpp > > >> +++ b/src/libcamera/software_isp/debayer_egl.cpp > > >> @@ -100,6 +100,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"); > > >> @@ -113,6 +114,7 @@ int DebayerEGL::getShaderVariableLocations(void) > > >> > > >> LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ > > >> << " tex_y " << textureUniformBayerDataIn_ > > >> + << " awb " << awbUniformDataIn_ > > >> << " ccm " << ccmUniformDataIn_ > > >> << " blacklevel " << blackLevelUniformDataIn_ > > >> << " gamma " << gammaUniformDataIn_ > > >> @@ -481,6 +483,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 bdde676f2394e7298006c88bbec75917800af4ad..23ef99117fbd209246ae565141a2365c6a7b0a63 100644 > > >> --- a/src/libcamera/software_isp/debayer_egl.h > > >> +++ b/src/libcamera/software_isp/debayer_egl.h > > >> @@ -97,6 +97,9 @@ private: > > >> > > >> GLint textureUniformBayerDataIn_; > > >> > > >> + /* Per-frame AWB gains */ > > > > > > All the uniforms below are per-frame parameters, I'd drop the > > > "per-frame". > > > > > > Sorting the members in processing block order (in a separate patch) > > > would make it easier to follow the code. > > Yes, I think processing order is the most useful ordering. > > > > > > >> + GLint awbUniformDataIn_; > > >> + > > >> /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */ > > >> GLint ccmUniformDataIn_; > > >> > > >>
Laurent Pinchart <laurent.pinchart@ideasonboard.com> writes: > On Wed, Apr 08, 2026 at 06:26:50PM +0100, Kieran Bingham wrote: >> Quoting Milan Zamazal (2026-04-08 12:10:56) >> > Laurent Pinchart <laurent.pinchart@ideasonboard.com> writes: > >> > > On Tue, Apr 07, 2026 at 11:01:05PM +0100, Kieran Bingham wrote: >> > >> 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> >> > >> --- >> > >> 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 f5c88ea6f896ff8a7ffdc328e09a4d4aa99df5e4..05155c83d172d64609053ba940a4c12a2248bb04 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; >> > > >> > > The combined matrix is used by the CPU implementation too, aren't you >> > > breaking AWB there ? >> > >> > Yes, AWB is not applied in CPU ISP after this change. It gets applied >> > again in "Apply gains in CPU ISP" patch; should the two be squashed? >> > >> > Other than that, the change itself looks good to me. >> >> Is it safe to swap the order and put your patches first to maintain >> 'correctness' in bisection? > > Then you will apply them twice. The black level patch can be applied separately and before this patch. The gains patch not, it must be applied at the same time as this change; it's like the GPU ISP changes here, which are also not easily separable. >> > >> - >> > >> - 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 34f7403a41d690cb3f0c271827ae2e915b6ea49d..8ccfacb46a59cedb5a0ad051d67f7c1f40af4b52 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 23747f78a6313503a46b61ed5bae6e7c178c5745..9a1992e219dd066945b3f46ec509f47a31590385 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; >> > > >> > > I'd name this wbGains or colourGains, that's more explicit. Same below. >> >> I'd like to introduce a full 'DigitalGain' control at somepoint (soon) >> which will be where/how awb will be applied. So I think it would get >> renamed then too. >> >> I could accept colourGains already for that I guess... >> >> > >> 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 76ffc47a8a29f242c1fba88f32bd8db731edeee0..87e4e4915fe19679943fdcc3d213a0224b89065e 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 2ad258bca69fb8dff19e35d9239ebd7d350590ae..738036e649224f370bdf9a0cc59b399f8b1066de 100644 >> > >> --- a/src/libcamera/software_isp/debayer_egl.cpp >> > >> +++ b/src/libcamera/software_isp/debayer_egl.cpp >> > >> @@ -100,6 +100,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"); >> > >> @@ -113,6 +114,7 @@ int DebayerEGL::getShaderVariableLocations(void) >> > >> >> > >> LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ >> > >> << " tex_y " << textureUniformBayerDataIn_ >> > >> + << " awb " << awbUniformDataIn_ >> > >> << " ccm " << ccmUniformDataIn_ >> > >> << " blacklevel " << blackLevelUniformDataIn_ >> > >> << " gamma " << gammaUniformDataIn_ >> > >> @@ -481,6 +483,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 bdde676f2394e7298006c88bbec75917800af4ad..23ef99117fbd209246ae565141a2365c6a7b0a63 100644 >> > >> --- a/src/libcamera/software_isp/debayer_egl.h >> > >> +++ b/src/libcamera/software_isp/debayer_egl.h >> > >> @@ -97,6 +97,9 @@ private: >> > >> >> > >> GLint textureUniformBayerDataIn_; >> > >> >> > >> + /* Per-frame AWB gains */ >> > > >> > > All the uniforms below are per-frame parameters, I'd drop the >> > > "per-frame". >> > > >> > > Sorting the members in processing block order (in a separate patch) >> > > would make it easier to follow the code. >> >> Yes, I think processing order is the most useful ordering. >> >> > > >> > >> + 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 f5c88ea6f896ff8a7ffdc328e09a4d4aa99df5e4..05155c83d172d64609053ba940a4c12a2248bb04 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 34f7403a41d690cb3f0c271827ae2e915b6ea49d..8ccfacb46a59cedb5a0ad051d67f7c1f40af4b52 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 23747f78a6313503a46b61ed5bae6e7c178c5745..9a1992e219dd066945b3f46ec509f47a31590385 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 76ffc47a8a29f242c1fba88f32bd8db731edeee0..87e4e4915fe19679943fdcc3d213a0224b89065e 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 2ad258bca69fb8dff19e35d9239ebd7d350590ae..738036e649224f370bdf9a0cc59b399f8b1066de 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -100,6 +100,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"); @@ -113,6 +114,7 @@ int DebayerEGL::getShaderVariableLocations(void) LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ << " tex_y " << textureUniformBayerDataIn_ + << " awb " << awbUniformDataIn_ << " ccm " << ccmUniformDataIn_ << " blacklevel " << blackLevelUniformDataIn_ << " gamma " << gammaUniformDataIn_ @@ -481,6 +483,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 bdde676f2394e7298006c88bbec75917800af4ad..23ef99117fbd209246ae565141a2365c6a7b0a63 100644 --- a/src/libcamera/software_isp/debayer_egl.h +++ b/src/libcamera/software_isp/debayer_egl.h @@ -97,6 +97,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_;
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> --- 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(-)