[{"id":38522,"web_url":"https://patchwork.libcamera.org/comment/38522/","msgid":"<20260408000101.GM1268443@killaraus.ideasonboard.com>","date":"2026-04-08T00:01:01","subject":"Re: [PATCH 02/13] softisp: Split AWB from Combined Matrix","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Tue, Apr 07, 2026 at 11:01:05PM +0100, Kieran Bingham wrote:\n> Move the AWB gains out of the combined matrix and pass\n> them directly to the EGL shaders.\n> \n> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> ---\n>  src/ipa/simple/algorithms/awb.cpp          | 16 +++-------------\n>  src/ipa/simple/ipa_context.h               |  5 +----\n>  src/libcamera/shaders/bayer_1x_packed.frag |  4 ++++\n>  src/libcamera/shaders/bayer_unpacked.frag  |  4 ++++\n>  src/libcamera/software_isp/debayer_egl.cpp |  5 +++++\n>  src/libcamera/software_isp/debayer_egl.h   |  3 +++\n>  6 files changed, 20 insertions(+), 17 deletions(-)\n> \n> diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp\n> index f5c88ea6f896ff8a7ffdc328e09a4d4aa99df5e4..05155c83d172d64609053ba940a4c12a2248bb04 100644\n> --- a/src/ipa/simple/algorithms/awb.cpp\n> +++ b/src/ipa/simple/algorithms/awb.cpp\n> @@ -38,15 +38,8 @@ void Awb::prepare(IPAContext &context,\n>  \t\t  DebayerParams *params)\n>  {\n>  \tauto &gains = context.activeState.awb.gains;\n> -\tMatrix<float, 3, 3> gainMatrix = { { gains.r(), 0, 0,\n> -\t\t\t\t\t     0, gains.g(), 0,\n> -\t\t\t\t\t     0, 0, gains.b() } };\n> -\tcontext.activeState.combinedMatrix =\n> -\t\tgainMatrix * context.activeState.combinedMatrix;\n\nThe combined matrix is used by the CPU implementation too, aren't you\nbreaking AWB there ?\n\n> -\n> -\tframeContext.gains.red = gains.r();\n> -\tframeContext.gains.blue = gains.b();\n>  \n> +\tframeContext.gains = gains;\n>  \tparams->gains = gains;\n>  }\n>  \n> @@ -59,11 +52,8 @@ void Awb::process(IPAContext &context,\n>  \tconst SwIspStats::Histogram &histogram = stats->yHistogram;\n>  \tconst uint8_t blackLevel = context.activeState.blc.level;\n>  \n> -\tconst float mdGains[] = {\n> -\t\tstatic_cast<float>(frameContext.gains.red),\n> -\t\tstatic_cast<float>(frameContext.gains.blue)\n> -\t};\n> -\tmetadata.set(controls::ColourGains, mdGains);\n> +\tmetadata.set(controls::ColourGains, { frameContext.gains.r(),\n> +\t\t\t\t\t      frameContext.gains.b() });\n>  \n>  \tif (!stats->valid)\n>  \t\treturn;\n> diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h\n> index 34f7403a41d690cb3f0c271827ae2e915b6ea49d..8ccfacb46a59cedb5a0ad051d67f7c1f40af4b52 100644\n> --- a/src/ipa/simple/ipa_context.h\n> +++ b/src/ipa/simple/ipa_context.h\n> @@ -71,10 +71,7 @@ struct IPAFrameContext : public FrameContext {\n>  \t\tdouble gain;\n>  \t} sensor;\n>  \n> -\tstruct {\n> -\t\tdouble red;\n> -\t\tdouble blue;\n> -\t} gains;\n> +\tRGB<float> gains;\n>  \n>  \tfloat gamma;\n>  \tstd::optional<float> contrast;\n> diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag\n> index 23747f78a6313503a46b61ed5bae6e7c178c5745..9a1992e219dd066945b3f46ec509f47a31590385 100644\n> --- a/src/libcamera/shaders/bayer_1x_packed.frag\n> +++ b/src/libcamera/shaders/bayer_1x_packed.frag\n> @@ -65,6 +65,7 @@ uniform vec2 tex_step;\n>  uniform vec2 tex_bayer_first_red;\n>  \n>  uniform sampler2D tex_y;\n> +uniform vec3 awb;\n\nI'd name this wbGains or colourGains, that's more explicit. Same below.\n\n>  uniform mat3 ccm;\n>  uniform vec3 blacklevel;\n>  uniform float gamma;\n> @@ -227,6 +228,9 @@ void main(void)\n>  \n>  \trgb = rgb - blacklevel;\n>  \n> +\t/* Apply AWB gains, and saturate each channel at sensor range */\n> +\trgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel);\n> +\n>  \t/*\n>  \t *   CCM is a 3x3 in the format\n>  \t *\n> diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag\n> index 76ffc47a8a29f242c1fba88f32bd8db731edeee0..87e4e4915fe19679943fdcc3d213a0224b89065e 100644\n> --- a/src/libcamera/shaders/bayer_unpacked.frag\n> +++ b/src/libcamera/shaders/bayer_unpacked.frag\n> @@ -24,6 +24,7 @@ uniform sampler2D       tex_y;\n>  varying vec4            center;\n>  varying vec4            yCoord;\n>  varying vec4            xCoord;\n> +uniform vec3            awb;\n>  uniform mat3            ccm;\n>  uniform vec3            blacklevel;\n>  uniform float           gamma;\n> @@ -130,6 +131,9 @@ void main(void) {\n>  \n>  \trgb = rgb - blacklevel;\n>  \n> +\t/* Apply AWB gains, and saturate each channel at sensor range */\n> +\trgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel);\n> +\n>  \t/*\n>  \t *   CCM is a 3x3 in the format\n>  \t *\n> diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp\n> index 2ad258bca69fb8dff19e35d9239ebd7d350590ae..738036e649224f370bdf9a0cc59b399f8b1066de 100644\n> --- a/src/libcamera/software_isp/debayer_egl.cpp\n> +++ b/src/libcamera/software_isp/debayer_egl.cpp\n> @@ -100,6 +100,7 @@ int DebayerEGL::getShaderVariableLocations(void)\n>  \tattributeTexture_ = glGetAttribLocation(programId_, \"textureIn\");\n>  \n>  \ttextureUniformBayerDataIn_ = glGetUniformLocation(programId_, \"tex_y\");\n> +\tawbUniformDataIn_ = glGetUniformLocation(programId_, \"awb\");\n>  \tccmUniformDataIn_ = glGetUniformLocation(programId_, \"ccm\");\n>  \tblackLevelUniformDataIn_ = glGetUniformLocation(programId_, \"blacklevel\");\n>  \tgammaUniformDataIn_ = glGetUniformLocation(programId_, \"gamma\");\n> @@ -113,6 +114,7 @@ int DebayerEGL::getShaderVariableLocations(void)\n>  \n>  \tLOG(Debayer, Debug) << \"vertexIn \" << attributeVertex_ << \" textureIn \" << attributeTexture_\n>  \t\t\t    << \" tex_y \" << textureUniformBayerDataIn_\n> +\t\t\t    << \" awb \" << awbUniformDataIn_\n>  \t\t\t    << \" ccm \" << ccmUniformDataIn_\n>  \t\t\t    << \" blacklevel \" << blackLevelUniformDataIn_\n>  \t\t\t    << \" gamma \" << gammaUniformDataIn_\n> @@ -481,6 +483,9 @@ void DebayerEGL::setShaderVariableValues(const DebayerParams &params)\n>  \tglUniform3f(blackLevelUniformDataIn_, params.blackLevel[0], params.blackLevel[1], params.blackLevel[2]);\n>  \tLOG(Debayer, Debug) << \" blackLevelUniformDataIn_ \" << blackLevelUniformDataIn_ << \" data \" << params.blackLevel;\n>  \n> +\tglUniform3f(awbUniformDataIn_, params.gains[0], params.gains[1], params.gains[2]);\n> +\tLOG(Debayer, Debug) << \" awbUniformDataIn_ \" << awbUniformDataIn_ << \" data \" << params.gains;\n> +\n>  \t/*\n>  \t * Gamma\n>  \t */\n> diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h\n> index bdde676f2394e7298006c88bbec75917800af4ad..23ef99117fbd209246ae565141a2365c6a7b0a63 100644\n> --- a/src/libcamera/software_isp/debayer_egl.h\n> +++ b/src/libcamera/software_isp/debayer_egl.h\n> @@ -97,6 +97,9 @@ private:\n>  \n>  \tGLint textureUniformBayerDataIn_;\n>  \n> +\t/* Per-frame AWB gains */\n\nAll the uniforms below are per-frame parameters, I'd drop the\n\"per-frame\".\n\nSorting the members in processing block order (in a separate patch)\nwould make it easier to follow the code.\n\n> +\tGLint awbUniformDataIn_;\n> +\n>  \t/* Represent per-frame CCM as a uniform vector of floats 3 x 3 */\n>  \tGLint ccmUniformDataIn_;\n>  \n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id A0948BDCBD\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed,  8 Apr 2026 00:01:05 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id D3ED162DA2;\n\tWed,  8 Apr 2026 02:01:04 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A95A762CEB\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  8 Apr 2026 02:01:02 +0200 (CEST)","from killaraus.ideasonboard.com\n\t(2001-14ba-703d-e500--2a1.rev.dnainternet.fi\n\t[IPv6:2001:14ba:703d:e500::2a1])\n\tby perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id B6BBF1121; \n\tWed,  8 Apr 2026 01:59:34 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"NvJfMjUY\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1775606374;\n\tbh=g8dKqM4W3puC5Zi4vGbvKWkcmYIu3ORFemL+MXycH08=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=NvJfMjUY1O0sif318m499CDNAMTPJGCN/ReTe73xweOVxtjuvduzvw9vAQA6ehnPx\n\taFdu5tZmxZU/ccFliG6Xs7BpJjP2sgYrA6WBVkd40i1ZHb3kAmTX9yJCjPYI76/Eow\n\tVKOTJWON5bzszpEaGKiw6JjU8N3JpRjbM/ftuVtc=","Date":"Wed, 8 Apr 2026 03:01:01 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH 02/13] softisp: Split AWB from Combined Matrix","Message-ID":"<20260408000101.GM1268443@killaraus.ideasonboard.com>","References":"<20260407-kbingham-awb-split-v1-0-a39af3f4dc20@ideasonboard.com>\n\t<20260407-kbingham-awb-split-v1-2-a39af3f4dc20@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20260407-kbingham-awb-split-v1-2-a39af3f4dc20@ideasonboard.com>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":38534,"web_url":"https://patchwork.libcamera.org/comment/38534/","msgid":"<853415g11b.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","date":"2026-04-08T11:10:56","subject":"Re: [PATCH 02/13] softisp: Split AWB from Combined Matrix","submitter":{"id":177,"url":"https://patchwork.libcamera.org/api/people/177/","name":"Milan Zamazal","email":"mzamazal@redhat.com"},"content":"Laurent Pinchart <laurent.pinchart@ideasonboard.com> writes:\n\n> On Tue, Apr 07, 2026 at 11:01:05PM +0100, Kieran Bingham wrote:\n>> Move the AWB gains out of the combined matrix and pass\n>> them directly to the EGL shaders.\n>\n>> \n>> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n>> ---\n>>  src/ipa/simple/algorithms/awb.cpp          | 16 +++-------------\n>>  src/ipa/simple/ipa_context.h               |  5 +----\n>>  src/libcamera/shaders/bayer_1x_packed.frag |  4 ++++\n>>  src/libcamera/shaders/bayer_unpacked.frag  |  4 ++++\n>>  src/libcamera/software_isp/debayer_egl.cpp |  5 +++++\n>>  src/libcamera/software_isp/debayer_egl.h   |  3 +++\n>>  6 files changed, 20 insertions(+), 17 deletions(-)\n>> \n>> diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp\n>> index f5c88ea6f896ff8a7ffdc328e09a4d4aa99df5e4..05155c83d172d64609053ba940a4c12a2248bb04 100644\n>> --- a/src/ipa/simple/algorithms/awb.cpp\n>> +++ b/src/ipa/simple/algorithms/awb.cpp\n>> @@ -38,15 +38,8 @@ void Awb::prepare(IPAContext &context,\n>>  \t\t  DebayerParams *params)\n>>  {\n>>  \tauto &gains = context.activeState.awb.gains;\n>> -\tMatrix<float, 3, 3> gainMatrix = { { gains.r(), 0, 0,\n>> -\t\t\t\t\t     0, gains.g(), 0,\n>> -\t\t\t\t\t     0, 0, gains.b() } };\n>> -\tcontext.activeState.combinedMatrix =\n>> -\t\tgainMatrix * context.activeState.combinedMatrix;\n>\n> The combined matrix is used by the CPU implementation too, aren't you\n> breaking AWB there ?\n\nYes, AWB is not applied in CPU ISP after this change.  It gets applied\nagain in \"Apply gains in CPU ISP\" patch; should the two be squashed?\n\nOther than that, the change itself looks good to me.\n\n>> -\n>> -\tframeContext.gains.red = gains.r();\n>> -\tframeContext.gains.blue = gains.b();\n>>  \n>> +\tframeContext.gains = gains;\n>>  \tparams->gains = gains;\n>>  }\n>>  \n>> @@ -59,11 +52,8 @@ void Awb::process(IPAContext &context,\n>>  \tconst SwIspStats::Histogram &histogram = stats->yHistogram;\n>>  \tconst uint8_t blackLevel = context.activeState.blc.level;\n>>  \n>> -\tconst float mdGains[] = {\n>> -\t\tstatic_cast<float>(frameContext.gains.red),\n>> -\t\tstatic_cast<float>(frameContext.gains.blue)\n>> -\t};\n>> -\tmetadata.set(controls::ColourGains, mdGains);\n>> +\tmetadata.set(controls::ColourGains, { frameContext.gains.r(),\n>> +\t\t\t\t\t      frameContext.gains.b() });\n>>  \n>>  \tif (!stats->valid)\n>>  \t\treturn;\n>> diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h\n>> index 34f7403a41d690cb3f0c271827ae2e915b6ea49d..8ccfacb46a59cedb5a0ad051d67f7c1f40af4b52 100644\n>> --- a/src/ipa/simple/ipa_context.h\n>> +++ b/src/ipa/simple/ipa_context.h\n>> @@ -71,10 +71,7 @@ struct IPAFrameContext : public FrameContext {\n>>  \t\tdouble gain;\n>>  \t} sensor;\n>>  \n>> -\tstruct {\n>> -\t\tdouble red;\n>> -\t\tdouble blue;\n>> -\t} gains;\n>> +\tRGB<float> gains;\n>>  \n>>  \tfloat gamma;\n>>  \tstd::optional<float> contrast;\n>> diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag\n>> index 23747f78a6313503a46b61ed5bae6e7c178c5745..9a1992e219dd066945b3f46ec509f47a31590385 100644\n>> --- a/src/libcamera/shaders/bayer_1x_packed.frag\n>> +++ b/src/libcamera/shaders/bayer_1x_packed.frag\n>> @@ -65,6 +65,7 @@ uniform vec2 tex_step;\n>>  uniform vec2 tex_bayer_first_red;\n>>  \n>>  uniform sampler2D tex_y;\n>> +uniform vec3 awb;\n>\n> I'd name this wbGains or colourGains, that's more explicit. Same below.\n>\n>>  uniform mat3 ccm;\n>>  uniform vec3 blacklevel;\n>>  uniform float gamma;\n>> @@ -227,6 +228,9 @@ void main(void)\n>>  \n>>  \trgb = rgb - blacklevel;\n>>  \n>> +\t/* Apply AWB gains, and saturate each channel at sensor range */\n>> +\trgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel);\n>> +\n>>  \t/*\n>>  \t *   CCM is a 3x3 in the format\n>>  \t *\n>> diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag\n>> index 76ffc47a8a29f242c1fba88f32bd8db731edeee0..87e4e4915fe19679943fdcc3d213a0224b89065e 100644\n>> --- a/src/libcamera/shaders/bayer_unpacked.frag\n>> +++ b/src/libcamera/shaders/bayer_unpacked.frag\n>> @@ -24,6 +24,7 @@ uniform sampler2D       tex_y;\n>>  varying vec4            center;\n>>  varying vec4            yCoord;\n>>  varying vec4            xCoord;\n>> +uniform vec3            awb;\n>>  uniform mat3            ccm;\n>>  uniform vec3            blacklevel;\n>>  uniform float           gamma;\n>> @@ -130,6 +131,9 @@ void main(void) {\n>>  \n>>  \trgb = rgb - blacklevel;\n>>  \n>> +\t/* Apply AWB gains, and saturate each channel at sensor range */\n>> +\trgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel);\n>> +\n>>  \t/*\n>>  \t *   CCM is a 3x3 in the format\n>>  \t *\n>> diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp\n>> index 2ad258bca69fb8dff19e35d9239ebd7d350590ae..738036e649224f370bdf9a0cc59b399f8b1066de 100644\n>> --- a/src/libcamera/software_isp/debayer_egl.cpp\n>> +++ b/src/libcamera/software_isp/debayer_egl.cpp\n>> @@ -100,6 +100,7 @@ int DebayerEGL::getShaderVariableLocations(void)\n>>  \tattributeTexture_ = glGetAttribLocation(programId_, \"textureIn\");\n>>  \n>>  \ttextureUniformBayerDataIn_ = glGetUniformLocation(programId_, \"tex_y\");\n>> +\tawbUniformDataIn_ = glGetUniformLocation(programId_, \"awb\");\n>>  \tccmUniformDataIn_ = glGetUniformLocation(programId_, \"ccm\");\n>>  \tblackLevelUniformDataIn_ = glGetUniformLocation(programId_, \"blacklevel\");\n>>  \tgammaUniformDataIn_ = glGetUniformLocation(programId_, \"gamma\");\n>> @@ -113,6 +114,7 @@ int DebayerEGL::getShaderVariableLocations(void)\n>>  \n>>  \tLOG(Debayer, Debug) << \"vertexIn \" << attributeVertex_ << \" textureIn \" << attributeTexture_\n>>  \t\t\t    << \" tex_y \" << textureUniformBayerDataIn_\n>> +\t\t\t    << \" awb \" << awbUniformDataIn_\n>>  \t\t\t    << \" ccm \" << ccmUniformDataIn_\n>>  \t\t\t    << \" blacklevel \" << blackLevelUniformDataIn_\n>>  \t\t\t    << \" gamma \" << gammaUniformDataIn_\n>> @@ -481,6 +483,9 @@ void DebayerEGL::setShaderVariableValues(const DebayerParams &params)\n>>  \tglUniform3f(blackLevelUniformDataIn_, params.blackLevel[0], params.blackLevel[1], params.blackLevel[2]);\n>>  \tLOG(Debayer, Debug) << \" blackLevelUniformDataIn_ \" << blackLevelUniformDataIn_ << \" data \" << params.blackLevel;\n>>  \n>> +\tglUniform3f(awbUniformDataIn_, params.gains[0], params.gains[1], params.gains[2]);\n>> +\tLOG(Debayer, Debug) << \" awbUniformDataIn_ \" << awbUniformDataIn_ << \" data \" << params.gains;\n>> +\n>>  \t/*\n>>  \t * Gamma\n>>  \t */\n>> diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h\n>> index bdde676f2394e7298006c88bbec75917800af4ad..23ef99117fbd209246ae565141a2365c6a7b0a63 100644\n>> --- a/src/libcamera/software_isp/debayer_egl.h\n>> +++ b/src/libcamera/software_isp/debayer_egl.h\n>> @@ -97,6 +97,9 @@ private:\n>>  \n>>  \tGLint textureUniformBayerDataIn_;\n>>  \n>> +\t/* Per-frame AWB gains */\n>\n> All the uniforms below are per-frame parameters, I'd drop the\n> \"per-frame\".\n>\n> Sorting the members in processing block order (in a separate patch)\n> would make it easier to follow the code.\n>\n>> +\tGLint awbUniformDataIn_;\n>> +\n>>  \t/* Represent per-frame CCM as a uniform vector of floats 3 x 3 */\n>>  \tGLint ccmUniformDataIn_;\n>>  \n>>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 46108BDCBD\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed,  8 Apr 2026 11:11:08 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 43D7962DE5;\n\tWed,  8 Apr 2026 13:11:07 +0200 (CEST)","from us-smtp-delivery-124.mimecast.com\n\t(us-smtp-delivery-124.mimecast.com [170.10.129.124])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 5433362CE6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  8 Apr 2026 13:11:05 +0200 (CEST)","from mail-wr1-f70.google.com (mail-wr1-f70.google.com\n\t[209.85.221.70]) by relay.mimecast.com with ESMTP with STARTTLS\n\t(version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n\tus-mta-663-640Jfy_YPY-uUxVGEntJSw-1; Wed, 08 Apr 2026 07:11:00 -0400","by mail-wr1-f70.google.com with SMTP id\n\tffacd0b85a97d-43b93781cb8so5076235f8f.3\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 08 Apr 2026 04:11:00 -0700 (PDT)","from mzamazal-thinkpadp1gen7.tpbc.csb\n\t(ip-77-48-47-2.net.vodafone.cz. [77.48.47.2])\n\tby smtp.gmail.com with ESMTPSA id\n\tffacd0b85a97d-43d1e2c50a7sm57298075f8f.15.2026.04.08.04.10.56\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tWed, 08 Apr 2026 04:10:57 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=redhat.com header.i=@redhat.com\n\theader.b=\"HaC5TBOV\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1775646664;\n\th=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n\tto:to:cc:cc:mime-version:mime-version:content-type:content-type:\n\tin-reply-to:in-reply-to:references:references;\n\tbh=6D9qrnZJZYsIWbMOziv0mwV0UjtGP4SB6uW3BrhLPu4=;\n\tb=HaC5TBOV4vegAdzZ0fCUqw714CUfz1E9t+yk4s+prXlKuYmHFrU+ldRDm+P58L2WCR5A4c\n\tfz1pgm4/Opto+Y/YtORtOkUHno9aHDICVRK8rnYqOGQLcrj7BAlgVyE6/L/hq8jUitQxWC\n\tNr16s1LZynj4mS4M1rCVFivqvKtvyiU=","X-MC-Unique":"640Jfy_YPY-uUxVGEntJSw-1","X-Mimecast-MFC-AGG-ID":"640Jfy_YPY-uUxVGEntJSw_1775646659","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20251104; t=1775646659; x=1776251459;\n\th=mime-version:user-agent:message-id:date:references:in-reply-to\n\t:subject:cc:to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject\n\t:date:message-id:reply-to;\n\tbh=6D9qrnZJZYsIWbMOziv0mwV0UjtGP4SB6uW3BrhLPu4=;\n\tb=pgqCZ0ekGhy010p+rKG3qsPMYWYhjIyFYs/iyU1fG1an3qHME+3GgIT9RBEvsIuAqy\n\tsv6ytnKFJ2VOA0HlViMWgsSfHT2EtYQKIl6lc62IK2zlUQj1PlYo141u4YVvCAaEoRGR\n\tBdOFIGKhje0+7px34xv1FhOB10Cn7zY0ZWH9MLGmijRP9VzuRaHXQSys0419j8l1a1rZ\n\tHWs07yN+EqzadcFbiPnVXH/B9blQ94ARqJz9w7G7SXEZAyDg7v8/UrPk8/ibLFyycJp3\n\tIrMX1PWoz1dwd0JSRFQRauAxBiVOovgMhjIWyB0TjIBN6R0yK8xEWoqecxaHq/Rs3r9Y\n\tfh+w==","X-Forwarded-Encrypted":"i=1;\n\tAJvYcCVZwapEnwnfAiRl0FIEaEHJk0VTmeMG/e1H+u2hmv08RR6kCOJsjBKmdNKG2dP9KTRyxvupE4TBkvrkmjbXVAk=@lists.libcamera.org","X-Gm-Message-State":"AOJu0YxC2ZzLWl7FSWMKyLlWWvearjx/LWnF06oqUoHb7HYv7Rwgyc7g\n\tpnJhH8ci19+/9N2DLp7KfiHe/qetVkB8PzbK9Pc2+/p7SwX9j1WWCHeJYY4EttCtdx4y3Q5nJB2\n\t7+bRmkt52oPpEcIPqGZg5FlPC9pvNo3gqH4LccNA9qr1KTYwcRcbTBY2u4P1ZK7OtJfsNxRZ7JP\n\t/uhDnj3yuAkNdpln4wUbm4mCZWDR0x8pzDkc8Rva89zt2yW6UW9yRQuX2q0Fk=","X-Gm-Gg":"AeBDiesmmCYM2pdrbEmbYjd87RW03CLrYJkcBgZXsFPsvgIwGtsO9ZqtFl8caSZEKJw\n\t85nnC42tQM29PsmzmmTMq1Q0hBHKCO0aqJz2BhwVzETOHVx5ZS0cc/JxXkSRdFNXYyVvyCrScoZ\n\tTBX5yHfSrjDfhhWeewAbdYJBGsX/iAIFtL+XC6+Wukr0eDbBdAFoFgqe/ncbNDX4kPCC9Qy8tFp\n\tkf1NC9KSCrybstC7Hzeiou5Z+W/EtFWMs71Jkxfx/+Do6ovK89Jz9GZQvss+daWa4ueE1LVBvFL\n\tH4BGldz+cC3slcGSiJQSm1Pe+Lgj9NqmF+fkMRG+BmjhnXoUjYo4AllYyfmiUkCNNUImwgHzfXr\n\tA6kYTMdhjlWDSlbuqDv8/Mh0Jwcg+k/5DNO/ENlSmjl09Xtjxfl1cV+AXxcy9TDN/sQ/LqVmB84\n\tk=","X-Received":["by 2002:a05:6000:11d1:b0:43c:fd4d:2404 with SMTP id\n\tffacd0b85a97d-43d29269f6emr21447110f8f.7.1775646659075; \n\tWed, 08 Apr 2026 04:10:59 -0700 (PDT)","by 2002:a05:6000:11d1:b0:43c:fd4d:2404 with SMTP id\n\tffacd0b85a97d-43d29269f6emr21447079f8f.7.1775646658589; \n\tWed, 08 Apr 2026 04:10:58 -0700 (PDT)"],"From":"Milan Zamazal <mzamazal@redhat.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"Kieran Bingham <kieran.bingham@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH 02/13] softisp: Split AWB from Combined Matrix","In-Reply-To":"<20260408000101.GM1268443@killaraus.ideasonboard.com> (Laurent\n\tPinchart's message of \"Wed, 8 Apr 2026 03:01:01 +0300\")","References":"<20260407-kbingham-awb-split-v1-0-a39af3f4dc20@ideasonboard.com>\n\t<20260407-kbingham-awb-split-v1-2-a39af3f4dc20@ideasonboard.com>\n\t<20260408000101.GM1268443@killaraus.ideasonboard.com>","Date":"Wed, 08 Apr 2026 13:10:56 +0200","Message-ID":"<853415g11b.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","User-Agent":"Gnus/5.13 (Gnus v5.13)","MIME-Version":"1.0","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"fBxwYUVgac6EuN-pouiY4kH0Vxf6rknKVByr8BzxFEI_1775646659","X-Mimecast-Originator":"redhat.com","Content-Type":"text/plain","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":38543,"web_url":"https://patchwork.libcamera.org/comment/38543/","msgid":"<177566921061.575056.12572454224071478541@ping.linuxembedded.co.uk>","date":"2026-04-08T17:26:50","subject":"Re: [PATCH 02/13] softisp: Split AWB from Combined Matrix","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Milan Zamazal (2026-04-08 12:10:56)\n> Laurent Pinchart <laurent.pinchart@ideasonboard.com> writes:\n> \n> > On Tue, Apr 07, 2026 at 11:01:05PM +0100, Kieran Bingham wrote:\n> >> Move the AWB gains out of the combined matrix and pass\n> >> them directly to the EGL shaders.\n> >\n> >> \n> >> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> >> ---\n> >>  src/ipa/simple/algorithms/awb.cpp          | 16 +++-------------\n> >>  src/ipa/simple/ipa_context.h               |  5 +----\n> >>  src/libcamera/shaders/bayer_1x_packed.frag |  4 ++++\n> >>  src/libcamera/shaders/bayer_unpacked.frag  |  4 ++++\n> >>  src/libcamera/software_isp/debayer_egl.cpp |  5 +++++\n> >>  src/libcamera/software_isp/debayer_egl.h   |  3 +++\n> >>  6 files changed, 20 insertions(+), 17 deletions(-)\n> >> \n> >> diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp\n> >> index f5c88ea6f896ff8a7ffdc328e09a4d4aa99df5e4..05155c83d172d64609053ba940a4c12a2248bb04 100644\n> >> --- a/src/ipa/simple/algorithms/awb.cpp\n> >> +++ b/src/ipa/simple/algorithms/awb.cpp\n> >> @@ -38,15 +38,8 @@ void Awb::prepare(IPAContext &context,\n> >>                DebayerParams *params)\n> >>  {\n> >>      auto &gains = context.activeState.awb.gains;\n> >> -    Matrix<float, 3, 3> gainMatrix = { { gains.r(), 0, 0,\n> >> -                                         0, gains.g(), 0,\n> >> -                                         0, 0, gains.b() } };\n> >> -    context.activeState.combinedMatrix =\n> >> -            gainMatrix * context.activeState.combinedMatrix;\n> >\n> > The combined matrix is used by the CPU implementation too, aren't you\n> > breaking AWB there ?\n> \n> Yes, AWB is not applied in CPU ISP after this change.  It gets applied\n> again in \"Apply gains in CPU ISP\" patch; should the two be squashed?\n> \n> Other than that, the change itself looks good to me.\n\nIs it safe to swap the order and put your patches first to maintain\n'correctness' in bisection?\n\n\n\n> \n> >> -\n> >> -    frameContext.gains.red = gains.r();\n> >> -    frameContext.gains.blue = gains.b();\n> >>  \n> >> +    frameContext.gains = gains;\n> >>      params->gains = gains;\n> >>  }\n> >>  \n> >> @@ -59,11 +52,8 @@ void Awb::process(IPAContext &context,\n> >>      const SwIspStats::Histogram &histogram = stats->yHistogram;\n> >>      const uint8_t blackLevel = context.activeState.blc.level;\n> >>  \n> >> -    const float mdGains[] = {\n> >> -            static_cast<float>(frameContext.gains.red),\n> >> -            static_cast<float>(frameContext.gains.blue)\n> >> -    };\n> >> -    metadata.set(controls::ColourGains, mdGains);\n> >> +    metadata.set(controls::ColourGains, { frameContext.gains.r(),\n> >> +                                          frameContext.gains.b() });\n> >>  \n> >>      if (!stats->valid)\n> >>              return;\n> >> diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h\n> >> index 34f7403a41d690cb3f0c271827ae2e915b6ea49d..8ccfacb46a59cedb5a0ad051d67f7c1f40af4b52 100644\n> >> --- a/src/ipa/simple/ipa_context.h\n> >> +++ b/src/ipa/simple/ipa_context.h\n> >> @@ -71,10 +71,7 @@ struct IPAFrameContext : public FrameContext {\n> >>              double gain;\n> >>      } sensor;\n> >>  \n> >> -    struct {\n> >> -            double red;\n> >> -            double blue;\n> >> -    } gains;\n> >> +    RGB<float> gains;\n> >>  \n> >>      float gamma;\n> >>      std::optional<float> contrast;\n> >> diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag\n> >> index 23747f78a6313503a46b61ed5bae6e7c178c5745..9a1992e219dd066945b3f46ec509f47a31590385 100644\n> >> --- a/src/libcamera/shaders/bayer_1x_packed.frag\n> >> +++ b/src/libcamera/shaders/bayer_1x_packed.frag\n> >> @@ -65,6 +65,7 @@ uniform vec2 tex_step;\n> >>  uniform vec2 tex_bayer_first_red;\n> >>  \n> >>  uniform sampler2D tex_y;\n> >> +uniform vec3 awb;\n> >\n> > I'd name this wbGains or colourGains, that's more explicit. Same below.\n\nI'd like to introduce a full 'DigitalGain' control at somepoint (soon)\nwhich will be where/how awb will be applied. So I think it would get\nrenamed then too.\n\nI could accept colourGains already for that I guess...\n\n> >\n> >>  uniform mat3 ccm;\n> >>  uniform vec3 blacklevel;\n> >>  uniform float gamma;\n> >> @@ -227,6 +228,9 @@ void main(void)\n> >>  \n> >>      rgb = rgb - blacklevel;\n> >>  \n> >> +    /* Apply AWB gains, and saturate each channel at sensor range */\n> >> +    rgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel);\n> >> +\n> >>      /*\n> >>       *   CCM is a 3x3 in the format\n> >>       *\n> >> diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag\n> >> index 76ffc47a8a29f242c1fba88f32bd8db731edeee0..87e4e4915fe19679943fdcc3d213a0224b89065e 100644\n> >> --- a/src/libcamera/shaders/bayer_unpacked.frag\n> >> +++ b/src/libcamera/shaders/bayer_unpacked.frag\n> >> @@ -24,6 +24,7 @@ uniform sampler2D       tex_y;\n> >>  varying vec4            center;\n> >>  varying vec4            yCoord;\n> >>  varying vec4            xCoord;\n> >> +uniform vec3            awb;\n> >>  uniform mat3            ccm;\n> >>  uniform vec3            blacklevel;\n> >>  uniform float           gamma;\n> >> @@ -130,6 +131,9 @@ void main(void) {\n> >>  \n> >>      rgb = rgb - blacklevel;\n> >>  \n> >> +    /* Apply AWB gains, and saturate each channel at sensor range */\n> >> +    rgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel);\n> >> +\n> >>      /*\n> >>       *   CCM is a 3x3 in the format\n> >>       *\n> >> diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp\n> >> index 2ad258bca69fb8dff19e35d9239ebd7d350590ae..738036e649224f370bdf9a0cc59b399f8b1066de 100644\n> >> --- a/src/libcamera/software_isp/debayer_egl.cpp\n> >> +++ b/src/libcamera/software_isp/debayer_egl.cpp\n> >> @@ -100,6 +100,7 @@ int DebayerEGL::getShaderVariableLocations(void)\n> >>      attributeTexture_ = glGetAttribLocation(programId_, \"textureIn\");\n> >>  \n> >>      textureUniformBayerDataIn_ = glGetUniformLocation(programId_, \"tex_y\");\n> >> +    awbUniformDataIn_ = glGetUniformLocation(programId_, \"awb\");\n> >>      ccmUniformDataIn_ = glGetUniformLocation(programId_, \"ccm\");\n> >>      blackLevelUniformDataIn_ = glGetUniformLocation(programId_, \"blacklevel\");\n> >>      gammaUniformDataIn_ = glGetUniformLocation(programId_, \"gamma\");\n> >> @@ -113,6 +114,7 @@ int DebayerEGL::getShaderVariableLocations(void)\n> >>  \n> >>      LOG(Debayer, Debug) << \"vertexIn \" << attributeVertex_ << \" textureIn \" << attributeTexture_\n> >>                          << \" tex_y \" << textureUniformBayerDataIn_\n> >> +                        << \" awb \" << awbUniformDataIn_\n> >>                          << \" ccm \" << ccmUniformDataIn_\n> >>                          << \" blacklevel \" << blackLevelUniformDataIn_\n> >>                          << \" gamma \" << gammaUniformDataIn_\n> >> @@ -481,6 +483,9 @@ void DebayerEGL::setShaderVariableValues(const DebayerParams &params)\n> >>      glUniform3f(blackLevelUniformDataIn_, params.blackLevel[0], params.blackLevel[1], params.blackLevel[2]);\n> >>      LOG(Debayer, Debug) << \" blackLevelUniformDataIn_ \" << blackLevelUniformDataIn_ << \" data \" << params.blackLevel;\n> >>  \n> >> +    glUniform3f(awbUniformDataIn_, params.gains[0], params.gains[1], params.gains[2]);\n> >> +    LOG(Debayer, Debug) << \" awbUniformDataIn_ \" << awbUniformDataIn_ << \" data \" << params.gains;\n> >> +\n> >>      /*\n> >>       * Gamma\n> >>       */\n> >> diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h\n> >> index bdde676f2394e7298006c88bbec75917800af4ad..23ef99117fbd209246ae565141a2365c6a7b0a63 100644\n> >> --- a/src/libcamera/software_isp/debayer_egl.h\n> >> +++ b/src/libcamera/software_isp/debayer_egl.h\n> >> @@ -97,6 +97,9 @@ private:\n> >>  \n> >>      GLint textureUniformBayerDataIn_;\n> >>  \n> >> +    /* Per-frame AWB gains */\n> >\n> > All the uniforms below are per-frame parameters, I'd drop the\n> > \"per-frame\".\n> >\n> > Sorting the members in processing block order (in a separate patch)\n> > would make it easier to follow the code.\n\nYes, I think processing order is the most useful ordering.\n\n> >\n> >> +    GLint awbUniformDataIn_;\n> >> +\n> >>      /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */\n> >>      GLint ccmUniformDataIn_;\n> >>  \n> >> \n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id AF37FBEFBE\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed,  8 Apr 2026 17:26:55 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id ED76462DF7;\n\tWed,  8 Apr 2026 19:26:54 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id B40A062CE6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  8 Apr 2026 19:26:53 +0200 (CEST)","from monstersaurus.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 440E22D5;\n\tWed,  8 Apr 2026 19:25:25 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"rE6Z0rDJ\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1775669125;\n\tbh=F1tOXZ++FzS5xqqWb4nfLkhlFmrZCKyFi/k3ogVaJ6I=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=rE6Z0rDJCTvlQFSxLjfsfBHfgOr+nPz5SZj9jIp5U/8lRQPpVIbAELGawzDi5sJXh\n\t5v0oIgmEb+lK43CdpF4eC+fGBHez1BTsKXn+UuPpuGtq79B1tbFwcTCYTl2/Xpg7f0\n\tOthpraLrl5QwTmbzljNf3eEB7c5sJNSxp7GflzS0=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<853415g11b.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","References":"<20260407-kbingham-awb-split-v1-0-a39af3f4dc20@ideasonboard.com>\n\t<20260407-kbingham-awb-split-v1-2-a39af3f4dc20@ideasonboard.com>\n\t<20260408000101.GM1268443@killaraus.ideasonboard.com>\n\t<853415g11b.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","Subject":"Re: [PATCH 02/13] softisp: Split AWB from Combined Matrix","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>,\n\tMilan Zamazal <mzamazal@redhat.com>","Date":"Wed, 08 Apr 2026 18:26:50 +0100","Message-ID":"<177566921061.575056.12572454224071478541@ping.linuxembedded.co.uk>","User-Agent":"alot/0.9.1","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":38547,"web_url":"https://patchwork.libcamera.org/comment/38547/","msgid":"<20260408174342.GE1965119@killaraus.ideasonboard.com>","date":"2026-04-08T17:43:42","subject":"Re: [PATCH 02/13] softisp: Split AWB from Combined Matrix","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Wed, Apr 08, 2026 at 06:26:50PM +0100, Kieran Bingham wrote:\n> Quoting Milan Zamazal (2026-04-08 12:10:56)\n> > Laurent Pinchart <laurent.pinchart@ideasonboard.com> writes:\n> > > On Tue, Apr 07, 2026 at 11:01:05PM +0100, Kieran Bingham wrote:\n> > >> Move the AWB gains out of the combined matrix and pass\n> > >> them directly to the EGL shaders.\n> > >\n> > >> \n> > >> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> > >> ---\n> > >>  src/ipa/simple/algorithms/awb.cpp          | 16 +++-------------\n> > >>  src/ipa/simple/ipa_context.h               |  5 +----\n> > >>  src/libcamera/shaders/bayer_1x_packed.frag |  4 ++++\n> > >>  src/libcamera/shaders/bayer_unpacked.frag  |  4 ++++\n> > >>  src/libcamera/software_isp/debayer_egl.cpp |  5 +++++\n> > >>  src/libcamera/software_isp/debayer_egl.h   |  3 +++\n> > >>  6 files changed, 20 insertions(+), 17 deletions(-)\n> > >> \n> > >> diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp\n> > >> index f5c88ea6f896ff8a7ffdc328e09a4d4aa99df5e4..05155c83d172d64609053ba940a4c12a2248bb04 100644\n> > >> --- a/src/ipa/simple/algorithms/awb.cpp\n> > >> +++ b/src/ipa/simple/algorithms/awb.cpp\n> > >> @@ -38,15 +38,8 @@ void Awb::prepare(IPAContext &context,\n> > >>                DebayerParams *params)\n> > >>  {\n> > >>      auto &gains = context.activeState.awb.gains;\n> > >> -    Matrix<float, 3, 3> gainMatrix = { { gains.r(), 0, 0,\n> > >> -                                         0, gains.g(), 0,\n> > >> -                                         0, 0, gains.b() } };\n> > >> -    context.activeState.combinedMatrix =\n> > >> -            gainMatrix * context.activeState.combinedMatrix;\n> > >\n> > > The combined matrix is used by the CPU implementation too, aren't you\n> > > breaking AWB there ?\n> > \n> > Yes, AWB is not applied in CPU ISP after this change.  It gets applied\n> > again in \"Apply gains in CPU ISP\" patch; should the two be squashed?\n> > \n> > Other than that, the change itself looks good to me.\n> \n> Is it safe to swap the order and put your patches first to maintain\n> 'correctness' in bisection?\n\nThen you will apply them twice.\n\n> > >> -\n> > >> -    frameContext.gains.red = gains.r();\n> > >> -    frameContext.gains.blue = gains.b();\n> > >>  \n> > >> +    frameContext.gains = gains;\n> > >>      params->gains = gains;\n> > >>  }\n> > >>  \n> > >> @@ -59,11 +52,8 @@ void Awb::process(IPAContext &context,\n> > >>      const SwIspStats::Histogram &histogram = stats->yHistogram;\n> > >>      const uint8_t blackLevel = context.activeState.blc.level;\n> > >>  \n> > >> -    const float mdGains[] = {\n> > >> -            static_cast<float>(frameContext.gains.red),\n> > >> -            static_cast<float>(frameContext.gains.blue)\n> > >> -    };\n> > >> -    metadata.set(controls::ColourGains, mdGains);\n> > >> +    metadata.set(controls::ColourGains, { frameContext.gains.r(),\n> > >> +                                          frameContext.gains.b() });\n> > >>  \n> > >>      if (!stats->valid)\n> > >>              return;\n> > >> diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h\n> > >> index 34f7403a41d690cb3f0c271827ae2e915b6ea49d..8ccfacb46a59cedb5a0ad051d67f7c1f40af4b52 100644\n> > >> --- a/src/ipa/simple/ipa_context.h\n> > >> +++ b/src/ipa/simple/ipa_context.h\n> > >> @@ -71,10 +71,7 @@ struct IPAFrameContext : public FrameContext {\n> > >>              double gain;\n> > >>      } sensor;\n> > >>  \n> > >> -    struct {\n> > >> -            double red;\n> > >> -            double blue;\n> > >> -    } gains;\n> > >> +    RGB<float> gains;\n> > >>  \n> > >>      float gamma;\n> > >>      std::optional<float> contrast;\n> > >> diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag\n> > >> index 23747f78a6313503a46b61ed5bae6e7c178c5745..9a1992e219dd066945b3f46ec509f47a31590385 100644\n> > >> --- a/src/libcamera/shaders/bayer_1x_packed.frag\n> > >> +++ b/src/libcamera/shaders/bayer_1x_packed.frag\n> > >> @@ -65,6 +65,7 @@ uniform vec2 tex_step;\n> > >>  uniform vec2 tex_bayer_first_red;\n> > >>  \n> > >>  uniform sampler2D tex_y;\n> > >> +uniform vec3 awb;\n> > >\n> > > I'd name this wbGains or colourGains, that's more explicit. Same below.\n> \n> I'd like to introduce a full 'DigitalGain' control at somepoint (soon)\n> which will be where/how awb will be applied. So I think it would get\n> renamed then too.\n> \n> I could accept colourGains already for that I guess...\n> \n> > >>  uniform mat3 ccm;\n> > >>  uniform vec3 blacklevel;\n> > >>  uniform float gamma;\n> > >> @@ -227,6 +228,9 @@ void main(void)\n> > >>  \n> > >>      rgb = rgb - blacklevel;\n> > >>  \n> > >> +    /* Apply AWB gains, and saturate each channel at sensor range */\n> > >> +    rgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel);\n> > >> +\n> > >>      /*\n> > >>       *   CCM is a 3x3 in the format\n> > >>       *\n> > >> diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag\n> > >> index 76ffc47a8a29f242c1fba88f32bd8db731edeee0..87e4e4915fe19679943fdcc3d213a0224b89065e 100644\n> > >> --- a/src/libcamera/shaders/bayer_unpacked.frag\n> > >> +++ b/src/libcamera/shaders/bayer_unpacked.frag\n> > >> @@ -24,6 +24,7 @@ uniform sampler2D       tex_y;\n> > >>  varying vec4            center;\n> > >>  varying vec4            yCoord;\n> > >>  varying vec4            xCoord;\n> > >> +uniform vec3            awb;\n> > >>  uniform mat3            ccm;\n> > >>  uniform vec3            blacklevel;\n> > >>  uniform float           gamma;\n> > >> @@ -130,6 +131,9 @@ void main(void) {\n> > >>  \n> > >>      rgb = rgb - blacklevel;\n> > >>  \n> > >> +    /* Apply AWB gains, and saturate each channel at sensor range */\n> > >> +    rgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel);\n> > >> +\n> > >>      /*\n> > >>       *   CCM is a 3x3 in the format\n> > >>       *\n> > >> diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp\n> > >> index 2ad258bca69fb8dff19e35d9239ebd7d350590ae..738036e649224f370bdf9a0cc59b399f8b1066de 100644\n> > >> --- a/src/libcamera/software_isp/debayer_egl.cpp\n> > >> +++ b/src/libcamera/software_isp/debayer_egl.cpp\n> > >> @@ -100,6 +100,7 @@ int DebayerEGL::getShaderVariableLocations(void)\n> > >>      attributeTexture_ = glGetAttribLocation(programId_, \"textureIn\");\n> > >>  \n> > >>      textureUniformBayerDataIn_ = glGetUniformLocation(programId_, \"tex_y\");\n> > >> +    awbUniformDataIn_ = glGetUniformLocation(programId_, \"awb\");\n> > >>      ccmUniformDataIn_ = glGetUniformLocation(programId_, \"ccm\");\n> > >>      blackLevelUniformDataIn_ = glGetUniformLocation(programId_, \"blacklevel\");\n> > >>      gammaUniformDataIn_ = glGetUniformLocation(programId_, \"gamma\");\n> > >> @@ -113,6 +114,7 @@ int DebayerEGL::getShaderVariableLocations(void)\n> > >>  \n> > >>      LOG(Debayer, Debug) << \"vertexIn \" << attributeVertex_ << \" textureIn \" << attributeTexture_\n> > >>                          << \" tex_y \" << textureUniformBayerDataIn_\n> > >> +                        << \" awb \" << awbUniformDataIn_\n> > >>                          << \" ccm \" << ccmUniformDataIn_\n> > >>                          << \" blacklevel \" << blackLevelUniformDataIn_\n> > >>                          << \" gamma \" << gammaUniformDataIn_\n> > >> @@ -481,6 +483,9 @@ void DebayerEGL::setShaderVariableValues(const DebayerParams &params)\n> > >>      glUniform3f(blackLevelUniformDataIn_, params.blackLevel[0], params.blackLevel[1], params.blackLevel[2]);\n> > >>      LOG(Debayer, Debug) << \" blackLevelUniformDataIn_ \" << blackLevelUniformDataIn_ << \" data \" << params.blackLevel;\n> > >>  \n> > >> +    glUniform3f(awbUniformDataIn_, params.gains[0], params.gains[1], params.gains[2]);\n> > >> +    LOG(Debayer, Debug) << \" awbUniformDataIn_ \" << awbUniformDataIn_ << \" data \" << params.gains;\n> > >> +\n> > >>      /*\n> > >>       * Gamma\n> > >>       */\n> > >> diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h\n> > >> index bdde676f2394e7298006c88bbec75917800af4ad..23ef99117fbd209246ae565141a2365c6a7b0a63 100644\n> > >> --- a/src/libcamera/software_isp/debayer_egl.h\n> > >> +++ b/src/libcamera/software_isp/debayer_egl.h\n> > >> @@ -97,6 +97,9 @@ private:\n> > >>  \n> > >>      GLint textureUniformBayerDataIn_;\n> > >>  \n> > >> +    /* Per-frame AWB gains */\n> > >\n> > > All the uniforms below are per-frame parameters, I'd drop the\n> > > \"per-frame\".\n> > >\n> > > Sorting the members in processing block order (in a separate patch)\n> > > would make it easier to follow the code.\n> \n> Yes, I think processing order is the most useful ordering.\n> \n> > >\n> > >> +    GLint awbUniformDataIn_;\n> > >> +\n> > >>      /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */\n> > >>      GLint ccmUniformDataIn_;\n> > >>  \n> > >>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 3D492BDCBD\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed,  8 Apr 2026 17:43:47 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 3AF6262E0B;\n\tWed,  8 Apr 2026 19:43:46 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 83A0662CE6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  8 Apr 2026 19:43:44 +0200 (CEST)","from killaraus.ideasonboard.com\n\t(2001-14ba-703d-e500--2a1.rev.dnainternet.fi\n\t[IPv6:2001:14ba:703d:e500::2a1])\n\tby perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 1385F1E7;\n\tWed,  8 Apr 2026 19:42:16 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"i6vgF0dI\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1775670136;\n\tbh=0bbhaVTRWK77rVjTAxsPuFqKmLNqQpUNopa0+qSlhk8=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=i6vgF0dIWSlWhWpTV1xZvW8Yzgh6DnbMb4+Yz+2+2aWsmgUX9kDRq7rBNbMEfqx36\n\tMB8Y9UMoWIyrR99vJUvS2M3KsY3Z+kfnG/BnxOBDFvXAUXXblg+8FGLl8WOyO99ypW\n\tEISI/AuxNBd1ppHYzZ0xKxDonU4uZU0SAVEZvCJM=","Date":"Wed, 8 Apr 2026 20:43:42 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Milan Zamazal <mzamazal@redhat.com>, libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH 02/13] softisp: Split AWB from Combined Matrix","Message-ID":"<20260408174342.GE1965119@killaraus.ideasonboard.com>","References":"<20260407-kbingham-awb-split-v1-0-a39af3f4dc20@ideasonboard.com>\n\t<20260407-kbingham-awb-split-v1-2-a39af3f4dc20@ideasonboard.com>\n\t<20260408000101.GM1268443@killaraus.ideasonboard.com>\n\t<853415g11b.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>\n\t<177566921061.575056.12572454224071478541@ping.linuxembedded.co.uk>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<177566921061.575056.12572454224071478541@ping.linuxembedded.co.uk>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":38550,"web_url":"https://patchwork.libcamera.org/comment/38550/","msgid":"<858qax9scd.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","date":"2026-04-08T19:15:14","subject":"Re: [PATCH 02/13] softisp: Split AWB from Combined Matrix","submitter":{"id":177,"url":"https://patchwork.libcamera.org/api/people/177/","name":"Milan Zamazal","email":"mzamazal@redhat.com"},"content":"Laurent Pinchart <laurent.pinchart@ideasonboard.com> writes:\n\n> On Wed, Apr 08, 2026 at 06:26:50PM +0100, Kieran Bingham wrote:\n>> Quoting Milan Zamazal (2026-04-08 12:10:56)\n>> > Laurent Pinchart <laurent.pinchart@ideasonboard.com> writes:\n>\n>> > > On Tue, Apr 07, 2026 at 11:01:05PM +0100, Kieran Bingham wrote:\n>> > >> Move the AWB gains out of the combined matrix and pass\n>> > >> them directly to the EGL shaders.\n>> > >\n>> > >> \n>> > >> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n>> > >> ---\n>> > >>  src/ipa/simple/algorithms/awb.cpp          | 16 +++-------------\n>> > >>  src/ipa/simple/ipa_context.h               |  5 +----\n>> > >>  src/libcamera/shaders/bayer_1x_packed.frag |  4 ++++\n>> > >>  src/libcamera/shaders/bayer_unpacked.frag  |  4 ++++\n>> > >>  src/libcamera/software_isp/debayer_egl.cpp |  5 +++++\n>> > >>  src/libcamera/software_isp/debayer_egl.h   |  3 +++\n>> > >>  6 files changed, 20 insertions(+), 17 deletions(-)\n>> > >> \n>> > >> diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp\n>> > >> index f5c88ea6f896ff8a7ffdc328e09a4d4aa99df5e4..05155c83d172d64609053ba940a4c12a2248bb04 100644\n>> > >> --- a/src/ipa/simple/algorithms/awb.cpp\n>> > >> +++ b/src/ipa/simple/algorithms/awb.cpp\n>> > >> @@ -38,15 +38,8 @@ void Awb::prepare(IPAContext &context,\n>> > >>                DebayerParams *params)\n>> > >>  {\n>> > >>      auto &gains = context.activeState.awb.gains;\n>> > >> -    Matrix<float, 3, 3> gainMatrix = { { gains.r(), 0, 0,\n>> > >> -                                         0, gains.g(), 0,\n>> > >> -                                         0, 0, gains.b() } };\n>> > >> -    context.activeState.combinedMatrix =\n>> > >> -            gainMatrix * context.activeState.combinedMatrix;\n>> > >\n>> > > The combined matrix is used by the CPU implementation too, aren't you\n>> > > breaking AWB there ?\n>> > \n>> > Yes, AWB is not applied in CPU ISP after this change.  It gets applied\n>> > again in \"Apply gains in CPU ISP\" patch; should the two be squashed?\n>> > \n>> > Other than that, the change itself looks good to me.\n>> \n>> Is it safe to swap the order and put your patches first to maintain\n>> 'correctness' in bisection?\n>\n> Then you will apply them twice.\n\nThe black level patch can be applied separately and before this patch.\n\nThe gains patch not, it must be applied at the same time as this change;\nit's like the GPU ISP changes here, which are also not easily separable.\n\n>> > >> -\n>> > >> -    frameContext.gains.red = gains.r();\n>> > >> -    frameContext.gains.blue = gains.b();\n>> > >>  \n>> > >> +    frameContext.gains = gains;\n>> > >>      params->gains = gains;\n>> > >>  }\n>> > >>  \n>> > >> @@ -59,11 +52,8 @@ void Awb::process(IPAContext &context,\n>> > >>      const SwIspStats::Histogram &histogram = stats->yHistogram;\n>> > >>      const uint8_t blackLevel = context.activeState.blc.level;\n>> > >>  \n>> > >> -    const float mdGains[] = {\n>> > >> -            static_cast<float>(frameContext.gains.red),\n>> > >> -            static_cast<float>(frameContext.gains.blue)\n>> > >> -    };\n>> > >> -    metadata.set(controls::ColourGains, mdGains);\n>> > >> +    metadata.set(controls::ColourGains, { frameContext.gains.r(),\n>> > >> +                                          frameContext.gains.b() });\n>> > >>  \n>> > >>      if (!stats->valid)\n>> > >>              return;\n>> > >> diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h\n>> > >> index 34f7403a41d690cb3f0c271827ae2e915b6ea49d..8ccfacb46a59cedb5a0ad051d67f7c1f40af4b52 100644\n>> > >> --- a/src/ipa/simple/ipa_context.h\n>> > >> +++ b/src/ipa/simple/ipa_context.h\n>> > >> @@ -71,10 +71,7 @@ struct IPAFrameContext : public FrameContext {\n>> > >>              double gain;\n>> > >>      } sensor;\n>> > >>  \n>> > >> -    struct {\n>> > >> -            double red;\n>> > >> -            double blue;\n>> > >> -    } gains;\n>> > >> +    RGB<float> gains;\n>> > >>  \n>> > >>      float gamma;\n>> > >>      std::optional<float> contrast;\n>> > >> diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag\n>> > >> index 23747f78a6313503a46b61ed5bae6e7c178c5745..9a1992e219dd066945b3f46ec509f47a31590385 100644\n>> > >> --- a/src/libcamera/shaders/bayer_1x_packed.frag\n>> > >> +++ b/src/libcamera/shaders/bayer_1x_packed.frag\n>> > >> @@ -65,6 +65,7 @@ uniform vec2 tex_step;\n>> > >>  uniform vec2 tex_bayer_first_red;\n>> > >>  \n>> > >>  uniform sampler2D tex_y;\n>> > >> +uniform vec3 awb;\n>> > >\n>> > > I'd name this wbGains or colourGains, that's more explicit. Same below.\n>> \n>> I'd like to introduce a full 'DigitalGain' control at somepoint (soon)\n>> which will be where/how awb will be applied. So I think it would get\n>> renamed then too.\n>> \n>> I could accept colourGains already for that I guess...\n>> \n>> > >>  uniform mat3 ccm;\n>> > >>  uniform vec3 blacklevel;\n>> > >>  uniform float gamma;\n>> > >> @@ -227,6 +228,9 @@ void main(void)\n>> > >>  \n>> > >>      rgb = rgb - blacklevel;\n>> > >>  \n>> > >> +    /* Apply AWB gains, and saturate each channel at sensor range */\n>> > >> +    rgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel);\n>> > >> +\n>> > >>      /*\n>> > >>       *   CCM is a 3x3 in the format\n>> > >>       *\n>> > >> diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag\n>> > >> index 76ffc47a8a29f242c1fba88f32bd8db731edeee0..87e4e4915fe19679943fdcc3d213a0224b89065e 100644\n>> > >> --- a/src/libcamera/shaders/bayer_unpacked.frag\n>> > >> +++ b/src/libcamera/shaders/bayer_unpacked.frag\n>> > >> @@ -24,6 +24,7 @@ uniform sampler2D       tex_y;\n>> > >>  varying vec4            center;\n>> > >>  varying vec4            yCoord;\n>> > >>  varying vec4            xCoord;\n>> > >> +uniform vec3            awb;\n>> > >>  uniform mat3            ccm;\n>> > >>  uniform vec3            blacklevel;\n>> > >>  uniform float           gamma;\n>> > >> @@ -130,6 +131,9 @@ void main(void) {\n>> > >>  \n>> > >>      rgb = rgb - blacklevel;\n>> > >>  \n>> > >> +    /* Apply AWB gains, and saturate each channel at sensor range */\n>> > >> +    rgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel);\n>> > >> +\n>> > >>      /*\n>> > >>       *   CCM is a 3x3 in the format\n>> > >>       *\n>> > >> diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp\n>> > >> index 2ad258bca69fb8dff19e35d9239ebd7d350590ae..738036e649224f370bdf9a0cc59b399f8b1066de 100644\n>> > >> --- a/src/libcamera/software_isp/debayer_egl.cpp\n>> > >> +++ b/src/libcamera/software_isp/debayer_egl.cpp\n>> > >> @@ -100,6 +100,7 @@ int DebayerEGL::getShaderVariableLocations(void)\n>> > >>      attributeTexture_ = glGetAttribLocation(programId_, \"textureIn\");\n>> > >>  \n>> > >>      textureUniformBayerDataIn_ = glGetUniformLocation(programId_, \"tex_y\");\n>> > >> +    awbUniformDataIn_ = glGetUniformLocation(programId_, \"awb\");\n>> > >>      ccmUniformDataIn_ = glGetUniformLocation(programId_, \"ccm\");\n>> > >>      blackLevelUniformDataIn_ = glGetUniformLocation(programId_, \"blacklevel\");\n>> > >>      gammaUniformDataIn_ = glGetUniformLocation(programId_, \"gamma\");\n>> > >> @@ -113,6 +114,7 @@ int DebayerEGL::getShaderVariableLocations(void)\n>> > >>  \n>> > >>      LOG(Debayer, Debug) << \"vertexIn \" << attributeVertex_ << \" textureIn \" << attributeTexture_\n>> > >>                          << \" tex_y \" << textureUniformBayerDataIn_\n>> > >> +                        << \" awb \" << awbUniformDataIn_\n>> > >>                          << \" ccm \" << ccmUniformDataIn_\n>> > >>                          << \" blacklevel \" << blackLevelUniformDataIn_\n>> > >>                          << \" gamma \" << gammaUniformDataIn_\n>> > >> @@ -481,6 +483,9 @@ void DebayerEGL::setShaderVariableValues(const DebayerParams &params)\n>> > >>      glUniform3f(blackLevelUniformDataIn_, params.blackLevel[0], params.blackLevel[1], params.blackLevel[2]);\n>> > >>      LOG(Debayer, Debug) << \" blackLevelUniformDataIn_ \" << blackLevelUniformDataIn_ << \" data \" << params.blackLevel;\n>> > >>  \n>> > >> +    glUniform3f(awbUniformDataIn_, params.gains[0], params.gains[1], params.gains[2]);\n>> > >> +    LOG(Debayer, Debug) << \" awbUniformDataIn_ \" << awbUniformDataIn_ << \" data \" << params.gains;\n>> > >> +\n>> > >>      /*\n>> > >>       * Gamma\n>> > >>       */\n>> > >> diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h\n>> > >> index bdde676f2394e7298006c88bbec75917800af4ad..23ef99117fbd209246ae565141a2365c6a7b0a63 100644\n>> > >> --- a/src/libcamera/software_isp/debayer_egl.h\n>> > >> +++ b/src/libcamera/software_isp/debayer_egl.h\n>> > >> @@ -97,6 +97,9 @@ private:\n>> > >>  \n>> > >>      GLint textureUniformBayerDataIn_;\n>> > >>  \n>> > >> +    /* Per-frame AWB gains */\n>> > >\n>> > > All the uniforms below are per-frame parameters, I'd drop the\n>> > > \"per-frame\".\n>> > >\n>> > > Sorting the members in processing block order (in a separate patch)\n>> > > would make it easier to follow the code.\n>> \n>> Yes, I think processing order is the most useful ordering.\n>> \n>> > >\n>> > >> +    GLint awbUniformDataIn_;\n>> > >> +\n>> > >>      /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */\n>> > >>      GLint ccmUniformDataIn_;\n>> > >>  \n>> > >>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id C4504BEFBE\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed,  8 Apr 2026 19:15:23 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id EBC4262E0E;\n\tWed,  8 Apr 2026 21:15:22 +0200 (CEST)","from us-smtp-delivery-124.mimecast.com\n\t(us-smtp-delivery-124.mimecast.com [170.10.133.124])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 3B5A462CE6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  8 Apr 2026 21:15:21 +0200 (CEST)","from mail-wr1-f72.google.com (mail-wr1-f72.google.com\n\t[209.85.221.72]) by relay.mimecast.com with ESMTP with STARTTLS\n\t(version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n\tus-mta-610-NpYWs-dSMXS2dCSdxPAJmQ-1; Wed, 08 Apr 2026 15:15:18 -0400","by mail-wr1-f72.google.com with SMTP id\n\tffacd0b85a97d-43d121c4271so35683f8f.3\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 08 Apr 2026 12:15:18 -0700 (PDT)","from mzamazal-thinkpadp1gen7.tpbc.csb\n\t(ip-77-48-47-2.net.vodafone.cz. [77.48.47.2])\n\tby smtp.gmail.com with ESMTPSA id\n\tffacd0b85a97d-43d1e4d282esm60481024f8f.18.2026.04.08.12.15.14\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tWed, 08 Apr 2026 12:15:15 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=redhat.com header.i=@redhat.com\n\theader.b=\"iNnIP7WF\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1775675720;\n\th=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n\tto:to:cc:cc:mime-version:mime-version:content-type:content-type:\n\tin-reply-to:in-reply-to:references:references;\n\tbh=rpWHYgNxrDbsni/76b9uGsq1Kq95muf7HU7/lX2tpAY=;\n\tb=iNnIP7WFlab2/LSHEkFHPjOSySMhRGhGIplsxdSzd30wDH6iKrHC0G6OsIT1gkDpsS1K7+\n\t1edJV4oUHBAMibdmGWvjp2GcglQwB0Ppts9XP5iMpjia7BOuEsh+Bcauk9eW2oLE0J52vs\n\tWniPYmOoAdfsGONY9fZeGlzLpdm5qBQ=","X-MC-Unique":"NpYWs-dSMXS2dCSdxPAJmQ-1","X-Mimecast-MFC-AGG-ID":"NpYWs-dSMXS2dCSdxPAJmQ_1775675717","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20251104; t=1775675717; x=1776280517;\n\th=mime-version:user-agent:message-id:date:references:in-reply-to\n\t:subject:cc:to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject\n\t:date:message-id:reply-to;\n\tbh=rpWHYgNxrDbsni/76b9uGsq1Kq95muf7HU7/lX2tpAY=;\n\tb=ngjrZNy2nTYJcN5zTmVUyOyTgomtXiV9KAbCdZpxujTwiZlK7uy95C0nYhh2VyVBik\n\t+ETA0EKBjmEwhw4yfr066yTU1l+4QTDwNidm2Mtww1KvQ+2QBz1zKuRp4JSs9LLeE0n4\n\t3KiyVJAxxkPXuYFrvhI1e7x4oXqrp9mkf/rJjjqiBzXOKtp1p2eUeTAmO78OQUtZjou/\n\tRQZBCTuFKKBkBAU6K1Y4Ga0OlSypYR8wXDfDuI8F9JsPQ1Cfa0BOJczwwouvVW9pIhwE\n\tuTCcWo0wUUAvJgEomyYCSjF5fAQYORQ1x5G1CUYd3zVvfj6wpCIMXzOUOND1RZRRLd/t\n\tO+3w==","X-Forwarded-Encrypted":"i=1;\n\tAJvYcCWQ8VI/NvDR0zg+ML62AXkjT/0NEC9YWVbuj36uFhJBORdUaZQ0SvYTfIfKE0GSiqMDajrTQRuR53kpuWAdm5Y=@lists.libcamera.org","X-Gm-Message-State":"AOJu0YyvVWOlgF22mYp98qaY/OVm3SspuHJhTB1JjktoTNV3ax0qM5v/\n\tboz44pkLlntcZzq9sXDupQEW/MrfQBmMIoS75aNey2HlSgVIcx7MAxE7EuEGYq6QmZQhUJ/xHir\n\tQwnjOO9J+jEjEaePyd3PXj63sVCG56LhoAwWHangdh6hz5GomHpmnWc0Ed4q7lpDTNcSl3Zw1TX\n\tQXdHnUQw/ZYfmmO/7GekSPxWR+pm9liTKbhTXvgqYm+qf8VNIgbDlnHiPnthc=","X-Gm-Gg":"AeBDiesGKzmtZfpL3b27fz/nuUhtWy/Nbk4FDggA0SoF7OIbzb93Otn1y1v8+APGVWH\n\t0SVOeBGCfvEpCCyd2T5lilZUXpotsuNoX0Nnj6gWu2KUxUrLymmgU3zKMFWsaMpu4mfOUGp48IP\n\t2fc+j0FTAmx886iiy1KjS/IZ77pjU0T1ULYUrNB9JmPCH0SpXAjV0KVVJhjIvXloax7PwJMKePZ\n\tN+3+1EuN2nVQT979lIsXQdbNMgwN0wQ3nG7o8ep8qFdD7WaaHkM25C3DDNZRXcbRcm29sxec11S\n\tZB1VhlND0w0wt+jmffwcT9bv6XfrLFQBBpW4Ly+YjvvgkF6iWoICjidz2Z/AXRAxUHz/FhhUxBw\n\tMLdu1glfsaj0Ox2iiHLg4oOzB+/px2RfADDq0S9onTn2IReI5DATo0oE5nesMFvrX3JOKKXXpK1\n\tU=","X-Received":["by 2002:a5d:584e:0:b0:43c:f81f:3e78 with SMTP id\n\tffacd0b85a97d-43d5a126eacmr642327f8f.5.1775675716783; \n\tWed, 08 Apr 2026 12:15:16 -0700 (PDT)","by 2002:a5d:584e:0:b0:43c:f81f:3e78 with SMTP id\n\tffacd0b85a97d-43d5a126eacmr642283f8f.5.1775675716132; \n\tWed, 08 Apr 2026 12:15:16 -0700 (PDT)"],"From":"Milan Zamazal <mzamazal@redhat.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH 02/13] softisp: Split AWB from Combined Matrix","In-Reply-To":"<20260408174342.GE1965119@killaraus.ideasonboard.com> (Laurent\n\tPinchart's message of \"Wed, 8 Apr 2026 20:43:42 +0300\")","References":"<20260407-kbingham-awb-split-v1-0-a39af3f4dc20@ideasonboard.com>\n\t<20260407-kbingham-awb-split-v1-2-a39af3f4dc20@ideasonboard.com>\n\t<20260408000101.GM1268443@killaraus.ideasonboard.com>\n\t<853415g11b.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>\n\t<177566921061.575056.12572454224071478541@ping.linuxembedded.co.uk>\n\t<20260408174342.GE1965119@killaraus.ideasonboard.com>","Date":"Wed, 08 Apr 2026 21:15:14 +0200","Message-ID":"<858qax9scd.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","User-Agent":"Gnus/5.13 (Gnus v5.13)","MIME-Version":"1.0","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"TGbhF-AskvHH8D3jBtXYWZP3TElIIWEbWFdfzXujibk_1775675717","X-Mimecast-Originator":"redhat.com","Content-Type":"text/plain","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":38768,"web_url":"https://patchwork.libcamera.org/comment/38768/","msgid":"<43622f9e-6232-4e26-bb3d-8c64e8900e64@oss.qualcomm.com>","date":"2026-05-07T12:21:04","subject":"Re: [PATCH 02/13] softisp: Split AWB from Combined Matrix","submitter":{"id":242,"url":"https://patchwork.libcamera.org/api/people/242/","name":"Hans de Goede","email":"johannes.goede@oss.qualcomm.com"},"content":"Hi,\n\nThank you for your work on this.\n\nOn 8-Apr-26 00:01, Kieran Bingham wrote:\n> Move the AWB gains out of the combined matrix and pass\n> them directly to the EGL shaders.\n> \n> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> ---\n\n<snip>\n\n> diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag\n> index 23747f78a6313503a46b61ed5bae6e7c178c5745..9a1992e219dd066945b3f46ec509f47a31590385 100644\n> --- a/src/libcamera/shaders/bayer_1x_packed.frag\n> +++ b/src/libcamera/shaders/bayer_1x_packed.frag\n> @@ -65,6 +65,7 @@ uniform vec2 tex_step;\n>  uniform vec2 tex_bayer_first_red;\n>  \n>  uniform sampler2D tex_y;\n> +uniform vec3 awb;\n>  uniform mat3 ccm;\n>  uniform vec3 blacklevel;\n>  uniform float gamma;\n> @@ -227,6 +228,9 @@ void main(void)\n>  \n>  \trgb = rgb - blacklevel;\n>  \n> +\t/* Apply AWB gains, and saturate each channel at sensor range */\n> +\trgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel);\n> +\n\nWhy clamp to 1.0 - blacklevel?  Why no just clamp at 1.0. I'm not sure\nwhat limiting the range to e.g. 0-240 here has as advantage ?\n\nTo me this seems undesirable.\n\n(same comment for the unpacked shader)\n\nRegards,\n\nHans","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id D881CBDCB5\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu,  7 May 2026 12:21:12 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 7675E6301E;\n\tThu,  7 May 2026 14:21:11 +0200 (CEST)","from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com\n\t[205.220.180.131])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 34F4062010\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  7 May 2026 14:21:09 +0200 (CEST)","from pps.filterd (m0279869.ppops.net [127.0.0.1])\n\tby mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id\n\t647BZ17N3157880 for <libcamera-devel@lists.libcamera.org>;\n\tThu, 7 May 2026 12:21:07 GMT","from mail-vk1-f200.google.com (mail-vk1-f200.google.com\n\t[209.85.221.200])\n\tby mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4e0mhf1gjx-1\n\t(version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT)\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 07 May 2026 12:21:07 +0000 (GMT)","by mail-vk1-f200.google.com with SMTP id\n\t71dfb90a1353d-5752402f5e1so1595682e0c.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 07 May 2026 05:21:07 -0700 (PDT)","from ?IPV6:2001:1c00:c32:7800:5bfa:a036:83f0:f9ec?\n\t(2001-1c00-0c32-7800-5bfa-a036-83f0-f9ec.cable.dynamic.v6.ziggo.nl.\n\t[2001:1c00:c32:7800:5bfa:a036:83f0:f9ec])\n\tby smtp.gmail.com with ESMTPSA id\n\ta640c23a62f3a-bc81cd347c6sm75051266b.7.2026.05.07.05.21.05\n\t(version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128);\n\tThu, 07 May 2026 05:21:05 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=qualcomm.com header.i=@qualcomm.com\n\theader.b=\"I+a6PmtI\"; dkim=pass (2048-bit key;\n\tunprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com\n\theader.b=\"gUfwCGE7\"; dkim-atps=neutral","DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h=\n\tcontent-transfer-encoding:content-type:date:from:in-reply-to\n\t:message-id:mime-version:references:subject:to; s=qcppdkim1; bh=\n\tgqv4Ui5mFZkOa+hBLyD9vT/8AunjeGLKjj5lZdfjLMQ=; b=I+a6PmtI2ZO7v2kn\n\tYUYGg3IhYyNu/o84xAOPwWc6SHGD2tPOQieOfZBMZM6/Qr/YgO3p6rA6W47qEfEz\n\tcrJxX0a6+ASP3mppRdk91K/oYgnk+f+AMvJPSbriMgi3uMQFXSSFANl96lZJeHGI\n\tG/Xr9pHjYkUFjjXQ302SqjkTIr5+kN0btjlu7rjtzlO6MzVwW/cNrnrIKtNsgtpk\n\tbu/1ggChxI+D18d5Ee0XLrs0BASVqRagxCK6fbQ9zQqrHgI9opXMBqx7t489FNqd\n\tT/3lWpMODj/komOcpoHdYAorBm+/urWPsc8+lQ4TfCgwE7aH9XjP8/1QdauUrngz\n\tU6ql6g==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=oss.qualcomm.com; s=google; t=1778156467; x=1778761267;\n\tdarn=lists.libcamera.org; \n\th=content-transfer-encoding:in-reply-to:content-language:references\n\t:to:subject:from:user-agent:mime-version:date:message-id:from:to:cc\n\t:subject:date:message-id:reply-to;\n\tbh=gqv4Ui5mFZkOa+hBLyD9vT/8AunjeGLKjj5lZdfjLMQ=;\n\tb=gUfwCGE7oWxKDaCSq5HpnDMNsqNV+NONyaWlX3V3AUl/pKrFJ8MrIVWHoDIM09pf48\n\tWGpLSl7g4TSoZbvZSZGsJ5HX1wtITarZE7Ce79gZt95avf/rqWp9Tj5JgAeGIu6aO5QK\n\tgv/y22Mg8RGg9iqdXT4YD0zlh0o9qBL7hidcpvyruY6Fm/Wb5dBoLH50kPfZPNQ4ZXWV\n\tYd1HRpsCrIFhe8BrDiJKb7J4St+yelP0WlrmWbbBPVh1X7kvZNDIFxPShcduvHqZCZXH\n\tcF7srhmONJlhoYIDZ2VZn08kNl6yOjaqHw1V/dJf4qC16LOjE2KgN2+JzFZUyLO8xWKI\n\tvIXg=="],"X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20251104; t=1778156467; x=1778761267;\n\th=content-transfer-encoding:in-reply-to:content-language:references\n\t:to:subject:from:user-agent:mime-version:date:message-id:x-gm-gg\n\t:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to;\n\tbh=gqv4Ui5mFZkOa+hBLyD9vT/8AunjeGLKjj5lZdfjLMQ=;\n\tb=B9p5wiJEUOYT6OzGk39UkhIzUgb7r4F+Q3kuKwNBW2obW+cI3satdUyMntQ5u/PcBO\n\tXwtAbnZBhuB+M3BPo3hQbfb+cC5osI+GupMntRz0LtvRMOYL0UocgpGZ6PbhT0nKVXGl\n\t7DaFYJvQ2o9HtFZH2zaryAMxmQE0dpMFE29x3Nvq5VosPElMUFVup2j2SnWdWKry2GUZ\n\tvM+rTUOsKQCKbLNJSX9WDMupNj39Gtrjn5K71pWKmgMyhgc1IGHZaF3iIzuRijF2k7UU\n\tlEbEJEDKf/7auju2SO+XgjHqfHTc+M7OTUoyUn9u7qWTdzcEe6TyKo92hHkI6aIEmmSY\n\tMSgA==","X-Forwarded-Encrypted":"i=1;\n\tAFNElJ/UycLgqpFGX15CDBzt7MP7kTy6lNYTNtfZ/eNO9uFbbhdkrxg1SlkbjCPisxiSp6IBmZ/RYCrw1sb+WqmgFGU=@lists.libcamera.org","X-Gm-Message-State":"AOJu0Ywn7SAGpIYShFWIUBlUEX5yb3IcNaJJL43Ug6S32aphLTrCUP1b\n\t5ld/5aHTRlXM/qpmNFKiMa6uGqIJydiTIGhDt7bScKeX2105+uh/KGLVE/kEZ1k4uQA+aNFXA8N\n\tsBgzHZwFvaqJJapxappyGA8RtiPZCmyob1mPpk6eHPsBF/2hPHD/64xy8zA0mMhmJ5iZEQHX4i1\n\tvX","X-Gm-Gg":"AeBDieswMWcNzvMhVNZe1Dn0g0A55stAxDEu2c1NPYWRlaG/U1fVxVv7LUnY0RaWMTG\n\teSCUw8YWjUquu/9NWwYTohd2Fx63q5JHorfLsLjG9qQtVnMjeJohzuAUrHmEd5N/6iqJBVXL+nh\n\tsW3aC/IecXkJ4hhFkM3bAurrMMFoAmGJY+CnAMQFmwX4+UkCfDn/odgXEnzwkhVL7ukYuYEv4y5\n\tMO4yI3y3Dl3Zq+W5q/R/Sg7opcD8Ib3mGVcwlOmK9lb8CrQTacJ+DK5JI06GiE1Dh6g51W4x9KN\n\tiUutMyheUuj+lNa/zUSYQuRTjiEatUb37dMdM10SKNpJW5q2PpuvymVqIhglPkqulxqUXO9G0xL\n\tHGyQK/RdR03Tf5n1L302jxSbyg1yG9B3InWBWlK7+psh4Xz1ly2XdL4bMZlw2zDBjA58qOP35jV\n\t6WulEyq1ombNoEtZXSu2By84nmAbTR9JV47eRdP60tnVIB0KEvIjTDsy+eiB5ZOaaMfdGHEdPpq\n\tVd6/UFkq/NYDJaZ9LuU15Jt0PA=","X-Received":["by 2002:a05:6123:2e5:b0:56c:d5cd:1e7c with SMTP id\n\t71dfb90a1353d-57559559f3emr4526977e0c.5.1778156467084; \n\tThu, 07 May 2026 05:21:07 -0700 (PDT)","by 2002:a05:6123:2e5:b0:56c:d5cd:1e7c with SMTP id\n\t71dfb90a1353d-57559559f3emr4526938e0c.5.1778156466672; \n\tThu, 07 May 2026 05:21:06 -0700 (PDT)"],"Message-ID":"<43622f9e-6232-4e26-bb3d-8c64e8900e64@oss.qualcomm.com>","Date":"Thu, 7 May 2026 14:21:04 +0200","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","From":"johannes.goede@oss.qualcomm.com","Subject":"Re: [PATCH 02/13] softisp: Split AWB from Combined Matrix","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","References":"<20260407-kbingham-awb-split-v1-0-a39af3f4dc20@ideasonboard.com>\n\t<20260407-kbingham-awb-split-v1-2-a39af3f4dc20@ideasonboard.com>","Content-Language":"en-US, nl","In-Reply-To":"<20260407-kbingham-awb-split-v1-2-a39af3f4dc20@ideasonboard.com>","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"7bit","X-Proofpoint-Spam-Details-Enc":"AW1haW4tMjYwNTA3MDEyMSBTYWx0ZWRfXyW1lHgB7Jrjt\n\tqguhYjW44NY3rnWCYyompJSNJ/2CG/xwBaSQ9Bc5It7gllEXMsVpoz2oiM5LkJFf2ZHGpZyx3KB\n\tuepe2W3Z68EE9+9tgvUDWr0x8/hmQ4b6WT6QqOIlkBjMQNPA+hrRBBrvCmV1WuhHr4zhplHtKMT\n\tGXL9JUDQBIAcekkylsyE27snZPOo5d1GsOwp1Vq/2K27uGWDvI6wwZj+ZW5QUQlgOgqjCj/wmwq\n\tBylD5YQVBRGu3Hy0FrVghT99yLvfF+R2yowsaaLCELE8qYSKvaUWKVRgKoBVtv9ST72Vpl8JSku\n\towNeDbTD8cXDnoCIyb3oexyDZd1ffzNty+dMIq2OW8wUrreA1MqSezmiWhR2UcGVyQrZnk4F6Uz\n\t/rDFu/YYyI4XBAIiJBzkb219CMZiYY+e3Cl215dXg8pXrUyZ+Lvi5dkObXlsEmkVECNzoqIcYai\n\tE3X+3jwp9MSQzMaC6gQ==","X-Proofpoint-ORIG-GUID":"ln3N84ipAQln_AHEqVNI6-5V8AKSBN6D","X-Authority-Analysis":"v=2.4 cv=SuagLvO0 c=1 sm=1 tr=0 ts=69fc83b3 cx=c_pps\n\ta=wuOIiItHwq1biOnFUQQHKA==:117 a=xqWC_Br6kY4A:10 a=IkcTkHD0fZMA:10\n\ta=NGcC8JguVDcA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22\n\ta=u7WPNUs3qKkmUXheDGA7:22 a=_glEPmIy2e8OvE2BGh3C:22 a=P1BnusSwAAAA:8\n\ta=-kYw-eEVRYrgrnezv6IA:9 a=QEXdDO2ut3YA:10 a=XD7yVLdPMpWraOa8Un9W:22\n\ta=D0XLA9XvdZm18NrgonBM:22","X-Proofpoint-GUID":"ln3N84ipAQln_AHEqVNI6-5V8AKSBN6D","X-Proofpoint-Virus-Version":"vendor=baseguard\n\tengine=ICAP:2.0.293, Aquarius:18.0.1143, Hydra:6.1.51,\n\tFMLib:17.12.100.49\n\tdefinitions=2026-05-07_01,2026-05-06_01,2025-10-01_01","X-Proofpoint-Spam-Details":"rule=outbound_notspam policy=outbound score=0\n\tclxscore=1015 malwarescore=0 suspectscore=0 bulkscore=0\n\tlowpriorityscore=0\n\timpostorscore=0 spamscore=0 adultscore=0 phishscore=0\n\tpriorityscore=1501\n\tclassifier=typeunknown authscore=0 authtc= authcc= route=outbound\n\tadjust=0\n\treason=mlx scancount=1 engine=8.22.0-2604200000\n\tdefinitions=main-2605070121","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":38792,"web_url":"https://patchwork.libcamera.org/comment/38792/","msgid":"<855x4zutzr.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","date":"2026-05-07T15:20:08","subject":"Re: [PATCH 02/13] softisp: Split AWB from Combined Matrix","submitter":{"id":177,"url":"https://patchwork.libcamera.org/api/people/177/","name":"Milan Zamazal","email":"mzamazal@redhat.com"},"content":"johannes.goede@oss.qualcomm.com writes:\n\n> Hi,\n>\n> Thank you for your work on this.\n>\n> On 8-Apr-26 00:01, Kieran Bingham wrote:\n>> Move the AWB gains out of the combined matrix and pass\n>> them directly to the EGL shaders.\n>> \n>> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n>> ---\n>\n> <snip>\n>\n>> diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag\n>> index 23747f78a6313503a46b61ed5bae6e7c178c5745..9a1992e219dd066945b3f46ec509f47a31590385 100644\n>> --- a/src/libcamera/shaders/bayer_1x_packed.frag\n>> +++ b/src/libcamera/shaders/bayer_1x_packed.frag\n>> @@ -65,6 +65,7 @@ uniform vec2 tex_step;\n>>  uniform vec2 tex_bayer_first_red;\n>>  \n>>  uniform sampler2D tex_y;\n>> +uniform vec3 awb;\n>>  uniform mat3 ccm;\n>>  uniform vec3 blacklevel;\n>>  uniform float gamma;\n>> @@ -227,6 +228,9 @@ void main(void)\n>>  \n>>  \trgb = rgb - blacklevel;\n>>  \n>> +\t/* Apply AWB gains, and saturate each channel at sensor range */\n>> +\trgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel);\n>> +\n>\n> Why clamp to 1.0 - blacklevel?  Why no just clamp at 1.0. I'm not sure\n> what limiting the range to e.g. 0-240 here has as advantage ?\n\nI think the primary problem is that the green gain is always 1, so green\ncannot exceed 1.0 - blacklevel.  If the other channels are allowed above\nthat limit, you get colour casts.\n\nAnother thing to consider may be that moving out of the sensor range\nincreases risks of values getting wild when applying the CCM, which is\nsupposed to be calibrated only for the sensor range.\n\n> To me this seems undesirable.\n>\n> (same comment for the unpacked shader)\n>\n> Regards,\n>\n> Hans","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 9DCEFBDCB5\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu,  7 May 2026 15:20:19 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id AEBF062FE1;\n\tThu,  7 May 2026 17:20:18 +0200 (CEST)","from us-smtp-delivery-124.mimecast.com\n\t(us-smtp-delivery-124.mimecast.com [170.10.129.124])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 7AE5A62010\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  7 May 2026 17:20:16 +0200 (CEST)","from mail-wr1-f69.google.com (mail-wr1-f69.google.com\n\t[209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS\n\t(version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n\tus-mta-189-xSS63ni-NHSKZ3Pgymvtxg-1; Thu, 07 May 2026 11:20:13 -0400","by mail-wr1-f69.google.com with SMTP id\n\tffacd0b85a97d-449b2a183d3so676723f8f.0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 07 May 2026 08:20:13 -0700 (PDT)","from mzamazal-thinkpadp1gen7.tpbc.csb\n\t(ip-77-48-47-4.net.vodafone.cz. [77.48.47.4])\n\tby smtp.gmail.com with ESMTPSA id\n\tffacd0b85a97d-45052953383sm19935366f8f.13.2026.05.07.08.20.09\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tThu, 07 May 2026 08:20:10 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=redhat.com header.i=@redhat.com\n\theader.b=\"ZZBHTxC4\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1778167215;\n\th=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n\tto:to:cc:cc:mime-version:mime-version:content-type:content-type:\n\tin-reply-to:in-reply-to:references:references;\n\tbh=IH2rWjfRMnl6R6s+zYO46zpzW3XT0DXJQ1mq+lUplS8=;\n\tb=ZZBHTxC4rFO53rdmWmO0Yitm3fpPZMprSIrQm8q2gn/9RvEaOcBnzipcCReKkqGyzYhFZ2\n\tigGLIzPupWkr6u+eyNQvN4UerNV5VhJzDGIxqijM2HJJuRJFPNCVEH+0LLJRlRj5YH6Pls\n\tO1fU7xeQPHSQvUj5NcTUDLGPGtLtiwY=","X-MC-Unique":"xSS63ni-NHSKZ3Pgymvtxg-1","X-Mimecast-MFC-AGG-ID":"xSS63ni-NHSKZ3Pgymvtxg_1778167213","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20251104; t=1778167212; x=1778772012;\n\th=mime-version:user-agent:message-id:date:references:in-reply-to\n\t:subject:cc:to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject\n\t:date:message-id:reply-to;\n\tbh=IH2rWjfRMnl6R6s+zYO46zpzW3XT0DXJQ1mq+lUplS8=;\n\tb=GI4NxqcY+VVI00lWqmZIbABmFJPF8eSkLhEFPHPXmlFkzJ0UKvIrBQGswZsbkoO7fk\n\tcfr9EN9nwH7dBNPPEHwdZVrUNVYYV0rsuW2eFEl31cbcAQ1Px5y32NV81OrAKnKw3y/2\n\tLbsWXtxdKEfux47XnZm3+ua4M95zwDYbM1MDPWJWcCwsjcBH5451ICCYYfP3Nhm/4/nP\n\tBItNzceczKoKlhi6occL3DcW/QR43FxZF3cOkvZoDyEYcKRoHRpkGNtI7fT8QLG2XRIS\n\tQ7EgX4CiDabjAWretbnAGZgiVnwK36Z7nnaKm3bIPhz2NIO5GMC+gKsL3tG9i5J+LWt2\n\to/dA==","X-Forwarded-Encrypted":"i=1;\n\tAFNElJ8G7QUJXw7TPcNdxAq8PGZQ/CSLJi0Fn3g66Aj31cOChpPsT7opMvmWU3bM3Q1Y4ACsw06mtXFuWVy1z7e/VCU=@lists.libcamera.org","X-Gm-Message-State":"AOJu0YzrUTDQllEqyLCwCFTU+mwNFULteht60goEjOezoX2IiNPwiHVX\n\tADLqneMWHZvvCge4XGbCiz4OFGoetsG3Hs188hx1FxPELKynLTZW2au+j0SeTlaIIlqNBl+f8xB\n\tKeeca8DrkCFPomTvjTjw9BkmF8hfvzZKndpt9O5tbjit8x/sSl5rv6VzKLluFNTY9FZDg9/rcuv\n\trwZ8qz6BLnVfDsPN3KZhRlmDAtnKKS+9Plg7wvd8glCFmyLqMjFuh3asiIrao=","X-Gm-Gg":"AeBDietkRRyRVdjD/Lxh3q2Pv4jrLRimbQvpSNXd2riIaj9O2xJy2jLrtZR7aJejGHU\n\tBKqBaqr2yxU9oONJqFovGOqbXhoLutztUEBLbYZ3eONWjfbFz20BNvicHR2SVPwa2n9JI//KojI\n\t+UlJHyTxHGAogSpyO5yM+/KPnJQp1+/Rv7CgpmeuHS6eqHgHzg6qeyJwHhaYIYRkuMuJWWaqF35\n\tSXgheF6uf49r7Gk0S3/EL0x6Qnf3kMMnGcPrL9Qd38N4kkvUDu0rP0CPAhAdvwPuYI6Qkb2FxZA\n\tH66Ed+f0DcUyi8KaeJf1+qWpHvLfsp+cQ9sciQmxYuXIeIRp+F/E/gVZNuGplTne2mXUZ+73zVM\n\t+9A5qwIE0d986oRcj98PG+QB+GPOPc3tjhczHeg+Z0+GfQIAEYijEVvNKUpcKTj4SCt/Is/on8x\n\tAbZYqSINyvZA==","X-Received":["by 2002:a05:6000:2a82:b0:451:ccce:33a9 with SMTP id\n\tffacd0b85a97d-452ea55352fmr3630526f8f.27.1778167211750; \n\tThu, 07 May 2026 08:20:11 -0700 (PDT)","by 2002:a05:6000:2a82:b0:451:ccce:33a9 with SMTP id\n\tffacd0b85a97d-452ea55352fmr3630473f8f.27.1778167210987; \n\tThu, 07 May 2026 08:20:10 -0700 (PDT)"],"From":"Milan Zamazal <mzamazal@redhat.com>","To":"johannes.goede@oss.qualcomm.com","Cc":"Kieran Bingham <kieran.bingham@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH 02/13] softisp: Split AWB from Combined Matrix","In-Reply-To":"<43622f9e-6232-4e26-bb3d-8c64e8900e64@oss.qualcomm.com>\n\t(johannes goede's message of \"Thu, 7 May 2026 14:21:04 +0200\")","References":"<20260407-kbingham-awb-split-v1-0-a39af3f4dc20@ideasonboard.com>\n\t<20260407-kbingham-awb-split-v1-2-a39af3f4dc20@ideasonboard.com>\n\t<43622f9e-6232-4e26-bb3d-8c64e8900e64@oss.qualcomm.com>","Date":"Thu, 07 May 2026 17:20:08 +0200","Message-ID":"<855x4zutzr.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","User-Agent":"Gnus/5.13 (Gnus v5.13)","MIME-Version":"1.0","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"lttycTijs8FrPgPDnSfUePmhLpHn9kJc05dap9mK5XU_1778167213","X-Mimecast-Originator":"redhat.com","Content-Type":"text/plain","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":38842,"web_url":"https://patchwork.libcamera.org/comment/38842/","msgid":"<177843778333.2475891.9072475643292658678@ping.linuxembedded.co.uk>","date":"2026-05-10T18:29:43","subject":"Re: [PATCH 02/13] softisp: Split AWB from Combined Matrix","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting johannes.goede@oss.qualcomm.com (2026-05-07 19:58:01)\n> Hi,\n> \n> On 7-May-26 17:20, Milan Zamazal wrote:\n> > johannes.goede@oss.qualcomm.com writes:\n> > \n> >> Hi,\n> >>\n> >> Thank you for your work on this.\n> >>\n> >> On 8-Apr-26 00:01, Kieran Bingham wrote:\n> >>> Move the AWB gains out of the combined matrix and pass\n> >>> them directly to the EGL shaders.\n> >>>\n> >>> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> >>> ---\n> >>\n> >> <snip>\n> >>\n> >>> diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag\n> >>> index 23747f78a6313503a46b61ed5bae6e7c178c5745..9a1992e219dd066945b3f46ec509f47a31590385 100644\n> >>> --- a/src/libcamera/shaders/bayer_1x_packed.frag\n> >>> +++ b/src/libcamera/shaders/bayer_1x_packed.frag\n> >>> @@ -65,6 +65,7 @@ uniform vec2 tex_step;\n> >>>  uniform vec2 tex_bayer_first_red;\n> >>>  \n> >>>  uniform sampler2D tex_y;\n> >>> +uniform vec3 awb;\n> >>>  uniform mat3 ccm;\n> >>>  uniform vec3 blacklevel;\n> >>>  uniform float gamma;\n> >>> @@ -227,6 +228,9 @@ void main(void)\n> >>>  \n> >>>     rgb = rgb - blacklevel;\n> >>>  \n> >>> +   /* Apply AWB gains, and saturate each channel at sensor range */\n> >>> +   rgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel);\n> >>> +\n> >>\n> >> Why clamp to 1.0 - blacklevel?  Why no just clamp at 1.0. I'm not sure\n> >> what limiting the range to e.g. 0-240 here has as advantage ?\n> > \n> > I think the primary problem is that the green gain is always 1, so green\n> > cannot exceed 1.0 - blacklevel.  If the other channels are allowed above\n> > that limit, you get colour casts.\n> If we do this and use the default identity ccm then the produced\n> RGB will only have values in the 0-240 range.\n> \n> I think what needs to happen here is apply an extra gain of\n> vec3(1.0) / (vec3(1.0) - blacklevel):\n\nYes, and we can likely optimise this extra multiplication into the AWB\ngain multiplier - which I want to rename from AWB to just 'digital gain'\nand then we'll apply this stretch in one single multiplication to save\nGPU operations.\n\n> Which can be folded into the awb vec3 value before setting\n> the uniform, so that green gain becomes:\n\nerr ... yes I think that's what I'm planning. But I don't want  to call\nit 'awb' at that point. It's just the GPU-ISP's per channel Digital\nGain, and we can also use this to then apply digital gain from AGC too\nfor fine grain gain control.\n\n> \n>         vec3(1.0) / vec3(1.0) - blacklevel\n> \n> and the other 2 gains get boosted (multiplied) by that\n> value and then clamp to vec3(0.0) - vec3(1.0)\n> \n> > Another thing to consider may be that moving out of the sensor range\n> > increases risks of values getting wild when applying the CCM, which is\n> > supposed to be calibrated only for the sensor range.\n> \n> Right we must clamp here, but clamping to eg 0 - 240\n> will just lead to a darker picture then we want.\n\nAbsolutely, I think we should restretch so that 0-240 becomes 0.0 ->\n1.0, but we should always act on R, G and B equally before the CCM.\n\n--\nKieran\n\n> \n> Regards,\n> \n> Hans\n> \n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 4B1F8BDCBD\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSun, 10 May 2026 18:29:48 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 7A39862E6A;\n\tSun, 10 May 2026 20:29:47 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 448CC62E6A\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSun, 10 May 2026 20:29:46 +0200 (CEST)","from monstersaurus.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id BC62818BC;\n\tSun, 10 May 2026 20:29:39 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"lz7tR2Lp\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1778437779;\n\tbh=Yuloxo0WcRNZ3OlQ4cz/spo/ASl+Qp7rtK9u8UyM2Yo=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=lz7tR2LpDvbPXg28AaInQQMHvXO9/UhJuU3r8wAQbZPnNsMiz2hcTAgZdG8CvghMw\n\twNE0t0jSy4ROurQKwJmojj2Hz7DzVVQTmOJ9QFBSIXStTSHCxGIduxaLnIs1mc4Lck\n\tuKwdJixcBykDWTAyjti5F2FKs8r4s9UyRAvfFaiA=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<d9f1320a-210a-478c-ac93-a7ae913157a9@oss.qualcomm.com>","References":"<20260407-kbingham-awb-split-v1-0-a39af3f4dc20@ideasonboard.com>\n\t<20260407-kbingham-awb-split-v1-2-a39af3f4dc20@ideasonboard.com>\n\t<43622f9e-6232-4e26-bb3d-8c64e8900e64@oss.qualcomm.com>\n\t<855x4zutzr.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>\n\t<d9f1320a-210a-478c-ac93-a7ae913157a9@oss.qualcomm.com>","Subject":"Re: [PATCH 02/13] softisp: Split AWB from Combined Matrix","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","To":"Milan Zamazal <mzamazal@redhat.com>, johannes.goede@oss.qualcomm.com","Date":"Sun, 10 May 2026 19:29:43 +0100","Message-ID":"<177843778333.2475891.9072475643292658678@ping.linuxembedded.co.uk>","User-Agent":"alot/0.9.1","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":38846,"web_url":"https://patchwork.libcamera.org/comment/38846/","msgid":"<54883ac2-0a72-47cc-a0e3-7d6a5c788aa8@oss.qualcomm.com>","date":"2026-05-11T08:52:44","subject":"Re: [PATCH 02/13] softisp: Split AWB from Combined Matrix","submitter":{"id":242,"url":"https://patchwork.libcamera.org/api/people/242/","name":"Hans de Goede","email":"johannes.goede@oss.qualcomm.com"},"content":"Hi,\n\nOn 10-May-26 20:29, Kieran Bingham wrote:\n> Quoting johannes.goede@oss.qualcomm.com (2026-05-07 19:58:01)\n>> Hi,\n>>\n>> On 7-May-26 17:20, Milan Zamazal wrote:\n>>> johannes.goede@oss.qualcomm.com writes:\n>>>\n>>>> Hi,\n>>>>\n>>>> Thank you for your work on this.\n>>>>\n>>>> On 8-Apr-26 00:01, Kieran Bingham wrote:\n>>>>> Move the AWB gains out of the combined matrix and pass\n>>>>> them directly to the EGL shaders.\n>>>>>\n>>>>> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n>>>>> ---\n>>>>\n>>>> <snip>\n>>>>\n>>>>> diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag\n>>>>> index 23747f78a6313503a46b61ed5bae6e7c178c5745..9a1992e219dd066945b3f46ec509f47a31590385 100644\n>>>>> --- a/src/libcamera/shaders/bayer_1x_packed.frag\n>>>>> +++ b/src/libcamera/shaders/bayer_1x_packed.frag\n>>>>> @@ -65,6 +65,7 @@ uniform vec2 tex_step;\n>>>>>  uniform vec2 tex_bayer_first_red;\n>>>>>  \n>>>>>  uniform sampler2D tex_y;\n>>>>> +uniform vec3 awb;\n>>>>>  uniform mat3 ccm;\n>>>>>  uniform vec3 blacklevel;\n>>>>>  uniform float gamma;\n>>>>> @@ -227,6 +228,9 @@ void main(void)\n>>>>>  \n>>>>>     rgb = rgb - blacklevel;\n>>>>>  \n>>>>> +   /* Apply AWB gains, and saturate each channel at sensor range */\n>>>>> +   rgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel);\n>>>>> +\n>>>>\n>>>> Why clamp to 1.0 - blacklevel?  Why no just clamp at 1.0. I'm not sure\n>>>> what limiting the range to e.g. 0-240 here has as advantage ?\n>>>\n>>> I think the primary problem is that the green gain is always 1, so green\n>>> cannot exceed 1.0 - blacklevel.  If the other channels are allowed above\n>>> that limit, you get colour casts.\n>> If we do this and use the default identity ccm then the produced\n>> RGB will only have values in the 0-240 range.\n>>\n>> I think what needs to happen here is apply an extra gain of\n>> vec3(1.0) / (vec3(1.0) - blacklevel):\n> \n> Yes, and we can likely optimise this extra multiplication into the AWB\n> gain multiplier - which I want to rename from AWB to just 'digital gain'\n> and then we'll apply this stretch in one single multiplication to save\n> GPU operations.\n> \n>> Which can be folded into the awb vec3 value before setting\n>> the uniform, so that green gain becomes:\n>>         vec3(1.0) / vec3(1.0) - blacklevel\n>>\n> \n> err ... yes I think that's what I'm planning. But I don't want  to call\n> it 'awb' at that point. It's just the GPU-ISP's per channel Digital\n> Gain, and we can also use this to then apply digital gain from AGC too\n> for fine grain gain control.\n\nRenaming this to digital gain is fine with me.\n\n\n>> and the other 2 gains get boosted (multiplied) by that\n>> value and then clamp to vec3(0.0) - vec3(1.0)\n>>\n>>> Another thing to consider may be that moving out of the sensor range\n>>> increases risks of values getting wild when applying the CCM, which is\n>>> supposed to be calibrated only for the sensor range.\n>>\n>> Right we must clamp here, but clamping to eg 0 - 240\n>> will just lead to a darker picture then we want.\n> \n> Absolutely, I think we should restretch so that 0-240 becomes 0.0 ->\n> 1.0, but we should always act on R, G and B equally before the CCM.\n\nAck.\n\nRegards,\n\nHans","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 7E111BDB1C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 11 May 2026 08:52:52 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id A5DA26271A;\n\tMon, 11 May 2026 10:52:51 +0200 (CEST)","from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com\n\t[205.220.180.131])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id B8AD362010\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 11 May 2026 10:52:49 +0200 (CEST)","from pps.filterd (m0279871.ppops.net [127.0.0.1])\n\tby mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id\n\t64B7A5GG1258540 for <libcamera-devel@lists.libcamera.org>;\n\tMon, 11 May 2026 08:52:48 GMT","from mail-vs1-f71.google.com (mail-vs1-f71.google.com\n\t[209.85.217.71])\n\tby mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4e3ag20bwu-1\n\t(version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT)\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 11 May 2026 08:52:48 +0000 (GMT)","by mail-vs1-f71.google.com with SMTP id\n\tada2fe7eead31-6332db4182dso896458137.0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 11 May 2026 01:52:48 -0700 (PDT)","from ?IPV6:2001:1c00:c32:7800:5bfa:a036:83f0:f9ec?\n\t(2001-1c00-0c32-7800-5bfa-a036-83f0-f9ec.cable.dynamic.v6.ziggo.nl.\n\t[2001:1c00:c32:7800:5bfa:a036:83f0:f9ec])\n\tby smtp.gmail.com with ESMTPSA id\n\ta640c23a62f3a-bcb6ae2cb12sm399365666b.22.2026.05.11.01.52.45\n\t(version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128);\n\tMon, 11 May 2026 01:52:46 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=qualcomm.com header.i=@qualcomm.com\n\theader.b=\"amzM3vIR\"; dkim=pass (2048-bit key;\n\tunprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com\n\theader.b=\"TJQ9hSjv\"; dkim-atps=neutral","DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h=\n\tcc:content-transfer-encoding:content-type:date:from:in-reply-to\n\t:message-id:mime-version:references:subject:to; s=qcppdkim1; bh=\n\tsjJeGEDxoJPR1pwY1uD72VFdS97W9FbsUdJpB3kZCRY=; b=amzM3vIRUDwbT+ls\n\tEnx5Mx1L5olgkL2YGoN00CwC59madBb8alH6KuX6rbJRNZh8WsdL0+3PALuleK68\n\tDlKWeDK4t5A5b+hJ/jNzgPRrnKYtSjBBOlR840BjCczINrf5atFwkK+C9H1yucrP\n\tQ/T5w4wCDyvIfx1wYfrTrvq+EmTSReBUaYlpxHdrBS2ZQKFjj+khwkP2mTpOggl6\n\t4aesbwVUeM8E8/VDReocsilN11HfI7zOJASATMrF3cK566TYgwaMQLjeml4Bd47/\n\t9yNP5nMfTB+HGsVrybhc/6JiC2GMleKPUbzjouCBryCQFY0FSuHpInD1a5qzu/+a\n\tm5TcQg==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=oss.qualcomm.com; s=google; t=1778489567; x=1779094367;\n\tdarn=lists.libcamera.org; \n\th=content-transfer-encoding:in-reply-to:content-language:references\n\t:cc:to:subject:from:user-agent:mime-version:date:message-id:from:to\n\t:cc:subject:date:message-id:reply-to;\n\tbh=sjJeGEDxoJPR1pwY1uD72VFdS97W9FbsUdJpB3kZCRY=;\n\tb=TJQ9hSjvqvWhmYkSQqG1cMUeJ7JMejNTCLPIZ84555wbwRhkLJVLgzgRnznGBpe/zK\n\tt7J534WVS/D92m98zdINK36gWtktvS0TCjkRa6565g30soL8R52UvO0MGwZD+3+KL2fH\n\tJ5OMr/uOp/6aG1Yy8Y54KuVPvCqzngqXslU38zgKoTVY9PnSFn2xUyFFzNb8qhlESPmk\n\t59HttnLTwj4pTPY5LfZOnKZ9wKZLM1FpfnnZZDfE8GikSj8atEy3FImStmt19L2yIT5u\n\t7mO8nbAc+nL8renEiHd5vfY0bWkwkFJsxalgpWP3U3krpG/tDoWkQW2kDKZLZm7eFJ9+\n\toelQ=="],"X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20251104; t=1778489567; x=1779094367;\n\th=content-transfer-encoding:in-reply-to:content-language:references\n\t:cc:to:subject:from:user-agent:mime-version:date:message-id:x-gm-gg\n\t:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to;\n\tbh=sjJeGEDxoJPR1pwY1uD72VFdS97W9FbsUdJpB3kZCRY=;\n\tb=TtqtaQIIQf0iSMv2SSrcvLEov7zAxwuXOkSEYeNwINN1Wc7OOEEzt7C8G+H2qN0/Fx\n\t05v8LVt8wjsHaDHB9FMzNuQOvLfr195OzFMba65UtimWIf0EMKvG/vEWf/E+75WhgZ0L\n\tdt8gNfwbKQfXgz6M/qZwOoTFLpbkDcv9EgF7i05F9lqyYhD/0EaDFBRIV81Xe/Wwm2s9\n\tG8fhPebailDGdopdd/rkteQOwpFOngvTBeTLtnG6qY9ddTHtNXMq5f5ErKv5c9MI/uTe\n\tolZv/sJBfcKhpyyNTyGqf8ClLBzyVoPR3oQAi0+iX0U8YuvjS+gDwzncK8JtdWvmGQRK\n\tcP2w==","X-Gm-Message-State":"AOJu0YxYlZnTrhmslC5ChIEnn8Ek4+dAhtd+a8zZScXniiM7Mg3MBgVL\n\t4ZLxcfUreflihcMK7tWDnNNWEJr19b+gIbteuXBCVv9yLIkx5bw2W/sk1bg3gS97+qBFkKM1GT6\n\t8AZwhS4MGZxufqtnIXZVaXeN2O/uAnxxX7Lv304MhHbWOE6LNH8KscRkmHIwVZNQc2G4pboAeT8\n\tRm","X-Gm-Gg":"Acq92OGag5hgZ9HE66r+agXx0ERjSNVr2VvVafP3o1tOK3FGDCIL4YFDf9V2/CBLyQM\n\tGArKgQMSgGB1kyZKO4nMRWiEn3UaENhyiDBWGZtaQ9IIO0keGKrYvV2uyYedhEPi3OSzNBmsCyb\n\tSvtSfv7t52Jdgr5HT3UcOuhc0n/cx6KzhuZueM9lETRJNEH9Wi9BSPPPrvO8ByMctMvjNykWTM0\n\tS6lvQp5/tvjcg26goEOJV0UTA4e5f611zLFgIlriX2akKrheSFqFpy/CG6qMNIejfxrgd55Sa4y\n\t8u6z5bBa8+rt2g3yb7Ma5rQsDcDchzmFuKzx0KjKLsPSXPv0Nu7gR2DovH3wHXfZvCf0U40KsST\n\txVEhram+2rJ3hbOPYS5KnoUzrtqEO+Nl4Tz+NxgycpI1PXFwFER47lkekEJYHj0aoPzhRuLE+Wc\n\tkHpJrBbmXJcew2qga6TNEXmXjptY6YMqe7WMic9se859YryVCZ5CIwqQb6PHYiVJSW9+7zXtjUg\n\tkBjXcJhBzlejtYP","X-Received":["by 2002:a05:6102:2b9a:b0:62f:33f9:37e5 with SMTP id\n\tada2fe7eead31-630f8eec11amr12141571137.10.1778489567588; \n\tMon, 11 May 2026 01:52:47 -0700 (PDT)","by 2002:a05:6102:2b9a:b0:62f:33f9:37e5 with SMTP id\n\tada2fe7eead31-630f8eec11amr12141562137.10.1778489567050; \n\tMon, 11 May 2026 01:52:47 -0700 (PDT)"],"Message-ID":"<54883ac2-0a72-47cc-a0e3-7d6a5c788aa8@oss.qualcomm.com>","Date":"Mon, 11 May 2026 10:52:44 +0200","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","From":"johannes.goede@oss.qualcomm.com","Subject":"Re: [PATCH 02/13] softisp: Split AWB from Combined Matrix","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>,\n\tMilan Zamazal <mzamazal@redhat.com>","Cc":"libcamera-devel@lists.libcamera.org","References":"<20260407-kbingham-awb-split-v1-0-a39af3f4dc20@ideasonboard.com>\n\t<20260407-kbingham-awb-split-v1-2-a39af3f4dc20@ideasonboard.com>\n\t<43622f9e-6232-4e26-bb3d-8c64e8900e64@oss.qualcomm.com>\n\t<855x4zutzr.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>\n\t<d9f1320a-210a-478c-ac93-a7ae913157a9@oss.qualcomm.com>\n\t<177843778333.2475891.9072475643292658678@ping.linuxembedded.co.uk>","Content-Language":"en-US, nl","In-Reply-To":"<177843778333.2475891.9072475643292658678@ping.linuxembedded.co.uk>","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"7bit","X-Proofpoint-ORIG-GUID":"GvEQFHcwH_yMXNBmGf7Dexd5UAr6uKsd","X-Proofpoint-Spam-Details-Enc":"AW1haW4tMjYwNTExMDA5NyBTYWx0ZWRfX0EWJjnl9cUcg\n\t3teUlfdeM1ktmMGh6ykq41Z0iTJFBrIdMaVjABIoIb1ux+Q5q/AopxbUT9EN1VLJDK9aXMusl5r\n\tRbQYEfCCWWbVWRreGXbXos8SkUdDJFJZQ4vJ3RO84qV3cCPaJJO3Mo/pcy3Q4UxhXnaPii1O1PS\n\tQEVaGtUTmD5CmE93y2rms46Q3ob5q6WdNfctZnXgbRADF5AhXulrLNgZYSHeqf5kvqbRFroso5/\n\tjYShg4I+vcDEYDDS/x8pe7WSpTX2v3+YmQ7ZZMZaVostfBZDrAb09J7vcx7Jhh0mn+VqxPZjao4\n\tN4LpGuRPoy8q45J8XSSOt8r4jFHrOM44ONizZmKCDNSRNYwycDeq5aZLxVmfYi8PZy+AR9Ib0IO\n\tryif+ibpUQCSi4iaCPCLKiyUNBLn+IXBKzNGk3ZV+YeY97xy0te0DNkByZx2//1+jDOhWWNbigF\n\t4LVju4hz+DpFzgM1vfQ==","X-Proofpoint-GUID":"GvEQFHcwH_yMXNBmGf7Dexd5UAr6uKsd","X-Authority-Analysis":"v=2.4 cv=NODlPU6g c=1 sm=1 tr=0 ts=6a0198e0 cx=c_pps\n\ta=P2rfLEam3zuxRRdjJWA2cw==:117 a=xqWC_Br6kY4A:10 a=IkcTkHD0fZMA:10\n\ta=NGcC8JguVDcA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22\n\ta=u7WPNUs3qKkmUXheDGA7:22 a=3WHJM1ZQz_JShphwDgj5:22 a=EUspDBNiAAAA:8\n\ta=P1BnusSwAAAA:8 a=IJktq662XHk5d70ZSpYA:9 a=QEXdDO2ut3YA:10\n\ta=ODZdjJIeia2B_SHc_B0f:22 a=D0XLA9XvdZm18NrgonBM:22","X-Proofpoint-Virus-Version":"vendor=baseguard\n\tengine=ICAP:2.0.293, Aquarius:18.0.1143, Hydra:6.1.51,\n\tFMLib:17.12.100.49\n\tdefinitions=2026-05-11_02,2026-05-08_02,2025-10-01_01","X-Proofpoint-Spam-Details":"rule=outbound_notspam policy=outbound score=0\n\tpriorityscore=1501 bulkscore=0 adultscore=0 suspectscore=0\n\tmalwarescore=0\n\tlowpriorityscore=0 impostorscore=0 spamscore=0 phishscore=0\n\tclxscore=1015\n\tclassifier=typeunknown authscore=0 authtc= authcc= route=outbound\n\tadjust=0\n\treason=mlx scancount=1 engine=8.22.0-2604200000\n\tdefinitions=main-2605110097","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]