From patchwork Tue Dec 2 13:45: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: 25310 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 605AEC3260 for ; Tue, 2 Dec 2025 13:45:56 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 977A860C88; Tue, 2 Dec 2025 14:45:55 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="AhyndsQq"; dkim-atps=neutral Received: from mail-wm1-x32f.google.com (mail-wm1-x32f.google.com [IPv6:2a00:1450:4864:20::32f]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7190E60C77 for ; Tue, 2 Dec 2025 14:45:53 +0100 (CET) Received: by mail-wm1-x32f.google.com with SMTP id 5b1f17b1804b1-4779adb38d3so41021105e9.2 for ; Tue, 02 Dec 2025 05:45:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683152; x=1765287952; 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=n/Dr3v1jgs2rQ+R/y4XCcTtZPdFoLGM7Zc7OE3xBNt0=; b=AhyndsQqpCs9FbJlPxS8yb2eJ3NQDtSqyFUDxpODH9kqcG18kxen3hp67JV61zFKkP 3am1VNEvXVNj9X3tuUb5cuqYdCpNmvdrwA26pYze/CV5+LwZ/yMLyTQ9JhKw/4wKGgw6 Mj0utGZtt2sBB7JNknxfzhHZJxniCLkbDkUQk3777J8cWwoVongnkR9bZuxRDu5g21cL 7lRobMawP3NLdSvmgO8DXyAdDW7bMeym8NpIJJWV9871+B+jTluQAsi9zMDfkgScop7T avXQNRUPg0qevSRPHXFpNJCexyjvPtb8WhbgveR6Oe/lyzisbDLtxVdkgkIE/fUcV4Yz f+1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683152; x=1765287952; 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=n/Dr3v1jgs2rQ+R/y4XCcTtZPdFoLGM7Zc7OE3xBNt0=; b=dJ++ohvwofHFNbvHAMaecKQYrSCabDh6YogDlpIJp7EJbz4Sl3JKo1ArDTGBFbUC3O kmNHqgZApFo2CBAkvlRKUVVcaK3IcXlOJM6bDM0mGAGVN26JG4YoxcAWYKsaKvBCEDBI RIt3oWu+xMnRtslEe/CtKH+r7NW7jctYXppNO4t9/YjW0RRT7KihMz75id0p8Sgn55RF aYbmE9oGWHjuczMwyDgu/ytFS8WIPWDBTCFdUGbFGOVY78crPdaknZAsFMVb4zruXJlZ E6ad/F0PkRNU1saJzj74rG0zajwikz1lqLhfp8zS8vxzGWqBL0oQX1XpjocEDTydul6Z PwMg== X-Gm-Message-State: AOJu0Yy8NUL7LSPTNqL+SE0SxYWYyNz3ouwiBLPMz3Pe7UkD3nXeQbJn UvtZUaHm6xKZHz7OIPzQouOrtd3+bnJ5sMMagOVp7q122c52ygAAzdpkDF0zqBHOvrSBOTGCeAT uCL3S X-Gm-Gg: ASbGncvEbxEWhhBWzO6L/CuoEYyh3grXmt+yw/ZkJWHgt0ElPT7tzWgg9m3n/1nb1/w x4tXsZUSZ7LHNU/iCUjFYFGX2x7TCrKiH+DLP+vD03Nuoqz+qRr5Lpwi9PNJgBUtCsdypHAA5g3 Z3TSYq4x4T37xRpd5yYw7DdYzrthiQgZbKMM5up1BmqZzsxhVrn8/SXG2QJP9WRBa9/FaYfxHen Ve1hOPJe9CQVsV4LPKAmHAjIr95tzaOU5f3f1GWnNIDY8Kjfvzrl97LoGsGp1lJzovLDQ/gQTVG nuz2mQSUilD9FvDuoOtWEyQ2NmJS5URs/F3HfR9VGL1dVCOSrmn9VJsjddC5FcbfZN1vhwfV4kp fl/wxCw7sHVEX/BM+sIgGL2EaGsqjoH7QSB4+QeRIhwHgC2mFfLB6P/K2r0TfMnOq1SjbhiMoQT WNvC/XH9E/zixIuKWPWHQJecjYkdq2K+Rrg9qmlxBC2PB1U1c1fn/JpyD+oz1l5XD8+LM= X-Google-Smtp-Source: AGHT+IEBsZK4czuOzq1ubBK5Kfa39erknNowrvyEPdkj74mAjIaCEACEykbwuweQOPhjiMD1KmkRsg== X-Received: by 2002:a05:600c:c8c:b0:471:d2f:7987 with SMTP id 5b1f17b1804b1-47904b23c04mr275801315e9.26.1764683152429; Tue, 02 Dec 2025 05:45:52 -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-47926f0ec69sm19383375e9.1.2025.12.02.05.45.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:45:51 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Kieran Bingham Subject: [PATCH v6 01/24] libcamera: software_isp: gbm: Add a GBM helper class for GPU surface access Date: Tue, 2 Dec 2025 13:45:21 +0000 Message-ID: <20251202134544.662446-2-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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 Tue Dec 2 13:45: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: 25311 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 BF6DCC326B for ; Tue, 2 Dec 2025 13:45:59 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E8F9360D0D; Tue, 2 Dec 2025 14:45:58 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="uw1Z9OVJ"; 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 5D1EF60C79 for ; Tue, 2 Dec 2025 14:45:55 +0100 (CET) Received: by mail-wm1-x333.google.com with SMTP id 5b1f17b1804b1-477ba2c1ca2so63292605e9.2 for ; Tue, 02 Dec 2025 05:45:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683155; x=1765287955; 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=SXcmigsVXdUpbRe1YX6KkXB2lAedVFpsPgAcymXXKk8=; b=uw1Z9OVJbGQrFSlMsGGad0BMzhLt+FQl5K+zhjZ3MDojK4q1T4IgXRIaflRebWSIWH WPMbszzPPiqy9QOikOV8nStgxNCvt2jtiXnC6UkICsgj/fpJmwa861n+EnJvJRLsS6tm uNvYdg4wzwgzn7v5a+E/wcDNsoyWjulD9VCmnWCROO7rubmZQDfQuvcbptWYOIAdFM4s z3A0hzSI+yMWzicoX2Wzr2og0uGY+VJyrH4w5p25lxLvR1MOf5Xy66G7cmbY81xve6oO FjleGAMbgsIOQssYol64m4Rn7YH6GPlGFKXt8h/BmmcLvr+VquV3gb5aOeObdN9NyV3H VQ5A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683155; x=1765287955; 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=SXcmigsVXdUpbRe1YX6KkXB2lAedVFpsPgAcymXXKk8=; b=MNHE+q35wfn6EtEbGfR+WJYSjcHtVOPemqbt3xjSeatsRxzPrKuWEXcjYVxlibKVY+ Ofe8GD+CBSvzBA/ZqOUE9fd2/hBXvC8nVcwtpv0YpsJsXFMOlXdT9hWAWhNZFyBW7a7l JoKj0ZB/5m2ymlvopNSnbM5urrmKhKrBO9c3QFJxHs3JZFBmPi2twdXtmhWuqgKxt9Ko 2gzRB1xti9wPkxj1zjhxb9KxKO/5q8sbhcKa2PkXpiQcpLZlFxFDvZeMsUfZHyPYpUfK sbiI++oMaAOwFXQ5wdtNDJ3zk78yt7j5Gqt3uyOq33PS1QwWomhH5KcKxnHLvU/P4LG/ GmxQ== X-Gm-Message-State: AOJu0YwFMgp+KnDmuk5nppCh3WgM3aZ3CMARE/w6GETO3oGwoGnWsQt8 So3+0HQTbPiPRQtutUTxQP9XUAPh4PcG0hS9xLV97+NAidodbBWm+uta4E7YAGaRcQT2P98jTzo LPAwy X-Gm-Gg: ASbGncvVbHYTqFf10BgZKPDoUXcxpJI4WfY9OOVwBvZI8gj3I07veOX7uQerqoWMdwG MuZEBX1eQO6I9TeKX+Mv/OeP/DU4J88IXgzDgB0W2RzezR2SBjj5LV6B88wiB7TMELitXteIlm9 qFlDRWSQ/4vloZJVis0odQ0otlUQKHJLr/z8Nwc5wETh1R8IEt/nWjzrA6qXWjFOeP5vxny5SQA qp5k5BGFNfkcq0kzklJUuM5YbAzcwuF11iF8HOvRtShmHCS+/VtPnvcK/TKMu8DSQjBBT/4MAyK rGKnhjvEghK+84YWdMmCHAATHHqs3a2nx9yxr7X+bXakzkxjK1RUeItUR/obqKPkvQoWZymPoz9 6sugr6qDjeIX+0eQvUhSsYNeP82EiwGiuIl6/1mBcyRDVrLjjsBBkN21cbnp9/B57o6Mdi6am63 6EA0AENg4dSvy4I4TnzOyeWpmEAx7ZMs/WIHS8NmPvNcuvfxusrxt9zYbfijwxdvX1X+k= X-Google-Smtp-Source: AGHT+IFMgQpURiX5qUjF+c3bkCsLBM6axVFu9GGywO1a6ZJcJWdsdp2211kwxdFz7hdkIZKWaXE0KA== X-Received: by 2002:a05:600c:3b0a:b0:477:9574:d641 with SMTP id 5b1f17b1804b1-47904b1b2ecmr271629085e9.22.1764683154218; Tue, 02 Dec 2025 05:45:54 -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-47926f0ec69sm19383375e9.1.2025.12.02.05.45.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:45:53 -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 v6 02/24] libcamera: software_isp: egl: Add a eGL base helper class Date: Tue, 2 Dec 2025 13:45:22 +0000 Message-ID: <20251202134544.662446-3-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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 | 186 ++++++++++ src/libcamera/egl.cpp | 619 +++++++++++++++++++++++++++++++ src/libcamera/meson.build | 23 ++ 3 files changed, 828 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..542787dc5 --- /dev/null +++ b/include/libcamera/internal/egl.h @@ -0,0 +1,186 @@ +/* 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, const unsigned char *shaderData, + unsigned int shaderDataLen, + Span shaderEnv); + int compileFragmentShader(GLuint &shaderId, const unsigned char *shaderData, + unsigned int shaderDataLen, + Span shaderEnv); + int linkProgram(GLuint &programId, GLuint fragmentshaderId, GLuint vertexshaderId); + void dumpShaderSource(GLuint shaderId); + void useProgram(GLuint programId); + void deleteProgram(GLuint programId); + int syncOutput(); + +private: + LIBCAMERA_DISABLE_COPY_AND_MOVE(eGL) + + pid_t tid_; + + EGLDisplay display_; + EGLContext context_; + EGLSurface surface_; + + int compileShader(int shaderType, GLuint &shaderId, const unsigned char *shaderData, + unsigned int shaderDataLen, + Span shaderEnv); + + int createDMABufTexture2D(std::unique_ptr &eglImage, int fd, bool output); + + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; + PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; + PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; +}; +} //namespace libcamera diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp new file mode 100644 index 000000000..2ef1156eb --- /dev/null +++ b/src/libcamera/egl.cpp @@ -0,0 +1,619 @@ +/* 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 + * + * \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, const unsigned char *shaderData, + unsigned int shaderDataLen, + Span shaderEnv) +{ + return compileShader(GL_VERTEX_SHADER, shaderId, shaderData, shaderDataLen, shaderEnv); +} + +/** + * \brief Compile a fragment shader + * \param[out] shaderId OpenGL shader object ID + * \param[in] shaderData Pointer to shader source code + * \param[in] shaderDataLen Length of shader source in bytes + * \param[in] shaderEnv Span of preprocessor definitions to prepend + * + * Compiles a fragment shader from source code with optional preprocessor + * definitions. On compilation failure, logs the shader info log. + * + * \return 0 on success, or -EINVAL on compilation failure + */ +int eGL::compileFragmentShader(GLuint &shaderId, const unsigned char *shaderData, + unsigned int shaderDataLen, + Span shaderEnv) +{ + return compileShader(GL_FRAGMENT_SHADER, shaderId, shaderData, shaderDataLen, shaderEnv); +} + +/** + * \brief Compile a shader of specified type + * \param[in] shaderType GL_VERTEX_SHADER or GL_FRAGMENT_SHADER + * \param[out] shaderId OpenGL shader object ID + * \param[in] shaderData Pointer to shader source code + * \param[in] shaderDataLen Length of shader source in bytes + * \param[in] shaderEnv Span of preprocessor definitions to prepend + * + * Internal helper function for shader compilation. Prepends environment + * definitions to the shader source and compiles the shader. + * + * \return 0 on success, or -EINVAL on compilation failure + */ +int eGL::compileShader(int shaderType, GLuint &shaderId, const unsigned char *shaderData, + unsigned int shaderDataLen, + Span shaderEnv) +{ + GLint success; + size_t i; + + ASSERT(tid_ == Thread::currentId()); + + auto count = 1 + shaderEnv.size(); + auto shaderSourceData = std::make_unique(count); + auto shaderDataLengths = std::make_unique(count); + + // Prefix defines before main body of shader + for (i = 0; i < shaderEnv.size(); i++) { + shaderSourceData[i] = shaderEnv[i].c_str(); + shaderDataLengths[i] = shaderEnv[i].length(); + } + + // Now the main body of the shader program + shaderSourceData[i] = reinterpret_cast(shaderData); + shaderDataLengths[i] = shaderDataLen; + + // And create the shader + shaderId = glCreateShader(shaderType); + glShaderSource(shaderId, count, shaderSourceData.get(), shaderDataLengths.get()); + glCompileShader(shaderId); + + // Check status + glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success); + if (success == GL_FALSE) { + GLint sizeLog = 0; + + glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &sizeLog); + auto infoLog = std::make_unique(sizeLog); + + glGetShaderInfoLog(shaderId, sizeLog, &sizeLog, infoLog.get()); + LOG(eGL, Error) << infoLog.get(); + } + + return (success == GL_TRUE) ? 0 : -EINVAL; +} + +/** + * \brief Dump shader source code to the log + * \param[in] shaderId OpenGL shader object ID + * + * Retrieves and logs the complete source code of a compiled shader. + * Useful for debugging shader compilation issues. + */ +void eGL::dumpShaderSource(GLuint shaderId) +{ + GLint shaderLength = 0; + + ASSERT(tid_ == Thread::currentId()); + + glGetShaderiv(shaderId, GL_SHADER_SOURCE_LENGTH, &shaderLength); + + LOG(eGL, Debug) << "Shader length is " << shaderLength; + + if (shaderLength > 0) { + auto shaderSource = std::make_unique(shaderLength); + + glGetShaderSource(shaderId, shaderLength, &shaderLength, shaderSource.get()); + if (shaderLength) { + LOG(eGL, Debug) << "Shader source = " << shaderSource.get(); + } + } +} + + +/** + * \brief Link a shader program + * \param[out] programId OpenGL program object ID + * \param[in] fragmentshaderId Compiled fragment shader ID + * \param[in] vertexshaderId Compiled vertex shader ID + * + * Links vertex and fragment shaders into an executable shader program. + * On link failure, logs the program info log and deletes the program. + * + * \return 0 on success, or -ENODEV on link failure + */ +int eGL::linkProgram(GLuint &programId, GLuint vertexshaderId, GLuint fragmentshaderId) +{ + GLint success; + GLenum err; + + 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 Tue Dec 2 13:45: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: 25312 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 3F79FC3257 for ; Tue, 2 Dec 2025 13:46:01 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 51A1B60C91; Tue, 2 Dec 2025 14:46:00 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="wrwhyC1d"; 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 AA63660C77 for ; Tue, 2 Dec 2025 14:45:56 +0100 (CET) Received: by mail-wm1-x331.google.com with SMTP id 5b1f17b1804b1-477770019e4so46195725e9.3 for ; Tue, 02 Dec 2025 05:45:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683156; x=1765287956; 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=amMoQCO1WpNVR7VV2kItwg29g4ljwGAnIqXk1bcdxT4=; b=wrwhyC1djZOoIgYgv6Pu6zHhrb3J1BX9/NvsKj0n5tkOd35GDpkcNsNXeFae/YA/3v QkjUHqE6nSfcRJUq/rQ/cDjyVBjAu746reyeK2QOcwB1xV+PuaxEodVpnd9gSWtlQ+Yw u0wWZ7AjmjCqqR98lUA2LAhr3GSASr9Xe+WfUrEQnL1RKBYxN9Rc0csjtC09Pac1tyEm 9V3FZhPs7SsbAaFLUJGvii44n+ZORZ+IxddaSbLmK256WKS5k028UfyiPLH4GnzBvtow W+2Diek7iiXQj+DpriI8Uv8+qWpBMesWTlb90sgJwhLyhy83elgkJr7WToLoDTJvvycg Bx8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683156; x=1765287956; 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=amMoQCO1WpNVR7VV2kItwg29g4ljwGAnIqXk1bcdxT4=; b=EUJq32FJZgPTV3SDYzigPAvszfk6MTDVDuUZviuZQk6b6Ew4cSL2MTPxM2VSJ2tQxV VcX+8ZdnWsPlTnlUisJmORNEy6wV2MrBHUsUK25ylu9+Br//sBbpwGF/xX26X3LKiLRe 6ABeB/jRx4Z2MmxoNMkKuVZgomk/L1C+BYzsKwjwJy6xDhwXluoqLlEd8wG64QHTZY5m PElu0NvoJx9936Nd24B7OjxoaKAW98/D956flxGRsdbJws+4BOjRpFQpgXxPdxTRSuAF meo6FtmfiiOoctvIO3bR1ovCUl3enDGUsxaR23IZllaASAYsg0LKsSwv+qkI8JrmmFIy 17rQ== X-Gm-Message-State: AOJu0Yx++mlxWHfT0hWrkTb+nKUxi1g+wTWMeWBpWbBZ+fbCbmOhmOaT WNB4B+qxD/wnU0bYeXyl1a1HSvilHrCWEecmIK9OzDUw+0E7Xbnel3RY5aunOHxIdD4r0TgpGQb oa9+N X-Gm-Gg: ASbGnctR79E7Gd2mQh4CZ1+quxkfB7Qv/UczVWx2dnDclFo/YGFd3zQ6Rx/g/LIxoDs 3GyXSFumqdYXMzFY1u8QDcx5K+l4NFJVSr3n7poXv3yiHJ2t7GDS0J56I4iW7hJ4YY/zL2SBudz 3o+L5zMf8LeF7lxgs/+xCQmN+HQBP+bHWcrO3PA35l1t5+HhPX6vVcCP0h7Pb4Ckee1uzmdT/WG APVye6K+hVGplZ4inw95kCuNER/hmzUCM2+1XbSJarJ2NXIjc4L0bdV3l7H5ts3mvLDlO91tZu2 5i9kYcBbneG9lhkUbrMrY48jALzPqs1fp8bWP/IhlUXX7ASExaf1uq34BN8HrGgN6Q/PPOEBsXI 9KsN7L8V2iCiyLopBXTOiYHbqibnHUAG1Lyu03bkBxEMm8aocff8qHNR8aMu+YhU+SYnFj+Z7Wl rLhpDL2mPq3qufT59QmtRUUOhPWVVq+d+83p+NzDacoIVAyRyA5MC+XHK1dJc9h9UUxJU= X-Google-Smtp-Source: AGHT+IGRDiF22iUsZjPGDrX8ZcsDo4jDMYlPfSU3itkTff+gWN94oVIndJv4kPDXwjb6tuOpqLJn5w== X-Received: by 2002:a05:600c:4f48:b0:471:115e:87bd with SMTP id 5b1f17b1804b1-47904b2494cmr306646675e9.26.1764683155786; Tue, 02 Dec 2025 05:45:55 -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-47926f0ec69sm19383375e9.1.2025.12.02.05.45.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:45:54 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v6 03/24] qcam: viewfinder_gl: Set no-op Bayer shader values Date: Tue, 2 Dec 2025 13:45:23 +0000 Message-ID: <20251202134544.662446-4-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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/apps/qcam/viewfinder_gl.cpp | 25 +++++++++++++++++++++++++ src/apps/qcam/viewfinder_gl.h | 12 ++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/apps/qcam/viewfinder_gl.cpp b/src/apps/qcam/viewfinder_gl.cpp index 1554c94d5..69b7c6e59 100644 --- a/src/apps/qcam/viewfinder_gl.cpp +++ b/src/apps/qcam/viewfinder_gl.cpp @@ -473,6 +473,10 @@ bool ViewFinderGL::createFragmentShader() textureUniformSize_ = shaderProgram_.uniformLocation("tex_size"); textureUniformStrideFactor_ = shaderProgram_.uniformLocation("stride_factor"); textureUniformBayerFirstRed_ = shaderProgram_.uniformLocation("tex_bayer_first_red"); + ccmUniformDataIn_ = shaderProgram_.uniformLocation("ccm"); + blackLevelUniformDataIn_ = shaderProgram_.uniformLocation("blacklevel"); + gammaUniformDataIn_ = shaderProgram_.uniformLocation("gamma"); + contrastUniformDataIn_ = shaderProgram_.uniformLocation("contrast"); /* Create the textures. */ for (std::unique_ptr &texture : textures_) { @@ -542,6 +546,15 @@ void ViewFinderGL::doRender() /* Stride of the first plane, in pixels. */ unsigned int stridePixels; + /* Identity CCM */ + float ccm[] = {1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 1.0f }; + QMatrix3x3 qCcmMat(ccm); + + /* Black Level */ + QVector3D qBlackLevelVec(0.0f, 0.0f, 0.0f); + switch (format_) { case libcamera::formats::NV12: case libcamera::formats::NV21: @@ -788,6 +801,18 @@ void ViewFinderGL::doRender() * the generic stride factor to 1.0. */ stridePixels = size_.width(); + + /* Colour Correction Matrix */ + shaderProgram_.setUniformValue(ccmUniformDataIn_, qCcmMat); + + /* Black Level */ + shaderProgram_.setUniformValue(blackLevelUniformDataIn_, qBlackLevelVec); + + /* Gamma */ + shaderProgram_.setUniformValue(gammaUniformDataIn_, 1.0f); + + /* Contrast */ + shaderProgram_.setUniformValue(contrastUniformDataIn_, 1.0f); break; default: diff --git a/src/apps/qcam/viewfinder_gl.h b/src/apps/qcam/viewfinder_gl.h index 23c657bcf..c1b2d9d51 100644 --- a/src/apps/qcam/viewfinder_gl.h +++ b/src/apps/qcam/viewfinder_gl.h @@ -103,5 +103,17 @@ private: GLuint textureUniformBayerFirstRed_; QPointF firstRed_; + // Represent per-frame CCM as a uniform vector of floats 3 x 3 + GLint ccmUniformDataIn_; + + // Black Level compensation + GLint blackLevelUniformDataIn_; + + // Gamma + GLint gammaUniformDataIn_; + + // Contrast + GLint contrastUniformDataIn_; + QMutex mutex_; /* Prevent concurrent access to image_ */ }; From patchwork Tue Dec 2 13:45: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: 25313 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 24586C32AF for ; Tue, 2 Dec 2025 13:46:02 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id AF92B60D0C; Tue, 2 Dec 2025 14:46:01 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="mNCmal8f"; 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 5490260C77 for ; Tue, 2 Dec 2025 14:45:58 +0100 (CET) Received: by mail-wm1-x335.google.com with SMTP id 5b1f17b1804b1-4775e891b5eso23291605e9.2 for ; Tue, 02 Dec 2025 05:45:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683158; x=1765287958; 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=lV+JLx0+P4aigKpifcEHa5VvxL7Qodjjb3+3JXtFVoo=; b=mNCmal8fhLkDwziuGOZsSVCGbohKLLmKxY3MUBR1Il81FR4DYM78+dfeM9DOurVwM4 a7bNeOXtzeghcF6RbYJP+XVISgsZ08zFxPqSckFZ4MNtbSuq58PJkOO/3MrDpKUKcCPT PKeR2OJagSBLUShgvANFRroKGVg/OKElW0Cs8WW90khLitixAPMN0ths+ehrbUmDAexS DxoLXvUGf//o6YzHOwmR5MODstevwzeGZ01WY+78I+vTOmuGgbWP1OltJEa+Ag9JrYQM DoxBLL7y1MBwlNqv6KcrxTFXXuttdw2mbfMJw2e99I2A/CACWGABMJgveBCamDq+50SO 4MKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683158; x=1765287958; 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=lV+JLx0+P4aigKpifcEHa5VvxL7Qodjjb3+3JXtFVoo=; b=LhjTzlueXSO3vu6MDiJh+KpUgPmniU7Yo9ttU7ERfyIt7Vm1eyGWj8vZ6vIqfX+Edf BCpWbihlDM3ElI66MUDt2RNo2e9MLVPd06ObnX/pyLdzBAKCQv5MqwduC4rLCN9aKijX z11UjwMh5RJubuTgylSC6HAacpPOF6b5G1b8VPl4eIDcTRUSRX4vWEq+P/806x94OHUo cpKv22r1+2QA+XXo6hYvnxkL1KXprCSBwl0Ri/TYM2OtrYXsiXXFL5TE5kotf7YIEfMo kHW0KdfOVMsH311OhWHRxdwFm7Wf1cjXpGWEEmugZFcjWEmej7jgJed1bTBC1CvznnTA lr6Q== X-Gm-Message-State: AOJu0YyyuRjb1t7lSWLMvokGj8S/NL+DMGxUZMCcimz8WG1qlJNSRtei wrNvhNd/2k1CMdfr+5JONFygu+QvSB7H/WqM3c+cOCpTA1LgtuZJtaAEXWzqZFluUCFr+xvc0Lo 2awgd X-Gm-Gg: ASbGnctIso3mI81p+OQ2yCtPWaj6/dHKpG/lshs8Y2szefB2x+ua6KPOXl8s2SYa1sx lVMyE/9EtyCgplCGnsg1q23x7Cp88tlSDbdAwVoMwwr+Y2CFaD+cF5a2KODc0xUtv8mQflNaLeH Mh1gBbbM4Z655PpHz+ByRWz6HgHTaqS3Jgp4pZra2G7sDKP5uxvn+Nbw2XOwHxvztzz3iBMmeII Kacx606e1F3m38cb64+PY3ZJd4f4Pquz5oOE13evT0WNErTIsSfhNIgZaSHFaq2Ufm1E//auHs8 DhQ9APKzx/TFdVePik71r/kVr6kcFNu9ks4iMQ+pw+Kha3B5LUg1AbGO7cZDOnib2c2jLOhE56w qZxVgKnybMMI01zt45mGV12H24ORgQe77mS3lSgPQw6eCIzycuEZRGFKD8pLe14xQ4UApxCdTNg /dsoDvWTK8fDx4It45DtCYbMyxrLhKGg5TkLWuVC+kIOQ0ukHwX2Ef7HPYeo307XS8Y28= X-Google-Smtp-Source: AGHT+IHxkjtXhWVmVNDuHeY9tIV/UvNU0R57KLBDKaCdjqkF78LijCT/ZUqhd+4JYxEr5Og1DoH1pA== X-Received: by 2002:a05:600c:3baa:b0:475:de12:d3b5 with SMTP id 5b1f17b1804b1-477c01ecc7cmr430279725e9.34.1764683157465; Tue, 02 Dec 2025 05:45:57 -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-47926f0ec69sm19383375e9.1.2025.12.02.05.45.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:45:56 -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 v6 04/24] libcamera: shaders: Rename bayer_8 to bayer_unpacked Date: Tue, 2 Dec 2025 13:45:24 +0000 Message-ID: <20251202134544.662446-5-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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 69b7c6e59..ea957dc65 100644 --- a/src/apps/qcam/viewfinder_gl.cpp +++ b/src/apps/qcam/viewfinder_gl.cpp @@ -235,29 +235,29 @@ bool ViewFinderGL::selectFormat(const libcamera::PixelFormat &format) case libcamera::formats::SBGGR8: firstRed_.setX(1.0); firstRed_.setY(1.0); - vertexShaderFile_ = ":src/libcamera/shaders/bayer_8.vert"; - fragmentShaderFile_ = ":src/libcamera/shaders/bayer_8.frag"; + vertexShaderFile_ = ":src/libcamera/shaders/bayer_unpacked.vert"; + fragmentShaderFile_ = ":src/libcamera/shaders/bayer_unpacked.frag"; textureMinMagFilters_ = GL_NEAREST; break; case libcamera::formats::SGBRG8: firstRed_.setX(0.0); firstRed_.setY(1.0); - vertexShaderFile_ = ":src/libcamera/shaders/bayer_8.vert"; - fragmentShaderFile_ = ":src/libcamera/shaders/bayer_8.frag"; + vertexShaderFile_ = ":src/libcamera/shaders/bayer_unpacked.vert"; + fragmentShaderFile_ = ":src/libcamera/shaders/bayer_unpacked.frag"; textureMinMagFilters_ = GL_NEAREST; break; case libcamera::formats::SGRBG8: firstRed_.setX(1.0); firstRed_.setY(0.0); - vertexShaderFile_ = ":src/libcamera/shaders/bayer_8.vert"; - fragmentShaderFile_ = ":src/libcamera/shaders/bayer_8.frag"; + vertexShaderFile_ = ":src/libcamera/shaders/bayer_unpacked.vert"; + fragmentShaderFile_ = ":src/libcamera/shaders/bayer_unpacked.frag"; textureMinMagFilters_ = GL_NEAREST; break; case libcamera::formats::SRGGB8: firstRed_.setX(0.0); firstRed_.setY(0.0); - vertexShaderFile_ = ":src/libcamera/shaders/bayer_8.vert"; - fragmentShaderFile_ = ":src/libcamera/shaders/bayer_8.frag"; + vertexShaderFile_ = ":src/libcamera/shaders/bayer_unpacked.vert"; + fragmentShaderFile_ = ":src/libcamera/shaders/bayer_unpacked.frag"; textureMinMagFilters_ = GL_NEAREST; break; case libcamera::formats::SBGGR10_CSI2P: diff --git a/src/libcamera/shaders/bayer_8.frag b/src/libcamera/shaders/bayer_unpacked.frag similarity index 100% rename from src/libcamera/shaders/bayer_8.frag rename to src/libcamera/shaders/bayer_unpacked.frag diff --git a/src/libcamera/shaders/bayer_8.vert b/src/libcamera/shaders/bayer_unpacked.vert similarity index 100% rename from src/libcamera/shaders/bayer_8.vert rename to src/libcamera/shaders/bayer_unpacked.vert diff --git a/src/libcamera/shaders/meson.build b/src/libcamera/shaders/meson.build index 386b342d0..dd441a577 100644 --- a/src/libcamera/shaders/meson.build +++ b/src/libcamera/shaders/meson.build @@ -4,7 +4,7 @@ # for the purposes of inclusion in OpenGL debayering shader_files = files([ 'bayer_1x_packed.frag', - 'bayer_8.frag', - 'bayer_8.vert', + 'bayer_unpacked.frag', + 'bayer_unpacked.vert', 'identity.vert', ]) From patchwork Tue Dec 2 13:45: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: 25314 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 63523C32DE for ; Tue, 2 Dec 2025 13:46:05 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C5FE960D17; Tue, 2 Dec 2025 14:46:04 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="xGs2SImB"; 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 A041E60C92 for ; Tue, 2 Dec 2025 14:45:59 +0100 (CET) Received: by mail-wm1-x32d.google.com with SMTP id 5b1f17b1804b1-477b198f4bcso40705295e9.3 for ; Tue, 02 Dec 2025 05:45:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683159; x=1765287959; 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=W/s9mmdbl87zzKzmRKPs0PR9N0I+f2koWRf2p9p2M+w=; b=xGs2SImBMNZNY3bgVCwvLRDQFE9cSmvYpy93h9e/mtAQHFW1mC4VcKBCKOhnC31Cnz y/EqqTGA/c5f1dvX07KenpvVTskAJPuxX7LFIhnWnf2CRdoTvre418xR1cWb0zmM7MuB zE8G+ZLWfeeb0zetqTyTeBu5HUPi5M9+K+6VAfmj9FpEg3UXcnb+vl2v8RFGqkVVNDZw t1Rh9chHVgNco6UQ/Rp+KZdnOil9Xj7Dvlm4a9n2FwRtFkrl2KOkr6UhnEgvv2m44gFL UujNdmIMzLcBwemgq5n2lWyUDhtzbFprBurhDj6mTRdHbrhfzC3R8EUGlDXFQ+qM8JMU 7Nng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683159; x=1765287959; 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=W/s9mmdbl87zzKzmRKPs0PR9N0I+f2koWRf2p9p2M+w=; b=vHS+0orpDEfKcI4Mmw4KDEyzKij7D5WaSYZ3hB8JaWsDPjHIvEGj6o24Hz5Pra8Ywi 4Zv4AFFkyGzJGn+mQm5yxiTw5XJIbQd3KvrmtmitCRbX0t9ujoR+DrzNvZKpBqVQ2QMF MbZwwmpNdiD6vj2UCYQkuFfXHh0KboDgugqWJxKsHmPLO5TebbP9+0Rg55FpHF60AOi/ hs1723SRyGf8Kv6Vj4C7V76dC0Z2OhyB5JvtznP7O/YiigOm3n2YJ6AIMJgMQPDB8FTn DEEtQtTYxacIRNIuS29Ekw84t7rEkAGZGa+pUuzMF7ysP84XwgsomObr41yEIFzsLa9J g3jA== X-Gm-Message-State: AOJu0YwhPNqqACHNMTdvYO2lxMJ8MS3X+pHImm447xmNJ/URUeQQN4Gx yN/y0BhducxfqQN/tkdOCx1vYUaZrXhRQCSOadaHmmD7aJK+WUg404rfNHOQbxCkGif/UBM9G2d +XgYL X-Gm-Gg: ASbGncvnU0EifQdZwLV3r+CWVzlIBXdeVjOlYFHV8mC16Bzgt8EH4Tal/cNvu3Hd95J J4LSCYBnt2ptqsQEuH4iKFLF0RrJJLTPRog4nuS8Uj72/fD3pfq4/7UZekWq3+0Cpi6Lu9udzXT ihEPpAxlEXIepawC4sHrjivuR+p8OxEMvwGnXRHSPO9HCroWTs9XKkF85ZRfxNWZGxH7OT2qrXA K7Jfj7uHtaVyEK8HJjMQb0RvEMkL+Z/rN/BrgJ1QZYrZf8yFvO+I+kEAE0TzGyyPauX5Sx4BdC+ 9UCPHYankBp2RyMpQcVBcNzyXIYyAOK1PNCVMyASTVNhSIZfAdgNLZvw4/rzo/jQ1b++G/r+k0S Phr8WfdgWqXLthJPCIVVohO5YLpNmcUltiIV3QdNXpqR+Wi6YVOjhdbbvyxDlavDrBr6+C4VmB9 83pWSvBR5trsQ9Q9Zgav81n7NvqSAS/5Tp7hKRWGanGQef/BqP0r/sGc/60qYKDBXLnCU= X-Google-Smtp-Source: AGHT+IHoFvCrxxewE0J4bGcOHNU5dUGu6ccyxKVs6Jo6GnqbmLGYKPsOjqdtSFPyeOJzqX98TKxiOg== X-Received: by 2002:a05:600c:474b:b0:477:9dc1:b706 with SMTP id 5b1f17b1804b1-477c01b494fmr443451105e9.19.1764683158899; Tue, 02 Dec 2025 05:45:58 -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-47926f0ec69sm19383375e9.1.2025.12.02.05.45.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:45:58 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Kieran Bingham Subject: [PATCH v6 05/24] libcamera: shaders: Use highp not mediump for float precision Date: Tue, 2 Dec 2025 13:45:25 +0000 Message-ID: <20251202134544.662446-6-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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 Tue Dec 2 13:45: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: 25315 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 47408C32E0 for ; Tue, 2 Dec 2025 13:46:07 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3B4DB60D26; Tue, 2 Dec 2025 14:46:06 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="QGB2nxL7"; 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 33E9B60C77 for ; Tue, 2 Dec 2025 14:46:01 +0100 (CET) Received: by mail-wm1-x32a.google.com with SMTP id 5b1f17b1804b1-477a219db05so35538735e9.2 for ; Tue, 02 Dec 2025 05:46:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683160; x=1765287960; 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=Ar/9Plv8U/t5q9HLAAZVcFMeUCSIVj27Ri9+oiHLDzQ=; b=QGB2nxL7Z8VQgJeKQWrReu9wKIMGvRRfrSeaV9/6tL8lqJmZ+iCHYHf1mxvzRaVNgp HAQPRvHniLvdz/2+OegUBhmt2qnULraPdQNaNQjZBPqUI7sCrgSPc+69Ome/6IZ35uIN /i0/eN3V1VgwkYjONg4wICPCiqn6TZWo4NZvIGR2F6xjj5B97AYSlRUcnxfnwEGVUG6b CTP+9lt+/WmFPAj+bxvNClda/iXzBJmMuwmYGLJXniRBX9ex2ihWNdNLoZqISeijGDd9 65ArydcWIwCk9XMrMZ3ya9LVGt2jb1DqhOA8+Y2IrFkrMa7rwQtgnoSm8NTq7MxKJl/V iRGg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683160; x=1765287960; 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=Ar/9Plv8U/t5q9HLAAZVcFMeUCSIVj27Ri9+oiHLDzQ=; b=IqmaFBePdFu0DmuQcNby2f4E6BzoT1F3p/zr/XjDI/y5CD70CtZnexVg/hxaWPA1Qb RadT24rmqKBzBZZECyAMsYBP3GeS/wiaXIXA81Vq50JGp+42xA7dFHat+97cot4dkblr LCEq4uuv3PUGOXzIxpo4bzewMlK4NvNOKcDdEpiCcZX0ZSKHFd04b2oKe3gg0HmjEYSy Lgff1vG4Mr30ZaNXCu4HL3YSdokf0I3jOSd2Cx4JHfba5aF8Em/RPYzQoAvGWZVxcM8Q 9CPz8mJqQPIMNz3I7L6BJ34JKBsbA0QPbsmfnLjvaA22vdmZeqJJwcj/IzxsRIxbmIei og8Q== X-Gm-Message-State: AOJu0Ywl1eigpyUm4Rj2o12c30/8wAWa3jJoUz+yphZW1dgy6y/0BqFR 4cMolXCmauByZHGz5O2l1UfSI5tuVuzhqPLsQUZ8FgcBIixF2mb6xnW8uC019mCuXTi1FGNuGEe a8aBj X-Gm-Gg: ASbGncvEPgqW7wD2s6CgRtqOarfuJFYjPIQPOTveF9E4BfJygxmqhRLQJlkBE8JoGUB 8MHO3wiWwIe7p4YmEXM1wfDGUhahbC6X1qGo7JD2PyJKK8RJwQBYrtQyq8MgAKbd77DtDIi2o5h iWxVQCOx/9313ZVJOp+2zn7KmIddVPuG0epqHL20gJYyXtu5WbyFdZPfY2/V2VuOnVkBTHMWIbv wTrnZwJhWkUJUBxhwr3vilx2ykj0vlJElOUyKu4vM70yJDDt4uqMZYwRogSl7HTj8PptzpFHF/H PL+q6yeoxGWgjB9F7LXeOGII+HH5KLuFFeS8X2Q0xlpXTyHQ3bAQA+Ejwz+hvjKeKD19I3wzVwg XBsElBsc5R7WmnEem4fja0Pp62rHqiEckTrM7SLHP5XrtQ6QTLfr0DPjdGApQbxdlSIgd0ncI13 OgTjjWzZpnwKZTVrRT88ioA+v+Pqly2aAk68Q3I/Pck7HrKC4UWxDOett0omAKX6TUFzmGCQWV8 qQDfA== X-Google-Smtp-Source: AGHT+IGVhzau5WJ5THeB6e3QlSM041Xe70HBvcou3dSZl47PJsnc7QYmtc1STMJZAxDl3kMIMrzF5g== X-Received: by 2002:a05:600c:470a:b0:45d:dc85:c009 with SMTP id 5b1f17b1804b1-477c10d49b5mr365686655e9.10.1764683160452; Tue, 02 Dec 2025 05:46:00 -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-47926f0ec69sm19383375e9.1.2025.12.02.05.45.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:45:59 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v6 06/24] libcamera: shaders: Extend debayer shaders to apply RGB gain values on output Date: Tue, 2 Dec 2025 13:45:26 +0000 Message-ID: <20251202134544.662446-7-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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 | 45 +++++++++++++++++++ src/libcamera/shaders/bayer_unpacked.frag | 51 +++++++++++++++++++++- 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag index 19b13ad08..171a928c2 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -65,6 +65,7 @@ uniform vec2 tex_step; uniform vec2 tex_bayer_first_red; uniform sampler2D tex_y; +uniform mat3 ccm; void main(void) { @@ -212,5 +213,49 @@ void main(void) vec3(patterns.y, C, patterns.x) : vec3(patterns.wz, C)); + /* + * CCM is a 3x3 in the format + * + * +--------------+----------------+---------------+ + * | RedRedGain | RedGreenGain | RedBlueGain | + * +--------------+----------------+---------------+ + * | GreenRedGain | GreenGreenGain | GreenBlueGain | + * +--------------+----------------+---------------+ + * | BlueRedGain | BlueGreenGain | BlueBlueGain | + * +--------------+----------------+---------------+ + * + * Rout = RedRedGain * Rin + RedGreenGain * Gin + RedBlueGain * Bin + * Gout = GreenRedGain * Rin + GreenGreenGain * Gin + GreenBlueGain * Bin + * Bout = BlueRedGain * Rin + BlueGreenGain * Gin + BlueBlueGain * Bin + * + * We upload to the GPU without transposition glUniformMatrix3f(.., .., GL_FALSE, ccm); + * + * CPU + * float ccm [] = { + * RedRedGain, RedGreenGain, RedBlueGain, + * GreenRedGain, GreenGreenGain, GreenBlueGain, + * BlueRedGain, BlueGreenGain, BlueBlueGain, + * }; + * + * GPU + * ccm = { + * RedRedGain, GreenRedGain, BlueRedGain, + * RedGreenGain, GreenGreenGain, BlueGreenGain, + * RedBlueGain, GreenBlueGain, BlueBlueGain, + * } + * + * However the indexing for the mat data-type is column major hence + * ccm[0][0] = RedRedGain, ccm[0][1] = RedGreenGain, ccm[0][2] = RedBlueGain + * + */ + float rin, gin, bin; + rin = rgb.r; + gin = rgb.g; + bin = rgb.b; + + rgb.r = (rin * ccm[0][0]) + (gin * ccm[0][1]) + (bin * ccm[0][2]); + rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); + rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + gl_FragColor = vec4(rgb, 1.0); } diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag index aa7a1b004..c41d72f4f 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -24,8 +24,11 @@ uniform sampler2D tex_y; varying vec4 center; varying vec4 yCoord; varying vec4 xCoord; +uniform mat3 ccm; void main(void) { + vec3 rgb; + #define fetch(x, y) texture2D(tex_y, vec2(x, y)).r float C = texture2D(tex_y, center.xy).r; // ( 0, 0) @@ -97,11 +100,57 @@ void main(void) { PATTERN.xw += kB.xw * B; PATTERN.xz += kF.xz * F; - gl_FragColor.rgb = (alternate.y == 0.0) ? + rgb = (alternate.y == 0.0) ? ((alternate.x == 0.0) ? vec3(C, PATTERN.xy) : vec3(PATTERN.z, C, PATTERN.w)) : ((alternate.x == 0.0) ? vec3(PATTERN.w, C, PATTERN.z) : vec3(PATTERN.yx, C)); + + /* + * CCM is a 3x3 in the format + * + * +--------------+----------------+---------------+ + * | RedRedGain | RedGreenGain | RedBlueGain | + * +--------------+----------------+---------------+ + * | GreenRedGain | GreenGreenGain | GreenBlueGain | + * +--------------+----------------+---------------+ + * | BlueRedGain | BlueGreenGain | BlueBlueGain | + * +--------------+----------------+---------------+ + * + * Rout = RedRedGain * Rin + RedGreenGain * Gin + RedBlueGain * Bin + * Gout = GreenRedGain * Rin + GreenGreenGain * Gin + GreenBlueGain * Bin + * Bout = BlueRedGain * Rin + BlueGreenGain * Gin + BlueBlueGain * Bin + * + * We upload to the GPU without transposition glUniformMatrix3f(.., .., GL_FALSE, ccm); + * + * CPU + * float ccm [] = { + * RedRedGain, RedGreenGain, RedBlueGain, + * GreenRedGain, GreenGreenGain, GreenBlueGain, + * BlueRedGain, BlueGreenGain, BlueBlueGain, + * }; + * + * GPU + * ccm = { + * RedRedGain, GreenRedGain, BlueRedGain, + * RedGreenGain, GreenGreenGain, BlueGreenGain, + * RedBlueGain, GreenBlueGain, BlueBlueGain, + * } + * + * However the indexing for the mat data-type is column major hence + * ccm[0][0] = RedRedGain, ccm[0][1] = RedGreenGain, ccm[0][2] = RedBlueGain + * + */ + float rin, gin, bin; + rin = rgb.r; + gin = rgb.g; + bin = rgb.b; + + rgb.r = (rin * ccm[0][0]) + (gin * ccm[0][1]) + (bin * ccm[0][2]); + rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); + rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + + gl_FragColor.rgb = rgb; } From patchwork Tue Dec 2 13:45: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: 25316 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 BAD79C32E7 for ; Tue, 2 Dec 2025 13:46:08 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6362060D12; Tue, 2 Dec 2025 14:46:07 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="Yf4UHbLA"; 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 6DDD760C88 for ; Tue, 2 Dec 2025 14:46:03 +0100 (CET) Received: by mail-wm1-x32c.google.com with SMTP id 5b1f17b1804b1-4779cb0a33fso57907485e9.0 for ; Tue, 02 Dec 2025 05:46:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683163; x=1765287963; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=nAlpCB4iJopL0Pn768w20N/UlmcrQmnghUNHBy8yJOY=; b=Yf4UHbLAzRl0+cXHae4TGW+DoXiRVno/Gci1f0JCMkfGm4VWF+d9FYQ4UnylRgE3eK NMAZYTTOmF8ao/WHnU+UUOtxZzzkDvZxA4fi2uxbjqJ3cgXC/5FGo0x4YPx05N31BLqu U3/QcC3bEbjxQTG5jZ9JTEiK+CnlPIqDJM5rXGPCdk9uemarXwecDFhvS1g4Zc0q2JhB PHjcLyCNVn8+XKaGOI9c5tnzj3N+m9mBOjuv+Z/UttPt9Y1oy7N7JaEJvpxlq7f7SQD1 Zts9f5Z7Wj2cu0OXXZQGmC6p3nwfVAXxVedLpKARYlJnB/NKlZc4uunkQf2mmt9bnnDL wiLw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683163; x=1765287963; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=nAlpCB4iJopL0Pn768w20N/UlmcrQmnghUNHBy8yJOY=; b=l0ApkMqWyMDp+MZOuLlAfJtO0/DbhtlcNmzsrz2/Kv8zkVZn65Mlw63UCZPzvmEsLZ D/Bl7EZr31zo2H9DyiZxQD1PVENFzpNefzTCwAkfJT82GpnoE2zeZuJwfkGDjYDpVR/+ zewT4zhgsTcIVjptMCET6OM+eqbFL5YSkPrKKL5RToV2zpiQ06LP04CuOGezffwz/cdA 87i7YASeuQ/7gznGTFl4/5MMj7BKrFWKGaKxlXx779yTXcaWkdDfrHl3Bj2CaEXPz/eF hozAKGar556WrPzS5RVbtfLCXEqbawuPIjkw5jilonkU7DVXfwcP8ypwm3zOUSwCREFH oPkA== X-Gm-Message-State: AOJu0YwOWSIOuIrrZ2qHbsMHWkv2qkwaReGCBsfb2XEWpOJoPDVeKw4l fnxaiRaKPZ3uHQuBSDgPiaZ/kAbvU8J+9NysieOHtNcYmD3OfJLniRlgnOoWRWuKdmpmPpPmPjr eU4js X-Gm-Gg: ASbGncs00pMBJCJAUphEkT0c8IfmF81QBa1RYNHUDG3AuXZ9v2TC/ort1y7Oa1jpyLF rWphDOsAcbE3o5rbAdWKE9LLDDRiiPNWF3FyX2muVYymHM6TbTOc9CbHFIcah/6aeQ9Z4kQMeNr tqBcsdDe3Z4aM3xp7/rmIXHwg9Nbgxj4a/spf27HIBdKlA4DXxKoLI2F74HNb/kzatj0qy1p259 HaBtzZKLuTx2fVUsjBEUF3ea1pnJtxVbhbYGeVQmO9kzpiLujc+9HMnCvj/VphiiQUb7e/z5Rmo cRDsy0K3YTR/r8IR1ZLT0u9Yv0OjMjKX6f0MBku3zH8wbHMS2zOTVgkJ9XzJX3xYM94owfzu7vH uZ+lW/fXwrRlmAJbhIXzkbbWk4V+SmI3Lt3Es5UF2Eg2pS5XEaDfckJrGNM8AICX60biQUm2hqh C8EfSQyim/TsD8FNUHvMBivjKXQ7Ca+4kQeKz7MAND4qxFgdWq0Atm5pPkw/zIpzXACXA= X-Google-Smtp-Source: AGHT+IFa03vzASFOeV3tkYwOCHMw8tgEJ5PO5wg+99OqFUMyin7qdWS3VHfWaCM9WZslKvcaaksONw== X-Received: by 2002:a05:600c:470d:b0:471:1717:411 with SMTP id 5b1f17b1804b1-477c01edab1mr514226995e9.24.1764683162615; Tue, 02 Dec 2025 05:46: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-47926f0ec69sm19383375e9.1.2025.12.02.05.46.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:46: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 v6 07/24] libcamera: shaders: Extend bayer shaders to support swapping R and B on output Date: Tue, 2 Dec 2025 13:45:27 +0000 Message-ID: <20251202134544.662446-8-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" We can easily facilitate swapping R and B on output. Pivot on an environment define for this purpose. Reviewed-by: Milan Zamazal Acked-by: Kieran Bingham Signed-off-by: Bryan O'Donoghue --- src/libcamera/shaders/bayer_1x_packed.frag | 4 ++++ src/libcamera/shaders/bayer_unpacked.frag | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag index 171a928c2..db8c2a0b3 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -257,5 +257,9 @@ void main(void) rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); +#if defined (SWAP_BLUE) + gl_FragColor = vec4(rgb.bgr, 1.0); +#else gl_FragColor = vec4(rgb, 1.0); +#endif } diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag index c41d72f4f..06d80f3dd 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -152,5 +152,9 @@ void main(void) { rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); - gl_FragColor.rgb = rgb; +#if defined (SWAP_BLUE) + gl_FragColor = vec4(rgb.bgr, 1.0); +#else + gl_FragColor = vec4(rgb, 1.0); +#endif } From patchwork Tue Dec 2 13:45: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: 25317 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 D09D3C3260 for ; Tue, 2 Dec 2025 13:46:11 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6712360D22; Tue, 2 Dec 2025 14:46:11 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="DkoW4gRh"; 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 B80B560D15 for ; Tue, 2 Dec 2025 14:46:04 +0100 (CET) Received: by mail-wm1-x330.google.com with SMTP id 5b1f17b1804b1-477b91680f8so49631295e9.0 for ; Tue, 02 Dec 2025 05:46:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683164; x=1765287964; 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=Q4CDq2GIoZiOmZZizVsTSfFeZOkehjzWMK1uj6JNWy4=; b=DkoW4gRhd/36dHcXec5DQU9gRzylxw0+DI9m/k57EE76I2quYRX8qdkvkRfjEfTngA 1M5PXayaYi98iWxSGFoAxPIZY3F08BTg5nMMLMjv4IuxnJKjWmY7CEYWv5NXK+/S831c CMYSpDPH+oCUXZe0Qdi6zlgpBXtT1N2xGcR6NptK5t0gGUVm9heaNeKb7ubChENp+g2i QDQwHbCABxy2wwxhaPUwKnt47e++KNkbQu4Y30BZYkxBmj3phpPO5sraAuQdD4hehYW0 V3RqNiXO0ryH2zxHREU/8XpP7zH0SoqiX+8E3IXoJifleg9Kc6byrh96TNKClm+p4alg aCOQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683164; x=1765287964; 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=Q4CDq2GIoZiOmZZizVsTSfFeZOkehjzWMK1uj6JNWy4=; b=s4HFfXhqPeqB9JS33SEu2GoHJhK769Rq0fGTmJApEfNw6qUp8NEITsF88iwVKV06+M fHgnRUjZVyjbhsG92JJz2CPFD7Y9iOUm3fvJM8t+ln1bqS+nalZmzcVq0nqhe8rmoplT UymXqmk0qcGRh6feDd/WoRRBuH6bLlNuHBzD2chSrNvztrhWUDQLsEoUI3yxTB8T1E4L b9t5g56bvq0gOr981vDyW62V+ZLDJw0Cp9gt7QK+5fBXBeiPBu+BGIEpW0qzkoFIrp9H WHD8VmLhcRFSFqd/mtxDcOfG5U63ktz1Hm16yDLmoeQL9GXsHE6eFO4eyUEyLveMWRpN xdUg== X-Gm-Message-State: AOJu0YxE2DRIv167RaNzYjZ9BxmgIqK/LwNvLaIEPCARaz6a2omqStmW H+JVkE5oOt40l6GnzQ8HDl1AleWfHNwenx/SDVoqA2bMnvvLamTWvl4A0suMZ3ZI5GHsGB0Rxen eVpUx X-Gm-Gg: ASbGncuWLLCQeZOzUCS83KLeSgBnA87JRKfzN2R20WrVpu1ENbSU8MvOkxrekgprfmx rnFrXQojJVl4FO1Nf9iSfgZbieoKP3Zgcn3grSfh11/JyknkyebJCzqEMKa6NKtDBfX6wfSZr4N FnszQRc2/wv8M27SAHj5qZ5egLKsYFfhJVZqvvcMrx2aESnklWA0aDYSwUDsaqSAHx3ZQN1LhUM DZZgMlUdkkBCvp6NRYS5heNWR/rfL8oqWZruSjjs+zE31GBPfDX+FuRVcsehdKgns8RA/lpDUSR ln3j3mu+Au5WSdTn/1/3MDyJe0haInnXdQB9Zy1i0WyieiJ06TcL3INNLja2PSxMJAYhrw2v0Gc f6eqa2DMPY4Ng/GAobADhDdV9sF5yqG9O5S4MUs+Nx/BiiO1SdPvqsgP3j9bEGZZ47jBL6FbxQU 3g7p8MuG1FiqbNOh+KUbesvivreGHmdxvfUMqdgYW54Ci7y2lfLjoX8d+mV0GT08OK0qc= X-Google-Smtp-Source: AGHT+IG4587gG4HV1H9wekoEynXcC7oBI1rxT/PcB1y7euqVSbYXnZyKwgWH7dlB9DYxaMbWy3m30w== X-Received: by 2002:a05:600c:5489:b0:45d:5c71:769a with SMTP id 5b1f17b1804b1-477c112400amr409330585e9.26.1764683164050; Tue, 02 Dec 2025 05:46:04 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-47926f0ec69sm19383375e9.1.2025.12.02.05.46.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:46:03 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v6 08/24] libcamera: shaders: Add support for black level compensation Date: Tue, 2 Dec 2025 13:45:28 +0000 Message-ID: <20251202134544.662446-9-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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 | 3 +++ src/libcamera/shaders/bayer_unpacked.frag | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag index db8c2a0b3..7036fe278 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -66,6 +66,7 @@ uniform vec2 tex_bayer_first_red; uniform sampler2D tex_y; uniform mat3 ccm; +uniform vec3 blacklevel; void main(void) { @@ -213,6 +214,8 @@ void main(void) vec3(patterns.y, C, patterns.x) : vec3(patterns.wz, C)); + rgb = rgb - blacklevel; + /* * CCM is a 3x3 in the format * diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag index 06d80f3dd..f0d8cd1e2 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -25,6 +25,7 @@ varying vec4 center; varying vec4 yCoord; varying vec4 xCoord; uniform mat3 ccm; +uniform vec3 blacklevel; void main(void) { vec3 rgb; @@ -108,6 +109,8 @@ void main(void) { vec3(PATTERN.w, C, PATTERN.z) : vec3(PATTERN.yx, C)); + rgb = rgb - blacklevel; + /* * CCM is a 3x3 in the format * From patchwork Tue Dec 2 13:45: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: 25318 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 C0884C32EA for ; Tue, 2 Dec 2025 13:46:13 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 42EA860D36; Tue, 2 Dec 2025 14:46:13 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="Dlw2tWJG"; 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 2C60D60D22 for ; Tue, 2 Dec 2025 14:46:06 +0100 (CET) Received: by mail-wm1-x332.google.com with SMTP id 5b1f17b1804b1-477632b0621so34570105e9.2 for ; Tue, 02 Dec 2025 05:46:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683165; x=1765287965; 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=20MMXTnFm6SHHWDjaqh8aMbgaaC551tC4RzFJEsLOHE=; b=Dlw2tWJGShfvohzQBYBoyrKvcKs2TZBmoMydxdQYHWFsGQNZmCDwSPT8wLICmOIB/0 BbgGlNAPXSsAqJWwWWBIvfop/Yu7VGZBDi4tx+HsM7iDAQGptCbkKD02HOU8wLqVY7+f UHoPJyojEPdFO3jUfTp+KlioxwVsfhmybHMw5jpE/P8geV4qE3nTTJR3ZrPSnsQ6tqug 3nCunlBwWnnmU7KPYH7amlVaw1jPJFYtrn4zYw6FQeUNxqwPEQ1s6L3Se9zG2nz4i98+ 2GXiIP3RbbRN5TfCWz82vvcLLAelaFyTQ74wNGv6DMD7qRew+nap9poSByCXgiZAFJB8 LcGQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683165; x=1765287965; 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=20MMXTnFm6SHHWDjaqh8aMbgaaC551tC4RzFJEsLOHE=; b=ST1PrtvROM38bKu/aQ9BciHjmWIsYnmBlch5/cGiFaOs7ef150GV6OHhlmkPf2NQ9V MyghuCLTriyWQTJgWwdZutd0zwRKXimA4k7h9nyZKHLwIPEa+sva4If/wRPwKwZsblKk M1R0hixSIoYF/k7bgeTsJbb3R2Uoy1TdP+UVGbVuFGjBSK+l+1j5o9y2E++8rXqmDr3Q CC0jlRueGiSRZ9/2U7E2yBpnrcLYQRA6hzMgUsRg6VCsVwD4Zm8BzH46cgX3147uI3Ld C0qOp/QEY/+BvGHkvVnvxm/5DP5FJaqTNdBXfAoMY3PVrYDdldOVJOf4yk4Wb/A8M3KG ZYSw== X-Gm-Message-State: AOJu0Yzn4qcGAj4U8lqoFGTiwNokSqvxDAS3DkwnUoC1QwjQH/U35sKs gK+jyCYpJzAS+3JuDCgy7L/+am13AHgHr2bhZG5B3BJA1JZ2kZQoSz7F5IW2Uk1IcPY46nDLfnN lrtj+ X-Gm-Gg: ASbGncuklPwLeFpVhQ7HGlw+d3+z1He39A2GwbnhAM4o0mVC/iB3OZF8yTTXD+2hPjA M9O8a2e//Wk+4H4nhonwdwJaeh0D+63k1Q7u7COItuEjbT5O9vhsNjF6CKbG2mY26lTVWORfo0+ r+7D+6ALh5RuWtbIbPk6O74BKGbzD85I+0b9URAXd6/oiaSJi73OX6DMMFiSsWCGYNl8l34vCNx gErbJiYfgtTFGI1xRBgc5W9uH8tKl2ftWaRYq8GsYIIO7p18DhobjPjR3nCScx+Ud+V+JC1/1ht wbIoC9ZJhj9ttyLa3PIrQes/iHukGp2loE1SX+IkkpNuyX8lmvDAkCo9WLrW2B6kamnjbbycJQr gBhN1KcDrlqR9P2tmafUF+E7miZHjoZvKacn+1hRLTZlX+tjUz1xPaY+zkn9f3hogrpZZMhOC+K liKn2IIknvGfnkya6JTlFDBCFKgICHL7cusY5adWA7GCryDPO1iF7JWnDvNuaRiHxqayY= X-Google-Smtp-Source: AGHT+IE7R4Mk2WORyE6WCzL0gC4n4l6u7b5fRXJ7te7IFUqRB8+Dn/Azkx6S6/7ZWc4qF7pS8z7Wwg== X-Received: by 2002:a05:600c:46cd:b0:475:dc5c:3a89 with SMTP id 5b1f17b1804b1-477c1136b7fmr414976585e9.34.1764683165396; Tue, 02 Dec 2025 05:46:05 -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-47926f0ec69sm19383375e9.1.2025.12.02.05.46.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:46:04 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v6 09/24] libcamera: shaders: Add support for Gamma Date: Tue, 2 Dec 2025 13:45:29 +0000 Message-ID: <20251202134544.662446-10-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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 7036fe278..77d9fbfa7 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -67,6 +67,7 @@ uniform vec2 tex_bayer_first_red; uniform sampler2D tex_y; uniform mat3 ccm; uniform vec3 blacklevel; +uniform float gamma; void main(void) { @@ -260,6 +261,9 @@ void main(void) rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + /* Apply gamma after colour correction */ + rgb = pow(rgb, vec3(gamma)); + #if defined (SWAP_BLUE) gl_FragColor = vec4(rgb.bgr, 1.0); #else diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag index f0d8cd1e2..aba11a87f 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -26,6 +26,7 @@ varying vec4 yCoord; varying vec4 xCoord; uniform mat3 ccm; uniform vec3 blacklevel; +uniform float gamma; void main(void) { vec3 rgb; @@ -155,6 +156,9 @@ void main(void) { rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + /* Apply gamma after colour correction */ + rgb = pow(rgb, vec3(gamma)); + #if defined (SWAP_BLUE) gl_FragColor = vec4(rgb.bgr, 1.0); #else From patchwork Tue Dec 2 13:45: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: 25319 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 D7895C32EF for ; Tue, 2 Dec 2025 13:46:14 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 005C960D17; Tue, 2 Dec 2025 14:46:13 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="cx1rFdu3"; 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 9795A60D1A for ; Tue, 2 Dec 2025 14:46:07 +0100 (CET) Received: by mail-wm1-x331.google.com with SMTP id 5b1f17b1804b1-4779d47be12so44926835e9.2 for ; Tue, 02 Dec 2025 05:46:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683166; x=1765287966; 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=C/sV5SonuYN3A35MLfu7GzsniU0bzqMrcJSwifQ1Hik=; b=cx1rFdu3zr+rQDeRvuCQRCpd9PQrDwhkYY12hpOPpI5FYd7gCoZDT2Hr5T1+m0Ik/p A/lRp2bKNevHDjzXI0+SOholmNzck3YnjlYOXhHDLSzveKe9zlWq/ajp+oQtnGe5Bl7G rFsgRbEw5YoNdgY8GFIV/5rqSgq6b3bnGMB8nlAMMY8S6TYKnSwHQJFpouePascGW+XQ lZb4XdEu2mb1e5gtxv4oXdpD478PX315hLjrZrxoTIruBYOdlQe8RVM7cbNuUpO4ub9V mwlSkUUxVAzRoD4kLy9ENSndIRRB1hv5OzGgBjdOR88Uga6O7BwdgDHRuv8cmrzTrVKj PWMg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683166; x=1765287966; 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=C/sV5SonuYN3A35MLfu7GzsniU0bzqMrcJSwifQ1Hik=; b=pSQzomaen7i8gDfaNxvLPBDnnuNSGgFfKelNuHECxhvbhH+fbj0CaYznCvLm+8pRP4 qRVDSu5hDFndUWMVbhhJy7kcw9gotjf/i6SEa1UXzxiKcq3+7I5Ue//OmUygcfF/BSNK 1/AB+2tHM248swqW1uexKhCJUgkEVGlKmClU3qzd0ReHHc0rjG/nWpzgGPWpYkFwVP0z kQ0IhvhSrGA6ZVijO5XesqB8f08KAK1Aj0GPWMt2gM9vNsyEFbt+bexvkTuPxtNz4/fu pBFWhfHMVNyuwhq/c+iL2WuujxlcBnjc4UY7wFDTiRfXF096QKgCFAsyuk48+rmXcGKk SsFQ== X-Gm-Message-State: AOJu0YxMcMGJMd21sbCOp0N+UvpCrC1z8XOc66gDOt83irdWushEFWZi WZco44GCuWmza+yiMbXvZBt8V3fGe7AB/S6UNbX3fKcUu3ucbeYne/MBbsbVF2WNfIK6zRSGVhQ uW4xa X-Gm-Gg: ASbGncvwm43dB0l+kTp7WdPynYWOvwNxeN9M/XeponXyN0p3KoMQQVWjoRg8/eoDVmz 2WLB3TH8KgT4lc6GJFb5dYBnrU/emTLBr073I+yxu5ETL9GqcsbmichZpEmakaYhlbsOmL6ZL5A T+EBtPBcsBe/fsICUANCFyLWmqtOlzw0TgHW2VyavjsdcKHLhYaC4dX8zQrhJqBLG9MHHplJ5XM TGQz0qi6vDMizeRy/81hd4nm9Ms7ert6IhlJfrOk5/nwKzkNBnYezm1BaleapF4uM5J95poJPGT wK2V3XzWGgu0nkC+6QTEeZg0zYNokOf7QJaEFsI93guJxxcw8Qu7t+C7+BxoY69BS/CG5cY3hHo aRmxNnVOIJ2cU5gFx8pO9tRNHrahOLfyj6JfaIivPZ/yDCUVZWqDTvTC39cvyiahxjQewR/5PjR bTDY8bB+zfCKqhK+Vef1SAaPydGk+tzv1OAIayIyLAdavGSApJnqdxArwLy7u8fwONLa0= X-Google-Smtp-Source: AGHT+IFofNvOacnLduLBPdUDH62M9if1OU5eoHP6UlGVwUjxgqWnAot+k6CNhiXEtjbAoaJJ0QrLFw== X-Received: by 2002:a05:600c:5494:b0:477:93f7:bbc5 with SMTP id 5b1f17b1804b1-477c0184c3amr404258905e9.10.1764683166581; Tue, 02 Dec 2025 05:46: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-47926f0ec69sm19383375e9.1.2025.12.02.05.46.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:46:05 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v6 10/24] libcamera: shaders: Add support for contrast Date: Tue, 2 Dec 2025 13:45:30 +0000 Message-ID: <20251202134544.662446-11-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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 77d9fbfa7..2fc9952e2 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -68,6 +68,19 @@ uniform sampler2D tex_y; 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) { @@ -261,6 +274,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 aba11a87f..caa0ba15d 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -27,6 +27,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; @@ -156,6 +169,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 Tue Dec 2 13:45: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: 25320 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 0CA97C32F0 for ; Tue, 2 Dec 2025 13:46:16 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 49EBD60D26; Tue, 2 Dec 2025 14:46:16 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="yVYAamle"; dkim-atps=neutral Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4196960D0C for ; Tue, 2 Dec 2025 14:46:09 +0100 (CET) Received: by mail-wm1-x329.google.com with SMTP id 5b1f17b1804b1-47775fb6cb4so40125785e9.0 for ; Tue, 02 Dec 2025 05:46:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683168; x=1765287968; 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=lT2eJ2agSvDxCvtLEFurZF722zwcGLXZKk9J6KGVpFg=; b=yVYAamleZy0RZ5rmYLIhNnvLZR6OTiXLhFD3QSn+1+erUoSqXvGof6pukDcK7W5aIn 69D/AHwCMog7fAyEwuFNofFzpV1WrNeIUNS/G8/bGFvpW3CSjd7Y93AFoyca/9tSTxdF I28RJTS5lPI+pmTq+stcsnG7LpSbXsVMAhHLhaw1y3F08H79Hh1FnZYXTJPzoB1eTToy g/qe8XdnWFsNCwHCyTefMJ0FIk8HqC5lPEMWIXNugSBRskwuFpkoJRTwvIXHlDaLOJ1l 7bf++ekibptRjAESVHMtY3OU3etYCS9X0HQ9Nt2x5UgAnwVmz1ihvOfdQOC2p+ZAPyM2 lBaA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683168; x=1765287968; 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=lT2eJ2agSvDxCvtLEFurZF722zwcGLXZKk9J6KGVpFg=; b=Mdo4poqnHDV9MWxZxeEdSWB1fd1HIANYiGk5AAkXG6imMvWMy7Xue92bcpZYcsmpTr EaTlGX10UecKeV1gHy/YyhdZpFB8WcpnquvnnNoMG2XUv9q3pRniLlsRtuji36NXBwRl olxrzTKIVmM8cENvDA1TbhqwekdwZTtkJkG+8JIo9xNgjwEHrr3M1Es4qr2HWjvvXsFo Q7Wk7PJ7RnMBH3GhMQB8DVX7ekFHq3cXTga/fXDdR9ahl/pFOj/S7dguZFnJL+g4DR+Y lhlk/JvM6Y0Co8w3Nw6lxcIz1BHkccGaqaCRvSrQXTb+koeRbv9kZoJFioLmClOyVZwq TeWw== X-Gm-Message-State: AOJu0YxIm1uWArWTNM6kSEJBz4ALUIezj4UcaC0XnK/G0REFFvqxU/Ho ThwmVqNLtG4qkZqydnVUowfgqSj83fRZs/Ewsb8A6NKN41aHGXGl2mvKDIb/8mMMVRG9w+Tts9n hmYww X-Gm-Gg: ASbGnctjlxUGEXdzv21ye0KNk+pAW0ksk8xHPGFuOsiuwF3bFCkBtfbQHBk7X77ZVdJ 9BHQ2TFZK9G5XtHaUT4JXv1xiaYJ0xLuo99rCHDnnfmSiOmeGY/H5yeOEyccVoRLwPscriEEF0m NyJHADwqIyPuw0LyS6BioHGiXT3uXspUtpA/e5pkQE1nGmVjl0MlygjNTAzlTBUqkeVFvKfo6U5 8nHjb27MFtNzofmbEwSrDdIuhjHJNu+w466PeqYv4ze1D3yIB1h4Hx+5DIc+9n5z7aeNYYcdbgw sDa/f5BWecO+1WUneLviMY8ylUrMLusjjZIRgdHRXL2J0WSQ2eJcdx8piKrmum0VUBmB9yrnyBW v+Gx1L8j++VyqgpHUGLVi8f4KosHyQhDFwQbCOPull3u4Rq07rIlBRskEIoNZ3DQV9OoSrAHhMp LibMZEpJaBMRzrRwUl+WTVeudf9acOWr06Xndz372/ilMgYQQPcwq/7vnAh/mMupcVH4s= X-Google-Smtp-Source: AGHT+IFD4sbIsWk93pwjlLd69+3+IWVVU37mH3l+piLhbrBYqCjhzmurd8MMnQHrxbwws1KkjmV5mg== X-Received: by 2002:a05:600c:1d1b:b0:477:9671:3a42 with SMTP id 5b1f17b1804b1-477c1133e4bmr416225035e9.35.1764683168522; Tue, 02 Dec 2025 05:46: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-47926f0ec69sm19383375e9.1.2025.12.02.05.46.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:46:08 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Hans de Goede , Bryan O'Donoghue Subject: [PATCH v6 11/24] libcamera: shaders: Fix input sampling when width != stride Date: Tue, 2 Dec 2025 13:45:31 +0000 Message-ID: <20251202134544.662446-12-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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 Tue Dec 2 13:45: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: 25321 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 1218DC32F1 for ; Tue, 2 Dec 2025 13:46:17 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 33B3D60E3A; Tue, 2 Dec 2025 14:46:17 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="p/k12Yih"; 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 CB62F60D1F for ; Tue, 2 Dec 2025 14:46:10 +0100 (CET) Received: by mail-wm1-x330.google.com with SMTP id 5b1f17b1804b1-477a219db05so35539895e9.2 for ; Tue, 02 Dec 2025 05:46:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683170; x=1765287970; 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=VhiuERx2vMJRfmFF4eANvKcaLtsYNNbBOcJTKQ8FMPU=; b=p/k12Yih5mtugcKytXEzYzjEUmeIzgoWE4Q6U1dTkkHA1dKbEATOFH3YDBJwCTOB/G U3m2c/rw/oQAxGMkpWF3C0ZIkbaXOleLPYY8gLIwG5XXj2GF/x9Wp6EGFWswZnT50MzU 1pnL5Pwba3ivOLAjMLcjPQb0r4sunTucgoxgRIiX1jMZrkQkO9ijrxsmhElnFIyrks3z l55+tDao3OmmVGwZ+5pc3U8/UcS/1N9boJv1r1FSZRO69U3UCvgykowFO9+lpVtahqSK So4G0ZDy7gGJ/HzFjXd+Z8Sd3qllghHkErqawdG1pfo6ixEi9hy2tgUedd9vJKxfllpX h2Jg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683170; x=1765287970; 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=VhiuERx2vMJRfmFF4eANvKcaLtsYNNbBOcJTKQ8FMPU=; b=l1vvS1Q+Zf5VNnEJ3+2aTEv7GLficrqRDDClIwcz0Xpb0EbjuXwK+sw6Uq7k5DXAYW 1Q7jRgqtqIR4ufwpIw4XUbxuAmX8e1dJz2dabLHriW6TeCtMHDJqQboIP5GFT1lbxab0 YyfCbY64CtY+YlXZUooUumKTNmpuz1MrgRUP4ZonnxoXL0Q0j6g49QyJX0hwbG89NycX k8lkta1ntyivn+hhchNi2Vwgo53pnTEkf8Mu9fbed3DHuf3/+UQPSGQY9JaIosr3sCKe 618Cgrjvw7/9hdpzjam2Vu6yJrZLSQTToSXgfYV9KJ/zkZof6ogSWaFcDVJ1IlFOvLLA 9i4g== X-Gm-Message-State: AOJu0YygXyvoX3Z++rBOj5IMYMQfOf69jetKG6vHpX3UtrlvXWTbl1Xc tTBLjj6Wb23vJW42G34V8qSaBtwJ6hLz1JQoywMN537Pl9An8k+Nyrqtmwayzl0WMic+vXxdrAM mhZKO X-Gm-Gg: ASbGncvG3dMQ4xGu2I6tH34C4FxrUhwELdvF7TELA5VNXF0eCYRa94gT2HdQyIzvqYN 4el1X4Gg20lR3cXAIxASj1XEeyGffoUDAy7VLqpYEG6c9WWcju74m2ZAA+RUswY0rGnN7lmoayR 1RxVeEOHjoMLXKMv+Xt0r9d9L2XcAawe4EdjZ3ET9kct7WdUXdV0tOrH6x4aTzIvnXcoJajzNc6 bMQisvUeOfGpbXv5uyGo5OYDeJd5MUVBUglcsQcnYRk0me6X4HsH6+/t8DgPdWbxvO/HDfSTxS9 9A7dpJI/KTi6RutRKDnNSkEdDLsDP3dRcfRr1ofFP+aUEtWOndqpWzzq9EDmXYa2G1l5fn7T5gT tNYpuuatZ5kBkXaBGaWPWD0UtQV+tdjjABzETbjqtldoFCvrRqW2Ztb3FI5RgUahm6QYi9tU8hp KV9UfIp2fs+e0pog6kvlXNB187JOrxI4R6CFotr31saTHVXnk4XkApNktUxLC4goFnKIk= X-Google-Smtp-Source: AGHT+IGhk6pHWAaCoq+NYqUGyZk+F8aGTInpklt+aIWYR7H0uiFJfqFTNju5/A3B5Z0dj5vQe2gpfg== X-Received: by 2002:a05:600c:529a:b0:477:8a2a:123e with SMTP id 5b1f17b1804b1-477c1133932mr427455235e9.33.1764683170029; Tue, 02 Dec 2025 05:46: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-47926f0ec69sm19383375e9.1.2025.12.02.05.46.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:46:09 -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 v6 12/24] libcamera: software_isp: debayer_egl: Add an eGL Debayer class Date: Tue, 2 Dec 2025 13:45:32 +0000 Message-ID: <20251202134544.662446-13-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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 | 641 +++++++++++++++++++++ src/libcamera/software_isp/debayer_egl.h | 142 +++++ src/libcamera/software_isp/meson.build | 8 + 3 files changed, 791 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..2b3df05a6 --- /dev/null +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -0,0 +1,641 @@ +/* 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"); + 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_ + << " 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; + const unsigned char *fragmentShaderData; + unsigned int vertexShaderDataLen; + const 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); + + // Texture we will render to + eglImageBayerOut_ = std::make_unique(outputCfg.size.width, outputCfg.size.height, 32, outputCfg.stride, GL_TEXTURE4, 4); + + 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_ + << " tex_step " << textureUniformStep_ + << " tex_size " << textureUniformSize_ + << " stride_factor " << textureUniformStrideFactor_ + << " tex_bayer_first_red " << textureUniformBayerFirstRed_; + + LOG(Debayer, Debug) << "textureUniformY_ = 0 " + << " firstRed.x " << firstRed[0] + << " firstRed.y " << firstRed[1] + << " textureUniformSize_.width " << imgSize[0] + << " textureUniformSize_.height " << imgSize[1] + << " textureUniformStep_.x " << Step[0] + << " textureUniformStep_.y " << Step[1] + << " textureUniformStrideFactor_ " << Stride + << " textureUniformProjMatrix_ " << textureUniformProjMatrix_; + + GLfloat ccm[9] = { + params.ccm[0][0], + params.ccm[0][1], + params.ccm[0][2], + params.ccm[1][0], + params.ccm[1][1], + params.ccm[1][2], + params.ccm[2][0], + params.ccm[2][1], + params.ccm[2][2], + }; + glUniformMatrix3fv(ccmUniformDataIn_, 1, GL_FALSE, ccm); + LOG(Debayer, Debug) << " ccmUniformDataIn_ " << ccmUniformDataIn_ << " data " << params.ccm; + + /* + * 0 = Red, 1 = Green, 2 = Blue + */ + glUniform3f(blackLevelUniformDataIn_, params.blackLevel[0], params.blackLevel[1], params.blackLevel[2]); + LOG(Debayer, Debug) << " blackLevelUniformDataIn_ " << blackLevelUniformDataIn_ << " data " << params.blackLevel; + + /* + * Gamma + */ + glUniform1f(gammaUniformDataIn_, params.gamma); + LOG(Debayer, Debug) << " gammaUniformDataIn_ " << gammaUniformDataIn_ << " data " << params.gamma; + + /* + * Contrast + */ + glUniform1f(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..d659dab88 --- /dev/null +++ b/src/libcamera/software_isp/debayer_egl.h @@ -0,0 +1,142 @@ +/* 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_; + + // Shader parameters + float firstRed_x_; + float firstRed_y_; + GLint attributeVertex_; + GLint attributeTexture_; + GLint textureUniformStep_; + GLint textureUniformSize_; + GLint textureUniformStrideFactor_; + GLint textureUniformBayerFirstRed_; + GLint textureUniformProjMatrix_; + + GLint textureUniformBayerDataIn_; + + // Represent per-frame CCM as a uniform vector of floats 3 x 3 + GLint ccmUniformDataIn_; + 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 Tue Dec 2 13:45: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: 25322 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 6BBB5C32F2 for ; Tue, 2 Dec 2025 13:46:19 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B025B60D2F; Tue, 2 Dec 2025 14:46:18 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="KLUAQFlF"; 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 05F7460D15 for ; Tue, 2 Dec 2025 14:46:12 +0100 (CET) Received: by mail-wm1-x334.google.com with SMTP id 5b1f17b1804b1-47790b080e4so29263975e9.3 for ; Tue, 02 Dec 2025 05:46:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683171; x=1765287971; 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=vQVPOM12y5l41Oik4t/KhoAdrAnNrZonwF1zaIVHcZw=; b=KLUAQFlFrX05yTNve/JDhbfgfVP/rmhkBEiWw4Bno+W2uanGgOUpStcmT2KZEvaExX 4r3u7xsLbJFmrDT5BS8NdUIEo4btzMCAW7WxzROnZ/RGpbFUDkJtWMMI4dXx0JZAaYXs YqTwTV+2ops8FMU6b1LBKHA3Sr4lsqiow36jjdzofNlvuu70xxBBoJiUjaEI7QkUldrF bIRaLKos4txi/AWjj3fzsV/14tVE/dsfbhJN2S+XDN97Se0uuXRnmrIejbhyGUyRxYql S/pl/Nl7xLDQgYn+VnYcfqfayVNJcvpFtNCMh2qAr0JPC26eQM3IPVAC3IjUd4DpmQoH 7NOA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683171; x=1765287971; 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=vQVPOM12y5l41Oik4t/KhoAdrAnNrZonwF1zaIVHcZw=; b=cqOlV5AgZDbgLKXrquuEGg5NCaj3tsr0KTwGgOKJAXLeeSV4RzBd2Z1WFRgr2JXMPa WMZLKiWOQHMZzMDW03PfbazEXW6XRiYtTm2A9BvIQ5mcck4TDbFljAnZgCV1ratEjixf vJZHytpA2jspeuuUv1CEceVixQY82ThpWnVC7EgZ/1QOWVTEVMVNbhoI3sjIyClajG84 H1rhJC/HJqFEQcnA22+lcLS1vgPTXG0yVDgyNsHb/iG9sq3g6ryJHF9YpqBJ7sefbVRp /BqUfdAIMQBKyunBP1EpGMCLIQftG60EzRlQtm5t2P17JYVZuobpx6IVb4F8j+d+j+EK KpWw== X-Gm-Message-State: AOJu0YxOgfCxc1jV7ybEHKTcojNjdNVlmSBcXMHWNLl0nJG7SFeX19PF THH3ZJZ8P5+620YXUK84kMESRzyHyUUQHhk9s1DA0ORDb8FnR3CCg/PgjZO/sCZz2SaU9LpRL0Y gynz5 X-Gm-Gg: ASbGncvA+SNnY3YiJjO9TP+gFPq7Na8d96ospnM2Cusmpe36Zi3iKalPlzYsq8WBcYX RULNwH4p3E91aSm+saAe2zeQZV3/MBvNreVnREk6KnuKv/neOry2WFgnk7IQay/w0ITxGvpxbxF 72Hy57RowioYUrw30MZyPpIpipL34Mr1fQqmsSeFX+T3Dcv+JaOORMnkLeID3vyTmVlSzfr7vcV +J8cN5JpPKK8HXzYLKXT/kSwHwdcl4hADsLYPy42UEjYJDVzs8g/WXvJUJCXzpoDWnLzUbZe3ik xuhJzLH4DsiCe4b56SHoQT1DNAnyWR4OHvJtupPdj5tKXncWIOfCuRri1yqlXP7EWRSdEpI5pkV U2j9lTILsaY2KzR8zutVa7tzUsZLCc3sjlKjQf3Ke4pgQxc0u0/L/ny474rQ5WHe3i9OvrJ25Ni a9v3rm2GUijh+tDTinDe+klbXI4IaQcc1RgkNxIvue4cx4kXTlz9jdvGd0Q1e783CMD+bR/PqRe IGbYg== X-Google-Smtp-Source: AGHT+IFLraZPQtKgszeCWuUGzes16e4eLH4wOa5eVdiDfZ3PToDvhq7g88a35ykZ1cgfwk4zEwX2mw== X-Received: by 2002:a05:600c:354d:b0:46e:49fb:4776 with SMTP id 5b1f17b1804b1-477c10d7003mr425799865e9.11.1764683171347; Tue, 02 Dec 2025 05:46:11 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-47926f0ec69sm19383375e9.1.2025.12.02.05.46.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:46:10 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Kieran Bingham Subject: [PATCH v6 13/24] libcamera: software_isp: debayer_cpu: Make getInputConfig and getOutputConfig static Date: Tue, 2 Dec 2025 13:45:33 +0000 Message-ID: <20251202134544.662446-14-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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 ecc4f9dd0..67df2b93a 100644 --- a/src/libcamera/software_isp/debayer_cpu.h +++ b/src/libcamera/software_isp/debayer_cpu.h @@ -97,8 +97,8 @@ private: template void debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]); - int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config); - int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config); + static int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config); + static int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config); int setupStandardBayerOrder(BayerFormat::Order order); int setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat, From patchwork Tue Dec 2 13:45: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: 25323 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 B08F7C32F3 for ; Tue, 2 Dec 2025 13:46:20 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 0D3A060D35; Tue, 2 Dec 2025 14:46:20 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="ycVigsk7"; 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 4796260D38 for ; Tue, 2 Dec 2025 14:46:13 +0100 (CET) Received: by mail-wm1-x32c.google.com with SMTP id 5b1f17b1804b1-4779cb0a33fso57909525e9.0 for ; Tue, 02 Dec 2025 05:46:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683172; x=1765287972; 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=hEJlz6jAIwEy8yb7eChaXjiRWpNQ8XNoPDVpvPMJ0/8=; b=ycVigsk7CHOO/Nh2YXqcxvRWOaXNpF1ZOTJdJphOTP+6nuTkWUc36QBTiW5flJFqoP 5QlXes11GYmvhd5thdmJtuS2OaoHjyyz39r8DLSjNg30MyYYKBrZAwhd8SpLtiZ3Cs11 qbLG40SbmCMQV1XS/VDmgoNR/LEwL6dkHVT3iQWw+xullItCE7HtQHdCogKesw0xAzrI UssPlQe9UPWmbLsn8pxMP0rK3FZL6XXQ7a75FI/kKiAY5W1vWCxEhN8sYdvNKdxMi0dY R5AkOjlLXQmpHNYiVRkFhvr3QFBrnBWlJqZM0iWWNqiVRZ2Y1CaEUDUbsHsb9Rs+r4qL dsWQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683172; x=1765287972; 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=hEJlz6jAIwEy8yb7eChaXjiRWpNQ8XNoPDVpvPMJ0/8=; b=fhA8Cvw04bis/6xb9/0CfYpMR679Q1DO1a7Wyc43eXF8GRZYDoVxNfidVmbevg1TwY rVIErbG3D9TwqqpInelQ8asQd5BE7ClaD0v+hDJgzfOBairhZHk9P0pXDHgpaBgDqM/w 3X2CucRFObtFTMJBYrqtnOzWgRsBQhmWgXOaSiKKFMeuUqvTfX7A3oCfs5Wol9JrwrgI H4JKtsZ6l9OkNsUwL7AMiRlLLe32umforu6gZndvM3jWIdVaDxob4B/Dd0xd9M75DR+F wsTIgIUabsTEikexvQYfC5E9lr/dnlTnZC+8YmKVI5ZGVbfQvVgtgvu76BRwi/L7+fxm KVVw== X-Gm-Message-State: AOJu0YyPXBnucIUo0trGr9cRKj2sr6/XnMLR/j68A+V8CApYGE5kPB5I 57G1+fK/jXxOstiEP8sYQ7zHLt19LyIdXew/mGhYU6rgLTzXcKrOH/US9dGJMFq4EWK8CSdUDGs b9Ekn X-Gm-Gg: ASbGnctBYrYDi3V92WA9HIUsWeRXEdmybYw9+6MpJJa5u29HHQvpyFgVfqH5n9htgbx 0PcEHR3Lo5PPbFVGExhz76dUra+FX+mZIzsvY0Kbu2/IWcSjQiyUWinJfvgcjYSs5VBx6xu3dY2 0r7y2AOdLh0Tc2kYko5n2Jkk0JQFuMmB2ZzNPPbHGnwS2Ky34gePYbqidtWi9H0xqcXgmKZ486C 1yi8qeK+C+bRu3kPQ7SmguZAUA+J7irRxeHRFq3qYmbYn6q7U9PqU2+c9RJ5wXTUtuqVnoZX/ZD FOAG/nlapVZ/6iOBIzdSKqmG0APclWraqpl1zEt/gyywBSzHPS4xn6D0inSlov3KzNA1IIbBTKM DANhYHtHDsqmsdIytAyRzgkd7YnGdn/OqrjsKdvJSA6YynzgERMHanMTZPKHA+nDzAK4LE/xcl/ lhJBBQe/1HoyRMZ13JwX1LGOlZUYrnov9Qh93IikzVFB7/wnCeLjGjrcU2ULiaP9gWSrU= X-Google-Smtp-Source: AGHT+IHIEM7qLl4oiqmaNDVHGpzfVdpiJ0N5+OeBbsZdNgAunKMbEVMXjQI8UJQTjZEkkBFT6+kETg== X-Received: by 2002:a05:600c:314d:b0:477:b0b9:3129 with SMTP id 5b1f17b1804b1-477c0175164mr422962795e9.3.1764683172603; Tue, 02 Dec 2025 05:46: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-47926f0ec69sm19383375e9.1.2025.12.02.05.46.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:46:11 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Milan Zamazal , Bryan O'Donoghue Subject: [PATCH v6 14/24] libcamera: software_isp: GPU support for unpacked 10/12-bit formats Date: Tue, 2 Dec 2025 13:45:34 +0000 Message-ID: <20251202134544.662446-15-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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 caa0ba15d..af5af38e4 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -44,9 +44,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 Tue Dec 2 13:45: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: 25324 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 9CFC6C326B for ; Tue, 2 Dec 2025 13:46:21 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1FD0960F2E; Tue, 2 Dec 2025 14:46:21 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="a0WUG/Cg"; 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 312B160D1F for ; Tue, 2 Dec 2025 14:46:15 +0100 (CET) Received: by mail-wm1-x331.google.com with SMTP id 5b1f17b1804b1-47798ded6fcso32431435e9.1 for ; Tue, 02 Dec 2025 05:46:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683174; x=1765287974; 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=YP6iClNl5iXvt4wCmpyJtVGzkYrv7XW1L69Mp5vdnxM=; b=a0WUG/Cg+E3CXGikBSqQl6KQZDzmUYIss08AcMLEGNLKNz30KcqP15rvjAbEEuB4ta jTVpVDoJhznhjUA4TcFhoGJ2xZOCAjLDUWg0DTJYtwyglwDhXVYZDPOw4+jXmDMqhrJ6 CC5RFHTQDSoLe3LrwW9BrkJfShKQf5rVMDEuT0w4y84lC3oask4k66yn1kqThgA8U7uh OHp+C5Ds7P4X1HNdB+1+nnLb2669yONUKi1cI55YahZHdvk7N5ZAeDfpb1wO5gQLnPz5 /82fMkA48lhAeEZB/6rvVTxIz5h1sR8xJ3Kxx8hThWVwsF0lMOnMx2XbMt22o2zXOfpC QI1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683174; x=1765287974; 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=YP6iClNl5iXvt4wCmpyJtVGzkYrv7XW1L69Mp5vdnxM=; b=EjEaR0/NVtp3huULdh9MOJPa98ZgWRyaywT1IAC2gjRVqeNPDbOB9w5bIBUYygbkOA CPBw6RxnSrA4YwiIuOzX0PbGnDh6bdtLjSYJkeMKJq7OaI+cgNBmFWCuzZ0P7T7dm2HW 8lYOsdhwYBsvLNG3aiitd4CAQw6M7TTqIX4rI5XZZ4V4OBYE/GV/Cdni795pcW/Z0oDR G8GSD9+zl/lD32mHGYpChkgapzH4r6N9ihJAK/EAnimDe8XJVhrV5ZOpT6zZvAwkWaEY 4uQxKyY4y8w0GCcG5P1kMgP6Sy4iA9xO+mZbKaEAvll84DqKTCb7R5+LGinRAZebCwXb JQCQ== X-Gm-Message-State: AOJu0YxUormCmVtcCLcllaCZZh/+bJSdegKOCBFJAHD5tn6le907pB2z lViQ820U6BEAxkawwmU1XhMIonNXfIvlA+5jMaD5g1FMKiNd2PzXbAjk55moIw9XWGVhftNd8gl /PUs7 X-Gm-Gg: ASbGncsVA5cQlHhe3pUzZIWiFC0DtNU5neNR510ITlSM4N8PGpNLcsT+RdYzMv/HazP OV7NtpV3s2lxJsy0a5SgfP3hzOrArpEF+JGQGiipqXOqKz6DPAut6KOwToDge/dxboU6VobZ5pL kn/unPpovzpFoZrWWaihEFqWYntJjRC3dV51oqnka+XmetX9N/SI5xle009zzReVisBLs97a8AU uJ7RReF6KciBBDyWy5LF18AZDFpnjTUB7yX5pKmjTC6GeeVyORcAiqgfKQADzmtXTA6LkdeqqeO PsHCwkWPV58TuC7wQJpZhQIfafoiw6MsczzO3y0i7ZbB8KlN41Aot25/Q0A3e6aroW6EY+KNUN6 t03pH/nXapm5uMVjQ9V+d0VCq9tT7cvndC2PXa8crIt93WSeSx2aoFHXNGC0nb2QQ8Qm+ZBO4TX +z16RUPcH2ssRaSwMNysbrNM6nr9OUU0uDMet0eIYj3hxqZc1g3JLzOi/ZuLgwa4X4kcDBvhyA5 vYFsQ== X-Google-Smtp-Source: AGHT+IEa/Tok+E6Hdu62wimAnqj3ly8uWAsB1pbP+d/yyqOR9kAqzRtQ7Pqga3q5vQb8iJwKihp30Q== X-Received: by 2002:a05:600c:310f:b0:475:de14:db1e with SMTP id 5b1f17b1804b1-477c1125568mr465508925e9.24.1764683174390; Tue, 02 Dec 2025 05:46: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-47926f0ec69sm19383375e9.1.2025.12.02.05.46.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:46:13 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v6 15/24] libcamera: software_isp: debayer_egl: Make DebayerEGL an environment option Date: Tue, 2 Dec 2025 13:45:35 +0000 Message-ID: <20251202134544.662446-16-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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 638d9a6e6..125a5dd81 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 Tue Dec 2 13:45: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: 25325 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 4DB3FC32F4 for ; Tue, 2 Dec 2025 13:46:25 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5E4B960F4E; Tue, 2 Dec 2025 14:46:24 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="wNw0cItN"; 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 6254A60D2D for ; Tue, 2 Dec 2025 14:46:16 +0100 (CET) Received: by mail-wm1-x330.google.com with SMTP id 5b1f17b1804b1-477b198f4bcso40708765e9.3 for ; Tue, 02 Dec 2025 05:46:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683176; x=1765287976; 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=TolVqEkHZsRaLOAV12HngkrzaM70wlhXChPq2Fetlso=; b=wNw0cItNuUCklfEFz/euLUQ21yJPD4ErlX/fgct5PKfyqtdvveYDPsDTIb1xU9S0eH D4eUBGr3pg0z8V7d2hPLot53xoqS2RCRXZ0VaDOad8OEdzZPcLQSKLGuXVlSyyFW5UmT YlnIEhh7IJod2hkbEcgOIKpwyctbOCOtZ6fNzgJpC3ABQZtQEviTJznuYZspZ7/U79Hh bpVIv/sTq4mArTAhFKPhe0hwNQpZ05llxLNcZYBGXkwJaDsXiWwu3lGbvJgCdSDkDZ39 wfPUWkAlNOr2/frbrb3nwNTReu4nKd2HNgxGCIzeKMWdFHzOaC1mC+tByq2zuKOeu7Tt UNfA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683176; x=1765287976; 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=TolVqEkHZsRaLOAV12HngkrzaM70wlhXChPq2Fetlso=; b=jjkeLy4GlVwQx74i+W9JHnBQ22p/DDxwnhm0mS0xKt/Wxpyt5lf2ajJcMI0VQAOGFx wCvJ0eIo3APPENhueMAbOZf5fM8LelYgY0+jzfrEXLa9yK0QX09BG4HZj2ADJPNMs5aU cXKwnLLU8dS746YUel9jKDpu8LwghRcgEgUWju73jU/Ed2UnfEvV27fFrlhuNBXCVw5o TyXNRAmmdoBma5t1TArY/sRk1lX/hhDfmLy7fw9j8lC19YaqPSjwkRqcZ8y4jpfHJhxA 3cNQ5hs0Wrba6s5ScXckMluTVUYrAmy67nXB+1vuSkqi4TJUk+BayGlzcsVrObUhIruS rAKQ== X-Gm-Message-State: AOJu0YxP1hGmadQPy/ZoQk0CMP8OmKaRWBAl4cf2z1C0vo/e8WG6bCI8 e7/kdfnmb43GXJ5JJMItT2D1htiyhzkbl7hfHC25Gn13QqeLHEU35He72uEhmlNezXQzsWByslV sZ59y X-Gm-Gg: ASbGncvoDwxGqVOezoGLOEv08EDr1jAYoK/mz1nTevXjDuOks6oemqVRbF4doos2haX 5G2VujCu323tdtuFl2yH5bqgHQn/+97ZIfAYh6gWbJFwoFF5Hynf6ZP5UEwxYgt2C4pmNR8xLVl R2Y+/7ocNOReZDpmfGzS+HkEzX0lrb/NwflBZtmBbuIuCCjnt3shcXSkdSWz8IMta10N78TQsVb FNC6NFDO+wq0QZsdJB+ACivce3qwTF69DJR5tRpny3oGxx18bAC9UHTHQT0YDmOfWXkW719TQee 2rZt9S3Sy+Z5N5miHzPeqQWw6p1Q7c1lUJrgNe1160i2NxTgx9SQG9KOFU/hvBwBoijcxuAsHbh 4Si+l82U73zDa5GrPDA8Oa3hVQiC+zvg+N9uRD+u1yGbqfQiLF1qrYwtkbNwHs21jogAZbe+gYs lw5kpZ+pXhGEQvgRMwNPI0MIoLgkPpPgWi5EvMl1Ova86X2XbE3s8JcWpxaLZQBymM6TOsUYdBE yXGjg== X-Google-Smtp-Source: AGHT+IEzYmiL2FE4oKEpDHtVWmuiqaSNHgfYo1XLBzs9mI8kvpHVFkCO0EyUrpLQX7Mbf/yGGVrT2Q== X-Received: by 2002:a05:600c:840f:b0:477:952d:fc00 with SMTP id 5b1f17b1804b1-477c0176752mr478108635e9.12.1764683175693; Tue, 02 Dec 2025 05:46:15 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-47926f0ec69sm19383375e9.1.2025.12.02.05.46.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:46:15 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v6 16/24] libcamera: software_isp: debayer_egl: Make gpuisp default softisp mode Date: Tue, 2 Dec 2025 13:45:36 +0000 Message-ID: <20251202134544.662446-17-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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 125a5dd81..fd68dd0c5 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 Tue Dec 2 13:45: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: 25326 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 56419C32F6 for ; Tue, 2 Dec 2025 13:46:26 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2ADAA60F3A; Tue, 2 Dec 2025 14:46:25 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="i6K9mtxT"; 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 B443160E3E for ; Tue, 2 Dec 2025 14:46:17 +0100 (CET) Received: by mail-wm1-x32c.google.com with SMTP id 5b1f17b1804b1-477b198f4bcso40709035e9.3 for ; Tue, 02 Dec 2025 05:46:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683177; x=1765287977; 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=Cd4Lu/rRh8VWoA0Rmsx0kqTDJoCB3bfU/VXyPDYvPPU=; b=i6K9mtxTyiewTnoSFnfb2tF2i3y8H2nRhIFf67Wtw4eiAUvfg7pXOiHgmoY9JSghBC XM0onFF6jG3ThltSwZP2Rb8jYpN8CmmovshfJ/2ojezOHtii4voA8T8MCxEiv8OJthEW CzVpDHRSHwTIp4eeNsRIO/lTg2pCiEYuBfOE33Uu2sQIzzunC6y9bWsvZVZ7pM6Hxax8 JvdQtg41GF8V9Do67FP8tckNFcGmhCRlJd7lHWfHA+7BJa9Eap/VgSk1ENk/68MI/45h QK6EMxh+SWQuKPhBnTD2iMaUpokWkZ4Emk4x1CUt/E5766kDjR8E9d0cihUiJXTT5H0m V/Pg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683177; x=1765287977; 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=Cd4Lu/rRh8VWoA0Rmsx0kqTDJoCB3bfU/VXyPDYvPPU=; b=tFhRLwXiQM5gsgr89vDAxaTb79umS3WugdBU1QxlLsYfmL2lemGzyM6olEJCMHBzc7 /DlmEPKYT8feDNUwx8GndesLl0PSrnUBVY6Nh7hSmXEZ4ewGFWqPxSpPaUWCVwKip2xT XKXCyK310VEKnctBp2Q+BKIu3OWG2meCN4tvcgG3+AlE9BGQ/+GAE7RqxIUb83uGq+xJ r67uzsar4UnBikHnHKRdCo6qfN28F99vqC/w/pkn23c4t9Zm2qQMcnuL9fZRW5EHo/1J Jxw6J9zVUs/GiEvExtfX4ySwfQCpN/x6CIBXuU7OWuMXQoNHrf6WUNOm/urLpwcwD23D qLyQ== X-Gm-Message-State: AOJu0YxzOfcNj04+80lo1HPopn84Sr9wye8wnk5q4tvA28j7mtW4tkZI xPRv859nr9VhWPkwo6d8n5LI+TTkrWnlJM9sBKUmUI+DcQE7sfFuiJJNd3izoYGtGvAiD5Tz3kG KWbtF X-Gm-Gg: ASbGncu/C1+vmIKjW+6EvFYZt61BjgdoIpL7LaG6fq2zk7qHe17Gtd0hW6SE32+sC1k Q9Av8BmbGWeS4149b4eaSo8XNpJQm9S8jy6o2NhMvYAXnZdt1YhxS9Vr5PDVuk5NLZztwozRxZf MhLQ7JfjfqFw8v/prE0F9JE9eHwgYpbJN/yLNSa/pLh0mlSK6xipIC0g+60mVvVNMrgFWfckpJq JyzPFMHvFjopnmtkm9ixr5JyEPVDsPdWVhgy4BNP6aBz/IFpKVeDQ8O/1W3AsO6k3RxDVpxqgu6 cm1Nu4IoIb0TFYBKSH/KaUTFN3Iiw5M0jTFJzaY+Y3jOF2lQlO5m/PtJkyy+AFd7N/dMWSPazfV NQvwenq2+fGkZExGqWcTnOgIjwXBkNPBp5yXy8OKhVmndluwSI5sAPxJir1DLAnHov6abnztwp4 biuwSjNBtslZV8JiBEmm/AdTBmyda1dMmpW8FtljWpryRNqgcydmWqPyfuZNYSBJZa4qM= X-Google-Smtp-Source: AGHT+IFbTH/idGfHRNb1xaMvM0Pjd32yq6G5UtU19LwiV0W/63ilRELll6aD4JFxt0V01+BVBF+86Q== X-Received: by 2002:a05:600c:4e8e:b0:477:9f34:17b8 with SMTP id 5b1f17b1804b1-477c0165bf3mr408139665e9.1.1764683177017; Tue, 02 Dec 2025 05:46:17 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-47926f0ec69sm19383375e9.1.2025.12.02.05.46.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:46:16 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v6 17/24] ipa: Add a new Algorithm::init() to support self-initalising algorithms Date: Tue, 2 Dec 2025 13:45:37 +0000 Message-ID: <20251202134544.662446-18-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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 Tue Dec 2 13:45: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: 25327 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 3C512C32F7 for ; Tue, 2 Dec 2025 13:46:28 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7B18B60E3E; Tue, 2 Dec 2025 14:46:27 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="fWgfHMJq"; 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 0B32060D36 for ; Tue, 2 Dec 2025 14:46:19 +0100 (CET) Received: by mail-wm1-x332.google.com with SMTP id 5b1f17b1804b1-477632d9326so34862025e9.1 for ; Tue, 02 Dec 2025 05:46:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683178; x=1765287978; 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=3Y8+tq/SF7PURWDF6ElcSls3YEXtlcYRYqDXKFddwTk=; b=fWgfHMJqLd/cjGh1oMV6lHMf30XX6sf3/8pGdve8Fcm89GNoKT5kxvNNcq0rIFGE7L 1sZRZIcQq4THsIRmi7AqKH8O+YXvHoLS2WY+3XetjL4b6VdMQUjML8M+9yfH6Bj+TjHQ 2peL7QuZg4rwJeJay73JSA7fCEbyruh/PbDn8/Gw50hnOlnEyCsII4+QMTdgR2yCx+Dp 7lkEUwV2wX9DfFvpeBdSFZbKfz7neUOfNuqmz6MrtX4ZxcgMstkGN+rKW6Wg9qSk+XEj ugF/FasCo85A8yaHjpi8FRG9pXI1pSMyTnSuCJvE9rMfhgtdu5s2YCoJeqHCgPQxwgLS 8jRg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683178; x=1765287978; 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=3Y8+tq/SF7PURWDF6ElcSls3YEXtlcYRYqDXKFddwTk=; b=B+Cx93vefMvP5mwIwctxdhqHtz4jyTQ8rUa7KS+ZNNaVbM7/aaIXY8bayC03odw01K 3kjdwasu61fOVF5L8SncXzhQF/8FvKoXfIHHbVYZozRqM5n7HPUjsL4GELLB59TD2pYq H/OVapn2H5iJz8AAPbM6wH0Twsa+0D0nxLuV5BzNg70LQnZttq8Kd2t6D7epb6zpILfw FAIpVJKa91l/ZPQUwYsPihxIIhWoddklyZQi8Cu+RxuZnfoiJfCooUx+WHAcFOLc53+i QROtyU4VmGp2VmRWrDutDsmnacPqKoS6ENpVaJLcG2ZxaWhtB/I1+ak5K0EVz86VDaMh IFbA== X-Gm-Message-State: AOJu0YxdVjN5f2pmBjJw7LiFAScurnrSRxUggBg3HBDWznFP722r6+4t JZk1vtJ7gYsY4tAZRZAxnLqE+8KFwnlS7xNSrT7ufOX0HCRAAZ+qu3dLr+d7l4GNhuwFSs4rjJ4 ewOwG X-Gm-Gg: ASbGnculAhhz03G+yYXP0paNNH59OLHe+S32SCdd4koZrFK2roNZyyYJHqXIMFjMMkJ 6ECWW/zZOGqadbFJiNzJe89M7eUaslWTH7ytD/d0xOXd84sYWBLh8bVrkXc+llETZtx6KeWbEij kNmmgHQRFU8vy8t3P7XvPp9Lb0sPjq/iIeMkvA9Q3gRQZXqMEjQNTNt/57UfCD0mspapnNN+461 Tf1+to+xuhcis+mwiIfrPBzfmJlu931+54iVFfBJ7Ypm/SP6IJiPAGKi/me3cnrwLB2gAqAKcbV /LWWKx9LIBz2ZD8Q61MqtUUfFSr2TNt1pm5h3srS09URHl0XomQCvn5a3UbH/K+SOTiFRZIZCeI AC7k55meCMOHoK2WJ6wncqUxmTu9zOqBXNQczViXh2XledPDtuKxji9HlCaAxThWxXYzGKh7k/5 QX6Q/XxegeM3cHHXSWQuLtePctCWJp1dSbyzBRFZdXnaQvmmn/YD65gaqgHvs2V9T426A= X-Google-Smtp-Source: AGHT+IFPbxEDnFr2zioZjIKcX05HlT24ToS7YjukqMaei4yZI1YRnl/8lQsxT1thfB30kbRRVxwzQg== X-Received: by 2002:a05:600c:45c9:b0:477:af07:dd1c with SMTP id 5b1f17b1804b1-477c0212123mr431591465e9.35.1764683178322; Tue, 02 Dec 2025 05:46: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-47926f0ec69sm19383375e9.1.2025.12.02.05.46.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:46:17 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v6 18/24] libcamera: software_isp: Implement a static init() routine Date: Tue, 2 Dec 2025 13:45:38 +0000 Message-ID: <20251202134544.662446-19-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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 Tue Dec 2 13:45: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: 25328 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 F008AC32F8 for ; Tue, 2 Dec 2025 13:46:28 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2E78360F5C; Tue, 2 Dec 2025 14:46:28 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="OOZcDnrA"; 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 6C22C60F2B for ; Tue, 2 Dec 2025 14:46:20 +0100 (CET) Received: by mail-wm1-x32b.google.com with SMTP id 5b1f17b1804b1-47795f6f5c0so32984605e9.1 for ; Tue, 02 Dec 2025 05:46:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683180; x=1765287980; 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=nivFNcCIHsaOZPEeps0+pnpIxnf4gkOkum1uGeCG8kg=; b=OOZcDnrAIaJEATiiN1Q4DnRaCWBnPp0ALon9oYtB2Ii7bLNM6E2nlapcdlRUO0OO06 W5ytibjC7PR3fIFY0PzBmjZVMGbQ+7bSvIAMB31HSh4bnzBqjz2czMEk0VHU8wL4EiEn 8goZMHYkoTcY+iOEy5dm7kdvfCVG6MPbV7mCoNzbGtJ8zr/rJWsSSQBHAa32L4fmuH1y Eiya4EWGjE2UMrvg2NZtcvcI8pdfnt0c310cHWu/z/nVzpCRGfSGuSbqCJFyLpxdBugO gcfxD28asmsa/6ksz7iUWNjRksJ7GGlLaKqmBzchCjlVZ+bG6+ZqunHAs1oj/XVoIu6m iFVw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683180; x=1765287980; 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=nivFNcCIHsaOZPEeps0+pnpIxnf4gkOkum1uGeCG8kg=; b=g2sg02jJ5OozvKZpHzefTueiFWRtXo6wqG61SWUYGB/79d0/y/ZYmLLFsCygnf/qRC 2NzkquEJchYxjLWxBykjnBGPl8Zak8ye8KGBwRD3V75P1Tm5bEvoi1VN01r51yrUIPA7 qRPVB7OqffLFzNosMt8fxKLspgRKkDstLxS3dL2N6tAfHc0SyH7ycgYv451gbD0PzTWz uNLBnZ6aNsu5A6BcVopGi3w405GNN3/amIFeW8pJaz3SG+6Rtksy8shwUPLwSWgbD5Xn noPtyL34bIwfXEd56Ssm2w3rLUKFm7vlDET5fwKIOl2iROo6BxNAKLrMlHi9igRqVCvd eNBA== X-Gm-Message-State: AOJu0YxgLIle6Zlvdsf3Hn8xY28qjj6Ste12Rmj4LoWHOQBwUL9jtIZr F/VJj8Tok+Pcu6Wg7iSwufLkxsaKFKI+3wK/iMTjVX2i2vDwV1s/L2NPZtlQDcnP6NyrLSlgv6u 7WmUn X-Gm-Gg: ASbGncsO1nVYFFQHsB0NjoG4WoKy6VUhmifBSJTAlEWcDxVuj0aiaxmeHp6TY6a+MY6 QkrI8n7d6glan7VDtMbN3aMpsGdrnscIEMNHLdLlbFtig2JxiqTtGq9JQtCdBiCjSrJd7QtFub/ vcR9RzqXVbH9MtRq46OQBA+Ni07dQyh/JqDhPqKErzkdEFr71/0KeqL5qoLizlhQYdPnye0Sfbb TRvZtEXiZXgImR+LDd1QfM95S8cWxtA5taMm9EXnLuGnyJvW9pXuMDdvn+wIlmGLW4TYkyJIkoC +azN+6u2IeImbVKYVyXhZkhoK/11hf1r4fAWlv6YL1QWC5S6l8JWgEDbevhMcGnYCc3kUBVlo6d G8wY8GbfyR3u83ucbpwJYeEkjzr0TcE/Lbg4MDxEePAzcsVyxOjf9GWVA2zcZQ/AEEtamuSiZrH +dun6M5OQfZVH0GTBzXElJTOgDwu9R27HdGykm2aLpMAm6IdHYMFi6WHSIWF7ggiVeXMIiwtNaH CnKEA== X-Google-Smtp-Source: AGHT+IHt/9vIppjRGfU4/n9GiNKPzEPhqhNpUtJkvFIscW/5xTxxJgXpdVjYnvxVDCHU1QtsaDmSGA== X-Received: by 2002:a05:600c:5253:b0:477:63dc:be00 with SMTP id 5b1f17b1804b1-477c01bf726mr362385535e9.25.1764683179693; Tue, 02 Dec 2025 05:46:19 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-47926f0ec69sm19383375e9.1.2025.12.02.05.46.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:46:19 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v6 19/24] ipa: simple: Add a flag to indicate gpuIspEnabled Date: Tue, 2 Dec 2025 13:45:39 +0000 Message-ID: <20251202134544.662446-20-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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 fd68dd0c5..a14fa22e5 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 Tue Dec 2 13:45:40 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: 25329 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 BC789C3257 for ; Tue, 2 Dec 2025 13:46:29 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 39A8660D35; Tue, 2 Dec 2025 14:46:29 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="yW2xyyeH"; 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 0A8C560F30 for ; Tue, 2 Dec 2025 14:46:22 +0100 (CET) Received: by mail-wm1-x333.google.com with SMTP id 5b1f17b1804b1-47775fb6cb4so40127675e9.0 for ; Tue, 02 Dec 2025 05:46:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683181; x=1765287981; 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=TQsZfDaoGFUl4eFxvv+cU20DJlcn/08chTcEqRf6U74=; b=yW2xyyeHgjo6U/99gkWfm1I/pAfyd0ENZ71QcwNiRm2CooApXyCwZdDfFC4qye5cYP 873gKLFiBZnZcfDd1bndSe804h1NZ/pHD9lVmEWMf9rWht7Buxq6D4pPmkrC9qmZvo9B AO7T5cK6xNDWrCCLz8rZjJ2piaR0CSKSVLNaldD9z4KFWEmzyNNYxlcuzQteUn8lPbB8 L1quhpc3Tu35dS/+F0VtKezemSlRN1ss0ftR0Eskw/Bj5XfSfXn/ZkAUGhj3vNYIGKES XaP23UntQf8DGFc+zveYnDEF0rACjyVyqgmKnziex7VuZm2v0f1AzfSwAlt4KTEPJcC/ 1ntw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683181; x=1765287981; 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=TQsZfDaoGFUl4eFxvv+cU20DJlcn/08chTcEqRf6U74=; b=tyz2kk/90eY31qU15BFzE/4JWDfLc8+XeyKfa0fQ/K0TW4dCWWgtUuAFNoqUjDeyo7 85GAdrwnPuSEEY7RrdWXNuajfMrHGMC8PIJdgaQ3GhrjPMS6+vsAl/fbkT/rSFD4Ldvj fIGPdQcMVPURPgytst2mXU8I9w5r3d62CGHr4BCg5pOhNoZFrvZIXSv4ZsRmkh+z+gR1 uTZ8GHjTgyqA3cHdkm/m/nWsQ3okjSz3tyWIpfBZQCkUd1Ev+/MnX+/PuQu/cGaI5/oL fBYBJ5WOHvyQdo/R1mgiP045tRZqO/Wx8ZL0lsGGurjAghM8WW/x3bhlkE1RA7s21gML THcQ== X-Gm-Message-State: AOJu0Yw39+OuF5A4IX5Js2GVob70axt+P0n030epjhwsNSk5wQ2oRMMa RkuqQ7fsj5H1+V9gdYXsG56FbrfvuCLs6YF2XAVd0CYYHT6SUObYONrGxxveMYTfWDZpyBi1y3h I8mCr X-Gm-Gg: ASbGncuBJOHMiSUTGv6Fzm2aGFJgQX5AqS7YHFzCgkRlffMr3QrTvxNGrUFGvujVKOM 23kR5RDLrEtgmCCCCV6VyDbg+hwrEeQYmkaDQD/fnjwxM40H9ZrHZOsSoNVin2x89uOEfi0w2ik raM2HxeJcY9Oy5Ri09MKU+mmvXteN7UYdFaUncCO4s16QKI/2VRCD1m+KqkZGDghzmGgbHoaBEK KmEn0gGKugDw5cvNXb18XydBe7Fuhf1DecJc8pxaqtEcwaXsqC98srg3WMznjSsI4FUrP9u0rkM xhpq4kj0E27R8QEeXmtFWtI++OjL0B+96syriGTvWQ5dqeTUXwVNxZJQz7jiQ/p/G2vX365o8HN NK+DcFeOhp9UWJWjzS/iMSE8IPRVspBOg7FtTmqHreX8uw++Twb4s+X5SXXgaSeWu4x4YpNS1wx H3J7PKhJyNLEF2U2hceiMvjWe0zUwzmGPrJPxZa8NDMclCPxTXnDNc2y4u+3iVDY+klDI= X-Google-Smtp-Source: AGHT+IH0EDLtxCyLLH1V0ghyKKxzG1pxyNUqLIoOrmKfbr0ADTcj5enXfmu2oeKwZ8dShPKXZyhpLg== X-Received: by 2002:a05:600c:4591:b0:477:7925:f7f3 with SMTP id 5b1f17b1804b1-477c10e1cacmr414142025e9.14.1764683181314; Tue, 02 Dec 2025 05:46: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-47926f0ec69sm19383375e9.1.2025.12.02.05.46.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:46:20 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v6 20/24] ipa: libipa: module: Add createSelfEnumeratingAlgorithm Date: Tue, 2 Dec 2025 13:45:40 +0000 Message-ID: <20251202134544.662446-21-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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 Tue Dec 2 13:45:41 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: 25330 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 AD677C32F9 for ; Tue, 2 Dec 2025 13:46:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1508160F4C; Tue, 2 Dec 2025 14:46:30 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="zKbi9ftg"; 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 BF4F560F4A for ; Tue, 2 Dec 2025 14:46:23 +0100 (CET) Received: by mail-wm1-x335.google.com with SMTP id 5b1f17b1804b1-477bf34f5f5so36310245e9.0 for ; Tue, 02 Dec 2025 05:46:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683183; x=1765287983; 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=2pApn0Ftt225wj2OFxj2PTyD+pMbuHYXyYVVwJZOq28=; b=zKbi9ftgeS/1jICA++DQn41GDdcwfUk4UEwAW2+DV2RIYsLitCdwdv90MHonsCq5mX g6W0Cxb5yRAi3l/ACCJ7Bi8hgDfB7M9YkzOd07V9ft2Ln4UDUVM2LgRyQ/SriFEd6THd jvq9EhLmkiinnG5qILTYqpVxOlBjeX6aQix0UzNzjEa4XregNu4gOKielLpS6YxyHQ4Z 5QQbjwDbsFC4KsdWDB1hDky17QbF2FuPoZOkIhsqatJKuIhqKng9JtMMEC0yIoGUMqD8 P4QPtWvAp5iS/rHUatvpf+hQvUQ0Mhif1oJka9BQew5tapMlbb9WuGtJSTIaN69PLqUy 7m4g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683183; x=1765287983; 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=2pApn0Ftt225wj2OFxj2PTyD+pMbuHYXyYVVwJZOq28=; b=SJ2VCn4WlVMoGIaAdQ4o4Uq7cxFORpHHh9UDJine4xQcqVV4jb2ZL1uc2T6Ods9Iwl dg9TyQFUa52+Hf4xR+r1Zd70Nu2iTy4KvthxS0ilJwzUmYCxVdHtN+rOMWFZEXWxC1rY rsl4VxeZNJt0ppLOlddN7i1LCJgqvJYIik1yr//vKUrFhehk8HTiPRhFKKSNd+0xHrIY RChsIA+VbRZaHlCC4QLc4yABNSOB11xeQpGGkvH39fFVlqj09Ub7XGFCz3S9simTtIMi cAO5GZP9FKOjqgLDuKy5WF0iL8FPIWS1oVIVoW2gpk2UruisYauPTWYB+WYn4rTloHOp l2qQ== X-Gm-Message-State: AOJu0YwIfDtgSKYhaQRRsiPNo2MyB8Z/xvaWm2vsLveWiEcZahS7Q+lP UrQ2h8u/8EQWJgox3eMtygPbRHaV+qceGk3UU6pF8DT3g0SUKp3usR4HY2Ew3iCEoPgLbx8OH6m HLGfP X-Gm-Gg: ASbGncvt8KyP5Yq/M7GLKvYfXhzkIzSPCpjiNBdJb+jdLlcaR/noYIvpb+1GJsSGVve j/x+R9NjJs+OSpTKivGnCJIcULJ2a/UxxSvdtynXv0Wh7QbwWw6LHEf1jBoG0Z0+Sh7ElBjlhmX /ouz7UsB6G+mh2A0LBzcC8W3le14JO/hc84gilt4wtxDUbXHOKwPjfrCEhIP3O+UXgc77IGHRQp W23UrmidCqStwuCFkw4udcImpBqf8+q7uj1YRuTgrCkzrAXVb2PfryxJdTDACmHlMEvUUYR9kqH 3dM1UQhGWqg3Z9IArLQgsOWaPnAi7aBWnL/QUGFDF/k+ItBowOaSHLV4ycBJhhUPFk+FMxHk14A WiioMPjsxJm0lFFNrQDq0+/5tFd+noyu5cOzuLYoQ9DjGzUkAXtbsaRPnZUEaH3vWUwnjVmtAAk vWaPmo6OY85JxrHhf/CWG8p+q/ZW1ByNQCqM6gJ/1PSYm9APvhToyi2FSBpnu8qRj5BCM= X-Google-Smtp-Source: AGHT+IFf6xQq/tyvhXWJOEo+JfLCumsebumw+TzJABkXHArLxJru2YWSdJ0D54o7vXcWQpf/EPQ6Cg== X-Received: by 2002:a05:600c:4591:b0:475:e067:f23d with SMTP id 5b1f17b1804b1-47904b1fac9mr286816615e9.25.1764683183106; Tue, 02 Dec 2025 05:46:23 -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-47926f0ec69sm19383375e9.1.2025.12.02.05.46.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:46:21 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v6 21/24] ipa: software_isp: Call createSelfEnumeratingAlgorithm() to statically instantiate CCM algo Date: Tue, 2 Dec 2025 13:45:41 +0000 Message-ID: <20251202134544.662446-22-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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 Tue Dec 2 13:45:42 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: 25331 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 902F0C32FB for ; Tue, 2 Dec 2025 13:46:32 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 107A560F78; Tue, 2 Dec 2025 14:46:32 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="sJWCZyuF"; 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 23F0360F39 for ; Tue, 2 Dec 2025 14:46:25 +0100 (CET) Received: by mail-wm1-x32e.google.com with SMTP id 5b1f17b1804b1-477b91680f8so49634725e9.0 for ; Tue, 02 Dec 2025 05:46:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683184; x=1765287984; 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=dTywnjywTYFDNqkP0cnk9UpWXHvyZGmzqAChiiWsJt8=; b=sJWCZyuFavvW0Kj84F0MHIKhQ+bh+8S+BQEeLCLDgLCy7kT2z2r7H9GPki7VGTfxNe qsOxJy8IpxTn1GlNBLR7EEVfqFbBzZL1dP3nme3VeNA6zEneDM5li8h5xSMhUNGyZ4sA 45OTBv2MT3wqmobnvNv6Ps83G0C+sQ4T4PW4ZZ+//WuR0ukQSpoLt9H8tWivu91J6DHT gZrOD+VwkolZmHM003m58v5rpO3ZOyh31+Gtn4xJ98WEvBx+h0ekWQB36h3bHgnkZ7gX e7BJ/sErc+WHGXVZUdgcrTRShY/cMhizzPcWUSVOvDXvC/V+uswsE3amm/yYsA7kzsah uhyA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683184; x=1765287984; 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=dTywnjywTYFDNqkP0cnk9UpWXHvyZGmzqAChiiWsJt8=; b=lRf4J3F9u8pRGL7OmeJw65EXBIQo4jZSSWLt0GDbPgLuKZeAFsWVen3qMWa6tqrYEL JOdrPddaUP5zZ04uXcgxRZ60aq775UyCt62Drgv2jCUE/Q5MPcKqTUKJBgrxyVPzstk6 +R0J/5QzoEvlOOQNjnr4HWxt8pi+SxgiIAnUzX5St+3C9Xpcsvwi3S1wy6WFOD3xudzA NDQXoYDI2EYOBBuedRMPVKPJtmK31K9O1Sv/ildhaVASR2YM6ZTJEtxm45AQ1agKiJvu ndjUZsyCTnzsWZ2dlzMVA6QhRtHhXFBJaEZZXZqr/frov0fAngwBBPXffH6k9lNaekqK M1tg== X-Gm-Message-State: AOJu0Yzpy9ZrlMkmfL/+rkSCK+mI+OZY3sHEXhdL45oqEz4OmUvnqXmJ 2kHCpyB9CydnlmzKGHu603ImTKoxdgoSZKVSWt21zEe0YmRP8vYEwPUuK3eTKKH0bI7D3qffcKm 9EnjJ X-Gm-Gg: ASbGncsIHuk8XGbcsuF/KZTV9xizlBbEz1fFcIhacZhx+MNH3mXc7GPiXw02UknFila 3u5uSvQpKQgPgvwIvtv8r8Nqj4CkWWtzJ27j7joblF7sorFvVrhTJeDtphEEG/xBD90gTJwPBaz 0agGgVEX6CU6tAOQJcP67qQl6RTalQNz9y3v8cGTYhaZnzemuWwIY4meNkL25PiW3FGjx6nC4P+ gFgYfAv1E01zl8cZAmbB/hTHx8i7xsM7ajKNGR5+m06pcqFJCS5p+KYy864dPgjQ80O90UT3ct7 +1AeJIUlZmnZtahbDvNkLoau8ehWsNln5umgkw/ccYaMbbVj/E2M7CpLETg0ixOBu9+wdGbSeQe HaOQFy0xIAbLGyMd67MBTFCErBJG5fDfG7bJjxF+fi5b2x/ilblMoL9+dLsRrOkuYBSjovz2ELq 2kQalSn8xi8XAZCfr3uBCoNgH9nop9TBERFvPrlP7UD6oK8boTvugj7tI8nGhvLfPUxkfU/90AL IRvcA== X-Google-Smtp-Source: AGHT+IFIBgfDaKUq8XjdGVLzL9SE3d8U512DKUNvxIYCVaM2buY37PYIgMcH0VakUrgLKPAt8jYzAw== X-Received: by 2002:a05:600c:474a:b0:477:b0b9:3137 with SMTP id 5b1f17b1804b1-477c10c8886mr407852965e9.1.1764683184382; Tue, 02 Dec 2025 05:46: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-47926f0ec69sm19383375e9.1.2025.12.02.05.46.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:46:23 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v6 22/24] libcamera: software_isp: lut: Change default Gamma to 1.0/2.2 Date: Tue, 2 Dec 2025 13:45:42 +0000 Message-ID: <20251202134544.662446-23-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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 Tue Dec 2 13:45:43 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: 25332 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 C4EEAC3330 for ; Tue, 2 Dec 2025 13:46:33 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2183860D36; Tue, 2 Dec 2025 14:46:33 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="HmMP+mUF"; 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 35E7160F78 for ; Tue, 2 Dec 2025 14:46:27 +0100 (CET) Received: by mail-wm1-x333.google.com with SMTP id 5b1f17b1804b1-47778b23f64so32157985e9.0 for ; Tue, 02 Dec 2025 05:46:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683186; x=1765287986; 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=St8BDxwP4t/WaFpYmjnDvCofVLPqsqEHtlV+2cA2P1g=; b=HmMP+mUFEbYdy8cqPxMhNgAaxbz4F7hc7TEZqxY2HO7WL/4m2U4zeLKYayAzgtrIfn J6RYFpde6jIA7GaW6FyNH3EYL9xGVlUcfW4UiIG3vpYZWw8BR4pE/qb/1OXT/FCPoouJ 6Zn3CkRFyl/y7uwtRJmGxyA7r2BesQu4UXjfEg0Oc+JSeBqb1jlIipPQnU+omIUh61LS kl7G9C3OnbWTfEDVGOkhLPUJ3YzX6TmVeaXWmrzh6CYfRdauaIr0jAxvSdN79mPPLLhJ ocjIlhqt3B6xiJ/sbHFeWTdPpDUNTF1TJtuXmLY3dBLjxLTXAKX2ZmwzzF677BjS82fc Ew3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683186; x=1765287986; 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=St8BDxwP4t/WaFpYmjnDvCofVLPqsqEHtlV+2cA2P1g=; b=kr66hEvqPPPgC8PcAJ7pJKSye6UoOwFw0mUsH1k/sQCGWCO+87OyKPSN0mjSwrx+Ij oBymBIePGTt0unFb1Ho2vxCpsqmdOnh5gP4EBZbOPvFDruXo4j9+/2D//GWIPcr8eBd2 c1yxWENPiiPmxKOj2xtezL96mmvHt42+Em4Fl+/bpdcEQh5nfaPcZffXpRAxQ+ONWe63 /gldGZJlk8obRIDjmA6UpHrpYzeQI3JEbV9yCZzKrccrQ/PtZZmz/riTArVcAwTQjGwf /edV+lPaFxJ5dCrcHEgNllumj9Tyw4Xb9md23pialn1iLvnIGJi8s7y5VI+QC0zqxb+R ir0Q== X-Gm-Message-State: AOJu0YzF08wC7H3uNjZTqJJS8RKUe2/bZU40mVH+fOaGvUTrdDqOK4n6 ATdWXuX1DjAXq8hFatN8jR2bqdg1RrcrG9nVrnC+N+wOlnmmwnircvz9eAnQNmVpJwkPgm2Or8g 6v9ln X-Gm-Gg: ASbGncsb5TZKTaKzxvfLN2JRUtRjCCcBYGyMig6Pn/9tMPWYRBWL+hkQyj7MU4AOGOF gvOdrtLj3yQKcgwaJTcMx+TJTBgnTfPCjUURwxRDWgFNTOMtEuIYlk/G5zBi8J12DYc47OoibWs JNK5AeZBor+KGKKdl/rQVnzKJE0UQzJrMnCZXdUDNHEKPMdqOKUSTSXJUg0cCvO/E2gqgmvmc1e tvzACiAgOhl/PIoJ2xJrT+SNYvuvN+HPBjYl3IjHxjyhF1VC6hpyn4l8Y68K/fhHT4aR/XOO+Fv fKXXUEhOYCF0gl80SMQ0GBCcDDyvgIRKq3Kiagm1cW4Z/vSmrGuKiWqGXd15lYzw2bKKtlgyPcp shxjxMhd9cJaFfqcGpr5PorOdCWcBI2dOsQRKoETt3uymv34bi6p9q9SzB6INHrVNHdHV075Iut FilcAFntH5Lh8dKuWQVkCjAvcFJstdSHnmkQk7apvTDvbqa3apFVqNJSBnT30uYfbwFoY= X-Google-Smtp-Source: AGHT+IEfihEi2WV4Rb6i2UrinCmuqFEvrmQhplNCftWhO+XsEoKKHsNDhfMBK633eLOTzkFq3BOFtw== X-Received: by 2002:a05:600c:c492:b0:477:8985:4039 with SMTP id 5b1f17b1804b1-477c1143024mr411348075e9.17.1764683185383; Tue, 02 Dec 2025 05:46: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-47926f0ec69sm19383375e9.1.2025.12.02.05.46.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:46:24 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v6 23/24] libcamera: software_isp: lut: Skip calculation lookup tables if gpuIspEnabled is true. Date: Tue, 2 Dec 2025 13:45:43 +0000 Message-ID: <20251202134544.662446-24-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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]; + } } } From patchwork Tue Dec 2 13:45:44 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: 25333 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 A0DF7C3333 for ; Tue, 2 Dec 2025 13:46:35 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E4FF861009; Tue, 2 Dec 2025 14:46:34 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="c8cgNY2a"; 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 9517760D36 for ; Tue, 2 Dec 2025 14:46:28 +0100 (CET) Received: by mail-wm1-x334.google.com with SMTP id 5b1f17b1804b1-477770019e4so46200895e9.3 for ; Tue, 02 Dec 2025 05:46:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1764683188; x=1765287988; 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=iKJW+qI1D70zuWFggqa2ta4Vy4rY99zX/Wr7gC8b7TM=; b=c8cgNY2aiE97JeKabvZquTpqaCc31i/DQ0tyUCEW9wIoIGiMmd3dBztYgoVdMAgUjb SmWsT2AUBdI2fa+8nwnTUxhBtRrr1Lsb8wGPOVVVrPKi3fTEsb896T2WWfWfdZRNm3C8 2dKb8GFsYPZV++d2YsFvO+f4IaFFmIyySxNf8gdciZ/yNzu5nI8w2FwCPTTSIKhhbjG6 x5bJqIMyKbqHJXmG/nQsF92zhpnP0pOTaostXXJq66n+Ze3CAUSWsiEuaptoLF3Xntq8 8vDDGTO+NThciLxBq0lmIJjUPmyjuO6C5vqPodB5gj0805u1xbPfOghz/r5WTBHnAsVs qwoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764683188; x=1765287988; 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=iKJW+qI1D70zuWFggqa2ta4Vy4rY99zX/Wr7gC8b7TM=; b=HKiACh76tc9PcdE1CQXqoojj4qD56Vodp4sCaSncd+ErpFtJlXezMcF7j3pXNBhZZM l0En7opFxc10PuJu4LUdJ+fZ7r8hhdk9ea9ONmr7uu5hr8VaBpMTQ360EUnE6HbX8ZAF XcICJOtsV+cstNbbG2JNWlOU5wYZhwz37QjmRy0VOE7g75V3LXcVff23yvREZV0nmsPT s1aNYyajZGNsaLeD1praT1+PMzxTxfD3AM9hMFk2KT8/bEn6qjKSajU6ac72LZix5jVA DHueK29Dc2iz2gnFpbtyLkIAF2Vt2Ov3cO3vvKmmR/2PbG0vJtOkH0O4cxuiDmGgXNgz DBYw== X-Gm-Message-State: AOJu0Yz4uSahjbd7EzeRerBD/2IFpsIjafRm5u5lzgMIPeqlwZ3mp+lV oIj1T8ZRAAumkmcyCrfG+B/Pnw+y6z5DRTsYt3R5fCf5omNKKgj8su238QTrPitUpe7632ZFyrz zc99L X-Gm-Gg: ASbGncv2VQwl+ztqHesG8tFhPRtbFn96ZwEcS0HBJ5RzeSoRRwuYv+FmgnVO320BY1R CizEwQELEFkyeIaRGFl++RE5dvMOZ7XLw5aFFkpxqKrkH4gD77rwL1lPRmXWYf2eKmRaSPF67H1 jwycBRT0/e8xk4xWHaXSEKz19GFMq1POdwv9zHCM5464ZILThun0ya+TrdHtY0B2al+xgTyayn1 q5mNbkcigaptcg5WNSP2m+dGOSZfclWkaIWG+VsfXps15fJZF/wi67WivqmXWXxnODnMyc5+J1N GUUSg0s9e4ZEle5DqNc4bwjbTW/ZJOQB8NvS+pLJNMcQouEtRYW2gmAv9g60V6Hi9v7LLvoykof hL4eCEHdciFX5xWJZ1BhyK22UDRrhprzj/zffDa0G5YpTln3NUEMCtBwLAQFHDRD35x5/tFrHJT o/I6OxrjwLJpz72IWNArvBQ3eiNRr3TSpbFIPs6bEx7Ji0FV6fO+NuKRPI4OzYdwiHHtc= X-Google-Smtp-Source: AGHT+IHz2/XT49PRMxU/vKG2gW16uJDgt0WfXXwcJ1HuEP2BZT7w6AX55MOMdUfuv9MEAgfqIdTGzQ== X-Received: by 2002:a05:600c:c48e:b0:477:58:7cf4 with SMTP id 5b1f17b1804b1-47904acef07mr289061985e9.4.1764683187777; Tue, 02 Dec 2025 05:46: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-47926f0ec69sm19383375e9.1.2025.12.02.05.46.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Dec 2025 05:46:26 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Kieran Bingham Subject: [PATCH v6 24/24] libcamera: software_isp: Add a gpuisp todo list Date: Tue, 2 Dec 2025 13:45:44 +0000 Message-ID: <20251202134544.662446-25-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251202134544.662446-1-bryan.odonoghue@linaro.org> References: <20251202134544.662446-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