[{"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>"}}]