Patch Detail
Show a patch.
GET /api/patches/26928/?format=api
{ "id": 26928, "url": "https://patchwork.libcamera.org/api/patches/26928/?format=api", "web_url": "https://patchwork.libcamera.org/patch/26928/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/projects/1/?format=api", "name": "libcamera", "link_name": "libcamera", "list_id": "libcamera_core", "list_email": "libcamera-devel@lists.libcamera.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20260618-rppx1-ipa-v1-13-32337264cfcd@ideasonboard.com>", "date": "2026-06-18T10:18:52", "name": "[13/14] ipa: rppx1: Add AWB algorithm", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "0b54bf8327f9dad1c7c3b419ceeb216d86e35187", "submitter": { "id": 143, "url": "https://patchwork.libcamera.org/api/people/143/?format=api", "name": "Jacopo Mondi", "email": "jacopo.mondi@ideasonboard.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/26928/mbox/", "series": [ { "id": 6003, "url": "https://patchwork.libcamera.org/api/series/6003/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=6003", "date": "2026-06-18T10:18:39", "name": "libcamera: Add support for R-Car Gen4 and RPP-X1 ISP", "version": 1, "mbox": "https://patchwork.libcamera.org/series/6003/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/26928/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/26928/checks/", "tags": {}, "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 3EA33C330F\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 18 Jun 2026 10:19:15 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id B804E62C6B;\n\tThu, 18 Jun 2026 12:19:14 +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 AFDE8629E2\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 18 Jun 2026 12:19:02 +0200 (CEST)", "from [192.168.125.177] (mob-109-113-4-199.net.vodafone.it\n\t[109.113.4.199])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 7D77ADF3;\n\tThu, 18 Jun 2026 12:18:27 +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=\"kEaykUTi\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1781777907;\n\tbh=gJjQ+ZviYAXTXT0jc81ax4NVY2j+qk1gkvld9egxiI8=;\n\th=From:Date:Subject:References:In-Reply-To:To:Cc:From;\n\tb=kEaykUTi/RmABuM4hrEU1rqvEzMiuxI+lHkzuGiLQu2cAT1f2Ka/RkFLPjBZNxRco\n\t2TZQtnv+0kWvVsM3HricuQ/vZABw+gU9GJ0g21Np48ejoEmgnJg+mf2LkP3IXbwD+5\n\tTVR96TcDuuO+KuHBx7qKS8dQ2fWq/GtcPbmF9L7I=", "From": "Jacopo Mondi <jacopo.mondi@ideasonboard.com>", "Date": "Thu, 18 Jun 2026 12:18:52 +0200", "Subject": "[PATCH 13/14] ipa: rppx1: Add AWB algorithm", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=\"utf-8\"", "Content-Transfer-Encoding": "7bit", "Message-Id": "<20260618-rppx1-ipa-v1-13-32337264cfcd@ideasonboard.com>", "References": "<20260618-rppx1-ipa-v1-0-32337264cfcd@ideasonboard.com>", "In-Reply-To": "<20260618-rppx1-ipa-v1-0-32337264cfcd@ideasonboard.com>", "To": "=?utf-8?q?Niklas_S=C3=B6derlund?=\n\t<niklas.soderlund+renesas@ragnatech.se>, \n\tlibcamera-devel@lists.libcamera.org", "Cc": "Jacopo Mondi <jacopo.mondi@ideasonboard.com>", "X-Mailer": "b4 0.14.3", "X-Developer-Signature": "v=1; a=openpgp-sha256; l=13952;\n\ti=jacopo.mondi@ideasonboard.com; h=from:subject:message-id;\n\tbh=gJjQ+ZviYAXTXT0jc81ax4NVY2j+qk1gkvld9egxiI8=;\n\tb=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBqM8YKq3P+O2XCdyZusZBrjyJ9+TpkTCPDwJWgP\n\tJ15uhH7h0GJAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCajPGCgAKCRByNAaPFqFW\n\tPFy5D/9Gb3ugTRW7s2JiS5j18EMGkExD3+zZL2qWGgTRQxmWbdTgA+fWAeDc+0BXOCwdh82qZb0\n\tBvGnWAgH6qMiREC7nOeyK/sBZscVOB8ftG2rw0hRPwRposAXK0gr28uKvvNc6mom6IKkB9NiHjq\n\tEqgjYpVv31jbYKvV4C7+ZtBBUg3mHXzpB1croY2Tem746pEGFZnx77yobdCiGmrHcU+uOjFftLQ\n\txH45hTpP8lLt8Tpe2WRjYwZsLxHuw53QcBNI8JN8qTPOq6kSz2XGI02/WByz6Be9qNbGyDKBn01\n\ttOO02W3/EjKljgyYIj2cY3G35vf9xSfdCcdQd64zEikmEF0iKzPWZ/IBtSponUvEUOV80W++dfM\n\tQZmMjPX45NXF2i8Z5STCsXkZt8kGpnDqZ1fBAZ3nddIZdTc6HtWHJ7kkWkAqNd3HCdYrr25ays3\n\tif1y5nbFSf3Iy1rq01pZxQnlsG9dNEOHDxiQ3yAxARH2/jZgimsu9p2/yJ6sDyeoXnPnA72Dt23\n\tgO1SQcmHcWbeK15502JAWU0jJy1XAzJ6a1Im2TjjzDVyU90mrOdIh1/kTKU+SBGsRpnppN+kILf\n\tvDlEKUM2jUuLiQzse4NFBn5cLygN3RWGXfahV4NM1csKdguR5NnLGc60CXvpC3JCePT72uKC2+L\n\tKrHWZIH6rAAiSeQ==", "X-Developer-Key": "i=jacopo.mondi@ideasonboard.com; a=openpgp;\n\tfpr=72392EDC88144A65C701EA9BA5826A2587AD026B", "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>" }, "content": "Add Awb algorithm to the RPP-X1 IPA.\n\nThe implementation is based on libIPA AwbAlgorithm.\n\nSigned-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n---\n src/ipa/rppx1/algorithms/awb.cpp | 298 +++++++++++++++++++++++++++++++++++\n src/ipa/rppx1/algorithms/awb.h | 48 ++++++\n src/ipa/rppx1/algorithms/meson.build | 5 +\n src/ipa/rppx1/ipa_context.cpp | 30 ++++\n src/ipa/rppx1/ipa_context.h | 10 ++\n src/ipa/rppx1/meson.build | 4 +\n 6 files changed, 395 insertions(+)", "diff": "diff --git a/src/ipa/rppx1/algorithms/awb.cpp b/src/ipa/rppx1/algorithms/awb.cpp\nnew file mode 100644\nindex 000000000000..6316606b4b0f\n--- /dev/null\n+++ b/src/ipa/rppx1/algorithms/awb.cpp\n@@ -0,0 +1,298 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2026, Ideas On Board\n+ *\n+ * RPP-X1 AWB control algorithm\n+ */\n+\n+\n+#include \"awb.h\"\n+\n+#include <libcamera/base/log.h>\n+#include <libcamera/internal/vector.h>\n+\n+/**\n+ * \\file awb.h\n+ * \\brief RPP-X1 Auto White Balance\n+ */\n+\n+namespace libcamera {\n+\n+namespace ipa::rppx1::algorithms {\n+\n+/* \\todo RPP-X1 doesn't support the Lux algorithm. */\n+static constexpr unsigned int kDefaultLux = 500;\n+\n+LOG_DEFINE_CATEGORY(RppX1Awb)\n+\n+namespace {\n+\n+/* Quantize a gain to the UQ6.12 register format. */\n+constexpr uint32_t quantizeGain(double gain)\n+{\n+\treturn UQ<6, 12>(static_cast<float>(gain)).quantized();\n+}\n+\n+}; /* namespace */\n+\n+/*\n+ * The RPP-X1 ISP has a bus width of 24 bits and all the measurement limits are\n+ * expressed as 24 bit values. In order to make it simpler to express limits\n+ * in code use an 8-bit value and left-shift by 16 to match the 24 bit width of\n+ * the ISP processing pipeline.\n+ */\n+constexpr unsigned int kRPPX1BusWidthShift = 16;\n+\n+class RppX1AwbStats final : public AwbStats\n+{\n+public:\n+\tRppX1AwbStats() {}\n+\tRppX1AwbStats(const RGB<double> &rgbMeans)\n+\t\t: AwbStats(rgbMeans)\n+\t{\n+\t}\n+\n+\t/* Minimum mean value below which AWB can't operate. */\n+\tdouble minColourValue() const override\n+\t{\n+\t\treturn 2.0;\n+\t}\n+};\n+\n+/**\n+ * \\class Awb\n+ * \\brief RPP-X1 white balance correction algorithm\n+ */\n+\n+/**\n+ * \\copydoc libcamera::ipa::Algorithm::init\n+ */\n+int Awb::init(IPAContext &context, const ValueNode &tuningData)\n+{\n+\treturn awbAlgo_.init(tuningData, context.ctrlMap);\n+}\n+\n+/**\n+ * \\copydoc libcamera::ipa::Algorithm::configure\n+ */\n+int Awb::configure(IPAContext &context,\n+\t\t const IPACameraSensorInfo &configInfo)\n+{\n+\tawbAlgo_.configure(context.activeState.awb);\n+\n+\t/*\n+\t * Define the measurement window for AWB as a centered rectangle\n+\t * covering 3/4 of the image width and height.\n+\t */\n+\tcontext.configuration.awb.measureWindow.h_offs = configInfo.outputSize.width / 8;\n+\tcontext.configuration.awb.measureWindow.v_offs = configInfo.outputSize.height / 8;\n+\tcontext.configuration.awb.measureWindow.h_size = 3 * configInfo.outputSize.width / 4;\n+\tcontext.configuration.awb.measureWindow.v_size = 3 * configInfo.outputSize.height / 4;\n+\n+\tcontext.configuration.awb.enabled = true;\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * \\copydoc libcamera::ipa::Algorithm::queueRequest\n+ */\n+void Awb::queueRequest(IPAContext &context, const uint32_t frame,\n+\t\t IPAFrameContext &frameContext,\n+\t\t const ControlList &controls)\n+{\n+\tawbAlgo_.queueRequest(context.activeState.awb, frame, frameContext.awb,\n+\t\t\t controls);\n+}\n+\n+/**\n+ * \\copydoc libcamera::ipa::Algorithm::prepare\n+ */\n+void Awb::prepare(IPAContext &context, const uint32_t frame,\n+\t\t IPAFrameContext &frameContext, RppX1Params *params)\n+{\n+\tawbAlgo_.prepare(context.activeState.awb, frameContext.awb);\n+\n+\tauto gainConfig = params->block<BlockType::AwbgPre1>();\n+\tgainConfig.setEnabled(true);\n+\n+\tgainConfig->gain_green_b = quantizeGain(frameContext.awb.gains.g());\n+\tgainConfig->gain_blue = quantizeGain(frameContext.awb.gains.b());\n+\tgainConfig->gain_red = quantizeGain(frameContext.awb.gains.r());\n+\tgainConfig->gain_green_r = quantizeGain(frameContext.awb.gains.g());\n+\n+\tif (frame > 0)\n+\t\treturn;\n+\n+\t/*\n+\t * If this is the first frame, program the white balance measurement\n+\t * engine.\n+\t */\n+\n+\tauto awbConfig = params->block<BlockType::WbmeasPost>();\n+\tawbConfig.setEnabled(true);\n+\n+\t/* Configure the measure window for AWB. */\n+\tawbConfig->wnd = context.configuration.awb.measureWindow;\n+\n+\t/* Number of frames to use to estimate the means (0 means 1 frame). */\n+\tawbConfig->frames = 0;\n+\n+\t/* Use YCbCr measurement mode. */\n+\tawbConfig->mode = RPPX1_WBMEAS_MODE_YCBCR;\n+\n+\t/* Set the reference Cr and Cb (AWB target) to white. */\n+\tawbConfig->ref_cb_max_b = 128 << kRPPX1BusWidthShift;\n+\tawbConfig->ref_cr_max_r = 128 << kRPPX1BusWidthShift;\n+\n+\t/*\n+\t * Filter out pixels based on luminance and chrominance values.\n+\t * The acceptable luma values are specified as a [16, 250]\n+\t * range, while the acceptable chroma values are specified\n+\t * with a minimum of 16 and a maximum Cb+Cr sum of 250;\n+\t */\n+\tawbConfig->min_y_max_g = 16 << kRPPX1BusWidthShift;\n+\tawbConfig->max_y = 250 << kRPPX1BusWidthShift;\n+\tawbConfig->min_c = 16 << kRPPX1BusWidthShift;\n+\tawbConfig->max_csum = 250 << kRPPX1BusWidthShift;\n+\n+\t/* \\todo Disable ymax_cmp even if we program 'max_y' */\n+\tawbConfig->ymax_cmp = 0;\n+\n+\t/*\n+\t * Program coefficients and offsets to perform RGB-to-YCbCr\n+\t * conversion according to the BT.601 specification for limited\n+\t * range YUV.\n+\t *\n+\t * Y = 16 + 0.2500 R + 0.5000 G + 0.1094 B\n+\t * Cb = 128 - 0.1406 R - 0.2969 G + 0.4375 B\n+\t * Cr = 128 + 0.4375 R - 0.3750 G - 0.0625 B\n+\t *\n+\t * which resuls in the following register values:\n+\t *\n+\t * - coefficients are signed Q4.12 format\n+\t * - their numerical value is then 'reg / 2^12'\n+\t * - negative numbers need to reverse the 2's complement\n+\t * (!(reg & !BIT(16)) + 1) / 2^12\n+\t *\n+\t * coeff G0 0x00000800; = 0.500\n+\t * coeff B0 0x000001c0; = 0.1094\n+\t * coeff R0 0x00000400; = 0.2500\n+\t * coeff G1 0x0000fb40; = -0.2969\n+\t * coeff B1 0x00000700; = 0.4375\n+\t * coeff R1 0x0000fdc0; = -0.1406\n+\t * coeff G2 0x0000fa00; = -0.3750\n+\t * coeff B2 0x0000ff00; = -0.0625\n+\t * coeff R2 0x00000700; = 0.4375\n+\t * offset R 0x00100000; offset_r = (16 << 16)\n+\t * offset G 0x00800000; offset_g = (128 << 16)\n+\t * offset B 0x00800000; offset_b = (128 << 16)\n+\t *\n+\t * Use the inverse of this matrix in calculateRgbMeans() to\n+\t * reverse the colorspace conversion.\n+\t */\n+\tawbConfig->ccor_coeff[0][0] = 0x00000800;\n+\tawbConfig->ccor_coeff[0][1] = 0x000001c0;\n+\tawbConfig->ccor_coeff[0][2] = 0x00000400;\n+\tawbConfig->ccor_coeff[1][0] = 0x0000fb40;\n+\tawbConfig->ccor_coeff[1][1] = 0x00000700;\n+\tawbConfig->ccor_coeff[1][2] = 0x0000fdc0;\n+\tawbConfig->ccor_coeff[2][0] = 0x0000fa00;\n+\tawbConfig->ccor_coeff[2][1] = 0x0000ff00;\n+\tawbConfig->ccor_coeff[2][2] = 0x00000700;\n+\n+\tawbConfig->ccor_offs[0] = 16 << kRPPX1BusWidthShift;\n+\tawbConfig->ccor_offs[1] = 128 << kRPPX1BusWidthShift;\n+\tawbConfig->ccor_offs[2] = 128 << kRPPX1BusWidthShift;\n+}\n+\n+/**\n+ * \\copydoc libcamera::ipa::Algorithm::process\n+ */\n+void Awb::process(IPAContext &context,\n+\t\t [[maybe_unused]] const uint32_t frame,\n+\t\t IPAFrameContext &frameContext,\n+\t\t const RppX1Stats *stats,\n+\t\t ControlList &metadata)\n+{\n+\tRppX1AwbStats awbStats = calculateRgbMeans(frameContext, stats);\n+\n+\tawbAlgo_.process(context.activeState.awb, frameContext.awb, awbStats,\n+\t\t\t kDefaultLux, metadata);\n+}\n+\n+RppX1AwbStats Awb::calculateRgbMeans(const IPAFrameContext &frameContext,\n+\t\t\t\t const RppX1Stats *stats) const\n+{\n+\tif (!stats)\n+\t\treturn {};\n+\n+\tconst auto awb = stats->block<StatsType::WbmeasPost>();\n+\tif (!awb)\n+\t\treturn {};\n+\n+\tif (awb->cnt == 0) {\n+\t\tLOG(RppX1Awb, Debug) << \"AWB statistics are empty\";\n+\t\treturn {};\n+\t}\n+\n+\tVector<double, 3> rgbMeans;\n+\n+\t/* Get the YCbCr mean values: we use YCbCr measurement mode. */\n+\tVector<double, 3> yuvMeans({\n+\t\tstatic_cast<double>(awb->mean_y_or_g),\n+\t\tstatic_cast<double>(awb->mean_cb_or_b),\n+\t\tstatic_cast<double>(awb->mean_cr_or_r)\n+\t});\n+\n+\t/*\n+\t * Convert from YCbCr to RGB. The statistics engine has been\n+\t * programmed with the following matrix:\n+\t *\n+\t * Y = 16 + 0.2500 R + 0.5000 G + 0.1094 B\n+\t * Cb = 128 - 0.1406 R - 0.2969 G + 0.4375 B\n+\t * Cr = 128 + 0.4375 R - 0.3750 G - 0.0625 B\n+\t *\n+\t * Use the inverse matrix here.\n+\t */\n+\tstatic const Matrix<double, 3, 3> yuv2rgbMatrix({\n+\t\t1.1636, -0.0623, 1.6008,\n+\t\t1.1636, -0.4045, -0.7949,\n+\t\t1.1636, 1.9912, -0.0250\n+\t});\n+\tstatic const Vector<double, 3> yuv2rgbOffset({\n+\t\t16, 128, 128\n+\t});\n+\n+\trgbMeans = yuv2rgbMatrix * (yuvMeans - yuv2rgbOffset);\n+\n+\t/*\n+\t * Due to hardware rounding errors in the YCbCr means, the\n+\t * calculated RGB means may be negative. This would lead to\n+\t * negative gains, messing up calculation. Prevent this by\n+\t * clamping the means to positive values.\n+\t */\n+\trgbMeans = rgbMeans.max(0.0);\n+\n+\t/*\n+\t * \\todo\n+\t * The ISP computes the AWB means after applying the CCM. Apply\n+\t * the inverse as we want to get the raw means before the colour gains.\n+\t * rgbMeans = frameContext.ccm.ccm.inverse() * rgbMeans;\n+\t */\n+\n+\t/*\n+\t * The ISP computes the AWB means after applying the colour gains,\n+\t * divide by the gains that were used to get the raw means from the\n+\t * sensor. Apply a minimum value to avoid divisions by near-zero.\n+\t */\n+\trgbMeans /= frameContext.awb.gains.max(0.01);\n+\n+\treturn RppX1AwbStats(rgbMeans);\n+}\n+\n+REGISTER_IPA_ALGORITHM(Awb, \"Awb\")\n+\n+} /* namespace ipa::rppx1::algorithms */\n+\n+} /* namespace libcamera */\ndiff --git a/src/ipa/rppx1/algorithms/awb.h b/src/ipa/rppx1/algorithms/awb.h\nnew file mode 100644\nindex 000000000000..2e4f67f11bc0\n--- /dev/null\n+++ b/src/ipa/rppx1/algorithms/awb.h\n@@ -0,0 +1,48 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2026, Ideas On Board\n+ *\n+ * AWB control algorithm\n+ */\n+\n+#pragma once\n+\n+#include \"libipa/awb.h\"\n+#include \"libipa/fixedpoint.h\"\n+\n+#include \"algorithm.h\"\n+\n+namespace libcamera {\n+\n+namespace ipa::rppx1::algorithms {\n+\n+class RppX1AwbStats;\n+\n+class Awb : public Algorithm\n+{\n+public:\n+\tAwb() = default;\n+\t~Awb() = default;\n+\n+\tint init(IPAContext &context, const ValueNode &tuningData) override;\n+\tint configure(IPAContext &context, const IPACameraSensorInfo &configInfo) override;\n+\tvoid queueRequest(IPAContext &context, const uint32_t frame,\n+\t\t\t IPAFrameContext &frameContext,\n+\t\t\t const ControlList &controls) override;\n+\tvoid prepare(IPAContext &context, const uint32_t frame,\n+\t\t IPAFrameContext &frameContext,\n+\t\t RppX1Params *params) override;\n+\tvoid process(IPAContext &context, const uint32_t frame,\n+\t\t IPAFrameContext &frameContext,\n+\t\t const RppX1Stats *stats,\n+\t\t ControlList &metadata) override;\n+\n+private:\n+\tRppX1AwbStats calculateRgbMeans(const IPAFrameContext &frameContext,\n+\t\t\t\t\tconst RppX1Stats *stats) const;\n+\n+\tAwbAlgorithm<UQ<6, 12>> awbAlgo_;\n+};\n+\n+} /* namespace ipa::rppx1::algorithms */\n+} /* namespace libcamera */\ndiff --git a/src/ipa/rppx1/algorithms/meson.build b/src/ipa/rppx1/algorithms/meson.build\nnew file mode 100644\nindex 000000000000..70368ad9bac9\n--- /dev/null\n+++ b/src/ipa/rppx1/algorithms/meson.build\n@@ -0,0 +1,5 @@\n+# SPDX-License-Identifier: CC0-1.0\n+\n+rppx1_ipa_algorithms = files([\n+ 'awb.cpp',\n+])\ndiff --git a/src/ipa/rppx1/ipa_context.cpp b/src/ipa/rppx1/ipa_context.cpp\nindex 5ac60dfc7bf6..ea7008f5685d 100644\n--- a/src/ipa/rppx1/ipa_context.cpp\n+++ b/src/ipa/rppx1/ipa_context.cpp\n@@ -16,21 +16,51 @@\n \n namespace libcamera::ipa::rppx1 {\n \n+/**\n+ * \\struct RppX1AwbSession\n+ * \\brief RPP-X1 Awb session configuration\n+ */\n+\n+/**\n+ * \\var RppX1AwbSession::measureWindow\n+ * \\brief Awb measurement window\n+ */\n+\n+/**\n+ * \\var RppX1AwbSession::enabled\n+ * \\brief Awb enabled flag\n+ */\n+\n /**\n * \\struct IPASessionConfiguration\n * \\brief Session configuration for the IPA module\n */\n \n+/**\n+ * \\var IPASessionConfiguration::awb\n+ * \\brief Awb session configuration\n+ */\n+\n /**\n * \\struct IPAActiveState\n * \\brief Active state for algorithms\n */\n \n+/**\n+ * \\var IPAActiveState::awb\n+ * \\copydoc ipa::awb::ActiveState\n+ */\n+\n /**\n * \\struct IPAFrameContext\n * \\brief Per-frame context for algorithms\n */\n \n+/**\n+ * \\var IPAFrameContext::awb\n+ * \\copydoc ipa::awb::FrameContext\n+ */\n+\n /**\n * \\struct IPAContext\n * \\brief Global IPA context data shared between all algorithms\ndiff --git a/src/ipa/rppx1/ipa_context.h b/src/ipa/rppx1/ipa_context.h\nindex f268a35081bc..57197d865d3f 100644\n--- a/src/ipa/rppx1/ipa_context.h\n+++ b/src/ipa/rppx1/ipa_context.h\n@@ -20,17 +20,27 @@\n #include <libipa/camera_sensor_helper.h>\n #include <libipa/fc_queue.h>\n \n+#include \"libipa/awb.h\"\n+\n namespace libcamera {\n \n namespace ipa::rppx1 {\n \n+struct RppX1AwbSession {\n+\tstruct rppx1_window measureWindow;\n+\tbool enabled;\n+};\n+\n struct IPASessionConfiguration {\n+\tstruct RppX1AwbSession awb;\n };\n \n struct IPAActiveState {\n+\tipa::awb::ActiveState awb;\n };\n \n struct IPAFrameContext : public FrameContext {\n+\tipa::awb::FrameContext awb;\n };\n \n struct IPAContext {\ndiff --git a/src/ipa/rppx1/meson.build b/src/ipa/rppx1/meson.build\nindex 8034fe24d241..8b8c79e997c1 100644\n--- a/src/ipa/rppx1/meson.build\n+++ b/src/ipa/rppx1/meson.build\n@@ -1,4 +1,6 @@\n # SPDX-License-Identifier: CC0-1.0\n+#\n+subdir('algorithms')\n \n ipa_name = 'ipa_rppx1'\n \n@@ -7,6 +9,8 @@ rppx1_ipa_sources = files([\n 'rppx1.cpp',\n ])\n \n+rppx1_ipa_sources += rppx1_ipa_algorithms\n+\n mod = shared_module(ipa_name, rppx1_ipa_sources,\n name_prefix : '',\n include_directories : [ipa_includes],\n", "prefixes": [ "13/14" ] }