From patchwork Thu Nov 27 02:37:16 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25238 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 C2614C3257 for ; Thu, 27 Nov 2025 02:37:48 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6280360AA4; Thu, 27 Nov 2025 03:37:48 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="v6e1zN0n"; dkim-atps=neutral Received: from mail-wm1-x334.google.com (mail-wm1-x334.google.com [IPv6:2a00:1450:4864:20::334]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B74A2609DE for ; Thu, 27 Nov 2025 03:37:46 +0100 (CET) Received: by mail-wm1-x334.google.com with SMTP id 5b1f17b1804b1-47795f6f5c0so1431565e9.1 for ; Wed, 26 Nov 2025 18:37:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211066; x=1764815866; 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=25pB8O0ewcdP9Lkbp8q4k2CjU62VSX7AV+aAc5IUYUA=; b=v6e1zN0noHZ0CcfQcwz++p9RmMQvLttJuoaLjJJWxvTYSJy0B2stl1wlu8v5hpIute KGbDZjh6cWBjoskL11wM+ROpLE/jmTMepm+Gu33yA9o1gYrEDi0SNnBM+4EqnKL9UiTH feesg9K3H6ubzSujN1dIM9v0eFlm0nEGV6sLxQyt5qifeJDh5rEsrQHbBNLinabu4km/ IERC1MV3X6tI/ffFGECoZD+L6t0UprtKu89Yq8XizMYdQMs/bkp1QzuW9VDekkWtk5Ml aVhboGgJs+9l6fRuGcrRBGRDgD6bOFY2Ji+FNqXIvMPjnHDYCAURWkzCAlzSbXkCMYsd fazQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211066; x=1764815866; 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=25pB8O0ewcdP9Lkbp8q4k2CjU62VSX7AV+aAc5IUYUA=; b=a6/SqjblBMccaAwm2RwfTaFQFt+54FKNcPs8Ap0W10roDWOiFO+mfgdV5Kg6p7PBtb L2L0ASh8mSr2kIsp9uRbqU+BOqF8oSjGlTZOXSu+hzK9sUpfFuwTOrEnGnHZTPgB1fYw H1XgyAcNBcGDz7ija/rN6etY2uMJnT5uH0QCNqs7JVbjuSuhnKW+80c0wtmLrTaF/jIj yBqZ+MCdNMIM4fD0VxxfybVHTYHLAvmzuE+pN/Erritkbk4bMmVUzae4yM7pmkowGn8W cKbnK4lDKF1Wa/bHiQLcLSwHLv6SXg/zihHu3y0HHE8MmiWMI5u0WUuHlJcWEloKVBkd v1uQ== X-Gm-Message-State: AOJu0YypC7bqz5hpKoaUQr5QBp2L+GWx7RtHDZduuHdIbuSLLOKcXGx1 /wX5EfALUkJjNOYW9obOH0KDrJI0rdHNlF3C4YlE35fDnQj0arE1MU900eHKDux5gXbSa3pWdQm ArNCkGlc= X-Gm-Gg: ASbGncvu7qeACSsKbbcfKUkB0DIdPfoPNWn2ajmfSFoXNr5/QPsPG/dHA3walhLi9D2 dGWO7np7p++n0Ug3XFFLMPX13zNwR+OniSQOn7/MLKamGlZL4L93BC7fve8Ipve84I4zCdQAzV8 7wub+uJivYhE8BNZDOryHIETvAFK9MpL4+2fHvpuFFRqN9AgYWr4CAZ9+kneeL1zleeArJGz0z5 6HqyhXwbA76ahyzibAUskg0aMmAXP3M/pOwOCwuMwxptjOqXxJ4PPHN4IkcDmRUT4qBmUQhhQv7 nW2374IheNk+ytOjkdcDuX97o7lJvzbu00V6Sqm/SnzucyNJZwsDfH83nUmKTMZjT7lNTdBLJyr NEORZkXGVZl0Js4X1nb2oR9JqiAlfphWZHxRdVkCKGtNv3PWZpZ8F449rYbmYiuNor2Ld8c+wUI 9t6OT8lPvLhkCz4RdqSTbECWaiVtJAiHWRgIvVH8LLdQ/v/8Gs9YaVK45+wzC1njiJdNLt0vPa5 MWCkg== X-Google-Smtp-Source: AGHT+IGcWhzJBO2L5Al6zpkMFC0ws+AAOa45xxwnHeRxra6E2mmlTLUqG6m1lew8WR6uSrq0euRG+Q== X-Received: by 2002:a05:600c:474b:b0:477:8b2e:aa8f with SMTP id 5b1f17b1804b1-477c0181287mr253291615e9.15.1764211066059; Wed, 26 Nov 2025 18:37:46 -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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.37.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:37:44 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Kieran Bingham Subject: [PATCH v5 01/24] libcamera: software_isp: gbm: Add a GBM helper class for GPU surface access Date: Thu, 27 Nov 2025 02:37:16 +0000 Message-ID: <20251127023739.179652-2-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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 Signed-off-by: Bryan O'Donoghue --- include/libcamera/internal/gbm.h | 39 ++++++++ include/libcamera/internal/meson.build | 1 + src/libcamera/gbm.cpp | 130 +++++++++++++++++++++++++ src/libcamera/meson.build | 11 +++ 4 files changed, 181 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..6852def58 --- /dev/null +++ b/include/libcamera/internal/gbm.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Linaro Ltd. + * + * Authors: + * Bryan O'Donoghue + * + * gbm.h - Helper class for managing GBM interactions. + */ + +#pragma once + +#include + +#include + +#include + +namespace libcamera { + +LOG_DECLARE_CATEGORY(GBM) + +class GBM +{ +public: + GBM(); + ~GBM(); + + int createDevice(); + struct gbm_device *getDevice(); + PixelFormat getPixelFormat(); + +private: + int fd_; + struct gbm_device *gbm_device_; + 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..7d53cd43e --- /dev/null +++ b/src/libcamera/gbm.cpp @@ -0,0 +1,130 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Linaro Ltd. + * + * Authors: + * Bryan O'Donoghue + * + * egl.cpp - 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::gbm_device_ + *\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 unitialised state. + */ +GBM::GBM() +{ + fd_ = 0; + gbm_device_ = NULL; +} + +/** + *\brief GBM destructor + * + * Cleans up the GBM device if it was successfully created, and closes + * the associated file descriptor. + */ +GBM::~GBM() +{ + if (gbm_device_) + gbm_device_destroy(gbm_device_); +} + +/** + * \brief Create and initialize a GBM device + * + * 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"; //TODO: get from an env or config setting + + fd_ = open(dri_node, O_RDWR | O_CLOEXEC); + if (fd_ < 0) { + LOG(GBM, Error) << "Open " << dri_node << " fail " << fd_; + return fd_; + } + + gbm_device_ = gbm_create_device(fd_); + if (!gbm_device_) { + LOG(GBM, Error) << "gbm_crate_device fail"; + goto fail; + } + + format_ = libcamera::formats::ARGB8888; + + return 0; +fail: + close(fd_); + return -errno; +} + +/** + * \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 * GBM::getDevice() +{ + return gbm_device_; +} + +/** + * \brief Retrieve the pixel format + * + * \return The PixelFormat used by this GBM instance (ARGB8888) + */ + +PixelFormat GBM::getPixelFormat() +{ + return format_; +} +} //namespace libcamera diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 90d434a5a..4eaa42062 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -70,6 +70,16 @@ libcamera_deps = [] libatomic = cc.find_library('atomic', required : false) libthreads = dependency('threads') +libgbm = cc.find_library('gbm', required: false) +gbm_works = cc.check_header('gbm.h', required: false) + +if libgbm.found() and gbm_works + config_h.set('HAVE_GBM', 1) + libcamera_internal_sources += files([ + 'gbm.cpp', + ]) +endif + subdir('base') subdir('converter') subdir('ipa') @@ -178,6 +188,7 @@ libcamera_deps += [ libcamera_base_private, libcrypto, libdl, + libgbm, liblttng, libudev, libyaml, From patchwork Thu Nov 27 02:37:17 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25239 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 98422C3257 for ; Thu, 27 Nov 2025 02:37:51 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3A9EA60AA3; Thu, 27 Nov 2025 03:37:51 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="h2peUL3r"; 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 93A00609DE for ; Thu, 27 Nov 2025 03:37:49 +0100 (CET) Received: by mail-wm1-x32d.google.com with SMTP id 5b1f17b1804b1-4779a637712so1782855e9.1 for ; Wed, 26 Nov 2025 18:37:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211069; x=1764815869; 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=ZO55zerjaQrCQZrZcEbeB5YVLisBVaTOEyxQCUPAczg=; b=h2peUL3rkyNEjLQHCsDPU6VJKH+1S3gRB6YI2kB/Tlc93UGzr2tt7nspB/cSnhnNWo skS2HaZeWh4RjPdlqzWgkmOC6ugfn7eu2A5YtCJGzjZYgO/qH6/reiZ3XyBAoORMeWYX Y/7qN8GPeG0xDdvAy6cbzbvU4q8lWM56PUmg0EYwb+I3asTwIC4hFbDl0hMFliQLzi13 tuQ/Mt0mQzPkC5rxXcDp8k2ZVoPcm2STd3Zd9VgQzt0fp/DC7+UtVtVdR9RMX/IN0I2a MW0VkPxaCn4qm67P1UlUoQ0lEg0imwaUZx5yvHVsYfIWBCCNRIaCWfmp37Vi8SuLGajV lXkA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211069; x=1764815869; 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=ZO55zerjaQrCQZrZcEbeB5YVLisBVaTOEyxQCUPAczg=; b=IBGNZbCLekeovigiYPpY+OvuVekPxU+QjrCvr3uWhnav70h7mxfBD/WH2B4NMJ0YL8 HgLRJ4GGXaEIr50hQgeZXaZbMRt8rdizU2/g462OiHDilwzwJ4BVQ6jAd/33FkQqCRd/ dq6EA/HiAx8vWxPZo6rxCIqmnXPDZBFe8tAvdOrd04irYBnGOhiUuYjIDUz8GQu/Q0KB TvueP8PQm4rzTmlQ0wtqPbkyeyfa0ztSdmQh/jss2QtxKNDPg8zSYEbo6rQeBjaqycTl Yc86unJoFaQT7KG1tdSkAo++EdlpRrVqLxnJbTpcj9TMKWoCfKwltB1Vlrw7kKwZBD7w mLSw== X-Gm-Message-State: AOJu0YxdkTZ6GcfUnVXw5VgwRLIS/6ARpvGo4qXJ3wALbIw1yQzNtPA2 q1PmnyXkie2UoBten5qVUJS2lG92JNMDvydTve1FoHjtgoR6qOKK/Hrx2LhTzdk0eGpa6EpSNLy Q7JXcF2s= X-Gm-Gg: ASbGncv078ptvtU4stZzqiDX+ygLkhYtMhOQtSw8xa4bBcIStc2u3IM7NeEUN9bIjDq fRaARH5aZeyzor4qlkY24sjDAb01fLzzpW62L4/E6ZCXsnxYEICHH/FyLsE6pSaBK7AUvOVFBrF tj+ZqvIEWsE//FlP2TSQEn5KGbSZ+dSQSqE9JlUkhwyraAUul2L6iOL9dpJd4Gj/7uzr1RstNn4 fr8fS8rV+ggIX24oyGIxS7WyoGKS8OSEJ6xZIe1eQ16h2+8vIdEbvzqMdJPAHH13KF0BU70asun bpmSlznrM3q/E12BnTBHCa30GfBMiNbJodAYJpNLpXflwY2Zh8qljGpsXx6PoDLs5qQ4kk5USGk AqjFJtHXGTSM9HhXaidPdp757420jz216N1y10A84Eie97+kRJ4yqoBYv17TrXtJdTPaJ36GgAC gzkG9kxk2j+UlANn5YhzZf7l3rFfVj821/l8BF+6gesMHz/OwMwxiNA5DMiivnVqAidbE= X-Google-Smtp-Source: AGHT+IEPMyWWlp5qO0YP8BR0NZdKGrCbVo8KvIV1vWODbS3izuubd8gs6N4LSNmSjjGnVawCoaydLw== X-Received: by 2002:a05:600c:5491:b0:46e:32d4:46a1 with SMTP id 5b1f17b1804b1-477c01c36d7mr196998085e9.22.1764211068978; Wed, 26 Nov 2025 18:37:48 -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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.37.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:37:47 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v5 02/24] libcamera: software_isp: Make isStandardBayerOrder static Date: Thu, 27 Nov 2025 02:37:17 +0000 Message-ID: <20251127023739.179652-3-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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 this member function static so that it may be called from static members of derived classes. Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/debayer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h index 088b062c0..2763b0699 100644 --- a/src/libcamera/software_isp/debayer.h +++ b/src/libcamera/software_isp/debayer.h @@ -90,7 +90,7 @@ private: protected: void setParams(DebayerParams ¶ms); void dmaSyncBegin(std::vector &dmaSyncers, FrameBuffer *input, FrameBuffer *output); - bool isStandardBayerOrder(BayerFormat::Order order); + static bool isStandardBayerOrder(BayerFormat::Order order); }; } /* namespace libcamera */ From patchwork Thu Nov 27 02:37:18 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25240 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 37734C3257 for ; Thu, 27 Nov 2025 02:37:54 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E736460AA3; Thu, 27 Nov 2025 03:37:53 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="oWE3wAgW"; dkim-atps=neutral Received: from mail-wm1-x335.google.com (mail-wm1-x335.google.com [IPv6:2a00:1450:4864:20::335]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 97E02609DE for ; Thu, 27 Nov 2025 03:37:52 +0100 (CET) Received: by mail-wm1-x335.google.com with SMTP id 5b1f17b1804b1-47118259fd8so2249465e9.3 for ; Wed, 26 Nov 2025 18:37:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211072; x=1764815872; 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=wPrNN6No60iynnuJevpIExcWRJy7ztNAUo4+/Jfj+No=; b=oWE3wAgWAIyllMpX1v7d3lKJN4QgnR705D7Vm9myafi/Pg5ZqLx6d+d/X6TOfL6MV9 QBBWua5X07PVgmk8W2+ZD4eFGaLfITGpnjxxGMtr+Wk/dugXA63fQzWsw+YavqQQeAaE 7EO9OecSlunxkPGy9hogOxtE5JTmpSwswdO7Ak8oBd6bmO+5M4rAdIXtoE8nf/M+IXjq OR1UztATbFfYqWlnWjR7I92U/pt5wGlGQfWhru2y4/BrBKomxLc/jywoE5TpHufLoe4g +TIWlDwFL84cWIE561sljM06Qyjf/DLjtFh5C7dkLpFgcsvc3uAgefgmX8v6xNnSJLVu QS6g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211072; x=1764815872; 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=wPrNN6No60iynnuJevpIExcWRJy7ztNAUo4+/Jfj+No=; b=sXEylutd2xt3engk7wuy0JKkSXA/CJYLEj+Y6xl+xCNBOLDOd3/0Q9rMQzM2DvEd4s mI2TJLlJz43N5sNrzJ5ATUjr8QDHFv7pmcrDha2G3mVBRKOmCizfgplYCD1nGoUDZ+T/ FjtO7Y52j4gKk/bSI2kFifTyQndx+cp7mxuMfle4flnpX794S5EVRFbgQfwa0JcMhWCK km3GOOVyiIFBRfj0VPVrkYbzO5jx3LXjDtQhQVtwOjxiASqo8MuK081FmeOcZ9HnTq2+ ecRqKZ1pXaffT/WklQS6YcGZPXn+hXRBDYOTi53/KmLCQkGVpzIqoYktGXGUKsB0XcT1 nyJg== X-Gm-Message-State: AOJu0YyvTJSMUtYAP8LkgXsMWpYgVfTsZi/QMZF2b1E4nq4yl2AUUvHK U97uv0Wek6p+Nrq5dXvHzduSUKZEAcETcBsYQqV9pCJH7DhDSzKk69PzccFX2tHl8bbhAm649iD 4DGVJnS8= X-Gm-Gg: ASbGncsw5sU4AhhPdDfalmpDvDnEGDwnaqFbEMpTs9lcsOjzkuWcjvqDEnJtS7LdQHk ThG+vNelIh53UpVnbXdliKN2xzkZMLqQaspeY/gSZAWV9/dIk7PyiimNwmOPQZ/ZvzEIG0mbX7P dI8BLTmdXabxIEwtlt0hA7pQ5/MAug9hutNeAUmFfJJMHrQ+vTM0fOJ/RsedTEDbiW36w30Mvur DvmacAwP1v6q/Zz+eKGqlp9ftUsh1tkJCedvIhILMNacViZlq7vkvh684DOrexkRIF/zeD9Dntj UrFU2FV+QAQ5qcy8IgH66vKxB/ztHVZhdI5c2J44uFwl44YIb12to5PtnBt1X5PPhdZDNQHmoTF m0mNzQHun2bHRA13fBVsm7ujymppN9T8IIvamN+jwrzVngC2FjRYiCVYKAiM7LS36aCuZ44BXcy oXYTzy0EiezrpUczc8zaKAolqVTZOlpK3M54+5GPRpyIlkaYgUVIk3vQaMlNJ/a6wBheE= X-Google-Smtp-Source: AGHT+IFnA7lejV1xHCTp87svy1dSchmOEHfcnL04O+eHttRs7xKrg9iDIvoLRst3qZkPb4HNGYwhXA== X-Received: by 2002:a05:600c:c8c:b0:471:d2f:7987 with SMTP id 5b1f17b1804b1-47904b23c04mr76973245e9.26.1764211071803; Wed, 26 Nov 2025 18:37:51 -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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.37.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:37:50 -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 Subject: [PATCH v5 03/24] libcamera: software_isp: egl: Add a eGL base helper class Date: Thu, 27 Nov 2025 02:37:18 +0000 Message-ID: <20251127023739.179652-4-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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 Signed-off-by: Bryan O'Donoghue --- include/libcamera/internal/egl.h | 192 ++++++++++ src/libcamera/egl.cpp | 620 +++++++++++++++++++++++++++++++ src/libcamera/meson.build | 23 ++ 3 files changed, 835 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..3822e61b0 --- /dev/null +++ b/include/libcamera/internal/egl.h @@ -0,0 +1,192 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Linaro Ltd. + * + * Authors: + * Bryan O'Donoghue + * + * egl_context.cpp - Helper class for managing eGL interactions. + */ + +#pragma once + +#include +#include + +#include +#include + +#include "libcamera/base/utils.h" +#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 (e.g., GL_TEXTURE0) + * \param[in] texture_unit_uniform_id Shader uniform ID for this texture unit + * + * Creates an eGLImage with the specified dimensions and stride. The stride + * may differ from width * bpp due to alignment. + */ + eGLImage(uint32_t width, uint32_t height, uint32_t bpp, uint32_t stride, GLenum texture_unit, uint32_t texture_unit_uniform_id) + { + init(width, height, bpp, stride, texture_unit, texture_unit_uniform_id); + } + /** + * \brief Construct an eGLImage with automatic stride calculation + * \param[in] width Image width in pixels + * \param[in] height Image height in pixels + * \param[in] bpp Bytes per pixel + * \param[in] texture_unit OpenGL texture unit (e.g., GL_TEXTURE0) + * \param[in] texture_unit_uniform_id Shader uniform ID for this texture unit + * + * Creates an eGLImage with automatic stride calculation. The stride is + * aligned to 256 bytes because 256 byte alignment is a common baseline alignment for GPUs. + */ + eGLImage(uint32_t width, uint32_t height, uint32_t bpp, GLenum texture_unit, uint32_t texture_unit_uniform_id) + { + uint32_t stride = libcamera::utils::alignUp(width * bpp / 8, 256); + + init(width, height, bpp, stride, 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) + + /** + * \brief Initialise eGLImage state + * \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 + * + * Common initialisation routine called by both constructors. Sets up + * member variables and generates OpenGL texture and framebuffer objects. + */ + void init(uint32_t width, uint32_t height, uint32_t bpp, uint32_t stride, GLenum texture_unit, uint32_t texture_unit_uniform_id) + { + image_ = EGL_NO_IMAGE_KHR; + width_ = width; + height_ = height; + bpp_ = bpp; + stride_ = stride; + framesize_ = stride_ * height_; + texture_unit_ = texture_unit; + texture_unit_uniform_id_ = texture_unit_uniform_id; + + glGenTextures(1, &texture_); + glGenFramebuffers(1, &fbo_); + } +}; + +class eGL +{ +public: + eGL(); + ~eGL(); + + int initEGLContext(GBM *gbmContext); + void cleanUp(); + + int createInputDMABufTexture2D(std::unique_ptr &eglImage, int fd); + int createOutputDMABufTexture2D(std::unique_ptr &eglImage, int fd); + void destroyDMABufTexture(std::unique_ptr &eglImage); + void createTexture2D(std::unique_ptr &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, unsigned char *shaderData, + unsigned int shaderDataLen, + Span shaderEnv); + int compileFragmentShader(GLuint &shaderId, 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); + int syncOutput(); + +private: + LIBCAMERA_DISABLE_COPY_AND_MOVE(eGL) + + pid_t tid_; + + EGLDisplay display_; + EGLContext context_; + EGLSurface surface_; + + int compileShader(int shaderType, GLuint &shaderId, unsigned char *shaderData, + unsigned int shaderDataLen, + Span shaderEnv); + + int createDMABufTexture2D(std::unique_ptr &eglImage, int fd, bool output); + + PFNEGLEXPORTDMABUFIMAGEMESAPROC eglExportDMABUFImageMESA; + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; + + PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; + PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; + + PFNEGLCREATESYNCKHRPROC eglCreateSyncKHR; + PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR; + PFNEGLCLIENTWAITSYNCKHRPROC eglClientWaitSyncKHR; +}; +} //namespace libcamera diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp new file mode 100644 index 000000000..fc56f5d22 --- /dev/null +++ b/src/libcamera/egl.cpp @@ -0,0 +1,620 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Linaro Ltd. + * + * Authors: + * Bryan O'Donoghue + * + * egl.cpp - Helper class for managing eGL interactions. + */ + +#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() +{ + context_ = EGL_NO_CONTEXT; + surface_ = EGL_NO_SURFACE; + display_ = EGL_NO_DISPLAY; +} + +/** + * \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. + * + * \return 0 on success + */ +int eGL::syncOutput(void) +{ + ASSERT(tid_ == Thread::currentId()); + + glFinish(); + + return 0; +} + +/** + * \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(std::unique_ptr &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(std::unique_ptr &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(std::unique_ptr &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(std::unique_ptr &eglImage) +{ + eglDestroyImage(display_, eglImage->image_); +} + + +/** + * \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(std::unique_ptr &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 + * - eglCreateSyncKHR / eglDestroySyncKHR / eglClientWaitSyncKHR + * + * \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->getDevice()); + 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(void) {} + + +/** + * \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(void) +{ + 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, 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, 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, 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; + + ASSERT(tid_ == Thread::currentId()); + + programId = glCreateProgram(); + if (!programId) + goto fail; + + glAttachShader(programId, vertexshaderId); + if ((err = glGetError()) != GL_NO_ERROR) { + LOG(eGL, Error) << "Attach compute vertex shader fail"; + goto fail; + } + + glAttachShader(programId, fragmentshaderId); + if ((err = glGetError()) != GL_NO_ERROR) { + LOG(eGL, Error) << "Attach compute vertex shader fail"; + goto fail; + } + + glLinkProgram(programId); + if ((err = glGetError()) != GL_NO_ERROR) { + LOG(eGL, Error) << "Link program fail"; + goto fail; + } + + glDetachShader(programId, fragmentshaderId); + glDetachShader(programId, vertexshaderId); + + // Check status + glGetProgramiv(programId, GL_LINK_STATUS, &success); + if (success == GL_FALSE) { + GLint sizeLog = 0; + GLchar *infoLog; + + glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &sizeLog); + infoLog = new GLchar[sizeLog]; + + glGetProgramInfoLog(programId, sizeLog, &sizeLog, infoLog); + LOG(eGL, Error) << infoLog; + + delete[] infoLog; + goto fail; + } + + return 0; +fail: + if (programId) + glDeleteProgram(programId); + + return -ENODEV; +} +} // namespace libcamera diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 4eaa42062..e19898a0b 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -80,6 +80,27 @@ if libgbm.found() and gbm_works ]) endif +libegl = cc.find_library('EGL', required : false) +libglesv2 = cc.find_library('GLESv2', required : false) +mesa_works = cc.check_header('EGL/egl.h', required: false) + +if libegl.found() and mesa_works + config_h.set('HAVE_LIBEGL', 1) +endif + +if libglesv2.found() and mesa_works + 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') @@ -188,7 +209,9 @@ libcamera_deps += [ libcamera_base_private, libcrypto, libdl, + libegl, libgbm, + libglesv2, liblttng, libudev, libyaml, From patchwork Thu Nov 27 02:37:19 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25241 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 30ADEC3257 for ; Thu, 27 Nov 2025 02:37:57 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D3FDF60AB1; Thu, 27 Nov 2025 03:37:56 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="TdpOOZze"; dkim-atps=neutral Received: from mail-wm1-x330.google.com (mail-wm1-x330.google.com [IPv6:2a00:1450:4864:20::330]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C8E62609DE for ; Thu, 27 Nov 2025 03:37:54 +0100 (CET) Received: by mail-wm1-x330.google.com with SMTP id 5b1f17b1804b1-47796a837c7so1861955e9.0 for ; Wed, 26 Nov 2025 18:37:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211074; x=1764815874; 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=H5BShESTnB/MbwTFxOodjFsYW/bRikVrhmyhH5umiF8=; b=TdpOOZze7obc7NMTqFuM+WwvQkHO980oM7GUTLJ2GFvT71iI5ivvZGhaXRzcGeyj2J 1HuaF+GSC1AZdhBZMzVrikTIaQrvE38lQ/lTf5Qnj01lIi+ksmfBz9VYjbCa1ayus/0k kyJIUjrSZKygIe9du/G3fzE3LBe8+yRByE0uTvn0bGHNf+Pu3cSYfyCGphzO9WTFr37Q sPW8zWdd2UGxg2+D5g43/k/M6AB7s0XYnpPIEEcKyJu70g1r8DyJqKOPZqrk/EaJZmsA q4ZldhbNNYxeXcKJTWouTfj84JmLx9RaP5i8F9fpJddIaFlcpNQaNQ+0qVk8umSkyHH8 B+3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211074; x=1764815874; 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=H5BShESTnB/MbwTFxOodjFsYW/bRikVrhmyhH5umiF8=; b=uQaVw+IEGM0RPdjZM21MkqxerKrWogRHVehZQA4otsvTaaOo638/1UkW/50GI+4rPJ YPfcKKmMnucf8w/mMOWyTueOzaiJ12VLoUUSwkvTezndv2r5mYrtmmrmzeuKjhJLj5XC GzfB9m65IWfd3NlAZG+H/vAAcVzDFqKCYJthDXx7/ZGEt4iVgWJt3IkIR/BJkzMyuAv1 vI/KhdtOCLDIC/LqMHWrdwXwlfANGeijnAByRUfiKYyU4VObW6HWiDcHz0s+huk3YHYj PV95LWXzm5kWgbGTokrR0MPJ1x2D7J7z5fnfDG2AoK8kc/+akaEB05t51eaUWFDguThg eKOg== X-Gm-Message-State: AOJu0YzPZ3MxBFA3pTWYkVQSZhAvr7Oq/eRfPl3ZEOKkkmJxcxQ9yAI2 /dKp5rslQU/hZsk//aC6eD/4Qg/PKQo7x91DS9OZjd+EW8bAcYAmvyBePAmaD0So/Pv9R4W5+FO ukZ5zzes= X-Gm-Gg: ASbGncup4arawJTadrCdchE2Ved51QylpGUAsv/zAooklEOxc8/UNie4LehoWgHZngG 7G73eKV6V5he0MO0QSjJBKgFNTBhNDAERMUhP31nO++yrANgc1hOEyYHGNYOXjdyoPhzUNdktsR tlpiJaiCLczphMAsw8sPbWLDoDD8qb6bJBlUWovv/Fb4liwOVdaDTb8/eg+XfNJrodDsYB8lYBo YmUBik+ZKkAjr49lm6eTiJg9WouZ7iUqCL8lubOMuKIF9iXj2qgidQ8yP3CW1tGHAWM/vNWnm9L oYVixO1WStzpT0IHB5wm3MKFWtxr9heEGcxRKS5jwInJbU7TpM3uAr/siRW5DX0vcHOPNJvqVcQ Mu3PIjptUq8OJ51ZZvolxrDbF589XZ8YneEnDCF1vmXAPhqiW9VuScqR2Q83dAwNdLFtZAJJnDS EEzJKrIcmrOZjo8hBEuz+zrHvWjQiLDNyo9+iDRxu6+YAzqrtE93xZv69igH81HteOm+Uz22E1e aD1NA== X-Google-Smtp-Source: AGHT+IEL/kmIbL+KeAF1if82xyP20U6ve1NzbERLhte1Yh7aUs38gS7/IjndlaaXMmUVHPF8dM6MHg== X-Received: by 2002:a05:600c:2296:b0:477:73e9:dbe7 with SMTP id 5b1f17b1804b1-477d24871d6mr86409195e9.35.1764211073989; Wed, 26 Nov 2025 18:37:53 -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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.37.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:37:53 -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 v5 04/24] libcamera: shaders: Rename bayer_8 to bayer_unpacked Date: Thu, 27 Nov 2025 02:37:19 +0000 Message-ID: <20251127023739.179652-5-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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 1554c94d5..b0c8ecaf8 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 Thu Nov 27 02:37:20 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25242 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 107D8C32DE for ; Thu, 27 Nov 2025 02:37:59 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A94C560AA3; Thu, 27 Nov 2025 03:37:58 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="B8dlZb+v"; dkim-atps=neutral Received: from mail-wm1-x331.google.com (mail-wm1-x331.google.com [IPv6:2a00:1450:4864:20::331]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4A66460AB3 for ; Thu, 27 Nov 2025 03:37:57 +0100 (CET) Received: by mail-wm1-x331.google.com with SMTP id 5b1f17b1804b1-4779adb38d3so1789925e9.2 for ; Wed, 26 Nov 2025 18:37:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211076; x=1764815876; 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=mt8VuycA4JtISYG1OMwP/mShybOjaHrIEZw7TC7UHZg=; b=B8dlZb+vi/Ay031On+rNdj2DvCD2bItylXo0jzsudJjv8/OOHF6bUN7Y3FCzbXpDvg ViYDiwB3ZKmWUEdJYJAKxrgLtJdVbqXl2prgTuMAwgTDuWdCZl2yC0SErPw8Df3cyBCl SgGtTI+8MnWcOaF3oPCdYYDnZ6qQF1nHPETpxp02XB/uXCWqtj0/WOKRhXxVaI1qKP1h 7HjSGrOQq/VnvP5MFi3AcdZrYMdKJKJZjhxPwPXbtpHwW8OoRI7WTnKE4hG9hOOmLicN PQD/2sswinHyHO4pxdIL/VHo5KaRo58y56Gc/m1Xe95OPnxBta5Emc0e0jZYyIOdJOZL mVjw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211076; x=1764815876; 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=mt8VuycA4JtISYG1OMwP/mShybOjaHrIEZw7TC7UHZg=; b=xUXtBk3pded9qS7fk0XZyAMSf4VOxkMyPHbBBTHypJmfNqnB/VMkk7HayDYbyLtplT W42uOdjZoLM7ILxke9VfBDjrEpDh5k3vp5zlXjsjeIMXYgbK7SKeEILFaww+paOBmFkC xHz8Vtafuh3KsX/hziMSRAIgrVwjs4oqepqwQLL9jlzA1iA7pH/McQm/U/+ujkRE+A5y 4LilcXRY1TknYBUIAnkV3Av7sCyhRJZl+M4/DiD/xYndD9yinqM4J9zbHN9jmdNNUk9U k1ab4dO5v5GQgpMK0KNydtik65YYA3gh6VJgqyphey5Z8rFCSfPepK0OgGhXD/E5nI4h kaEw== X-Gm-Message-State: AOJu0Ywxh9WL04QT1jR3RymkqAEFA4OyfXzWECQ3juZ/Uz2JveuQTpYJ r+PDiJJnlsFz6J2j/VOArLvKhfG/OIYz1isIQ/fR7USKEErX7B8clQ1jkkm6M+BYg5pRJZCK2Fp lfhsb8f4= X-Gm-Gg: ASbGncvU5bRgbE/65FZQIgTUXdMgvuOumxFKZbUr2w31jAphypEqm/BWd9cb/vs88TQ BuJR64cLL+z/BkrXUFkPD/6BI57RX3ohKEG5o2QrETtiauBKp0tnrLyPuo6mFjEwoIGqkPwHXSe Ut5cNG0SsJ4Gr99qzfoYEc+TlWN2WCokLlIDeKr3X6ITDIrXUjEvxPwuPCuRhw9g6/fwoNFY1vO mpMP4klii2V8sUA4SQ11VvjaCx00C8wwZ7kLtMCf6vvJQD2xRyLvDjFbmsjoL68m7Uq6aoVMqmL OwQr9d7fV2Zo3rc+CM4SOl0+0RKQnm+8YCKzj3PO5gz6wNkSelFshzPvGAKlIFyTVUCFj6+i3Ke pwL3aW91kdYm+aYPNX7b09M3iD1VQM0e30B1Y/eGXyWYaV995pGgIzxhv54zf6KdlLUNKY6BO3G NTXrBpt6Glgy8hlXKrt/ctBIGdAS/4mTG/rTlcIx9KCHFleJVpRhxYAGojKCjlUDd6oNA= X-Google-Smtp-Source: AGHT+IGq2QWxaAkfBfeUaCBFNkzwKce5lSkNq+FVdton/7mygJouvmW/lA/LWh+KA6euzoZJLwsxbQ== X-Received: by 2002:a05:600c:1c0d:b0:477:9a28:b0a4 with SMTP id 5b1f17b1804b1-47904a6867fmr102638375e9.0.1764211076603; Wed, 26 Nov 2025 18:37:56 -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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.37.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:37:56 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Kieran Bingham Subject: [PATCH v5 05/24] libcamera: shaders: Use highp not mediump for float precision Date: Thu, 27 Nov 2025 02:37:20 +0000 Message-ID: <20251127023739.179652-6-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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 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 Thu Nov 27 02:37:21 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25243 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 ED252C3257 for ; Thu, 27 Nov 2025 02:38:00 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8207560A8B; Thu, 27 Nov 2025 03:38:00 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="wJ2aDUdV"; dkim-atps=neutral Received: from mail-wm1-x334.google.com (mail-wm1-x334.google.com [IPv6:2a00:1450:4864:20::334]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DC1C7609DE for ; Thu, 27 Nov 2025 03:37:59 +0100 (CET) Received: by mail-wm1-x334.google.com with SMTP id 5b1f17b1804b1-4779cb0a33fso2934895e9.0 for ; Wed, 26 Nov 2025 18:37:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211079; x=1764815879; 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=e9cIZnLKMjoKTXRCg5aiS+zFbq3BqFPUvk7OeX1bh1o=; b=wJ2aDUdVEURmhk4MxHaW1IAPZjA1cWUJhsPAdT0xcj/ThsLMZ5FjYHqdiAnDyb38Nu 8hg2kd5yZ00yISjR2DHabLzoy3AlEYqDJYalTEeGBWDxORW0fftHeAGUxSxW6cFl0vMn dqe9ATnhmrW+hVARTt6yTOC3HMeqPoX/3Q+CkXJpNDLaOkQggHNvtrxBPXyyeCMSfyaR wf3pVEZam16tczaob5VmThhFvh1q2R3PnAYAhy9QeMKTWHk06J886F8AiXTeYQCH5jV+ OWSuc1Ax1BGEX5csd/MaN37r9tuVXrWXKarRGvAkXFV1+gEOYSy6OHEi3NBwf1sQw8G5 1OeQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211079; x=1764815879; 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=e9cIZnLKMjoKTXRCg5aiS+zFbq3BqFPUvk7OeX1bh1o=; b=Guoh1cyzkXhRibvcFJnreE3/KMg+HjhF/0wiPeLbRYvrQdT7GuIBrmPrJkhXKwtDMb kn7vkoTljLmJwNHOH644YXa8cPrzK0h++OhfCpqZQCXYYTtcWOF5PcBjDPIinleiH19+ THA8bW1AuFeN5iTisFSGYMYjGl5WbuCD0kENeXHW6tZK5slBz46JkmBFdBXdizyL+jTS d8DoL/HSs7Jm1Ebm8VysKS52UB/vxvpwOWc6drdicOucHsesTGBwvodVayQFB6AeFa/5 TMJI07kt765SZ8SVG18xfG9hdwQVdfPhBQ+bz/pEnn7LtppEPSifIRCNUIjbCBBOVvX3 p3Iw== X-Gm-Message-State: AOJu0YzhEKGS5zZ4HKLqyf3uOpLvt7zz0vsAHBOBbDNBr9Wgu8KFUZrS 9VvP6LXUsDiJd067kcelzKb+5O/RcgzBUwpzBxzImcmx9O4+OUl2qZ+6S7JeddF8wiPiGmFGVoJ JiaRGHjQ= X-Gm-Gg: ASbGncuS2O5UjOgwMn2P6ymvPh5PQrGRFEQLt1h1R0CkUnX/Byaoc3v9VtKdyLaIJTL FITifkUlo5x96cH1aFDA4NIvBRci1PCFjlTjRPKAjp27R4ZjTa5/88QEN/zsrpZJTXq9CfZxpCB JJeYI/rgUGGCwx+neJ2dRoNnZXD/IZLoeC0yNCkDbc2LN5YTr4dQgOpgfqnIziouQNUb8tcUAlz SE/6Kan+DzHiZo4I7Al4BTIkz9WEyGUlxmfdTdn2D9LrGTz9uugiKfbR24qVq+OwWb1mfKbjiYb yszpqCJECUSSLEmr8+wbOBcvDiiDXzu+vJxXabCbz2wa0KVqHTROAnz05NYhxRE7ugEZbA0sLv/ Zg4+olVOZ6bLRDR8srcfR2fN9a9TL3PvYfwUad1HNSTD5wSzN5pNcDXO/pB7BtzrnJX3MCRMsAj AEMg8XD7O5kdeb22ZdL9Fv5GXKDbHDq63UvdDV/pAAns6GNhNFR7+/DFHdzKbGJrRjlvQ= X-Google-Smtp-Source: AGHT+IFlikomhw7T7nYeCMvg7tDZh2fVX/tgwOtdygivyYRPqkLr4VDCaYkpQCbtXCrnjZqc1/ySVg== X-Received: by 2002:a05:600c:3110:b0:477:b734:8c52 with SMTP id 5b1f17b1804b1-477c0185bebmr233215005e9.14.1764211079244; Wed, 26 Nov 2025 18:37:59 -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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.37.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:37:58 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v5 06/24] libcamera: shaders: Extend debayer shaders to apply RGB gain values on output Date: Thu, 27 Nov 2025 02:37:21 +0000 Message-ID: <20251127023739.179652-7-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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 out the bayer fragment shaders to take 3 x 256 byte inputs as textures from the CPU. We then use an index to the table to recover the colour-corrected values provided by the SoftIPA thread. Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/libcamera/shaders/bayer_1x_packed.frag | 56 +++++++++++++++++++ src/libcamera/shaders/bayer_unpacked.frag | 62 +++++++++++++++++++++- 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag index 19b13ad08..90bd64570 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -65,6 +65,10 @@ uniform vec2 tex_step; uniform vec2 tex_bayer_first_red; uniform sampler2D tex_y; +uniform sampler2D red_param; +uniform sampler2D green_param; +uniform sampler2D blue_param; +uniform mat3 ccm; void main(void) { @@ -212,5 +216,57 @@ void main(void) vec3(patterns.y, C, patterns.x) : vec3(patterns.wz, C)); +#if defined(APPLY_CCM_PARAMETERS) + /* + * 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]); + +#elif defined(APPLY_RGB_PARAMETERS) + /* Apply bayer params */ + rgb.r = texture2D(red_param, vec2(rgb.r, 0.5)).r; + rgb.g = texture2D(green_param, vec2(rgb.g, 0.5)).g; + rgb.b = texture2D(blue_param, vec2(rgb.b, 0.5)).b; +#endif + gl_FragColor = vec4(rgb, 1.0); } diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag index aa7a1b004..924c477de 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -21,11 +21,17 @@ precision highp float; /** Monochrome RGBA or GL_LUMINANCE Bayer encoded texture.*/ uniform sampler2D tex_y; +uniform sampler2D red_param; +uniform sampler2D green_param; +uniform sampler2D blue_param; 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 +103,65 @@ 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)); + +#if defined(APPLY_CCM_PARAMETERS) + /* + * 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]); + +#elif defined(APPLY_RGB_PARAMETERS) + /* Apply bayer params */ + rgb.r = texture2D(red_param, vec2(rgb.r, 0.5)).r; + rgb.g = texture2D(green_param, vec2(rgb.g, 0.5)).g; + rgb.b = texture2D(blue_param, vec2(rgb.b, 0.5)).b; +#endif + + gl_FragColor.rgb = rgb; } From patchwork Thu Nov 27 02:37:22 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25244 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 7FCE0C3257 for ; Thu, 27 Nov 2025 02:38:05 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 36F6260AB8; Thu, 27 Nov 2025 03:38:05 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="Hu6Va5YL"; dkim-atps=neutral Received: from mail-wm1-x335.google.com (mail-wm1-x335.google.com [IPv6:2a00:1450:4864:20::335]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DFA2C609DE for ; Thu, 27 Nov 2025 03:38:02 +0100 (CET) Received: by mail-wm1-x335.google.com with SMTP id 5b1f17b1804b1-47774d3536dso2827835e9.0 for ; Wed, 26 Nov 2025 18:38:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211082; x=1764815882; 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=5QzPnlwjhvESIFdxhKHBTYkka7xzVX4r9w83gKJuA78=; b=Hu6Va5YLJCLJKWOkB6T7fTDekXAyxBcWKCKnQhmBJULuLWKouj8oZKy5r2oG0Ygs25 67I3UF/kPOZN8yscJu0Aqu5NynDyfLsv0ndICgek7KBe8/Nzopi8zKckNyXjdbYFbm3q G19FTmN1yYz4ePi5nj1lGfaWYLRHmkhvlFaLu62cKzeyXMyQJx7QT0t+ZND4UpTvvE9p OtXYYuALHmd9eSoFAbHrY3t4cdLH+FvPPrWSK7o6GELqGGHvX+3Br313uOl5Kut9J5r7 YkuBN6XNJ8dMHEWSQGYT3S35RHePoWZPqDBFEgMIVyyb03yYcHtqShQFRLXySNkQBYdE K0Ng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211082; x=1764815882; 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=5QzPnlwjhvESIFdxhKHBTYkka7xzVX4r9w83gKJuA78=; b=Qx4ZEozJY4DilN4a39JSOK1kPTMnjkzw8H7ryH6CnMPW+xQ2+T/IivDX5k7KJZKMWH TG+TsVeIrQtg08mm6IcP2CVuGxHGUJRYUxwHPwp+WQv0cFf+Jag5QrmPGUXxewlSErR0 J75Iiy2uQ1v3Ftr+zo1L11aQGDwMSMH640SGlqmhTBywKo5kD1hZc/95AbNAk0MMuXOi rFGtPCqp8S2OCra7CNrgxW9F9tYUV/Z1cfqT9GMDKMGIS2jmAVY82lqcGUFYbc9MbjLs 5DjbotBNpr1aJri+1mcfG6/mdi5mjwu4WNx1sklXChtNg4hrRoZmbWVfjvB7A7rUXDxp s4tg== X-Gm-Message-State: AOJu0Yyr6U79BPQvtOn5TXMo6VUwwyTv9e3oPbKF15k76Nijf/RX5sxc qbcOE8EgErpkdX6KWFvgJiio4e9dzawZ8RbdH+C6nTWA/gVPSvRaH+oemL4ugim9TONrV2DSfkk hIpnehd8= X-Gm-Gg: ASbGncueHj77FyjjVKspBAmnGRaCMUQeqdiIxRbUZ0NuQwxvj1CkbKgcZBdAz75F5uM 2/OUFXLxENu53B0GtiMACXuH80w7dYDx6xjslrWTvgq7KnG82adx+ZL8bdYpOY27/QBWPDrtRfO Vfr/gs9FPDW+3uqCOfSU6XxC1XzBLsk5WCxgRFEJ6wEHE2PAgsL4NYYIJ/pUsXavUzkOGdc1s/H sXzuTFeyKMXeUyBO6IeEVsGSIdfMvEr6ror2jczYVADMPfv6fgyWuZ8oUePeDPAitz3SuAEC/ah ZasSguLG2a1ypQJ42DU1w0tZDWPh3WrVl4rTtA0PRDGydGOzZgu7fqW/+74NIII/QUFhb/upDHQ PDfwNR0XyGXZSZaAqURq0zHsm5ZOQvoCbH+iAC1UdemuCjM1DDgOLuLYwjNDgQefl/ckTeIqC37 hI5il1uJcrEZfxGqIW6DZkIdaaAFFIGWmwXiE9hQ28BPQeaGu/0tkYBbRKkoBkD/r1PA4= X-Google-Smtp-Source: AGHT+IGbxsIKDnFRrau5MUln2wamfa2a/F8oI8AOjW00WSVuKniYdze5ukkjRpEsNDjRTzAGc9ZmOg== X-Received: by 2002:a05:600c:628f:b0:477:bf1:8c82 with SMTP id 5b1f17b1804b1-477c053c90amr232096685e9.15.1764211082311; Wed, 26 Nov 2025 18:38:02 -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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.37.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:38:01 -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 v5 07/24] libcamera: shaders: Extend bayer shaders to support swapping R and B on output Date: Thu, 27 Nov 2025 02:37:22 +0000 Message-ID: <20251127023739.179652-8-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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 90bd64570..c0632eb1f 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -268,5 +268,9 @@ void main(void) rgb.b = texture2D(blue_param, vec2(rgb.b, 0.5)).b; #endif +#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 924c477de..a9996b94e 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -163,5 +163,9 @@ void main(void) { rgb.b = texture2D(blue_param, vec2(rgb.b, 0.5)).b; #endif - 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 Thu Nov 27 02:37:23 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25245 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 B093DC0F2A for ; Thu, 27 Nov 2025 02:38:07 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 371E460ABD; Thu, 27 Nov 2025 03:38:07 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="UuqsVFEs"; 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 52C8C609DE for ; Thu, 27 Nov 2025 03:38:04 +0100 (CET) Received: by mail-wm1-x32d.google.com with SMTP id 5b1f17b1804b1-4777771ed1aso1615485e9.2 for ; Wed, 26 Nov 2025 18:38:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211084; x=1764815884; 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=a4Z5xi4jidv2phyy2JrFxGl8iOtQb7kkkaWyXWfEsJk=; b=UuqsVFEsAqeu3wY4y6uWmPcAywTZhWZToBQJhgjR7JDl2I9ROwkmZqqcf98mYdod8o M3q1DNnkTz+sgTSWYo0xxxDNB4sVDIUQcKKnYJC1MgVJyqJ0P0EGuGqGVUNt3CgA/z5S qtV2FkREM4KzVPfsm0rdwxWKCy41fia71zPML/kBT71CQiYN/z1po512APl53YBiX2NI H7aYMzBHwz9bqbJicBE4KamKsKzK30qCyL1CGpO9tSEPr+Ao7nCwWNDnzAssY/Wq2ooQ oHjYv/zqwsS5dRv/X7nicK86IwMcrulnKIjFUFzMkYEzQj2qYMz5A8P2nJA9bh810qwU h0hg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211084; x=1764815884; 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=a4Z5xi4jidv2phyy2JrFxGl8iOtQb7kkkaWyXWfEsJk=; b=OWqJ3qcLKmgxdGDS0OvHGnAi/0OXEb9AxWWsgKPCFVL+f5TtjKgNkIb0MLr2Zes/cD GAhnQJGTD6yNrAnpPf4YZm+bsq163Sjy21p81aLsJkLnJTXpHIvHY0J8O9LGvrbCWyYJ GDDX2OrNNJaZBWH56Y9HTIzzHicAZyB6wQQLLONJzbNOQLKYMIpXQHuCYXXmRWzBjhbs FH1B/F5ak9Pd5/hs3ky5lKFkOX16LPsX61zhTqv/ukANT59FbXBc1chlMcccs/TcKJlR XHaDWLAs9aI82j1X51ZEUWC9gAoB0+VFWb/Jx8LLvsFnmjl7ZJYlNNjiLOUwimbHZxt0 6qyA== X-Gm-Message-State: AOJu0YwCJFrzszDyLZGw33yu6W58QuRtZpLG7yg2iuPjCMS7hhEq1TUt lCBudiqHBsjZ8L0Frw9jAi+ofzVDsaGa4l2Crju79U7zIYJBmKNx+uUrFDmUhlyYLw1ZYEwjACE iPXp1QaM= X-Gm-Gg: ASbGncvPSvyMwsxdksiOr6Bx8Ov2ZMuGQIwSI6xgH2R3EOvJl7fU5VPzllLws/SKDh4 KTMQEWAx+qo/75JSsQTbt0sN93nUnN5ltzYmdB7xWyCM+3WGEFT6TGIIDed2JW+ioNPZfQ+1ZrE SOVaYPWm/B/sshvfV53kI/zpoitBrqFv69qb2H1yOB+lTIcu+2f+C21bM+z2xv6lK/di5UwEI4l 4Em22/K8SGSZG3+HGgc7gAYazF783j8U3pQ8VyU4/PQ0mBBjUisMUIpXCaXomucAegFtVWZ0rzT PZZ2GqJoJ7GHTtCbFw+lRYHKG5ctuOqQm59CcHixBlfYHD1vovn2wCj7Z/XUWthEXy1wQWul9Dz qyvPuY/iiCtOGCHy3VkzyXP90fbZzylEy6El+2x70/jI+yWrVbm5OzuiJ31X1VRDOmj8sLrr6eh bGj5ZSl2BB2kL4dYce2lc60MUDyepySSU2KEPyFLMq94W9qhW02r9FSTY7Cdsa4yxlos4= X-Google-Smtp-Source: AGHT+IH92azTQU6T9RAid0GlJZFMQN6FvmT+wF5sn3rj90loHi7C9BAmy6nviH5Lzg0qe/HbCe1OAA== X-Received: by 2002:a05:600c:3146:b0:477:df7:b020 with SMTP id 5b1f17b1804b1-477c01b2211mr216760505e9.18.1764211083726; Wed, 26 Nov 2025 18:38: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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.38.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:38:03 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v5 08/24] libcamera: shaders: Add support for black level compenstation Date: Thu, 27 Nov 2025 02:37:23 +0000 Message-ID: <20251127023739.179652-9-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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. We calculate the index into the RGB black-level table so that we can apply the black level when we sample the input prior to the demosiac operation. Don't do this when using the lookup tables as the black level is already calculated in those. 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 c0632eb1f..6bca07b6e 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -69,6 +69,7 @@ uniform sampler2D red_param; uniform sampler2D green_param; uniform sampler2D blue_param; uniform mat3 ccm; +uniform vec3 blacklevel; void main(void) { @@ -217,6 +218,9 @@ void main(void) vec3(patterns.wz, C)); #if defined(APPLY_CCM_PARAMETERS) + + 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 a9996b94e..66cece56b 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -28,6 +28,7 @@ varying vec4 center; varying vec4 yCoord; varying vec4 xCoord; uniform mat3 ccm; +uniform vec3 blacklevel; void main(void) { vec3 rgb; @@ -112,6 +113,9 @@ void main(void) { vec3(PATTERN.yx, C)); #if defined(APPLY_CCM_PARAMETERS) + + rgb = rgb - blacklevel; + /* * CCM is a 3x3 in the format * From patchwork Thu Nov 27 02:37:24 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25246 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 09AEEC32DE for ; Thu, 27 Nov 2025 02:38:09 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A4AEF60AA0; Thu, 27 Nov 2025 03:38:08 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="O1+BvDT6"; dkim-atps=neutral Received: from mail-wm1-x32a.google.com (mail-wm1-x32a.google.com [IPv6:2a00:1450:4864:20::32a]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E6E4D60A86 for ; Thu, 27 Nov 2025 03:38:06 +0100 (CET) Received: by mail-wm1-x32a.google.com with SMTP id 5b1f17b1804b1-4775ae77516so3296355e9.1 for ; Wed, 26 Nov 2025 18:38:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211086; x=1764815886; 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=ZkyPq4yV0BnWPF44d9dM8L8EGZ/L/3PzRMm8vBWSZ0k=; b=O1+BvDT6i9SG2Cs7My5pApMdwE4NWQaYNuvqs3jqgXlfiiToKOI1l87MqLV+HEvavb oGYf+q4Ty8kJx5VDHZyt1eXMKCCNaU5EtMIzDLi9vqPz3BiPAayf2jwIQG8iaonszLtl JSbTEk9v2gBvhvnjNqe+FCEpfhdbWWD6WSStrMPLLVhFPSlrS+7dgwidIdThNLceklU3 bikvHL2kKBqeUJO3gHUPCrYDyxGB7q9t3jKBkILIKYYbZ9XG4OU57kXxl/ytjp2Cymo0 Rjq2syYH3TB1HOs37ybHk39nt5IOLk4F+azUE9Nkpi4zoG5hgUekGazT8dax7lAfCtQk TA+g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211086; x=1764815886; 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=ZkyPq4yV0BnWPF44d9dM8L8EGZ/L/3PzRMm8vBWSZ0k=; b=IVwybg27a9T2+OQHK2Vf0wXqt62DL2E1CONWNprvr2KvNyd8ryJTe9Y0EvKPZH89QF IhjKIVa0OB8V3FyQJeL1e4JEEqoV8plSOdVaan7zu8T6Qw8buCK5XNN5/K8IEbyrZ1Os g/0kHYoCAuR138rBXPVo1yBNA3rJjfgR3lny5qs+jtH0NscGz7vuBxZjOV/APHyK3UDN FAfXQFD5Jv3DRftVGA65i814Atg0LtWV/HtmZjc6zb9IPOmoOZeXT/3Dh8Z8rPmzmXbR d99XrMVmnXblws0tMPoGtuYLs9MEhue4L4awd0C5ChXFlu+R6J0uadpJxOnWDeAwrXLC JlHw== X-Gm-Message-State: AOJu0YxDs8dAYSgWC3zPBjjXA/VI7gSyodi3QuppIj0+UXAnmeijzuLh 6AeCQ02jfZ5xvY5DKk1CKsiG3yfuYqeYWKtjXZYOPE1+n5FO6NnSHGe/8C02FzHrNG3UIaYviX9 hjxFYTW0= X-Gm-Gg: ASbGncsL1vBSMZGjQLL7cTG+OXU8DeNKfkcKPeKZcX0ReiSj9wQlH4ZHh9aNT1jk+ff PFavy86vaKlSDsSmo1lYd6d3IVFX+x96wSt4HON7JRkbTQW3UwfeJ/m3p87ITxA2NqQiKYQf3M/ g3flb+1poA7w3UKxWGyx3UVqmtBBTb+2DBNCaTiXnw5kvvahqETqwXhbl0i+TH4qMwfKp9ds4po /wmrV/SZbabCYA8ja0Shs9Pcnb4087MoJ27vii+hx6SEkT/dKp/df9xVriEZHXfvBICUhGP76Dg YehBTluVZSq4FNJY9RMUcdBCDmq/Ccj0JTevkXbUEgbVUTDZtk0cRLxB/WhFjPjqR8pEDMRj2XV V8IFF22rPDhSpnJ81XvAX1A6k27DVUOZGGJ4iL1WRjadtd3kitwddCuS9XXppbnw0a0+a8Nj4nH BldnZfnnnXLQNfMtoaE3qOAzmwo0UkkppwB9DsUUjWR3MFu9yGRdW9bUiFAqU6MVSU44c= X-Google-Smtp-Source: AGHT+IE0W1RU1Gyhc1RrfQY54hRlrfCJclreb9PIhB6kT/aqGxy+AnSiqnMK4iKTBPoYin2YO/Wlig== X-Received: by 2002:a05:600c:3ba1:b0:475:dd89:acb with SMTP id 5b1f17b1804b1-477c11160cdmr222093625e9.22.1764211086320; Wed, 26 Nov 2025 18:38: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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.38.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:38:05 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v5 09/24] libcamera: shaders: Add support for Gamma Date: Thu, 27 Nov 2025 02:37:24 +0000 Message-ID: <20251127023739.179652-10-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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 compentation 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 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 6bca07b6e..069b880ff 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -70,6 +70,7 @@ uniform sampler2D green_param; uniform sampler2D blue_param; uniform mat3 ccm; uniform vec3 blacklevel; +uniform float gamma; void main(void) { @@ -265,6 +266,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)); + #elif defined(APPLY_RGB_PARAMETERS) /* Apply bayer params */ rgb.r = texture2D(red_param, vec2(rgb.r, 0.5)).r; diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag index 66cece56b..86bf2c31c 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -29,6 +29,7 @@ varying vec4 yCoord; varying vec4 xCoord; uniform mat3 ccm; uniform vec3 blacklevel; +uniform float gamma; void main(void) { vec3 rgb; @@ -160,6 +161,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)); + #elif defined(APPLY_RGB_PARAMETERS) /* Apply bayer params */ rgb.r = texture2D(red_param, vec2(rgb.r, 0.5)).r; From patchwork Thu Nov 27 02:37:25 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25247 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 9168EC0F2A for ; Thu, 27 Nov 2025 02:38:12 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3EF3E60AD0; Thu, 27 Nov 2025 03:38:12 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="ICERSK2Q"; dkim-atps=neutral Received: from mail-wm1-x332.google.com (mail-wm1-x332.google.com [IPv6:2a00:1450:4864:20::332]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3626560A8B for ; Thu, 27 Nov 2025 03:38:09 +0100 (CET) Received: by mail-wm1-x332.google.com with SMTP id 5b1f17b1804b1-47118259fd8so2250385e9.3 for ; Wed, 26 Nov 2025 18:38:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211088; x=1764815888; 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=/PZjb99W2l+LEd1sej3PwFkHQEZZRLTROogT00grB9Y=; b=ICERSK2Q3X7yYfO5KKlgjCrvYAN/njv9h32XsiGwIbSsmg7d9d2n8RuveMusd7gdWn SCnFAHj2bpO3Hd+2hil3HErRlpmU7z6CRyiM5aZDeid92fF7b0OrkFov9ra9NABHwKWy WGCU/OamP6dGzkU4RGUJuTWzFE5kMQnQoIGCwIeseL4wTkYjdEM3/zemu5GgadIndrzI gX9b0RBDc1giNJBUkg811Im0YL1ax90E9nYgKsiRCKmNGBpwyZ07Rux7Up/R+t0LwcC+ I/5reUgoCzNLg7TxhKkF/v1QoJgBJN5Vm4GJGumhQ+6jN75ZuGQkWvRHRCii72EVgubU 1smQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211088; x=1764815888; 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=/PZjb99W2l+LEd1sej3PwFkHQEZZRLTROogT00grB9Y=; b=NkeFtFF5qsLHSzEZVkh7jOQIYv6/rHyfqa9+H6wEARE4wq6KErpZwXZtmUSbhzmORX B09u41z6PnI6eQnwVdToC8fuMo1dIQDI6QJPiRbqqOhrEOCIn8mEzdrWYA4a0ElT8CG0 o5pEqtXAAkPeyVFAusiYOhrGFJNUnyYKnxGaKojqHM5X9LkE7BcVDXMgwTZBipaUjWj5 nFkS21wZaT3PPMX3dexO4OKPLCZvkmhLRZD+azaWeDfM7lKDFOMd1IzcqqHY08BHms12 PK1+DamJKyemQnNflpqBWsw4Pz7ETJVb2zmU7O1TzkpyZbEjUmAe6+V/F5BqDCV7Oy/V 7dSQ== X-Gm-Message-State: AOJu0YwVM7GzsERN2cieKZHwRwG0+GVHqTZtDOtWJ4O3tgL4JXKmz860 YlNELw3cg3pBkDL5Ctznp5WoUGpt8neuocOHbkS2T13WlGWm6AuFROVchWiJazoPQCnF9ttvfLA xFUPYieU= X-Gm-Gg: ASbGncu4EhdC8qdA7pC6VYDrBGFAgzvz/B7gWRPeaZPMoyEWMmBJbZUPSFfgpFY2loS kSTZMgIHrqgIi/WxtLnuvBQsElyxjSy2fqg0zftajx3cSGP76seXOfjqbBGB1nN579tvw6mM715 9+oSiWZprW31fRqQtRJok8wx0SiGCVyehblP13UdWmyE+4rB8KT7DfwkJD5cR7qQfl9zvde5Bi7 Qrn8XoqP0HwVTmzqICtBhrOnpIPBeEujJsOP0rd4OArExcwA+hxMQ/R2lPL2DA9smPvAHH7IZeV EpNpowjldhLmwypDM01S2nRM5zSwZ2hpXiZdc3+39TiAN88eIZYQohs9HWw2RUuM6fReQ6aZJAs i81co8Uxh0dGQq3Flk3Rcbz2Wr2eUwjTOuAjmW6LhM47ql/ddg7zX03NI8T4a1kEkvkycsTzDHv rBKxZ1fHq+pgHz8NQKMiAah20eMhoPtRjzpyXzy3270ZkK6JIRc6jBSrEa59H31ZpBlhE= X-Google-Smtp-Source: AGHT+IED1IeoYlpP7jt3zgiKEDbrxcxz+fxhTOzb4FKxv5P69Hil4JGrPC7tl0dLP/0wHQWbzNVmuQ== X-Received: by 2002:a05:600c:6011:b0:477:abea:9028 with SMTP id 5b1f17b1804b1-47904ac44d6mr59225615e9.6.1764211088560; Wed, 26 Nov 2025 18:38: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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.38.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:38:07 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v5 10/24] libcamera: shaders: Add support for contrast Date: Thu, 27 Nov 2025 02:37:25 +0000 Message-ID: <20251127023739.179652-11-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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 Signed-off-by: Bryan O'Donoghue --- src/libcamera/shaders/bayer_1x_packed.frag | 19 +++++++++++++++++++ src/libcamera/shaders/bayer_unpacked.frag | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag index 069b880ff..741896d01 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -71,6 +71,19 @@ uniform sampler2D blue_param; uniform mat3 ccm; uniform vec3 blacklevel; uniform float gamma; +uniform float contrast; + +float apply_contrast(float normalise, float contrast_in) +{ + // Convert 0..2 contrast to 0..infinity; avoid actual infinity at tan(pi/2) + float contrastExp = tan(clamp(contrast_in * 0.78539816339744830962, 0.0, 1.5707963267948966 - 0.00001)); + + // Apply simple S-curve + if (normalise < 0.5) + return 0.5 * pow(normalise / 0.5, contrastExp); + else + return 1.0 - 0.5 * pow((1.0 - normalise) / 0.5, contrastExp); +} void main(void) { @@ -266,6 +279,12 @@ 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, contrast); + rgb.g = apply_contrast(rgb.g, contrast); + rgb.b = apply_contrast(rgb.b, contrast); + /* 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 86bf2c31c..43ed99e33 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -30,6 +30,19 @@ varying vec4 xCoord; uniform mat3 ccm; uniform vec3 blacklevel; uniform float gamma; +uniform float contrast; + +float apply_contrast(float normalise, float contrast_in) +{ + // Convert 0..2 contrast to 0..infinity; avoid actual infinity at tan(pi/2) + float contrastExp = tan(clamp(contrast_in * 0.78539816339744830962, 0.0, 1.5707963267948966 - 0.00001)); + + // Apply simple S-curve + if (normalise < 0.5) + return 0.5 * pow(normalise / 0.5, contrastExp); + else + return 1.0 - 0.5 * pow((1.0 - normalise) / 0.5, contrastExp); +} void main(void) { vec3 rgb; @@ -161,6 +174,12 @@ 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, contrast); + rgb.g = apply_contrast(rgb.g, contrast); + rgb.b = apply_contrast(rgb.b, contrast); + /* Apply gamma after colour correction */ rgb = pow(rgb, vec3(gamma)); From patchwork Thu Nov 27 02:37:26 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25248 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 B290AC32DE for ; Thu, 27 Nov 2025 02:38:13 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5541A60AA0; Thu, 27 Nov 2025 03:38:13 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="WftqorXx"; dkim-atps=neutral Received: from mail-wm1-x330.google.com (mail-wm1-x330.google.com [IPv6:2a00:1450:4864:20::330]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DAAE0609DE for ; Thu, 27 Nov 2025 03:38:10 +0100 (CET) Received: by mail-wm1-x330.google.com with SMTP id 5b1f17b1804b1-47790b080e4so1181175e9.3 for ; Wed, 26 Nov 2025 18:38:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211090; x=1764815890; 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=ks/FmitMWmPckFVWZHkmtbgY2cBV7upypIHZAZgxRaA=; b=WftqorXxCLQGye6PtgSxaMwLiZWxk01/5nfUByeK/YBba/P/4x240kiXoM1k/mLq9V WbjA1zFyz83FL0RGdAAQmqs9iaj2J2WsPgcJigL7YwuCT/bBzPcNG1kYi0YYwVbFkbhF IQ1LxZFIPYNTqlD+0ElHOY2kZMyRkHTT0d4kd0DvXq1ImBrCEhfU9kZtRelM6aHlaEKr DXhO7eghPCECieKEHd3kSTyPiTH3rij0JJnbtdGy/Em8ftNdV6l1iAV/k/vGNlo9eMdj FRNLMArd9ZdceT3tjIy/h+XG5SkLmaEmJ2eCAOqHD9XuvNdy/WChD8VMUInQP3yvU/sb JYyA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211090; x=1764815890; 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=ks/FmitMWmPckFVWZHkmtbgY2cBV7upypIHZAZgxRaA=; b=NUdRAdIhg12/cRIZB/FHiOxMDqrhB8mWV8m/RqBrA7ZMPSqFpdOn5Z0pXkCGKqmXqi 8kndkto2AxR4zkZIQr5uDMvVET2TcHCrLAnrSpQdTchMEWdUuJFPM2/9rBNtpVxq24fT loINA35taRPF9qPubggMVRaiKrdrCLLt9Kkm3PLVr+yCTJ2j0bAN0Hw7aES53cA4lihC /O/GnXV3kko4w5to6AW8JwQ5zXoE7I1D2kAVJxPSmfmdWS7pZvgepz00sJQYptdCa7vL FatfkNIECfExPy0mulSZfxqTXo9YmcSvUpgcAKPZGRBXxGjX6lF5ZNZQAVx+eunUl4xe oFEA== X-Gm-Message-State: AOJu0YzNioQKh8+Qlz+bjnDxG8A+e7+j5grckmMaj+BwalulgvRiLaCU F/aTnA+Pa7vKHMI2GleCg+xCK3rMfka0KIbJngGzkjpBJ2OVGHogVo8uMrxYlmr4lFYGOG1txzi khGLofL8= X-Gm-Gg: ASbGncuwKlVGoIZ5zl14lnCn5IxRUvmzyqGMhs3DySLkfIQfy2AkUbbKW1wSlOfAmzF /VnGDkpGsrNqP1pOtuqFhTRE7MiZEsS6cBZm2ovKpnyvDXXzYCY5eW9x6jy+D4h4BIlCDF4RQHy wMewqlPBrTWPCrY4NmZT0O2sAC2g1sU7VxIX2/QnWauOP4YIrdXgytQCk8JB4mnuWNux1v+aUxS pUirXQlrpOmh/gRtoHAtFWH5x5mc+a8WtSt5gZVqihH3HITUalJhVj+Gf23P9fbDqZgqpsID380 eSWHB2SwF0WPKVePWq1sD4M7dKvcBLCAljGkVNsMW92zP9QulnvvSVW5ogr7VvaWbYKBkPxRAQ0 eVug7GBeECcOY6i3HutKX2FiR7kA0yrWOvPA2JYPD2iqCJax02XxWsAZatdh8+iImQ6mnRMh1pm bbQEXIwBNkZFiigMvGeg6rddWlpx4bZiZlhk9F/FeafM5Yw2NCCUY//QCl5StN7Jm9pcw= X-Google-Smtp-Source: AGHT+IFt5IRKqw0XbYBKni8onyaQ09yv7FduvRaNor25K9aoOJKUhMXXeksEjz9jhrOhaZjp8B9vcw== X-Received: by 2002:a05:600c:1914:b0:471:114e:5894 with SMTP id 5b1f17b1804b1-477c112587fmr175550055e9.25.1764211090287; Wed, 26 Nov 2025 18:38:10 -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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.38.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:38:09 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Hans de Goede , Bryan O'Donoghue Subject: [PATCH v5 11/24] libcamera: shaders: Fix input sampling when width != stride Date: Thu, 27 Nov 2025 02:37:26 +0000 Message-ID: <20251127023739.179652-12-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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 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 Thu Nov 27 02:37:27 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25249 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 787CFC0F2A for ; Thu, 27 Nov 2025 02:38:16 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1BFFC60AD0; Thu, 27 Nov 2025 03:38:16 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="QPDEBURq"; dkim-atps=neutral Received: from mail-wm1-x32c.google.com (mail-wm1-x32c.google.com [IPv6:2a00:1450:4864:20::32c]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0BA67609DE for ; Thu, 27 Nov 2025 03:38:13 +0100 (CET) Received: by mail-wm1-x32c.google.com with SMTP id 5b1f17b1804b1-4775ae77516so3297005e9.1 for ; Wed, 26 Nov 2025 18:38:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211092; x=1764815892; 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=RJN8Y3Sdy/5fP1WaIPiCp87eLnrZwAg8dInf49k+Ch8=; b=QPDEBURqJIFBTRGPiezIP3y5SS6AetqCAIczN5zTQp3t0DM5jbJOjYdXIjDmhjkr5k aWdRpfToFFOFIY9B4m3V17qZgy9jEAAyD8CydDxySTbvT1AZ2P+T8gDvdDQOhZ9wMOKk yi4kYvF4bTH2D5I/XyvaTUVZ0dl0mSZ1XsDBRECFBvweKbvqrcGzuFxSKW8SmRCwgOot iqya5odo+S4lXgyC3PFIoVYDj8Mr7iFBiQUI/olK9wsOmOXd343/EBlbRsi+TA+ObVCd skjU36mwgco2ycIaCLgccJMvgIDxZSCe+DUoHvjuW2I07JsPacPm7d7SG8MPRyZJlf0w 53nw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211092; x=1764815892; 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=RJN8Y3Sdy/5fP1WaIPiCp87eLnrZwAg8dInf49k+Ch8=; b=A16PPeNwk3r4kc8RNKAYywUHRhx3lFAzZ7VltNnXbRQiEGggdsWYh8DtxInYH+lor1 NA7bTe3jMZSyQYZn6C4OIPEN6bkDFvb9wDoypnPQot1YRygQbI0syci0ZnKTIYx34Vhw kSeksts2X+rrsosYDuiohzvFlueaVchUdwqquu5nQQvnUl49hZodPVSWxAiBe7q94EWQ GMIfc16otHvOj4/X62ZwNEigSjXqe2SNNeHYmTowQxtepSzrpmJQIy+Di4vJ6Cu7Dgb5 vAFUIPvek+S1BemPrbXZPmy212ZtakgCB+VcH0DyUNacM3NCCmSQiSo1qW/zhD283/XJ MucA== X-Gm-Message-State: AOJu0YyALLOF2SmdjDieMDiSzYAyK4PdcNwYzaMjU2UKZ4fyDKQ4dcQW QahO+Yor13fxBa8N5k7DP9LpiVtJhrfOg7S0e8YA6RBGMj8tqSftKkl4Dht2CuVFtyh9AFwDCbe 8EEvM3zA= X-Gm-Gg: ASbGnct1Y13Y0E8NxADpYopGHL3z4pFR2GRY84DLQYKKobQjGP6a3zYEMS3gJunUyVN HqaxOvRFy9Q/sU8jVvVGtgZILpPzKLvqRlRLgMhjqYMdp+gKFh402ycA9JYA5Ra5EmhbkV1Hpf7 WwBuGAHdy6xYQcFVIlB05H82zOYd7Sa5N714lUFIqONz7DUcq/+5T8oeEWXweS1ajCb9w2wcFEj lkOqyzJf5yIjrN/Wqujbqfld1fmalhmjpIu6sAu9g/ackCv4v1KBOUEQam6DKOQaNnfHlmxPhZ/ v1Ewhh27BakspwnVJE/GtCi6Tf5OEE/j9LzfCnt7w/8bFJ5uaULHN27WIdFzmJnd6XwjUWOJFo4 +cEqht4sqE83jthkEmYsxMBxBfxdwDxQVRJ7w/iGZtGXTsVAB6/5TWOaByw7pc9TYO/BSza+D+B 19+mNO2bbMt9U/MaS90v5f93Aihm48L1pXkxefkDeLpsMjkX15eCdudeYE9P6HjjB/YAafjZ/gp WxJGA== X-Google-Smtp-Source: AGHT+IGaejHJNttFzjeoT6JgfRDKei+HFnSSzn4wSCVihWh+oLJMw0JakW2iXxG3HTz2fJS5cMT/tA== X-Received: by 2002:a05:600c:474a:b0:477:b0b9:3137 with SMTP id 5b1f17b1804b1-477c10c8886mr221571275e9.1.1764211092083; Wed, 26 Nov 2025 18:38: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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.38.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:38:11 -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 v5 12/24] libcamera: software_isp: debayer_egl: Add an eGL debayer class Date: Thu, 27 Nov 2025 02:37:27 +0000 Message-ID: <20251127023739.179652-13-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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 Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/debayer_egl.cpp | 682 +++++++++++++++++++++ src/libcamera/software_isp/debayer_egl.h | 151 +++++ src/libcamera/software_isp/meson.build | 8 + 3 files changed, 841 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..71b92f01f --- /dev/null +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -0,0 +1,682 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Linaro Ltd. + * + * Authors: + * Bryan O'Donoghue + * + * debayer_cpu.cpp - EGL based debayering class + */ + +#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.toString(); + + 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.toString(); + + return -EINVAL; +} + +int DebayerEGL::getShaderVariableLocations(void) +{ + attributeVertex_ = glGetAttribLocation(programId_, "vertexIn"); + attributeTexture_ = glGetAttribLocation(programId_, "textureIn"); + + textureUniformBayerDataIn_ = glGetUniformLocation(programId_, "tex_y"); + textureUniformRedLookupDataIn_ = glGetUniformLocation(programId_, "red_param"); + textureUniformGreenLookupDataIn_ = glGetUniformLocation(programId_, "green_param"); + textureUniformBlueLookupDataIn_ = glGetUniformLocation(programId_, "blue_param"); + ccmUniformDataIn_ = glGetUniformLocation(programId_, "ccm"); + blackLevelUniformDataIn_ = glGetUniformLocation(programId_, "blacklevel"); + gammaUniformDataIn_ = glGetUniformLocation(programId_, "gamma"); + contrastUniformDataIn_ = glGetUniformLocation(programId_, "contrast"); + + 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_ + << " red_param " << textureUniformRedLookupDataIn_ + << " green_param " << textureUniformGreenLookupDataIn_ + << " blue_param " << textureUniformBlueLookupDataIn_ + << " ccm " << ccmUniformDataIn_ + << " blacklevel " << blackLevelUniformDataIn_ + << " gamma " << gammaUniformDataIn_ + << " contrast " << contrastUniformDataIn_ + << " 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; + unsigned char *fragmentShaderData; + unsigned int vertexShaderDataLen; + unsigned char *vertexShaderData; + 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: + goto invalid_fmt; + } + + // 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: + goto invalid_fmt; + break; + }; + + // 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; + default: + goto invalid_fmt; + break; + }; + + if (ccmEnabled_) { + // Run the CCM if available + egl_.pushEnv(shaderEnv, "#define APPLY_CCM_PARAMETERS"); + } else { + // Flag to shaders that we have parameter gain tables + egl_.pushEnv(shaderEnv, "#define APPLY_RGB_PARAMETERS"); + } + + if (egl_.compileVertexShader(vertexShaderId_, vertexShaderData, vertexShaderDataLen, shaderEnv)) + goto compile_fail; + + if (egl_.compileFragmentShader(fragmentShaderId_, fragmentShaderData, fragmentShaderDataLen, shaderEnv)) + goto compile_fail; + + if (egl_.linkProgram(programId_, vertexShaderId_, fragmentShaderId_)) + goto link_fail; + + egl_.dumpShaderSource(vertexShaderId_); + egl_.dumpShaderSource(fragmentShaderId_); + + /* Ensure we set the programId_ */ + egl_.useProgram(programId_); + err = glGetError(); + if (err != GL_NO_ERROR) + goto program_fail; + + if (getShaderVariableLocations()) + goto parameters_fail; + + return 0; + +parameters_fail: + LOG(Debayer, Error) << "Program parameters fail"; + return -ENODEV; + +program_fail: + LOG(Debayer, Error) << "Use program error " << err; + return -ENODEV; + +link_fail: + LOG(Debayer, Error) << "Linking program fail"; + return -ENODEV; + +compile_fail: + LOG(Debayer, Error) << "Compile debayer shaders fail"; + return -ENODEV; + +invalid_fmt: + LOG(Debayer, Error) << "Unsupported input output format combination"; + return -EINVAL; +} + + +/** + * \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) +{ + GLint maxTextureImageUnits; + + if (getInputConfig(inputCfg.pixelFormat, inputConfig_) != 0) + return -EINVAL; + + if (stats_->configure(inputCfg) != 0) + 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.toString(); + return -EINVAL; + } + + inputConfig_.stride = inputCfg.stride; + width_ = inputCfg.size.width; + height_ = inputCfg.size.height; + ccmEnabled_ = ccmEnabled; + + if (outputCfgs.size() != 1) { + LOG(Debayer, Error) + << "Unsupported number of output streams: " + << outputCfgs.size(); + return -EINVAL; + } + + 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; + + if (!ccmEnabled && maxTextureImageUnits < DEBAYER_EGL_MIN_SIMPLE_RGB_GAIN_TEXTURE_UNITS) { + LOG(Debayer, Error) << "Fragment shader texture unit count " << maxTextureImageUnits + << " required minimum for RGB gain table lookup " << DEBAYER_EGL_MIN_SIMPLE_RGB_GAIN_TEXTURE_UNITS + << " try using an identity CCM "; + return -ENODEV; + } + + 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; + } + + 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())); + + // Raw bayer input as texture + eglImageBayerIn_ = std::make_unique(width_, height_, 32, inputCfg.stride, GL_TEXTURE0, 0); + + // Only do the RGB lookup table textures if CCM is disabled + if (!ccmEnabled_) { + /// RGB correction tables as 2d textures + // eGL doesn't support glTexImage1D so we do a little hack with 2D to compensate + eglImageRedLookup_ = std::make_unique(DebayerParams::kRGBLookupSize, 1, 32, GL_TEXTURE1, 1); + if (!eglImageRedLookup_) + return -ENOMEM; + + eglImageGreenLookup_ = std::make_unique(DebayerParams::kRGBLookupSize, 1, 32, GL_TEXTURE2, 2); + if (!eglImageGreenLookup_) + return -ENOMEM; + + eglImageBlueLookup_ = std::make_unique(DebayerParams::kRGBLookupSize, 1, 32, GL_TEXTURE3, 3); + if (!eglImageBlueLookup_) + return -ENOMEM; + } + + eglImageBayerOut_ = std::make_unique(outputCfg.size.width, outputCfg.size.height, 32, outputCfg.stride, GL_TEXTURE4, 4); + if (!eglImageBayerOut_) + return -ENOMEM; + + if (initBayerShaders(inputCfg.pixelFormat, outputCfg.pixelFormat)) + return -EINVAL; + + 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_); + GLfloat scaleX = (GLfloat)window_.width / width_; + GLfloat scaleY = (GLfloat)window_.height / height_; + GLfloat transX = -(1.0f - scaleX); + GLfloat transY = -(1.0f - scaleY); + GLfloat scale = std::max(scaleX, scaleY); + GLfloat projMatrix[] = { + scale, 0, 0, 0, + 0, scale, 0, 0, + 0, 0, 1, 0, + transX, transY, 0, 1 + }; + + // 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_ + << " red_param " << textureUniformRedLookupDataIn_ + << " green_param " << textureUniformGreenLookupDataIn_ + << " blue_param " << textureUniformBlueLookupDataIn_ + << " 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_; + + if (!ccmEnabled_) { + glUniform1i(textureUniformRedLookupDataIn_, eglImageRedLookup_->texture_unit_uniform_id_); + glUniform1i(textureUniformGreenLookupDataIn_, eglImageGreenLookup_->texture_unit_uniform_id_); + glUniform1i(textureUniformBlueLookupDataIn_, eglImageBlueLookup_->texture_unit_uniform_id_); + + egl_.createTexture2D(eglImageRedLookup_, GL_LUMINANCE, DebayerParams::kRGBLookupSize, 1, ¶ms.red); + egl_.createTexture2D(eglImageGreenLookup_, GL_LUMINANCE, DebayerParams::kRGBLookupSize, 1, ¶ms.green); + egl_.createTexture2D(eglImageBlueLookup_, GL_LUMINANCE, DebayerParams::kRGBLookupSize, 1, ¶ms.blue); + + LOG(Debayer, Debug) << "textureUniformRedLookupDataIn_ " << textureUniformRedLookupDataIn_ + << " textureUniformGreenLookupDataIn_ " << textureUniformGreenLookupDataIn_ + << " textureUniformBlueLookupDataIn_ " << textureUniformBlueLookupDataIn_; + } else { + 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(contrastUniformDataIn_, params.contrast); + LOG(Debayer, Debug) << " contrastUniformDataIn_ " << contrastUniformDataIn_ << " data " << params.contrast; + + 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; +} + +void DebayerEGL::stop() +{ + 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.toString(); + 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..f0d269758 --- /dev/null +++ b/src/libcamera/software_isp/debayer_egl.h @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2025, Bryan O'Donoghue. + * + * Authors: + * Bryan O'Donoghue + * + * debayer_opengl.h - EGL debayer header + */ + +#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); + 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_; + GLuint fragmentShaderId_; + GLuint programId_; + enum { + BAYER_INPUT_INDEX = 0, + BAYER_OUTPUT_INDEX, + BAYER_BUF_NUM, + }; + + // Pointer to object representing input texture + std::unique_ptr eglImageBayerIn_; + std::unique_ptr eglImageBayerOut_; + + std::unique_ptr eglImageRedLookup_; + std::unique_ptr eglImageGreenLookup_; + std::unique_ptr eglImageBlueLookup_; + + // Shader parameters + float firstRed_x_; + float firstRed_y_; + GLint attributeVertex_; + GLint attributeTexture_; + GLint textureUniformStep_; + GLint textureUniformSize_; + GLint textureUniformStrideFactor_; + GLint textureUniformBayerFirstRed_; + GLint textureUniformProjMatrix_; + + GLint textureUniformBayerDataIn_; + + // These textures will either point to simple RGB gains or to CCM lookup tables + GLint textureUniformRedLookupDataIn_; + GLint textureUniformGreenLookupDataIn_; + GLint textureUniformBlueLookupDataIn_; + + // Represent per-frame CCM as a uniform vector of floats 3 x 3 + GLint ccmUniformDataIn_; + bool ccmEnabled_; + + // Black Level compensation + GLint blackLevelUniformDataIn_; + + // Gamma + GLint gammaUniformDataIn_; + + // Contrast + GLint contrastUniformDataIn_; + + Rectangle window_; + std::unique_ptr stats_; + eGL egl_; + GBM gbmSurface_; + uint32_t width_; + uint32_t height_; + GLint glFormat_; + unsigned int bytesPerPixel_; + uint32_t shaderStridePixels_; + GLfloat vcoordinates[DEBAYER_OPENGL_COORDS][2] = { + { -1.0f, -1.0f }, + { -1.0f, +1.0f }, + { +1.0f, +1.0f }, + { +1.0f, -1.0f }, + }; + GLfloat tcoordinates[DEBAYER_OPENGL_COORDS][2] = { + { 0.0f, 0.0f }, + { 0.0f, 1.0f }, + { 1.0f, 1.0f }, + { 1.0f, 0.0f }, + }; +}; + +} /* 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 Thu Nov 27 02:37:28 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25250 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 A22AFC32DE for ; Thu, 27 Nov 2025 02:38:17 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1B63E60B0F; Thu, 27 Nov 2025 03:38:17 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="VUy9+i1+"; 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 7E4B560AB8 for ; Thu, 27 Nov 2025 03:38:13 +0100 (CET) Received: by mail-wm1-x32d.google.com with SMTP id 5b1f17b1804b1-4775ae77516so3297035e9.1 for ; Wed, 26 Nov 2025 18:38:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211093; x=1764815893; 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=+2GcZ5YL21UUK5YHwLU7zkEQf8v6DCPa5f56k85rtTM=; b=VUy9+i1+QwVOT5Fy/vLoNtEK/VcOElbPhb98lp+i12v8E8SkY+z2NVvnvpchn+VIrG HcaAxjJ/LOvFMfam+YApFAAWFL+YmgBbzZfJurMgBDkwXP53xODyvunGcQiPs8O8oO3l oJ4qFVhrcOGGch/t0Js09lyuhwikvnk9RQzwansS29EIfF6GwRf/HoL7aCFRcaylFDrs uI9ORvnR8rEswlBp8hAadr6EoYfDcwVNrwoVNXkZvc/tWZ9Pi8Tl/lhpFqh2czmSU4cD 33V6N84jxsSQ1hfm0yslHmJ9GoBEX/jJhrHzUm+d189y/iZqIxumiB+s9AHBxD832y/S wwzg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211093; x=1764815893; 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=+2GcZ5YL21UUK5YHwLU7zkEQf8v6DCPa5f56k85rtTM=; b=Ch3uN67v+QoKegGSF2HC4z8UDJ37FdiEuto4FoiHBhxsmR7UmSCNvkOkpingCpyJ7w +4XgX0AXdJjNruf7jC83ta1FZPcU9PRQJa/T84+pixhBU6ieBZJnG2o8LW7KejofwAxy ln676C1ISKbSMhQYo6JzRjT+0k+jkoAgMH54qJoHAMIYSyefSHbe0ubMHZH/6690Z5U0 MeUJ6b+abF+A6G11zdBujh74sk21F3fSh4ezgVvMz+2QT89DsZZDpWqTcaMzTOj5jOKl k/f3gT7mUIpSXqbbZrOo2CKHoRH0TKgLdoAqyr7GEQAULqQtxxX1Intiu53cXFZpFQRF PTcw== X-Gm-Message-State: AOJu0YyEZcoJjqEr/1wMW+SnGdJTMfuEv/KcSvlFYOhVBrPhB+No8yUp TR/Uh0JJvd8TPCj2ceUHHD8emsaoE0jTZs/G5mNNvjSXs7Mt/yLw8BMrsOn1SdhDYfeZ8PcooXm DM8r1Nsc= X-Gm-Gg: ASbGnct9BrNgnMkLZog5Sdf+oxoyPMLudft1FmZxgjpSg/YfkyASC3f4LvHpOMSvXxJ BP7TQPQTJ1fHkdvIymgcMzlac4PZj6/bUgGIIi00LgyljLXgecQ7oEWi1iFJ6pEAA8aAvqJ6bJ9 npwpWEi6hKzmiIk2xWrneke6AWexFyN2yeSGuZ4UtgLsb7QBVUOBWWg0NAtmA14b1/76w0tHBu6 JOXXuuo7sYNzdBDLMhIRpB8PQrj/QexT3SBYt6axYPIosn4HuHDtZA9fXzuQREoP/Gc9W/uKCst AmzXAHLaM8TgnG3vXFmn5JXUoPqnMBzBUhGMKGrSPyEsX4ibLz5Un5d20/LhvAfqorCAZ/pAuBz GRemx7baTaE3wq2fif6bVi4k8la9URbVI9FUbWeuKK5c1TAvhg/+3m4dN3juiNEAvZwKmDiT27e msvijuYVDEfA9eVGuUsfdxUxxVOSah3fkFtbBRJe406BVn/R3DwTtpN0iEnBci+oVfmeg= X-Google-Smtp-Source: AGHT+IEhTfCvKyTW0GwCobwbCDuHVZ4FQjtXb5BxqV0kc/rf16ZpPOnGed4TPK058QJ9YizHiCjWqg== X-Received: by 2002:a05:600c:1f85:b0:477:7b30:a6fe with SMTP id 5b1f17b1804b1-477c1116013mr197235665e9.18.1764211092864; Wed, 26 Nov 2025 18:38: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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.38.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:38:12 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v5 13/24] libcamera: software_isp: debayer_egl: Make DebayerEGL an environment option Date: Thu, 27 Nov 2025 02:37:28 +0000 Message-ID: <20251127023739.179652-14-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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 Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/software_isp.cpp | 24 ++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index aa4a40cb6..223c1d4be 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,25 @@ 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 + const char *softISPMode = utils::secure_getenv("LIBCAMERA_SOFTISP_MODE"); + + if (softISPMode && !strcmp(softISPMode, "gpu")) { + debayer_ = std::make_unique(std::move(stats), configuration); + if (!debayer_) { + LOG(SoftwareIsp, Error) << "Failed to instantiate GPUISP"; + return; + } + } +#endif + if (!debayer_) + debayer_ = std::make_unique(std::move(stats), configuration); + + if (!debayer_) { + LOG(SoftwareIsp, Error) << "Failed to create Debayer object"; + return; + } + debayer_->inputBufferReady.connect(this, &SoftwareIsp::inputReady); debayer_->outputBufferReady.connect(this, &SoftwareIsp::outputReady); From patchwork Thu Nov 27 02:37:29 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25251 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 EE730C0F2A for ; Thu, 27 Nov 2025 02:38:18 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8436360B2F; Thu, 27 Nov 2025 03:38:18 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="tI5cza/4"; 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 2CC4660AB7 for ; Thu, 27 Nov 2025 03:38:15 +0100 (CET) Received: by mail-wm1-x32b.google.com with SMTP id 5b1f17b1804b1-477b198f4bcso1723525e9.3 for ; Wed, 26 Nov 2025 18:38:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211094; x=1764815894; 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=i8EigPEvYaH2gSH8JSHJbCseJKpik1Nyc/20liFxLWw=; b=tI5cza/4onCcJRgREVTKeE8mbVNy9lQNeIOXtffxP3/w74/CwbnhSmkkZY4/j238mm BJEmq0GQ3cNY1pAFQP1gXRuPmheK4XLVvRtw3taxbrPC9mn/zmWKh1pjcXmACp9mn2YI dBXZm3KGaOZP6RJDxTpkJgljkYVacnv0AFkLmnm9ECnviO5PcmCSleiVxbhutBA29ptL 6OfCOE3xD+ljofnEm+QS6yCuXz9UPVekBPAcjTW9RQTG4xoZhFIaJj6+W9UjBtA/rMfC Hz3DLqJN6tusjgYczEqva31zYKdTER2RKUNArFOO7qPUFPtTk68qeChY5WK/Z8vh4vmE niMg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211094; x=1764815894; 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=i8EigPEvYaH2gSH8JSHJbCseJKpik1Nyc/20liFxLWw=; b=oYh+3rPg2c4l604Gi3Q3J43lHypW+F55U9HgJ0YGjpBpxO4zBTg3WRjDHat8orNUDh 9VIqj0gix5VGXXPXMkpfZPFHPUHvVaOdQjepShOIOHV0DStsnpu6PQLr3mYz5XRoAuTV Tt/sq7N0fyuaUsUOHaXGNtWoHn2+DV0M5TZPhGmEMCYlh8PA7+h7pbZx/3JgJyRmpl9h FJt5wWk1ZbIvwDSufkeoOrTq83VKK3XOgTc7yleyXL2UejS/TnCL75qnw7O4fc1vpR9v 8YpOIumDRWwUIlbobvQPcIcncbWYkKrkzi1JIyjxzGM8Dw1PVvlNjwq/MJNKMY40sN/X V1rg== X-Gm-Message-State: AOJu0YyeZPA4CWeMMuk0kg+pH5R6dRT/JktOQ7yY4JmtUMhyrE+ZRZcd /fqlPoV9VV83s8FOrjzmZLm/GZhVsIlLr9p169uTDcKE8gkIMUAVLbKDlYqsn3zxjya6r2+RVBz 2fXp2o94= X-Gm-Gg: ASbGncsYPrLXVn34I+Zsm5WrigO4pSfhESEIJrpCpaf7+6jkYheufteEbwPxqjRwZGL XXCev/k21+1syfUOi/04Dk8CkQKzlTSQWIV9zsNhPttn0/GPHUD4HcJc4h062LyNF4FwabzsbkH d4xtKtYsrsWUHRypOjlJvRME44Ga5jhJT+QA/z+HEXQZi2kcHt4VcrnsyWfXYhRG19KFQPN0A9Q dys0aJHuTLIhYu/24gXWEOuaXZSQnq0ZC/E8PIKgFQQZgQNn1ENwy3QxcoQ3oGRx74OMfV+5XpK pN2cmEXsmdNy8ZD8EEFCHlvm+WIQEH0Tq7A0Q6X1PUdLUPF9f2tD2tTwvt9yiPHxWtzgcwIRXfO poGrwSY0HvpSNz2B2mjSVzGBT1gzk1PvqEcUOq5BWHFPdGjwc4YK7Xq43Nlle71eVX2my9PnwON fKim6CgmRlB1nFuflG5iKf6+vd9vvl55X2NYw4l8JvbrLIVP7xKQNV4LlfONjMx2yB8Tw= X-Google-Smtp-Source: AGHT+IGLVm3kND/2YaGeOn9w8G+REHNi2OaV/9FIz+fRfdBoXHt1XP6KJbKhffPBVehNxJ+uCM17xA== X-Received: by 2002:a05:600c:4fcc:b0:471:9da:5252 with SMTP id 5b1f17b1804b1-477c01ebe2amr206500015e9.29.1764211094428; Wed, 26 Nov 2025 18:38: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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.38.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:38:13 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v5 14/24] libcamera: software_isp: debayer_egl: Make gpuisp default softisp mode Date: Thu, 27 Nov 2025 02:37:29 +0000 Message-ID: <20251127023739.179652-15-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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. Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/software_isp.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index 223c1d4be..a54dcbaf5 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -121,10 +121,17 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, } stats->statsReady.connect(this, &SoftwareIsp::statsReady); -#if HAVE_DEBAYER_EGL const char *softISPMode = utils::secure_getenv("LIBCAMERA_SOFTISP_MODE"); + if (softISPMode) { + if (strcmp(softISPMode, "gpu") && strcmp(softISPMode, "cpu")) { + LOG(SoftwareIsp, Error) << "LIBCAMERA_SOFISP_MODE " << softISPMode << " invalid. " + << "must be \"cpu\" or \"gpu\""; + return; + } + } - if (softISPMode && !strcmp(softISPMode, "gpu")) { +#if HAVE_DEBAYER_EGL + if (!softISPMode || !strcmp(softISPMode, "gpu")) { debayer_ = std::make_unique(std::move(stats), configuration); if (!debayer_) { LOG(SoftwareIsp, Error) << "Failed to instantiate GPUISP"; From patchwork Thu Nov 27 02:37:30 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25252 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 16D8AC32DE for ; Thu, 27 Nov 2025 02:38:22 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8654660BDD; Thu, 27 Nov 2025 03:38:21 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="uXNVdpdQ"; 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 C672B60AB8 for ; Thu, 27 Nov 2025 03:38:16 +0100 (CET) Received: by mail-wm1-x32d.google.com with SMTP id 5b1f17b1804b1-4779adb38d3so1790405e9.2 for ; Wed, 26 Nov 2025 18:38:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211096; x=1764815896; 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=U4gZBzqGbQfvRAdn9kIktQq170/k2VAqruGy17o40mc=; b=uXNVdpdQTop3ZHzevS5H6HFSdAqoX76vVnPm7tuBO6hhHACKMhwPSO86LzGD9TeBdm nAgWCAUeP6Iw5fTh9MR7MGHaPmIP6Rd3+zxsnqOJIp9ba2kScbPo6EKHuRryeH2VN8uD Cx7JxWZsouWZNwwpcwX7UyY7B4FRdIssiGcPEoTo1zuKQThaLIbzaoF3owSj9igrY0Rl XUass56gSnENzhaomyT/b3L4QgZyXwEBltvCSWGeSyoot0bFwI5gULJ3Yakf4xiSHSNv n2B1T9en9fm8oVI0dBEs/hyN7l2WdZ5L2k746Y7fMVE7U2ouCAYF5yM2jd723QHSIvzG MgXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211096; x=1764815896; 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=U4gZBzqGbQfvRAdn9kIktQq170/k2VAqruGy17o40mc=; b=RmmZxrKTCLjWVj6bpdk8P1YS7sTB+lpu06lX1nWMf/LizTANNwQL7B6s9uh1glI9dI Kr7tkyKISM7AdTrbuAdUdBnl7FThM1H9ikbjN9ffqqf9HsBnjFHxQeGM4pyQwvps63Pa 35g4hZf3j4YeZRGEjoCKzpCp0H+vSj9AkX+N12J/s8C68IJ4QG2r0WgMM+8vGLX2y23C KOfxfrfjGMDJiMck5MROKx2h6Fr/v/GM3rACH06C6gswZxosj7k6uGZtkWZ0NsfQQLNF XwCYSpgDWEIJSFjXDLj/aBAM+838JEZuH41kDVHgIgDkdFRVlTsr8r+JOPllPTTfheTt QCJw== X-Gm-Message-State: AOJu0YxDaO9RF4Es5AkRjDk9cOr67+bltXecHbrGQG7Sr1HGaRHoxg4b S2kNxL22SsM5w64LgUKR/0R9TvHoRLQP2vaa7YhhMovNi2FCMs8LUHL8E0GAckqK1DtBf21V7E2 GCYu/Ljw= X-Gm-Gg: ASbGncsQXNLJjUwOZZstx+nu5wGx4RTRPF3l8GipFwAGuXCj5SwxyP+tMsLHpB/xYxz rX3kHqdgAyDds8Wcj+zgwutpS7J3CLFNMF6FVgbtsNDu+U9jCZZfJRKA2uCgntQiqDckVd2yWqJ lPxb7z5HvZ/wSzpO4SAIqPn5x6WPXuPike5oH4OX+lHA1r9NtdYWvKHsTYYka8y8ckO0mcZDuiF 6UHxcSpeOgrhtc6ZoBFuFuqFm3ro7bNhjf0yfTZ2Fm/R89RtNDFJCn9hg/48tfSS+QSGlglphfD rIcDPGkv22QFc5yUNKqANqhks76GzPvTjZLx5K5fwM0S7YYCPyEnhaoT1iJmsfmwJkFGjTmn7bj jKcACTkR1hf44ZoPnAc6sGa0CnJyLzjU9LCMo28jBa7KCGIBpX4hnr24xm//Sd1YsBS/1PTygg3 4o2bpXQbyhO4bXxcHfZlEY0lK8b/kCGz0SvPqDIXs0L60ZLkyqU+vYVErZyqQd4LIMIXQ= X-Google-Smtp-Source: AGHT+IHwO5gJ0kdRSW3C7w3wM/FzY5P/yuC26EOEV4IO2FkM82nS1kSz1CbBCVhzjZTGbWFJ875qAg== X-Received: by 2002:a05:600c:460a:b0:471:700:f281 with SMTP id 5b1f17b1804b1-47904b1b2dfmr51046175e9.25.1764211096073; Wed, 26 Nov 2025 18:38:16 -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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.38.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:38:14 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Kieran Bingham Subject: [PATCH v5 15/24] libcamera: software_isp: debayer_cpu: Make getInputConfig and getOutputConfig static Date: Thu, 27 Nov 2025 02:37:30 +0000 Message-ID: <20251127023739.179652-16-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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 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 2d385cf01..a395fc97c 100644 --- a/src/libcamera/software_isp/debayer_cpu.h +++ b/src/libcamera/software_isp/debayer_cpu.h @@ -98,8 +98,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 Thu Nov 27 02:37:31 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25253 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 6D53BC32E0 for ; Thu, 27 Nov 2025 02:38:23 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 94B4F60B2F; Thu, 27 Nov 2025 03:38:22 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="Kbvt6NF3"; dkim-atps=neutral Received: from mail-wm1-x331.google.com (mail-wm1-x331.google.com [IPv6:2a00:1450:4864:20::331]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 1C6B560A8B for ; Thu, 27 Nov 2025 03:38:19 +0100 (CET) Received: by mail-wm1-x331.google.com with SMTP id 5b1f17b1804b1-477b198f4bcso1723635e9.3 for ; Wed, 26 Nov 2025 18:38:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211098; x=1764815898; 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=VHmyzGkOwao2iOVfyxrEPPmvuSeYu4ezxiDGM411cRc=; b=Kbvt6NF353QnjRwae+oVWjtEfC4z6gUUdYBwmAPXNr5nQdtB3B1PYE1XtKkNQaNgIO ngy4hGcC2bY0cmP2AY1E25EdmTAXcOQjVnFWRMJeTGqCJinh45270uP5Q5gbtXe580MS icCaiDOqSVwQgl0xJ5FNqLBOB+yRN2ISpNA7xa+HbtRQ2Bv2YRkC2GNSab3OOZbTBnGN ws3kM3Nb7nNlCoHOLkI7MFxmjsCyOQpbkKRnQ3j6fiP+FzjK4DAlCJpUSkxS7kQh8dRU mR6ZWmZQuR9GISJRDNabKMMjkyEZiUEb01fVv7Kgpk1Q/Xmy/xKW/Pf2BAcsU9fC3BMN Z1HA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211098; x=1764815898; 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=VHmyzGkOwao2iOVfyxrEPPmvuSeYu4ezxiDGM411cRc=; b=ecYISd4G4y0XjPvQGppOjo73OsIewoWr6vMrrmLFxFkDhzznli+4+FIMt9Cez49+m9 4iAcwjmU/SNz29ufiTqZMz50TgCO1A1LWga9ggiB9OdAVkWWiM6RugACeRXLVEJ2yAmy IKbc5vfc50T9q6nRMQ1gbsRfTrdrh31ZectbmgF51DcgGw6CQdyXKQIg6eCBuXxFt4tb +y2vnWLmh826N1N4cMpqPBQffCgDXkVghm3AX2YC2kdDK+weoHhtWjq2nvoj53tRvXfr 6xs2N2LwCgkah6ksLwBQTcNwPrEqLL5J+IgmPL9p8zei/qUnWyBbsze0+sFdcJaZSr4q zpBQ== X-Gm-Message-State: AOJu0YyzRJ9mWTQ+3K+JHEzWBbuZ5t/ZwUXpxZCPNIDpxpHp1adr3HQk a/nxsON6JkvdfdncUxWdkzZLCrF79AmwDE/hkKHlarYWvjjo2oyAOze2W+zGGEL7C8Wx4fWtL3r A+5DULXc= X-Gm-Gg: ASbGnctv/3b7P8YLo8ku0VN5qeY+tNVMDeJte7UVEEygqU+PMPETXiP45CE8d8pMRLq 63viep3cBnXiTHZ62lKtv7mg/Tt8hgIulbP4SPoL9Cey9rwJXGtI3g4qqqN9PM4vNhrO8zTSAq+ DxNu55EFLufBnWutTn6YKO5bVvIP7SrsHBoM0i4y9NQnbxj0tdeKyLWAg0taqdn3lF2DuriHs7G /bGVvPfJtokMoIGxmQI3oeudwNelCPpIgxmnNXlCk6wyC/EBqzpTW5yxXqs4JQe8du4vfMIfib6 GNG+xedWCKjKd2egCWOQ3Ipj37lDXv4GVM3tpFaQAwYzXkqx132xq1AqURSam93A7zTlNbODH/b RPC0fZeGg00FvoC84emnESj1dS7E/FFYeDKEMqv7XfTXwu55eO1/2lPv7jbw2gcGmDj+ZXBGIEl 6I6Lp0rg2gT7XbGPzLpTQ7K3CFpmt3yWNsnuzChphZ2ehT/bQkiWapBFXHMeSeQLgmHS5938Kgm q5c4A== X-Google-Smtp-Source: AGHT+IEAHTrmNmaP3m3VEtqo79dhNwcGcH7eucevY9b7r/Jawtg1SaqXgXIrUAyd/jj1AKZhz7HNyw== X-Received: by 2002:a05:600c:3541:b0:477:9650:3184 with SMTP id 5b1f17b1804b1-477c0165bc3mr213171935e9.2.1764211098387; Wed, 26 Nov 2025 18:38:18 -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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.38.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:38:16 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Milan Zamazal , Bryan O'Donoghue Subject: [PATCH v5 16/24] libcamera: software_isp: GPU support for unpacked 10/12-bit formats Date: Thu, 27 Nov 2025 02:37:31 +0000 Message-ID: <20251127023739.179652-17-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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 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 43ed99e33..7f24fe954 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -47,9 +47,17 @@ float apply_contrast(float normalise, float contrast_in) 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 Thu Nov 27 02:37:32 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25254 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 E7AA3C0F2A for ; Thu, 27 Nov 2025 02:38:24 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9171260B0F; Thu, 27 Nov 2025 03:38:24 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="sSua98qs"; dkim-atps=neutral Received: from mail-wm1-x333.google.com (mail-wm1-x333.google.com [IPv6:2a00:1450:4864:20::333]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 1034D60AB8 for ; Thu, 27 Nov 2025 03:38:21 +0100 (CET) Received: by mail-wm1-x333.google.com with SMTP id 5b1f17b1804b1-4779cb0a33fso2936345e9.0 for ; Wed, 26 Nov 2025 18:38:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211100; x=1764815900; 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=wNqHKfrdqEnCd6e0vklefM1kTOpuhhmzodWah3Zo3gc=; b=sSua98qsWzVhcyY4U35J8XFhp1oyUgGdo2EdxbLAGFXC2p2HN9IKM6lJyuT2VeOfIE zkbLa2IOYotQ4R+D1KzrJ7iPFjFlJufKsQfo+AIx93BzzoNISUIIeJyV2pm0Z7RHqV4P 2ogH4PBfiJQhdsy5/IQHH9+lovuj6f8W402/73j54W6qIXu/5TZy+7dDIiDA3gwnLO8K Em/wU8XPbW6ve1dX5+DMs06o5YL3oo17oxJG+FCyK5bE0KtfGd3OLnpzrPyMtjjn0dpe i2qY8aGoWimEuDRxKJjpGpuc/xo1elMWZPOkBUo9Cx10iXwqXgUZc00IL0JcG0N8OtNV 2Fvw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211100; x=1764815900; 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=wNqHKfrdqEnCd6e0vklefM1kTOpuhhmzodWah3Zo3gc=; b=dlVUiwiYLxlyMst4pXvX6nm7fobaQn/y3uDXrm+g0Ox2/T4O7/n9Lxiioxlv7WE8JE +2dZ2eY2W9p8m2lHR3HJ9NkMVd6hgrpqefLZV6hd372UyjA6RgdJYy9u6WL2QEyUMYOP YXo2iWOnKF3lxm6I0/v2EjN1wS81AjSspm8TYDFhT0rLDzJERvoSFXSEGpTlR3pYKuKn NLEJX1/Q/LuMDn2pEeTE8SloPqJM9mgnZzFNfAwsWnwYZwEHICxNIUeUq3nNLcMjDkbA EbBUEoOQme0NQVYucsExmdRvX0EKZvdUCPNJgkhEANE63VIz+lK3YvXY1XKBDKJF5Pvu mTVA== X-Gm-Message-State: AOJu0Yx3U44UZgOOgU3KCnte6c2hip7p83blwLF0k5nwg2UXbSe9EEa9 uuMLohV5zqWoNt9xyizexK1aO1Lh/AKFEg42BB5vITEgqNJs3H9Tlsmm1ttxBrOrZaCRF10a0T+ 0bs7ywA4= X-Gm-Gg: ASbGncv99VWr1yT7QnEifropehnwf7rO85D/aqPe7a5mth6+1fWBs/t5dpRUeowEqoW tVZNjsn9MOjSqcSVXN5unjgjqWpba2yezzuAI4tvbh74oOFpJ5by4ctmH4dpj+rcPsU/a3CphPq 0VH7qr+Mk/Cu7lvJtPxdSCianQ371kenXus8Am+GA07k8ZJV+h/OaBKqg6qkSQmfpz1XU9M/cIY khtF/rkPAyA+o4panEJYOwgontwqN2TvLHBJWa9lqJM9gVP1Dippol5AQ/1w4+r5NBr/kpjkhK+ Te8yPDQk/ojYnioS1a7JtMGRsTaLRY5VjREPvG9rtfnHseo0K/xai/IqJ6PvB6JBP6f92GVD43D BK/Kn7lm1oIXVlc1P0wljHidzxmRKFsikmUAZwE7MwApc0RyRkwJugUXj9GvoIPJOfIIhPf0m7v oaZ89j7zm5+fAhTw9TK5MAU0h2eDeROu7IuOXNjbPoctfj46RQP+fu/cENPBHrdnj0FbM= X-Google-Smtp-Source: AGHT+IFqX200VboC3AtNvqi0QDpyUB95dLnWrjnYxzzpv17YHNRnvGnvLpVa1g3pGaLZSUTP2lHZ0Q== X-Received: by 2002:a05:600c:470d:b0:471:1717:411 with SMTP id 5b1f17b1804b1-477c01edab1mr272526585e9.24.1764211100395; Wed, 26 Nov 2025 18:38: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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.38.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:38:19 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Kieran Bingham Subject: [PATCH v5 17/24] libcamera: software_isp: Add a gpuisp todo list Date: Thu, 27 Nov 2025 02:37:32 +0000 Message-ID: <20251127023739.179652-18-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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 Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/gpuisp-todo.txt | 83 ++++++++++++++++++++++ 1 file changed, 83 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..768dcc320 --- /dev/null +++ b/src/libcamera/software_isp/gpuisp-todo.txt @@ -0,0 +1,83 @@ +List the TODOs in perceived order of ease. + +Version 3: +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. + +Denoising: + - As below still TBD + +Dead pixel correction: + - As below still TBD + +Lense shading correction: + - This is WIP but as yet still TBD + +Lense flare correction: + - Not WIP still TBD + +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. + +Version 2: +Make GPUISP default: + - Right now the environment variable allows over-riding to swtich + from CPU to GPU. + - Once we support 24 BPP output on GPUISP we will have the same + pixel format support as CPU and can set the default to GPU without + regressing functionality + +glTexture1D: + - Initial code was developed for < GLES 2.O but since we have fixed + on GLES >= 2.0 this means we can use glTexture1D + - Provided this is so amend the shaders to do val = texture(x, y, 0); + not texture(x, y, 0.5) the 0.5 is because of using glTexture2D + +Denoising: + - Run a denoise algorithm in the shaders + - Supply a control to influence the noise-floor ? + +Dead pixel correction: + - Add logic to correct dead pixels in the fragment shaders + +Version 1: +24 bit output support: + - Take the BPP we already capture and get a 24 bit GBM surface + - Pass a compile-time parameter to the shaders to tell them to do + gl_FragColor = rgb not gl_FragColor = rgba + - Version 2: + This is not possible. + gl_FragColor expects vec4 not vec3 on the output. + If you really want RGB888 run cpuisp. + +Surfaceless GBM: + - We get a GBM surface and then have to swap buffers + If we rework for surfaceless GBM and EGL then the swap buffer can + be dropped. + - Version 2: + Complete GBM surface removed, memcpy() phase removed also + +dma-buf texture upload: + - Currently we pass the input buffer to glCreateTexture2D. + We should be able to make the upload of the input buffer go faster + by using eglCreateImageKHR and enumerated the dma-buf contents. + - Version 2: + Complete sm8250 test platform shows 20x performance increase + with CCM. + +Render-to-texture: + - Right now we render to the GBM provided surface framebuffer + and then memcpy from that buffer to the target output buffer. + This necessitates flushing the cache on the target buffer in + addition to the memcpy(). + - Render-to-texture where we generate the target framebuffer + directly from a dma-buf handle will mitigate the memcpy() phase. + - It should be the case then that the consumer of the output buffer + i.e. the thing that's not libcamera is responsible to flush the cache + if-and-only-if that user writes to the buffer. + - We need to flush the cache on the buffer because we are memcpying() to it. + - Version 2: + Done in version 2 From patchwork Thu Nov 27 02:37:33 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25255 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 55FCDC32E7 for ; Thu, 27 Nov 2025 02:38:26 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B166E60AC8; Thu, 27 Nov 2025 03:38:25 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="sOEYBu0X"; dkim-atps=neutral Received: from mail-wm1-x336.google.com (mail-wm1-x336.google.com [IPv6:2a00:1450:4864:20::336]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8E0B260B2C for ; Thu, 27 Nov 2025 03:38:22 +0100 (CET) Received: by mail-wm1-x336.google.com with SMTP id 5b1f17b1804b1-477619f8ae5so1499555e9.3 for ; Wed, 26 Nov 2025 18:38:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211102; x=1764815902; 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=mmy0r+9dV3Qznnotmc5WkFhDt1dkOI+Qma0jEOM5Zrc=; b=sOEYBu0X7Yk8cwW9O6N74IB9YMYiqZrgU8ePCb3uuQdGNBjs2opRDJIKxhUBX0mn5D JD4VXIhM1CS49Gw523u8t3206tx3v+9AXn3vBO8ICc/LqAAAHQKALf7X/fsll1QxG6/g L+4FnDBtLu8tHd31qZ5rVMAlAEE/c5e/1xIvtqJg3HjA8ZGlCfgaCT6WL06gBoxvloHj e2pR8gbcTLIaJo3Z8SxV0k+LScyq9Qi7fvldpPNvmSzuES25x2BYUETs3qEo9Cm+hcjH Xyxt+hU3kVh0DJ329xt1/0E87TUZ78UryKsrsovYsWhXjOUx56inTOiQTpp2sm0PgzsJ Y2ww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211102; x=1764815902; 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=mmy0r+9dV3Qznnotmc5WkFhDt1dkOI+Qma0jEOM5Zrc=; b=Nfk5QrBnogRfqZW67T6bEm2wVuQkbytFYN5T1oXDDmAfrSpsQGK/83AETUWrUtbBYp GnUiglDPKTUhXPNbLnMaPMWD1kaJwxXGT7tJqVxJQGCARYQ1ee7G1i2bauDEQqnMGu9X clTbD9rb/pZw2FgCUi9BmlvTTrGydRnDmzLqAzSBjwkl07AhI0WxL6SI6bwUNOlgWC2h oHCZFAQcZh3mWPVy15A4j9NFV05eK8I/b0CsX8vzBfX0AIBeSbHFl7F6Pd0mzVaGUclj YJ1riqJKRy4NRR2uYSEgWBYQ+6Bg9ueJ1HuwD9DfOb/6OelEvyT7hriAxMdkS5LZCQNw lF5A== X-Gm-Message-State: AOJu0Yyt/XXP2oy/E/KJafDICA9VB3gexjC3JZpROWhGhTont1gNBm2I Lzu5f0muvljIx2KDwYGm4sGMcE/t3t/WpUy6Z/8nQ+fbuArMVf8+F9olJLE3+gZcy7Isdkk9b0n uvmMqlOw= X-Gm-Gg: ASbGncsMOC8KLGtaRbniUNIY1/xPY9VYxkHFI02Kvu0V1CV91wcfABXkAnShpNexyWx FQ/3h+UofyFwYk30Y2L5eBb15b0skrlYL47rRyPCoTW+2DdmUwEN/n/pxLf5hAI+AyZNWkBjLMr L9NCDjNKY24rHovPsBsHlEuTD3+NlHhd+kNpFeLzdQjuktp7CnryG06Rqsr4lSjAvrt28wBmQ6D R6Wo7QxpiFtodi/DzeU8PkcfzmYAOS/ppyINCGLl6kXxQNoMJErq+R+EcgpIYqAijtPxnFL1lnN E/1LIgkcUlcWZKrv/fLGg45r/PKFvhbRlNQ1ul/XNWedCD8+SsPY5GxX5ZKMa4VAJ6F7bVzcTCk u0IcPHIThGn2bjkUUVWGefNiBReWwfrMzGgWVnDmNdK2gN8jXPXepYZk3T5Sum2JvP5QugwoSJC DrQ2bMaorIByOOEOQJzYl8fADwUw/CBbfKFOTwgQ3A2zOfxHfMaTEcHu8PDVMt0dqHI+s= X-Google-Smtp-Source: AGHT+IEXPrzlY66bN30ZDRqCDRhf/9TqdQJRBVcMeOHx8cbrDsqqmSbn8Uy+uTgcOXx7alLZRhjDMA== X-Received: by 2002:a05:600c:a08:b0:477:7b16:5fa6 with SMTP id 5b1f17b1804b1-477c0162e8emr207173305e9.3.1764211101890; Wed, 26 Nov 2025 18:38: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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.38.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:38:20 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v5 18/24] libcamera: software_isp: lut: Change default Gamma to 1.0/2.2 Date: Thu, 27 Nov 2025 02:37:33 +0000 Message-ID: <20251127023739.179652-19-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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. 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 9aaab54f1..7f223e812 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 Thu Nov 27 02:37:34 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25256 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 8368AC32DE for ; Thu, 27 Nov 2025 02:38:28 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2E57A60C66; Thu, 27 Nov 2025 03:38:28 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="Wmj+esZV"; dkim-atps=neutral Received: from mail-wm1-x32c.google.com (mail-wm1-x32c.google.com [IPv6:2a00:1450:4864:20::32c]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0336460C66 for ; Thu, 27 Nov 2025 03:38:25 +0100 (CET) Received: by mail-wm1-x32c.google.com with SMTP id 5b1f17b1804b1-4779aa4f928so2352635e9.1 for ; Wed, 26 Nov 2025 18:38:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211104; x=1764815904; 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=16pZ/JdoiYUGtAtk/R99scAohK2wEjdJ1P32w9Duc1Y=; b=Wmj+esZVbEXhV3QaSG552fkvTS1RT0rvfh+IHPfmfQBY3BIDw9SPr451r6isHqiJv0 Erc59n2bQu277dnkKZHAYFj/z+MxM9sb9XlydFVgAs4AMl6ioVC29pXawgaODXG1Ii7R 9VmzUZkBsor2wKAT1/H7u5t4deXgVEyP6ea6aiF1GXXf24hnqLgr5gncvyRGsXQhRDtM hNxaEEO/j86k7jUL7MOTgXfdXRbPlD1Y6ZCUqMlhaYwAWYozzbnlSRpttrUmcOBIJ4CW WTINJ68yHXBTzqIXjtDB5CYws5uNXGJkYQKbSxNjV7C9Ik3Hgh9b/y5aJdZ7mntnpQ+f 8ylw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211104; x=1764815904; 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=16pZ/JdoiYUGtAtk/R99scAohK2wEjdJ1P32w9Duc1Y=; b=wXRuqVzmOpAOsVcuU+75qzTPirSIfI3UPVGVFtxgok1+iB57DpxtGVuIdOKwGyF2en 9JbUeL9Vs8osPX4oOTS89vCuGVjmjliZ/9zJqNV/QWNmZLYbBE0RXryuisb6gbUlToDg r7vI1UQQpt9KU8k/sPcNqj3ess/C4pYKC30z+iqHowd9ANhufhkgoXR/gAocSDLZvMAh 327Qx9W4TMYJv7vVbeSJyqmOmOKOz92ElvL9Vpe+sKlOH9Bn8iCzCS7CQ+SfDp9Liu0t RirA/xAiSktPnKvarq2O4BJtQowxSAVDT1zYzTEawZs4NpSRxwmHxgR7ZS7FwHtqfyLj hHwA== X-Gm-Message-State: AOJu0Yzq6vU014Bx9GRDR6EJvYxlTLquKNpw5PiOUY5M6g+IF4ZrU14J wrSogrptxymNJNrW3lzLGhISkR+Ot5Naw6cXRy3Ko7i2+wSorrhfhTGfbZQa2PwUEZhf/YYpuwE GjJCwbVU= X-Gm-Gg: ASbGnct8KeCMEzxlLzjC0iicOyN6/1jnDUmBOpsn7bluz/M2kO8QMDayPXkQT7etjy9 n9GzQecFEjv2Nks/S55tptPwvpJwWbn/+E4N/mVHOdCyjPaAH5nz+AVNnKje1DlKKoawHnr+Pqj sdETTbw7QMNEplbtnZ//oOsdmt443QK0cuGxDV4OIxPZrrdM7a5R+zvgHaVR8VcrjlUIXyrkG65 qa3a94wWpYE8HlKeNdRSapuCgRMArQUtVvD7/DcC9vNljpULKCM0ZDL2KGGXNrhFKHw2W4qBUNg 56BZqVqDzosxk036rimQJPWTKQ0HP5DX5J2r9d1e0ketGEAybb/OafMsj6teUziqsrEtbcW7qZI +cL3PS5+ZLlf+91r51gU+XfkyplnQsWqMej3ojofeTshS47MOc2eGFKBea+KfG3p68Z0Q9S/BBS j1x92dsfQZOJD+PVFqacTrrAHRGD4iH0Sbcj/IoBfdKFK3jiyTjHhUkRr/URUybXvz730= X-Google-Smtp-Source: AGHT+IHzIQR+1DCDyIpRDMKPSK0EfjrwE6u55O6LGP6G8W8hQTzwHfYw+msbMCGKWK7ttfDlA0gsyA== X-Received: by 2002:a05:600c:c48e:b0:477:28c1:26ce with SMTP id 5b1f17b1804b1-47904acef1dmr83249335e9.7.1764211104376; Wed, 26 Nov 2025 18:38: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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.38.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:38:23 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v5 19/24] ipa: Add a new Algorithm::init() to support self-initalising algorithms Date: Thu, 27 Nov 2025 02:37:34 +0000 Message-ID: <20251127023739.179652-20-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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 in an algorithm init() routine which can be called in the absence of a Yaml input. Do this to allow an algorithm to set up a default set of parameters. Signed-off-by: Bryan O'Donoghue --- src/ipa/libipa/algorithm.cpp | 13 ++++++++++++- src/ipa/libipa/algorithm.h | 5 +++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/ipa/libipa/algorithm.cpp b/src/ipa/libipa/algorithm.cpp index 201efdfdb..da44c77ca 100644 --- a/src/ipa/libipa/algorithm.cpp +++ b/src/ipa/libipa/algorithm.cpp @@ -38,7 +38,7 @@ namespace ipa { */ /** - * \fn Algorithm::init() + * \fn Algorithm::init(typename Module::Context &context, const YamlObject &tuningData) * \brief Initialize the Algorithm with tuning data * \param[in] context The shared IPA context * \param[in] tuningData The tuning data for the algorithm @@ -50,6 +50,17 @@ namespace ipa { * \return 0 if successful, an error code otherwise */ +/** + * \fn Algorithm::init(typename Module::Context &context) + * \brief Initialize the algorithm with default parameters + * + * This method is called when no tuning data is available. The algorithm + * should initialize with sensible default values. + * + * \param context The IPA context containing algorithm state + * \return 0 on success, negative error code on failure + */ + /** * \fn Algorithm::configure() * \brief Configure the Algorithm given an IPAConfigInfo diff --git a/src/ipa/libipa/algorithm.h b/src/ipa/libipa/algorithm.h index 9a19dbd61..9fcbe23a9 100644 --- a/src/ipa/libipa/algorithm.h +++ b/src/ipa/libipa/algorithm.h @@ -32,6 +32,11 @@ public: return 0; } + virtual int init([[maybe_unused]] typename Module::Context &context) + { + return 0; + } + virtual int configure([[maybe_unused]] typename Module::Context &context, [[maybe_unused]] const typename Module::Config &configInfo) { From patchwork Thu Nov 27 02:37:35 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25257 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 7E526C0F2A for ; Thu, 27 Nov 2025 02:38:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3813560AC8; Thu, 27 Nov 2025 03:38:31 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="E67RJRJj"; dkim-atps=neutral Received: from mail-wm1-x333.google.com (mail-wm1-x333.google.com [IPv6:2a00:1450:4864:20::333]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4212860C68 for ; Thu, 27 Nov 2025 03:38:26 +0100 (CET) Received: by mail-wm1-x333.google.com with SMTP id 5b1f17b1804b1-4775895d69cso1144955e9.0 for ; Wed, 26 Nov 2025 18:38:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211105; x=1764815905; 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=XGZEOlg3N1WKIZQYXL2EvkWqNCC95nhRh04jkinhjFs=; b=E67RJRJj7Q/nEpQohbeByB0My/BX2QmeUGLEUSDFscus09NFeJxOHUJ++TIPnJhbEf yN8HX7Eo0t+ZwPrGGF7A1OFsbn8rTLpiq5ilTsXzcYAGZBSCQPAgZSRbcKlfzdXib12R qYOc07IoeQYZgIDJmD7PemCHjQMOnjyyMXr9Yzib7dN2QSkXZ7QYgBtNiONH7VJ9NvV+ 3VbbyCqdTb9hHN08YquF1hS0iBMKnOKsyscm9vMQIsnV/91Ll33A+S34w2v/ws7BTFnB vPLQJovd3t5SlQOzs/FHV8LOTuODtuGzzd9SWpvRuXddBN8q8fQMyGplgzGv21BH2uUc yOew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211105; x=1764815905; 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=XGZEOlg3N1WKIZQYXL2EvkWqNCC95nhRh04jkinhjFs=; b=mTs+/hd3VBM9Jo/uF4yYstOTx8yHCpV20/QXTptVh9eh4BKqWjAb6jUd1QG/pKBYEq HGDT4368KKLsnpEYe0wcxe4+r2LMEL2+K/4KZsfpWikJ6q8tz+Kqx8w/5poskuJmBIjE C9d+K7EwAnLJNW8JmmqdOPh0ozjbHfAfItwRRvI3QJTN/isNDnfkDWmAydoyzpTcZZ8Q EEKi1FraGAAqh7Dp/vPI2Dl4jpR0D0Yxum4f9BKJcl2ShP8gwxizQ4JKebN2WAmzL5yT xPEMxnP9dcZL5RcLYNwMo7ZxaozmZviCCQL71//NV+nS9+OyJp322a+uTsuhYOCrFbs1 i47g== X-Gm-Message-State: AOJu0YwrrxXOTc4zORQNK1l7CqVctPBh6KNvk4eVBaTXC8XCNrRh65Qz V8UjkzoMmpjmI1EmglbG4lHs9Vt2z7Oy7fu8yz/XLR/Gqyab+oJxVuu+PK1CT0zO93G8UiCfdD1 g8B+oqrE= X-Gm-Gg: ASbGnctIZK59NXXZrY+/tZT8ugveYe/8DjNLupV28fGv4j1HEIr5iCGNnBOb5axtMBQ YYPYhZBXLZTvxtfrlaHOoOlNqejW6H3uKb0UJuKYJyOZGLYeNEI2/8GdiSDlQbWU04/4Jbc+8c2 gpYCTeOpEOJmvPyK43eCukl3hsEZOIKMq2f9C+XKYPmedPII6jOrjtUcZswVQnWYJEyvmvMY7qr Gdb4I1+eqvUZ9eRZQiCLHkrhEM9dCppYXL4ZlZDg4Ob7th/7ALyOaQp/8hgy4RJxoGRaNYIHSWJ mf619M522GvFJxneoeIahe0WGSrQv37gR87MHhqSKLeZO3SAksOwXyKoRYTDnXFY/7sa2LOBy9C w77QK81PZLJO4IRl3BK0Gl3/YO4n8QWzwFi+xunRXGMpnEHSjWNL9hBdFXURlFci9wSqSoKQsJx t1m+TGHhjPkOrrEMaolDwuCpGVBFYna/VW7Yhyiq/NSENG9bV70C1TUqHSrSa8dm1X6Wk= X-Google-Smtp-Source: AGHT+IFvWfWYkN+rc0xLbjG+TdVbs+pnGLNubdJos3xPRMeIlU6MlnjEfdWYaEu5n3FuiLeTr2On8Q== X-Received: by 2002:a05:600c:6287:b0:477:7925:f7fb with SMTP id 5b1f17b1804b1-47904ad0724mr75489355e9.10.1764211105619; Wed, 26 Nov 2025 18:38: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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.38.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:38:25 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v5 20/24] libcamera: software_isp: Implement a static init() routine Date: Thu, 27 Nov 2025 02:37:35 +0000 Message-ID: <20251127023739.179652-21-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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" This is an overloaded init() routine that allows the CCM class to self enumerate a default identity CCM at colour temperature 6500k. This is required for the case where we are running GPUISP but don't have a CCM for the sensor. In this case we want to generate a default CCM and use it instead of using the CPUISP's lookup tables. Signed-off-by: Bryan O'Donoghue --- src/ipa/simple/algorithms/ccm.cpp | 18 ++++++++++++++++++ src/ipa/simple/algorithms/ccm.h | 1 + 2 files changed, 19 insertions(+) diff --git a/src/ipa/simple/algorithms/ccm.cpp b/src/ipa/simple/algorithms/ccm.cpp index 0a98406c1..e3da6adfc 100644 --- a/src/ipa/simple/algorithms/ccm.cpp +++ b/src/ipa/simple/algorithms/ccm.cpp @@ -42,6 +42,24 @@ int Ccm::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData return 0; } +int Ccm::init([[maybe_unused]] IPAContext &context) +{ + /* Initialize with identity CCM at standard D65 color temperature */ + float identity[] = { 1, 0, 0, + 0, 1, 0, + 0, 0, 1 }; + Matrix identityMatrix(identity); + + std::map> ccmData; + ccmData[6500] = identityMatrix; + + ccm_ = Interpolator>(std::move(ccmData)); + + context.ccmEnabled = true; + context.ctrlMap[&controls::Saturation] = ControlInfo(0.0f, 2.0f, 1.0f); + return 0; +} + int Ccm::configure(IPAContext &context, [[maybe_unused]] const IPAConfigInfo &configInfo) { diff --git a/src/ipa/simple/algorithms/ccm.h b/src/ipa/simple/algorithms/ccm.h index 8279a3d59..b46f17726 100644 --- a/src/ipa/simple/algorithms/ccm.h +++ b/src/ipa/simple/algorithms/ccm.h @@ -26,6 +26,7 @@ public: ~Ccm() = default; int init(IPAContext &context, const YamlObject &tuningData) override; + int init(IPAContext &context) override; int configure(IPAContext &context, const IPAConfigInfo &configInfo) override; void queueRequest(typename Module::Context &context, From patchwork Thu Nov 27 02:37:36 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25258 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 B333FC32E0 for ; Thu, 27 Nov 2025 02:38:32 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2A40260AD0; Thu, 27 Nov 2025 03:38:32 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="Aq1Gl/yL"; dkim-atps=neutral Received: from mail-wm1-x32e.google.com (mail-wm1-x32e.google.com [IPv6:2a00:1450:4864:20::32e]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4445960C68 for ; Thu, 27 Nov 2025 03:38:28 +0100 (CET) Received: by mail-wm1-x32e.google.com with SMTP id 5b1f17b1804b1-47798ded6fcso1421985e9.1 for ; Wed, 26 Nov 2025 18:38:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211108; x=1764815908; 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=woB0MgjmWr8Zdvt/377QQWSwZ83OLYd14divLlJMGJ8=; b=Aq1Gl/yLk/dc1rGhnplb5F9RqNiDuXmregiDJSHRBnxGThTLu2thuNwvJPfPg6v16l njT/9VTOclgqhTgtKTBP5DaKgP65E2RosnDkzGaalmFzBQqaNNcQkNyLqbim8MPw2YCj 3RdAhNkPzP+oDt6R9lfDj7r0aSZO1XGrma16NF8Tbfg5PFfgNBNxsVa3DOJx9iK7g65u KTfVkXzRDOdlKehFafjvfG06N0mA1h2kDAtqD6CCZ105Xm9VfptwekYJa0sN1HcXgTyq Xeq4GhW+NEePF7Q+HCqRBBbE4PQlXSmqt/FlVlkthDcI1DX6bMrYaipiTNTD4rf1tJ/4 FtiA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211108; x=1764815908; 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=woB0MgjmWr8Zdvt/377QQWSwZ83OLYd14divLlJMGJ8=; b=Kvuvs4IK+9loQJnlG20RQmGAR44kb5U+6WCSk+04W4+LPhO7yhSNhDt4xZBwmPuJfN m+q0EzrUFQw0C00hPmKo0TP4Y0MxFL5cpn7Aia2IN8Xlrxyo11XGl1YAT69wuRBhu1xr 6Y4FMXLAOeKD2UljWBrd1sZrdSBTUL7M3EGrKuE1AEXGyfkQ/spiyIn1pswjTdbnsd4c fAtdrerEoUj/UCALVddSMiSAw0yUn719JEevfkqMTZIjOMIeIiLKgI+FdwPKWtg31nmv OhIDxkoA1/KPwXM6AcvcgsoXv/WAaaY4MFynDqgtepHWytSGXWydItGip5xuMyPctpbi 87BA== X-Gm-Message-State: AOJu0YxQdbPQTex4nRQBD4E7WEqy1jiXUX+LERxk3LPSWilp+/mOgJo+ Y5+bw1xrbbKSPG6ROEfcBWLI264Oae21MUylRtedoXcW7yXfPnoOGc/n+wEhvAat2vAGw3K8ZUR pj4FrXa8= X-Gm-Gg: ASbGncuqUCMVsKLF+Sk5q4IwfU7vPmVSrhqg0cSdSE/mvOdIRhM171Ud7n45E0fSe8o 8XcdqCL5lHWhMKEEplvRghhqR7C5cJkav49IIykd38+ZtVWE1dCK6CWd4FuSjHEDysOtfcXGAx8 5z5wAbJL6eqp0Hw40W5sWlze4Mw7OVp98wmZXrSQmusuS6a0Oe4O6Lbbr64GtRQRgceD2aM5a0a hoO3gZ6IaNRI9DUP0WvOUWYaVrnqZNB4uncmg9pRU2QVAli+zdUctAKcu/iA9kPq/hM3ygYQuvF KwbSEvi2Ien4LDF1aKig5JZR9Z4oW6dtf/QMKoFzKTLfCrtnY46sdOvdHKOThUe7eVfKxDa+OoK OUpCpPBDIEFKH2A9GWSw4SurPx93Xyebsbsz6w+EbkTEK+g0tcMSCpbNdwwn1IKhLTLOw2+HpBO 3ozbZNLrnEcgCw3jKuzXGDdnq2VEkY1eBUgLSJeEG5XkvxI71bVvyzQ8h9BgEUzrmmwx33VmtAE SIIng== X-Google-Smtp-Source: AGHT+IEtUuVL65j4R+Pi3HuwdEsPnLIEGhWstSoMBW/2jBbnQaqFFXnE5N6r1qwislYeJPn3eHIExA== X-Received: by 2002:a05:600c:3511:b0:476:d494:41d2 with SMTP id 5b1f17b1804b1-477c112f7b1mr210333385e9.29.1764211107659; Wed, 26 Nov 2025 18:38: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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.38.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:38:27 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v5 21/24] ipa: simple: Add a flag to indicate gpuIspEnabled Date: Thu, 27 Nov 2025 02:37:36 +0000 Message-ID: <20251127023739.179652-22-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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. 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 | 8 +++++++- 4 files changed, 13 insertions(+), 2 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 c3081e306..ee8fb6b03 100644 --- a/src/ipa/simple/ipa_context.h +++ b/src/ipa/simple/ipa_context.h @@ -103,6 +103,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 b147aca2e..2bbe271d9 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 a54dcbaf5..8479760fc 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -130,6 +130,8 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, } } + bool gpuIspEnabled; + #if HAVE_DEBAYER_EGL if (!softISPMode || !strcmp(softISPMode, "gpu")) { debayer_ = std::make_unique(std::move(stats), configuration); @@ -137,10 +139,13 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, LOG(SoftwareIsp, Error) << "Failed to instantiate GPUISP"; return; } + gpuIspEnabled = true; } #endif - if (!debayer_) + if (!debayer_) { debayer_ = std::make_unique(std::move(stats), configuration); + gpuIspEnabled = false; + } if (!debayer_) { LOG(SoftwareIsp, Error) << "Failed to create Debayer object"; @@ -177,6 +182,7 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, sharedParams_.fd(), sensorInfo, sensor->controls(), + gpuIspEnabled, ipaControls, &ccmEnabled_); if (ret) { From patchwork Thu Nov 27 02:37:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25259 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 D3204C32E7 for ; Thu, 27 Nov 2025 02:38:34 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8A1EB60C6F; Thu, 27 Nov 2025 03:38:34 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="F+odiLz1"; dkim-atps=neutral Received: from mail-wm1-x333.google.com (mail-wm1-x333.google.com [IPv6:2a00:1450:4864:20::333]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8C93C60AD0 for ; Thu, 27 Nov 2025 03:38:30 +0100 (CET) Received: by mail-wm1-x333.google.com with SMTP id 5b1f17b1804b1-477632d9326so1689025e9.1 for ; Wed, 26 Nov 2025 18:38:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211110; x=1764815910; 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=e1pvUqnYS1JGS35UGpDUFqEIzGsf/5dEKRFZ9jpd2jQ=; b=F+odiLz13Sbgj9+yQLaXrZzjCGeT9nREiW20SRth2gyi7FqNPvCUv+KkLMfpaI0bCq ru7hx3QI+MU5K44d8y2Qw/g5O4NOXFyDYvWDbRJWV9UNIz2NIXVp1B70kb4bOmc2jLpA eUSagcWWcDqWb0FMOH2oml90ETE2n2u7Rhox1Ca5agUeb5qB8rdB518fD+RJMlDVmMvh jv55sSbDqNHj6d6MZpIS5ZvtiTbO18a+/FL0OomNrIge2tKSr6wxDWF30QrT5EaTvVaE WogOuPZ94dTiexefcCBJvG733aixkTjxCsT5IvRVv2tBMJ0qQhXSbeiteFBfIibPKU/t dMaw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211110; x=1764815910; 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=e1pvUqnYS1JGS35UGpDUFqEIzGsf/5dEKRFZ9jpd2jQ=; b=O/wmDzkhYrgQeZPiqq70u+Wv3Ps1fR1ae0hh4ZFYlLyNLN5+IkrSXcFJaF6gRR0bfn R1Nh6SE0WliA81/g5klJw4Zg7lS8HR64yDQ6MBeH+Bi+dajXsYXo8UyJuWPzyiJ0/5at mn1ssAonAk3bnur/i0aYfwdBPDfLtus1Y7PEA5YReuzyR6dxPZ9JneoFrxNk+6BSRbq0 dVPniPN/AlsHhHacarnjn6NlAlovzEpjO1VeyJ6NXQqq+ABleJcR9/e/hebyMAIYToWE SEWJCBe6lXA2xBkMzJ/VaqShWX00rwYYHctqVYx7pFwnNngvaSx/Bob3liBMu4q6+Ap2 Oeuw== X-Gm-Message-State: AOJu0YxmGz1FkWGzqCLvgok/vGTqyUplj+vB8XesCXOlSCaAugUzT/ip IrNLSKcS6B+0UBI28rF5YnS6A3mP2lhavPYh6Lj0THqo1ul3wo66zZD4UhZEm6WQ12ngSQ7A6Qe KVZiT7ac= X-Gm-Gg: ASbGnct0vmmSscp905hLihr414zGgqWUsGyMx3Dn/HdoZlbnamry8xRZcq6hqokF2a6 pM+8WV2HLLdGGhJOCOB1Sj5jo95eJFXwFERfe7KpJMvf/ZHqpPZl//x9iZy1g5UMxCXR/c5Z0lH SRKXzMs3znwxY+f+7uX+LzgE3PWUSDLsO0uexqdo56JYE0ntMNjLfzxhU9k5eb0yyigVX8vSJ8s UfcWxLOuiGlfXWEET5GBdlwdhAkb9bn58XZf3pL/jyASRsPIpdDBTxh6B84ZvkFjrDgfGedKS+q 6QbfErwb8F8HqjgjcCi4eYgEKkJMmAgEUbVU99AgTadOiAwnS6kdq+xVDIKK1+YJLeDp+L8wEU5 b1rcCugvA9j3RhyyNmSq/N7TcGgERS2gYbH1Gu9dSaHC3TgKwJSavArx1ShFstsOJcTisMFb2hQ zYHTUag0QcvQ+lict21hIAge3Zjf7k18WPjQ8g0p8rxixvePA47bOBolffgRBRj8hwGvo= X-Google-Smtp-Source: AGHT+IEwcxTZY0Cb0FU6rZAJA0EnNJ0oSzL1UQvMnf/VO67qkvq6wtAEhLAUtkC5xkG6wcgN03yOPA== X-Received: by 2002:a05:600c:3b09:b0:471:13fa:1b84 with SMTP id 5b1f17b1804b1-477c0185bc8mr249392525e9.12.1764211109900; Wed, 26 Nov 2025 18:38: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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.38.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:38:28 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v5 22/24] ipa: libipa: module: Add createSelfEnumeratingAlgorithm Date: Thu, 27 Nov 2025 02:37:37 +0000 Message-ID: <20251127023739.179652-23-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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" Signed-off-by: Bryan O'Donoghue --- src/ipa/libipa/module.h | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/ipa/libipa/module.h b/src/ipa/libipa/module.h index c27af7718..f320291e6 100644 --- a/src/ipa/libipa/module.h +++ b/src/ipa/libipa/module.h @@ -70,6 +70,47 @@ public: factories().push_back(factory); } + /** + * \fn int Module::createSelfEnumeratingAlgorithm(Context &context, const std::string &name) + * \brief Create and initialise a self-enumerating algorithm by name + * + * This function creates an algorithm instance from the registered algorithm + * factories using only the algorithm name, without requiring YAML configuration + * data. + * + * This is useful for algorithms that don't require external configuration + * parameters and can self-configure or use default values. + * + * \param[in] context The IPA context to pass to the algorithm's init function + * \param[in] name The name of the algorithm to instantiate + * + * \return 0 on success, negative errno value on failure: + * -EINVAL if the algorithm is not found in the factory registry + * Other negative values if algorithm initialisation fails + */ + int createSelfEnumeratingAlgorithm(Context &context, const std::string &name) + { + std::unique_ptr> algo = createAlgorithm(name); + if (!algo) { + LOG(IPAModuleAlgo, Error) + << "Algorithm '" << name << "' not found"; + return -EINVAL; + } + + int ret = algo->init(context); + if (ret) { + LOG(IPAModuleAlgo, Error) + << "Algorithm '" << name << "' failed to initialize"; + return ret; + } + + LOG(IPAModuleAlgo, Debug) + << "Instantiated algorithm '" << name << "'"; + + algorithms_.push_back(std::move(algo)); + return 0; + } + private: int createAlgorithm(Context &context, const YamlObject &data) { From patchwork Thu Nov 27 02:37:38 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25260 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 311ECC32EF for ; Thu, 27 Nov 2025 02:38:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A88BB60C6B; Thu, 27 Nov 2025 03:38:35 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="u6ytNMQX"; dkim-atps=neutral Received: from mail-wm1-x333.google.com (mail-wm1-x333.google.com [IPv6:2a00:1450:4864:20::333]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F165D60C6B for ; Thu, 27 Nov 2025 03:38:31 +0100 (CET) Received: by mail-wm1-x333.google.com with SMTP id 5b1f17b1804b1-4779adb38d3so1790785e9.2 for ; Wed, 26 Nov 2025 18:38:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211111; x=1764815911; 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=Fl7bKsKAlYLaLttSHKhj1oGaJ2+iNv6A2IYhlzS7gvI=; b=u6ytNMQXW9qdyoRT2fDSTXdVvTy2KyTcoZtY3jBGgGYsl7lYEmeTUCniYQqPo9gQpn AIEn5MkF4+/YTIMpDC8sc9ockt6mHZbprUSGvPFe+4+VcmCY70iIbAlyMzmaHPLO4pBP Pzrsz7oZrZgLpJArEVq1al7LOHFaJolHeZc3KUsic5JUeEaDvmyfFI7F4PaBQ2Dgln7C N3v+K+aE0sJhjKBFjSaAXXKBXN+JPcNJE0S80P5o5WfoAODuWD6BkYpCWdxj465gYW/7 d7ku9h0JFyO4F/e+6tSQIhK1g2YmnGVGksLFuLlio9oB0BplQmoPNXt7X3/hH30avNa2 Mcxg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211111; x=1764815911; 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=Fl7bKsKAlYLaLttSHKhj1oGaJ2+iNv6A2IYhlzS7gvI=; b=caInulDHt1y3rvjOoQeA3OAsgkf3+XG43whEJXdLWwbF9DPsz7Yf5mAaA6MpFuyLXW S8ZLUBac27j2VBpWDKtpd9wKcQ8wSrawiOSQu5uixO59mIqzgZPGFwLBSh2Wt+E1ZfHq i5+HOf6aR2Dd6yFM+OzgXZkcalzBCFEo4rKXtBFcrh3zeP6nHLpDg1yQ2vVQb/+PO+cv bOnZLWonE1SY1ZowzJRZmnxIVTpMot36z2zAp0Dn67WEC1k/10rx4PaDMhcwFYn8FmuU YvlRsOe0TIMnpQ6zvbV5/bhPYS5j0tqxjcXWrDkgpmIKZuCwQ2frqbq1iilBJl5rO3l0 Gn4A== X-Gm-Message-State: AOJu0YwiSANd6KXgUylH6bFKv2DXSuovdGly2CyztLt2ixuD8w4HoJhO II2rHHt4M8TUg5PUGEyWcmKbZuVljCiMoul78e0z5hUiAMvmN0NjIEJoCfuukYClutz2TBOqfm2 NROujDjw= X-Gm-Gg: ASbGncthv5dWtpPivGIzyLbtVfS/KXJ5RDFXaYmHLBwnUp4m1HNELAMx2TYNAQqtBSu uCM9qIH6QVIoLpCgdPpjzfBpiCxk6Wde0ZXFLkVwpt9sfspYj27KfsjnbfD39/xG/1ToL9Y5nnE pC24f3Y/DYO9nxKiHeN4Gj8Y7t6TlJBggZdESXz4VU5oPH2Jkg29npnplfpt4FHppI5Zb4tWumC bxgJGwGXBz3oYfUOALNEFgmdJBHptMihbfoz9oa0SBrsMJ8MVFPNneBb6R+mq+z5jqZWK/5NFlD mWp1tgDIbmKbUsUbKJsVZt0s3Y8BE5apEHdgADo9OLiSJzPs6LWJm9/WHvfoKZO9YGxFEtjGJ2T jWGOXT7dRUXmCQ74kZba24/5WtNkRVI/VTeTLCfEKsSXudsDD9Blay7aoIwLjaUqZ5EObv/SoJh wMlyMPOj+1DC3YRhBE2Sos68Xsf90w4+fCUVkpiNsDdoLTbIxuSYxy7h4kyxsZn0gJcRc= X-Google-Smtp-Source: AGHT+IFWS1qhnIYVf+9qWA8K7OREBP+Ern4Z97yhUk3S2Ip30gG8x28Gh+RL9dJw4J2NDk86m2t19g== X-Received: by 2002:a05:600c:21cb:b0:477:acb7:7141 with SMTP id 5b1f17b1804b1-4790f03337dmr25966475e9.3.1764211111296; Wed, 26 Nov 2025 18:38: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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.38.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:38:30 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v5 23/24] ipa: software_isp: Call createSelfEnumeratingAlgorithm() to statically instantiate CCM algo Date: Thu, 27 Nov 2025 02:37:38 +0000 Message-ID: <20251127023739.179652-24-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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" Signed-off-by: Bryan O'Donoghue --- src/ipa/simple/soft_simple.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp index 2bbe271d9..d5474bb7a 100644 --- a/src/ipa/simple/soft_simple.cpp +++ b/src/ipa/simple/soft_simple.cpp @@ -137,6 +137,12 @@ int IPASoftSimple::init(const IPASettings &settings, if (ret) return ret; + if (context_.gpuIspEnabled && !data->contains("ccm")) { + ret = createSelfEnumeratingAlgorithm(context_, std::string("Ccm")); + if (ret) + return ret; + } + *ccmEnabled = context_.ccmEnabled; params_ = nullptr; From patchwork Thu Nov 27 02:37:39 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25261 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 23785C32DE for ; Thu, 27 Nov 2025 02:38:38 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 97EFF60C6F; Thu, 27 Nov 2025 03:38:37 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="eLStOLLh"; dkim-atps=neutral Received: from mail-wm1-x332.google.com (mail-wm1-x332.google.com [IPv6:2a00:1450:4864:20::332]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AB18860AC5 for ; Thu, 27 Nov 2025 03:38:33 +0100 (CET) Received: by mail-wm1-x332.google.com with SMTP id 5b1f17b1804b1-477a219dbcaso2595435e9.3 for ; Wed, 26 Nov 2025 18:38:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764211113; x=1764815913; 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=24wXGFYfJlCqjSrTdSPnfcrWmHqpLPl1rwQ64/Nr/cU=; b=eLStOLLhjBRy6rS2yX//f/fQJqg3luyj8d27ELRhQ4n5su0WRVKvhowF7J661XWSXM S8LMINNPW7hrUTbam9d1jxF25jHC5B+lTwwVhv6cArWN+/88OodRCcKrr8CDOwWI62/i UojWkAfeJtHGSFKverFSvfbU2g2uWPmRIaHWWRe8qwS5zi5UNn7w9mHVLXYKjNJs7vok RLCmuU7lXvzaZ73Us09mQ4X6ywrA6PUHCz/i5M+zKgwJupYY8kdkIxW74tdMihvQenvt PbStImDQ7XfQgJirMTP7mIaw8dui/IREmRXgqcbNTUPhlbf3aqs7K3aWGWUcgUDbvJcY CEfw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764211113; x=1764815913; 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=24wXGFYfJlCqjSrTdSPnfcrWmHqpLPl1rwQ64/Nr/cU=; b=lMRvA6+kUSmf49ttEpJQ7W4RulGoOAYxe5AB6lgYXKw4lvu3giMucPrOyb1586RGZE 9NsdOSaHBfepyNa6RujhPaCe8YL0Li1fsnwyjRGpIr4hhbqxvKmNJ/IdkZJPuvxkvmpm yIhkKW2NLNu3Qs46FG5wyA6axLWLhz+HernoNFR9VcH9U9xCbT1N2NU+ehP2iZxp/en3 UBUKk39l/WBrxrNEvrjkacCAIUw+5rfHiSkHFNbIiOo19ewJwqGY2bOaoSfglQNYePIn wuJHkmaYg/ubZCRgYykOMFwIpznlJkKufKROJNpuewH5mJWVcAknZfT1m1KXexYqWnPf 4KQA== X-Gm-Message-State: AOJu0Yy1+7dwIGffMnU0PXiK0Bk1efvMdtN8H6nLIkxe1XYtqAc1S7FI +WvnFXuyoFHJm0twicuH/3XfM46/dF1Ff2pYbU5R7pQQkvrWcmMkHJpBoU+XCFaql6sBT65f+6M 7zEbQJdk= X-Gm-Gg: ASbGncvdvuRf39e50okUAchnb8OKEa115L5YPUrEXFt07JSE4loPrdh1TNjgckJJ9CX F5WP7layFXyXaERDMK/NZI2daheGKeAtMvUbtPxcejtGfMB3voj7V1hmDqcWqsVODixIMRqC+XN ffl97E/kVMTzbOj9+yPw+1qSoSk5o83rVhoYatlIAQGFYf2wN96FhUoYPn21kXjdTzd0v5LmxJ8 RNskvYJohuBBRNaUf8hDGQc9hdTUpxBmgp99xiUEnm8q7XtJSu+gPdmkjvV1zsZXScpj7iduJ7f zJ5u+4VIDLv7uDxvgPWguARFvhxC9em41XWQCBK6JfAf3eqMBnNbSQLiDD9uNTmMpSey9Cr08lw D6Wbwr1y8yA+zOU+otXAyyGjIa4Uw4P9ENMzGgyCiKk3UHj4yKulwk3QczVxf568llzqdqtpvb8 dyjvgzTckO1p4bWhK/dLFblQXxtwcFy61dpd9HSLPi567z6WMy5sEKio31Qbfm8O6XLIo= X-Google-Smtp-Source: AGHT+IGZ4j/tpVqxp8xe6nXiI8C7jsbS/ubjuR2ZPCWLAO9dJIaMM+yCcFxv1dxMlnfVsWXedGBTog== X-Received: by 2002:a05:600c:474b:b0:46e:35a0:3587 with SMTP id 5b1f17b1804b1-477c01ee377mr215704155e9.27.1764211113012; Wed, 26 Nov 2025 18:38:33 -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 5b1f17b1804b1-4790552c3c9sm58186345e9.0.2025.11.26.18.38.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Nov 2025 18:38:32 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v5 24/24] libcamera: software_isp: lut: Skip calculation lookup tables if gpuIspEnabled is true. Date: Thu, 27 Nov 2025 02:37:39 +0000 Message-ID: <20251127023739.179652-25-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251127023739.179652-1-bryan.odonoghue@linaro.org> References: <20251127023739.179652-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. Signed-off-by: Bryan O'Donoghue --- src/ipa/simple/algorithms/lut.cpp | 70 ++++++++++++++++--------------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/src/ipa/simple/algorithms/lut.cpp b/src/ipa/simple/algorithms/lut.cpp index 7f223e812..618219b17 100644 --- a/src/ipa/simple/algorithms/lut.cpp +++ b/src/ipa/simple/algorithms/lut.cpp @@ -56,32 +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); - 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); - 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; + /* 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); + 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.contrast = contrast; @@ -134,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]; + } } }