From patchwork Mon Jun 15 14:05:28 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 26880 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 0B585C324C for ; Mon, 15 Jun 2026 14:06:00 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5C1CE623FC; Mon, 15 Jun 2026 16:05:54 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="BgRCbChG"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AD592623E8 for ; Mon, 15 Jun 2026 16:05:47 +0200 (CEST) Received: from [192.168.1.104] (net-93-65-100-155.cust.vodafonedsl.it [93.65.100.155]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id DD121C59; Mon, 15 Jun 2026 16:05:14 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1781532315; bh=ZiPclq2MeaNu27qrQtHqVVg0Naj67q9W+X5UXQ/0yl4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=BgRCbChGm7BjjTtDXCWmvSygvzKQd3WKBmUKlch68iQKOFLgDpPQFWLBKySNK/ZgL EFQ14LWua1+mpgLynhlMaWN8UcyD/682TZIpJXry5GHfFTvmnnQbFoVHrYP4wns3Cg zYSPH6qtz27smeXOEdhNpHyzWv3qo2omx7Ny/iXo= From: Jacopo Mondi Date: Mon, 15 Jun 2026 16:05:28 +0200 Subject: [PATCH 03/11] softisp: Split AWB from Combined Matrix MIME-Version: 1.0 Message-Id: <20260615-libipa-algorithms-v1-3-e949c937422e@ideasonboard.com> References: <20260615-libipa-algorithms-v1-0-e949c937422e@ideasonboard.com> In-Reply-To: <20260615-libipa-algorithms-v1-0-e949c937422e@ideasonboard.com> To: libcamera-devel@lists.libcamera.org Cc: Jacopo Mondi , Kieran Bingham X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=5890; i=jacopo.mondi@ideasonboard.com; h=from:subject:message-id; bh=sI2mHqGV/pTQpVaqsTnK9HOkhX5mykscCA5981d1dJk=; b=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBqMAa4hoOSNrIAZTLDfnP3B7TVdinXeVKbnz+JO ukUG/ysgjKJAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCajAGuAAKCRByNAaPFqFW PL7nD/4nl0nLbHWgIzdC6CFLw2MPP9V9qYqUeVchpWfXEfnmvdtpBjzEi+YrxYtTkrV11emsvm0 2H/ktklsGikHxE/XhzTJ27hacqv7ZS6/11dP7RRbuSKWkRX5UmiTRT37bvZFEEeFpDNu2FwF5v4 WLwUWsH9ckTwvdqO8NKxvZGUy7BKgV2d7eYJic9YIpdbjKpaGHoXO5nEE8EpRA1NOf2VQG7HmbH Cj7VJkBuY4m1mUEPC/4ZRe1NfdmIE0m+A8tfJRXceyI7zkkUjj+L6WTfmQ5U6lylBdjtrf2DTGQ EH4PaVi85IK8MPjAAfbX3oGywDFbdrbzMcWIQxqLDuYeeI7SU1QRYTAm3YUVuxvi/0ExmJ24x1A hZPhQHWPwVoRVjgeE4xFEJj9Xtqu11Lr9bgqjvuDMtVvg6SbDAuG01x3XDFgot69camWFA9t8rG 6CfumjXE5pcKfBIZaXomiBVzNRGDpWhF0tpdJFEG6TjF3YWyPmn7wPPXaSjVDLAdcqqKDiNJs1Z 7fb7JY77yALTPY9c2AT5VcQ5oYJsQdIKARkQjRSRz3v3Vdaig2ORTzCx76+0GotHYAcBAkDM7XI c+XwinbWSwhG6M5g5pkCb2ZLsHWfF+i3l52K5msTRs7UG5dNawxvwDx5MM342ZshMFIra1FIV8D Y32khVWsW/KytkA== X-Developer-Key: i=jacopo.mondi@ideasonboard.com; a=openpgp; fpr=72392EDC88144A65C701EA9BA5826A2587AD026B X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Kieran Bingham Move the AWB gains out of the combined matrix and pass them directly to the EGL shaders. Signed-off-by: Kieran Bingham Signed-off-by: Jacopo Mondi --- src/ipa/simple/algorithms/awb.cpp | 16 +++------------- src/ipa/simple/ipa_context.h | 5 +---- src/libcamera/shaders/bayer_1x_packed.frag | 4 ++++ src/libcamera/shaders/bayer_unpacked.frag | 4 ++++ src/libcamera/software_isp/debayer_egl.cpp | 5 +++++ src/libcamera/software_isp/debayer_egl.h | 3 +++ 6 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp index f5c88ea6f896..05155c83d172 100644 --- a/src/ipa/simple/algorithms/awb.cpp +++ b/src/ipa/simple/algorithms/awb.cpp @@ -38,15 +38,8 @@ void Awb::prepare(IPAContext &context, DebayerParams *params) { auto &gains = context.activeState.awb.gains; - Matrix gainMatrix = { { gains.r(), 0, 0, - 0, gains.g(), 0, - 0, 0, gains.b() } }; - context.activeState.combinedMatrix = - gainMatrix * context.activeState.combinedMatrix; - - frameContext.gains.red = gains.r(); - frameContext.gains.blue = gains.b(); + frameContext.gains = gains; params->gains = gains; } @@ -59,11 +52,8 @@ void Awb::process(IPAContext &context, const SwIspStats::Histogram &histogram = stats->yHistogram; const uint8_t blackLevel = context.activeState.blc.level; - const float mdGains[] = { - static_cast(frameContext.gains.red), - static_cast(frameContext.gains.blue) - }; - metadata.set(controls::ColourGains, mdGains); + metadata.set(controls::ColourGains, { frameContext.gains.r(), + frameContext.gains.b() }); if (!stats->valid) return; diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h index 34f7403a41d6..8ccfacb46a59 100644 --- a/src/ipa/simple/ipa_context.h +++ b/src/ipa/simple/ipa_context.h @@ -71,10 +71,7 @@ struct IPAFrameContext : public FrameContext { double gain; } sensor; - struct { - double red; - double blue; - } gains; + RGB gains; float gamma; std::optional contrast; diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag index 23747f78a631..9a1992e219dd 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -65,6 +65,7 @@ uniform vec2 tex_step; uniform vec2 tex_bayer_first_red; uniform sampler2D tex_y; +uniform vec3 awb; uniform mat3 ccm; uniform vec3 blacklevel; uniform float gamma; @@ -227,6 +228,9 @@ void main(void) rgb = rgb - blacklevel; + /* Apply AWB gains, and saturate each channel at sensor range */ + rgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel); + /* * CCM is a 3x3 in the format * diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag index 1b85196ae161..2def33c82c8e 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -24,6 +24,7 @@ uniform sampler2D tex_y; varying vec4 center; varying vec4 yCoord; varying vec4 xCoord; +uniform vec3 awb; uniform mat3 ccm; uniform vec3 blacklevel; uniform float gamma; @@ -130,6 +131,9 @@ void main(void) { rgb = rgb - blacklevel; + /* Apply AWB gains, and saturate each channel at sensor range */ + rgb = clamp(rgb * awb, vec3(0.0), vec3(1.0) - blacklevel); + /* * CCM is a 3x3 in the format * diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index fd8de3942aa3..227f698a1fac 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -115,6 +115,7 @@ int DebayerEGL::getShaderVariableLocations(void) attributeTexture_ = glGetAttribLocation(programId_, "textureIn"); textureUniformBayerDataIn_ = glGetUniformLocation(programId_, "tex_y"); + awbUniformDataIn_ = glGetUniformLocation(programId_, "awb"); ccmUniformDataIn_ = glGetUniformLocation(programId_, "ccm"); blackLevelUniformDataIn_ = glGetUniformLocation(programId_, "blacklevel"); gammaUniformDataIn_ = glGetUniformLocation(programId_, "gamma"); @@ -128,6 +129,7 @@ int DebayerEGL::getShaderVariableLocations(void) LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ << " tex_y " << textureUniformBayerDataIn_ + << " awb " << awbUniformDataIn_ << " ccm " << ccmUniformDataIn_ << " blacklevel " << blackLevelUniformDataIn_ << " gamma " << gammaUniformDataIn_ @@ -502,6 +504,9 @@ void DebayerEGL::setShaderVariableValues(const DebayerParams ¶ms) glUniform3f(blackLevelUniformDataIn_, params.blackLevel[0], params.blackLevel[1], params.blackLevel[2]); LOG(Debayer, Debug) << " blackLevelUniformDataIn_ " << blackLevelUniformDataIn_ << " data " << params.blackLevel; + glUniform3f(awbUniformDataIn_, params.gains[0], params.gains[1], params.gains[2]); + LOG(Debayer, Debug) << " awbUniformDataIn_ " << awbUniformDataIn_ << " data " << params.gains; + /* * Gamma */ diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h index 943410fdd1fc..43038b45a109 100644 --- a/src/libcamera/software_isp/debayer_egl.h +++ b/src/libcamera/software_isp/debayer_egl.h @@ -90,6 +90,9 @@ private: GLint textureUniformBayerDataIn_; + /* Per-frame AWB gains */ + GLint awbUniformDataIn_; + /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */ GLint ccmUniformDataIn_;