From patchwork Tue Jan 6 17:00:36 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25654 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 980EFBDCC0 for ; Tue, 6 Jan 2026 17:01:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4014461FD2; Tue, 6 Jan 2026 18:01:06 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="vLUBsVcU"; dkim-atps=neutral Received: from mail-wr1-x433.google.com (mail-wr1-x433.google.com [IPv6:2a00:1450:4864:20::433]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6E74461FD3 for ; Tue, 6 Jan 2026 18:01:04 +0100 (CET) Received: by mail-wr1-x433.google.com with SMTP id ffacd0b85a97d-42e2ba54a6fso452598f8f.3 for ; Tue, 06 Jan 2026 09:01:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718864; x=1768323664; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=e2IR4ED7mZBKvzF2+iSu2ko6YvEmnv4sI3xsTCm2tIc=; b=vLUBsVcUHBTD0Beet/DLK4iXvhjniL6I2Pv2LokpIlXHcPb0WALOQWkK+CR6wj8iZe kD9BWdoyaHmCRD2HLNXHgpvW8J2tGfIR/Hgu9TnPsUHq0nNiARUxOuJ6MgdfIcgSN5pc le/ma5ha0tyJOxzTSTcKcourgdrvbvLi326Zd5C1B6g/uLDgiJeuGZZmrUs2vSR8WPq3 v7Sy0UJkxPMyQ70pKdgD8uwKQ7qCvNaRSoQrokei9XlpCRk/RRjOy+8LwWTUp4Zlj/JL 7n3iVWbs+6eYTJZnahSPlLDPhmyBcteAqEX6ftNhExUES7Wo+dG9JHrVnRBw7Nx1FABv PE/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718864; x=1768323664; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=e2IR4ED7mZBKvzF2+iSu2ko6YvEmnv4sI3xsTCm2tIc=; b=IxKbXiDylvpIYkUItSQcWHZ+EwaMR3N4SS8N4unEtSKwtZ32TFcO/3ivAwpNHy9hdW qJBTpjWwnuCljp3msfccksxQrXtL0DBcEEBv6XOt2jMbieP9c7mxdp+6zhh2/RxP95vD WIAtlRcpt1ddiwOPdJQ4AvTtNArk459oM6vO4Vs75vpff9k2e63L0mkbKqd2s0bUL0Bq bpUWQ9uP67vKPtARrebSi5T6gbCq55HRvnd3Umm7Kwxj/7ja2qcDovUhwXH7/LFzWzod LUGgpP90bSUYuDzR5GyqpLoO1wwibrXoLqy8eqMIrM52tZ6m9ZP6zqfoTEqGP08Kbp8A co9Q== X-Gm-Message-State: AOJu0YwvKjjylOWIIWP/MXagXOHe9IR3Vy2hojJVpDENVYrByHxTg+9Y tm/gpeeaJCA72u8BhAxm7gYiUGaAJFDX9CS5UYLfdN/60G2tRze+8/zGCEjo/gbRAy2PUfobsTI pMLIQubU= X-Gm-Gg: AY/fxX6bQortH9sQSl05kqba3YGpfqLa/vdjqsiWm+RnzyflH1MrHAVlUUh64ElJSXQ auwVm6XxMsQk00LeM5+j21PRxROg2ML/fbYHGVdnZC8ViwbPI0Tl8cYn3SAIMhSHx8cxxjObJjs 7UN6pjScyG8txQfiqS5/5gKu80fthufn3y1vuyRn+1MVAf+nwxQJEOpCPaFVsFL4MO3oiEdH8V2 Iw5S9ffQtxk/QWugMpLizQwHEjn8M88QZKnqsR6zPhM3EGvdDCJVuCKE1mKo3oMXaxZEIfVxuZK XM+bWdgKzIN+thHYQ7cr3YYXfiA5CCipA83qlWpa9IpAee+p0s5d9TE2Y+HTbFkgNMeZ1JlRJGJ Q1QJriwHpl2LxJl3hUrpBUgkYf5XJg1bluq3xkGjvs9zDGb+t40TDgIwwhbQSQphZ68dFK6Yp5E OZxWxbRcdGybKE6WhpwpHl5m6KE0ssY98E7smD2FtgbaatLAjvZWtLBwHLR8+RuoDIqZGKPQHvY MOOlA== X-Google-Smtp-Source: AGHT+IGsKCOZevJxuVFhiZ4nEsUD4nZvvJFjoLkfdNsFDgiKFBw0XcyaA8paUH3t4s4eTkU1FF6weA== X-Received: by 2002:a05:6000:2305:b0:431:c60:c5ed with SMTP id ffacd0b85a97d-432bca19d80mr4913791f8f.13.1767718863521; Tue, 06 Jan 2026 09:01:03 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:03 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v11 01/24] libcamera: software_isp: debayer: Latch contrastExp not contrast to debayer parameters Date: Tue, 6 Jan 2026 17:00:36 +0000 Message-ID: <20260106170059.56193-2-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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" Pass contrastExp as calculated in lut to debayer params not the raw contrast. This way we calculate contrastExp once per frame in lut and pass the calculated value into the shaders, instead of passing contrast and calculating contrastExp once per pixel in the shaders. Signed-off-by: Bryan O'Donoghue Reviewed-by: Milan Zamazal --- include/libcamera/internal/software_isp/debayer_params.h | 2 +- src/ipa/simple/algorithms/lut.cpp | 7 ++++--- src/ipa/simple/ipa_context.h | 1 + src/libcamera/software_isp/debayer.cpp | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/include/libcamera/internal/software_isp/debayer_params.h b/include/libcamera/internal/software_isp/debayer_params.h index 8033f7d5b..256c7d43d 100644 --- a/include/libcamera/internal/software_isp/debayer_params.h +++ b/include/libcamera/internal/software_isp/debayer_params.h @@ -59,7 +59,7 @@ struct DebayerParams { Matrix ccm; RGB blackLevel; float gamma; - float contrast; + double contrastExp; }; } /* namespace libcamera */ diff --git a/src/ipa/simple/algorithms/lut.cpp b/src/ipa/simple/algorithms/lut.cpp index 9aaab54f1..7d015ac89 100644 --- a/src/ipa/simple/algorithms/lut.cpp +++ b/src/ipa/simple/algorithms/lut.cpp @@ -60,12 +60,13 @@ void Lut::updateGammaTable(IPAContext &context) const auto blackLevel = context.activeState.blc.level; const unsigned int blackIndex = blackLevel * gammaTable.size() / 256; const auto contrast = context.activeState.knobs.contrast.value_or(1.0); + /* Convert 0..2 to 0..infinity; avoid actual inifinity at tan(pi/2) */ + double contrastExp = tan(std::clamp(contrast * M_PI_4, 0.0, M_PI_2 - 0.00001)); const float divisor = gammaTable.size() - blackIndex - 1.0; for (unsigned int i = blackIndex; i < gammaTable.size(); i++) { double normalized = (i - blackIndex) / divisor; /* Convert 0..2 to 0..infinity; avoid actual inifinity at tan(pi/2) */ - double contrastExp = tan(std::clamp(contrast * M_PI_4, 0.0, M_PI_2 - 0.00001)); /* Apply simple S-curve */ if (normalized < 0.5) normalized = 0.5 * std::pow(normalized / 0.5, contrastExp); @@ -84,7 +85,7 @@ void Lut::updateGammaTable(IPAContext &context) gammaTable[blackIndex]); context.activeState.gamma.blackLevel = blackLevel; - context.activeState.gamma.contrast = contrast; + context.activeState.gamma.contrastExp = contrastExp; } int16_t Lut::ccmValue(unsigned int i, float ccm) const @@ -149,7 +150,7 @@ void Lut::prepare(IPAContext &context, } params->gamma = context.configuration.gamma; - params->contrast = context.activeState.gamma.contrast; + params->contrastExp = context.activeState.gamma.contrastExp; } void Lut::process([[maybe_unused]] IPAContext &context, diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h index 26b60fb68..7837bb4dd 100644 --- a/src/ipa/simple/ipa_context.h +++ b/src/ipa/simple/ipa_context.h @@ -59,6 +59,7 @@ struct IPAActiveState { std::array gammaTable; uint8_t blackLevel; double contrast; + double contrastExp; } gamma; struct { diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp index b33f818a7..4cb5b4da4 100644 --- a/src/libcamera/software_isp/debayer.cpp +++ b/src/libcamera/software_isp/debayer.cpp @@ -116,7 +116,7 @@ namespace libcamera { */ /** - * \var DebayerParams::contrast + * \var DebayerParams::contrastExp * \brief Contrast value for GPUISP */ From patchwork Tue Jan 6 17:00:37 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25655 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 4229EBDCC0 for ; Tue, 6 Jan 2026 17:01:10 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EE4C661FE8; Tue, 6 Jan 2026 18:01:09 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="xzGK2tgl"; dkim-atps=neutral Received: from mail-wr1-x444.google.com (mail-wr1-x444.google.com [IPv6:2a00:1450:4864:20::444]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 20B9E61F9F for ; Tue, 6 Jan 2026 18:01:07 +0100 (CET) Received: by mail-wr1-x444.google.com with SMTP id ffacd0b85a97d-42fb2314eb0so867968f8f.2 for ; Tue, 06 Jan 2026 09:01:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718866; x=1768323666; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=dIJd7ak0Ig7Al4IlYwKYLFZCqKzLA54/kQmBA9xRHAI=; b=xzGK2tglHLszAl7ZIq9mP52yJcMbKtfEqNBVMXGMYEGaPEg7U+2HnLRt5aVvPGodAP 3tuhhc75y7FQnCsvCwhj7hoAFy1YsZAObzJfa14u0JPEek309X9MXQcH45fx2jvoN06N ffGd3dl83DPl+j6vGg1AGgVbriPBCTD/KbMisaYiORZN0+9qhmyNff2JaDeCLK6I67Fc 1RFxFPgOhRLOTRsWVsKzw2e4BONI/WPcS5mA2zy6ni2CVss+zD8fU1fDMwYKKAHmWEiF cUXy3kyQsSIkMy38mUsisXU514FyPpnMLGSuzhfyS4CCfhvkKJoPEmifrvfpo42tU0SS RIVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718866; x=1768323666; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=dIJd7ak0Ig7Al4IlYwKYLFZCqKzLA54/kQmBA9xRHAI=; b=uQ6FHI7kRq9upyS2R2P5ZbtJ6sWN/IRzU4ompzOSzw/AcYi0OYIa0Ns18M2SoDGJlZ V7poQU0i0yK65GVR+CxN55xy9bYkxSdZy1eB6KMfenh3UguRV1nWLTJcyuSVIVx9lOmh 18DOn/2shyi8i/CuBWkHpw5bNm6AUlBn/y+waEseDDX4GZe7WoY3Do0KsiPSMGD6dsfH grJ72IzHpbjsmNwqFvaKgnZl2IKdQy8aLNL/Dk1az3G+nCKCh5Vyq7qB5y4VDtVBJGQt fFz6q6MmEsUmWSgXuMuZu4DWPtlqp9obGP8rEMUyc0g3KHyXfbx9wYQBXOWlGrPKksTW F4QA== X-Gm-Message-State: AOJu0YyOTds5KUqIlKQh5ck3hyPgTwfAGyMgjHMLOha4x5WlRWQuwwm7 GSeVi/gegxx35VVV8NBMnYeaoaajOZVYbjeUAbCWLJ3C6UrCX/d+NFuQRbxpMdFmZ7k5eFPndPs FdnvfATeHZw== X-Gm-Gg: AY/fxX7u5Mx75AgFgf5nPEVrRk+5/T6WolyEaP09UPH1emih1CtVgznSj08Vefck05W ZcDnoWfra+KhU/52kNhKhpC+J8qs7007CWRa1HAEr+qY9fTNVPftes9v2Gp+lkrr9P/+8PKmNVp 5IFi734NkSC6Tni6bDp3t02BTYY+6A510G1wIVNpjM705LmMwtC4BShKBPFSApSILusDoxB+UQw e2gxZnWkTueuWCGMOcnPdBLFKFeD4Wi/IO3/guIX0zGkSggxvamGvwRefSuqhH53BBEtiimSTV+ Mr2uPyPiAXV7AiZI225Yi03cEIk7DgxQtM7uRlMAGwbBcetnKExrjMM6cZKlH0jh+AKgUMgTooc goA/wAGINmoKPauTkqpttoZY9H7OaziErdGXf81+FZrlPFSf6MK1lLCJg/RchXUL/jcpkBm9l7G JcvGtw2eIsnPZlpXXlGYUjs+h4zRjqOwoXJ8BL5nFqxtNrp5wK6ZOgLq17ItXukE86+xo= X-Google-Smtp-Source: AGHT+IEoSutKybrCsXzaTsn4ULJhLID7aLMymrnwLWy0LjOLzCpA8KF6SlkklKOxarC6nDXI08k0UQ== X-Received: by 2002:a05:6000:420f:b0:430:fd9f:e6e2 with SMTP id ffacd0b85a97d-432bca18993mr4224564f8f.9.1767718864770; Tue, 06 Jan 2026 09:01:04 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:04 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Kieran Bingham , Milan Zamazal , Robert Mader , Hans de Goede Subject: [PATCH v11 02/24] libcamera: software_isp: gbm: Add a GBM helper class for GPU surface access Date: Tue, 6 Jan 2026 17:00:37 +0000 Message-ID: <20260106170059.56193-3-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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" A helper class to interact with GBM. This will allow us to specify the internal storage format of the GPU when making a texture for the Debayer vertex/fragment shaders and thus ensure we receive an uncompressed and untiled output buffer. Acked-by: Kieran Bingham Reviewed-by: Milan Zamazal Reviewed-by: Robert Mader Tested-by: Hans de Goede # ThinkPad T14s gen 6 (arm64) ov02c10 + X1c gen 12 ov08x40 Signed-off-by: Bryan O'Donoghue --- include/libcamera/internal/gbm.h | 55 +++++++++++++ include/libcamera/internal/meson.build | 1 + src/libcamera/gbm.cpp | 107 +++++++++++++++++++++++++ src/libcamera/meson.build | 10 +++ 4 files changed, 173 insertions(+) create mode 100644 include/libcamera/internal/gbm.h create mode 100644 src/libcamera/gbm.cpp diff --git a/include/libcamera/internal/gbm.h b/include/libcamera/internal/gbm.h new file mode 100644 index 000000000..c10be06c1 --- /dev/null +++ b/include/libcamera/internal/gbm.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Linaro Ltd. + * + * Authors: + * Bryan O'Donoghue + * + * Helper class for managing GBM interactions + */ + +#pragma once + +#include + +#include +#include + +#include + +namespace libcamera { + +LOG_DECLARE_CATEGORY(GBM) + +class GBM +{ +public: + GBM(); + ~GBM(); + + int createDevice(); + + /** + * \brief Retrieve the GBM device handle + * + * \return Pointer to the gbm_device structure, or nullptr if the device + * has not been created + */ + struct gbm_device *device() const { return gbmDevice_; } + + /** + * \brief Retrieve the pixel format + * + * \return The PixelFormat used by this GBM instance (ARGB8888) + */ + PixelFormat format() const { return format_; } + +private: + LIBCAMERA_DISABLE_COPY_AND_MOVE(GBM) + + UniqueFD fd_; + struct gbm_device *gbmDevice_ = nullptr; + PixelFormat format_; +}; + +} /* namespace libcamera */ diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build index e9540a2f7..b8324996b 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -23,6 +23,7 @@ libcamera_internal_headers = files([ 'dma_buf_allocator.h', 'formats.h', 'framebuffer.h', + 'gbm.h', 'global_configuration.h', 'ipa_data_serializer.h', 'ipa_manager.h', diff --git a/src/libcamera/gbm.cpp b/src/libcamera/gbm.cpp new file mode 100644 index 000000000..d37808b0c --- /dev/null +++ b/src/libcamera/gbm.cpp @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Linaro Ltd. + * + * Authors: + * Bryan O'Donoghue + * + * Helper class for managing GBM interactions + */ + +#include "libcamera/internal/gbm.h" + +#include +#include +#include +#include +#include + +#include +#include + +namespace libcamera { + +LOG_DEFINE_CATEGORY(GBM) + +/** + * \class GBM + * \brief Helper class for managing GBM interactions + * + * The GBM class provides a simplified interface for creating and managing + * GBM devices. It handles the initialization and teardown of GBM devices + * used for buffer allocation in graphics and camera pipelines. + * + * This class is responsible for opening a DRI render node, creating a GBM + * device, and providing access to the device and its associated pixel format. + */ + +/** + *\var GBM::fd_ + *\brief file descriptor to DRI device + */ + +/** + *\var GBM::gbmDevice_ + *\brief Pointer to GBM device structure derived from fd_ + */ + +/** + *\var GBM::format_ + *\brief Pixel format the GBM surface was created in + */ + +/** + *\brief GBM constructor. + * + * Creates a GBM instance with uninitialised state. + */ +GBM::GBM() +{ +} + +/** + *\brief GBM destructor + * + * Cleans up the GBM device if it was successfully created, and closes + * the associated file descriptor. + */ +GBM::~GBM() +{ + if (gbmDevice_) + gbm_device_destroy(gbmDevice_); +} + +/** + * \brief Create and initialize a GBM device + * + * \todo Get dri device name from envOption setting + * + * Opens the DRI render node (/dev/dri/renderD128) and creates a GBM + * device using the libgbm library. Sets the default pixel format to + * ARGB8888. + * + * \return 0 on success, or a negative error code on failure + */ +int GBM::createDevice() +{ + const char dri_node[] = "/dev/dri/renderD128"; + + int fd = open(dri_node, O_RDWR | O_CLOEXEC | O_NOCTTY); + if (fd < 0) { + LOG(GBM, Error) << "Open " << dri_node << " fail " << strerror(errno); + return -errno; + } + fd_ = UniqueFD(fd); + + gbmDevice_ = gbm_create_device(fd_.get()); + if (!gbmDevice_) { + LOG(GBM, Error) << "gbm_create_device fail" << strerror(errno); + return -errno; + } + + format_ = libcamera::formats::ARGB8888; + + return 0; +} + +} /* namespace libcamera */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 575408b2c..cb7863852 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -70,6 +70,15 @@ libcamera_deps = [] libatomic = cc.find_library('atomic', required : false) libthreads = dependency('threads') +libgbm = dependency('gbm', required : false) +gbm_works = cc.check_header('gbm.h', required: false) + +if libgbm.found() and gbm_works + libcamera_internal_sources += files([ + 'gbm.cpp', + ]) +endif + subdir('base') subdir('converter') subdir('ipa') @@ -178,6 +187,7 @@ libcamera_deps += [ libcamera_base_private, libcrypto, libdl, + libgbm, liblttng, libudev, libyaml, From patchwork Tue Jan 6 17:00:38 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25656 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 D7ABBC3213 for ; Tue, 6 Jan 2026 17:01:10 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8AF8461FC4; Tue, 6 Jan 2026 18:01:10 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="z1q7rsfJ"; dkim-atps=neutral Received: from mail-wr1-x444.google.com (mail-wr1-x444.google.com [IPv6:2a00:1450:4864:20::444]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5DD1761FCA for ; Tue, 6 Jan 2026 18:01:07 +0100 (CET) Received: by mail-wr1-x444.google.com with SMTP id ffacd0b85a97d-430f57cd471so592902f8f.0 for ; Tue, 06 Jan 2026 09:01:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718867; x=1768323667; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=R6EFsuM5iVmwEy7R7n1dhgv/n5dm8RhaUFF5T3hYimw=; b=z1q7rsfJ1Xyka94cXhV20pqTjE7STuQOxk6OmOB0n1lnmc3SBoZdooJjW1EKQBRB20 Imbusdhe24r/qGXAXCk/3jjs7wbE/0qC5AJiylewVUjVjt68M7eWOcSCoAzUZ05Rk56v XPXwO5p3Q4yJAdqUyE/rZ+UBsadqGclSj1W7PwbQRSSg0/FHLXmxbYjqFDlMum+iFCW7 cKpso0/YjB/Li3VJffRHENQ0Zcw11FaOn82+VCi7mhXLvSfMOzQTY6FAtWrGLF2VeiOD erfRYTWHJoo8XO9MJ99ejzWs17nYti2Km/iCeSuJRiJeYekIPcOS3CrwVZ/Es3f4IZHC mPwg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718867; x=1768323667; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=R6EFsuM5iVmwEy7R7n1dhgv/n5dm8RhaUFF5T3hYimw=; b=EcPCVJNBCpwtHaEZB2bS8gF6DdDqMHivFRb0J/Ijinhw4T/azPKfdhRmGEE2Im5XKM tQgLjwMgSmV5h/vespFUozS4eR5PrpSkzjVbaa3+xAmlJE0uI3iANKGDzP8Sy3QPLsG4 5luyeglz3myA+km3HPbStViqBWVYN08V5QfAF/IlyFLPttULHqNuRy5OA99yCk72gxdM 23i4I4SHGHCPn0sgVJTl8ahN53rI+I7BrpANySzlrGLG1ptLIFbwf45EbNyjklLk1vX+ RINQ0kzwx5J4CKXx1Oj2UjN/Hr6IWssuw3QJc4H4iAjEVPjmGIK3LiWVBkpkOVZV7p88 FS3g== X-Gm-Message-State: AOJu0Yxgd/aX9BlNltHjzTYTy6w25lrkcnd+iOAOyisv7lf/UDIDvyDX LDl0FHw8uYUUzpuW+xB8ZlwtnYZKkVfEIrbtQ1EWodLw5xqKgBqxzl7lcDjra94Ev2Niw8GVMi9 NmSSty+RZhw== X-Gm-Gg: AY/fxX57hmdzZuwHwODIPN9G0BdddenPyXka3Nnoux+gTu3ef92KYUVZ0c2TcjoAXXk Yybt6EPtfP/Tm2n7S6xzYyBV3cJorUiNqAQ0MN4G9TmmSVIOrRAU9hAMsyMLNIr95U1iVFIHpli S7m2gbcfiesopdAv+M9svkOj0XdJTD6yadhqRnQgogY0VHF81YQrAnA8u9URWnXKho28l4I9vhH XlZmUlEwzsB3sYry2SCzJeHztOBmnz18OBo4LW2SgxfldJVrHqjLaIav11lW/I1fYOVUvzsJc98 tF4jesDHkDfeSQuJyp0ESFHlM1Xz//HCrTWKM/HwhzHz+hFninCuvkQ8Av6gla3SsqI0gj9VtIO XNfTc7+SqR+vQio2yF/EPpQMHuMnYpI+ssci0LNNonaTwTP/FbcHmlubAElIXj4t262B39hp/yg 0+R/8bQYmq7PnF21mGQKBZSu1mPVPhDNm11HtS5HfJNTy4jfUKxoLVFUbm5ZP2tHelnEs= X-Google-Smtp-Source: AGHT+IEDaAI4zLGzpTPYmFwhB4VCQs/YLArhAp6lymamFDKeyBLNArBWP8MPB1QWG5Z47778XfK6pA== X-Received: by 2002:a5d:5f50:0:b0:432:88c2:edb6 with SMTP id ffacd0b85a97d-432bca2cc7emr3850738f8f.2.1767718866252; Tue, 06 Jan 2026 09:01:06 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:05 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Kieran Bingham , Hans de Goede , Milan Zamazal , Robert Mader , Hans de Goede Subject: [PATCH v11 03/24] libcamera: software_isp: egl: Add a eGL base helper class Date: Tue, 6 Jan 2026 17:00:38 +0000 Message-ID: <20260106170059.56193-4-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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" Introduce an eGL base helper class which provides an eGL context based on a passed width and height. The initGLContext function could be overloaded to provide an interface to a real display. A set of helper functions is provided to compile and link GLSL shaders. linkShaderProgram currently compiles vertex/fragment pairs but could be overloaded or passed a parameter to link a compute shader instead. Breaking the eGL interface away from debayering - allows to use the eGL context inside of a dma-buf heap cleanly, reuse that context inside of a debayer layer and conceivably reuse the context in a multi-stage shader pass. Small note the image_attrs[] array doesn't pass checkstyle.py however the elements of the array are in pairs. Acked-by: Kieran Bingham [bod: Takes fix from Hans for constructor stride bpp] [bod: Drops eglClientWaitSync in favour of glFinish Robert/Milan] Co-developed-by: Hans de Goede Signed-off-by: Hans de Goede Co-developed-by: Milan Zamazal Signed-off-by: Milan Zamazal Reviewed-by: Robert Mader Tested-by: Hans de Goede # ThinkPad T14s gen 6 (arm64) ov02c10 + X1c gen 12 ov08x40 Signed-off-by: Bryan O'Donoghue --- include/libcamera/internal/egl.h | 152 +++++++ include/libcamera/internal/meson.build | 1 + src/libcamera/egl.cpp | 608 +++++++++++++++++++++++++ src/libcamera/meson.build | 23 + 4 files changed, 784 insertions(+) create mode 100644 include/libcamera/internal/egl.h create mode 100644 src/libcamera/egl.cpp diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h new file mode 100644 index 000000000..a92921123 --- /dev/null +++ b/include/libcamera/internal/egl.h @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Linaro Ltd. + * + * Authors: + * Bryan O'Donoghue + * + */ + +#pragma once + +#include +#include + +#include +#include +#include + +#include "libcamera/internal/gbm.h" + +#define EGL_EGLEXT_PROTOTYPES +#include +#include +#define GL_GLEXT_PROTOTYPES +#include +#include + +namespace libcamera { + +LOG_DECLARE_CATEGORY(eGL) + +/** + * \class eGLImage + * \brief Helper class for managing EGL image resources + * + * The eGLImage class encapsulates OpenGL ES texture and framebuffer objects + * along with their associated EGL image. It aggregates handles, descriptors, + * and routines for managing textures that can be associated with shader + * uniform IDs. + * + * This class is particularly useful for managing DMA-BUF backed textures + * in zero-copy rendering pipelines, where textures are bound to specific + * texture units and can be used as both input textures and render targets. + */ +class eGLImage +{ +public: + /** + * \brief Construct an eGLImage with explicit stride + * \param[in] width Image width in pixels + * \param[in] height Image height in pixels + * \param[in] bpp Bytes per pixel + * \param[in] stride Row stride in bytes + * \param[in] texture_unit OpenGL texture unit + * \param[in] texture_unit_uniform_id Shader uniform ID + */ + eGLImage(uint32_t width, uint32_t height, uint32_t bpp, uint32_t stride, GLenum texture_unit, uint32_t texture_unit_uniform_id) + : width_(width), height_(height), stride_(stride), + framesize_(stride * height), bpp_(bpp), + texture_unit_uniform_id_(texture_unit_uniform_id), + texture_unit_(texture_unit) + { + glGenTextures(1, &texture_); + glGenFramebuffers(1, &fbo_); + } + + /** + * \brief Construct an eGLImage with automatic stride calculation + */ + eGLImage(uint32_t width, uint32_t height, uint32_t bpp, GLenum texture_unit, uint32_t texture_unit_uniform_id) + : eGLImage(width, height, bpp, utils::alignUp(width * bpp / 8, 256), + texture_unit, texture_unit_uniform_id) + { + } + + /** + * \brief Destroy the eGLImage + * + * Cleans up OpenGL resources by deleting the framebuffer object and + * texture. + */ + ~eGLImage() + { + glDeleteFramebuffers(1, &fbo_); + glDeleteTextures(1, &texture_); + } + + uint32_t width_; /**< Image width in pixels */ + uint32_t height_; /**< Image height in pixels */ + uint32_t stride_; /**< Row stride in bytes */ + uint32_t offset_; /**< Buffer offset (reserved for future use) */ + uint32_t framesize_; /**< Total frame size in bytes (stride * height) */ + uint32_t bpp_; /**< Bytes per pixel */ + uint32_t texture_unit_uniform_id_; /**< Shader uniform id for texture unit */ + GLenum texture_unit_; /**< Texture unit associated with this image eg (GL_TEXTURE0) */ + GLuint texture_; /**< OpenGL texture object ID */ + GLuint fbo_; /**< OpenGL frame buffer object ID */ + EGLImageKHR image_; /**< EGL Image handle */ + +private: + LIBCAMERA_DISABLE_COPY_AND_MOVE(eGLImage) +}; + +class eGL +{ +public: + eGL(); + ~eGL(); + + int initEGLContext(GBM *gbmContext); + void cleanUp(); + + int createInputDMABufTexture2D(eGLImage &eglImage, int fd); + int createOutputDMABufTexture2D(eGLImage &eglImage, int fd); + void destroyDMABufTexture(eGLImage &eglImage); + void createTexture2D(eGLImage &eglImage, GLint format, uint32_t width, uint32_t height, void *data); + + void pushEnv(std::vector &shaderEnv, const char *str); + void makeCurrent(); + + int compileVertexShader(GLuint &shaderId, const unsigned char *shaderData, + unsigned int shaderDataLen, + Span shaderEnv); + int compileFragmentShader(GLuint &shaderId, const unsigned char *shaderData, + unsigned int shaderDataLen, + Span shaderEnv); + int linkProgram(GLuint &programId, GLuint fragmentshaderId, GLuint vertexshaderId); + void dumpShaderSource(GLuint shaderId); + void useProgram(GLuint programId); + void deleteProgram(GLuint programId); + void syncOutput(); + +private: + LIBCAMERA_DISABLE_COPY_AND_MOVE(eGL) + + pid_t tid_; + + EGLDisplay display_ = EGL_NO_DISPLAY; + EGLContext context_ = EGL_NO_CONTEXT; + EGLSurface surface_ = EGL_NO_SURFACE; + + int compileShader(int shaderType, GLuint &shaderId, const unsigned char *shaderData, + unsigned int shaderDataLen, + Span shaderEnv); + + int createDMABufTexture2D(eGLImage &eglImage, int fd, bool output); + + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; + PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; + PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; +}; +} //namespace libcamera diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build index b8324996b..dc48619e5 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -23,6 +23,7 @@ libcamera_internal_headers = files([ 'dma_buf_allocator.h', 'formats.h', 'framebuffer.h', + 'egl.h', 'gbm.h', 'global_configuration.h', 'ipa_data_serializer.h', diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp new file mode 100644 index 000000000..0544056bd --- /dev/null +++ b/src/libcamera/egl.cpp @@ -0,0 +1,608 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Linaro Ltd. + * + * Authors: + * Bryan O'Donoghue + * + */ + +#include "libcamera/internal/egl.h" + +#include +#include +#include +#include + +#include +#include + +#include + +#include + +namespace libcamera { + +LOG_DEFINE_CATEGORY(eGL) + +/** + * \class eGL + * \brief Helper class for managing OpenGL ES operations + * + * It provides: + * + * - EGL context setup and management + * - Extension function pointer retrieval + * - Shader compilation and program linking + * - DMA-BUF texture creation and management + * - Synchronisation primitives + * + * This class is designed to work with zero-copy buffers via DMA-BUF file + * descriptors. + */ + +/** + *\var eGL::tid_ + *\brief Thread ID of the thread associated with this EGL context + */ + +/** + *\var eGL::display_ + *\brief EGL display handle + */ + +/** + *\var eGL::context_ + *\brief EGL context handle + */ + +/** + *\var eGL::surface_ + *\brief EGL sufrace handle + */ + +/** + * \brief Construct an EGL helper + * + * Creates an eGL instance with uninitialised context. Call initEGLContext() + * to set up the EGL display, context, and load extension functions. + */ +eGL::eGL() +{ +} + +/** + * \brief Destroy the EGL helper + * + * Destroys the EGL context and surface if they were successfully created. + */ +eGL::~eGL() +{ + if (context_ != EGL_NO_CONTEXT) + eglDestroyContext(display_, context_); + + if (surface_ != EGL_NO_SURFACE) + eglDestroySurface(display_, surface_); +} + +/** + * \brief Synchronise rendering output + * + * Sychronise here. Calls glFinish() right now. + * + */ +void eGL::syncOutput() +{ + ASSERT(tid_ == Thread::currentId()); + + glFinish(); +} + +/** + * \brief Create a DMA-BUF backed 2D texture + * \param[in,out] eglImage EGL image to associate with the DMA-BUF + * \param[in] fd DMA-BUF file descriptor + * \param[in] output If true, create framebuffer for render target + * + * Internal implementation for creating DMA-BUF textures. Creates an EGL + * image from the DMA-BUF and binds it to a 2D texture. If output is true, + * also creates and attaches a framebuffer object. + * + * \return 0 on success, or -ENODEV on failure + */ +int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) +{ + int ret = 0; + + ASSERT(tid_ == Thread::currentId()); + + // clang-format off + EGLint image_attrs[] = { + EGL_WIDTH, (EGLint)eglImage.width_, + EGL_HEIGHT, (EGLint)eglImage.height_, + EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_ARGB8888, + EGL_DMA_BUF_PLANE0_FD_EXT, fd, + EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, + EGL_DMA_BUF_PLANE0_PITCH_EXT, (EGLint)eglImage.stride_, + EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, 0, + EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, 0, + EGL_NONE, + }; + // clang-format on + + eglImage.image_ = eglCreateImageKHR(display_, EGL_NO_CONTEXT, + EGL_LINUX_DMA_BUF_EXT, + NULL, image_attrs); + + if (eglImage.image_ == EGL_NO_IMAGE_KHR) { + LOG(eGL, Error) << "eglCreateImageKHR fail"; + ret = -ENODEV; + goto done; + } + + // Bind texture unit and texture + glActiveTexture(eglImage.texture_unit_); + glBindTexture(GL_TEXTURE_2D, eglImage.texture_); + + // Generate texture with filter semantics + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglImage.image_); + + // Nearest filtering + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + // Wrap to edge to avoid edge artifacts + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + if (output) { + // Generate a framebuffer from our texture direct to dma-buf handle buffer + glBindFramebuffer(GL_FRAMEBUFFER, eglImage.fbo_); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, eglImage.texture_, 0); + + GLenum err = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (err != GL_FRAMEBUFFER_COMPLETE) { + LOG(eGL, Error) << "glFrameBufferTexture2D error " << err; + eglDestroyImageKHR(display_, eglImage.image_); + ret = -ENODEV; + goto done; + } + } +done: + return ret; +} + +/** + * \brief Create an input DMA-BUF backed texture + * \param[in,out] eglImage EGL image to associate with the DMA-BUF + * \param[in] fd DMA-BUF file descriptor + * + * Creates an EGL image from a DMA-BUF file descriptor and binds it to + * a 2D texture for use as an input texture in shaders. The texture is + * configured with nearest filtering and clamp-to-edge wrapping. + * + * \return 0 on success, or -ENODEV on failure + */ +int eGL::createInputDMABufTexture2D(eGLImage &eglImage, int fd) +{ + ASSERT(tid_ == Thread::currentId()); + + return createDMABufTexture2D(eglImage, fd, false); +} + +/** + * \brief Create an output DMA-BUF backed texture + * \param[in,out] eglImage EGL image to associate with the DMA-BUF + * \param[in] fd DMA-BUF file descriptor + * + * Creates an EGL image from a DMA-BUF file descriptor and binds it to + * a 2D texture, then attaches it to a framebuffer object for use as a + * render target. This enables zero-copy rendering directly to the + * DMA-BUF. + * + * \return 0 on success, or -ENODEV on failure + */ +int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd) +{ + ASSERT(tid_ == Thread::currentId()); + + return createDMABufTexture2D(eglImage, fd, true); +} + +/** + * \brief Destroy a DMA-BUF texture's EGL image + * \param[in,out] eglImage EGL image to destroy + * + * Destroys the EGL image associated with a DMA-BUF texture. The OpenGL + * texture and framebuffer objects are destroyed separately in the + * eGLImage destructor. + */ +void eGL::destroyDMABufTexture(eGLImage &eglImage) +{ + eglDestroyImage(display_, std::exchange(eglImage.image_, EGL_NO_IMAGE_KHR)); +} + +/** + * \brief Create a 2D texture from a memory buffer + * \param[in,out] eglImage EGL image to associate with the texture + * \param[in] format OpenGL internal format (e.g., GL_RGB, GL_RGBA) + * \param[in] width Texture width in pixels + * \param[in] height Texture height in pixels + * \param[in] data Pointer to pixel data, or nullptr for uninitialised texture + * + * Creates a 2D texture from a CPU-accessible memory buffer. The texture + * is configured with nearest filtering and clamp-to-edge wrapping. This + * is useful for uploading static data like lookup tables or uniform color + * matrices to the GPU. + */ +void eGL::createTexture2D(eGLImage &eglImage, GLint format, uint32_t width, uint32_t height, void *data) +{ + ASSERT(tid_ == Thread::currentId()); + + glActiveTexture(eglImage.texture_unit_); + glBindTexture(GL_TEXTURE_2D, eglImage.texture_); + + // Generate texture, bind, associate image to texture, configure, unbind + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); + + // Nearest filtering + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + // Wrap to edge to avoid edge artifacts + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); +} + +/** + * \brief Initialise the EGL context + * \param[in] gbmContext Pointer to initialised GBM context + * + * Sets up the EGL display from the GBM device, creates an OpenGL ES 2.0 + * context, and retrieves function pointers for required extensions + * including: + * - eglCreateImageKHR / eglDestroyImageKHR + * - glEGLImageTargetTexture2DOES + * + * \return 0 on success, or -ENODEV on failure + */ +int eGL::initEGLContext(GBM *gbmContext) +{ + EGLint configAttribs[] = { + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + + EGLint contextAttribs[] = { + EGL_CONTEXT_MAJOR_VERSION, 2, + EGL_NONE + }; + + EGLint numConfigs; + EGLConfig config; + EGLint major; + EGLint minor; + + if (!eglBindAPI(EGL_OPENGL_ES_API)) { + LOG(eGL, Error) << "API bind fail"; + goto fail; + } + + display_ = eglGetDisplay(gbmContext->device()); + if (display_ == EGL_NO_DISPLAY) { + LOG(eGL, Error) << "Unable to get EGL display"; + goto fail; + } + + if (eglInitialize(display_, &major, &minor) != EGL_TRUE) { + LOG(eGL, Error) << "eglInitialize fail"; + goto fail; + } + + LOG(eGL, Info) << "EGL: version " << major << "." << minor; + LOG(eGL, Info) << "EGL: EGL_VERSION: " << eglQueryString(display_, EGL_VERSION); + LOG(eGL, Info) << "EGL: EGL_VENDOR: " << eglQueryString(display_, EGL_VENDOR); + LOG(eGL, Info) << "EGL: EGL_CLIENT_APIS: " << eglQueryString(display_, EGL_CLIENT_APIS); + LOG(eGL, Info) << "EGL: EGL_EXTENSIONS: " << eglQueryString(display_, EGL_EXTENSIONS); + + eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR"); + if (!eglCreateImageKHR) { + LOG(eGL, Error) << "eglCreateImageKHR not found"; + goto fail; + } + + eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR"); + if (!eglDestroyImageKHR) { + LOG(eGL, Error) << "eglDestroyImageKHR not found"; + goto fail; + } + + glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES"); + if (!glEGLImageTargetTexture2DOES) { + LOG(eGL, Error) << "glEGLImageTargetTexture2DOES not found"; + goto fail; + } + + if (eglChooseConfig(display_, configAttribs, &config, 1, &numConfigs) != EGL_TRUE) { + LOG(eGL, Error) << "eglChooseConfig fail"; + goto fail; + } + + context_ = eglCreateContext(display_, config, EGL_NO_CONTEXT, contextAttribs); + if (context_ == EGL_NO_CONTEXT) { + LOG(eGL, Error) << "eglContext returned EGL_NO_CONTEXT"; + goto fail; + } + + tid_ = Thread::currentId(); + + makeCurrent(); + + return 0; +fail: + + return -ENODEV; +} + +/** + * \brief Clean up EGL resources + * + * Destroys the EGL sync object. Must be called from the same thread + * that created the EGL context. + */ +void eGL::cleanUp() +{ +} + +/** + * \brief Make the EGL context current for the calling thread + * + * Binds the EGL context to the current thread, allowing OpenGL ES + * operations to be performed. Must be called from the thread that + * will perform rendering operations. + */ +void eGL::makeCurrent() +{ + ASSERT(tid_ == Thread::currentId()); + + if (eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, context_) != EGL_TRUE) { + LOG(eGL, Error) << "eglMakeCurrent fail"; + } +} + +/** + * \brief Activate a shader program for rendering + * \param[in] programId OpenGL program object ID + * + * Sets the specified program as the current rendering program. All + * subsequent draw calls will use this program's shaders. + */ +void eGL::useProgram(GLuint programId) +{ + ASSERT(tid_ == Thread::currentId()); + + glUseProgram(programId); +} + +/** + * \brief Delete a shader program + * \param[in] programId OpenGL program object ID + * + * Deletes a shader program and frees associated resources. The program + * must not be currently in use. + */ +void eGL::deleteProgram(GLuint programId) +{ + ASSERT(tid_ == Thread::currentId()); + + glDeleteProgram(programId); +} + +/** + * \brief Add a preprocessor definition to shader environment + * \param[in,out] shaderEnv Vector of shader environment strings + * \param[in] str Preprocessor definition string (e.g., "#define APPLY_RGB_PARAMETERS") + * + * Appends a preprocessor definition to the shader environment vector. + * These definitions are prepended to shader source code during compilation. + */ +void eGL::pushEnv(std::vector &shaderEnv, const char *str) +{ + std::string addStr = str; + + addStr.push_back('\n'); + shaderEnv.push_back(std::move(addStr)); +} + +/** + * \brief Compile a vertex shader + * \param[out] shaderId OpenGL shader object ID + * \param[in] shaderData Pointer to shader source code + * \param[in] shaderDataLen Length of shader source in bytes + * \param[in] shaderEnv Span of preprocessor definitions to prepend + * + * Compiles a vertex shader from source code with optional preprocessor + * definitions. On compilation failure, logs the shader info log. + * + * \return 0 on success, or -EINVAL on compilation failure + */ +int eGL::compileVertexShader(GLuint &shaderId, const unsigned char *shaderData, + unsigned int shaderDataLen, + Span shaderEnv) +{ + return compileShader(GL_VERTEX_SHADER, shaderId, shaderData, shaderDataLen, shaderEnv); +} + +/** + * \brief Compile a fragment shader + * \param[out] shaderId OpenGL shader object ID + * \param[in] shaderData Pointer to shader source code + * \param[in] shaderDataLen Length of shader source in bytes + * \param[in] shaderEnv Span of preprocessor definitions to prepend + * + * Compiles a fragment shader from source code with optional preprocessor + * definitions. On compilation failure, logs the shader info log. + * + * \return 0 on success, or -EINVAL on compilation failure + */ +int eGL::compileFragmentShader(GLuint &shaderId, const unsigned char *shaderData, + unsigned int shaderDataLen, + Span shaderEnv) +{ + return compileShader(GL_FRAGMENT_SHADER, shaderId, shaderData, shaderDataLen, shaderEnv); +} + +/** + * \brief Compile a shader of specified type + * \param[in] shaderType GL_VERTEX_SHADER or GL_FRAGMENT_SHADER + * \param[out] shaderId OpenGL shader object ID + * \param[in] shaderData Pointer to shader source code + * \param[in] shaderDataLen Length of shader source in bytes + * \param[in] shaderEnv Span of preprocessor definitions to prepend + * + * Internal helper function for shader compilation. Prepends environment + * definitions to the shader source and compiles the shader. + * + * \return 0 on success, or -EINVAL on compilation failure + */ +int eGL::compileShader(int shaderType, GLuint &shaderId, const unsigned char *shaderData, + unsigned int shaderDataLen, + Span shaderEnv) +{ + GLint success; + size_t i; + + ASSERT(tid_ == Thread::currentId()); + + auto count = 1 + shaderEnv.size(); + auto shaderSourceData = std::make_unique(count); + auto shaderDataLengths = std::make_unique(count); + + // Prefix defines before main body of shader + for (i = 0; i < shaderEnv.size(); i++) { + shaderSourceData[i] = shaderEnv[i].c_str(); + shaderDataLengths[i] = shaderEnv[i].length(); + } + + // Now the main body of the shader program + shaderSourceData[i] = reinterpret_cast(shaderData); + shaderDataLengths[i] = shaderDataLen; + + // And create the shader + shaderId = glCreateShader(shaderType); + glShaderSource(shaderId, count, shaderSourceData.get(), shaderDataLengths.get()); + glCompileShader(shaderId); + + // Check status + glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success); + if (success == GL_FALSE) { + GLint sizeLog = 0; + + glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &sizeLog); + auto infoLog = std::make_unique(sizeLog); + + glGetShaderInfoLog(shaderId, sizeLog, &sizeLog, infoLog.get()); + LOG(eGL, Error) << infoLog.get(); + } + + return (success == GL_TRUE) ? 0 : -EINVAL; +} + +/** + * \brief Dump shader source code to the log + * \param[in] shaderId OpenGL shader object ID + * + * Retrieves and logs the complete source code of a compiled shader. + * Useful for debugging shader compilation issues. + */ +void eGL::dumpShaderSource(GLuint shaderId) +{ + GLint shaderLength = 0; + + ASSERT(tid_ == Thread::currentId()); + + glGetShaderiv(shaderId, GL_SHADER_SOURCE_LENGTH, &shaderLength); + + LOG(eGL, Debug) << "Shader length is " << shaderLength; + + if (shaderLength > 0) { + auto shaderSource = std::make_unique(shaderLength); + + glGetShaderSource(shaderId, shaderLength, &shaderLength, shaderSource.get()); + if (shaderLength) { + LOG(eGL, Debug) << "Shader source = " << shaderSource.get(); + } + } +} + +/** + * \brief Link a shader program + * \param[out] programId OpenGL program object ID + * \param[in] fragmentshaderId Compiled fragment shader ID + * \param[in] vertexshaderId Compiled vertex shader ID + * + * Links vertex and fragment shaders into an executable shader program. + * On link failure, logs the program info log and deletes the program. + * + * \return 0 on success, or -ENODEV on link failure + */ +int eGL::linkProgram(GLuint &programId, GLuint vertexshaderId, GLuint fragmentshaderId) +{ + GLint success; + GLenum err; + int ret = -ENODEV; + + ASSERT(tid_ == Thread::currentId()); + + programId = glCreateProgram(); + if (!programId) { + LOG(eGL, Error) << "glGreateProgram error"; + return ret; + } + + utils::scope_exit programGuard([&] { glDeleteProgram(programId); }); + + glAttachShader(programId, vertexshaderId); + if ((err = glGetError()) != GL_NO_ERROR) { + LOG(eGL, Error) << "Attach compute vertex shader fail err=" << err; + return ret; + } + + glAttachShader(programId, fragmentshaderId); + if ((err = glGetError()) != GL_NO_ERROR) { + LOG(eGL, Error) << "Attach compute fragment shader fail err=" << err; + return ret; + } + + glLinkProgram(programId); + if ((err = glGetError()) != GL_NO_ERROR) { + LOG(eGL, Error) << "Link program fail err=" << err; + return ret; + } + + glDetachShader(programId, fragmentshaderId); + glDetachShader(programId, vertexshaderId); + + // Check status + glGetProgramiv(programId, GL_LINK_STATUS, &success); + if (success == GL_FALSE) { + GLint sizeLog = 0; + + glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &sizeLog); + auto infoLog = std::make_unique(sizeLog); + + glGetProgramInfoLog(programId, sizeLog, &sizeLog, infoLog.get()); + LOG(eGL, Error) << infoLog.get(); + + return ret; + } + + programGuard.release(); + return 0; +} +} /* namespace libcamera */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index cb7863852..6f952bd98 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -79,6 +79,27 @@ if libgbm.found() and gbm_works ]) endif +mesa_works = cc.check_header('EGL/egl.h', required: false) +libegl = dependency('egl', required : false) +libglesv2 = dependency('glesv2', required : false) + +if libegl.found() + config_h.set('HAVE_LIBEGL', 1) +endif + +if libglesv2.found() + config_h.set('HAVE_GLESV2', 1) +endif + +if mesa_works and gbm_works + libcamera_internal_sources += files([ + 'egl.cpp', + ]) + gles_headless_enabled = true +else + gles_headless_enabled = false +endif + subdir('base') subdir('converter') subdir('ipa') @@ -187,7 +208,9 @@ libcamera_deps += [ libcamera_base_private, libcrypto, libdl, + libegl, libgbm, + libglesv2, liblttng, libudev, libyaml, From patchwork Tue Jan 6 17:00:39 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25657 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 576DABDCC0 for ; Tue, 6 Jan 2026 17:01:12 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9518361FD9; Tue, 6 Jan 2026 18:01:11 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="raR2DRGP"; dkim-atps=neutral Received: from mail-wr1-x432.google.com (mail-wr1-x432.google.com [IPv6:2a00:1450:4864:20::432]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3206E61F9F for ; Tue, 6 Jan 2026 18:01:09 +0100 (CET) Received: by mail-wr1-x432.google.com with SMTP id ffacd0b85a97d-42e2ba54a6fso452635f8f.3 for ; Tue, 06 Jan 2026 09:01:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718868; x=1768323668; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Wt8h+ZjhgdR+OdkPLA1nogPcLvDpX9IavMvjc6CFwXo=; b=raR2DRGPCouq37rrYrtY3f6+YvIAJYadRjLy+llo3sHVjW6ts0UiyrxGhKKu6BKpEK sBxPKZuMEyclEEtkTFbHTpZHzkLqN8p7s1TlGoVLzjzIDEPZJ3yieGqZSu6HQS7fPiJt aPjC7Hz/1DgcoD6ADnC9I9wQ6OfopvQ38GcRVGe3x/m6ME6cF4PoDQ8A34Nf/ftWk5T2 dWIrg7pv3+xFVqQoaPY/0L0dWqZ1cedTIUp5rYf5SW0pudQqQdLaDYJdEghQCqcOhjSO vhapXokKBV2WPEhO/9kb7ZLOcU9BQbErRQJ1o4ofSH6qmiW4EfnC41B9XUCoLNrTym6v L6fA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718868; x=1768323668; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Wt8h+ZjhgdR+OdkPLA1nogPcLvDpX9IavMvjc6CFwXo=; b=ijBYGMyTsRQNm1/S7KxLCg0PdIFM7MhcynYmo5dPr5rtIA9WZ2YN5w286GgPcdiA7+ qU+y9ifICjbG1zmxSEBj/ZlFzdC3PyPEFWCot+zox4XdJSAlv2G7DY39R1J7ZH8NufnT ZQ/eq6ZJjkBurt8tOYKjuEmrd4fe/ELUqfkpOtpLG+47FujWJakqFvuQk7dWd/MFWFJa VdERCMJqccOAcG7Qaoh3pAme13GNaW34++eHur8H0m6QzleykA+APCXKXrkFEVYPJNw+ xQg+3GQidPKzjU5NcF8J/CIqlE0FF7z3Wy/jwx2FIFAtY3yvhxX+2HhitaLV9+HGYoY+ a69Q== X-Gm-Message-State: AOJu0YydD8KQqcbJmkOcz2nRHyB9TXtvBQnQyCdXF8gZlskuYA2QgS0I aBfUyY73ZBpnBQo0ezbSvV7TKFet34FWtswGIPy/ccmkdVPKGwuPKbZVx6szlPAgE5vVoEXCChY 6O2RcY/M= X-Gm-Gg: AY/fxX4TfFKg1P/No0ZpNHBvcI3F/n/KYafzpABZTAKAElQcj/2MHI0FAJWwJ5wiIxr gfi1ewWuLFrK1xbCAgIhWxOFv1ZkZ943VzULUGSVb4Ls7NUc5cKxGVcZUarN1afzBg7HABqRtTp 0zMAnCmdm8fnclnQRYRt6cAgVJz4vxnsE1T62dKyi3FdIViiVVlo/Oy026/2UZ3j0XKlWnwOn0/ TAth17dlv+RRAI9zRf73NOzyW/onyyfzTq93RElN34EeuvO6lO4iruH7Op6aPgrUV4fF8OhT766 D06fatHi2384EI4cIQW9CfXx1Nk3CE54QgHlyFmV9QeRgqckqxWHS0A+ZD8DTayyrMlj4HORGh2 V62MK/L72vR8RBifLZwHNN+uAhi/06O06YPaIoGWo0MkM+Wn6XlZeP22jFMTke6LB0+9B6LnyLz TZS95uiY3hP0Fl85FJ4Ev/D3G3lmuuhRVCM3pEL073jAeh7nl7zm2re4W67agjf8z1z0A= X-Google-Smtp-Source: AGHT+IGuwNlFxtJKT0LojJ9vOaxxwb0+S+2F6+M8PX1Ci2e27XJ+frMVK0BNWv704U/WwbR1hT7CtQ== X-Received: by 2002:a5d:5d11:0:b0:42f:bab5:953d with SMTP id ffacd0b85a97d-432bca50238mr5046775f8f.47.1767718867673; Tue, 06 Jan 2026 09:01:07 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:07 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v11 04/24] qcam: viewfinder_gl: Set no-op Bayer shader values Date: Tue, 6 Jan 2026 17:00:39 +0000 Message-ID: <20260106170059.56193-5-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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" Populate qcam viewfinder_gl to set default Bayer values so that the shaders can be used in their original mode without conditional compilation. Set an identity CCM, identity Black Level and set Gamma and Contrast to 1.0f respectively. Once this change is made we can use the Bayer shaders in their original format in qcam with raw streams. Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue Reviewed-by: Kieran Bingham --- src/apps/qcam/viewfinder_gl.cpp | 26 ++++++++++++++++++++++++++ src/apps/qcam/viewfinder_gl.h | 12 ++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/apps/qcam/viewfinder_gl.cpp b/src/apps/qcam/viewfinder_gl.cpp index 1554c94d5..0d06122f6 100644 --- a/src/apps/qcam/viewfinder_gl.cpp +++ b/src/apps/qcam/viewfinder_gl.cpp @@ -473,6 +473,10 @@ bool ViewFinderGL::createFragmentShader() textureUniformSize_ = shaderProgram_.uniformLocation("tex_size"); textureUniformStrideFactor_ = shaderProgram_.uniformLocation("stride_factor"); textureUniformBayerFirstRed_ = shaderProgram_.uniformLocation("tex_bayer_first_red"); + ccmUniformDataIn_ = shaderProgram_.uniformLocation("ccm"); + blackLevelUniformDataIn_ = shaderProgram_.uniformLocation("blacklevel"); + gammaUniformDataIn_ = shaderProgram_.uniformLocation("gamma"); + contrastExpUniformDataIn_ = shaderProgram_.uniformLocation("contrastExp"); /* Create the textures. */ for (std::unique_ptr &texture : textures_) { @@ -542,6 +546,16 @@ void ViewFinderGL::doRender() /* Stride of the first plane, in pixels. */ unsigned int stridePixels; + /* Identity CCM */ + float ccm[] = { 1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 1.0f }; + + QMatrix3x3 qCcmMat(ccm); + + /* Black Level */ + QVector3D qBlackLevelVec(0.0f, 0.0f, 0.0f); + switch (format_) { case libcamera::formats::NV12: case libcamera::formats::NV21: @@ -788,6 +802,18 @@ void ViewFinderGL::doRender() * the generic stride factor to 1.0. */ stridePixels = size_.width(); + + /* Colour Correction Matrix */ + shaderProgram_.setUniformValue(ccmUniformDataIn_, qCcmMat); + + /* Black Level */ + shaderProgram_.setUniformValue(blackLevelUniformDataIn_, qBlackLevelVec); + + /* Gamma */ + shaderProgram_.setUniformValue(gammaUniformDataIn_, 1.0f); + + /* Contrast */ + shaderProgram_.setUniformValue(contrastExpUniformDataIn_, 1.0f); break; default: diff --git a/src/apps/qcam/viewfinder_gl.h b/src/apps/qcam/viewfinder_gl.h index 23c657bcf..1aa85e4fc 100644 --- a/src/apps/qcam/viewfinder_gl.h +++ b/src/apps/qcam/viewfinder_gl.h @@ -103,5 +103,17 @@ private: GLuint textureUniformBayerFirstRed_; QPointF firstRed_; + /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */ + GLint ccmUniformDataIn_; + + /* Black Level compensation */ + GLint blackLevelUniformDataIn_; + + /* Gamma */ + GLint gammaUniformDataIn_; + + /* Contrast */ + GLint contrastExpUniformDataIn_; + QMutex mutex_; /* Prevent concurrent access to image_ */ }; From patchwork Tue Jan 6 17:00:40 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25659 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 8A3EDC3213 for ; Tue, 6 Jan 2026 17:01:15 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 32A0F6200B; Tue, 6 Jan 2026 18:01:15 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="WW73P4nU"; dkim-atps=neutral Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6A29861FD2 for ; Tue, 6 Jan 2026 18:01:11 +0100 (CET) Received: by mail-wr1-x42c.google.com with SMTP id ffacd0b85a97d-42b3d7c1321so696795f8f.3 for ; Tue, 06 Jan 2026 09:01:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718871; x=1768323671; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=dsnpPU/LrCFQHtN8Cq9/x2B3nNAbe5b+r69TX5DJM4Y=; b=WW73P4nUYU2db9m2ELM//PFdK6PNDUb3tUyuSq38E0oCL0BuMMfFBmU/ph1TMh89TU 37bpCmPP/dPgwg1M6a/QVyzhEnt/MDbnVHrKDHMCd+aMJ5Jp87DvxzN8VQYkBRGzBaAS MVwgFUj+TOcdwUNunGHejwkUG7grmzBDs+7Ystnw47bI+99C7jA3OemWo0llDM8rZIMX dhgn5uRpXTZjBhduaLUz0VsoMI9HfbvUWOpeIKB05N2JkFU5DJwQYROpmEg1BHzoNiNK xQ/k90l3FwcXQG/keTYh02gjv/4qT7WcOxJudNNpeLkPctvgPGKLfOWwRa6cLgNs/HFA B6jw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718871; x=1768323671; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=dsnpPU/LrCFQHtN8Cq9/x2B3nNAbe5b+r69TX5DJM4Y=; b=IQ4VCymwAksiRfV9QDnO5Fq1vHr8DRJZSrTduf3YJc+knEmqkCQQzmH23RRF4x0iot R9LknSHHRCpI2vrbvAIB73cfFxP6PQG9bjLwWEleP8jrVSlDLqdVlvMXU+NxkeGmlGX8 wvMb7HObfJ08IGunFmSXZ8PN7YBmgA/i6eRB/iYQvqpE3khTYADqG8IBoXl+T8vFDoHk h1qHG3BOiZOe+BkRDKu+YQ8umFmd9rk8p936nSM1h9+/vYryPTS1WAkUl8DmX/wuOxYA M3rFKp4Vytzb6+cYPQVlcxip41DoLJ7whK/Wn5DOu/wrYYpQwy0owZYIq8CoAzUCqTE4 Vf6g== X-Gm-Message-State: AOJu0YxvSWc0Lv9kXadzZ2LDmk2jvEJJzm+TvhNkXuM3MnheTsyi1dHA BuLbDssB9xKwnkmQB60tg3E7M/hpsY/9bvPFgFy4KaRehWZ6u7t/Y7KaWY+LvF/QHi12m14tMvl EsD0YY5s= X-Gm-Gg: AY/fxX4mFL1ftvuIueZaQT0qO8/CKjkaIzTkrfrMf5Z0Bs7IZD69fVXyXkEhi5TKVdh F6TaPwuAwSl5uUg84eL4b7Owlz+hTRMa++cqUeDT84jxUpaUi1Yh/5mjDv0EHJyApt4gwbWxnAQ 0reO0cHwBPpfcwcyGXR0l9QgETpCBFOtFSeQm0Wi+Uol96aLkvtx/FtS6RMD/AxfnxJvY2XNpYT lGSxUj6Ii7ewYSku07tPqI0kdwfAccHHJDnrHuJjI9ZhJuCMQhKEfaroveugh2+dX1oj2X1GFov l1remnnTW0rDuyqP6FoharP3YN9lwXumi+nSTDLxSJTsRmXvuWSkRj3t5Rcm3OnaZetIi41LArH MgbQzoH1d8g82DHfKdhIfmn70XLj6yH7bu/HOiZTh3Y0ttxQh6rG2+1MXtZ6E58d37b0P19gzBj a8oaLj19WzyA8Fa/Xv5xsH0Ys9OcD2Tj3goyG78TyGAYlYndWBRvU4F4CsRhjpqKnlVpE= X-Google-Smtp-Source: AGHT+IEkCiNe5TJa+bkQk6UUXwXrfVz/J+QVkfoecD2ildZitOsx8dYn1yWY7y+JURWbufuGvH+U0g== X-Received: by 2002:a05:6000:220f:b0:430:f5ed:83f3 with SMTP id ffacd0b85a97d-432bc9cc8a6mr4321999f8f.9.1767718868978; Tue, 06 Jan 2026 09:01:08 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:08 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Milan Zamazal , Kieran Bingham , Bryan O'Donoghue Subject: [PATCH v11 05/24] libcamera: shaders: Rename bayer_8 to bayer_unpacked Date: Tue, 6 Jan 2026 17:00:40 +0000 Message-ID: <20260106170059.56193-6-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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: Milan Zamazal bayer_8.* shaders are now used for all unpacked sensor data formats, regardless of the pixel bit width. Let's rename the "8-bit" shaders to avoid confusion. Signed-off-by: Milan Zamazal Reviewed-by: Kieran Bingham Signed-off-by: Bryan O'Donoghue --- src/apps/qcam/assets/shader/shaders.qrc | 4 ++-- src/apps/qcam/viewfinder_gl.cpp | 16 ++++++++-------- .../{bayer_8.frag => bayer_unpacked.frag} | 0 .../{bayer_8.vert => bayer_unpacked.vert} | 0 src/libcamera/shaders/meson.build | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) rename src/libcamera/shaders/{bayer_8.frag => bayer_unpacked.frag} (100%) rename src/libcamera/shaders/{bayer_8.vert => bayer_unpacked.vert} (100%) diff --git a/src/apps/qcam/assets/shader/shaders.qrc b/src/apps/qcam/assets/shader/shaders.qrc index 7369cdbe8..f11a68ef2 100644 --- a/src/apps/qcam/assets/shader/shaders.qrc +++ b/src/apps/qcam/assets/shader/shaders.qrc @@ -6,8 +6,8 @@ ../../../../../src/libcamera/shaders/YUV_3_planes.frag ../../../../../src/libcamera/shaders/YUV_packed.frag ../../../../../src/libcamera/shaders/bayer_1x_packed.frag - ../../../../../src/libcamera/shaders/bayer_8.frag - ../../../../../src/libcamera/shaders/bayer_8.vert + ../../../../../src/libcamera/shaders/bayer_unpacked.frag + ../../../../../src/libcamera/shaders/bayer_unpacked.vert ../../../../../src/libcamera/shaders/identity.vert diff --git a/src/apps/qcam/viewfinder_gl.cpp b/src/apps/qcam/viewfinder_gl.cpp index 0d06122f6..1d3f48917 100644 --- a/src/apps/qcam/viewfinder_gl.cpp +++ b/src/apps/qcam/viewfinder_gl.cpp @@ -235,29 +235,29 @@ bool ViewFinderGL::selectFormat(const libcamera::PixelFormat &format) case libcamera::formats::SBGGR8: firstRed_.setX(1.0); firstRed_.setY(1.0); - vertexShaderFile_ = ":src/libcamera/shaders/bayer_8.vert"; - fragmentShaderFile_ = ":src/libcamera/shaders/bayer_8.frag"; + vertexShaderFile_ = ":src/libcamera/shaders/bayer_unpacked.vert"; + fragmentShaderFile_ = ":src/libcamera/shaders/bayer_unpacked.frag"; textureMinMagFilters_ = GL_NEAREST; break; case libcamera::formats::SGBRG8: firstRed_.setX(0.0); firstRed_.setY(1.0); - vertexShaderFile_ = ":src/libcamera/shaders/bayer_8.vert"; - fragmentShaderFile_ = ":src/libcamera/shaders/bayer_8.frag"; + vertexShaderFile_ = ":src/libcamera/shaders/bayer_unpacked.vert"; + fragmentShaderFile_ = ":src/libcamera/shaders/bayer_unpacked.frag"; textureMinMagFilters_ = GL_NEAREST; break; case libcamera::formats::SGRBG8: firstRed_.setX(1.0); firstRed_.setY(0.0); - vertexShaderFile_ = ":src/libcamera/shaders/bayer_8.vert"; - fragmentShaderFile_ = ":src/libcamera/shaders/bayer_8.frag"; + vertexShaderFile_ = ":src/libcamera/shaders/bayer_unpacked.vert"; + fragmentShaderFile_ = ":src/libcamera/shaders/bayer_unpacked.frag"; textureMinMagFilters_ = GL_NEAREST; break; case libcamera::formats::SRGGB8: firstRed_.setX(0.0); firstRed_.setY(0.0); - vertexShaderFile_ = ":src/libcamera/shaders/bayer_8.vert"; - fragmentShaderFile_ = ":src/libcamera/shaders/bayer_8.frag"; + vertexShaderFile_ = ":src/libcamera/shaders/bayer_unpacked.vert"; + fragmentShaderFile_ = ":src/libcamera/shaders/bayer_unpacked.frag"; textureMinMagFilters_ = GL_NEAREST; break; case libcamera::formats::SBGGR10_CSI2P: diff --git a/src/libcamera/shaders/bayer_8.frag b/src/libcamera/shaders/bayer_unpacked.frag similarity index 100% rename from src/libcamera/shaders/bayer_8.frag rename to src/libcamera/shaders/bayer_unpacked.frag diff --git a/src/libcamera/shaders/bayer_8.vert b/src/libcamera/shaders/bayer_unpacked.vert similarity index 100% rename from src/libcamera/shaders/bayer_8.vert rename to src/libcamera/shaders/bayer_unpacked.vert diff --git a/src/libcamera/shaders/meson.build b/src/libcamera/shaders/meson.build index 386b342d0..dd441a577 100644 --- a/src/libcamera/shaders/meson.build +++ b/src/libcamera/shaders/meson.build @@ -4,7 +4,7 @@ # for the purposes of inclusion in OpenGL debayering shader_files = files([ 'bayer_1x_packed.frag', - 'bayer_8.frag', - 'bayer_8.vert', + 'bayer_unpacked.frag', + 'bayer_unpacked.vert', 'identity.vert', ]) From patchwork Tue Jan 6 17:00:41 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25658 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 8178EBDCC0 for ; Tue, 6 Jan 2026 17:01:14 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 36D8C62001; Tue, 6 Jan 2026 18:01:14 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="HbyTje2Q"; dkim-atps=neutral Received: from mail-wr1-x429.google.com (mail-wr1-x429.google.com [IPv6:2a00:1450:4864:20::429]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DEE6A61FD8 for ; Tue, 6 Jan 2026 18:01:10 +0100 (CET) Received: by mail-wr1-x429.google.com with SMTP id ffacd0b85a97d-430f9ffd4e8so12048f8f.0 for ; Tue, 06 Jan 2026 09:01:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718870; x=1768323670; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=FdyTcK0Xun67yTvAExHcO9DNNAcWNw/aYg3LzuhT/Zc=; b=HbyTje2Qt3bypbGQ+MKR2A1lhOly6h/tw6TNjaon0T1Fc49Krm1iP/Z5KaLE1pgrkK B14pVyBX5mW+PFHdwmxWb4XvyK7pil2R5Vra/90JCWXuIiZEd7druHP5bHe//WUov17v 5c+qF+RFBCWwV2us6QsxycJLR8hZujjFaFFWZgS3kqegbSWeMK6174S5IEYFa/LF31DP TTKY2tfA92tCMNEcZOK/R7wb5gGySWQB7/gxSFihzGmXutOz3rFLo/9zkBKVNOMB3bg9 HdZqACJGm79eEL7enmSoR//tjprr6wNb4BpOAGHn1Xq8UXybg/ws63avMj9nNhlTJi1j B5UQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718870; x=1768323670; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=FdyTcK0Xun67yTvAExHcO9DNNAcWNw/aYg3LzuhT/Zc=; b=wEHli2nxpDRd2XCZsS3p38sQmYnH3oRkL/sqD9f/lGARFCJF7u1Y1k5DOo5gTkBL19 nG6PXe55p7KgWSuoFLFEn2uAdOUTMzJXsJaAd5Ov2ROYybWgjzczEHF/36soFEDMmL3G Th/sT5/6PCUeQCX09974HydbsLuWfa2iab5irQ6fdqKZRndrYqtQG4wWWyX/maYdkpuu 15V9aUsNMjzNEaF4UoApKx2Znr+HVuVX3Mx2R2X0a5y/tGPj+VDug064QMVTL222HZnT BxpJ4RpHTR+Wg7GnnA2w52IXU8OXZzTPN4F6pNGbjdDc8u8mV4OmoBCoLon/YgZrmxRj 6k2w== X-Gm-Message-State: AOJu0YxIlyjJXv2BoWA7umfb2V3HsIa8O1CuU0ABT5eLp4ROEhp5FRKc D3vpg5hraQCNfBsEKFK+yflRTTXxSXT2QPQnuGh83hTwB+kADTX4Zz0vc3H3jOyXzG2KkEk6iaR VO9N2huc= X-Gm-Gg: AY/fxX4HvvAEdPXFLdy3wGyxceDhdd0dv7slty3aPXIW76qJetG8FLJRI8CINhRmfds wh2rwGKvbh+bZ+l0FrbtVMR1zT/P49thuxp/Pq6TgqTh+/qc+oPKe/TqqSfojNqdjKZvwe/p3qf d2lIaeU+xnmo5L8HXK+ihQFvxMBQ6JRMCETTZYrZEPTwVbpAEUjKgsnVRPJR1gUFZeRc7Uz7d2H kG++6v3N9bCGkPoZOnDVhtJlGBctA5/z3ZRH9JItaVkht/QsHKFEdxtpLUgYoYiZ7iUJCuxLO9S r9nTaVFxbjg+KhCMbJc641Bmm9T7Jee+Txu4ygvu71sjGLIxrCeqBL1t55qNuln643Y07itdWpy xjpNAqDYTewo4e9Yolw95r2zzvoy+I++krfq9015dARSVvoWgoPRrcAVbe/T4AwDepkBty50PW2 2b19UsTxvWdQckNstvn0/VgOZrQ0CJERxlHWN3GrsBd84OQ/pr2VhAdz8q50OSks26j0I= X-Google-Smtp-Source: AGHT+IGA3h8/j0K6YrgdG79neI22XcE/kolLhlAEY4OCLvXgzRRCxOe+ckTu2IzZMdiNAgdisF2TEA== X-Received: by 2002:a05:6000:3107:b0:430:f593:aa34 with SMTP id ffacd0b85a97d-432bcfd3d38mr4146306f8f.17.1767718869930; Tue, 06 Jan 2026 09:01:09 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:09 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Kieran Bingham , Milan Zamazal Subject: [PATCH v11 06/24] libcamera: shaders: Use highp not mediump for float precision Date: Tue, 6 Jan 2026 17:00:41 +0000 Message-ID: <20260106170059.56193-7-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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" mediump gives 10 bits of mantissa as the resolution. At higher resolutions 10 bits of accuracy is insufficient - for example at a width of 1928 bytes we need log2(1928) = ~11 bit resolution. Switching to highp gives us 23 bits of mantissa giving a sample width precision of about 2^23 ~ 8,388,608. Acked-by: Kieran Bingham Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/libcamera/shaders/RGB.frag | 2 +- src/libcamera/shaders/YUV_2_planes.frag | 2 +- src/libcamera/shaders/YUV_3_planes.frag | 2 +- src/libcamera/shaders/YUV_packed.frag | 2 +- src/libcamera/shaders/bayer_1x_packed.frag | 2 +- src/libcamera/shaders/bayer_unpacked.frag | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libcamera/shaders/RGB.frag b/src/libcamera/shaders/RGB.frag index 4c374ac98..724395894 100644 --- a/src/libcamera/shaders/RGB.frag +++ b/src/libcamera/shaders/RGB.frag @@ -6,7 +6,7 @@ */ #ifdef GL_ES -precision mediump float; +precision highp float; #endif varying vec2 textureOut; diff --git a/src/libcamera/shaders/YUV_2_planes.frag b/src/libcamera/shaders/YUV_2_planes.frag index 1d5d12062..d286f1179 100644 --- a/src/libcamera/shaders/YUV_2_planes.frag +++ b/src/libcamera/shaders/YUV_2_planes.frag @@ -6,7 +6,7 @@ */ #ifdef GL_ES -precision mediump float; +precision highp float; #endif varying vec2 textureOut; diff --git a/src/libcamera/shaders/YUV_3_planes.frag b/src/libcamera/shaders/YUV_3_planes.frag index 8f788e90a..8e3e0b4a5 100644 --- a/src/libcamera/shaders/YUV_3_planes.frag +++ b/src/libcamera/shaders/YUV_3_planes.frag @@ -6,7 +6,7 @@ */ #ifdef GL_ES -precision mediump float; +precision highp float; #endif varying vec2 textureOut; diff --git a/src/libcamera/shaders/YUV_packed.frag b/src/libcamera/shaders/YUV_packed.frag index b9ef9d41b..3c9e3e397 100644 --- a/src/libcamera/shaders/YUV_packed.frag +++ b/src/libcamera/shaders/YUV_packed.frag @@ -6,7 +6,7 @@ */ #ifdef GL_ES -precision mediump float; +precision highp float; #endif varying vec2 textureOut; diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag index f53f55758..19b13ad08 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -20,7 +20,7 @@ */ #ifdef GL_ES -precision mediump float; +precision highp float; #endif /* diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag index 7e35ca88e..aa7a1b004 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -16,7 +16,7 @@ Copyright (C) 2021, Linaro //Pixel Shader #ifdef GL_ES -precision mediump float; +precision highp float; #endif /** Monochrome RGBA or GL_LUMINANCE Bayer encoded texture.*/ From patchwork Tue Jan 6 17:00:42 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25660 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 81949BDCC0 for ; Tue, 6 Jan 2026 17:01:16 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2AD6861FD8; Tue, 6 Jan 2026 18:01:16 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="oUdIK4yz"; dkim-atps=neutral Received: from mail-wm1-x344.google.com (mail-wm1-x344.google.com [IPv6:2a00:1450:4864:20::344]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E18FD61FF4 for ; Tue, 6 Jan 2026 18:01:11 +0100 (CET) Received: by mail-wm1-x344.google.com with SMTP id 5b1f17b1804b1-477563e28a3so118815e9.1 for ; Tue, 06 Jan 2026 09:01:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718871; x=1768323671; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Zkzu0tqbzAOlMWvnkw6w2p9R2Nid+3zoTkR/m4lKMgE=; b=oUdIK4yzbMx259SE4ES9Qv6NSn+FjIRkPeATu8tA91bvOyqOOViBgdWTauZpZTHdkk niIe8I1Onvtm0hy/P3J4I0P/3FIY7P58GG8euYjZGYP5I6mbnmu7ajqeXcGRmt6GE+Ld rUeHqQv9E2/FnArlb78O0QyusKotmN2np/rIevqmDNf6JN1hiUL/RZJDWa18GD+BOLPZ BWdeEzU/eKgY5tywd2ktdPLqR0uvuxo2auw1owhbHDWG1hlqGUdBkXvhxUl8RixHchSK SwAsHFwXln5QMyuVFw+f38srWZVjJhblVmZDNmJq8+wOXsaMP5Yx8Xd1nhuFUBfmsGtm qPzQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718871; x=1768323671; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Zkzu0tqbzAOlMWvnkw6w2p9R2Nid+3zoTkR/m4lKMgE=; b=EMqbq8JTKc0TC9osxJjkpngafoi9qxysH3YdftYoeEkzmXnZ3ZrgGdBJLZFCU+jmWr mOgOQ7DIftJRt71F4Vexn5khxEkdu2++DvBa4wOZg++jYgpMNefvhg18u+kFZui/UgJh CkmG+OqaXGfyw7CsDJhcDF7iHU+cxQR596lqgCGV5873VxFnrv+PPyqr74z6EKJACKda vcc/9hPhK537HQOn5vrTlE0G+/qz/Jh/XBfL10JBzNLEkF8eqyGAUp8A/fx0l6WERAtr PkAbBsDpzaHrFweNpptS2CoHmyh+C4q3on2YCM/BGdWyNzjG6cUOheZKqbYmKgHz8Ewf XpNA== X-Gm-Message-State: AOJu0YxACYJ072j86j2BakbnkLDFFcK+hXrCa1z7K/k82zSueJkGO2QR /ib5sUg0H0j677P08qcJzST1r+e1rFoS8BhTx6SnkfSvNK8IazDPwGmVBxRi6ovwsHhVFa5BkcO DTr3SQnlz9A== X-Gm-Gg: AY/fxX6UNxAtEuP4nCtcgY1QZ6yXqGhUrivyn3N+hcRYKcBGPflGo+giWW8FxV5HJA9 rNJurawubz3kXYxlg+4NO2jlFQ6sIuzmc9jrc1i1dfPe5dsxrIpZiXXRJZ5Mz9JhLDuj12A4iRr kC9ueRmqQ9fCSjS53nkF542r5JFvrsQA9tstqjVvx1vs2NEJQ7rWKMVnhc7Z+UKSGC8jKBXz3If 3bQ8uNrM2jTGFRtLtLyimc+wxsS83ZhiDu8YaXUvKjr6xd5CZ48FA5oBwFnakjYUtu9TI1O6t55 Z6M9JHK/ooIYYANZXQLxOPHTa81mujTSAI1SuEDIAJX7L6ZJYyXFO+5VjqlTNUfNH/UHyFUMNIt O95/+aXERfucRgjyT0+9OKyASfLa4Rd3kwEpm9CKznGbl1MuPZfGPC7kKlJcZ+IAYo6NTv6fox3 af/JlEP9almszWF400rsBMSimnd2goPaD2XjttWlPvH5g77JFqPdA9mHE0L9GNSJqm8Do= X-Google-Smtp-Source: AGHT+IEWPolcrFllHr3v0D6uzYIpQTLfwLZCcALuhj+gPP98jVMpl1F+4EM2hYPqMYtYmPtqiFrmwg== X-Received: by 2002:a05:600c:46c3:b0:477:a2f7:74de with SMTP id 5b1f17b1804b1-47d7f404854mr51238645e9.3.1767718871170; Tue, 06 Jan 2026 09:01:11 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:10 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v11 07/24] libcamera: shaders: Extend debayer shaders to apply CCM gains Date: Tue, 6 Jan 2026 17:00:42 +0000 Message-ID: <20260106170059.56193-8-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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" Extend Bayer shaders to support application of a passed CCM table. Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/libcamera/shaders/bayer_1x_packed.frag | 45 +++++++++++++++++++ src/libcamera/shaders/bayer_unpacked.frag | 51 +++++++++++++++++++++- 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag index 19b13ad08..171a928c2 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 mat3 ccm; void main(void) { @@ -212,5 +213,49 @@ void main(void) vec3(patterns.y, C, patterns.x) : vec3(patterns.wz, C)); + /* + * CCM is a 3x3 in the format + * + * +--------------+----------------+---------------+ + * | RedRedGain | RedGreenGain | RedBlueGain | + * +--------------+----------------+---------------+ + * | GreenRedGain | GreenGreenGain | GreenBlueGain | + * +--------------+----------------+---------------+ + * | BlueRedGain | BlueGreenGain | BlueBlueGain | + * +--------------+----------------+---------------+ + * + * Rout = RedRedGain * Rin + RedGreenGain * Gin + RedBlueGain * Bin + * Gout = GreenRedGain * Rin + GreenGreenGain * Gin + GreenBlueGain * Bin + * Bout = BlueRedGain * Rin + BlueGreenGain * Gin + BlueBlueGain * Bin + * + * We upload to the GPU without transposition glUniformMatrix3f(.., .., GL_FALSE, ccm); + * + * CPU + * float ccm [] = { + * RedRedGain, RedGreenGain, RedBlueGain, + * GreenRedGain, GreenGreenGain, GreenBlueGain, + * BlueRedGain, BlueGreenGain, BlueBlueGain, + * }; + * + * GPU + * ccm = { + * RedRedGain, GreenRedGain, BlueRedGain, + * RedGreenGain, GreenGreenGain, BlueGreenGain, + * RedBlueGain, GreenBlueGain, BlueBlueGain, + * } + * + * However the indexing for the mat data-type is column major hence + * ccm[0][0] = RedRedGain, ccm[0][1] = RedGreenGain, ccm[0][2] = RedBlueGain + * + */ + float rin, gin, bin; + rin = rgb.r; + gin = rgb.g; + bin = rgb.b; + + rgb.r = (rin * ccm[0][0]) + (gin * ccm[0][1]) + (bin * ccm[0][2]); + rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); + rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + gl_FragColor = vec4(rgb, 1.0); } diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag index aa7a1b004..c41d72f4f 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -24,8 +24,11 @@ uniform sampler2D tex_y; varying vec4 center; varying vec4 yCoord; varying vec4 xCoord; +uniform mat3 ccm; void main(void) { + vec3 rgb; + #define fetch(x, y) texture2D(tex_y, vec2(x, y)).r float C = texture2D(tex_y, center.xy).r; // ( 0, 0) @@ -97,11 +100,57 @@ void main(void) { PATTERN.xw += kB.xw * B; PATTERN.xz += kF.xz * F; - gl_FragColor.rgb = (alternate.y == 0.0) ? + rgb = (alternate.y == 0.0) ? ((alternate.x == 0.0) ? vec3(C, PATTERN.xy) : vec3(PATTERN.z, C, PATTERN.w)) : ((alternate.x == 0.0) ? vec3(PATTERN.w, C, PATTERN.z) : vec3(PATTERN.yx, C)); + + /* + * CCM is a 3x3 in the format + * + * +--------------+----------------+---------------+ + * | RedRedGain | RedGreenGain | RedBlueGain | + * +--------------+----------------+---------------+ + * | GreenRedGain | GreenGreenGain | GreenBlueGain | + * +--------------+----------------+---------------+ + * | BlueRedGain | BlueGreenGain | BlueBlueGain | + * +--------------+----------------+---------------+ + * + * Rout = RedRedGain * Rin + RedGreenGain * Gin + RedBlueGain * Bin + * Gout = GreenRedGain * Rin + GreenGreenGain * Gin + GreenBlueGain * Bin + * Bout = BlueRedGain * Rin + BlueGreenGain * Gin + BlueBlueGain * Bin + * + * We upload to the GPU without transposition glUniformMatrix3f(.., .., GL_FALSE, ccm); + * + * CPU + * float ccm [] = { + * RedRedGain, RedGreenGain, RedBlueGain, + * GreenRedGain, GreenGreenGain, GreenBlueGain, + * BlueRedGain, BlueGreenGain, BlueBlueGain, + * }; + * + * GPU + * ccm = { + * RedRedGain, GreenRedGain, BlueRedGain, + * RedGreenGain, GreenGreenGain, BlueGreenGain, + * RedBlueGain, GreenBlueGain, BlueBlueGain, + * } + * + * However the indexing for the mat data-type is column major hence + * ccm[0][0] = RedRedGain, ccm[0][1] = RedGreenGain, ccm[0][2] = RedBlueGain + * + */ + float rin, gin, bin; + rin = rgb.r; + gin = rgb.g; + bin = rgb.b; + + rgb.r = (rin * ccm[0][0]) + (gin * ccm[0][1]) + (bin * ccm[0][2]); + rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); + rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + + gl_FragColor.rgb = rgb; } From patchwork Tue Jan 6 17:00:43 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25661 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 563D4C3213 for ; Tue, 6 Jan 2026 17:01:17 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F19A162004; Tue, 6 Jan 2026 18:01:16 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="Jixm7b+N"; dkim-atps=neutral Received: from mail-wr1-x442.google.com (mail-wr1-x442.google.com [IPv6:2a00:1450:4864:20::442]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DBA3961FB7 for ; Tue, 6 Jan 2026 18:01:12 +0100 (CET) Received: by mail-wr1-x442.google.com with SMTP id ffacd0b85a97d-430f2ee2f00so579008f8f.3 for ; Tue, 06 Jan 2026 09:01:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718872; x=1768323672; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=nAlpCB4iJopL0Pn768w20N/UlmcrQmnghUNHBy8yJOY=; b=Jixm7b+NPpIz9DA7+kErB9jEU2ezavMvvN1QMAcWF5Nd+UanmMobw0PmDlXfPbJnjL GfHb1HFzLvMQTOefKycCNAaaoELn+2BeGe45SaOLHLNDs45eX12lzt9+xnz6SKgJJVf1 6PgvyvTx42U2elOtc2MBwHy+rpUuNke2f0f8LFb+bhFpFqyc80PKADAq1VtOcSj01+4U tGJhXPwqk5tsOxgRPNfIEBMuPD69U0i4yk0lyJ070Px+cqgDFeSVGkWfKE8ynYPOQoLJ yAYSvn23PRN5jhnw8EAXiL2sBGoZ+qSZjnpIsvBn9jAmZ6wBbsovFxDI9JecCy+BmjHF Svyg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718872; x=1768323672; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=nAlpCB4iJopL0Pn768w20N/UlmcrQmnghUNHBy8yJOY=; b=jGLClE7Sqbreh0DAXsZrIqy+2Bi36W5WtLJLFxpzxtF6Xbx7BxGQvPuo5Dx1rb2jOR HmeuASn+TQjJpuUo6P2RxMVIQlk/cTRR3hYtNfLG7qTd41VLHZJLqgoNByc8zWAw0d0N 90fUz+2LhlQ3vBo8gjwGVBKafwNI2Frvdj4gg2HZHYthVXktY+ULwa6TacKg5L6edYWP GCg1eWVJp4MktWhVgs5zSzBDwCa15ofLqnV52qJkjt8AxpSZMXOfytPKI/DmMUFJmvGa j1Yk7gz4hRX/3kdGLlewyGxQRN6r1VaQ6aj7kbQGxN922pEcHKcdd+RKaf25Gzaxk8u2 ph3g== X-Gm-Message-State: AOJu0Yxwtyx32quyylu2/iszTdrpYbe6ahN34zDFflLW60yJnCN/TlL5 O6Pen+2f5u3w0UXqFWBXgaqy2PAF3a7D5fU4zP8zHrTn5HsQ1gDn1+oKTBFvjVlYPE5Zaxea3JU 0HTcBtEfHLg== X-Gm-Gg: AY/fxX7PK7nDoi8vWvjyIbiDUdu/9CEu0JK5t9l/OAyrw6EoI5MxKkvj9TSCOyYVgg7 SE5zg4mguCwVbRTvEqc19GbWmCC5nHJZxO/a9ONhRK31BMU50mVptqqeKkkrt8neDkDslGhu2vB 0I7PQz2ZtFhI3Uq8Uyp8YcHkZNW6c2JW7L6udNxs0TFCn9E1s4O0PCMorrBGAXxlOAe6rkuuNN/ EJDKzcJwJn4WVHHvgL8FbSP0JInC8ehQfEVDNu6oqk+Sq9/NupaAsMpq2yw8JI+mLHGBu110W91 fOqB8UziDgvnEEq9fyHGr7CqJ7qZvrwdX4ud2vGFa3xrDKF5uRWPQlxI23Z05tFeWkdLiILpewa AoIbmKq9PTRI/Y7StP1ZtE3t7uGF9YrsG7n7zlDx6BdsicYmSmdZgv1ZHa4p4vD99NiFLDaN7gB kEU+9B0cEsaamJwDtKRTQDMfv/4yvPQ/VwzUMyrsXFv+LjTqOdRnZ8CKMdFcUt1cQ2c94= X-Google-Smtp-Source: AGHT+IH1XYy9baiES9UT5C5d2cXk0dpA8cWnmrLNNJXTzi/7Z2GvMxXG5yV7o8l7Zr0HvEYa272V0w== X-Received: by 2002:a05:6000:2c0c:b0:401:5ad1:682 with SMTP id ffacd0b85a97d-432bca29ae0mr4326605f8f.14.1767718872150; Tue, 06 Jan 2026 09:01:12 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:11 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal , Kieran Bingham Subject: [PATCH v11 08/24] libcamera: shaders: Extend bayer shaders to support swapping R and B on output Date: Tue, 6 Jan 2026 17:00:43 +0000 Message-ID: <20260106170059.56193-9-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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" We can easily facilitate swapping R and B on output. Pivot on an environment define for this purpose. Reviewed-by: Milan Zamazal Acked-by: Kieran Bingham Signed-off-by: Bryan O'Donoghue --- src/libcamera/shaders/bayer_1x_packed.frag | 4 ++++ src/libcamera/shaders/bayer_unpacked.frag | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag index 171a928c2..db8c2a0b3 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -257,5 +257,9 @@ void main(void) rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); +#if defined (SWAP_BLUE) + gl_FragColor = vec4(rgb.bgr, 1.0); +#else gl_FragColor = vec4(rgb, 1.0); +#endif } diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag index c41d72f4f..06d80f3dd 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -152,5 +152,9 @@ void main(void) { rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); - gl_FragColor.rgb = rgb; +#if defined (SWAP_BLUE) + gl_FragColor = vec4(rgb.bgr, 1.0); +#else + gl_FragColor = vec4(rgb, 1.0); +#endif } From patchwork Tue Jan 6 17:00:44 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25662 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 E3F09BDCC0 for ; Tue, 6 Jan 2026 17:01:18 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9D4856200F; Tue, 6 Jan 2026 18:01:18 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="jHotMmce"; dkim-atps=neutral Received: from mail-wm1-x32b.google.com (mail-wm1-x32b.google.com [IPv6:2a00:1450:4864:20::32b]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7D20C6200D for ; Tue, 6 Jan 2026 18:01:14 +0100 (CET) Received: by mail-wm1-x32b.google.com with SMTP id 5b1f17b1804b1-4775ae77516so13072525e9.1 for ; Tue, 06 Jan 2026 09:01:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718874; x=1768323674; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=5qjoeAop1GzrvnIG7vvLvJkbwSmYKtE+YPe2MFgINpo=; b=jHotMmceuVQWtt2vCL4tt2JIeiZiunHPvS4OWghvc1sLpYQSvQf5vlxxWDCqpxEIno g7BjWfiFAnCM8H/Q5HO9yU5ibj3KD0XvC3fqxG9Tbn3SDd5zSg538zHDDJJSmbTecNcq YO/VUjnWpB6JGnZZzemvaVMJDyGE4azhBjE3eJfjCNqrneNlib+YWfOG8KMGqVKjYhIl 83yXN7DzojM//0pvhMr8posd46S6PByYYPcWm8195wWKu0iw/kKWHIpa3PIGIa/F24P4 YlrvVVEPojBsj8v/PDD+nAWAdC/QzN4OVeKBrvb645tw2jyaXXpGomDLMgKGiPX68N0h DN4Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718874; x=1768323674; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=5qjoeAop1GzrvnIG7vvLvJkbwSmYKtE+YPe2MFgINpo=; b=rY/SxSWkPEGlysZ8TvFZXcEpA9XnKCU+QQumEymRd3pUXMlUs7lSSTS5+YtvxhVKpz 4vv4BcJ8HBizDiyPtlG+8Txztbqq4M5QcvQzDwyvuv3lVNc0ZWzoFgOJ9zfq5re0dby+ fssj9TSSLo+VDI5v8zCdeZvbrwkUKCGjPLFuFsyNDwUwgJaUr/udRc1Yow/ZBmsFq2os +v+dWyeTTXgKoQD5IWDLneabXpfYW0fC2Qkmwu7xTt/1tVLThTqhh4TGB/3FLgORjN70 YnsuEfgkA6B+JrVWDvFbjl1jCoCCWHnAxxXkMRXJtf3LvTefMAv+WUoWqQTgfNT+rTHZ IHjg== X-Gm-Message-State: AOJu0YwSvqYwV17RROP9IcwKAsLaYMHPp3VRgkRhAIAJuVnVMgTmcJFv QMnlqDBfkTePLisR0xkfq0kCnVbRHx72Gr/qCNwWTuJIYHeBjonUJxtCCbh8AL3rx33FIQphkkO 22oLy9Tk= X-Gm-Gg: AY/fxX5xxJlHY0cqeBcQw7YqO4gW6S2qxs35q4GojPOrIbvfwhXZJDAJrPcyYYAOxIH CYgdKdkxvObK2vPKBaGp6iO1sBoVChvbjWSYsIm59NXX14oJN2npB856RFWGcdksxG+DbA93BHu G0wMDAl3toWWqlXiR0lH4ZBAXj8Jbmstb2lWdBLPhIwlstdrsGqAkBG6CdnDvWLWDOSG+nl1MK+ XZjXPSuhoaDA+vWbSkE5Xs1ZnJp38G8LDYJgldCUT8T405DgTct+ZqvTbE33AC189C0VWHlyVFe L+3wVqi6g8D/0tg6Rhiq37/3fAhBdZhy6TxY0M5gxIxqbCwvjAChRl0tmdoKtSGJcCcegyLKQFm DrM22rp7sOywDN4JBfzocGT4+tWUZWIlpwCJ1R5pQ52wJCBPgSN4NmdY2EwRHrW1epXYqWa2YYz 22T8kkohfZBumZ5UA81ytJh5lnluU0TLBbjeF0GZh84TFKBuf03QQv7ta9mdTKZ3swmrY= X-Google-Smtp-Source: AGHT+IGk04wS6fiwL2wtMDFH/ztDpNqMqNc48Kz8v8UVM+7jXklUA4Va1pvciKOKJa64TPKDoZ1CLA== X-Received: by 2002:a05:600c:818f:b0:471:131f:85b7 with SMTP id 5b1f17b1804b1-47d7f076b6fmr41724875e9.15.1767718873182; Tue, 06 Jan 2026 09:01:13 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:12 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v11 09/24] libcamera: shaders: Add support for black level compensation Date: Tue, 6 Jan 2026 17:00:44 +0000 Message-ID: <20260106170059.56193-10-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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" Add the ability to apply a int blacklevel gain against the demosaiced data prior to application of colour correction data. Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue Reviewed-by: Kieran Bingham --- src/libcamera/shaders/bayer_1x_packed.frag | 3 +++ src/libcamera/shaders/bayer_unpacked.frag | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag index db8c2a0b3..7036fe278 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -66,6 +66,7 @@ uniform vec2 tex_bayer_first_red; uniform sampler2D tex_y; uniform mat3 ccm; +uniform vec3 blacklevel; void main(void) { @@ -213,6 +214,8 @@ void main(void) vec3(patterns.y, C, patterns.x) : vec3(patterns.wz, C)); + rgb = rgb - 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 06d80f3dd..f0d8cd1e2 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -25,6 +25,7 @@ varying vec4 center; varying vec4 yCoord; varying vec4 xCoord; uniform mat3 ccm; +uniform vec3 blacklevel; void main(void) { vec3 rgb; @@ -108,6 +109,8 @@ void main(void) { vec3(PATTERN.w, C, PATTERN.z) : vec3(PATTERN.yx, C)); + rgb = rgb - blacklevel; + /* * CCM is a 3x3 in the format * From patchwork Tue Jan 6 17:00:45 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25663 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 BE0A7BDCC0 for ; Tue, 6 Jan 2026 17:01:20 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5E5B962019; Tue, 6 Jan 2026 18:01:20 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="FNKauIS/"; dkim-atps=neutral Received: from mail-wr1-x42b.google.com (mail-wr1-x42b.google.com [IPv6:2a00:1450:4864:20::42b]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9AC6A6200C for ; Tue, 6 Jan 2026 18:01:15 +0100 (CET) Received: by mail-wr1-x42b.google.com with SMTP id ffacd0b85a97d-42e2ba54a6fso452688f8f.3 for ; Tue, 06 Jan 2026 09:01:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718875; x=1768323675; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ZRuITSMve+FWc8iDUneEG5zb0QDixsRjAIi5XBQ3RYM=; b=FNKauIS/0dsSJ14v1qXPu6hy/xqD5CDby92U9OEV5hjxK+fm8iCrpp143ubGRhDN1+ G1iU770ii5gWvC+Fwr/YVhUb9CIB7v99wJjwU3rwRPH3v8tukuDFW4Qn0WkFNzaacUkw OvTJDdat6jtitPTf7h+srb2NKsqhjRzcdibOcqZmGK2iPG+pX9i/ZHG3MasZG2r9Sbh/ 7Tp2EBjPrYkBtu9/gcK/NOQJpFrOomCKGiyiLcNQcxWc9afx9jeCPhiZ5wUreyllmhHa aZqIpsZWAg5qeGWrBeZR7PzDszffpmyMlPU8PYGFw8Eh8WiXSCR2X1TRIJMASCmOw5Uj inaQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718875; x=1768323675; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=ZRuITSMve+FWc8iDUneEG5zb0QDixsRjAIi5XBQ3RYM=; b=NTrMgg3I4Ff2FKvxKEKlD3iMXndt7Akowa0adO6niobRqYePlxncMcS1qxfWwy3hMp 4gTg+JB0ZT1YVBXNEI0icfkzxjbWKgixo5Pr6kS9kfRcbOorM65U4dbYwzBAlgEAhK6A Tb4cbFaeSYLJrw7CVpK3a8hVRPfjn75QrEFHT36VJ4ifUK8ZY6OF+4n8/QBXBkEMVlcj 3agJlX4ruwm3cB6yJL9KPWi07MYm4yCCnfR8QcLHSly12s3YAY2loVT0T8pwC23wBmP1 7tCbB+4i6QmU8MS66dbeFlI7ZRMGKrmH1jNn8NU9V1GH8CpHxLSrofo0ePI2yZvl0iDK /Vzg== X-Gm-Message-State: AOJu0YyZ8cKqjJvLbaIWcfWEw+KW6RMdhEy03ISlHuWdD2ll5002rxMP gpqm74fhLG6CcSJRci1UbE8MDk4eggXKvhTOvzIQuTo/LE6shYyQlX8g+vOARFFSsD9+9s7fpVJ 2cTYCjL0= X-Gm-Gg: AY/fxX4jSE7ttjnDFSD08Si6+fK0Yvm6X8OC4ZWfEDiZCYhpbiHGjUuqHewC+LhLv7Q yeuni1gP8M7cnlTY08JsEkNrpiij3klzzBSieDs3gqfZR8rFPP7NiXL0mX/5FnAapZpu39/twEL S5waAv9tCt+nPqboVPmzribMkzQq/thWI7at72SJmoS3vNFR0Gdfa39WpNnmLYBL4ApHDUTEZAn wWcApTiS5ETdbkmyMTv1cKwfeu7RerxkpHmopuMhBlUl6BUQZ0oW8E5hjj7PQVYvlQr9YETOnpx QhkZ+SJjNuebGhThmS5TFIZdvSTJAxcrlOVL16MXfyD4EaDWr/4gacTgOnhU6WhLu6f1hPCE02a LQ7lCvhl75sevqvrYzzkwB6kvrGshc25Hc6URd16ke9tgvtpTaObzB6uCWStfXZF6SZQ75WwaMM 2iunfZNM/1RwGnKDDfCgBw+fjzm9K/m3tXExmRFSkgIWQCkaHofr8hswD9Sya2Om5buwQ= X-Google-Smtp-Source: AGHT+IHjztrKp6NRVqwM91T18D8N7dDx7S3P1yh7Osny7IqH5lH71GasDNyTKcn2cFJMkDzvNtqL0Q== X-Received: by 2002:a05:6000:4014:b0:431:a0:7de0 with SMTP id ffacd0b85a97d-432bca4867cmr4894735f8f.35.1767718874737; Tue, 06 Jan 2026 09:01:14 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:14 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v11 10/24] libcamera: shaders: Add support for Gamma Date: Tue, 6 Jan 2026 17:00:45 +0000 Message-ID: <20260106170059.56193-11-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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" Add gamma compensation to the debayer shaders after colour correction is applied. Similarly only apply the calculated Gamma curve when using the CCM as the lookup tables already contain the data. Suggested-by: Milan Zamazal Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/libcamera/shaders/bayer_1x_packed.frag | 4 ++++ src/libcamera/shaders/bayer_unpacked.frag | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag index 7036fe278..77d9fbfa7 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -67,6 +67,7 @@ uniform vec2 tex_bayer_first_red; uniform sampler2D tex_y; uniform mat3 ccm; uniform vec3 blacklevel; +uniform float gamma; void main(void) { @@ -260,6 +261,9 @@ void main(void) rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + /* Apply gamma after colour correction */ + rgb = pow(rgb, vec3(gamma)); + #if defined (SWAP_BLUE) gl_FragColor = vec4(rgb.bgr, 1.0); #else diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag index f0d8cd1e2..aba11a87f 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -26,6 +26,7 @@ varying vec4 yCoord; varying vec4 xCoord; uniform mat3 ccm; uniform vec3 blacklevel; +uniform float gamma; void main(void) { vec3 rgb; @@ -155,6 +156,9 @@ void main(void) { rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + /* Apply gamma after colour correction */ + rgb = pow(rgb, vec3(gamma)); + #if defined (SWAP_BLUE) gl_FragColor = vec4(rgb.bgr, 1.0); #else From patchwork Tue Jan 6 17:00:46 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25664 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 51842C3213 for ; Tue, 6 Jan 2026 17:01:21 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 19C606200C; Tue, 6 Jan 2026 18:01:21 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="KiaeBcaV"; dkim-atps=neutral Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A77CC61FF4 for ; Tue, 6 Jan 2026 18:01:16 +0100 (CET) Received: by mail-wr1-x434.google.com with SMTP id ffacd0b85a97d-42fbc305552so816362f8f.0 for ; Tue, 06 Jan 2026 09:01:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718876; x=1768323676; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=x/vTDR1Id8mqE5zdziJRdnnrmiapjAEMf9XvNPsLCKY=; b=KiaeBcaVsPxNDfZdZEg/rCPj6gmDYENJTWEH2o7D8Z5XnahcHemsa1L8Cq5Ppphzde YvfKycAdbVQUi7cZW7rXY3Vh6vfjKX6bEaZu6jfJTJPVtOFcrHGGkAnH+VUmY7EgqM9d ivwkX02XSqFoW1j0VUTUmMF2SvCzQXS2BuvuqZZQsC/oCCPkLejGVXfzCGizpKs+GIJp YNkSCr6wr67EM6UwfR7plgRvpsrO9JJ9ce20rM3u9LP4DznDVaZZdejiFU3oJd6Atm9p VcJcSlaYjGSAkMXN55TTAQ80Uj+WdD8xWc0xU+SMC2O8qbck5UlZhHW/UPnuLadMgayd LTKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718876; x=1768323676; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=x/vTDR1Id8mqE5zdziJRdnnrmiapjAEMf9XvNPsLCKY=; b=kkS3/bA9Z1yQn5wvpw6Tcejz0/YD5FptvaXcGCD6y9z39t1+meiZr3dtWvgoaosW1R acUv1XH07aqI+esfnW5smHTcxcGKwgvjty52ohLVIfl+DUNT5KOqiTliobaNkrNv153t ixQYCfcF+fSjOyOBOcn8EZOWn77hoT0zuN0+aM1hgE0VZbA30rBpcT/3BBc/eOshPaEq MVIfqtiPoXl/tJw/zxoZD8bfEzwOBaZMTsE8iE1XFj14hqFG+l7P+HiLlUtopwTNA+cF gYemRtZOZtwiN43jPBWH0h/0EfBKjXux6NaLDwduX4mheuwbejJryd/I/DUgmkkpv0fe is1A== X-Gm-Message-State: AOJu0YysIIvyXp6/FeX3TPGSgYgrsbsiMaxmRqWwyvDLDZyA6JjW2DEQ 6eCkhSgclsrKqmEPY3vn7AXYoPdr33uVCEGoHiJ7Q1KmLygIGa0w1xmnLv0jxQxZFGlBJNZiC8C hCxl7yhI= X-Gm-Gg: AY/fxX7FtN+EedTmS51w8bEsOfmPMLFzLmrqdLX0jY+ifj3tF9wuP1A546uDXwoH028 o1QM5h11gHHkDrhMqvPrwWqpxqXupJZ7P5PAmkrH6H/i3ekoTwJDsASoMPQ7pQ75igtqktQccWB Q1Ny3V4Pnh5lzmQC+RqRU5XUGS63eOLQ0/Rvw3NXqfrqgzSeKNfl9MoHtYH0T48NTrT3UkBjRSr LUNh6GT5RLRQM+IPlKuV0OhIKtlZ6GK8DoM12LJIh+rNF3IjgYgBKi7B+7fRd3HjKNgmp7jRjBr gnDNe0EEzyRMzKhsmwGs8HRiSRNIch5W4cJHyPXUcw8y0GxyZ70qeTGIcdv6G2wHDWLenji3W9Z XvwIbujUAfwFOyneeckhrPCVlX25A5Q3vvxYshQSp7EDUrJqGhgqm0RvV1kIyWXrFS+vYh726fD BjbL+HI2wWoUTAB2aOwg/5hOyxwo4ybSUzv1c8QbpNxSfnaEHgEUEzp6j5SgjnvN29QvE= X-Google-Smtp-Source: AGHT+IH5psgNQ1Q2PXksIOut5FJSMKzpTAdyvJItUlBfbrks7UyevVqPrdO0Tz7CoGVTyLZhEl9ilQ== X-Received: by 2002:a05:6000:2504:b0:430:f742:fbb2 with SMTP id ffacd0b85a97d-432bc9d0bcdmr4626777f8f.19.1767718875854; Tue, 06 Jan 2026 09:01:15 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:15 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v11 11/24] libcamera: shaders: Add support for contrast Date: Tue, 6 Jan 2026 17:00:46 +0000 Message-ID: <20260106170059.56193-12-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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" Apply contrast after black-level and CCM operations. Suggested-by: Milan Zamazal Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/libcamera/shaders/bayer_1x_packed.frag | 19 +++++++++++++++++++ src/libcamera/shaders/bayer_unpacked.frag | 18 ++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag index 77d9fbfa7..23747f78a 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -68,6 +68,16 @@ uniform sampler2D tex_y; uniform mat3 ccm; uniform vec3 blacklevel; uniform float gamma; +uniform float contrastExp; + +float apply_contrast(float value) +{ + // Apply simple S-curve + if (value < 0.5) + return 0.5 * pow(value / 0.5, contrastExp); + else + return 1.0 - 0.5 * pow((1.0 - value) / 0.5, contrastExp); +} void main(void) { @@ -261,6 +271,15 @@ void main(void) rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + /* + * Contrast + * contrastExp 0..2 contrast to 0..infinity; avoid actual infinity at tan(pi/2) + */ + rgb = clamp(rgb, 0.0, 1.0); + rgb.r = apply_contrast(rgb.r); + rgb.g = apply_contrast(rgb.g); + rgb.b = apply_contrast(rgb.b); + /* Apply gamma after colour correction */ rgb = pow(rgb, vec3(gamma)); diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag index aba11a87f..af4a30c4b 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -27,6 +27,16 @@ varying vec4 xCoord; uniform mat3 ccm; uniform vec3 blacklevel; uniform float gamma; +uniform float contrastExp; + +float apply_contrast(float value) +{ + // Apply simple S-curve + if (value < 0.5) + return 0.5 * pow(value / 0.5, contrastExp); + else + return 1.0 - 0.5 * pow((1.0 - value) / 0.5, contrastExp); +} void main(void) { vec3 rgb; @@ -156,6 +166,14 @@ void main(void) { rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + /* + * Contrast + */ + rgb = clamp(rgb, 0.0, 1.0); + rgb.r = apply_contrast(rgb.r); + rgb.g = apply_contrast(rgb.g); + rgb.b = apply_contrast(rgb.b); + /* Apply gamma after colour correction */ rgb = pow(rgb, vec3(gamma)); From patchwork Tue Jan 6 17:00:47 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25665 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 5284FBDCC0 for ; Tue, 6 Jan 2026 17:01:22 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CDE6062020; Tue, 6 Jan 2026 18:01:21 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="Cj6eSyyQ"; dkim-atps=neutral Received: from mail-wr1-x42b.google.com (mail-wr1-x42b.google.com [IPv6:2a00:1450:4864:20::42b]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 99D7962000 for ; Tue, 6 Jan 2026 18:01:19 +0100 (CET) Received: by mail-wr1-x42b.google.com with SMTP id ffacd0b85a97d-43246af170aso21178f8f.0 for ; Tue, 06 Jan 2026 09:01:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718879; x=1768323679; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=YOU8yzvJmLe2CYSAv2DGpWHlxVqrCoB7v5e5gKZ8hTI=; b=Cj6eSyyQTcA3G0N8aE1jc31EwvELltSe79uyDuTdj6/Q+lyWfCOIOpvguyCw1V5ThM E3amdzxhRXxxw3h3yJVVf+6awAtE7hnIb2UpjBzfUIdcMyoy3n1hT8gESsswz5QGPaVv pX+PZdoIs1mB1zveuVHKVLdzXQYZb8me7OrHV22fZP+tK7apGL4lLnZZVaRiECDyO7Y/ kyOfFWom5Yw4njDXUmbCb1vi9SjEPXguOgIX4ERKuMI5CpXOUTlM+ibow6eMlR6VyQ+z 8gajjbgwxDMP4gpSe8459jCyxkpIxmcQOtWVp9YahCAxP/6gyLcNIn2HXKgyJRpr9spP adNA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718879; x=1768323679; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=YOU8yzvJmLe2CYSAv2DGpWHlxVqrCoB7v5e5gKZ8hTI=; b=Gs3x0jP15SOjT0y5tvBx3ZY8psYs/LLBbj6Cc7lEM8sINkKBlVVLdmkP4ABp2abipD fLNBXMZVK+X7uNxYga39jquvJ1nVFau5Ubrz6fBpyE5OQ6HAjMcy6cDGwmcUiA6IgiK6 8sd9X9Zwk9GWowNhkhvxoHuhuXsgoXARVIsH+Q7x1KXm4k9hpK6DPpCHJDaGXgvK0S0z cmUqr5Cs/7KKoZ2NbSU4jZZ8/7+gh0ygNhbE3lRF6EdgjVhUkulN8LZm+KFhFUFwHhAS pXMWGEjJWo5gpx/KyO9yjCKxuDRmNG28IUQAzDFCyECOwSlWvZ3YU5uDvueNyUyrl/jf e6tA== X-Gm-Message-State: AOJu0Yzmvv/NC1UJIp+RI6I3UT3cXUuXAsQwpQ4beACb0G8S9irVetq7 /OxipWmEilThalX70eVEcyr3rLxIyGe7crsyOJPNeG/nPIwCRqRz5YbRn5OmhjSrBunxx1wIppV K+5w6RhQ= X-Gm-Gg: AY/fxX6CZSPfhusEr4pNA5qU3ME8e2/xhj5al0FGoBSDKAV5NE49C5EO2t+FMicFuN6 mks2DLYD1S9gt5z++eJt5e/yfeqHl1d6B3OMcWzx/vv5Fepu7AHQ5fhfJsaFTYfpntJZFrH2kTr kok/s1ywmGlqmk0pGJhjS1xe83loWAM3hjKJJI10WmE6KMNP47nQbRMxVvdIyX1OH327E53rc0u NsVVwJwzW4fTGQLUU6phbMkzwmj2jeqn1kQtyhnLd5XzdiM3mj6u3hVGZNm1tV6jwNdDHABiaMk VwBZcgZ7gv91bONSHDugZl3SXMFVjLuAX5+yCpLTBZeq6xuMZXAGNy7Nf/SZDxVBBFw4Q9lVrO3 5SfBA+KIixFBaF5/jq6GXdmGsu3HXqLoSZs3Wd7GMmPkgT3ZgcCG8ZIHdum1mKOeTcXoBn4dLIP qdxTY0SvsBZyzPpOxrIC4nYFJHR7mx+XjThvglj3I6P+tHI4Tg0Id2yhhEEZ+vXyrmGXHWVBKwk RqVLw== X-Google-Smtp-Source: AGHT+IFFSjBWSiPnPvuCiBStC+Y7T1LagObIdM5dxP3tcDUZA9r60pb4D8NTxBLaDnxWh9vsZV8tBA== X-Received: by 2002:a5d:5a4f:0:b0:430:f2ee:b21f with SMTP id ffacd0b85a97d-432bcfc4689mr3196825f8f.22.1767718877380; Tue, 06 Jan 2026 09:01:17 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:16 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Hans de Goede , Milan Zamazal , Bryan O'Donoghue Subject: [PATCH v11 12/24] libcamera: shaders: Fix input sampling when width != stride Date: Tue, 6 Jan 2026 17:00:47 +0000 Message-ID: <20260106170059.56193-13-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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: Hans de Goede When bayer_unpacked.vert is calculating the center and x/yCoord values stride != width is taken into account for x/yCoord deltas since it is taken into account by debayer_egl when setting the x part of tex_step uniform. But it is not taken into account for the center.x which is just directly copied from textureIn, leading to the input width sampling covering the entire input stride instead of just covering the input width. Use the existing and currently unused stride_factor uniform to pass the width/stride ratio and correct center.x for this. This fixes the misrendering seen on x86 laptops which is caused by the CSI2 receiver there requiring a stride which is a multiple of 32 often leading to stride != width. Signed-off-by: Hans de Goede Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/libcamera/shaders/bayer_unpacked.vert | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libcamera/shaders/bayer_unpacked.vert b/src/libcamera/shaders/bayer_unpacked.vert index fb5109eee..423dde0fa 100644 --- a/src/libcamera/shaders/bayer_unpacked.vert +++ b/src/libcamera/shaders/bayer_unpacked.vert @@ -21,7 +21,7 @@ attribute vec2 textureIn; uniform mat4 proj_matrix; -uniform vec2 tex_size; /* The texture size in pixels */ +uniform vec2 tex_size; /* The texture size in pixels */ uniform vec2 tex_step; /** Pixel position of the first red pixel in the */ @@ -40,8 +40,10 @@ varying vec4 xCoord; /** of the adjacent pixels.*/ varying vec4 yCoord; +uniform float stride_factor; + void main(void) { - center.xy = textureIn; + center.xy = vec2(textureIn.x * stride_factor, textureIn.y); center.zw = textureIn * tex_size + tex_bayer_first_red; xCoord = center.x + vec4(-2.0 * tex_step.x, From patchwork Tue Jan 6 17:00:48 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25666 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 130ACC3213 for ; Tue, 6 Jan 2026 17:01:23 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C4B0061FFC; Tue, 6 Jan 2026 18:01:22 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="pekLfVdO"; dkim-atps=neutral Received: from mail-wr1-x42b.google.com (mail-wr1-x42b.google.com [IPv6:2a00:1450:4864:20::42b]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C969762011 for ; Tue, 6 Jan 2026 18:01:19 +0100 (CET) Received: by mail-wr1-x42b.google.com with SMTP id ffacd0b85a97d-42b3d7c1321so696871f8f.3 for ; Tue, 06 Jan 2026 09:01:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718879; x=1768323679; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=qdq7BA4RV8ukinhniZlFu8ZUJ0DD8hbXSQeatSegKMQ=; b=pekLfVdOQuzhYRcpG5UUrscC3kzY2aOuymw7Pc3VG6u7/lQay8xo371puSyyY/2arG SiQqBJSL+KfhiIvbAC4Z3csoshNHledRs19Qi3qdNC2SawC3w1gypRuN1tQRGZljo00W Z8ejvp/tZ3jqHzDykS7GW3QSP1lLdjAsbwK/BP3YF84sAX1OP3MjgTjfmm00s/dsHNwE bqJyDGPo68t39VEHYXiV4eFeY3jh0zln5Db+WaIH6uDBnZBn6iIdT/s5Ard3I5bhxAPc QlLk+ppZe9zX//EVU52PLDEXypH2olIzUSG7MyR+jt/5xcIVrMRS1gqrDPl/X9khOFp8 EmEg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718879; x=1768323679; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=qdq7BA4RV8ukinhniZlFu8ZUJ0DD8hbXSQeatSegKMQ=; b=rbQ4j+0oRh86LklxwZYU0NZe/KeKnmVsohKHJa0r9kz7JvH1rcpSmMhh7V9Cs9+xPr /R6s2k/uzvupvnpYZvaQFyovt2gyHzl35n6d4hTHRG1MZEiEt7nZt6GCZdPf85m5un9O P7fqz65xk6KIfOiHG0nvhdU3i6br0lQCobdXAvxmXT/bsPRBvzhPmzA62XWmzGDxwI4R hsaqki8dLsm+U1IV6qeGUY0p4BZZMpJiligHY110uDY/TqQo0c8i8lXJYqywn+/OPA0h GFyZ9ieg19z734DmkqCZ9RB5od8hNfPU/2enEcZmq2ifJMP35YCz8jQKGJuGu4ixn7VC PA7w== X-Gm-Message-State: AOJu0Ywm3jo9mrPozi4KPK5PVZugL2XriDMixyg1+4yA1ec76mzpJ0rV 1Qcy6biOzose8ialXrFdHz51RurX2eQDf0goBDWEnGH2futf0wVUr0AkB0IZaDvQCvtoYrJUEKu u+/l3gw0= X-Gm-Gg: AY/fxX6ypdCZKW0TVpAsOM5zNM0LPC2IZSjhCR7Zqzuqj1u8Vg0sEVcUCajPqPUiWOt DJPltf2Ks48bzqMuGLa66WWM766BdvDbkyRbGlamSYjzG9/9dieKsCHFMpHW1CSoqOr11GAyoyM 4gtB1H98hjd6J5g+B06W1eRTYWRahR4M0hNgb8cbvwg0BF6WaZoXna3N/2LS4xDhmGNMeizAxCE OZ6ffj7E1Rq9K7c0ugIEdROsaZigi9WZaP10qgIDof+mBluq0C7MEy5isA7L1+S7uP+2r6ASbyo 8xqvE0TwPEMTzBXhsnQabzSM0F6MHsZ+vVHQU9/iMU4nf7gMQ/GdSUfYLVIiibAy8ioFEcWm4DE VNKjkgzksN+mcVLZ2Ahnv4Pl/0NZ76O1Nx4T2NQpsJROr8LVyo2ffa/0pjMAl//Ie/vaExSAvTk Udz8O1dL1IQUp1b3s2RjwpKUBZ3NqGeWLwn6MrwP4i1rONtiw8y4IGDCe+1svOHxoxMYg= X-Google-Smtp-Source: AGHT+IGsb7x3KJ1KzZdw69Mk5GTsI+BcFvtIjMYRFmhEq+SC4R5I0KZ8J2T5MKLy10MQ1Ch5JVMWfw== X-Received: by 2002:a05:6000:2584:b0:430:f1d3:fa2 with SMTP id ffacd0b85a97d-432bc9cbee7mr4479936f8f.7.1767718879002; Tue, 06 Jan 2026 09:01:19 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:18 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v11 13/24] libcamera: software_isp: Add member variables to track selected input/output pixelFormat Date: Tue, 6 Jan 2026 17:00:48 +0000 Message-ID: <20260106170059.56193-14-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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" In order to have Debayer::start() tell the eGL shader compilation routine what the input and output pixel format is, we need to have a copy of the selected format available. Add variables to the inputConfig and outputConfig structures to allow tracking of this data for later use. Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/debayer.cpp | 10 ++++++++++ src/libcamera/software_isp/debayer.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp index 4cb5b4da4..b948efad1 100644 --- a/src/libcamera/software_isp/debayer.cpp +++ b/src/libcamera/software_isp/debayer.cpp @@ -290,6 +290,16 @@ Debayer::~Debayer() * output image buffer. Set during stream configuration. */ +/** + * \var Debayer::inputPixelFormat_ + * \brief The incoming pixel format + */ + +/** + * \var Debayer::outputPixelFormat_ + * \brief The output pixel format + */ + /** * \var Debayer::red_ * \brief Lookup table for red channel gain and correction values diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h index b8287166e..d716ad080 100644 --- a/src/libcamera/software_isp/debayer.h +++ b/src/libcamera/software_isp/debayer.h @@ -75,6 +75,8 @@ public: DebayerInputConfig inputConfig_; DebayerOutputConfig outputConfig_; + PixelFormat inputPixelFormat_; + PixelFormat outputPixelFormat_; DebayerParams::LookupTable red_; DebayerParams::LookupTable green_; DebayerParams::LookupTable blue_; From patchwork Tue Jan 6 17:00:49 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25667 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 AE096BDCC0 for ; Tue, 6 Jan 2026 17:01:24 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6FECE6200B; Tue, 6 Jan 2026 18:01:24 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="JpPV6cae"; dkim-atps=neutral Received: from mail-wr1-x442.google.com (mail-wr1-x442.google.com [IPv6:2a00:1450:4864:20::442]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9D1FA62013 for ; Tue, 6 Jan 2026 18:01:21 +0100 (CET) Received: by mail-wr1-x442.google.com with SMTP id ffacd0b85a97d-42fbc544b09so784913f8f.1 for ; Tue, 06 Jan 2026 09:01:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718881; x=1768323681; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Kxm+TvuTYLZzzlNTLu4vqJH5eGTqBUQnuXrPXaS2+qk=; b=JpPV6caevL3PhluhDCO0X39HKcRYe/cDKAhI4vWb6gowWV5gwM8Zz3MrufQ9toWv9v WN9anzAQRixzaxJtkLmAFB8NJq9+sPQu/1vi14KCRo/X4o2VaqQaLbREfaDsyPaW/vsr rV8xSF5VC1RH1G1+NEkvy0cqaVop7Qxpz8n1GzT9u11TH+BSka8xVTkGTHbPvjpB5cDc yM1DAJesTqb6PJSt5/8SAZtuaVao7XkCPl0HwOorx3mpmySnNbW2tYCxyNd9UGZp7U6m UgCTMHyyK6XVhNaFDX0vPOFOL7UrWyu3TO/UceinsowzCgLdg4L33puA+xGfXJHulKWN 7Bww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718881; x=1768323681; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Kxm+TvuTYLZzzlNTLu4vqJH5eGTqBUQnuXrPXaS2+qk=; b=dJHcLD/rCVRRNTN9slzaODkepUg4eUuC/Cclw67R7OI9TtDZmO+BEhjxQx1Q9hv+im cwu+C6a0BxdBjcz9QB7JR5FaMN6CGKNsbQFDzIfrthYvq3lHAuHM//z2PQwXI9Cl+48m 8HRWZdp4YvNTGBA+xpwGgzwg/19v1o93GjDyI56Qe4Nu0Nc+4TXSRFGK86vCZwEhoSdl s2pGA1mSg4qDk2SUd0ClUvfZGOqfWfASJTrZ6t49IDaDcfrgF1//PJsw3BpwwW6uy2HJ lSWfwmdb6fHJUea2FBNKR02gzjtzkebjrjObo0Jg5Kl7txFgDQgfW80HHP8aCKXTQLcx NBfw== X-Gm-Message-State: AOJu0Yxz2hongP6ew2tPSED0qn8is2q6cIu6YuGm2qGb1tC5+SeMUpPI Z0t5eqRuqYj8deh7aKz/LmHd0QDe6TveoZIuqyJZmEvJTlf0u9bmaOd1zNAKK4CfHZrFXlHccbA kIDYISHWZMQ== X-Gm-Gg: AY/fxX7rDLEADmaFZGLqr5szWfpvMpiTOC6xsytUPN+pTNPFlYZSE288d81DNWKU5mt fvm56oR0Dr1umJifUqunGED06p92QJbmS0Ku/JkriB0qKCQYUAzfaAbGUSBEsct0yl6DS9LEX28 bJ+FdqIVnoJSED8WmxxQeA8idu/1E79c/Li2EveODXL3gzNsJ5g65ySj0Kw2NzfDJaMNAd1dqnF MEJlpupICWSi3T4J9vW33XvaNuK4wTpKI8GCk1fLwXgH5nxQIuMwRbOh19Vq1Nf+kk1sBdLvX/6 6RmcwYMvLNt9bfsqOvkinMuzlc82aGlKmcgPFMLg5406sjgznAeVgqq01/wzLyEsXAmQM4aSYTe h/J1+vVsWi9YQYKUVRmZVLVHF700w9HqZsyk/tbFe6NO9SiT/HAiM23MfhE/PPtwhpkZxM+R7ss hZ/4uYgmMJpEumLfAkkZMAAgkLqeqzog6igqfR0FrywWGVSbqMquhiTeIRAKOTEQhWZvw= X-Google-Smtp-Source: AGHT+IG3MmK9MccYgzy4ypT/GeRmlDLVcS/NK0Rr8CEP/z7HP5s+lXz08ifQX6gQf5EdHKuOii3hPg== X-Received: by 2002:a5d:5886:0:b0:431:35a:4a7d with SMTP id ffacd0b85a97d-432bca56856mr4701758f8f.58.1767718880415; Tue, 06 Jan 2026 09:01:20 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:20 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v11 14/24] libcamera: software_isp: Add a Size_ member variable to pass to eGL later Date: Tue, 6 Jan 2026 17:00:49 +0000 Message-ID: <20260106170059.56193-15-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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" We will be initialising eGL from Debayer::start(). We need a copy of the size data passed in configure() to tell the fragment shaders the right output size. Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/debayer.cpp | 5 +++++ src/libcamera/software_isp/debayer.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp index b948efad1..65a1762dd 100644 --- a/src/libcamera/software_isp/debayer.cpp +++ b/src/libcamera/software_isp/debayer.cpp @@ -300,6 +300,11 @@ Debayer::~Debayer() * \brief The output pixel format */ +/** + * \var Debayer::outputSize_ + * \brief Output size object + */ + /** * \var Debayer::red_ * \brief Lookup table for red channel gain and correction values diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h index d716ad080..cd2db9930 100644 --- a/src/libcamera/software_isp/debayer.h +++ b/src/libcamera/software_isp/debayer.h @@ -75,6 +75,7 @@ public: DebayerInputConfig inputConfig_; DebayerOutputConfig outputConfig_; + Size outputSize_; PixelFormat inputPixelFormat_; PixelFormat outputPixelFormat_; DebayerParams::LookupTable red_; From patchwork Tue Jan 6 17:00:50 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25669 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 D8567C3213 for ; Tue, 6 Jan 2026 17:01:26 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8269B62022; Tue, 6 Jan 2026 18:01:26 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="uff4Kujo"; dkim-atps=neutral Received: from mail-wr1-x443.google.com (mail-wr1-x443.google.com [IPv6:2a00:1450:4864:20::443]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6D15961FD8 for ; Tue, 6 Jan 2026 18:01:24 +0100 (CET) Received: by mail-wr1-x443.google.com with SMTP id ffacd0b85a97d-42e2d02a3c9so808222f8f.3 for ; Tue, 06 Jan 2026 09:01:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718884; x=1768323684; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=FlcsopdCqx0Vxy6Jo6h6qgZr9xc2hxHELOy7x3Ka3AA=; b=uff4Kujo176Gd4CYBAQ7UF88VERED2VtMYTg14Boq7g5IQ6NRCCgi7begry/lTa9SL 1e0LYw/AMGp0I0VteueArmLdiUQYJ5ue1KYUtdGdHD1dlqnZ9c8XfCd5rlrEYLjmcfSM rvfrGr+fckde8VcBtl0qLRcRPt1gZlFGtMPVUns6vgFkVXzcqZS0tzQvQRw0A8CBCSZj 96bGq0KuX+HUX5KL2AlVhSo3HaS9O43PfnTd2GXzAXxN8BisEK+JUWbT2IfNB3/XTdep 9k2TBRnkPAo2M84fYkOb7BO//anbKLukLHh2/tmn6OfogOmfowfguM7/kqTeFtc6mCpW BQ1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718884; x=1768323684; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=FlcsopdCqx0Vxy6Jo6h6qgZr9xc2hxHELOy7x3Ka3AA=; b=YhM1ND1wVUn4s5E1Mo4RtZ7y95rSsl4q+GaI6I09UjYCtSyv/hyGNbGm1jY3Gmiolh fmc4S89mw2h6aD90ZNoAmCMk3KEI0ro3pcGvKg27CIKf5KK2ZDHiITTk/1NRbxBhv7aZ 1e1Np+Ef23V3dRkMOTCpLJnneYjYUeIYpBH75YfbWZ0jQ3kPcZuFT/WOPSbkvzEMOGtt liXBqe7aD6TWEmmd0OxwB5FWtMB/WdPlCc1yHWexh09x6Vbc+YqY9566DDIpwwcEcchy tyaeHB/xXMqUMKNVC5dKdD54p7r0zQV++YwpKKq57yqk9qbAZactdkYS0eRU7i2IkzF8 kW+A== X-Gm-Message-State: AOJu0Ywk0e3nY1CFy7G2iGRtdCH2iqsdJk1eUio+Yu4VxSkLoVEKItZe 7BjoPL4jSs3pRwKIJLnWGEnM3qKiv+9ujPDo43pkoMX/HWo0ajpwqq7YojDEBXHxOv5V32J12N+ LCG7I6ge/wg== X-Gm-Gg: AY/fxX58vMte3gyeLivX8WZrn+sK7A+zAbPhnaPIC8yOTPuapDCep5DVwPiuytemi56 HAxxI308IZlAR8DylGz+WOCA0Yevi7j4EIvkUxSuwOyF2dbnYSOfH6eKLs7Y4UTC9/WvuStmS1e Vn/IeEJw1nRN58TOalnY0MwbzM0uWOC1kNIBRRp631keFZLt7P0MydJ/AShWYRQ/7jEI/UbJRWc 7mzEQCb6suyKvP1pYpnGOuKiEFFRTPUCPthppBNmX9MLvyBQbfzaskZb39mWTqr/MStuS2wu5/r zXpSIJYx/fVUnHjSgoGaDv8GprxplSbCS6Sl9V2SSuyFBW3vKgwrAg+0k+qvSA3Hjv498bVzHUL Tms5awC90Eqr1S74Xts4ItcMktb1dRWBYE9GtzThp/QiekHROBxKM+QoAXQHE+Qnt6NZQaTq1x+ a+tjLpnoBzRpub2GoeqnzoUJKoSZXWohYWyPWOiKhpU/0yCSr02i3Bb1gNnSdNOO340CU= X-Google-Smtp-Source: AGHT+IEg/eIbxWNvie5S1NjuEmS3bzJhS10nht8U8A59UE8VldKi7LLS4BvfebKAp8AZ78AMKt7wtg== X-Received: by 2002:a05:6000:2c0f:b0:42b:396e:2817 with SMTP id ffacd0b85a97d-432bc9f4634mr4944382f8f.40.1767718881965; Tue, 06 Jan 2026 09:01:21 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:21 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Robert Mader , Milan Zamazal Subject: [PATCH v11 15/24] libcamera: software_isp: debayer_egl: Add an eGL Debayer class Date: Tue, 6 Jan 2026 17:00:50 +0000 Message-ID: <20260106170059.56193-16-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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" Add a class to run the existing glsl debayer shaders on a GBM surface. Signed-off-by: Robert Mader Co-developed-by: Robert Mader [bod: took scaling and buffer size fixes from Robert] [bod: took fix for center byte calculation from Hans] [bod: took formatting fixes from Milan] Signed-off-by: Milan Zamazal Co-developed-by: Milan Zamazal Reviewed-by: Robert Mader Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/debayer_egl.cpp | 651 +++++++++++++++++++++ src/libcamera/software_isp/debayer_egl.h | 124 ++++ src/libcamera/software_isp/meson.build | 8 + 3 files changed, 783 insertions(+) create mode 100644 src/libcamera/software_isp/debayer_egl.cpp create mode 100644 src/libcamera/software_isp/debayer_egl.h diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp new file mode 100644 index 000000000..8e0890323 --- /dev/null +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -0,0 +1,651 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Linaro Ltd. + * + * Authors: + * Bryan O'Donoghue + * + */ + +#include "debayer_egl.h" + +#include +#include +#include + +#include + +#include + +#include "../glsl_shaders.h" + +namespace libcamera { + +/** + * \class DebayerEGL + * \brief Class for debayering using an EGL Shader + * + * Implements an EGL shader based debayering solution. + */ + +/** + * \fn DebayerEGL::DebayerEGL(std::unique_ptr stats, const GlobalConfiguration &configuration) + * \brief Construct a DebayerEGL object + * \param[in] stats Statistics processing object + * \param[in] configuration Global configuration reference + */ +DebayerEGL::DebayerEGL(std::unique_ptr stats, const GlobalConfiguration &configuration) + : Debayer(configuration), stats_(std::move(stats)) +{ +} + +DebayerEGL::~DebayerEGL() +{ +} + +int DebayerEGL::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config) +{ + BayerFormat bayerFormat = + BayerFormat::fromPixelFormat(inputFormat); + + if ((bayerFormat.bitDepth == 8 || bayerFormat.bitDepth == 10) && + bayerFormat.packing == BayerFormat::Packing::None && + isStandardBayerOrder(bayerFormat.order)) { + config.bpp = (bayerFormat.bitDepth + 7) & ~7; + config.patternSize.width = 2; + config.patternSize.height = 2; + config.outputFormats = std::vector({ formats::XRGB8888, + formats::ARGB8888, + formats::XBGR8888, + formats::ABGR8888 }); + return 0; + } + + if (bayerFormat.bitDepth == 10 && + bayerFormat.packing == BayerFormat::Packing::CSI2 && + isStandardBayerOrder(bayerFormat.order)) { + config.bpp = 10; + config.patternSize.width = 4; /* 5 bytes per *4* pixels */ + config.patternSize.height = 2; + config.outputFormats = std::vector({ formats::XRGB8888, + formats::ARGB8888, + formats::XBGR8888, + formats::ABGR8888 }); + return 0; + } + + LOG(Debayer, Error) + << "Unsupported input format " << inputFormat; + + return -EINVAL; +} + +int DebayerEGL::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config) +{ + if (outputFormat == formats::XRGB8888 || outputFormat == formats::ARGB8888 || + outputFormat == formats::XBGR8888 || outputFormat == formats::ABGR8888) { + config.bpp = 32; + return 0; + } + + LOG(Debayer, Error) + << "Unsupported output format " << outputFormat; + + return -EINVAL; +} + +int DebayerEGL::getShaderVariableLocations(void) +{ + attributeVertex_ = glGetAttribLocation(programId_, "vertexIn"); + attributeTexture_ = glGetAttribLocation(programId_, "textureIn"); + + textureUniformBayerDataIn_ = glGetUniformLocation(programId_, "tex_y"); + ccmUniformDataIn_ = glGetUniformLocation(programId_, "ccm"); + blackLevelUniformDataIn_ = glGetUniformLocation(programId_, "blacklevel"); + gammaUniformDataIn_ = glGetUniformLocation(programId_, "gamma"); + contrastExpUniformDataIn_ = glGetUniformLocation(programId_, "contrastExp"); + + textureUniformStep_ = glGetUniformLocation(programId_, "tex_step"); + textureUniformSize_ = glGetUniformLocation(programId_, "tex_size"); + textureUniformStrideFactor_ = glGetUniformLocation(programId_, "stride_factor"); + textureUniformBayerFirstRed_ = glGetUniformLocation(programId_, "tex_bayer_first_red"); + textureUniformProjMatrix_ = glGetUniformLocation(programId_, "proj_matrix"); + + LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ + << " tex_y " << textureUniformBayerDataIn_ + << " ccm " << ccmUniformDataIn_ + << " blacklevel " << blackLevelUniformDataIn_ + << " gamma " << gammaUniformDataIn_ + << " contrastExp " << contrastExpUniformDataIn_ + << " tex_step " << textureUniformStep_ + << " tex_size " << textureUniformSize_ + << " stride_factor " << textureUniformStrideFactor_ + << " tex_bayer_first_red " << textureUniformBayerFirstRed_ + << " proj_matrix " << textureUniformProjMatrix_; + return 0; +} + +int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputFormat) +{ + std::vector shaderEnv; + unsigned int fragmentShaderDataLen = 0; + const unsigned char *fragmentShaderData = 0; + unsigned int vertexShaderDataLen = 0; + const unsigned char *vertexShaderData = 0; + GLenum err; + + /* Target gles 100 glsl requires "#version x" as first directive in shader */ + egl_.pushEnv(shaderEnv, "#version 100"); + + /* Specify GL_OES_EGL_image_external */ + egl_.pushEnv(shaderEnv, "#extension GL_OES_EGL_image_external: enable"); + + /* + * Tell shaders how to re-order output taking account of how the + * pixels are actually stored by GBM + */ + switch (outputFormat) { + case formats::ARGB8888: + case formats::XRGB8888: + break; + case formats::ABGR8888: + case formats::XBGR8888: + egl_.pushEnv(shaderEnv, "#define SWAP_BLUE"); + break; + default: + LOG(Debayer, Error) << "Unsupported output format"; + return -EINVAL; + } + + /* Pixel location parameters */ + glFormat_ = GL_LUMINANCE; + bytesPerPixel_ = 1; + shaderStridePixels_ = inputConfig_.stride; + + switch (inputFormat) { + case libcamera::formats::SBGGR8: + case libcamera::formats::SBGGR10_CSI2P: + case libcamera::formats::SBGGR12_CSI2P: + firstRed_x_ = 1.0; + firstRed_y_ = 1.0; + break; + case libcamera::formats::SGBRG8: + case libcamera::formats::SGBRG10_CSI2P: + case libcamera::formats::SGBRG12_CSI2P: + firstRed_x_ = 0.0; + firstRed_y_ = 1.0; + break; + case libcamera::formats::SGRBG8: + case libcamera::formats::SGRBG10_CSI2P: + case libcamera::formats::SGRBG12_CSI2P: + firstRed_x_ = 1.0; + firstRed_y_ = 0.0; + break; + case libcamera::formats::SRGGB8: + case libcamera::formats::SRGGB10_CSI2P: + case libcamera::formats::SRGGB12_CSI2P: + firstRed_x_ = 0.0; + firstRed_y_ = 0.0; + break; + default: + LOG(Debayer, Error) << "Unsupported input format"; + return -EINVAL; + }; + + /* Shader selection */ + switch (inputFormat) { + case libcamera::formats::SBGGR8: + case libcamera::formats::SGBRG8: + case libcamera::formats::SGRBG8: + case libcamera::formats::SRGGB8: + fragmentShaderData = bayer_unpacked_frag; + fragmentShaderDataLen = bayer_unpacked_frag_len; + vertexShaderData = bayer_unpacked_vert; + vertexShaderDataLen = bayer_unpacked_vert_len; + break; + case libcamera::formats::SBGGR10_CSI2P: + case libcamera::formats::SGBRG10_CSI2P: + case libcamera::formats::SGRBG10_CSI2P: + case libcamera::formats::SRGGB10_CSI2P: + egl_.pushEnv(shaderEnv, "#define RAW10P"); + if (BayerFormat::fromPixelFormat(inputFormat).packing == BayerFormat::Packing::None) { + fragmentShaderData = bayer_unpacked_frag; + fragmentShaderDataLen = bayer_unpacked_frag_len; + vertexShaderData = bayer_unpacked_vert; + vertexShaderDataLen = bayer_unpacked_vert_len; + glFormat_ = GL_RG; + bytesPerPixel_ = 2; + } else { + fragmentShaderData = bayer_1x_packed_frag; + fragmentShaderDataLen = bayer_1x_packed_frag_len; + vertexShaderData = identity_vert; + vertexShaderDataLen = identity_vert_len; + shaderStridePixels_ = width_; + } + break; + case libcamera::formats::SBGGR12_CSI2P: + case libcamera::formats::SGBRG12_CSI2P: + case libcamera::formats::SGRBG12_CSI2P: + case libcamera::formats::SRGGB12_CSI2P: + egl_.pushEnv(shaderEnv, "#define RAW12P"); + if (BayerFormat::fromPixelFormat(inputFormat).packing == BayerFormat::Packing::None) { + fragmentShaderData = bayer_unpacked_frag; + fragmentShaderDataLen = bayer_unpacked_frag_len; + vertexShaderData = bayer_unpacked_vert; + vertexShaderDataLen = bayer_unpacked_vert_len; + glFormat_ = GL_RG; + bytesPerPixel_ = 2; + } else { + fragmentShaderData = bayer_1x_packed_frag; + fragmentShaderDataLen = bayer_1x_packed_frag_len; + vertexShaderData = identity_vert; + vertexShaderDataLen = identity_vert_len; + shaderStridePixels_ = width_; + } + break; + }; + + if (egl_.compileVertexShader(vertexShaderId_, vertexShaderData, vertexShaderDataLen, shaderEnv)) { + LOG(Debayer, Error) << "Compile vertex shader fail"; + return -ENODEV; + } + utils::scope_exit vShaderGuard([&] { glDeleteShader(vertexShaderId_); }); + + if (egl_.compileFragmentShader(fragmentShaderId_, fragmentShaderData, fragmentShaderDataLen, shaderEnv)) { + LOG(Debayer, Error) << "Compile fragment shader fail"; + return -ENODEV; + } + utils::scope_exit fShaderGuard([&] { glDeleteShader(fragmentShaderId_); }); + + if (egl_.linkProgram(programId_, vertexShaderId_, fragmentShaderId_)) { + LOG(Debayer, Error) << "Linking program fail"; + return -ENODEV; + } + + egl_.dumpShaderSource(vertexShaderId_); + egl_.dumpShaderSource(fragmentShaderId_); + + /* Ensure we set the programId_ */ + egl_.useProgram(programId_); + err = glGetError(); + if (err != GL_NO_ERROR) { + LOG(Debayer, Error) << "Use program error " << err; + return -ENODEV; + } + + return getShaderVariableLocations(); +} + +/** + * \brief Get the output frame size + * + * \return The output frame size + */ +unsigned int DebayerEGL::frameSize() +{ + return outputConfig_.frameSize; +} + +int DebayerEGL::configure(const StreamConfiguration &inputCfg, + const std::vector> &outputCfgs, + bool ccmEnabled) +{ + if (getInputConfig(inputCfg.pixelFormat, inputConfig_) != 0) + return -EINVAL; + + if (stats_->configure(inputCfg) != 0) + return -EINVAL; + + if (!ccmEnabled) + return -EINVAL; + + const Size &stats_pattern_size = stats_->patternSize(); + if (inputConfig_.patternSize.width != stats_pattern_size.width || + inputConfig_.patternSize.height != stats_pattern_size.height) { + LOG(Debayer, Error) + << "mismatching stats and debayer pattern sizes for " + << inputCfg.pixelFormat; + return -EINVAL; + } + + inputConfig_.stride = inputCfg.stride; + inputPixelFormat_ = inputCfg.pixelFormat; + width_ = inputCfg.size.width; + height_ = inputCfg.size.height; + + if (outputCfgs.size() != 1) { + LOG(Debayer, Error) + << "Unsupported number of output streams: " + << outputCfgs.size(); + return -EINVAL; + } + + StreamConfiguration &outputCfg = outputCfgs[0]; + SizeRange outSizeRange = sizes(inputCfg.pixelFormat, inputCfg.size); + std::tie(outputConfig_.stride, outputConfig_.frameSize) = + strideAndFrameSize(outputCfg.pixelFormat, outputCfg.size); + + if (!outSizeRange.contains(outputCfg.size) || outputConfig_.stride != outputCfg.stride) { + LOG(Debayer, Error) + << "Invalid output size/stride: " + << "\n " << outputCfg.size << " (" << outSizeRange << ")" + << "\n " << outputCfg.stride << " (" << outputConfig_.stride << ")"; + return -EINVAL; + } + + outputPixelFormat_ = outputCfg.pixelFormat; + outputSize_ = outputCfg.size; + + window_.x = ((inputCfg.size.width - outputCfg.size.width) / 2) & + ~(inputConfig_.patternSize.width - 1); + window_.y = ((inputCfg.size.height - outputCfg.size.height) / 2) & + ~(inputConfig_.patternSize.height - 1); + window_.width = outputCfg.size.width; + window_.height = outputCfg.size.height; + + /* + * Don't pass x,y from window_ since process() already adjusts for it. + * But crop the window to 2/3 of its width and height for speedup. + */ + stats_->setWindow(Rectangle(window_.size())); + + return 0; +} + +Size DebayerEGL::patternSize(PixelFormat inputFormat) +{ + DebayerEGL::DebayerInputConfig config; + + if (getInputConfig(inputFormat, config) != 0) + return {}; + + return config.patternSize; +} + +std::vector DebayerEGL::formats(PixelFormat inputFormat) +{ + DebayerEGL::DebayerInputConfig config; + + if (getInputConfig(inputFormat, config) != 0) + return std::vector(); + + return config.outputFormats; +} + +std::tuple +DebayerEGL::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) +{ + DebayerEGL::DebayerOutputConfig config; + + if (getOutputConfig(outputFormat, config) != 0) + return std::make_tuple(0, 0); + + /* Align stride to 256 bytes as a generic GPU memory access alignment */ + unsigned int stride = libcamera::utils::alignUp(size.width * config.bpp / 8, 256); + + return std::make_tuple(stride, stride * size.height); +} + +void DebayerEGL::setShaderVariableValues(DebayerParams ¶ms) +{ + /* + * Raw Bayer 8-bit, and packed raw Bayer 10-bit/12-bit formats + * are stored in a GL_LUMINANCE texture. The texture width is + * equal to the stride. + */ + GLfloat firstRed[] = { firstRed_x_, firstRed_y_ }; + GLfloat imgSize[] = { (GLfloat)width_, + (GLfloat)height_ }; + GLfloat Step[] = { static_cast(bytesPerPixel_) / (inputConfig_.stride - 1), + 1.0f / (height_ - 1) }; + GLfloat Stride = (GLfloat)width_ / (shaderStridePixels_ / bytesPerPixel_); + /* + * Scale input to output size, keeping the aspect ratio and preferring + * cropping over black bars. + */ + GLfloat scale = std::max((GLfloat)window_.width / width_, + (GLfloat)window_.height / height_); + GLfloat trans = -(1.0f - scale); + GLfloat projMatrix[] = { + scale, 0, 0, 0, + 0, scale, 0, 0, + 0, 0, 1, 0, + trans, trans, 0, 1 + }; + /* Static const coordinates */ + static const GLfloat vcoordinates[4][2] = { + { -1.0f, -1.0f }, + { -1.0f, +1.0f }, + { +1.0f, +1.0f }, + { +1.0f, -1.0f }, + }; + static const GLfloat tcoordinates[4][2] = { + { 0.0f, 0.0f }, + { 0.0f, 1.0f }, + { 1.0f, 1.0f }, + { 1.0f, 0.0f }, + }; + + /* vertexIn - bayer_8.vert */ + glEnableVertexAttribArray(attributeVertex_); + glVertexAttribPointer(attributeVertex_, 2, GL_FLOAT, GL_TRUE, + 2 * sizeof(GLfloat), vcoordinates); + + /* textureIn - bayer_8.vert */ + glEnableVertexAttribArray(attributeTexture_); + glVertexAttribPointer(attributeTexture_, 2, GL_FLOAT, GL_TRUE, + 2 * sizeof(GLfloat), tcoordinates); + + /* + * Set the sampler2D to the respective texture unit for each texutre + * To simultaneously sample multiple textures we need to use multiple + * texture units + */ + glUniform1i(textureUniformBayerDataIn_, eglImageBayerIn_->texture_unit_uniform_id_); + + /* + * These values are: + * firstRed = tex_bayer_first_red - bayer_8.vert + * imgSize = tex_size - bayer_8.vert + * step = tex_step - bayer_8.vert + * Stride = stride_factor identity.vert + * textureUniformProjMatri = No scaling + */ + glUniform2fv(textureUniformBayerFirstRed_, 1, firstRed); + glUniform2fv(textureUniformSize_, 1, imgSize); + glUniform2fv(textureUniformStep_, 1, Step); + glUniform1f(textureUniformStrideFactor_, Stride); + glUniformMatrix4fv(textureUniformProjMatrix_, 1, GL_FALSE, projMatrix); + + LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ + << " tex_y " << textureUniformBayerDataIn_ + << " tex_step " << textureUniformStep_ + << " tex_size " << textureUniformSize_ + << " stride_factor " << textureUniformStrideFactor_ + << " tex_bayer_first_red " << textureUniformBayerFirstRed_; + + LOG(Debayer, Debug) << "textureUniformY_ = 0 " + << " firstRed.x " << firstRed[0] + << " firstRed.y " << firstRed[1] + << " textureUniformSize_.width " << imgSize[0] + << " textureUniformSize_.height " << imgSize[1] + << " textureUniformStep_.x " << Step[0] + << " textureUniformStep_.y " << Step[1] + << " textureUniformStrideFactor_ " << Stride + << " textureUniformProjMatrix_ " << textureUniformProjMatrix_; + + GLfloat ccm[9] = { + params.ccm[0][0], + params.ccm[0][1], + params.ccm[0][2], + params.ccm[1][0], + params.ccm[1][1], + params.ccm[1][2], + params.ccm[2][0], + params.ccm[2][1], + params.ccm[2][2], + }; + glUniformMatrix3fv(ccmUniformDataIn_, 1, GL_FALSE, ccm); + LOG(Debayer, Debug) << " ccmUniformDataIn_ " << ccmUniformDataIn_ << " data " << params.ccm; + + /* + * 0 = Red, 1 = Green, 2 = Blue + */ + glUniform3f(blackLevelUniformDataIn_, params.blackLevel[0], params.blackLevel[1], params.blackLevel[2]); + LOG(Debayer, Debug) << " blackLevelUniformDataIn_ " << blackLevelUniformDataIn_ << " data " << params.blackLevel; + + /* + * Gamma + */ + glUniform1f(gammaUniformDataIn_, params.gamma); + LOG(Debayer, Debug) << " gammaUniformDataIn_ " << gammaUniformDataIn_ << " data " << params.gamma; + + /* + * Contrast + */ + glUniform1f(contrastExpUniformDataIn_, params.contrastExp); + LOG(Debayer, Debug) << " contrastExpUniformDataIn_ " << contrastExpUniformDataIn_ << " data " << params.contrastExp; + + return; +} + +int DebayerEGL::debayerGPU(MappedFrameBuffer &in, int out_fd, DebayerParams ¶ms) +{ + /* eGL context switch */ + egl_.makeCurrent(); + + /* Create a standard texture input */ + egl_.createTexture2D(*eglImageBayerIn_, glFormat_, inputConfig_.stride / bytesPerPixel_, height_, in.planes()[0].data()); + + /* Generate the output render framebuffer as render to texture */ + egl_.createOutputDMABufTexture2D(*eglImageBayerOut_, out_fd); + + setShaderVariableValues(params); + glViewport(0, 0, width_, height_); + glClear(GL_COLOR_BUFFER_BIT); + glDrawArrays(GL_TRIANGLE_FAN, 0, DEBAYER_OPENGL_COORDS); + + GLenum err = glGetError(); + if (err != GL_NO_ERROR) { + LOG(eGL, Error) << "Drawing scene fail " << err; + return -ENODEV; + } else { + egl_.syncOutput(); + } + + return 0; +} + +void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, DebayerParams params) +{ + bench_.startFrame(); + + std::vector dmaSyncers; + + dmaSyncBegin(dmaSyncers, input, nullptr); + + setParams(params); + + /* Copy metadata from the input buffer */ + FrameMetadata &metadata = output->_d()->metadata(); + metadata.status = input->metadata().status; + metadata.sequence = input->metadata().sequence; + metadata.timestamp = input->metadata().timestamp; + + MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read); + if (!in.isValid()) { + LOG(Debayer, Error) << "mmap-ing buffer(s) failed"; + goto error; + } + + if (debayerGPU(in, output->planes()[0].fd.get(), params)) { + LOG(Debayer, Error) << "debayerGPU failed"; + goto error; + } + + bench_.finishFrame(); + + metadata.planes()[0].bytesused = output->planes()[0].length; + + /* Calculate stats for the whole frame */ + stats_->processFrame(frame, 0, input); + dmaSyncers.clear(); + + outputBufferReady.emit(output); + inputBufferReady.emit(input); + + return; + +error: + bench_.finishFrame(); + metadata.status = FrameMetadata::FrameError; + return; +} + +int DebayerEGL::start() +{ + GLint maxTextureImageUnits; + + if (gbmSurface_.createDevice()) + return -ENODEV; + + if (egl_.initEGLContext(&gbmSurface_)) + return -ENODEV; + + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits); + + LOG(Debayer, Debug) << "Available fragment shader texture units " << maxTextureImageUnits; + + /* Raw bayer input as texture */ + eglImageBayerIn_ = std::make_unique(width_, height_, 32, inputConfig_.stride, GL_TEXTURE0, 0); + + /* Texture we will render to */ + eglImageBayerOut_ = std::make_unique(outputSize_.width, outputSize_.height, 31, outputConfig_.stride, GL_TEXTURE1, 1); + + if (initBayerShaders(inputPixelFormat_, outputPixelFormat_)) + return -EINVAL; + + return 0; +} + +void DebayerEGL::stop() +{ + eglImageBayerOut_.reset(); + eglImageBayerIn_.reset(); + + if (programId_) + glDeleteProgram(programId_); + + egl_.cleanUp(); +} + +SizeRange DebayerEGL::sizes(PixelFormat inputFormat, const Size &inputSize) +{ + Size patternSize = this->patternSize(inputFormat); + unsigned int borderHeight = patternSize.height; + + if (patternSize.isNull()) + return {}; + + /* No need for top/bottom border with a pattern height of 2 */ + if (patternSize.height == 2) + borderHeight = 0; + + /* + * For debayer interpolation a border is kept around the entire image + * and the minimum output size is pattern-height x pattern-width. + */ + if (inputSize.width < (3 * patternSize.width) || + inputSize.height < (2 * borderHeight + patternSize.height)) { + LOG(Debayer, Warning) + << "Input format size too small: " << inputSize; + return {}; + } + + return SizeRange(Size(patternSize.width, patternSize.height), + Size((inputSize.width - 2 * patternSize.width) & ~(patternSize.width - 1), + (inputSize.height - 2 * borderHeight) & ~(patternSize.height - 1)), + patternSize.width, patternSize.height); +} + +} /* namespace libcamera */ diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h new file mode 100644 index 000000000..a5033bc63 --- /dev/null +++ b/src/libcamera/software_isp/debayer_egl.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2025, Bryan O'Donoghue. + * + * Authors: + * Bryan O'Donoghue + * + */ + +#pragma once + +#include +#include +#include + +#define GL_GLEXT_PROTOTYPES +#define EGL_EGLEXT_PROTOTYPES +#include + +#include "libcamera/internal/bayer_format.h" +#include "libcamera/internal/egl.h" +#include "libcamera/internal/framebuffer.h" +#include "libcamera/internal/mapped_framebuffer.h" +#include "libcamera/internal/software_isp/benchmark.h" +#include "libcamera/internal/software_isp/swstats_cpu.h" + +#include +#include +#include + +#include "debayer.h" + +namespace libcamera { + +#define DEBAYER_EGL_MIN_SIMPLE_RGB_GAIN_TEXTURE_UNITS 4 +#define DEBAYER_OPENGL_COORDS 4 + +class DebayerEGL : public Debayer +{ +public: + DebayerEGL(std::unique_ptr stats, const GlobalConfiguration &configuration); + ~DebayerEGL(); + + int configure(const StreamConfiguration &inputCfg, + const std::vector> &outputCfgs, + bool ccmEnabled); + + Size patternSize(PixelFormat inputFormat); + + std::vector formats(PixelFormat input); + std::tuple strideAndFrameSize(const PixelFormat &outputFormat, const Size &size); + + void process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, DebayerParams params); + int start(); + void stop(); + + const SharedFD &getStatsFD() { return stats_->getStatsFD(); } + unsigned int frameSize(); + + SizeRange sizes(PixelFormat inputFormat, const Size &inputSize); + +private: + static int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config); + static int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config); + int setupStandardBayerOrder(BayerFormat::Order order); + void pushEnv(std::vector &shaderEnv, const char *str); + int initBayerShaders(PixelFormat inputFormat, PixelFormat outputFormat); + int initEGLContext(); + int generateTextures(); + int compileShaderProgram(GLuint &shaderId, GLenum shaderType, + unsigned char *shaderData, int shaderDataLen, + std::vector shaderEnv); + int linkShaderProgram(void); + int getShaderVariableLocations(); + void setShaderVariableValues(DebayerParams ¶ms); + void configureTexture(GLuint &texture); + int debayerGPU(MappedFrameBuffer &in, int out_fd, DebayerParams ¶ms); + + /* Shader program identifiers */ + GLuint vertexShaderId_ = 0; + GLuint fragmentShaderId_ = 0; + GLuint programId_ = 0; + + /* Pointer to object representing input texture */ + std::unique_ptr eglImageBayerIn_; + std::unique_ptr eglImageBayerOut_; + + /* Shader parameters */ + float firstRed_x_; + float firstRed_y_; + GLint attributeVertex_; + GLint attributeTexture_; + GLint textureUniformStep_; + GLint textureUniformSize_; + GLint textureUniformStrideFactor_; + GLint textureUniformBayerFirstRed_; + GLint textureUniformProjMatrix_; + + GLint textureUniformBayerDataIn_; + + /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */ + GLint ccmUniformDataIn_; + + /* Black Level compensation */ + GLint blackLevelUniformDataIn_; + + /* Gamma */ + GLint gammaUniformDataIn_; + + /* Contrast */ + GLint contrastExpUniformDataIn_; + + Rectangle window_; + std::unique_ptr stats_; + eGL egl_; + GBM gbmSurface_; + uint32_t width_; + uint32_t height_; + GLint glFormat_; + unsigned int bytesPerPixel_; + uint32_t shaderStridePixels_; +}; + +} /* namespace libcamera */ diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build index 59fa5f02a..c61ac7d59 100644 --- a/src/libcamera/software_isp/meson.build +++ b/src/libcamera/software_isp/meson.build @@ -2,6 +2,7 @@ softisp_enabled = pipelines.contains('simple') summary({'SoftISP support' : softisp_enabled}, section : 'Configuration') +summary({'SoftISP GPU acceleration' : gles_headless_enabled}, section : 'Configuration') if not softisp_enabled subdir_done() @@ -14,3 +15,10 @@ libcamera_internal_sources += files([ 'software_isp.cpp', 'swstats_cpu.cpp', ]) + +if softisp_enabled and gles_headless_enabled + config_h.set('HAVE_DEBAYER_EGL', 1) + libcamera_internal_sources += files([ + 'debayer_egl.cpp', + ]) +endif From patchwork Tue Jan 6 17:00:51 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25668 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 4B1AABDCC0 for ; Tue, 6 Jan 2026 17:01:26 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 055B962013; Tue, 6 Jan 2026 18:01:26 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="sB4nMzNA"; dkim-atps=neutral Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E64E762013 for ; Tue, 6 Jan 2026 18:01:23 +0100 (CET) Received: by mail-wr1-x436.google.com with SMTP id ffacd0b85a97d-42fbad1fa90so973526f8f.0 for ; Tue, 06 Jan 2026 09:01:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718883; x=1768323683; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=BO0mMIWhB901RhyMhEcHbc+LWlQiOyKCJvDrt0v6kXI=; b=sB4nMzNAeDLfxT/7bOjvIVdLUWyad+hI2PeUQXzCzm9uLwhVNpuffVezei0IH021tE xxrUfY4r2toyQvJ7I5g14fjOui9BN2aecmmEcVRKfgXdl9JweSxylA/tKUFJBd/chEGw YMzsiNxGqbNeGgRcByPo6Zn6RW6YFrwu07D9nEg/+2L20hA6ITJE9qfgM4m7159dX4Hc fbs33LRNnmDVsS5TjTiKTsMeVhTNTh71gr8/A4u2e9UG7rXgz4I7+X2K9gPw6AhEd+99 Kt6C/jAZH04PZT0ijVJZbzOVyvswV1OkWnh2gwI/K2nhOShPiUi94y/XXKBNhTxrilzX ne5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718883; x=1768323683; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=BO0mMIWhB901RhyMhEcHbc+LWlQiOyKCJvDrt0v6kXI=; b=tE1M0Z5O4+Ucw6Ngt8yxkviVWZS/+M5TRtVvE2UZ9j9n4b+nd72LMZS0XYU/tZPOrq guJR5sjPZsbUzaoJBsLuZdMb6691QiOk30Fl0b70PAXFQO+h/S+x2HmwZdaX5ycV2fqf gEI3h6vXIhmqtjmbCh75idDzs+sMomJm6qCbNLs2u0Y4uwgB4cCuwjSEBH1+Gdafvc37 BijDOjJXu6o3W2j9pQCs3VluRi2wvrLs6TElLFGMmMwNeRjUog7j8yQbmy5Ss5uSnyp2 /nbWvUMcEc5FTJaAYGo3+vYFCEbP6yuE7S4ej5kYIcrktFj8afvVZGScrfcrdY8Ufm3q phdQ== X-Gm-Message-State: AOJu0Yz8hafGHuUcNhQSsgz0qR26LfZ5SbBPNXDx8Xk/8BX6eorl5hOg QBmk4g3uTznzeQeTEhFey8K+fRQkAaxZziYaDwbWgO2sWLAknRzVXOW0QcmG3DU6lQLN4608jZc toB0p7Fw= X-Gm-Gg: AY/fxX7Mi3jakGkXNwH9fiwPVpTknGtjjNI6ZqT5hDywXnM+b6CqX5Vs2HBko2LXkdi P92/iZ011HDN8Hs75HoQvHysd+SqSfvqaFaZvYYUWMP1TrqmlPwQxuf4Hi3u33Xz/cV/mKzZBpJ /N1ZqlYXR9Lin3Vl6vIphTqeLyWzegA4Jkr4/SwnPYDqtkw34bWA+rq/LuL016HX1M0FsZalTXy 92lcB/tHVjccgddsO6q1jWyY1KTqfUZ0y6dWANSApzU3sFzJgIsddw7qfGGRJ339qmYy2KloatR fJafG04LtUULEYQIvgLvzWKcS6F8KEbQmMOhl9pFj1qkW9aF184ImWy81zR5Ji6vYQzvPSJEwWo zVnZ1/zgn5tcQgTjFtnDaLnUANRFjt1aqgCIvWnLdkIpEb/Wsw4+1DuWxl7D+9xxtetd1AjTHWB 7GsTa+GFdKEHmuudwvhaoZ38Zp/VYzEakkx4zbkWImndhzlkjkYtsrSU4G1fR6zqTP+Mo= X-Google-Smtp-Source: AGHT+IGRqjz2VW5/U6E4U01qlwSqVp5kzylBAmebYkRcGvT3M2SzqvZMyd7qoVUCJNnfe0lSFzZxew== X-Received: by 2002:a05:6000:22c7:b0:432:586f:2ab2 with SMTP id ffacd0b85a97d-432bc9ccc24mr4398820f8f.4.1767718882931; Tue, 06 Jan 2026 09:01:22 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:22 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Kieran Bingham , Milan Zamazal Subject: [PATCH v11 16/24] libcamera: software_isp: debayer_cpu: Make getInputConfig and getOutputConfig static Date: Tue, 6 Jan 2026 17:00:51 +0000 Message-ID: <20260106170059.56193-17-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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" Make getInputConfig and getOutputConfig static so as to allow for interrogation of the supported pixel formats prior to object instantiation. Do this so as to allow the higher level logic make an informed choice between CPU and GPU ISP based on which pixel formats are supported. Currently CPU ISP supports more diverse input and output schemes. Acked-by: Kieran Bingham Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/debayer_cpu.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h index ecc4f9dd0..67df2b93a 100644 --- a/src/libcamera/software_isp/debayer_cpu.h +++ b/src/libcamera/software_isp/debayer_cpu.h @@ -97,8 +97,8 @@ private: template void debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]); - int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config); - int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config); + static int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config); + static int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config); int setupStandardBayerOrder(BayerFormat::Order order); int setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat, From patchwork Tue Jan 6 17:00:52 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25670 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 BE700BDCC0 for ; Tue, 6 Jan 2026 17:01:27 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 78A9D6200F; Tue, 6 Jan 2026 18:01:27 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="nCa1AS4t"; dkim-atps=neutral Received: from mail-wr1-x42d.google.com (mail-wr1-x42d.google.com [IPv6:2a00:1450:4864:20::42d]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D3FCF6201B for ; Tue, 6 Jan 2026 18:01:24 +0100 (CET) Received: by mail-wr1-x42d.google.com with SMTP id ffacd0b85a97d-42fbad1fa90so973549f8f.0 for ; Tue, 06 Jan 2026 09:01:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718884; x=1768323684; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=slR7u71MBKDNK7zqNb3HFSBXdLunmgpP/3QgIZdLnTA=; b=nCa1AS4thZ0UpoSR8MKAg7Rt5oksluLwgdUkAGfS3tQkkoEe1H43TfwvUOVEmx4p34 CHAgjzvI5tjC09fR5qQDWSXxqydfbYZTK6xYtbzyIe/3ct68ckkrC+0V44JMn942bXD6 pkvKnixRD/T+PD6oVJaVPmu90eIRD9H5Phv5C3lfS72ZjTN+mgSpcy8wPHsJGntrcIeM CepCro+POvTvNRka5dbm297BVr7daP4cacspUs3np5o4OxiN+SxwTocNGZbo6bNtaY1X 0PQfg7vQX6RqjCaPhSagsGo8/9DgXUKRSbyYy1cgVCjDbDpK1uu0hiAybwDYb6CAksO+ tZkg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718884; x=1768323684; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=slR7u71MBKDNK7zqNb3HFSBXdLunmgpP/3QgIZdLnTA=; b=stPGog9xOa4FcjtE32pDacD27Q9GTgWVhGMQR0ifi0hY6HfV916g3vKtViDtVyw8fP LSmSv3Ha3YriSq4MdjoCjuTZVaOoK38jrXWQZIbyGYig4EVHB0uBuVz5oBbC4RjlPqGG Lea2q4FtL2otH8JiUAR0866b19VPOhyxzr21HaL8YMnr33qSzYmrVSQMZ1JgBt0f4SNk FrgkajNAelgqMfWbf4gWdmmK/lxF1D/usMC3txl/J949EXhBZ3i4QBQUa+9yuJWDYvtv 5LfnziEctEuy0cBa4AglHfX4Yk17fN+Ls4daKktoNTzM0Ul9QEvD7vvfQ7wzR5Xh8q+E 6yDg== X-Gm-Message-State: AOJu0YxlIbxqHzx68CU0SfUNkO1VdX+rowVB4iOXahFbIAJiZ4NsKxse +1ko9Oy/QSmCXCQbt5w5XlPsNtXIts1E6ESt+t4k17QP6WkUDvn+Sip9BRY+NGU2mux0O44iOC5 Q881sOT0= X-Gm-Gg: AY/fxX4CDEdYg7OU70KKiWGUeCq2LBZkRTs0oI41yrszxq4UvDkQAiIJUll3joPzmPG /iRNgfkt5Cw1gA5f9fa57TsiGt73WrUu6vAlnuoTeKdJfhOnbqZQmXUXTtQ/AihE6irHqUlvRqM i9sY7S//ctQm7g0vJ3rJhThP1TrY69IoAk/AUhd9XWlew/vLayEvsUYKgqk6+/Bs6qUmQlMZbib MmBVYC4qXBQ4fOL4ITWwma9BoPHShTxtic2IqAAuxU9MvvS9QAVCHIz8PGL6TCGmzwtmJTcysZA YbQwZPh4AIwxeZRKYqBZ/0jU9oj4TyvXXXkluAq4WaoLrfrs7Yt7eSc+BKiJiGlELVO7/P8/iDi S9YiHN3R0b3e/Wzxae0hPmzRUqLOMi7YtWdaewf+S1h/ecx1w1yhvD6XGIGw0hXU4K1FUI9b92g TTCG9Sq1DcIwoxdLYzP5UX8fuqEkMfGQ6/r/unx8cwNbundDDhFpXewqI2pvkorfs8oiA= X-Google-Smtp-Source: AGHT+IHmA40Wzv6zC64BVsAxLRt0MQ2ZrZK74G9mazdZPcStGkWEfO1mmZ38Avn7y/Mvz1ew9VKYBg== X-Received: by 2002:a05:6000:2082:b0:431:62:d946 with SMTP id ffacd0b85a97d-432bc9d7881mr5089809f8f.23.1767718884039; Tue, 06 Jan 2026 09:01:24 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:23 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Milan Zamazal , Hans de Goede , Bryan O'Donoghue Subject: [PATCH v11 17/24] libcamera: software_isp: GPU support for unpacked 10/12-bit formats Date: Tue, 6 Jan 2026 17:00:52 +0000 Message-ID: <20260106170059.56193-18-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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: Milan Zamazal The GPU processing supports 8-bit sensor formats and 10/12-bit packed formats. Support for 10/12-bit unpacked formats is missing, let's add it. 10/12-bit unpacked formats use two adjacent bytes to store the value. This means the 8-bit shaders can be used if we can modify them for additional support of 16-bit addressing. This requires the following modifications: - Using GL_RG (two bytes per pixel) instead of GL_LUMINANCE (one byte per pixel) as the texture format for the given input formats. - Setting the texture width to the number of pixels rather than the number of bytes. - Making the definition of `fetch' macro variable, according to the pixel format. - Using only `fetch' for accessing the texture. Signed-off-by: Milan Zamazal Reviewed-by: Hans de Goede Signed-off-by: Bryan O'Donoghue --- src/libcamera/shaders/bayer_unpacked.frag | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag index af4a30c4b..1b85196ae 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -41,9 +41,17 @@ float apply_contrast(float value) void main(void) { vec3 rgb; + #if defined(RAW10P) + #define pixel(p) p.r / 4.0 + p.g * 64.0 + #define fetch(x, y) pixel(texture2D(tex_y, vec2(x, y))) + #elif defined(RAW12P) + #define pixel(p) p.r / 16.0 + p.g * 16.0 + #define fetch(x, y) pixel(texture2D(tex_y, vec2(x, y))) + #else #define fetch(x, y) texture2D(tex_y, vec2(x, y)).r + #endif - float C = texture2D(tex_y, center.xy).r; // ( 0, 0) + float C = fetch(center.x, center.y); // ( 0, 0) const vec4 kC = vec4( 4.0, 6.0, 5.0, 5.0) / 8.0; // Determine which of four types of pixels we are on. From patchwork Tue Jan 6 17:00:53 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25672 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 3457BC3213 for ; Tue, 6 Jan 2026 17:01:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F228661FCB; Tue, 6 Jan 2026 18:01:30 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="FSRMLKG7"; dkim-atps=neutral Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 747506201E for ; Tue, 6 Jan 2026 18:01:27 +0100 (CET) Received: by mail-wr1-x42c.google.com with SMTP id ffacd0b85a97d-42fb03c3cf2so650294f8f.1 for ; Tue, 06 Jan 2026 09:01:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718886; x=1768323686; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=OsQgF7Qs+HMvg1ZequOlo1SF53K1FeHzGwsdEPNX8Cs=; b=FSRMLKG7LkWvz0e7P6rF70f4UbIOBFUCnliNcPwthZGv7Z9hXOrcgVZD+SPRNcFV7u QKp/53O3eNGIcK8WcBJhOEgJaE7cyUtsdMXggR2URcakU+1C0K0xhXTYMAPReCJia6Ha fLOPfNH8HUjYGC+mRsRfheuKvKZeSzPXyBXJbUttVHEEyUkY2bH+fKBc+t3W66+rSSfV hGMIfFx6x63D/vW1RitFmF/dxfsFU+njUDaoOrvXWqmOqRViDyLTbkH6V6asph6iBT4t OENL1gWabwrndtzdpMcXo0xucEn4Gornyn/M9b7jj/OXNyuR/UA/oxwTD14kcYZ9Adgg 6sPA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718886; x=1768323686; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=OsQgF7Qs+HMvg1ZequOlo1SF53K1FeHzGwsdEPNX8Cs=; b=wRyvnF5v+/FMTu1kylBfO0tbB6tp4xYXaiU1N80moUprrRcB5pHwmYeNoHONuDtgrr Ak5MbO226cmgOLZHWOVXUGWmTaZxJC9ebl7v2g2q5tdKau9I+zUenv3zqwCF5nl1wEv6 9J5OGWglI6iNidbE8fFZ/yo5Jr5AxPhZwlopj9qH7HqbcKd9FG8TPIeZWPbtGdPZjNh2 Uj8YEsQRB0JkLFJRtj6KmpUIlYXqO8VJyhQ0cqkeKIzEG+MQxBQt/ENEC53cE/o8GZQs aWqL8yyhU+k5eDofVMFQKOWq/0jGwbTHmtnr1QjQQT0q4DuiKLZ6tYVZhdLogpomNmZ6 rqmw== X-Gm-Message-State: AOJu0YywKgnHx7aleQ4SUkYJ/am1pXOxt52+1hwj3+j4joWDuF3DvxRT 9K8d3aVqTbFvLkQjim80rdukOrcwcGISRtJZx/BLhUr1Rq3rwt5hqfUB5DQOSR5HTtyUlzNHNT6 nob2Lxdk= X-Gm-Gg: AY/fxX59pRqXfH4yCjnwQLrW7Mg5kPHERVqB5pmVZg0kFBJwjH9LCoWKuEh3CejJ21Z IjZzJvv2aMSCSkJx8qv+DaCWSZKntKes6QiKK2iEF1ulU7bBq2a0jlVnYBVFuKGE2HbVSbQaRwK qjDVOGKGhZiwRIe7UndkT2s+YtwwN6OwsZXm3fWtXIze0kxYE4FPRR+WFjotozMrD3f+MgNalfr VXLsNINQOlIp9P3SOrtROIUnZDh73nAO3ymuuyV1rv0HPVGIzCMMedzB7L1DoTTMrYTbfpYAwL/ XY9Eumjj4k+UOp4qCRP//ukD9BvcG1bvOpC3aB1GpRhxQv+0KIh32YMewV0wIt3gOYZ0kK4q5+H MmDHtYKROIBnbQ6DEyzt2w6DdJ8UEQ2hf1SbymCKe7hd9dXa5k8Bpotfk0WaP+mZZOjQm9UvNhA ZSYhd4pkd/2cd+oTuJN6kMEX51VF2B7kzFJ1jioVZ94zqv9qJHnfhECkBikGA+FKQsA9/8a/xTN tYZqg== X-Google-Smtp-Source: AGHT+IGemVHqweql1wbJDuSan5Jt1VoRPrcuKnpwI5wryy1dlrdhuKYqyje0mUB4nDc1AWj0dvusQg== X-Received: by 2002:a05:6000:401f:b0:432:5b81:497 with SMTP id ffacd0b85a97d-432bca03f1cmr4639101f8f.58.1767718885064; Tue, 06 Jan 2026 09:01:25 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:24 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v11 18/24] libcamera: software_isp: debayer_egl: Make DebayerEGL an environment option Date: Tue, 6 Jan 2026 17:00:53 +0000 Message-ID: <20260106170059.56193-19-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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" If GPUISP support is available make it so an environment variable can switch it on. Given we don't have full feature parity with CPUISP just yet on pixel format output, we should default to CPUISP mode giving the user the option to switch on GPUISP by setting LIBCAMERA_SOFTISP_MODE=gpu Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/software_isp.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index b31a374d8..5e837af4c 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -25,6 +26,9 @@ #include "libcamera/internal/software_isp/debayer_params.h" #include "debayer_cpu.h" +#if HAVE_DEBAYER_EGL +#include "debayer_egl.h" +#endif /** * \file software_isp.cpp @@ -117,7 +121,15 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, } stats->statsReady.connect(this, &SoftwareIsp::statsReady); - debayer_ = std::make_unique(std::move(stats), configuration); +#if HAVE_DEBAYER_EGL + std::optional softISPMode = configuration.envOption("LIBCAMERA_SOFTISP_MODE", { "software_isp", "mode" }); + + if (softISPMode && softISPMode == "gpu") + debayer_ = std::make_unique(std::move(stats), configuration); +#endif + if (!debayer_) + debayer_ = std::make_unique(std::move(stats), configuration); + debayer_->inputBufferReady.connect(this, &SoftwareIsp::inputReady); debayer_->outputBufferReady.connect(this, &SoftwareIsp::outputReady); From patchwork Tue Jan 6 17:00:54 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25671 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 791ECBDCC0 for ; Tue, 6 Jan 2026 17:01:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 283596202B; Tue, 6 Jan 2026 18:01:30 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="OQqI5vIS"; dkim-atps=neutral Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4CD346201B for ; Tue, 6 Jan 2026 18:01:27 +0100 (CET) Received: by mail-wr1-x436.google.com with SMTP id ffacd0b85a97d-42fb2314f52so580905f8f.0 for ; Tue, 06 Jan 2026 09:01:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718886; x=1768323686; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=obbRpAVZjcoxO7/iHqw+nRA0ImMCqi2GHIb0BnjqJe8=; b=OQqI5vISHPn1XG88qnL24FTu7QisQ7HuloHNpdQqnl1QLTbR5P7FVRTGb4Qu9eYQPD rkL7+8KY6jtTYCDUOyktgsYwxIg1rXkDRlF96W/1vMhLRAtLvw1IJ5FQ3/Sh4yF9lPNt Uaxx9jtx2OkFmwiiYZk2hXIj7bNyWMGrs14ut5IoDyArJFMzf1BN+8WpRQv+TKCePebR NgUjjFa7OYJxQfa9pyWsEDd1GftfGPIcasKX4u1K/LODFvOs39CYiMGl+uEYBKIdvkXK Lu5v9XAEFYXylmExFB9fAL1duIHZ8dVDOpgGLCPBsJQLSIQxY+LYqGTJSswPoJN8lDPG myIg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718886; x=1768323686; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=obbRpAVZjcoxO7/iHqw+nRA0ImMCqi2GHIb0BnjqJe8=; b=NDqj1AWDz6xWGrqMMFt493HnqO0ZBb9Ln7n28cjVjdklgZE12Bm8fQXO2+qby4Wjvc aWz9UCptH8ZV6cct8JsfIqgHgZgKHWha4epkCTE/DFOuyUineW8yOo6RomNOSjoGbHxR cLbaWnpHGAy02072yFcj60eRVXw3zrHSqqy2Ny7+B9vBrqqBcyJTKaBMLoJ4pFKrUnJF noBTdr8Kc2aT0r9e6e8+SKfgsiEJkaGqa4fnM3/MH66skxm4leeGdL3B9JQG2rpybez6 n9xOrgJqzFzLij3ZF7rJCXAemOruDCLbx2PgI0/Mqvg56PbBnD7nB1AQv5bjyA3siHVE K+Cw== X-Gm-Message-State: AOJu0YxjFJvF48IEFqhcpBxChZDXYlAWYo7/0hJq8r3uBjYayJUAEgCm ZdGMeXYIQ92hvGLefmCZ91T6ja2WLRqY+eXcfqVaBwqJRJHDtAHg6/SvLi9YIgVwZgqnUv/XM/l 7P+1/K74= X-Gm-Gg: AY/fxX4wVlejL0eJGReUblVfux9yJRDAO51E14Jy99rRq9/rhgEWR+yr6wBKrQYkEgO CD60qjMz8YnyACm48ceJwdgYS3kjmLVzSuIgD+us7mWrnYOq+gZn+wPYL1VoOAkmxy3Q7sAlwP8 N/wqrg5ClCTRBdAEIsr2z6rRi0EBeeFvv0zWmhyfuMsIl4jn48XA9KmcGMPgLal0i5keqwqCvio ypmqC5AkZorduwrQurDPJUZgFvchKy/1OimzOa8Rm11Exw10oifBs9BQJDXR8rlkXThqnTeMED5 S118VWWA2RcuooAnYTqoFDj0PdJ1vZ4WIdLikqFx61CjjEW9YaH8TFnBh2ofS6ioBGxs7uij/A9 HOtVjJOBgVFS4oiw5UxAy4bZ6bPcqojPSkT3oxLY7IqSXh89Wq7jQGUECrccMMERz63KIMCwq26 wqmYekG/NtEa0+SqTirqM9sh3nGuQwNYc4nY6Ms2VO1WImOhQHoXYQ5b9PTfKfPyIafRA= X-Google-Smtp-Source: AGHT+IGEVnZnrOVFylNVBK5+GhMY1mrE44j1PP/HesrtiFTxXbOJLBuQWQhfJp7lPC1ZKRx1tcqb2Q== X-Received: by 2002:a05:6000:288b:b0:430:fb6d:1442 with SMTP id ffacd0b85a97d-432bca52322mr5037484f8f.62.1767718886418; Tue, 06 Jan 2026 09:01:26 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:25 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v11 19/24] ipa: simple: Add a flag to indicate gpuIspEnabled Date: Tue, 6 Jan 2026 17:00:54 +0000 Message-ID: <20260106170059.56193-20-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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" Flag gpuIspEnabled in the simple IPA context. This flag will allow to selectively avoid some calculations or to generate a default CCM. Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- include/libcamera/ipa/soft.mojom | 3 ++- src/ipa/simple/ipa_context.h | 1 + src/ipa/simple/soft_simple.cpp | 3 +++ src/libcamera/software_isp/software_isp.cpp | 11 +++++++++-- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/include/libcamera/ipa/soft.mojom b/include/libcamera/ipa/soft.mojom index 77328c5fd..aff8fcbd3 100644 --- a/include/libcamera/ipa/soft.mojom +++ b/include/libcamera/ipa/soft.mojom @@ -17,7 +17,8 @@ interface IPASoftInterface { libcamera.SharedFD fdStats, libcamera.SharedFD fdParams, libcamera.IPACameraSensorInfo sensorInfo, - libcamera.ControlInfoMap sensorControls) + libcamera.ControlInfoMap sensorControls, + bool gpuIspEnabled) => (int32 ret, libcamera.ControlInfoMap ipaControls, bool ccmEnabled); start() => (int32 ret); stop(); diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h index 7837bb4dd..26db92e93 100644 --- a/src/ipa/simple/ipa_context.h +++ b/src/ipa/simple/ipa_context.h @@ -105,6 +105,7 @@ struct IPAContext { FCQueue frameContexts; ControlInfoMap::Map ctrlMap; bool ccmEnabled = false; + bool gpuIspEnabled = false; }; } /* namespace ipa::soft */ diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp index dde116661..57836c73c 100644 --- a/src/ipa/simple/soft_simple.cpp +++ b/src/ipa/simple/soft_simple.cpp @@ -55,6 +55,7 @@ public: const SharedFD &fdParams, const IPACameraSensorInfo &sensorInfo, const ControlInfoMap &sensorControls, + bool gpuIspEnabled, ControlInfoMap *ipaControls, bool *ccmEnabled) override; int configure(const IPAConfigInfo &configInfo) override; @@ -95,6 +96,7 @@ int IPASoftSimple::init(const IPASettings &settings, const SharedFD &fdParams, const IPACameraSensorInfo &sensorInfo, const ControlInfoMap &sensorControls, + bool gpuIspEnabled, ControlInfoMap *ipaControls, bool *ccmEnabled) { @@ -106,6 +108,7 @@ int IPASoftSimple::init(const IPASettings &settings, } context_.sensorInfo = sensorInfo; + context_.gpuIspEnabled = gpuIspEnabled; /* Load the tuning data file */ File file(settings.configurationFile); diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index 5e837af4c..5a93442f8 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -121,14 +121,20 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, } stats->statsReady.connect(this, &SoftwareIsp::statsReady); + bool gpuIspEnabled; + #if HAVE_DEBAYER_EGL std::optional softISPMode = configuration.envOption("LIBCAMERA_SOFTISP_MODE", { "software_isp", "mode" }); - if (softISPMode && softISPMode == "gpu") + if (softISPMode && softISPMode == "gpu") { debayer_ = std::make_unique(std::move(stats), configuration); + gpuIspEnabled = true; + } #endif - if (!debayer_) + if (!debayer_) { debayer_ = std::make_unique(std::move(stats), configuration); + gpuIspEnabled = false; + } debayer_->inputBufferReady.connect(this, &SoftwareIsp::inputReady); debayer_->outputBufferReady.connect(this, &SoftwareIsp::outputReady); @@ -160,6 +166,7 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, sharedParams_.fd(), sensorInfo, sensor->controls(), + gpuIspEnabled, ipaControls, &ccmEnabled_); if (ret) { From patchwork Tue Jan 6 17:00:55 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25674 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 7817FC3213 for ; Tue, 6 Jan 2026 17:01:32 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 21E6962033; Tue, 6 Jan 2026 18:01:32 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="tk54yVWa"; dkim-atps=neutral Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C78CB6201C for ; Tue, 6 Jan 2026 18:01:29 +0100 (CET) Received: by mail-wm1-x329.google.com with SMTP id 5b1f17b1804b1-47bdbc90dcaso8809785e9.1 for ; Tue, 06 Jan 2026 09:01:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718889; x=1768323689; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=psNP2vqDkJBYOqosGTGOW6EtApQ+kyXWy6fpn8pZtNw=; b=tk54yVWaUgUYStdJWZyKiawG1Jvs/UqMFC4jkIxevPVasTsmhMptjrRcMRh0kZqHG8 KTNSGC/LTnRzRQU7MWSIhCumIEjUvMSyKA/MIqJwJ4D31mIMTqa3picA7Gux+VFYssNB 2+RXXlPUcrj/DL5UOxq6qgX74/hRHGiea2j1lgP2/yJV4RJ0sTaJUUIXqWBTTwclYulu rrux4JYOLqYBXfTfUeS0QjVul4Qitfy1H0iQcnIgyVPZ+2Rwnh0CBHr4dZ8mIGVU3ksZ 9E5g8up4g/EJy762Fk2QlFlpKBcMxxxS0RiLnOJviGzjPgSp0AhwuPzMDDzvDZzHvn5o Hsxw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718889; x=1768323689; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=psNP2vqDkJBYOqosGTGOW6EtApQ+kyXWy6fpn8pZtNw=; b=AWDiRr/8Iwjt4T2mNTYbOu4PESyolW3xnEWtBMOOBOV6vbB9+ivuh41V2+dEwq7LRz akGq4uW4eH9+nQZO6n8TN7P9+kDrt8tl90HKosE3a9Lsev758ONt3Q8/TVd0LZAGtn9B LHm49vPLBiQH6R+ULcMo4/lwIB7sbkpQsbqjogHTBXbGnVYDIUWR7nhVdpWathykJiF9 1CkBNjnBJ2m2juK7hg1prNOVyW3T91HeMBIevj2hwRzZHJhNnk0G75t2RJqYUk+9LSYV nlyJhG0YAGvEbGsk3fxi10tvb424H0KyZj6K7ifZO9teY7UyJ9I2KC23f0rvti+cVmS+ XxdQ== X-Gm-Message-State: AOJu0YyLA8BpNxociNu5ZKmXnHKs+9VVb6hHRF/WhvIniv/PVBKuTvQr 1PneAx058/DK35mYyfs+1rYS4n2J/T0O673O3jLlK5ZxDdS+QmXaovIbXythLYeKW4Oe7GSxp+1 uL5vxESQ= X-Gm-Gg: AY/fxX5r6Ca+yG/nXciW96fziiwirRfUcFSpiu/Dz7rhZk6Pqtd10OJSTZawviD3Xjy Tt23XHLDsa49U+zuAChINgvFYE75WBYtgm4/oZ4GFVKbhUhRgZvFf87xJ0F/Dm43GtsiQ/91o2r 34WuEUoEjz1LCze2DWWv9+EbyIvhNjrnjpxuMOE58TqfXBlRgveSGqrbubc7W7DH3yftNz54lUe dsVyMc3Q6ooAaoN/2aLtHYqiUp10n8mznFDrAHrvCsPF2t9nM9+j7QUtrHdJRj7s7z6Nuy+Yg0f Nv5oVVaIQlto88Hm8SK8WHJZw9AJBCrMMIUw2HqUI3ZBAIKsHU24XRI6ic0+ElQeKw9fYm6qMCn FS9/61sijhZJHnyN+tAwUXLE3BgHj1/sH4Dj2Vkgjv7BzTVNIqMcJkK5OHQzP5XqM899XoG3RkX rHPD1x7ZuWfVLUdd5A1Z4uRxCoesAj22gVh1B4ab/Ux/xNR2Dfx/r3qoKYG6EWB4Itw10= X-Google-Smtp-Source: AGHT+IHQAMRlOnKgd/tLsYCT9fskVYUJH3wDT3/4tugoJhXY8VAKQ+2NQJOTimyBAPOibVneTJsgnQ== X-Received: by 2002:a05:600c:1d24:b0:479:2a09:9262 with SMTP id 5b1f17b1804b1-47d7f077676mr41871795e9.9.1767718887582; Tue, 06 Jan 2026 09:01:27 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:27 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v11 20/24] libcamera: software_isp: lut: Skip calculation lookup tables if gpuIspEnabled is true Date: Tue, 6 Jan 2026 17:00:55 +0000 Message-ID: <20260106170059.56193-21-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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" On my reference platform Qualcomm RB5 sm8520 the qcam application CPU occupancy drops from ~100% to about 95% of a single core so this one change sheds aprox 5% CPU usage. Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/ipa/simple/algorithms/lut.cpp | 67 ++++++++++++++++--------------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/src/ipa/simple/algorithms/lut.cpp b/src/ipa/simple/algorithms/lut.cpp index 7d015ac89..7418daa1e 100644 --- a/src/ipa/simple/algorithms/lut.cpp +++ b/src/ipa/simple/algorithms/lut.cpp @@ -56,33 +56,34 @@ void Lut::queueRequest(typename Module::Context &context, void Lut::updateGammaTable(IPAContext &context) { - auto &gammaTable = context.activeState.gamma.gammaTable; const auto blackLevel = context.activeState.blc.level; - const unsigned int blackIndex = blackLevel * gammaTable.size() / 256; const auto contrast = context.activeState.knobs.contrast.value_or(1.0); /* Convert 0..2 to 0..infinity; avoid actual inifinity at tan(pi/2) */ double contrastExp = tan(std::clamp(contrast * M_PI_4, 0.0, M_PI_2 - 0.00001)); - const float divisor = gammaTable.size() - blackIndex - 1.0; - for (unsigned int i = blackIndex; i < gammaTable.size(); i++) { - double normalized = (i - blackIndex) / divisor; - /* Convert 0..2 to 0..infinity; avoid actual inifinity at tan(pi/2) */ - /* Apply simple S-curve */ - if (normalized < 0.5) - normalized = 0.5 * std::pow(normalized / 0.5, contrastExp); - else - normalized = 1.0 - 0.5 * std::pow((1.0 - normalized) / 0.5, contrastExp); - gammaTable[i] = UINT8_MAX * - std::pow(normalized, context.configuration.gamma); + if (!context.gpuIspEnabled) { + auto &gammaTable = context.activeState.gamma.gammaTable; + const unsigned int blackIndex = blackLevel * gammaTable.size() / 256; + const float divisor = gammaTable.size() - blackIndex - 1.0; + for (unsigned int i = blackIndex; i < gammaTable.size(); i++) { + double normalized = (i - blackIndex) / divisor; + /* Apply simple S-curve */ + if (normalized < 0.5) + normalized = 0.5 * std::pow(normalized / 0.5, contrastExp); + else + normalized = 1.0 - 0.5 * std::pow((1.0 - normalized) / 0.5, contrastExp); + gammaTable[i] = UINT8_MAX * + std::pow(normalized, context.configuration.gamma); + } + /* + * Due to CCM operations, the table lookup may reach indices below the black + * level. Let's set the table values below black level to the minimum + * non-black value to prevent problems when the minimum value is + * significantly non-zero (for example, when the image should be all grey). + */ + std::fill(gammaTable.begin(), gammaTable.begin() + blackIndex, + gammaTable[blackIndex]); } - /* - * Due to CCM operations, the table lookup may reach indices below the black - * level. Let's set the table values below black level to the minimum - * non-black value to prevent problems when the minimum value is - * significantly non-zero (for example, when the image should be all grey). - */ - std::fill(gammaTable.begin(), gammaTable.begin() + blackIndex, - gammaTable[blackIndex]); context.activeState.gamma.blackLevel = blackLevel; context.activeState.gamma.contrastExp = contrastExp; @@ -135,17 +136,19 @@ void Lut::prepare(IPAContext &context, auto &green = params->greenCcm; auto &blue = params->blueCcm; params->ccm = ccm; - for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) { - red[i].r = ccmValue(i, ccm[0][0]); - red[i].g = ccmValue(i, ccm[1][0]); - red[i].b = ccmValue(i, ccm[2][0]); - green[i].r = ccmValue(i, ccm[0][1]); - green[i].g = ccmValue(i, ccm[1][1]); - green[i].b = ccmValue(i, ccm[2][1]); - blue[i].r = ccmValue(i, ccm[0][2]); - blue[i].g = ccmValue(i, ccm[1][2]); - blue[i].b = ccmValue(i, ccm[2][2]); - params->gammaLut[i] = gammaTable[i / div]; + if (!context.gpuIspEnabled) { + for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) { + red[i].r = ccmValue(i, ccm[0][0]); + red[i].g = ccmValue(i, ccm[1][0]); + red[i].b = ccmValue(i, ccm[2][0]); + green[i].r = ccmValue(i, ccm[0][1]); + green[i].g = ccmValue(i, ccm[1][1]); + green[i].b = ccmValue(i, ccm[2][1]); + blue[i].r = ccmValue(i, ccm[0][2]); + blue[i].g = ccmValue(i, ccm[1][2]); + blue[i].b = ccmValue(i, ccm[2][2]); + params->gammaLut[i] = gammaTable[i / div]; + } } } From patchwork Tue Jan 6 17:00:56 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25673 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 D39C4BDCC0 for ; Tue, 6 Jan 2026 17:01:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8C17D6202E; Tue, 6 Jan 2026 18:01:31 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="XHIUAMJ2"; dkim-atps=neutral Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 49B2F62015 for ; Tue, 6 Jan 2026 18:01:29 +0100 (CET) Received: by mail-wr1-x436.google.com with SMTP id ffacd0b85a97d-42fb6ce71c7so840636f8f.1 for ; Tue, 06 Jan 2026 09:01:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718888; x=1768323688; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Aa61dwHFuPU2nWkKgOcbVNULPiuPFfYjvl4Thr3u7LI=; b=XHIUAMJ2fY5v5nE5rFJMo3yBBr+AKI74BjM1w0GxSRQBnzBs1c2HS5FCnCzgBrq+Jc O+doVh1gDQkQ2VYSHo+EOlmiwTkHHZLbbAs/MdHgSMEGLTDd+/KwDA5DWRohsoSJNfh3 Q8G07wg1Jz2FVRjp0MNewa7k4n0vt1bU5smS8YO9aHlf955Zi0WAyT1R5xqdUByozabU gXhrN+7UQrNFnN4k8q2kR869kz0jgR4i87Lt3h/9CKQq25lZXegKKrH9dYhkpp4uEYcz JD7R4lcciODCNWbuSJ1aH8fkCpkdJwts39Sn7V1P/52ZgDDmCRtCv+nRHrgiqrKM9V1t E00g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718888; x=1768323688; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Aa61dwHFuPU2nWkKgOcbVNULPiuPFfYjvl4Thr3u7LI=; b=MZTmni2tLjZ93DMWsiUux6tx/9i9vEvvZjAW6I/6WIEtrjO7PcgmpMJHhgGRx3U+a2 OTywkSSaeDF99SFx+3bujQIkbbQEqqoWNfAjZc+8ciSzhg2XAUTAQguRHg65GwCe9yNF UbXJyy5+j6ay+JZu+3Mcjg6AItUQ4KrzbA9JA3s4T1Lbet8ZFn7xFdvU08GCZg6gbRci iQOpyF/Y19PmqEunPNs3EFxcGK8vkhHELBA4BoeWwxlJkE+VppLRaryb5Kgs4eBIW6Sr VWmOfnB7z0XFVnh/bgjsl0aRpT4Rvj0ntSA2cFtOmPH923pIFKIaHG+ssSJVRb2YdOI8 4QXw== X-Gm-Message-State: AOJu0YwkVxwHXsBGnQM/WJFDLDQIf3pHpcpYFLGoZ/aH7/MsWRiyiJ1E XBxZHOt5o0oMQg4aT4/kanAXNPELYut3aks6+GTvIiVA0Wg441e9g1tAzvnDmilITtBFFcxgEr2 jaVRnTY0= X-Gm-Gg: AY/fxX7wE4faAj3z23ci/ySsrhVERDoYLAQ9HM37Jw1hDuVD+QkgpnmXsSKafndRzw9 zQSK2HwuikqSwII997M02LXnMcwrvT90bBXE8wRljYUwC7G/9hZMQk0izewd4KBcTKXTxOOn7YF dC1wCPNymMF2yYSxyPLV2q+0AEAR4spqnXIrsQIt1O0whjdYLyaz27yFocM/pubenG547LUFmDs e2Xa4rU0/wljqoNon5TAd7GXtuBd6e3S4+4aIFdCBd5PoWfhmqGH+4l9U7adTWFBRiWUyTs0dkZ lW+iF/Ph1zMQIz6eiR19rOxuNl35j3xb6erS4njGbUx9BSKXpUBKC3Lup71P3T7Web1rnDjBCm0 zYa64oFd42Kmquq4if/YuYjjoXDncApd+a8IIBaJ5eVtOM/QDUUdQ+Iie2rbvGri1WM2tLw53Tw ewayrE+5QociIcIl6IdCuhCIC0v5YMorKULcfRLKol+ivaIi9seO7gnWH6JMsr8wHKQs3U0wknV NKzkA== X-Google-Smtp-Source: AGHT+IGdPYEe0ck6tEiEEU05vYDlwMwn3E62XB5eNzvaHeU9uZvIcLNPUqqzoC6/ff+i4jFZbG9vnQ== X-Received: by 2002:a05:6000:3109:b0:431:c60:c600 with SMTP id ffacd0b85a97d-432bc9f52abmr4865707f8f.35.1767718888486; Tue, 06 Jan 2026 09:01:28 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:28 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Hans de Goede , Milan Zamazal Subject: [PATCH v11 21/24] libcamera: software_isp: lut: Change default Gamma to 1.0/2.2 Date: Tue, 6 Jan 2026 17:00:56 +0000 Message-ID: <20260106170059.56193-22-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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" Change the default softisp Gamma from 0.5 to 1.0/2.2. Reviewed-by: Hans de Goede Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/ipa/simple/algorithms/lut.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ipa/simple/algorithms/lut.cpp b/src/ipa/simple/algorithms/lut.cpp index 7418daa1e..54cb804e7 100644 --- a/src/ipa/simple/algorithms/lut.cpp +++ b/src/ipa/simple/algorithms/lut.cpp @@ -35,7 +35,7 @@ int Lut::configure(IPAContext &context, [[maybe_unused]] const IPAConfigInfo &configInfo) { /* Gamma value is fixed */ - context.configuration.gamma = 0.5; + context.configuration.gamma = 1.0 / 2.2; context.activeState.knobs.contrast = std::optional(); updateGammaTable(context); From patchwork Tue Jan 6 17:00:57 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25675 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 8459EBDCC0 for ; Tue, 6 Jan 2026 17:01:33 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3E7FC62035; Tue, 6 Jan 2026 18:01:33 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="r9U2mQrc"; dkim-atps=neutral Received: from mail-wm1-x32d.google.com (mail-wm1-x32d.google.com [IPv6:2a00:1450:4864:20::32d]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2588B62029 for ; Tue, 6 Jan 2026 18:01:30 +0100 (CET) Received: by mail-wm1-x32d.google.com with SMTP id 5b1f17b1804b1-47a95efd2ceso10428175e9.2 for ; Tue, 06 Jan 2026 09:01:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718889; x=1768323689; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=gu8tmem/7pHqmS78yQ8iconF+t7R9LczIGfmwoVQURE=; b=r9U2mQrc+5luZxOajRNBXAG63zuH/LxMOPkP1X5lPS+fTTIAk2Vif0T67rjvNuS740 S8/9Tg6CQxejVWKb5RVEzGLv2/zQccJX3+t9LhxRULhu5oyMT2oVZ+SOtSm1oYzsxlRM Efzb0V18e6bDadefeX2xBlJeZGjFwhJjRIrdAYSysjSqwj1wxbv3czxWCsVXiumYwgr7 IOLRgRKBAEfGEFwItrt4e2fnjLVCBndVDHy/o+Ojts4/LPb2wuQKpB4BUAOKrXsez5as RsWJ2D3OYBg/ZdSBYCQozv4amPuKTLOzEw+FYnf4Pbfzkmi8eKeV49ICUOuAqewnrZi0 zOVA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718889; x=1768323689; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=gu8tmem/7pHqmS78yQ8iconF+t7R9LczIGfmwoVQURE=; b=doh7xKMx5/ymi8Rr6C0B5BPOt/Sqz6H5CDEfHarUW2YyhLDtaG/9SNVoAejQ/pv//Y r352LkA9xLMr5svisyMODLKJX33+5qj32cWzll8nGSa+ekRk0bl+HceWtVx7OQmtMrRw 3OkU9NgT1ID5b+7T4PSSNop8wpVtaOGLlgau5MY+q26fD2FDamadLApgvwC48lg4VQBx RAIGXJKjwDVM95avM8/jLgDxDllr1ESXEeKZvfdYu1n14+yhbsDx9D43ZuJFVtqQMg3T 03vm/QYhrb5bQ9OIB4kOmh7QdYpTomc6fFGBngMt9lTjbgox3lpGr+2gtmoE4i/H/ead pnCA== X-Gm-Message-State: AOJu0Yx8dXeKJ0zpQbYnSFE+72VMJyzxmRlLDXjPniHT0mcoKkUTGCfG u8WNAsHf8DlUsNbWbUe8Dk/8ZYGLfTRDNhG8EF+HaCeC8y6q6cSHH8d+f6pFrnA7NMfmMr4z9Ur 9YFmLzKE= X-Gm-Gg: AY/fxX5C5AODW3Mjr9f37IPFZSdE2rti2vzeJm3R6vowo1UbnboaDKlDEfJvt0u1kdQ bTlPfPJUzcgYX327FynM1x7OU2AGur41ZI4ngu21TBH/5SJdjg0KMBPu0JLbVsqfcDQ27tJKBIC mZtuCBjPNH/5ZYxQa0WhnLq+fCqgmkyISr4j4PDTYGyYAQjjxiPpKYO+Ip3gPDkPag6PjiXh7CB +lDNs/LXRA7zlP0bjM04P+YDyzfwlvb90wpeC/XvoUcqXd/XZqETH0ToRNhbxmn+hDKVEMFjz4C 8duxz+xNu5wAzXk1na+pr5aQI51/x9eUaVdnEpSzObVN7+dfdUm1Fw+GNamYX3WFqIpDY47CI4V Tc+3dZyWWVhDnIrth/dWgXdmWCqt4fpLA31TyD2Veyt0Mkp1HfTkqKBGk8I9U2kIPdzIc0p1nY6 HB00tax80YAVvhOSB5ILE8bNlMiz482Z///Y2+kiSB4U9K3RLHCYjuzq58vjlZHfWTKvQ= X-Google-Smtp-Source: AGHT+IFzVbrD2pTBkBu6vFXNIe9g/ZE5B52e1+DnYXQ7tb5R/LteDYVnnortuvvSNtbWfSN14wSPUg== X-Received: by 2002:a05:600c:37ce:b0:477:af07:dd1c with SMTP id 5b1f17b1804b1-47d7f0a3adcmr41711925e9.35.1767718889418; Tue, 06 Jan 2026 09:01:29 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:29 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v11 22/24] libcamera: software_isp: Switch on default CCM at 65k Date: Tue, 6 Jan 2026 17:00:57 +0000 Message-ID: <20260106170059.56193-23-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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" Switch on the uncalibrated CCM @ 65k colour temperature. This will become the default for SoftISP where we have swtiched to GPUISP as default. Signed-off-by: Bryan O'Donoghue Reviewed-by: Milan Zamazal --- src/ipa/simple/data/uncalibrated.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ipa/simple/data/uncalibrated.yaml b/src/ipa/simple/data/uncalibrated.yaml index 5508e6686..8b6df9afc 100644 --- a/src/ipa/simple/data/uncalibrated.yaml +++ b/src/ipa/simple/data/uncalibrated.yaml @@ -8,12 +8,12 @@ algorithms: # Color correction matrices can be defined here. The CCM algorithm # has a significant performance impact, and should only be enabled # if tuned. - # - Ccm: - # ccms: - # - ct: 6500 - # ccm: [ 1, 0, 0, - # 0, 1, 0, - # 0, 0, 1] + - Ccm: + ccms: + - ct: 6500 + ccm: [ 1, 0, 0, + 0, 1, 0, + 0, 0, 1] - Lut: - Agc: ... From patchwork Tue Jan 6 17:00:58 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25677 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 D7545BDCC0 for ; Tue, 6 Jan 2026 17:01:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 78E2462021; Tue, 6 Jan 2026 18:01:36 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="I0BWxU3v"; dkim-atps=neutral Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C7BBF6200C for ; Tue, 6 Jan 2026 18:01:32 +0100 (CET) Received: by mail-wr1-x42c.google.com with SMTP id ffacd0b85a97d-430f9ffd4e8so12253f8f.0 for ; Tue, 06 Jan 2026 09:01:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718892; x=1768323692; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=fPV+YYnhiWt58AQ9eXmUONQuZ2vN/bNk/theU7ub+2o=; b=I0BWxU3v1wKRyY+56+/rhy+3v4dJjnUrMRiCCTLgpjCFYM34x9oklVdGjb74EhyFLD zgLS8XFOkfnDFiIY1+7OGVgNthAX8Zxbx+s4yoZVR5cdxxeRgnYY8gN7W4aqOIYfKpGn E7+5RVkMRGYb4MfIpaF7aGZVdOwWBlpdBuecAad34501Erzrc+iGyxJvCUtKcVn7L9N9 EIT40WJXnWKZxAvT1/exOke2lL6lMwXYEYrP4piA5Mns6ClwBKenZShbNUrMeLO3oVkT 6SvKCVh8EElPdnC8hOfgYgEvcUs2IHnoG8/zylngy8aYKjYbdxyaA9FIaYIFm9ffAF3Q dKxA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718892; x=1768323692; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=fPV+YYnhiWt58AQ9eXmUONQuZ2vN/bNk/theU7ub+2o=; b=J8bbponJse7ynNZBzPDRy1dR+vpGtn33X03cp2GbBfkcCRuR+IMGR6teuzhzWTCIer VG/ppZrMqj4A/VBx3m6IJn90C0f8Cxn4FdeRyOxuyRMubXMn/nDIBdhuYpbdWsFVUM3/ ap5ICspyr4P1EhNwEz4NmZKAqAHQH3AVZBNemFG6pGUcDghrMl2JHnCG7GrhjPga503K 73jY8oyKW9D9+DOQA90RiqlTNOxbIuO0NJRbmApD7f2jvZNAGCsCI37xjReQafVxO/tO kQd6VtYyRGzayTu0fS75cJlZ6Wm7QD398lAyH6ga+AJAl9n5RpmU9SRKJ3m/+Cyd2xox mpJQ== X-Gm-Message-State: AOJu0YwvQoEPyI3+l30xMY3CbFdtALgbpg77TIPXEEIdHiwYwB+QAxGc 0N+e9Zm4OHbkIMx7D/OoB0vksWsLSdN1L5lAyknLNN3qLqXbpL4ir2pIOF6gYsmLMxsiQcMdhXS mCFOnHKE= X-Gm-Gg: AY/fxX5j4GA0zucl1nACQJ4bxwytqggeOiwekpsbD11ODCMFLavWkUHJng0dtV5CJ0v twaaavw8fqY19dX8Ai1LF5UOv/wGoQDTEU2rzeIaFBLsZoNIdygUlSAEO5IUOBEXc4Xm8mg2+ta eBX29Eyfc8m3VLRVZXTi1BQdThAisIIm6BTHt3s4tB4KJ2PS12+NepRj5JwcnlFSVg6WADaqQlY YVHRIRcnOgy1GlT2KaQOTaUAU9fLC0Zyy5GcyAJuQVGRAcNS+ROPZ+FStxWnbdrPVWNeY4srQsD 0tWr6s3q25bVQy/hUYKyeqwMeG1cJQQeEIc+zN3ZkAkjQG7TBKKvzPX/2FLAP9RUCmZ3u854d67 pcjkMIomTIVCndSjpHE2otJIq3ewWMCEjsvZmxS/Zl2lfFTWxqm0FXESlcvPxxrGvmWsrH2bpEO xjbgFSYRVz6Ya+rG2CRsOxPpf1IkIMgr71buM+b/jZWID55jYnV7EthGFji76ngMKAoD4= X-Google-Smtp-Source: AGHT+IHLwmE51hkUiQkYF/nSap+OoFieFzoCtTLbufQ0A6E6w/oXQgnTdoSjCKG3Zrmwovgvg4z/PA== X-Received: by 2002:a05:6000:4287:b0:430:f74d:6e9f with SMTP id ffacd0b85a97d-432bcfd37b3mr4600620f8f.14.1767718890580; Tue, 06 Jan 2026 09:01:30 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:30 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v11 23/24] libcamera: software_isp: debayer_egl: Make gpuisp default softisp mode Date: Tue, 6 Jan 2026 17:00:58 +0000 Message-ID: <20260106170059.56193-24-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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" In some cases the GPU can deliver 15x performance in Debayer with the CCM on, reference hardware Qualcomm RB5 with IMX512 sensor. Given this large performance difference it makes sense to make GPUISP the default for the Software ISP. If LIBCAMERA_SOFTISP_MODE is omitted gpu will be the default. If libcamera is compiled without gpuisp support, CPU Debayer will be used. It is still possible to select CPU mode with LIBCAMERA_SOFISP_MODE=cpu. Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/software_isp.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index 5a93442f8..7ad3511db 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -125,8 +125,15 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, #if HAVE_DEBAYER_EGL std::optional softISPMode = configuration.envOption("LIBCAMERA_SOFTISP_MODE", { "software_isp", "mode" }); + if (softISPMode) { + if (softISPMode != "gpu" && softISPMode != "cpu") { + LOG(SoftwareIsp, Error) << "LIBCAMERA_SOFISP_MODE " << softISPMode.value() << " invalid " + << "must be \"cpu\" or \"gpu\""; + return; + } + } - if (softISPMode && softISPMode == "gpu") { + if (!softISPMode || softISPMode == "gpu") { debayer_ = std::make_unique(std::move(stats), configuration); gpuIspEnabled = true; } From patchwork Tue Jan 6 17:00:59 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25676 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 286FEBDCC0 for ; Tue, 6 Jan 2026 17:01:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D4EF86200B; Tue, 6 Jan 2026 18:01:35 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="eVV+aaPG"; dkim-atps=neutral Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A345A6203E for ; Tue, 6 Jan 2026 18:01:32 +0100 (CET) Received: by mail-wr1-x42e.google.com with SMTP id ffacd0b85a97d-42fb0fc5aa4so890953f8f.1 for ; Tue, 06 Jan 2026 09:01:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1767718892; x=1768323692; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=cR80ZvDKl1PnsXEsbuYPf4NeCxqkK7YbeqET+brIs1A=; b=eVV+aaPG+ROWY8zLHnUBFwTxA6exq/vWQfie7z6bnYbthKcTxZXRqK+lRpm6IrY9jp mWKrjrR6SCDadbKteqMrl0sHPvOtSKZb7lyTmav7AuaANreDYbsksUZ3k4L64uFaUcSm pTMTReF5bbMgZhw5lOvrWgi9mnMwkZuXOxmpbkWEltxkDpws9q6Mw4RzdBnn7Hi600x2 uOLospVVeGKRBDv1Klgv6b0lTJFiNC5MrxZ1qP8VQG1ETUHYwNqkELJrBD5WqNjQS/73 Vy6Z+dO+xdyb7S8frziLPPIklvkREPUIhZvwcLb/AJejW4kpPfe0f9vpFqHqDgD0BXXR 1zIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767718892; x=1768323692; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=cR80ZvDKl1PnsXEsbuYPf4NeCxqkK7YbeqET+brIs1A=; b=GJJINv70PS9ajCi90X64TtRfS8lFAzG6uZKtq2zuX+VMOOSdaS8qCenWczlk20qUk0 GdUdVjIGt8pnn51rYxTTbA2fD2CELAbsXOq5vwiHDtYSwKFKrIMjy5Pyp4BxwmGz3xlu isY0kQIqfXMaM/hePfdwUTPDflq7NuA5z6xYFNIgdSwtkHm8zrnphL7ER3BnQhrl9cGQ sHcorfg6nO/i7GzsnAzaEUEUWAjH/G8+ABA3HNAPfm5WP9w6eNtELee4UajIj7ZrCO+g xg6nYUb8hcLXj5aixBb0S3e3Wc2xrsSjulZ5wwrnkNCyVVcH6UVE3FSv4WYady/KrJ0f qyMg== X-Gm-Message-State: AOJu0YzE+NEd6rnxATE5yLuhnKRleNC8OQ3uj5Mn8x7xaBqrUIfeoMS2 3B8LdlYBRBar3O1RZVwIlPMtdRINw2AQKlGWhtyyj7LDhgkbVdhVuoAZ3QxXgFoVzoCHu2+EuxW 7BAxEOwg= X-Gm-Gg: AY/fxX55xoomkeNgA6sxYqoswKbDP5BPPFSsOd4DtKxTdJ/yVXO83utWbrd2+VtrfF8 jEP4HJxOk3MCg+5DWygYC+wRpTbY6PU2N9eH09Sos8MAX16rEN2sivmnb/7jex3wE5Zd1g1/WHR LM6Z5jNvCKs+h/jDOtcr/p7bK4s7q7QJTPPwVFBIIpmnAssSFq1oVGNQPUr92uH9gAOjT35AN7C IJ/1RJGaHpJjzXhMJ7gaIV9OIrBiPAZhhQHtAKXLpMudVq0B2Xj9cIKR2plOVIq0Actesz8iu4/ 74A2P17PPteMeuBQXtnbbEtueiaMaGReH7JvsWIny2v9nktRrpduaawn1qH5Q21WqizIQZR/pNs DS+LABCBNHa6OteAZGBV80OKTcSxM207johmO+SF5xATrSPVJNmaBjfSGilPdsZRopNx83XMQAg q1Vov6FWGzrHoVjYfvWv4UmDz2pVhW8BeK5RE+yDNEXLoojpmQP1jHgKNzKiYloCPHULhmR+3eh +GBeg== X-Google-Smtp-Source: AGHT+IHwdASHVjNpkuodtp/BXtCraHYEsO1pEvCW3Rbt+3iQiifG8aN7jLHfkpX35nCc/PsVPRDihw== X-Received: by 2002:a05:6000:18a6:b0:431:104:6dd5 with SMTP id ffacd0b85a97d-432bc9fd1c4mr4954807f8f.58.1767718891699; Tue, 06 Jan 2026 09:01:31 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd0dadcfsm5515322f8f.3.2026.01.06.09.01.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Jan 2026 09:01:31 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Kieran Bingham , Milan Zamazal Subject: [PATCH v11 24/24] libcamera: software_isp: Add a gpuisp todo list Date: Tue, 6 Jan 2026 17:00:59 +0000 Message-ID: <20260106170059.56193-25-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260106170059.56193-1-bryan.odonoghue@linaro.org> References: <20260106170059.56193-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 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" List the series of things to do in GPU ISP in perceived order of difficulty. Acked-by: Kieran Bingham Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/gpuisp-todo.txt | 40 ++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/libcamera/software_isp/gpuisp-todo.txt diff --git a/src/libcamera/software_isp/gpuisp-todo.txt b/src/libcamera/software_isp/gpuisp-todo.txt new file mode 100644 index 000000000..8930da120 --- /dev/null +++ b/src/libcamera/software_isp/gpuisp-todo.txt @@ -0,0 +1,40 @@ +List the TODOs in perceived order of ease. + + +Denoising: + - WIP + +Dead pixel correction: + - WIP + +Lense shading correction: + - WIP + +Use dma-buf handle to generate upload texture: + - eglCreateImageKHR can be used to generate the upload texture i.e. + to feed the bayer data into the GPU. + +processFrame() to run in its own thread: + - processFrame() runs in the context of the Debayer::process() + thread. Robert Mader suggested and it seems like a good + suggestion too to run processFrame() in its own thread. + +Multi-pass shaders: + - This needs some rewiring the idea is to have a list + of algorithms as is done in cpuisp iterating through the + list in a for() loop. + - The logic managing the loop has an initial input buffer + and the final output buffer. + - The higher level logic must then inform each of the + algorithms either to generate an internal working buffer + or pass the final output buffer to the last shader + in the list + - This will allow for multi-pass shaders with the final + algorithm presenting data not to its internal buffer + but to the final output buffer + +24 bit output support: + - Need to implement compute shader to do this. + +Lense flare correction: + - Not WIP still TBD