From patchwork Fri Dec 12 00:29:12 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: 25516 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 14497BD1F1 for ; Fri, 12 Dec 2025 00:33:28 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id BB3B161623; Fri, 12 Dec 2025 01:33:27 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="oHdE+QPo"; dkim-atps=neutral Received: from mail-pf1-x432.google.com (mail-pf1-x432.google.com [IPv6:2607:f8b0:4864:20::432]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3ED7E61613 for ; Fri, 12 Dec 2025 01:33:25 +0100 (CET) Received: by mail-pf1-x432.google.com with SMTP id d2e1a72fcca58-7b7828bf7bcso718235b3a.2 for ; Thu, 11 Dec 2025 16:33:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499604; x=1766104404; 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=Q4G+/DobTRCRFFgGje+jTAlgyU0g2iZaIgwaHTHs6zc=; b=oHdE+QPohMRukKQ9QVleMVLI/fvNGYttp3dOAUpiS0iljeWf5u/QfxRP2rRPWhxHnv Onpjdi7yC/CKSTg3E2j3uRJcfxG3tG2yUqmCo6sghBomtIcg8lfkmbqyjk2nIQAanFR5 CkMCZ6HUOzb4NxoLNfqzA9IMcTXAM4kLAzG8rKAjh4On+ju+s9fDecohFz9Pk8TdvIeT C4VqxbLlEGAVd1MRB69gJkJwHpYDSx21HL+Z27wW2CCzTNFcWF5cVLC0gJv9HMru1l/c 0Af25IHFhbxWz3jPFZhray+KNg+kHC5e2ArLD6Y0i6Vp0I3Cuv+TV7WQP5iaI7163Inh sHfg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499604; x=1766104404; 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=Q4G+/DobTRCRFFgGje+jTAlgyU0g2iZaIgwaHTHs6zc=; b=nu7Vdy28S1EEmPrkEnq+9MA5ckSa4tU0lbdzv/jVH0onNSFNksa/sqGH3gnHtXEIEp BGpr9XRF2prx/nvD3Hev/J0pWzknIMDcZJFVkxH6QGColZlGFU5hEYUicM12OMZ+wiCR rOYFPA6XorAM4cYlw9xQKQmhXiiom2WU6F6axN/Kit5j1hDGKbO1Y6U2Uxu9vamFluCv PZBukaAXoJY2zL4wtJsnRtcBikNQZwY+ihMr2aZRlydit1Hi01zyyMRoCdp8mREljVbl 7tQh9ioMxdq0H/9pdi7Kz5UQCE16IyTgc5uBQh05FdehAp0LoKv8/C1D0Tg3WZAoGqDO XwZA== X-Gm-Message-State: AOJu0Yx0yoCO4tJSlON+bSJyX4MV/81oQXlYVaw5gzWatrA3iz/4JSat hdt1KmKnISLAWBDniSonMUChyJsJUiX17IzYZXohWb2sehHuFLqOs054RjvUj2tbz7uLOqjv1T5 6keg3 X-Gm-Gg: AY/fxX78tScipSSFux7YECT7p69wWWcwJ2CqBDyrJ/myVhrqZyCpTe4WSgH8fYxDJaP iZy6XAH/wdiKIdTjd/usT+4s7f+th6wm2ffzgZmf9SLWAQyAYvRiPCBFpYq8KjHJg9O9KYLBMI5 ZsSJ6pnXJs0YJ4rp4zn9bRTprVCDtHH3deD58+JBRi1oT8VtnhOGqpjRw4A21xup2To5ergdyV0 Kwrb6W/EU+75ZAhnamOFVqDCQHdEMkfn+C/SNuWXuWcIWdskpr9p2bg/puXw37lZ/81uO4mJ8JJ Sy9UIXHiUbtPXdAhRmo2/YMSMV7grNXbKyXtPH+JtxYJ+li2CpHmTMuUfEj5mARChuqHYh248xg +XtQXuWzj3hdo8nkV1hRcpT9ntywvTGUmJLCENN8rOgfoBy04nr0dscTNS/1WWrd4Uq1lXceSB/ d5vjaOwbAazpPGohevAq0hjfeS0vVrgH9YXy8Ybu6V8+RJ8hnEh1GZNfn8Bsua74qChR5GQA== X-Google-Smtp-Source: AGHT+IEJt/wRmmkrWUJlbUTkbwoxANdfIpff0nUJuUngpEjMtYZnf00gnXF0y+f+N9lnzorGtB80Mw== X-Received: by 2002:a05:6a20:914e:b0:35d:d477:a7d8 with SMTP id adf61e73a8af0-369ae4901dcmr337317637.36.1765499603507; Thu, 11 Dec 2025 16:33:23 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.33.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:33:22 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Kieran Bingham Subject: [PATCH v8 01/26] libcamera: software_isp: gbm: Add a GBM helper class for GPU surface access Date: Fri, 12 Dec 2025 00:29:12 +0000 Message-ID: <20251212002937.3118-2-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-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 | 10 ++ 4 files changed, 180 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..09811d1ef --- /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 + * + * 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 *gbmDevice_; + 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..a2e4c7076 --- /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 + * + * Helper class for managing GBM interactions + */ + +#include "libcamera/internal/gbm.h" + +#include +#include +#include +#include +#include + +#include +#include + +namespace libcamera { + +LOG_DEFINE_CATEGORY(GBM) + +/** + * \class GBM + * \brief Helper class for managing GBM interactions + * + * The GBM class provides a simplified interface for creating and managing + * GBM devices. It handles the initialization and teardown of GBM devices + * used for buffer allocation in graphics and camera pipelines. + * + * This class is responsible for opening a DRI render node, creating a GBM + * device, and providing access to the device and its associated pixel format. + */ + +/** + *\var GBM::fd_ + *\brief file descriptor to DRI device + */ + +/** + *\var GBM::gbmDevice_ + *\brief Pointer to GBM device structure derived from fd_ + */ + +/** + *\var GBM::format_ + *\brief Pixel format the GBM surface was created in + */ + +/** + *\brief GBM constructor. + * + * Creates a GBM instance with unitialised state. + */ +GBM::GBM() +{ + fd_ = 0; + gbmDevice_ = nullptr; +} + +/** + *\brief GBM destructor + * + * Cleans up the GBM device if it was successfully created, and closes + * the associated file descriptor. + */ +GBM::~GBM() +{ + if (gbmDevice_) + gbm_device_destroy(gbmDevice_); +} + +/** + * \brief Create and initialize a GBM device + * + * \todo Get dri device name from envOption setting + * + * Opens the DRI render node (/dev/dri/renderD128) and creates a GBM + * device using the libgbm library. Sets the default pixel format to + * ARGB8888. + * + * \return 0 on success, or a negative error code on failure + */ +int GBM::createDevice() +{ + const char *dri_node = "/dev/dri/renderD128"; + + fd_ = open(dri_node, O_RDWR | O_CLOEXEC); + if (fd_ < 0) { + LOG(GBM, Error) << "Open " << dri_node << " fail " << fd_; + return fd_; + } + + gbmDevice_ = gbm_create_device(fd_); + if (!gbmDevice_) { + LOG(GBM, Error) << "gbm_create_device fail"; + close(fd_); + return -errno; + } + + format_ = libcamera::formats::ARGB8888; + + return 0; +} + +/** + * \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 gbmDevice_; +} + +/** + * \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..685213c78 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -70,6 +70,15 @@ libcamera_deps = [] libatomic = cc.find_library('atomic', required : false) libthreads = dependency('threads') +libgbm = cc.find_library('gbm', required: false) +gbm_works = cc.check_header('gbm.h', required: false) + +if libgbm.found() and gbm_works + libcamera_internal_sources += files([ + 'gbm.cpp', + ]) +endif + subdir('base') subdir('converter') subdir('ipa') @@ -178,6 +187,7 @@ libcamera_deps += [ libcamera_base_private, libcrypto, libdl, + libgbm, liblttng, libudev, libyaml, From patchwork Fri Dec 12 00:29:13 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: 25517 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 984DABD1F1 for ; Fri, 12 Dec 2025 00:33:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 55BD161623; Fri, 12 Dec 2025 01:33:31 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="zBYLl7a4"; dkim-atps=neutral Received: from mail-pl1-x631.google.com (mail-pl1-x631.google.com [IPv6:2607:f8b0:4864:20::631]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D050761613 for ; Fri, 12 Dec 2025 01:33:29 +0100 (CET) Received: by mail-pl1-x631.google.com with SMTP id d9443c01a7336-29f0f875bc5so7641425ad.3 for ; Thu, 11 Dec 2025 16:33:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499608; x=1766104408; 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=g1ksjKvh42ffwWP1wYtLNAXmrFfPoVxptDMDo5IhR18=; b=zBYLl7a4ePlcHQuTqOb6V8dXTpQuKVFoxanrhiXZedUGHxCHXPgvNNI1MKUWdN8wMO XFWKnTM2ur0Y/B2bJDqigftVmAFebgpdfqHkfojOjyxru8lkJgt8i6tx4j1ZD9buMYch mo9s/CEETQtZNF4nxBFj1I7ypkERXC5dPV1RBYr9V3Ct07KWelnvp/nGSP8XpLnyWThy 9AwppLS6vs5yRvAEDL/Edh15YoB+Fuljac1a93jSdoQIqMFFmYqckknsgNnNTKirN7Ry jH6MgUfiOyjHfzn7gLcIpEmweBdmr5AuQmMm/DqRWr0i6g7k91Azp7ocnJ8fWS6/pouW rGtw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499608; x=1766104408; 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=g1ksjKvh42ffwWP1wYtLNAXmrFfPoVxptDMDo5IhR18=; b=tiCyqQ3AAonyVpoEIhZfMBhkWlHoi16V+9+zjX+SJT85tCCYgsIW+16/n8OAnO49WD 5+nYxFPH07JlN5gvgS3gLz1vKQxiwUfH56HSG36GyG6iRHmTdqK1SJgmLYXg2BaVCOM2 KxpIONUk9T9evRIBGCrjEGRO60ndY0N0sJ7pyFU6Q3Il74jE/VplMboHN4Xb9PhLBDBP +2jEX4rBdQtzZiQMZukfEwRxA4BzO9nLFj5cxMMbU6EHL25DkxxqVEifK7xPwFsRMfgO 7yBn6MY/CbUAegPc9Ri8NiNzAWFoDIL2F5HuPLKjftDNHOWNQED2ziZnH+CG/4v7Pt4v saKQ== X-Gm-Message-State: AOJu0YzLDK3/F2xCGCZpn7XLoEuevmoovJRI0LimuD3G3s37jpDaeNTJ VSehpM/El6UQx4ZM+OWRbnn35vP7xQgUxORUlmHcAf99Cn1xnETK2fvDpuMefIH8lENVPO/1iVL M0Cun X-Gm-Gg: AY/fxX5Ps+luxSftf6zo+EOu4BrH0DxzJnDfaSQaFHmvSsKmLyAq9sTm8z+XI6GprmU buYUHilS2Yuo0Gu6V64UzVPXe+8yrEEtoPY/1Ms3puQTaUu8Ul2RyfeK26giNoci35b4voXpz8k 0qXHGJLilM2VJkxn6Qz45r4QWYIk/IUvgUwwDLXlHJSr6WqnXbvSW2HDz0l018Qcw68aWbBWq4a icePpF/L9nh3rSr8mY2iSSsbLkVHSFc52c+WokBjo/LfLsvhGPbVifmjtDa8vBDByrSjmXFCH70 yKe4oyKW5FV30eX30IO9MWTvEde+CEVGlXB4P5whv6l6IVJx9JVn/esvKXggWWGOJgO0vACu9K2 uL06bJm6Iheh36gj0IOzrex9dg1axecw/S0t3zP5x5eno0pOqKdbRYsNLawxg5BLrLc/2Ntfjcd nKupR2Gh1ZMaul15FgvjOANKdiew8N9dllr8Eq8qeo2JRlPdHTVsESBeR4eTnWyq4W5h/Qwg== X-Google-Smtp-Source: AGHT+IGJQ26sWIo5rSJvLcM5O63gPZ8T+hcCp5nfDsttGL7wnPawaHIq+Ay927JVpldO7TBOK2vapg== X-Received: by 2002:a17:903:2f8b:b0:295:8a09:bcf2 with SMTP id d9443c01a7336-29f23dfeb5bmr3374345ad.8.1765499607595; Thu, 11 Dec 2025 16:33:27 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.33.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:33:27 -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 v8 02/26] libcamera: software_isp: egl: Add a eGL base helper class Date: Fri, 12 Dec 2025 00:29:13 +0000 Message-ID: <20251212002937.3118-3-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-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 685213c78..71ab39c25 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -79,6 +79,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') @@ -187,7 +208,9 @@ libcamera_deps += [ libcamera_base_private, libcrypto, libdl, + libegl, libgbm, + libglesv2, liblttng, libudev, libyaml, From patchwork Fri Dec 12 00:29:14 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: 25518 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 68F0EBD1F1 for ; Fri, 12 Dec 2025 00:33:34 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2EEAC61637; Fri, 12 Dec 2025 01:33:34 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="T6s16xEI"; dkim-atps=neutral Received: from mail-pj1-x1029.google.com (mail-pj1-x1029.google.com [IPv6:2607:f8b0:4864:20::1029]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id EA7F461613 for ; Fri, 12 Dec 2025 01:33:32 +0100 (CET) Received: by mail-pj1-x1029.google.com with SMTP id 98e67ed59e1d1-3438d4ae152so757924a91.1 for ; Thu, 11 Dec 2025 16:33:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499611; x=1766104411; 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=II6CNKAdf/lZ/qp3rhzbc8QP/zzmnb1ppQZ/htfgUOs=; b=T6s16xEI61eN7a9mHZq0uRApXIvZNRcHI+hjm1dgnUlyprrsbIdIxKevcdhfGhrEmo SRAAIJrR1R4RZZM8+/u27puzEtLu+eaZaiwTXr49L7J4em/PIaAXGDG73y0aJLmriW8+ XHqzTUbpvSoY6MhmpTmJ18Zw/giTqmstIzmEFHNvGtmhDiMcBkrxXs/VR/s2pRZd30aq jsJGbeGziGinvdgAEpWEGIfXp3EhmkT6ct/yut9F+7/cRRUBCk/1ZM7mwZAJSLb4YuqX OwgLV+QnqWQyP5kfWLMe8371Yb01K8TgTpbkSGPJzVhepyspl4jy4123V0yXA9IsrF6r jm3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499611; x=1766104411; 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=II6CNKAdf/lZ/qp3rhzbc8QP/zzmnb1ppQZ/htfgUOs=; b=i/gbXGYrLtUKFmzegP8mzaZqyQliVPAN2siQeKsUXe7qb6+LaiBJp3d8Zp9Vke+IY3 JqgAj+tRwlmFyJTqwLs7kUhcRHdB/67H5iFhm4ZD5bKoZoxJ63MA+OVwDR83Wy7CKU7h sqDCX24YZqCVxNPhjOFi9dfUN3NWTMtwcF6oamiI5HzzVMN4WC5sxYuFlQ2BSudEMmcJ Ep4V0dcCSNvG/P9FhlsQzgge5DnQEpbOgS6xZukMlxz8LzyoAWNdvxvrqi/UWqtcxMz9 9n+RAXp2bbRN6pwDGKzrrH1sxtRQ38eiUWGNXxBrKnEgNhRU56Qp2tzIgTQBSAyndwaF p9OA== X-Gm-Message-State: AOJu0YzYNs9VigsTzASyt6O9AOg2DT5u78cvG7XAPyXp6EFCkRsiah9U 5/vEmll4fSG1hfKLgYGClZEjF68Vz4fksDUEGD3kwEGnbja+W6y2XgaY53p1d9M/v83fQB68VOh nuYWD X-Gm-Gg: AY/fxX7U0q226wnwTV2SP1IwcNL0agnQBan3qzNVbJxM59Lvfo/6HnauAKyLtY24WUs oUeoi4BZf0WYaOBK+5H25e2S+lFZbuaxs7D0UT+DmESgQniCvpsVN0xM92428QoxbHjamnKHxyB nZAOH0mQDqe2LGRBinjf5VzYKxh+vV5yMZOz3v6kWNoD/UGwmB4pEfP182skznyEXFmg2NF1Yk1 fR9w0ELVet8vzJSprDqIppavRlGMsAuofFcGJ/V+tl1n1Jv6UbIRQfd7KCQT5LwMbLxbdCnbwqI ipCxV78k7hxT3Uk12UyqNHi7+6NgmUTDX/AdKyf/S6sko6lpM3yswCe4mCOYO4WXdBNG3lsl7T3 R+wuGaj1jptpT6zA4Lg3wYiyC5cyGzXcOufyIENl3OqEdRmRk5nUdRYCZjlf8smYsqv5gQh+zif eNdFXdf7PUsYKkQKDlLLgW+7vlEOkr1W1xruwyr66nF1+nJ1UNUjyvhiLaqKA= X-Google-Smtp-Source: AGHT+IFCrsq9Mnvc2KoWoBOxjvbj/0sIvnK4eglh1u1FvXFLkSz4CojcbdV6XRJWgPa+5W5bm1VlEQ== X-Received: by 2002:a17:90b:2b4d:b0:32d:f352:f764 with SMTP id 98e67ed59e1d1-34abe3e0134mr173771a91.2.1765499611114; Thu, 11 Dec 2025 16:33:31 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.33.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:33:30 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v8 03/26] qcam: viewfinder_gl: Set no-op Bayer shader values Date: Fri, 12 Dec 2025 00:29:14 +0000 Message-ID: <20251212002937.3118-4-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Populate qcam viewfinder_gl to set default Bayer values so that the shaders can be used in their original mode without conditional compilation. Set an identity CCM, identity Black Level and set Gamma and Contrast to 1.0f respectively. Once this change is made we can use the Bayer shaders in their original format in qcam with raw streams. Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- 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..59f122217 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 Fri Dec 12 00:29:15 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: 25519 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 4B7ACBD1F1 for ; Fri, 12 Dec 2025 00:33:38 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 0158F61635; Fri, 12 Dec 2025 01:33:38 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="nsYbYvld"; dkim-atps=neutral Received: from mail-pf1-x432.google.com (mail-pf1-x432.google.com [IPv6:2607:f8b0:4864:20::432]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3258661613 for ; Fri, 12 Dec 2025 01:33:36 +0100 (CET) Received: by mail-pf1-x432.google.com with SMTP id d2e1a72fcca58-7f216280242so215865b3a.1 for ; Thu, 11 Dec 2025 16:33:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499615; x=1766104415; 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=nsYbYvldMMkS4h+VoJ+thPz9kyICIq1qx0mT5jxyVNbdfWuM2Xmldzdd9vucK8Hpzu Lp8+/88SVV1FaPXVsJVxoY40qfyR9WVzKlsMQId7siPn2ewuzO/y2zjVd7xf3WLVJTPG 41d4O/a9y9Q69eNlEa2/uUw4LRYW9sI/daj1mSbfz4yyviMQaOUKpOmBrQuU3yjQEtWV OioAuT4MIvTQ7d0ULuvRPJ1Kpv7Yi1RcDyonKRFffrRY006Gsbu8iU/THCFLM20HfGLm fdfsNagCN6MboyqW7RD1yT9WloRi+ywrD/ZQ6Ej8KOBIX5HMausuOs4WTmeiaatJLp4f h3bg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499615; x=1766104415; 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=Z/gLx19lcfislLSGQmQY2JqfXOUv9ghDUS5Qem499RZrYKVkjNuDzrY+kJAD+Umyej 6+rROoZBUIppUaf3RJuKPe049xM4ltNYRWe22ogYpRt05jWDPQEsX8vDpyiXtYYKWycD Hge5dej8j+nNat9IjDXACfAyuIs8bsvaF+l2P3wrrQ/suo6L6rL0m3o19xrplgayxOPn aK9V/g2XNWTatGugy53WbMj7Kb2ZQ4PLc3tT3qiSv02Y0pZBZ6QPg2YqOhc6A8hXdyJk 0nreF4hDdg0yp6JT+d9+6/WhAmim2edWcD+AUfcPalbCBebFxHFmjyvAG3Q8c15acEgR kKhw== X-Gm-Message-State: AOJu0YwtuUvzvzyWtRyPbozCiLixmex/7FZUq4C3oTcarlFBRE4fh1Cg gxH6XqZZ8YWeYcccgTIPb1U/lv839ElONcCagMUUmEyM1dWJpeOe5tvbLTp48VJNKm92oG3rjY2 lnNpH X-Gm-Gg: AY/fxX4cpRiH2eJx0hr45fvJhXwtcXS80xAUWiYuH7zWT6wyRP4ySrRAyOP3CHkp4Ry qL9kOgR+IFFqIKnmZj/5vet0i7bgcNiiltEkGAoJmsjgJIuYNDDm3W8C/Tsxjl8KzXBUZ534+LJ 9iZ/ssNCOFMvJZrcQ5Ol2eiFm8tJfFoiuaRDX2yqmqVOnZw9FwTCsjLxrSrl0MvPlCNbDIDl+y7 BoZUWsnrHj8eU+ZlPqQs1e5ccgL6oMJrRRuCC+5MtUQKL5D3cNaMh05IADmb9aqKd5iOKFRG26c 7ABadLOoxV6woaE8YlIw9h2X2aRUH11j8YmCVUav3PSq7ullUj+5fW5laXilmTF261vpN7GZl92 2wbMW8ASoK+QF4k+hdbLnX8iaUp+SmOQzyv5A5dw5gtIJz5wireg8IqYtk2U2WkIM9E1sUzT8R/ dDQlFTODzeRL3P/CiiKGYidbwoI8lPXdl1N/LAOk5rDVAm+b25oNaSNWziOjI= X-Google-Smtp-Source: AGHT+IHUxIgzmVQQrJLQx1HGJTExHGTJFwcPhomuKaqCm56WYyHlnat7ucD7MKX/C0ctUKiHUlIeRg== X-Received: by 2002:a05:6a20:a123:b0:366:14b0:4afb with SMTP id adf61e73a8af0-368599a8d0bmr4775356637.34.1765499614489; Thu, 11 Dec 2025 16:33:34 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.33.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:33:33 -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 v8 04/26] libcamera: shaders: Rename bayer_8 to bayer_unpacked Date: Fri, 12 Dec 2025 00:29:15 +0000 Message-ID: <20251212002937.3118-5-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-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 Fri Dec 12 00:29:16 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25520 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 C6ACDBD1F1 for ; Fri, 12 Dec 2025 00:33:40 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7B7BC61668; Fri, 12 Dec 2025 01:33:40 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="Kd5A36sM"; dkim-atps=neutral Received: from mail-pf1-x434.google.com (mail-pf1-x434.google.com [IPv6:2607:f8b0:4864:20::434]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 52DB161613 for ; Fri, 12 Dec 2025 01:33:39 +0100 (CET) Received: by mail-pf1-x434.google.com with SMTP id d2e1a72fcca58-7b80fed1505so702460b3a.3 for ; Thu, 11 Dec 2025 16:33:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499618; x=1766104418; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=FdyTcK0Xun67yTvAExHcO9DNNAcWNw/aYg3LzuhT/Zc=; b=Kd5A36sM/n0QakJIRzCM2UpTm5YIhWpIZeAFU4VFMFnSpGcYETz2AQbLIqj+5C/SrP afHP2nYd4eb45CCd9YQdilqT2wVm+HHd1S2DAM1U3wqCHEVb33Pea7epW/4+UQixEHG4 XQ6yvOKSyBjbZVDz+20WIeh635KsFbL9dyPFWr0qKxG+GMqoYmH7TenTSXGd34d3NmGH 8V1Yhe8AzpuklU0l1akiHLiWzWa/AMhMzKNxbsM0AAi1ERpIW2p/cnyRTvakkyrOZXdp H5obWOf6jOdplrGg7n55h/tRjA/02sScIMJIlmbkKn8ljjDhfdtTr3KrWDx3O2prNZWF Q1Zw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499618; x=1766104418; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=FdyTcK0Xun67yTvAExHcO9DNNAcWNw/aYg3LzuhT/Zc=; b=Dx880Fi4KIH+rlPopJI1DDZ/eQ8JXAygrVdxwR48qEoFulS+ElaNotSdoVbRKsqHjP 8KUyGrBnmoKNwsgdqkpdM0RCIac26ojb8M5dNKOfCEi3+4PDUNaa32AGZDMwY0YME49O jSTr/ydTS6Xge84iH6uqtNPnRptR/MF86TSJO/pQPST86jYViAMp3I322E9N/o5Lgk+S l0hpk6Vqgd2/YQPhtUrOzfw9eLmK3r5sjOSQk51Y69818la808Q2Zpb4LDgGkHRoHZS6 vKkNsAZU8BsgxhKbXUVwG/eHirZXaBCLuarr+WzrrMt/uj9SHmJaY4dKuIrPrnjXEHUf GBUw== X-Gm-Message-State: AOJu0YwrpfncTC5T6Q3DfxHyWXBjKOnm+sqjo89PAIEQnJYJGMtXy0On fz2PNexiV8qJP1B2LGu4P8RkTiNSRJvDpmrC7xsAthUt4YVLcIIgDhd741PrpslQTgXfxkkCodf 2Vs8j X-Gm-Gg: AY/fxX46zMk1ORCLOU+wVcXvUHCb4iaoxFjQS0QvdXiYa5f9EkK7Qz1fFiFksrGmYP5 hm4G5m42k95BBvS9H1/NQfHk/J3Me97rcvdd+UGvdDFguGdBAlhrJa2NuWSEixn8MhkLHhO9QVk BYWMg07MnH+M39eW4ajQOcxdUwTkodsZGQKFnos4XaJ6BiOTci2oELvetuiWmaYCoSryOPQ666O eJTxpYP1+ZyJQ2m5Ts+kEtUSiDXLgop4fC1fc+ePcCpWvnohyYrHegWGwf/F+rX+JLsVNnD0uoG bcbNnLOxJGixJ/vgdUAoMIB5fyGgbXAjD7/8KCmSSIWWkEWrujqf+lCbroGkMwarT8rpAnqF89h YE8eDWSTy5uOnF3x8EDwCwlXR83tOwBztr3t7H0Kjtr8sXULCkgJofVshm8c8TQdIXwMbSv269z sls6eapYUi4uUktkVRr2jXWfNhdXWOGrGSJ1fLa+UUu7XammQag9uo1CsnJlU= X-Google-Smtp-Source: AGHT+IFneNeD0CzS7tRSKSHPz5TD+SUN8ZRmcHdKHiOYddMfUuBaRWjQM4pCTrtMs8qInAhNsXFTUg== X-Received: by 2002:a05:6a20:3d8b:b0:35e:11ff:45b4 with SMTP id adf61e73a8af0-369adfb3407mr290384637.21.1765499617627; Thu, 11 Dec 2025 16:33:37 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.33.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:33:37 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Kieran Bingham , Milan Zamazal Subject: [PATCH v8 05/26] libcamera: shaders: Use highp not mediump for float precision Date: Fri, 12 Dec 2025 00:29:16 +0000 Message-ID: <20251212002937.3118-6-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" mediump gives 10 bits of mantissa as the resolution. At higher resolutions 10 bits of accuracy is insufficient - for example at a width of 1928 bytes we need log2(1928) = ~11 bit resolution. Switching to highp gives us 23 bits of mantissa giving a sample width precision of about 2^23 ~ 8,388,608. Acked-by: Kieran Bingham Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/libcamera/shaders/RGB.frag | 2 +- src/libcamera/shaders/YUV_2_planes.frag | 2 +- src/libcamera/shaders/YUV_3_planes.frag | 2 +- src/libcamera/shaders/YUV_packed.frag | 2 +- src/libcamera/shaders/bayer_1x_packed.frag | 2 +- src/libcamera/shaders/bayer_unpacked.frag | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libcamera/shaders/RGB.frag b/src/libcamera/shaders/RGB.frag index 4c374ac98..724395894 100644 --- a/src/libcamera/shaders/RGB.frag +++ b/src/libcamera/shaders/RGB.frag @@ -6,7 +6,7 @@ */ #ifdef GL_ES -precision mediump float; +precision highp float; #endif varying vec2 textureOut; diff --git a/src/libcamera/shaders/YUV_2_planes.frag b/src/libcamera/shaders/YUV_2_planes.frag index 1d5d12062..d286f1179 100644 --- a/src/libcamera/shaders/YUV_2_planes.frag +++ b/src/libcamera/shaders/YUV_2_planes.frag @@ -6,7 +6,7 @@ */ #ifdef GL_ES -precision mediump float; +precision highp float; #endif varying vec2 textureOut; diff --git a/src/libcamera/shaders/YUV_3_planes.frag b/src/libcamera/shaders/YUV_3_planes.frag index 8f788e90a..8e3e0b4a5 100644 --- a/src/libcamera/shaders/YUV_3_planes.frag +++ b/src/libcamera/shaders/YUV_3_planes.frag @@ -6,7 +6,7 @@ */ #ifdef GL_ES -precision mediump float; +precision highp float; #endif varying vec2 textureOut; diff --git a/src/libcamera/shaders/YUV_packed.frag b/src/libcamera/shaders/YUV_packed.frag index b9ef9d41b..3c9e3e397 100644 --- a/src/libcamera/shaders/YUV_packed.frag +++ b/src/libcamera/shaders/YUV_packed.frag @@ -6,7 +6,7 @@ */ #ifdef GL_ES -precision mediump float; +precision highp float; #endif varying vec2 textureOut; diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag index f53f55758..19b13ad08 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -20,7 +20,7 @@ */ #ifdef GL_ES -precision mediump float; +precision highp float; #endif /* diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag index 7e35ca88e..aa7a1b004 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -16,7 +16,7 @@ Copyright (C) 2021, Linaro //Pixel Shader #ifdef GL_ES -precision mediump float; +precision highp float; #endif /** Monochrome RGBA or GL_LUMINANCE Bayer encoded texture.*/ From patchwork Fri Dec 12 00:29:17 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25521 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 4906EBD1F1 for ; Fri, 12 Dec 2025 00:33:44 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 103BF61635; Fri, 12 Dec 2025 01:33:44 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="zLUyt7r8"; dkim-atps=neutral Received: from mail-pf1-x42f.google.com (mail-pf1-x42f.google.com [IPv6:2607:f8b0:4864:20::42f]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0031F61635 for ; Fri, 12 Dec 2025 01:33:41 +0100 (CET) Received: by mail-pf1-x42f.google.com with SMTP id d2e1a72fcca58-7c66822dd6dso319338b3a.0 for ; Thu, 11 Dec 2025 16:33:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499620; x=1766104420; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Zkzu0tqbzAOlMWvnkw6w2p9R2Nid+3zoTkR/m4lKMgE=; b=zLUyt7r8h2WbEJlIa28BQ19Geegxn1w/seiUlg6COsvoKiO/KH0wEWdg0i0LsoD2CP sekiWqDWsejT+Ej332hOYKLj9G52A1l/2/X2smcgid9ZXjJeLkG/K9p9VAgNKzrI/qtW pHPnOhl7C/I6byYQdAHKoPF57ZwpS6Y2DBEdscVcdLOHRhpm64NwYmK/FLZDbm8mB+M3 ze2c8bCPh0YYc8c1zcReKidbU5AT1eUQbKHuy0PXD0ETee7bQZY0ordwO6FRLXR2N5T1 T02utBvKfPKtYaQIQc/v75k/8gLrCUhAhTRhwZF0OdLh0KhDckcQROz9xP/lEFT3dVGE AhHQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499620; x=1766104420; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Zkzu0tqbzAOlMWvnkw6w2p9R2Nid+3zoTkR/m4lKMgE=; b=LohoCzSsKhCEzFxQz4UKJisl3UG8zE15XnVX6rcZ690UfK6/eM0iyOGw4FvI+7DOFE MRegbq8D1/ZpI3BiBfgwv4Zkn/69qcfeVMJmk5kauaMHFtgsDmhdVf7qvlDic9hD5bkd J1VSuPlxoxkhyjbyeTdW9ceRp6dkZhdlSGb8ZPZaRBl/manHneD3N04/shXIWH4JkX31 VjPK05NoFE/Pa5maVAeoX85SAtcFklovEpmNInJYiUUxnwqgG6IYmnvYO5VjiFhgL/on Pklv48CeWxgpJrWz1z6Ld7+i7oPWOpg2Vs8u3q33+jH1l8n5xXYXbNrd23j4HHGVkswV zErA== X-Gm-Message-State: AOJu0YzsgsLdnAt65CI/9MS4aROXZT/ge9PeyPVQp7Kn+n715gxpVLPk 9qO+bibHmIs5sC73b6sZ5lJ7SI3q0od4Azl7nkB27v6gdeCKIRbteXUgs+wuLMRU4DKwsNVtFoZ S1ZA5 X-Gm-Gg: AY/fxX6uWJbj+rekotGGSvEy96cjoshd47g8wa1H/kIC68nx5bzqaa2I4RtDraTRbzy EoQVnoNENdAJAlpa5fZ9VTX9dFMtpP0kbq5RBVzm9ZGQYM8forFyXEnFAsne03WvgY0H3E0yzNL kjWlSy52cl27ugc0flyXypnaWGLQHAJQC7dd6Md/RnM6yg28V5XZIDyiq0E7KmzJJ9yKhOFkYIg RB5xTAERjoezBxk5kFW03+YAL3p+scyoo++1wdB6RK0jXn+KVoSqJftcRnFVPy/zVgdNOIbg7qE 8qNG7ESF28xwW2vxyO68dqFD4nep6pBOEuyDA662KaEotKbYB59nIrjFCRPhmlT1ULz3VwG5W/c 55EERy7m/+NDk7u8V81oKXtDkb7ih4seJ12HxIGzvxcu+rqSHmrJ3XmGezKRebigipRsCtBugM7 zBle0RngObfPNQh7b2rIpI2E8Xszy0zu+YsuAUKnhq6c150clBENdyMK37VJI= X-Google-Smtp-Source: AGHT+IGbB0YnSVpvwEyvcMRlLd5rVt5PKMwmgQaD6pvORp0rHSk/5draKAB+exmK07bhIXGl5ICRVA== X-Received: by 2002:a05:6a20:72aa:b0:35e:b02b:4efd with SMTP id adf61e73a8af0-368594b7cc0mr3840158637.27.1765499620247; Thu, 11 Dec 2025 16:33:40 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.33.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:33:39 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v8 06/26] libcamera: shaders: Extend debayer shaders to apply CCM gains Date: Fri, 12 Dec 2025 00:29:17 +0000 Message-ID: <20251212002937.3118-7-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Extend Bayer shaders to support application of a passed CCM table. Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/libcamera/shaders/bayer_1x_packed.frag | 45 +++++++++++++++++++ src/libcamera/shaders/bayer_unpacked.frag | 51 +++++++++++++++++++++- 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag index 19b13ad08..171a928c2 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -65,6 +65,7 @@ uniform vec2 tex_step; uniform vec2 tex_bayer_first_red; uniform sampler2D tex_y; +uniform mat3 ccm; void main(void) { @@ -212,5 +213,49 @@ void main(void) vec3(patterns.y, C, patterns.x) : vec3(patterns.wz, C)); + /* + * CCM is a 3x3 in the format + * + * +--------------+----------------+---------------+ + * | RedRedGain | RedGreenGain | RedBlueGain | + * +--------------+----------------+---------------+ + * | GreenRedGain | GreenGreenGain | GreenBlueGain | + * +--------------+----------------+---------------+ + * | BlueRedGain | BlueGreenGain | BlueBlueGain | + * +--------------+----------------+---------------+ + * + * Rout = RedRedGain * Rin + RedGreenGain * Gin + RedBlueGain * Bin + * Gout = GreenRedGain * Rin + GreenGreenGain * Gin + GreenBlueGain * Bin + * Bout = BlueRedGain * Rin + BlueGreenGain * Gin + BlueBlueGain * Bin + * + * We upload to the GPU without transposition glUniformMatrix3f(.., .., GL_FALSE, ccm); + * + * CPU + * float ccm [] = { + * RedRedGain, RedGreenGain, RedBlueGain, + * GreenRedGain, GreenGreenGain, GreenBlueGain, + * BlueRedGain, BlueGreenGain, BlueBlueGain, + * }; + * + * GPU + * ccm = { + * RedRedGain, GreenRedGain, BlueRedGain, + * RedGreenGain, GreenGreenGain, BlueGreenGain, + * RedBlueGain, GreenBlueGain, BlueBlueGain, + * } + * + * However the indexing for the mat data-type is column major hence + * ccm[0][0] = RedRedGain, ccm[0][1] = RedGreenGain, ccm[0][2] = RedBlueGain + * + */ + float rin, gin, bin; + rin = rgb.r; + gin = rgb.g; + bin = rgb.b; + + rgb.r = (rin * ccm[0][0]) + (gin * ccm[0][1]) + (bin * ccm[0][2]); + rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); + rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + gl_FragColor = vec4(rgb, 1.0); } diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag index aa7a1b004..c41d72f4f 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -24,8 +24,11 @@ uniform sampler2D tex_y; varying vec4 center; varying vec4 yCoord; varying vec4 xCoord; +uniform mat3 ccm; void main(void) { + vec3 rgb; + #define fetch(x, y) texture2D(tex_y, vec2(x, y)).r float C = texture2D(tex_y, center.xy).r; // ( 0, 0) @@ -97,11 +100,57 @@ void main(void) { PATTERN.xw += kB.xw * B; PATTERN.xz += kF.xz * F; - gl_FragColor.rgb = (alternate.y == 0.0) ? + rgb = (alternate.y == 0.0) ? ((alternate.x == 0.0) ? vec3(C, PATTERN.xy) : vec3(PATTERN.z, C, PATTERN.w)) : ((alternate.x == 0.0) ? vec3(PATTERN.w, C, PATTERN.z) : vec3(PATTERN.yx, C)); + + /* + * CCM is a 3x3 in the format + * + * +--------------+----------------+---------------+ + * | RedRedGain | RedGreenGain | RedBlueGain | + * +--------------+----------------+---------------+ + * | GreenRedGain | GreenGreenGain | GreenBlueGain | + * +--------------+----------------+---------------+ + * | BlueRedGain | BlueGreenGain | BlueBlueGain | + * +--------------+----------------+---------------+ + * + * Rout = RedRedGain * Rin + RedGreenGain * Gin + RedBlueGain * Bin + * Gout = GreenRedGain * Rin + GreenGreenGain * Gin + GreenBlueGain * Bin + * Bout = BlueRedGain * Rin + BlueGreenGain * Gin + BlueBlueGain * Bin + * + * We upload to the GPU without transposition glUniformMatrix3f(.., .., GL_FALSE, ccm); + * + * CPU + * float ccm [] = { + * RedRedGain, RedGreenGain, RedBlueGain, + * GreenRedGain, GreenGreenGain, GreenBlueGain, + * BlueRedGain, BlueGreenGain, BlueBlueGain, + * }; + * + * GPU + * ccm = { + * RedRedGain, GreenRedGain, BlueRedGain, + * RedGreenGain, GreenGreenGain, BlueGreenGain, + * RedBlueGain, GreenBlueGain, BlueBlueGain, + * } + * + * However the indexing for the mat data-type is column major hence + * ccm[0][0] = RedRedGain, ccm[0][1] = RedGreenGain, ccm[0][2] = RedBlueGain + * + */ + float rin, gin, bin; + rin = rgb.r; + gin = rgb.g; + bin = rgb.b; + + rgb.r = (rin * ccm[0][0]) + (gin * ccm[0][1]) + (bin * ccm[0][2]); + rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); + rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + + gl_FragColor.rgb = rgb; } From patchwork Fri Dec 12 00:29:18 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25522 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 D757DBD1F1 for ; Fri, 12 Dec 2025 00:33:47 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8F4FD61661; Fri, 12 Dec 2025 01:33:47 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="qKIsKf+i"; dkim-atps=neutral Received: from mail-pf1-x42e.google.com (mail-pf1-x42e.google.com [IPv6:2607:f8b0:4864:20::42e]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9E8776165B for ; Fri, 12 Dec 2025 01:33:45 +0100 (CET) Received: by mail-pf1-x42e.google.com with SMTP id d2e1a72fcca58-7aad4823079so642682b3a.0 for ; Thu, 11 Dec 2025 16:33:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499624; x=1766104424; 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=qKIsKf+i+6t98BJGQ9XM324UX7KPA9IMCHU2ugfZnVxoNAoKWACOu2eYC5mkxhkF0i G0SWwXq/E5Y9WVU1aPqvfICjnaKNeijczSgipk/40KFnNW2ESSlkzsIbyNGjZpZSPiaW qS37lYhBMKcvV6U9TLry/BJx0eRWLPNd2NeDgOBy3ZNk1Ekt/YyqtxUp3PmEQs9ERcqZ B2vzHt7evW2aL9Vr5gvdPnHd6xLkRiG2IZmDfi4TRvOJEhtar+g+9mmCqkLnsRFySQY+ LGYPSmy3wkOd8c28QzXlgZCl/7xeKY8GNi09oNTIZOgr9N7SLPLM+YIDnkhPizgo9oA9 dj0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499624; x=1766104424; 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=laxaLOmzHHvcnbSF3doSV064FmtrSyVeBIYtsmgo4wwgQwE9cW4iAWz4qVBFcZEyg2 IZmU6eKMvA02Qcmv/jydiCxTrzHZXO9g5IpK9pLwuECLQC0BFl6Q/g7ckPbnNW3byyYq 41jVTdgjrzpVU/2XkY0MXwQM+G0hiB1SR0+ojPnOURTt/E0ji4x486jku3dFRB7n5Aud JPfmZJHm6WZC8uCzpOEErZN12UXo7/nHkwH/6l7NbpctYGh3dwCXb2snz7++jtxUpf96 ixSOwKkCvQNbEAi4yDdMzKylksrI8rgNpv61luRqzsQSxVds5ztuykXjk0vZrkJi3UjN SMNg== X-Gm-Message-State: AOJu0YyUBkHKoOlhMOX/ZI/1z+RhAqmME4CUnUE1D7w0ssrIZZPACWNi SR8QxbfD8O4g+7akr/lt5QSOv4U46xLM9VHMV01bUYybBQkKnAkJOlpGioJPv31RQum4k/+971f kdeJY X-Gm-Gg: AY/fxX5q3d7zP7a06yDPfdQ6nzYpZ7KfT7Rv7+OB6c0tqgq0iLjK7yx48V9cOzNm4tS 6iOs3dsKAc7hubT1hxAP4rVw3tAm5SMoW7TeL7z1BjYE4b2+4kfLX2+ZBkd2eAR+M2fjvkCr070 5goDiUFy3T5r6I4kvoDy9L3NWvtzWAJ8jps/MJ0Qe8Z2WobdTUAvigZ5sHZB+0u6zAL67lybHYw s2/tBv94ssDfi4YvGrVMvS+87W1UNStWojQ7u9x5WJfa1lbUZY4vIpJES0kvZNz1cmfWehqXjjZ N1DzDrDWPecllgbdC28xA68mPwmAsvPwiz6EQCgR9Ov23Fc5B8QcFnijcAWTfbqKIU5qfbEIkYB WV9YVjhyMfCOVgnvkrH+qpo8NihXaM2xJxjDonJf/NImnff5d83qqVMNfnVFEKST+B/jKPY+4ui 6593vFp+kFMCWDb4H+xtliR7EQ2VP/efcezNhUPYXNMDCecBO0afN4i73HwHlMtyv7aQunOQ== X-Google-Smtp-Source: AGHT+IFc8ID1slBJEexswPI4ub811riWu1VP8BCHRvkdXDoJ4+4I+uKCLTazKZe3pADWjjXzxtW5Vw== X-Received: by 2002:a05:6a21:339f:b0:366:5c4a:c49c with SMTP id adf61e73a8af0-369af33590fmr300568637.41.1765499623922; Thu, 11 Dec 2025 16:33:43 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.33.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:33:43 -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 v8 07/26] libcamera: shaders: Extend bayer shaders to support swapping R and B on output Date: Fri, 12 Dec 2025 00:29:18 +0000 Message-ID: <20251212002937.3118-8-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-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 Fri Dec 12 00:29:19 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25523 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 52D85C326B for ; Fri, 12 Dec 2025 00:33:51 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1ADDF6166C; Fri, 12 Dec 2025 01:33:51 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="iKWpHqv/"; dkim-atps=neutral Received: from mail-pf1-x431.google.com (mail-pf1-x431.google.com [IPv6:2607:f8b0:4864:20::431]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9880A61635 for ; Fri, 12 Dec 2025 01:33:48 +0100 (CET) Received: by mail-pf1-x431.google.com with SMTP id d2e1a72fcca58-7b6dd81e2d4so696588b3a.0 for ; Thu, 11 Dec 2025 16:33:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499627; x=1766104427; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=5qjoeAop1GzrvnIG7vvLvJkbwSmYKtE+YPe2MFgINpo=; b=iKWpHqv/7DcRhOGlktoHAWFS/MYdjodoqwQOkYIiMqMezEQMWiHuq+gZvplcMKp6H8 G6uLiQn7JKdHBJXLhjLFCvw0F+KTCZx+Jc5VgeZvW1L7ZB8Rnhhc4Lt4KpiDpX2lcwn/ K2iwFnDkeiGfel3loAabfJjXQdWxI2vwH8QggbC2pRpAx+zFQEajSOMepIk//Rk+aWff eqqdsyeqfZEK9xP3aF6DNrjp8q88UBUnVx1fjjU9R7kF5RTPQrc442Ev0DikbGP6l1yk Is3hZWefBER075nxZNc5g2xNGUbY4eC+1u1ynAU4U0PaKUmeJmoQzV/x7zGWaaF2OpdX BHJA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499627; x=1766104427; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=5qjoeAop1GzrvnIG7vvLvJkbwSmYKtE+YPe2MFgINpo=; b=ve7RyDyhI3rrMgYfXj6yc/7xGcwNmih7hYuRKPWIrki/uXkR3y73M9vok9MuScr+1D FgZ0cOf7yWgGxwcKQm+RfPQiOqHaJvc2iK6c4Q1373liUzw9ymPoTc5eI+wi6PH7wd3s tgUwavmAY0oQVpL25P/hjRVv5pw1oGzyFTppFIwBUCRv89/X7uiFcfLgq3AtHc902TBq Lcw8rb408r0yW4rkIfLGfOs6ZK4L4Yue6M8COltl6riQG01qqK7VPZ3EqwcudHZ01WXV aogxuYVpiuZTPqUxjsrITX9kz0ZMlvHShu/WcJgJnVIYi0p5NuHgJiLM8aRFkXl9t8hh SyQw== X-Gm-Message-State: AOJu0YxwnMiCubqrsb+ikVcmzhJwlYSpoXQPm5ZORAPYuu+JrA3UfgrH iI/0ebYk1d7vtp93+wN0/nuvbqdzmhKv/rkucjp//FXH+kaTt+gz75QNA/+7wsURcSH/oK0q6r1 42gV3 X-Gm-Gg: AY/fxX7w4ZOVyuG2giP8jwgzdFMJDlqE1EAsV6Uo+0hyIeuqFNKCBC5tqydD7ocxjed 97vJeKzRqi9OvPdZ5D3DBP420GDvF6jb7oEsjui0suEFt+kn7nr/TD5XkkV0COv0FZX1MzNFIOq /yuvNVuMkXXF2Ji4gOwXYg17KV5kYwqR5zlXA7dsC197dhw5YOkS3taAtOa7+OPTRB2tnfsWa+G 0nr5ZS0wbvH7KRpi6Xd+21TkzY1/jMHlEL7hs0UvoErrecAmu3XCR0PjtzIE0BBFPI/6BZ0Txz5 mTB2Q3vpbJvHvutiMhu3DFMZcuGvTI1pejF0MwCsmj5/ntPOUkoVlfAvo+mZMVeKx1F3OYCEKUt Wd9D3ATynU46n2FGxqeV4n2Z/r5JPENs7JXWFRGHe7sTINnVeeJekrWsKUuRNu7MrkLw89nVtfY Ffd8RenHqDdn7bd50Mhh69IDgimr8fOa87ANX83qsyhyK+cZNh7c+fC0dutZPQQd2YNC/7TQ== X-Google-Smtp-Source: AGHT+IHFdaAI1TlPzI5mnhQQqiVPYeiHHHbFB4r36z7dUCqQ5NUOE0dK6SJd0G9qHoQm9ReTdZ+mgw== X-Received: by 2002:a05:6a20:7344:b0:35e:7605:56bb with SMTP id adf61e73a8af0-369b00eaa8bmr331731637.59.1765499626932; Thu, 11 Dec 2025 16:33:46 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.33.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:33:46 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v8 08/26] libcamera: shaders: Add support for black level compensation Date: Fri, 12 Dec 2025 00:29:19 +0000 Message-ID: <20251212002937.3118-9-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add the ability to apply a int blacklevel gain against the demosaiced data prior to application of colour correction data. Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- 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 Fri Dec 12 00:29:20 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25524 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 DE4A7BD1F1 for ; Fri, 12 Dec 2025 00:33:53 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 906236166C; Fri, 12 Dec 2025 01:33:53 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="G+Ua28eg"; dkim-atps=neutral Received: from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com [IPv6:2607:f8b0:4864:20::102c]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3695C61635 for ; Fri, 12 Dec 2025 01:33:52 +0100 (CET) Received: by mail-pj1-x102c.google.com with SMTP id 98e67ed59e1d1-34374febdefso695891a91.0 for ; Thu, 11 Dec 2025 16:33:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499630; x=1766104430; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ZRuITSMve+FWc8iDUneEG5zb0QDixsRjAIi5XBQ3RYM=; b=G+Ua28egfZ4IoQ0wIgUNMbJuI6rby+BqYfBD3+fvpjfYD4jGZxHXDvrskIzoXFCIGP 2plQwVJCSuGjt9Uvx9vHyEKQyV2mzpbiLIKY3REkniejoA7omNUzPu0SYXE+HFEygtIH FPV1zmsqFpY78TSjywL0+/vrqBLAxUpxEmUrxWlZ8MO2+zz8xq+TlgxZlVZfRbPzkx10 zAsK4QtNhQLOZdoBQeCBNjSKEU1HPN/saXJ5UahKtEa1GX9qBJSd7DzcgF/wt6dLx+aK /Y4l+pTJ6MuwvzGR7NIz34RuSR5bT9U622f/jLrxOEDycrmyce0iH3v91+i1GzXxsSju FKyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499630; x=1766104430; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=ZRuITSMve+FWc8iDUneEG5zb0QDixsRjAIi5XBQ3RYM=; b=FMr6esA/a+HaXWVScOdq/bZe4rlrPICdbCT/PmYQ+HUy1kNy/DfBw4yKwZJjL+vkkD f1S5tB5vCL9aNyqK4pU3WboDXUTvD4RKBTp49egl3xC61/1prtNcxHxvnwWwepdqmZvw hZXhQQ/UDxnIJz+BQHs+SqjPEBm7yDzOcB+GOXMfMtF//ohDL0LDWpToEzPbVM4ZAgZs a1IYKecPvc+2jI237pXQ62v/o8Ppu9A8tGyt5/3joC3LMGAFI7QwudusMSBd0cJUj1Hb W9etZ1DVtKOidmvInOPgqzcSLjd5CsY9vCJxsG+mN/JR77LGT0KKvFsmlHSpbyGaXpQA Ke0g== X-Gm-Message-State: AOJu0Yxxp8CgECVYq0Ya6HdvdhgG3rnvCAzIVvxvMWxEA5ayTwoES4LS 5Udf8HhrH9PLu+z/JWSM2rjxIAFdiMqV5kTgNh2mRit+UwYl7xmsFQDMyRSCZ/pe00Th/JoWy3c 1o/1y X-Gm-Gg: AY/fxX7ZfyJ54/73n8h2pwzV3q8KsSr4nowWD9i6k9Et/8Cu6QWb9h9qLTssgnjRd2W P8Tfs1yWdfVHtPhRv19iMk0evH9QVnq+uiwHAoorC8FT9utHatsdlA495lOW0uZjS7RLS/pI+sO M0NZ8wZzNkmAGks3tGbL2n4vexxDk2ggihWfJ+0Kl1G8dLDmqguHK5A8tINwLrMuhEWtVEI2aYd j+SUUH0AYao6zYkBElK04CuACgYMzdw2yzLvj180t0umgrU4DfINKQ6fz5YUy5r426t4Z4cjT8g XCzPQfYB6uANJo3QA+Nn1FTm08AyqPp22wkSB8b16uXnYaLtDOUGK+ORMIydYzgCA16ny4jv8gt E5O2+zzxJrjtGZpUeh6rUomGtJFTBfR57UTF1DYZXcwwqJbN7mP7aMQ9+N6P9BTgmzLoywfSmKX zw33ZMjUPhd0mpJD6wf/EORqeq7KV5wJLjN1w8NqbVjTl1pHPwTsyAES3QMo0= X-Google-Smtp-Source: AGHT+IHcFukGZ9huue0rHLReGc2lU4rqvel/uXgSOmeSJMnjzEXcI7Wf4OOEGyfNxZpKZKTRAlAhhg== X-Received: by 2002:a05:6a21:328a:b0:350:ee00:3cc1 with SMTP id adf61e73a8af0-369ae3977f7mr302450637.30.1765499630517; Thu, 11 Dec 2025 16:33:50 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.33.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:33:50 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v8 09/26] libcamera: shaders: Add support for Gamma Date: Fri, 12 Dec 2025 00:29:20 +0000 Message-ID: <20251212002937.3118-10-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add gamma compensation to the debayer shaders after colour correction is applied. Similarly only apply the calculated Gamma curve when using the CCM as the lookup tables already contain the data. Suggested-by: Milan Zamazal Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/libcamera/shaders/bayer_1x_packed.frag | 4 ++++ src/libcamera/shaders/bayer_unpacked.frag | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag index 7036fe278..77d9fbfa7 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -67,6 +67,7 @@ uniform vec2 tex_bayer_first_red; uniform sampler2D tex_y; uniform mat3 ccm; uniform vec3 blacklevel; +uniform float gamma; void main(void) { @@ -260,6 +261,9 @@ void main(void) rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + /* Apply gamma after colour correction */ + rgb = pow(rgb, vec3(gamma)); + #if defined (SWAP_BLUE) gl_FragColor = vec4(rgb.bgr, 1.0); #else diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag index f0d8cd1e2..aba11a87f 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -26,6 +26,7 @@ varying vec4 yCoord; varying vec4 xCoord; uniform mat3 ccm; uniform vec3 blacklevel; +uniform float gamma; void main(void) { vec3 rgb; @@ -155,6 +156,9 @@ void main(void) { rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + /* Apply gamma after colour correction */ + rgb = pow(rgb, vec3(gamma)); + #if defined (SWAP_BLUE) gl_FragColor = vec4(rgb.bgr, 1.0); #else From patchwork Fri Dec 12 00:29: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: 25525 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 8A8F7BD1F1 for ; Fri, 12 Dec 2025 00:33:58 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 42A906168E; Fri, 12 Dec 2025 01:33:58 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="hKteUxNY"; dkim-atps=neutral Received: from mail-pf1-x42d.google.com (mail-pf1-x42d.google.com [IPv6:2607:f8b0:4864:20::42d]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E42F261635 for ; Fri, 12 Dec 2025 01:33:55 +0100 (CET) Received: by mail-pf1-x42d.google.com with SMTP id d2e1a72fcca58-7e1651ae0d5so592164b3a.1 for ; Thu, 11 Dec 2025 16:33:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499634; x=1766104434; 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=dN8UZt6qlRDwenuDplOdpGWNKDU85eQ9zmywwDQb0Cg=; b=hKteUxNYqaFPD0AXzSSJCPoSWv5u4LGGq8fiYjz12DBEHslvpsV4yZGGO8acUR1g2/ gHHTf0iM2sYKvrsR9aEFaGtfq1aIqTmhryT6fej6HiFBoGOqZpKrOCDYqT3c3r89j+H7 DRiVRdO5OzlvblsDl/TNSX4vlw0gMcO7/VRvoFcohrignYH/83DDxIKE3KZOGe8cn6yp U3qMydgW/p1ZfAkmRMA8n/X3Sw0MeUDs2/dV7ZHIO86hoe1CkCVRbETEQ3p/fkWjnszJ WztF9twKrUFITUifJ+/7A1VAT8lV9jaUdps3xTqBfpEwAaFduU6Bwxu5KaktR0C2OM0p mchQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499634; x=1766104434; 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=dN8UZt6qlRDwenuDplOdpGWNKDU85eQ9zmywwDQb0Cg=; b=LZMgoVhGm5kVFseH1s8aBbHTM6PDaoddZLbkLB7HGPMUHAvQqquVgitrbrKxRAegE3 uvItCnePl3Y7Y8Thkx2nXFc01lAQ5Wf7S0dzW7hCWsEv1z/aym9X4eeyuQvLmr3h89U9 +O0Pq/x7xid83zQCtFNHe59iLFxjAdP00kJA0GOk6Spk95gp3M1Yd28Rfg1vWQM0ssSA RIxqkSaba1g4+mY1fuAGcac62Evusnet5pGuzWEcjO8z21lImBEgmHx08tlPlXuw6SlA DC+kkqqLKPGV5mmSnjhMP+hN9mgZeaLRJeXuHdb1ryX6xyIJlE/j3DwW6f42gHGJ77cN qNaA== X-Gm-Message-State: AOJu0YxmNR3LzhPhVMq3fdP5RpJrpzOK3FsVkGM/W8rzZPE++5HwQcSP 9N80VR0UHMgKp+QXZjWUkVgutFFOZ0ZCpRwjVEuX9t9GOt0hnRqFnuVsYo8+UfI61V8s4upC02k af/Jm X-Gm-Gg: AY/fxX6emuY6rFDiREVEX7sspcZvWp7tKweeHkUzHsC+LKWxAHawpZsjqSeYckMYnn2 VkzULQpVzvq6OzM7+xO5nIexHSK+QZdipbfwEbbym9ePQSNn5q3UNz0EZrTG9qQtpYDtV/+tdLt Px3QoA7IsgP/6illN7cU26ShzE3b9f78iHqcmBJ82oVEpyx85h+L5HgL/SSPpe5X3s4f3ZsuRpT 8lbPTuvsR4uGy8HuMGbGFovriywJtYI4gtIQU86wUXqGijflDm80KygmPxID6VmCZlXDW4mV68k 0CELlaM0ORT2cpz9rOJgNoyx6A3HyGgPQpE9HWRW5HDzqFtCh1OR+MWm6Nr+VKDkvGv+7H/J+vO ZjH1Iy31JoAK6Kqh0lrQQC3peGMhpO1uWIwd9xWLVDe8l5uG8hbFy4n9iCTDlAe/lNf2ACAJ7Of y1u6fZJGcsW4T5X/TQ/fm+6HgUg3QHqzcYGX0J0wej5ySB71s+IcaA32Kgo2HbB4s5CJlG8A== X-Google-Smtp-Source: AGHT+IFrlauqKahU3yInGY0OzEsCeCYb7WzxgMij7edjwKkoRIGg540bRyLP6D5+zDeouPgYSH0ETA== X-Received: by 2002:a05:6a20:6a21:b0:35f:27d:2ded with SMTP id adf61e73a8af0-369adfb33b3mr335863637.25.1765499634196; Thu, 11 Dec 2025 16:33:54 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.33.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:33:53 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v8 10/26] libcamera: shaders: Add support for contrast Date: Fri, 12 Dec 2025 00:29:21 +0000 Message-ID: <20251212002937.3118-11-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-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 | 21 +++++++++++++++++++++ src/libcamera/shaders/bayer_unpacked.frag | 21 +++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag index 77d9fbfa7..0b730070e 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -68,6 +68,16 @@ uniform sampler2D tex_y; uniform mat3 ccm; uniform vec3 blacklevel; uniform float gamma; +uniform float contrast; + +float apply_contrast(float value, float contrastExp) +{ + // Apply simple S-curve + if (value < 0.5) + return 0.5 * pow(value / 0.5, contrastExp); + else + return 1.0 - 0.5 * pow((1.0 - value) / 0.5, contrastExp); +} void main(void) { @@ -261,6 +271,17 @@ void main(void) rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + /* + * Contrast + * contrastExp 0..2 contrast to 0..infinity; avoid actual infinity at tan(pi/2) + */ + float contrastExp = tan(clamp(contrast * 0.78539816339744830962, 0.0, 1.5707963267948966 - 0.00001)); + + rgb = clamp(rgb, 0.0, 1.0); + rgb.r = apply_contrast(rgb.r, contrastExp); + rgb.g = apply_contrast(rgb.g, contrastExp); + rgb.b = apply_contrast(rgb.b, contrastExp); + /* 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..114e32058 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -27,6 +27,16 @@ varying vec4 xCoord; uniform mat3 ccm; uniform vec3 blacklevel; uniform float gamma; +uniform float contrast; + +float apply_contrast(float value, float contrastExp) +{ + // Apply simple S-curve + if (value < 0.5) + return 0.5 * pow(value / 0.5, contrastExp); + else + return 1.0 - 0.5 * pow((1.0 - value) / 0.5, contrastExp); +} void main(void) { vec3 rgb; @@ -156,6 +166,17 @@ 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 + * Convert 0..2 contrast to 0..infinity; avoid actual infinity at tan(pi/2) + */ + float contrastExp = tan(clamp(contrast * 0.78539816339744830962, 0.0, 1.5707963267948966 - 0.00001)); + + rgb = clamp(rgb, 0.0, 1.0); + rgb.r = apply_contrast(rgb.r, contrastExp); + rgb.g = apply_contrast(rgb.g, contrastExp); + rgb.b = apply_contrast(rgb.b, contrastExp); + /* Apply gamma after colour correction */ rgb = pow(rgb, vec3(gamma)); From patchwork Fri Dec 12 00:29: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: 25526 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 F3D9FBD1F1 for ; Fri, 12 Dec 2025 00:34:00 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id AE2656168E; Fri, 12 Dec 2025 01:34:00 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="UKZjV2bW"; dkim-atps=neutral Received: from mail-pf1-x434.google.com (mail-pf1-x434.google.com [IPv6:2607:f8b0:4864:20::434]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5AD5561635 for ; Fri, 12 Dec 2025 01:33:59 +0100 (CET) Received: by mail-pf1-x434.google.com with SMTP id d2e1a72fcca58-7e1651ae0d5so592205b3a.1 for ; Thu, 11 Dec 2025 16:33:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499638; x=1766104438; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=YOU8yzvJmLe2CYSAv2DGpWHlxVqrCoB7v5e5gKZ8hTI=; b=UKZjV2bW8I98CMbqU9UU0SXvuor5D95dN0syEzQU5fZIf2YDZWX++3kYcs8WJK8V2g uoljtstZA5jPF2kXkJAxcSTYPnT/3NMtuHR9EHvmATIwMLXHkYsrGVNREPqnHuwRhAEK dx4juGdzfJLGHyOB9noHJTshAEv8JeSA+FtlpzIgfs5VtjPaYvSvnZ6PP/3DJKvTa/Hm kZg/hRtQUA0F5W1w4QMnzXl9TJvodNgDCXNPq8L0PoJJyMiVDhYko0PKBtNDuAUjC4Sa Inz+aG4i9qAEcUHH1QSZWoLYkt1OQsvQ1hyv123aMIpFtkeDFIf4GU9er8b/qc3W4Ueo HKGg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499638; x=1766104438; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=YOU8yzvJmLe2CYSAv2DGpWHlxVqrCoB7v5e5gKZ8hTI=; b=lvqhgVbIlaPFqlw3yK9Hms3kln+X98Yfm6LuzPw9rB2CtN2cwRKK6BOufGycpHlYkR zu+R0ah5BG8ixnJ6IhfYaiR3TX/lKzRN2uB6gWXk4LmMZkXvWkUzwO8I0JWth2JnGSpm naUqqETawmbZhwDE6skjCWQtYSAtYxbhxCRgvgnHeDc+JzQO9t/BjxQVAxvDPtxEgAL2 Ltn4At5W9nPbikoFoXKWqGz5+IPM0Bo35LHAOPPnMhevNK+MqIw+m/5dADYAFe2WmN45 qdqkfb0pQ2bVdLrNsR6+WFTwySRsr/BAzAesuSsgEbqJnOSW9qxT6CnxsO6hA1CBMIwy FndQ== X-Gm-Message-State: AOJu0YxBUFnD57DZ02E/esLIp++dRzqUanJ0ehJhoH496plQfuzvoyFB 9Oqv7qdwK1zGXc9lOmD67vYAYtf4s2+SHfoQ+NDGj4dppau3eLdP7DeraJgVqbt1BQ02PAc6Oy9 Ia48N X-Gm-Gg: AY/fxX58hBjys3Ysec3bYSCGanTFQa4pQZCbjoYV3jvtyTQz4q8R5cQGP/Xh1EpE+VC jLgw29DM6UaXqNGnfFKXuVuAcL+Hj0ZWplDCrbbJM1Wg3q4BvQ/mwHuXX1yhwLuc2eUQfTUnYM+ vprs682Ek31K7ZpP7BOzLUuUM8MeBbbpMtkLoVX4eIl3a+HQEgAs9c2VCKonBPwP1KO4dJc8l6G UsD0ad9lJwfhI3p2tmanROl6uFg5mGHEe77o7xNwecJdACF0PG6RXNOc9McCP3ktFXAcQpaLhy7 aalfxLyJEtvqQ+azNL+kJH1oikoMLm+zcqC8LXYN/ku+UQVpIDqOo811r/qBvPTK3uKGFXxoRU3 C0/qba228lkDaj85p39rXg/r3g/oSJO2z0w8GCP/mkOanOdw/m0lbz9F7sKLG0EZbujYkaPOp87 hJJ8IWROxemSw5oriuKboAC/driV8lAx2mcynPR/KhiP+dKj9kktow6UPLx4Neyhlupu80Jg== X-Google-Smtp-Source: AGHT+IFIIWBdUJzKJq6CiCUmgDW+Ea3qewSygyNDvKXn75MGxofk0dZMGitPRC3Qs21pV4VrgethqA== X-Received: by 2002:a05:6a21:6da2:b0:361:3311:322e with SMTP id adf61e73a8af0-369afa029dbmr289599637.46.1765499637670; Thu, 11 Dec 2025 16:33:57 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.33.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:33:57 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Hans de Goede , Milan Zamazal , Bryan O'Donoghue Subject: [PATCH v8 11/26] libcamera: shaders: Fix input sampling when width != stride Date: Fri, 12 Dec 2025 00:29:22 +0000 Message-ID: <20251212002937.3118-12-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Hans de Goede When bayer_unpacked.vert is calculating the center and x/yCoord values stride != width is taken into account for x/yCoord deltas since it is taken into account by debayer_egl when setting the x part of tex_step uniform. But it is not taken into account for the center.x which is just directly copied from textureIn, leading to the input width sampling covering the entire input stride instead of just covering the input width. Use the existing and currently unused stride_factor uniform to pass the width/stride ratio and correct center.x for this. This fixes the misrendering seen on x86 laptops which is caused by the CSI2 receiver there requiring a stride which is a multiple of 32 often leading to stride != width. Signed-off-by: Hans de Goede Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/libcamera/shaders/bayer_unpacked.vert | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libcamera/shaders/bayer_unpacked.vert b/src/libcamera/shaders/bayer_unpacked.vert index fb5109eee..423dde0fa 100644 --- a/src/libcamera/shaders/bayer_unpacked.vert +++ b/src/libcamera/shaders/bayer_unpacked.vert @@ -21,7 +21,7 @@ attribute vec2 textureIn; uniform mat4 proj_matrix; -uniform vec2 tex_size; /* The texture size in pixels */ +uniform vec2 tex_size; /* The texture size in pixels */ uniform vec2 tex_step; /** Pixel position of the first red pixel in the */ @@ -40,8 +40,10 @@ varying vec4 xCoord; /** of the adjacent pixels.*/ varying vec4 yCoord; +uniform float stride_factor; + void main(void) { - center.xy = textureIn; + center.xy = vec2(textureIn.x * stride_factor, textureIn.y); center.zw = textureIn * tex_size + tex_bayer_first_red; xCoord = center.x + vec4(-2.0 * tex_step.x, From patchwork Fri Dec 12 00:29: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: 25527 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 8A293BD1F1 for ; Fri, 12 Dec 2025 00:34:04 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 408056168E; Fri, 12 Dec 2025 01:34:04 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="tS2Sclc1"; dkim-atps=neutral Received: from mail-pf1-x434.google.com (mail-pf1-x434.google.com [IPv6:2607:f8b0:4864:20::434]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 59D74616A1 for ; Fri, 12 Dec 2025 01:34:02 +0100 (CET) Received: by mail-pf1-x434.google.com with SMTP id d2e1a72fcca58-7bb3092e4d7so736513b3a.0 for ; Thu, 11 Dec 2025 16:34:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499641; x=1766104441; 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=Gq8OF1ZTHYJ405oahlUP/ID9xX8JXtEW/1dvjN5qFO0=; b=tS2Sclc175vHGHUF9PKqXZs6kX86O2IXeEta+13JIuW7agr+0Zj6oQn1eenl5uA1Yy pKP5vArUnQmeYLaSOZx51a+jO9GMad8V/YYZZaG9LU+bUo4NuJu1rUEpaOgrSM7K2iAM v3NkKVrCtWNL9UZtJ9z63sV1/M2ghdDxMLJW/eyczVy0ceFjh/2Qj/yIAEB4cUWGFc6E r1buaJknEYD2QYJZPwoUK6EA289145vjZbTENnJN+l9of1BS/pJqApQ/annfsgmuXSgJ alycR4NNJv7B1ueyBq1GTuzujJPBqFlkpxmLJQX5vMLdnFzxaX8eCa+ZnvYsXdIVeXmJ 9Dng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499641; x=1766104441; 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=Gq8OF1ZTHYJ405oahlUP/ID9xX8JXtEW/1dvjN5qFO0=; b=utWBnCxpXh2Y5ohTokzyIHRVw/kOJ0UefDFLAN/ikpyqXZvw5NNyRXWCc9lJOpJpZ6 bdMCWj3oebnRi0lIyS3p6ZfbJOg8JgH26gjoJNZ11+GdS+Ph8Yqc9ceNsqKBYOm0be26 rHWTd8wrXvt/eyY68SDx+Gwj8GArvnb/UqoJKLxJOJ9nTkZE2NtQaKzyo+jLjd/zkq+L B3BR0qlOKVtZCapFm4QoQNRHEanrPcSbsdbuTp3DbzDvF3dAVzgGLlhi63rtwmLUx4A0 4tLYFPMZzvNCj0r3Wc3vZh5pnnhFKsJVsxNACXnyTEqZaFTiwQ8EjrrB08OoiSu5dGhi ZMqg== X-Gm-Message-State: AOJu0YzzVp3GmKRccNZ6cMLUQ4s0k1by6JQMg+cUPqIj/laHcULLgpKG ReAHZxfQZBxtfLrSPSZFvAbG4ZVLX7sRBVZzIBryRZVt9rwNOhyrX7+z6WOYeD/GNIc5buVBh0T E5/Hl X-Gm-Gg: AY/fxX7GT4sZwljeQRvkuw1ThO0PCqjsb+Vko6rv6cBar4F3g6ltaR+fMG1hy8LPN/9 XkPmu8KY2BgcDmGjHADQZoVcmtHZ1hBnhAtZ3vQKoaVnwFHhN1a+gM3GcU+bcAgKzkrS/TDk1W2 IvTgsiHWyaVzX+HGBVGi4muWBc4m7SvpIKfzmVsvPlK/09X7w6bA0+dPaN77gCRPYzXgAaJit/w HBSlBdahaL73Gn0UuFPy88COq33Z0DL6+GmfP7E7hguLTn/EIhwnkgmMaJpewrdbKrKKoA4SyjA QjNEMiNSd37zIqF6F0mbXkpB/ARCUncK8Zhmcd8QiPmhks0MoAUqD+TDq/817OBKV9b5zFjihG6 YWierXKxjSccFT7fgCe5vRjmQuUBkh2Vh5/H5kY3ZEunsrE8C5g/UJYuSRdRhoi9nNg8P3qp32k sivjj+e2E2BBK+PzNYbLyHELK/4NQwmqYTOOpJGFVsK92/10sm3dDo9+MGWx4= X-Google-Smtp-Source: AGHT+IGJw7ktuIRIhe011Q+dRTO1PrrcDwX/QttGohTh9LcfK/+2oAzm2Jfh1IUVvAPlvkjpzDh5sw== X-Received: by 2002:a05:6a00:2883:b0:7e8:450c:61cc with SMTP id d2e1a72fcca58-7f671f413b8mr260249b3a.60.1765499640694; Thu, 11 Dec 2025 16:34:00 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.33.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:34:00 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v8 12/26] libcamera: software_isp: Add member variables to track selected input/output pixelFormat Date: Fri, 12 Dec 2025 00:29:23 +0000 Message-ID: <20251212002937.3118-13-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" In order to have Debayer::start() tell the eGL shader compilation routine what the input and output pixel format is, we need to have a copy of the selected format available. Add variables to the inputConfig and outputConfig structures to allow tracking of this data for later use. Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/debayer.cpp | 10 ++++++++++ src/libcamera/software_isp/debayer.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp index b5b99d390..4e6fa3d74 100644 --- a/src/libcamera/software_isp/debayer.cpp +++ b/src/libcamera/software_isp/debayer.cpp @@ -290,6 +290,16 @@ Debayer::~Debayer() * output image buffer. Set during stream configuration. */ +/** + * \var Debayer::inputPixelFormat_ + * \brief The incoming pixel format + */ + +/** + * \var Debayer::outputPixelFormat_ + * \brief The output pixel format + */ + /** * \var Debayer::red_ * \brief Lookup table for red channel gain and correction values. diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h index 5c0cb3914..4a2ec3e53 100644 --- a/src/libcamera/software_isp/debayer.h +++ b/src/libcamera/software_isp/debayer.h @@ -75,6 +75,8 @@ public: DebayerInputConfig inputConfig_; DebayerOutputConfig outputConfig_; + PixelFormat inputPixelFormat_; + PixelFormat outputPixelFormat_; DebayerParams::LookupTable red_; DebayerParams::LookupTable green_; DebayerParams::LookupTable blue_; From patchwork Fri Dec 12 00:29: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: 25528 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 EDC3DBD1F1 for ; Fri, 12 Dec 2025 00:34:07 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id BB29C61858; Fri, 12 Dec 2025 01:34:07 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="c/+dED+h"; dkim-atps=neutral Received: from mail-pf1-x42c.google.com (mail-pf1-x42c.google.com [IPv6:2607:f8b0:4864:20::42c]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 720BB616A1 for ; Fri, 12 Dec 2025 01:34:06 +0100 (CET) Received: by mail-pf1-x42c.google.com with SMTP id d2e1a72fcca58-7d26a7e5639so696354b3a.1 for ; Thu, 11 Dec 2025 16:34:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499645; x=1766104445; 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=5JFGAxxzJIIeX87u+TLTHc8/im0W2ElWoVY5etd6y20=; b=c/+dED+hbNhDzdbofAzW7YCbSH938RuzaUf5/ob0yeS+6T77NLI5r8XI6YCEfdMmFy 8T9SNqfHGoL1XDnej8WMrtUDYciwK7xqD4oMncrk/pYTePmBAPv0VbgI72Do82/NL1tP UWHbiaOBOLK1Gr1FbQbMAbHawXJC3vNEiaBNHnXpigE3555tUX5Gxt6GyPMLqdmGKrlW kDdVhkINBinPYsrGe6vCU5Oxlm6Db8wVJ1R7MtRC6hhPEVuEfpWB2nLp9R0zENuOSb5g DpBTGgRYou+smiqJ5g8XTR3gpO4BchoPd4/KeZ6YSBlEeqsdpwJoMPpSOcw7a9gCA6AZ P1wg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499645; x=1766104445; 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=5JFGAxxzJIIeX87u+TLTHc8/im0W2ElWoVY5etd6y20=; b=pFGOEYnd7xho8PJZ2vmIXploc0VqaaEhhZqUcZW4jN5+ITmYpd5U8hxYPOcEtqoQOl sUWJK3BPCQxBre11gxHzn9zM4mK2zU8JSWSxpQGgRledh9G0xAzJPbqm/rQ3HPmsYE1s 3Nw4FF5eyZ+JC5dEWw+gdWBW3L6pKPfVpuQ7lad3TKtLWhjZla2o7DXK6BQORraVIq8g SxK/hAJ+IA/jk7MwmPOvepJMJKgTJOnJmXGtgMJw6QYiS1NYaXy8r36uUs4LMloytC24 K2h3thzl+Iz8mNIZXmDPYGWIX4ATgwUtcewM5uzlok+f2HGIyRFMLjfL/Q7ctFao+5SE nBXw== X-Gm-Message-State: AOJu0Yyp7dWOHXPaEU9wwMlvRyyWziJAUUiE3BcgW6X4z/QP6iDpuoUu DClVG2qgnoEAIvA+Wzj+aMLsRpDBsfXtPYExBfqMZdzcarH9IB17lLYvxuuXVovjp/h3HY4rJsv 95nGx X-Gm-Gg: AY/fxX7bgEGyF86YIwTPTIIvgWwiQbQpj39UcXNgAD5qI3TMCQmiapS5S7sj1UhVLdd zzu3dYAu9ZlXgfdF8RJLUY0+lr8YtTT7rLuxGdfShgutBL6f+/rFe6Xjlv85vZT0NTKRC3NBHWS 5puRC0a6b/0az5glWk4vCZM0dRVhOAN4UOVZwZFvmKjxraUre0vkT3guTpJBnJCMtPEbMT9Kl4n Zgx24dac/IEEP82KRCpNxA53JivOyxJSXwIJygCRdyBPfjr3BroyKJDk7Sp41MSZzQ7tAHlY28m Eg9dKuSqNQ6OKi9KlrKiUIIINTOGhgmKF/yz7/LU5/zcdOh98Dqeq3H63YHlmjImlQKwmHYu1c4 xjYy471vDKd3zBqBgc+nOJmZwOTQruQXXKW/wGLxbUpHokZHI6HqkD8bH3Hibf44rCBXgzfTAQG vrR2sUtDDrTsxfX9/0QK5vWkYlDPFPks1RkUzXgh5sUZoNWcUU/UponrP2u3Y= X-Google-Smtp-Source: AGHT+IE4mkIVKrnH5hUkKOXuegBk3Tkiavuosw/pBlMjG2eC05uRiklF8SXuNPV9xAXYiGG4A5+Ayw== X-Received: by 2002:a05:6a21:e081:b0:341:d5f3:f1ac with SMTP id adf61e73a8af0-369b6ab0568mr232864637.41.1765499644805; Thu, 11 Dec 2025 16:34:04 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.34.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:34:04 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v8 13/26] libcamera: software_isp: Add a Size_ member variable to pass to eGL later Date: Fri, 12 Dec 2025 00:29:24 +0000 Message-ID: <20251212002937.3118-14-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" We will be initialising eGL from Debayer::start(). We need a copy of the size data passed in configure() to tell the fragment shaders the right output size. Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/debayer.cpp | 5 +++++ src/libcamera/software_isp/debayer.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp index 4e6fa3d74..feb41acd6 100644 --- a/src/libcamera/software_isp/debayer.cpp +++ b/src/libcamera/software_isp/debayer.cpp @@ -300,6 +300,11 @@ Debayer::~Debayer() * \brief The output pixel format */ +/** + * \var Debayer::outputSize_ + * \brief Output size object + */ + /** * \var Debayer::red_ * \brief Lookup table for red channel gain and correction values. diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h index 4a2ec3e53..189b32930 100644 --- a/src/libcamera/software_isp/debayer.h +++ b/src/libcamera/software_isp/debayer.h @@ -75,6 +75,7 @@ public: DebayerInputConfig inputConfig_; DebayerOutputConfig outputConfig_; + Size outputSize_; PixelFormat inputPixelFormat_; PixelFormat outputPixelFormat_; DebayerParams::LookupTable red_; From patchwork Fri Dec 12 00:29: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: 25529 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 8E3B7BD1F1 for ; Fri, 12 Dec 2025 00:34:11 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 49D0761866; Fri, 12 Dec 2025 01:34:11 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="CB1OC6WK"; dkim-atps=neutral Received: from mail-pj1-x102d.google.com (mail-pj1-x102d.google.com [IPv6:2607:f8b0:4864:20::102d]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 648246168E for ; Fri, 12 Dec 2025 01:34:09 +0100 (CET) Received: by mail-pj1-x102d.google.com with SMTP id 98e67ed59e1d1-3438231df5fso902922a91.2 for ; Thu, 11 Dec 2025 16:34:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499648; x=1766104448; 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=RQa6EYeW0m0FmWOvvOH0Twk6IpKVvczdGv8r4Du2Cik=; b=CB1OC6WKE54GokcDOh8o7Oyskb9gjv7AtgH7t6CisB4//vKvrFGpIKtQ9YQh1VYUWk iZB6wpgEg1K+A/YiCA75k4Tut6kdrwLzhgig0fBxPKkroFOsxU+J2p+cfXY2nq2A7Fdf GrKEyDZSTQaltULDdzp9T4z7tPBcHxPCg3KXNxl5aCTbiXnTX9npC5oCkEC1+rNnobB5 DaZBtJ2oqfPSUnt77AEzuQRX9Di0sbVT4Vgczrq65E7rL8DXJdSVM2FvWW5+U3b5Kvgm fvXygzOQ1iM1lTljoGjGV+olMyFeS7eIixkqTwYsZG3k20ZFpcfFA6+L+C1x1ccZm/3Y CGZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499648; x=1766104448; 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=RQa6EYeW0m0FmWOvvOH0Twk6IpKVvczdGv8r4Du2Cik=; b=t1LVOf2m8ckWrNl/F7dgiEex52GGLI9GqBuOWU3WnPonfZwDdVvFu60omOgTafnHKP UMOYvHXKI9YBlOlvSU12gKFOvmPhnwkS47DGhPulzYX0TEk4TqZJ/3akKIlVkz+REviJ ythOiftQy6Uglba7EMUQc+EVHAoSN8UJJWVthvhSTQlszWhmMnCsXSQ1zOUEjYg1sjLA Ly6GQRiaUSWpWNGuYMyvMgggnlmMDQ5nrLTByUR+lseZPIaqGph7E5/h2N+dCYT//QQr VYOTSV2azmaMsIj9o6RmAK97EjsoUrlmDZbFiRLUWrxEkkzazXj3O9pwH4zFM66nLTre dVGQ== X-Gm-Message-State: AOJu0YyQr7myOlZwAOSln6EYDRl/xIKBGEMiJC8sqNlz85fogTsrfx7s dpQ+RG1o7rXERJQa38QiCOHU0IrYrjW8iUBN89+0/CGBC0+OCD3Bqe9DDQX5hHpfDzDdxTtkhfK z7Pyk X-Gm-Gg: AY/fxX7+UtXQSt+01YcOqY1cEE2hxmJK33axwcB63N7sHEzqEwkFVDeuwfdldiJVB15 dNLSq57XbTaAQMjniqNJy1Z2iojeC8i+09EANUtwnEiSImZzyY59oW1L/zunKbhvAbvSRvegMnP ClduXhxnIpDZAiZCmvX0KjMhLkYbQ4wFxYQZrVhDuYn6+2SUjRHsWydkmeZT06HotT6Ok4hGzqs lRg8/bOfMHk4riJMDJKE0OpcVDf9ckUZeyTktJJyFWP2JehpCEnGZDI4vpVcNl5+UDWgqqk1LXZ o0wmHySV3b3rQrvVR+Ozg2G82kZPF9WFHtArjSX2EnXhADyea5/WtL2794wrZAWp+NeCpKOJfUj tJuPTRCA0lh3kcEknpg96Rd9YTEVKKhU/AJlIYdr9UgREB6eC0kuaoGJ32WbBcjuaFut5OlhgAd yRTXIJW3eeDvNTY1YWclvAoRzoyXCr17hHlyPkoqAV+CnR0kiO8zW2BFq4EQY= X-Google-Smtp-Source: AGHT+IHmJexSDnAiXtytRhzROJauQLUdeePUb5zJQJ5A33zyfHKm2CO4QwBcfeV1YjBYj9HaC6U7zg== X-Received: by 2002:a05:6a20:3ca7:b0:34f:c83b:b3f6 with SMTP id adf61e73a8af0-369afa009e2mr350745637.43.1765499647523; Thu, 11 Dec 2025 16:34:07 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.34.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:34:07 -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 v8 14/26] libcamera: software_isp: debayer_egl: Add an eGL Debayer class Date: Fri, 12 Dec 2025 00:29:25 +0000 Message-ID: <20251212002937.3118-15-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-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..cae7cb227 --- /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 (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) +{ + if (getInputConfig(inputCfg.pixelFormat, inputConfig_) != 0) + return -EINVAL; + + if (stats_->configure(inputCfg) != 0) + return -EINVAL; + + if (!ccmEnabled) + return -EINVAL; + + const Size &stats_pattern_size = stats_->patternSize(); + if (inputConfig_.patternSize.width != stats_pattern_size.width || + inputConfig_.patternSize.height != stats_pattern_size.height) { + LOG(Debayer, Error) + << "mismatching stats and debayer pattern sizes for " + << inputCfg.pixelFormat.toString(); + return -EINVAL; + } + + inputConfig_.stride = inputCfg.stride; + inputPixelFormat_ = inputCfg.pixelFormat; + width_ = inputCfg.size.width; + height_ = inputCfg.size.height; + + + if (outputCfgs.size() != 1) { + LOG(Debayer, Error) + << "Unsupported number of output streams: " + << outputCfgs.size(); + return -EINVAL; + } + + StreamConfiguration &outputCfg = outputCfgs[0]; + SizeRange outSizeRange = sizes(inputCfg.pixelFormat, inputCfg.size); + std::tie(outputConfig_.stride, outputConfig_.frameSize) = + strideAndFrameSize(outputCfg.pixelFormat, outputCfg.size); + + if (!outSizeRange.contains(outputCfg.size) || outputConfig_.stride != outputCfg.stride) { + LOG(Debayer, Error) + << "Invalid output size/stride: " + << "\n " << outputCfg.size << " (" << outSizeRange << ")" + << "\n " << outputCfg.stride << " (" << outputConfig_.stride << ")"; + return -EINVAL; + } + + outputPixelFormat_ = outputCfg.pixelFormat; + outputSize_ = outputCfg.size; + + window_.x = ((inputCfg.size.width - outputCfg.size.width) / 2) & + ~(inputConfig_.patternSize.width - 1); + window_.y = ((inputCfg.size.height - outputCfg.size.height) / 2) & + ~(inputConfig_.patternSize.height - 1); + window_.width = outputCfg.size.width; + window_.height = outputCfg.size.height; + + /* + * Don't pass x,y from window_ since process() already adjusts for it. + * But crop the window to 2/3 of its width and height for speedup. + */ + stats_->setWindow(Rectangle(window_.size())); + + return 0; +} + +Size DebayerEGL::patternSize(PixelFormat inputFormat) +{ + DebayerEGL::DebayerInputConfig config; + + if (getInputConfig(inputFormat, config) != 0) + return {}; + + return config.patternSize; +} + +std::vector DebayerEGL::formats(PixelFormat inputFormat) +{ + DebayerEGL::DebayerInputConfig config; + + if (getInputConfig(inputFormat, config) != 0) + return std::vector(); + + return config.outputFormats; +} + +std::tuple +DebayerEGL::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) +{ + DebayerEGL::DebayerOutputConfig config; + + if (getOutputConfig(outputFormat, config) != 0) + return std::make_tuple(0, 0); + + /* Align stride to 256 bytes as a generic GPU memory access alignment */ + unsigned int stride = libcamera::utils::alignUp(size.width * config.bpp / 8, 256); + + return std::make_tuple(stride, stride * size.height); +} + +void DebayerEGL::setShaderVariableValues(DebayerParams ¶ms) +{ + /* + * Raw Bayer 8-bit, and packed raw Bayer 10-bit/12-bit formats + * are stored in a GL_LUMINANCE texture. The texture width is + * equal to the stride. + */ + GLfloat firstRed[] = { firstRed_x_, firstRed_y_ }; + GLfloat imgSize[] = { (GLfloat)width_, + (GLfloat)height_ }; + GLfloat Step[] = { static_cast(bytesPerPixel_) / (inputConfig_.stride - 1), + 1.0f / (height_ - 1) }; + GLfloat Stride = (GLfloat)width_ / (shaderStridePixels_ / bytesPerPixel_); + 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; +} + +int DebayerEGL::start() +{ + GLint maxTextureImageUnits; + + if (gbmSurface_.createDevice()) + return -ENODEV; + + if (egl_.initEGLContext(&gbmSurface_)) + return -ENODEV; + + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits); + + LOG(Debayer, Debug) << "Available fragment shader texture units " << maxTextureImageUnits; + + // Raw bayer input as texture + eglImageBayerIn_ = std::make_unique(width_, height_, 32, inputConfig_.stride, GL_TEXTURE0, 0); + + // Texture we will render to + eglImageBayerOut_ = std::make_unique(outputSize_.width, outputSize_.height, 31, outputConfig_.stride, GL_TEXTURE1, 1); + + if (initBayerShaders(inputPixelFormat_, outputPixelFormat_)) + return -EINVAL; + + return 0; +} + +void DebayerEGL::stop() +{ + eglImageBayerOut_.release(); + eglImageBayerIn_.release(); + + 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..1bbae5234 --- /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); + int start(); + void stop(); + + const SharedFD &getStatsFD() { return stats_->getStatsFD(); } + unsigned int frameSize(); + + SizeRange sizes(PixelFormat inputFormat, const Size &inputSize); + +private: + static int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config); + static int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config); + int setupStandardBayerOrder(BayerFormat::Order order); + void pushEnv(std::vector &shaderEnv, const char *str); + int initBayerShaders(PixelFormat inputFormat, PixelFormat outputFormat); + int initEGLContext(); + int generateTextures(); + int compileShaderProgram(GLuint &shaderId, GLenum shaderType, + unsigned char *shaderData, int shaderDataLen, + std::vector shaderEnv); + int linkShaderProgram(void); + int getShaderVariableLocations(); + void setShaderVariableValues(DebayerParams ¶ms); + void configureTexture(GLuint &texture); + int debayerGPU(MappedFrameBuffer &in, int out_fd, DebayerParams ¶ms); + + // Shader program identifiers + GLuint vertexShaderId_; + 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_; + + // 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 Fri Dec 12 00:29: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: 25530 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 28A21BD1F1 for ; Fri, 12 Dec 2025 00:34:13 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CAA7B61895; Fri, 12 Dec 2025 01:34:12 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="kefycMXw"; dkim-atps=neutral Received: from mail-pf1-x435.google.com (mail-pf1-x435.google.com [IPv6:2607:f8b0:4864:20::435]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9FB4361893 for ; Fri, 12 Dec 2025 01:34:11 +0100 (CET) Received: by mail-pf1-x435.google.com with SMTP id d2e1a72fcca58-7b8bbf16b71so708990b3a.2 for ; Thu, 11 Dec 2025 16:34:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499650; x=1766104450; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=BO0mMIWhB901RhyMhEcHbc+LWlQiOyKCJvDrt0v6kXI=; b=kefycMXwwyy6vSv5z+Eaxx2I93RrSCBVESS4CwhovwopDTkTlF9cYsTPp0133PzQZW DCR4g9fv3zJ8XoRmp6k0qn46VHsQwdvKD/5Mai6iGnh/63s6DjhxGMAGoCfkMHIls5OY wPU66ZA62JSv4uaC1es5BCIG+roEzlW7GDKj34bpQlBYWMlji85V0FlCi6EpI9gnb4KA VIMomEFbcsrjKGBHz8tDDwdY0/rGHp/zyjJIQ7ZLhGVlP2d9HALKElkW83H8/NJOGtqm YZ5wew6Ah+HVXlhy8z+QQSsBnPF0UdHmTt0IagGathKw319l9MSxXmHPkV5+dPT5cHwQ qMqQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499650; x=1766104450; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=BO0mMIWhB901RhyMhEcHbc+LWlQiOyKCJvDrt0v6kXI=; b=tQHM+Q9W43qvguCNZYoyQTanVtnHNpljuW9PbVUnM3t9yeiB1fR3QM/Bl/iU9HJMAD I85YwZiSf5QNAlWmxTEj3KMfiHeCz2ox4WMzq/zMlw2Dld/8Hz+g7i4zb5140GFupd0z /oQRBKl/kKaTqjCw4GKefkDdP1NQkpgK9b5Q7fTNxztWFXuz4sao9r5h7xzKtP11X+LR UBSTrk7yz6zVTpDzII4bWPs7bk03IM5+D0PWTpj4uvbdUKiHcy6AQCoA7x5mjttysdR5 sbgNxfIlTjDJMtOowgVU55HSIhFUERGrBfwVBC/RG4d2axTDQdoTdWXikxCeDNDlkZ1J 05Hw== X-Gm-Message-State: AOJu0Yym20mPxR6TkMjzWU2LX33b+Nw38Nqe2pC3Mn3G3saiRYcJjGpu zzQwi2/k4bGo9sHqPd5iIkwVIdhj2mdK7nEcg5946n3pyC6KE6EouEE4bMoIU9pUGZthPokiCD4 HL64d X-Gm-Gg: AY/fxX6tDO+BK36UkmJlTyAfV+xzEemoOYbOMjeILylp4xXW3Feiq58jkCO/j9AEYl6 xtHraEu3+mofYHXUA4ws7kQZhx/Q/BPhcZNTaR8DteGPeo5/IykfOYm+vNxSui190+Ei+/IAwGC p+cOdoYkdmKgfTTT9CrHOkv1qJzeSrme3LuEFPo+C7dvrjv8cFT7SsIp4gxBWs8n6b/xZdla9KK wXGyURJSO+pBjIJ+a0a3RDo3s2nC54CifLFF+qfJCkUCGa42OcPfd2BQ3yEjrHQR5cS9SM06lpn HUbZbuldB/3BQYffbYjGN/3E8NgubDKN1521CuQhGblZh88ekeIEiNeKmOAX9CJvUtCmlH9E49w WiLLI+WjHPxYhlLg1aRiYm39STJ6V8c4bK/5/g1YrGMgGY2PmPhvG8cf79SAjyxXPpa+lhSPZrq 7njRKDo8gnSRb5w0zKehKiFH97ZGO/Nu/5OJ/tdvx39XE7lQByI/rpc2nqZQ4xLM54XZJdeg== X-Google-Smtp-Source: AGHT+IGFVP2FsOQP694q5fUy5q61F6m/fkJa1QgQxpkygT+Jy0DKS3Q0omxk4n99ytA3oGdiFrWPUA== X-Received: by 2002:a05:6a20:9155:b0:35d:d477:a801 with SMTP id adf61e73a8af0-369b4335469mr254933637.13.1765499649948; Thu, 11 Dec 2025 16:34:09 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.34.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:34:09 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Kieran Bingham , Milan Zamazal Subject: [PATCH v8 15/26] libcamera: software_isp: debayer_cpu: Make getInputConfig and getOutputConfig static Date: Fri, 12 Dec 2025 00:29:26 +0000 Message-ID: <20251212002937.3118-16-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Make getInputConfig and getOutputConfig static so as to allow for interrogation of the supported pixel formats prior to object instantiation. Do this so as to allow the higher level logic make an informed choice between CPU and GPU ISP based on which pixel formats are supported. Currently CPU ISP supports more diverse input and output schemes. Acked-by: Kieran Bingham Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/debayer_cpu.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h index ecc4f9dd0..67df2b93a 100644 --- a/src/libcamera/software_isp/debayer_cpu.h +++ b/src/libcamera/software_isp/debayer_cpu.h @@ -97,8 +97,8 @@ private: template void debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]); - int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config); - int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config); + static int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config); + static int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config); int setupStandardBayerOrder(BayerFormat::Order order); int setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat, From patchwork Fri Dec 12 00:29: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: 25531 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 07A2EBD1F1 for ; Fri, 12 Dec 2025 00:34:16 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B1ADC618B5; Fri, 12 Dec 2025 01:34:15 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="keuJcyXh"; dkim-atps=neutral Received: from mail-pf1-x433.google.com (mail-pf1-x433.google.com [IPv6:2607:f8b0:4864:20::433]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5C13D6162E for ; Fri, 12 Dec 2025 01:34:14 +0100 (CET) Received: by mail-pf1-x433.google.com with SMTP id d2e1a72fcca58-7b22ffa2a88so698122b3a.1 for ; Thu, 11 Dec 2025 16:34:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499653; x=1766104453; 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=HhtFnWRlGMhahKWMF7YUw5HWUh4rGouum/Sd9bsme4c=; b=keuJcyXhwe0WVbsbG1E0b/XhQEN/5b3aTap4TBhZVyueSp+KX9Z6RxfmHIrAJ/kxiQ 9l6JaNmPGT/s7Rio+RrPGDA4czAxPGVOI4Nmr9iewrOSB8otG89vny27gn66049KHIXH SWMGCL+o+5KrPbzGEeXKBzCR4bkWJNdvBa01HlJuVlzGo1qaaDcc+nqUBVQLUG64Azrq VorMGvt0L3pDoRWxEgk/vY93bvUOepYXIsPuGiz8aMXZruespToPolF63xZIXM2Ylz48 XzUzCFzqi/xQwGdPqPDpw4Wy8cZFATy4KH9jdxaQKgtTmXPB6Au7f1VGyOSZLvZ6U1Rr Dg8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499653; x=1766104453; 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=HhtFnWRlGMhahKWMF7YUw5HWUh4rGouum/Sd9bsme4c=; b=erZ+d7H4DfK6KJkWVh5SY9WztPLIMIM2ZRG9DFjml2+cyy+fp4ZZGV1EA6n1GmF9pV gnmetV1KdgVQhkm0jNL/TfzDhv2P4UP4YKSf15Yma9Ko66iB3F0MV5nn5G6vs3SUWoAV QvjGLbf2s3nmIjNSVHEcq2TFf+7edDUVTU1YGchAHIkH9a0cmtBzPpX+R8v1erTgSqxl nU85ntaQDtysTZrF5lRTvDra0L0GBlga0t8iX5C9NFpoaZuJFpbALnP7Us79aBz3C3bo KLBQClllAIDiahWxTJdFQfpWalI66mbJgXvBfiGqFpnHrtVtfF1J+GsGAUmvN6V7wmvx qm4g== X-Gm-Message-State: AOJu0YztvATsx+kUR7jsRt8MSbG0gaeHbN8He/M1E+9svq67kLgD1inu kepEMW79NgAecOguRFYu2Jf8SKqeBwvofB7Rl8noPM9Td9aFaTBKabGkgJsy2a6+e54FCIzg3Nt mHzOT X-Gm-Gg: AY/fxX7G3TLm9bcau3ksEjQ439AuyVW2vyqFFimFB3JGqh7jbYjW5mqmdDahRwH0F/H Ee3V2TQWe64qRU7XZ4mF+7AhnuxXMa38h2tNz/UUsjgVn0zjYtO2N/mJW2aVxSUXuURAVyPWUAq IOHgCycJ7kgHvORJpnfQZfNd2wyXSrSYY6IC2SsxfIx3UmkVwa4Q4hExNb1g7ZP1B3xosTG4NsW XVsN3tMJnQWGCy9KykDPNXve+ec/ORrTJNzQvtySAtZIkFdBJeGC3bQomlv5Cm+JwTX9vv+fpvN UuhBGT/e3h3X025BzozyIUTFPpSoNb5vHFExSnlx8K/UT/9GKCWHGdCF7NEvkdYJGL3IejfTVH0 Qpe1sRs+dGjz/HYOe5vOMF+htzKeW0cj7Ld7aCNqQLFBmlhwcRgepuAvhBZ5TQkEgEtoFWvZLQg hF4u0AOEuuvk5n0rZYLYaYRPPwwUNPoBZDSzVBOMvhmZdEbmMFFTOkkhtBSag= X-Google-Smtp-Source: AGHT+IHYwr7NAvCQKDR9xkByGviw8lz609WP7GCC94t07QIK7KsFLPIfvBv7OaP/FcuPuepKek7Jxw== X-Received: by 2002:a05:6a21:6d9a:b0:340:cc06:94ee with SMTP id adf61e73a8af0-369affec34fmr320814637.60.1765499652688; Thu, 11 Dec 2025 16:34:12 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.34.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:34:12 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Milan Zamazal , Bryan O'Donoghue Subject: [PATCH v8 16/26] libcamera: software_isp: GPU support for unpacked 10/12-bit formats Date: Fri, 12 Dec 2025 00:29:27 +0000 Message-ID: <20251212002937.3118-17-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-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 114e32058..477e8bbf6 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -41,9 +41,17 @@ float apply_contrast(float value, float contrastExp) 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 Fri Dec 12 00:29: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: 25532 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 8B6B2BD1F1 for ; Fri, 12 Dec 2025 00:34:20 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 547A9618BF; Fri, 12 Dec 2025 01:34:20 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="ujRA0ddU"; dkim-atps=neutral Received: from mail-pj1-x1032.google.com (mail-pj1-x1032.google.com [IPv6:2607:f8b0:4864:20::1032]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4A5BC61636 for ; Fri, 12 Dec 2025 01:34:18 +0100 (CET) Received: by mail-pj1-x1032.google.com with SMTP id 98e67ed59e1d1-340a5c58bf1so448198a91.2 for ; Thu, 11 Dec 2025 16:34:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499657; x=1766104457; 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=qveDztGD+z1bcvRVfeWU9FTU1qkHWCGGVTIxAh2VXQw=; b=ujRA0ddUeT0adfRfxY/sZN2ZFfAZY4M0ufgfA2VWfZyczhWBU3YqRTNLrYhktB0PUv CJmeWO1aHpL5L5M2Wddrog43R59B4TSVRkjMZE8jE4GY/OmpIK6riNx7nrNoNqmpQLXY Z6XnKHx9DEsBoqOxN6EtX3+a3tu6g2JdE8SAx6mQM3Rjb/fZcMIEiv2S/own2iHe/wkp acifRras90WIzOt+kfcCc1XB1swMypT7RKCdFsTheUxKEuV2TMlX3v+wSXZ/ws3zdhyI Et3+4ar2+weYHnjUhIv3NnfeMvQ+46WrNIaxB/FMWRQQyjJhYAaRwc1RSKVeGdfbG5vI GXaQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499657; x=1766104457; 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=qveDztGD+z1bcvRVfeWU9FTU1qkHWCGGVTIxAh2VXQw=; b=nVijrKqCT958oS7DeqOKSEbYJO8cen+gH9lN2B7Vc/udL/sWeVmibDpK2QDY2IpGBH 0xTle0/eB7BwMYUaepPBMfqTF1ZxYXD5A3wuZCnTEVLWg9NuK3u3br/PoVXOtSBwKWIj Z+9VavPCn9RvSL/+lJCBx4OawFlxhhMD5SylRxq1Z10p1sYQscKegNJXAguFKbHds4So c87Cvbxrs1Nxg5gOBF7DVTgEn6XESRhYUDkGG4v3po+01MOdw8qjgM/rqaDbZ/v15YLY kemEJ8n2m2+f/kndBVONHDy0x9xTWiO67BHmn3sIqjKg+j8IEv6X6crg0uJjo/cqrdaZ ZEhw== X-Gm-Message-State: AOJu0YyAmBFt6wbI9a58/VsLvVecepnisBSi5XhcVte8MP471v3X7A62 sCIFSKvU3bJ+c5eyvoBKcVBUltR2mzPNB9olbOGcixunAcTxtEO0B511L1H9I0bz5IlnRemDtmi cHfdb X-Gm-Gg: AY/fxX7fBYdRvV5PrtUK6uXFkVw3/EI0MXEApAcWREG975OCAgtz3IXuQsLe9Tf+At+ Tq8N7RW/mRnPVjtatrDXokMS4dO2Jq77fqZlBZc0XrqMyETGu4MQFCyFB0snogBGtXCClgQn8wy UKVpRfpyIRjuTF7/QBHYcCvb887+qG2A4TZclf35qHdazqiEP/9miBRT0IllG6+2/PG3fmduRsr ATAKnsVr51rFKqJP+gxWNNx13yBHmVWhfA3B7ows23AYuuaL3qRXm9supdPvusocAm1p0fCnIIf Dmx4GHZ9iOhZ18eWOr273RnY5vjcMs6y+2kL54jz42nd9b0ly0vDLeLJiWkIF2lYV4Lr/tbftyb kLpY7ywjsVXSf39ADudwn/+UiJsWRXAKny7Fb6Xa37AYd1SAqlkm0M3QaP1EE6FDtLd/5S+KGqk /ID4zEoGN21b1vKdsYef1fVFi2OZL62t+nKm0fiBD4pDf2eUo08YS4IQ9DaTQ= X-Google-Smtp-Source: AGHT+IHXC9GjiM25nk9JU9k8vtsKsk2M7GHr8WRUwyeexPXBOUZkl8jUIjZ+BhCmaaJbw63hSh6knQ== X-Received: by 2002:a17:90a:d2cf:b0:349:30b4:6365 with SMTP id 98e67ed59e1d1-34abd858908mr342348a91.27.1765499656544; Thu, 11 Dec 2025 16:34:16 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.34.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:34:16 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v8 17/26] libcamera: software_isp: debayer_egl: Make DebayerEGL an environment option Date: Fri, 12 Dec 2025 00:29:28 +0000 Message-ID: <20251212002937.3118-18-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" If GPUISP support is available make it so an environment variable can switch it on. Given we don't have full feature parity with CPUISP just yet on pixel format output, we should default to CPUISP mode giving the user the option to switch on GPUISP by setting LIBCAMERA_SOFTISP_MODE=gpu Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/software_isp.cpp | 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 b31a374d8..efe44e393 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 + std::optional softISPMode = configuration.envOption("LIBCAMERA_SOFTISP_MODE", { "software_isp", "mode" }); + + if (softISPMode && 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 Fri Dec 12 00:29: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: 25533 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 39223BD1F1 for ; Fri, 12 Dec 2025 00:34:23 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id DBDB461917; Fri, 12 Dec 2025 01:34:22 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="Hxf4dfP5"; dkim-atps=neutral Received: from mail-pl1-x62e.google.com (mail-pl1-x62e.google.com [IPv6:2607:f8b0:4864:20::62e]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9C1B361866 for ; Fri, 12 Dec 2025 01:34:21 +0100 (CET) Received: by mail-pl1-x62e.google.com with SMTP id d9443c01a7336-29d7b8bd6b0so4388875ad.0 for ; Thu, 11 Dec 2025 16:34:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499660; x=1766104460; 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=enuSJNXFUuoTYs1Tq2LkRLCCtdszeCb+2wiWiBmGXZE=; b=Hxf4dfP5QFBLhX10/974KgsDZqCzDx6A2iPDJwsC4USIUm07AkCWp/JJ0OyswqEfgN FXbmUqle70Ms1dnspmMhKnA7+E78CwN1ZZpHGK+0JQSvT9vklnXokLrjQ2cqcKflED1u ilcEbXMDIEDgcn2mZ44/PNH8nL2QMoZBiN9cJYnyfhJXnfAFpiHGu4df8Q6inz930nIN EcwJreciPv7dcuX+h4sWPXXooaQSCYjDfpoOE4ICuxGjDCdfnDevUYnhZ/pHpLYaMqOh 2Pbz5WcYXBaIWh1pxJc6qYAcVymaoVEVWxjRZphHfL6Tc7f8dwts7MMaV8Yo+g6u6iLc jvJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499660; x=1766104460; 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=enuSJNXFUuoTYs1Tq2LkRLCCtdszeCb+2wiWiBmGXZE=; b=bwbz4OzYYFufB8fBrRx/esDpKZTqaf2GQo98ezDXjKJ/fYh4q4skviNkjcsY3FgBtZ 0X5hHFDwq+vU+915+Pw6n2t6eAZICEczjcg0IO6u1VZTsOSuu4eDp/Q0GH/jWCSmF9q3 NAWe4hTWovW51Qzd8qOmlfMcW7JnoUWz7q5lIuNILTWjMh8Lo/cTgZGKk4Y+E2pzoiUL dQLdn6iyyzfG8dvB/sb609/72FiMxgWW/PRdqk2UtHj6D9wmQlNEWHXBKvxeIenm67VA NlCU/kUzzCKIvpLevsVLspkYKlXlrMaK2DFPz0dHLHpeLIsxio9WruVtCaVgleg453UL +Bpw== X-Gm-Message-State: AOJu0YxoK0ObieFSElaQ6+Sg8qJi9WI5LTjJGrrJQ93Vvx0H/9KUf5GQ yl2RVlicjD0JJEgckp/j6dJ2eYqrDC0GCElu6tjbwex6hgT35IpfKDjFSHevWtIOJuuj2Mmf2M+ lDAFh X-Gm-Gg: AY/fxX6fcTSy/EJdMAenpwLw+VIC7/cMQQj3JwIHp8IFDQbz/jaPoPzWcsQ4XHDGUKu LEQYB+DGrDPDwpFpTz3Nh2OStS3/+uPSsW1RBAjXbg+u17q0umT7r/XIbLo5TNPt63FMWGjMpXG yMXIsShjm+ZKCCcoc2JfIW2vxF2tV3crlp/4qtfBcEp6beCxd6Gm4zv3uPGguenPlcs6kZ6vAUV iKRSelUDM1QVM/v1a5MHKYuBo2n+sNaDNnPQd6QcH9iDD4tex33iRRSeD6sGfOrAphOgcUwySuj 0GJ/reKnwO1JcjeaAgXk6+GPOnhFJu1oeISovC8UV1CW/QduiUbVO0M1WaCzuycQH+WyoswEh5G /nCSNKXP39wGMvyaKKm5+LaU1YJkiS7D0l3yXKKFB+cDH68BKRlJsY/oCoi9Y4S4YqSZ+kw0qe9 XcgeBtLVmAJBiCM+fDH1FLVkmA7XMbSlw8hFefM8CVK11SB3C98OzWRqPbMd0= X-Google-Smtp-Source: AGHT+IGR5UQuOK5s0Yz6qgT74OAdEzZ0pk/Yc+NAzhk+P3EcujKsroruznjqPlMR2tlfkfJk3aDlwQ== X-Received: by 2002:a17:903:2451:b0:295:5da6:5ff7 with SMTP id d9443c01a7336-29f24e6f089mr3915865ad.15.1765499659940; Thu, 11 Dec 2025 16:34:19 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.34.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:34:19 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v8 18/26] libcamera: software_isp: debayer_egl: Make gpuisp default softisp mode Date: Fri, 12 Dec 2025 00:29:29 +0000 Message-ID: <20251212002937.3118-19-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" In some cases the GPU can deliver 15x performance in Debayer with the CCM on, reference hardware Qualcomm RB5 with IMX512 sensor. Given this large performance difference it makes sense to make GPUISP the default for the Software ISP. If LIBCAMERA_SOFTISP_MODE is omitted gpu will be the default. If libcamera is compiled without gpuisp support, CPU Debayer will be used. It is still possible to select CPU mode with LIBCAMERA_SOFISP_MODE=cpu. Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/software_isp.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index efe44e393..7fde57aec 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -123,8 +123,15 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, #if HAVE_DEBAYER_EGL std::optional softISPMode = configuration.envOption("LIBCAMERA_SOFTISP_MODE", { "software_isp", "mode" }); + if (softISPMode) { + if (softISPMode != "gpu" && softISPMode != "cpu") { + LOG(SoftwareIsp, Error) << "LIBCAMERA_SOFISP_MODE " << softISPMode.value() << " invalid " + << "must be \"cpu\" or \"gpu\""; + return; + } + } - if (softISPMode && softISPMode == "gpu") { + if (!softISPMode || softISPMode == "gpu") { debayer_ = std::make_unique(std::move(stats), configuration); if (!debayer_) { LOG(SoftwareIsp, Error) << "Failed to instantiate GPUISP"; From patchwork Fri Dec 12 00:29: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: 25534 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 C707FBD1F1 for ; Fri, 12 Dec 2025 00:34:26 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7AC38618CD; Fri, 12 Dec 2025 01:34:26 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="Pg/UHHji"; dkim-atps=neutral Received: from mail-pf1-x430.google.com (mail-pf1-x430.google.com [IPv6:2607:f8b0:4864:20::430]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3AB8861899 for ; Fri, 12 Dec 2025 01:34:24 +0100 (CET) Received: by mail-pf1-x430.google.com with SMTP id d2e1a72fcca58-7b8e49d8b35so864792b3a.3 for ; Thu, 11 Dec 2025 16:34:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499663; x=1766104463; 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=MPqMdgKkALoqu2kv8QWwW4WzZZNyfJxOyfa02dN1G2U=; b=Pg/UHHjiTbPGXVgBTnCt1bgYe4y5Cun1IoYWKK0rbbZnXUF5NjQEzTE8ELUTVF3KCL Dt13N0WXdsMketax1/5LNZ1nOI2dXpSa7Cqjnjd4q/LE5q7xYnl0pxlekyhTsiy/j5IU pmKcVMXrRhHJfMc7KF8Uk/qZtXCUEddBCaK/sXcVEhrSanvrSVfaNxqsNmZHpc4C49ex hJZi2FsC9Z+3XNyDqHEK6wKZOewdn7eGQUOk1LdDmBUc4HgLatzr2kbBsTfetOoWYdkj lwFU97i4Ie90RqJY6O/xdBShCKmzu7YbCZiaTe8ac/BAXVXVsFeaaQspkrO1bufs9nxZ Yukg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499663; x=1766104463; 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=MPqMdgKkALoqu2kv8QWwW4WzZZNyfJxOyfa02dN1G2U=; b=fUpOhDHMlCW+as25slvEiMxFhSir5eHHhnC4DQMcp1GeVGIqzD6XQSKA5T9XY6nxKm kcVM5ru+Mhq/frkNQRXHl2kYaIJF3gO7A3Vt5aYr3t58eobOvEHDqDR1JqIDzV5dKeiJ BMYx/6Y3PBVk9XFAkSV26QsP+o6wFUXccQcpdX10lEBl/PgnQ42CBbNzi0F/7j45vUZc enYhyhKBNNDFkjnrnjqztAKlJXsSc1/HzsyX/x0vhn8ld5rBj0vnc5KqzZvfkvxi+z0M PAsA2UdDyWCgZZ9EIcxAYKOhWYaPM1HHjZly7fc4MUxkC6UBTwiLGeeOiGJIZmxrNXU7 /Uvw== X-Gm-Message-State: AOJu0YwjZlG5ANn50JzUKiwhuHESTzh9Gx5c66QrWXEgQqG0UAY6mtMC 7vpzbDoLv1xN+qrxVENAEjWBMi84w+8NgwcUZ15DBnyG4EKtlEraRRFGQq2qXB3Vfef3d1BdJp3 AoGZf X-Gm-Gg: AY/fxX7fFGh3sZXtdWGA/pgV9gwnj3m7aLGCVScx7HzzMlOsiX7VMfSz8KcofelDGFj 3hQoFlQI0H89BhkziUsdE6cs0EwBPfOVt+Xa8ugxpgM/H3gKOfw+svui/z+evzI5rcngnDCNfoi p3mipZZzCkRZmLliGb52uP8KZix+RPdcy5bvnXaDT5tVeJ2ffWqmPJTF0tqIX/2QYIhsqs/R3yl YpKqpVkjmpUVGtWVx3b8ufrfsoOr8M6bhdh+AaaPwX5Veo6vFPCDYQhamMxAh2sgTafD/ymLml+ L+9QvgnQ+2N+XC+lTpcROi1FRyX9ZFCNpssk4f1oETUGNVgN1nl8ugLouVnBpyv030uhsMqyrDo PKLNdSZ8EhDJiDUuvHdTwTcQ2Msp+oIYdneP3Mv0wuQZFDvSdpoZ4OVqx0Ra76M7/yasVZM0liN r6UZW54Qyaif7Y3Z3veRd2AG87As5b2RRB/wb+c+xbkkxCbIUMuhTaoB9UAtg= X-Google-Smtp-Source: AGHT+IEgnEyWvr7t2SmHGHEvCM5Lfh99Q1bYzWWLu+3hfpG0ENZoihbVF9z4yICm0OS5BPVmqHJKfg== X-Received: by 2002:a05:6a20:d497:b0:35f:5fc4:d88a with SMTP id adf61e73a8af0-369afa09e22mr262162637.49.1765499662518; Thu, 11 Dec 2025 16:34:22 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.34.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:34:22 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v8 19/26] ipa: software_isp: Add a selfInitialising flag to IPAContext Date: Fri, 12 Dec 2025 00:29:30 +0000 Message-ID: <20251212002937.3118-20-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-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 flag when true indicates that an algorithm should self-initialse instead of consuming YAML data. Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/ipa/simple/ipa_context.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h index c3081e306..03d8007ea 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 selfInitialising = false; }; } /* namespace ipa::soft */ From patchwork Fri Dec 12 00:29: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: 25535 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 6C10DBD1F1 for ; Fri, 12 Dec 2025 00:34:28 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1A6B561918; Fri, 12 Dec 2025 01:34:28 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="DDIGjP5g"; dkim-atps=neutral Received: from mail-pj1-x102a.google.com (mail-pj1-x102a.google.com [IPv6:2607:f8b0:4864:20::102a]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4A87B61919 for ; Fri, 12 Dec 2025 01:34:26 +0100 (CET) Received: by mail-pj1-x102a.google.com with SMTP id 98e67ed59e1d1-349bb6f9c86so906052a91.0 for ; Thu, 11 Dec 2025 16:34:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499665; x=1766104465; 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=VNUHfHpg2M2YuqSAMwLvCr/seKArsWE4nrFMPIDyMeI=; b=DDIGjP5g8vXnNnIboMRfaez2sa9Cc2WiFylh1L0Mn4XXWQhWQ5idRk646XvXPNPqzP V3TScyOsdz2zln8PCeXuk3lAKdXTXPDdyNP7U4mzbT7BeVjtckQ9+E5xy9kZD75zTRXY K5z1GhhRgMNcTG5xINnT709pa10pGWazkux7MJQIEJhV2zW6x8GUpkvhUB6YUN6M9z3z j0cmK7zs+apmOAG+zydtLq36MtwnR7pZuNT8bxC3Zqect4ZfX1bDMiGx/V/ciMXPBKgj PK6VB2fjPVioaoPtSROOH1MmrLP/I8uLej+Wx89jZDPT0mzQO0XUQRnQtANjmBfea/E8 CBsw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499665; x=1766104465; 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=VNUHfHpg2M2YuqSAMwLvCr/seKArsWE4nrFMPIDyMeI=; b=N/hD6CMZKVcsr2/1ViYsYPRJ5eDGvd+x+NyUhQiM82MeQbIexiLb2K/9AH4/mS75pY wvjU70sKsvboLMAtkHLUEhPZOQOz3tnRrXOb+VNGads/5nhsHNiWv+26gYb60tvmqVkv 5tjTNAWyaScKKUZz7Rnged8VP/K53yCF8PoGRDtRhKwrvpdyzALdaW03nrnNdIghW9bg FpsMfnHJ0pND8ObRGykz/Ca3zloXccMTXxpMCxnPoMMxDTZQtl1uFX44m3jUi2YKR2dw lFJ4/mTUI66wKOKrLTGxEI50LeRHy4Ku1vo0BrSf8u4f0el+RqjM2RBXV/YFvBOZ8VrK KZyw== X-Gm-Message-State: AOJu0YwV48rj3FCKlM/A+G7kBrBPdY/uox+IHdn9/tpSjJJ7b3o/YIeq 2xBmzTx/VAzxG131smAlSONMMy9fXs2UYH0XCyr+jrwHSZnToNPfgpExL+rdQizgPbPnqeSodFD b9LGu X-Gm-Gg: AY/fxX6ESlWtTwe+Wo357UvvOn+09RnECSD1izMatU6Ch2jsTDxvoI4eWdsoMFi5jVi NdXJGaKJi7NWObciiT/ELXVNRSeUm/h4PmCgvjbPRewtptV+4ERC92qUJ5cVYp5UspLkOpPeMYf 7o26MYUzQynLNLmInUgexejBZZg7/K9ewmhzCozqL7RBKgpTFyEFCG4CnWTw3ZNyfHFY1jQYmFr 171W+3bJzjHMRo2W3zpqa5mX0o7FsC0rPMY2CYu9X2/Uo/d1ogS/tD4dzUZ+Ix5wKQh2gejIpX2 vCNlzEwJb4FVq77DysKb3Pllb5GdLphF9axxaWzQ4UfN4y+Vxw2QnQ+5u3TWzO+FkVPnijmKPM3 3/RF8QK3P8vTv5AsGoBgpLgfQcS18CL3IGNthm+MNeH8bozRLY067m/tDDbHYzcEyXjAm03CTFV UvW4YCCbIjCjnilgWH5l9lvhgGtj3YI8pRkQPbFblOWUHwSC3nLjAxNzrrynw= X-Google-Smtp-Source: AGHT+IEDcm3QWbbIds8HOaa4svhq96gjtcENALL1wW0LShvBqpU9crGiMP+ZpRZRMBRCo3anVrAERQ== X-Received: by 2002:a05:6a21:6da7:b0:34e:7bef:e820 with SMTP id adf61e73a8af0-369af90821dmr281696637.41.1765499664583; Thu, 11 Dec 2025 16:34:24 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.34.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:34:24 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v8 20/26] libcamera: software_isp: ccm: Add self-initialising identity CCM to Ccm::init Date: Fri, 12 Dec 2025 00:29:31 +0000 Message-ID: <20251212002937.3118-21-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-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 have a need to generate an identity CCM when running the GPUIsp without a sensor tuning file. A preivous patch added a selfInitialising bool to the IPAContext structure. When that bool is true generate an identity CCM at colour temperature 6500k. Signed-off-by: Bryan O'Donoghue --- src/ipa/simple/algorithms/ccm.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/ipa/simple/algorithms/ccm.cpp b/src/ipa/simple/algorithms/ccm.cpp index 0a98406c1..ac1ce1685 100644 --- a/src/ipa/simple/algorithms/ccm.cpp +++ b/src/ipa/simple/algorithms/ccm.cpp @@ -27,13 +27,23 @@ namespace ipa::soft::algorithms { LOG_DEFINE_CATEGORY(IPASoftCcm) -int Ccm::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData) +int Ccm::init([[maybe_unused]] IPAContext &context, [[maybe_unused]] const YamlObject &tuningData) { - int ret = ccm_.readYaml(tuningData["ccms"], "ct", "ccm"); - if (ret < 0) { - LOG(IPASoftCcm, Error) - << "Failed to parse 'ccm' parameter from tuning file."; - return ret; + if (!context.selfInitialising) { + int ret = ccm_.readYaml(tuningData["ccms"], "ct", "ccm"); + if (ret < 0) { + LOG(IPASoftCcm, Error) + << "Failed to parse 'ccm' parameter from tuning file."; + return ret; + } + } else { + /* Initialize with identity CCM at standard D65 color temperature */ + Matrix identityMatrix = Matrix::identity(); + + std::map> ccmData; + ccmData[6500] = identityMatrix; + + ccm_ = Interpolator>(std::move(ccmData)); } context.ccmEnabled = true; From patchwork Fri Dec 12 00:29: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: 25536 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 5E0B0BD1F1 for ; Fri, 12 Dec 2025 00:34:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 13C3B61921; Fri, 12 Dec 2025 01:34:30 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="xBrRAmmE"; dkim-atps=neutral Received: from mail-pl1-x62a.google.com (mail-pl1-x62a.google.com [IPv6:2607:f8b0:4864:20::62a]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4A5C96191A for ; Fri, 12 Dec 2025 01:34:28 +0100 (CET) Received: by mail-pl1-x62a.google.com with SMTP id d9443c01a7336-29d7b019e0eso8862715ad.2 for ; Thu, 11 Dec 2025 16:34:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499667; x=1766104467; 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=Ycci6C9edEvwR+DeR6OxjWNs4OeJb37qDGnfoes6rM0=; b=xBrRAmmEWsKS0SOk0kiEfngpGxlOBxB5EHGFNh0L8c5ECDz5c6A+d31VXDqQH47Xdx hWkdJhnnQl337BSZ+D6RuQvzkkE0JQezKwosQj93hm42HH91VL1EVZrtoqOK+yfwhpVw pHuVKgpDL3W1j2dygYILxJZ3RKSnDHUReCNRutbm0ciQ5eD3EX+qZER2RPwXi2sV0l3p oM/QYDoeF/Y+A3Vgp1q3b+y0L8ON0/ubMW0/LLjqwt1lPyjtvM7864Tnq3mdkmB1/C3B D6v3I4FH8o33csl0CPzsp51ico2EJR7rSYi/8z4d/w2IXfdAfVULIQxUBLlX18pTP0Ud bpqg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499667; x=1766104467; 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=Ycci6C9edEvwR+DeR6OxjWNs4OeJb37qDGnfoes6rM0=; b=bgRo8/mhISEELJJdH9lX6yVvb283Of9ElFdy7jR3A9SX1cNexbEHxIkRJ1nAcieyY4 vPg3L1LiqdOAQ30aCh3Ky+/r5wpJcX113nHMWFpqbY+15iAx5H1A6JaqG16u8Fyazbct pb0nu5/PbTC5OusQR0ZtMD3ID5ZsW/QJF6lipi9bo+8q9c0Ivj4yjNmAPLu51gjFdRjd uywAAq8lj3jXfQGyVBarJ+aKh3lUBgrSkoeLK+JTIWytMrVE4RSrZ6Y/4MicfPOTKmzy I1GqHYkjacX/qkYhja9BB5t8IERQ/XZiWrhMiz/yxz9DG3M84/cm4qNKqpsg5M+4QwEG hSPg== X-Gm-Message-State: AOJu0YwhASMz3MTn1MJL5TzFW1x3CXwqW5WfEO1PF9/5fr86wGPWLd8C tytpYZRNMyed0y7l2NzZfxNF9KG5VLk+9DHuSLAsLlYy/L3fer1p7eqgqXfyookUk9bsmn14RHk rg68K X-Gm-Gg: AY/fxX7XKTii9fpnawheHFmw65cke8/GvLBL3tUA0a7328qOctsvvHNSIKHtJd6v51Z H3PxqE1q9MvVEIVTrBi7s3P1lxexAsdQANFW4G15mdM+aHDn0rNsO1fez2MK2XkH5qoVUvrUbO6 P18YelX2VeqTnDMF9YflFhR5SSfHCymfOvBLVBIwlEFgXty7mGZXPx+br2DVI3eB5Ie9s1SZ9gH hJgXRNXJmwxV+oGLcHn0ZxwsVbkLD2LMSmJqNkWsIqttgoY9IZwTFTiRJMPP/VHEfkdQLJUttzJ cCcTBwUpjikdM5USbLDiiGHvrydXdZeDih0WesY3lVayisL0ccZUSMyhaGk2YJydRgxQaeTA8Gd SjeO7/Jd8tfg3d1QPConUcB53GdbjuT6LoF6AfBZx8q19MOzZjBUgS0hbIrLWo7f5cEqj6BwUmm ZH342I3UDjULIRRbQbeTKsycq4s3m4dxGivFqJ94M9HB5bR/dUzPRJyiUVszE= X-Google-Smtp-Source: AGHT+IHV5VCJNqj3JYE+QpyY+8THgMODQGOIohct7Qg7gtevkrlR94MTuRVkrwofdF1NkhLnAEzSVQ== X-Received: by 2002:a05:6a21:e097:b0:35d:8881:e6ce with SMTP id adf61e73a8af0-369ae1a9b3fmr288711637.26.1765499666503; Thu, 11 Dec 2025 16:34:26 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.34.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:34:26 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v8 21/26] ipa: libipa: module: Add createSelfEnumeratingAlgorithm Date: Fri, 12 Dec 2025 00:29:32 +0000 Message-ID: <20251212002937.3118-22-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-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" Create an algorithm without having YAML data input. Signed-off-by: Bryan O'Donoghue --- src/ipa/libipa/module.cpp | 34 ++++++++++++++++++++++++++++ src/ipa/libipa/module.h | 47 +++++++++++++++++++++++++++++---------- 2 files changed, 69 insertions(+), 12 deletions(-) diff --git a/src/ipa/libipa/module.cpp b/src/ipa/libipa/module.cpp index a95dca696..41235f902 100644 --- a/src/ipa/libipa/module.cpp +++ b/src/ipa/libipa/module.cpp @@ -83,6 +83,40 @@ namespace ipa { * \return The list of instantiated algorithms */ +/** + * \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 + */ + +/** + * \fn int Module::createAlgorithmCommon(Context &context, const YamlObject &algoData, const std::string &name) + * \brief Common helper fucntion to allow createSelfEnumeratingAlgorithm and createAlgorithm share code + * + * Worker method which allows sharing of common code in the Yaml and self-initialising algorithm case + * + * \param[in] context The IPA context to pass to the algorithm's init function + * \param[in] algoData Yaml object. + * \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 + */ + /** * \fn Module::createAlgorithms() * \brief Create algorithms from YAML configuration data diff --git a/src/ipa/libipa/module.h b/src/ipa/libipa/module.h index c27af7718..5ab6afc18 100644 --- a/src/ipa/libipa/module.h +++ b/src/ipa/libipa/module.h @@ -70,22 +70,26 @@ public: factories().push_back(factory); } -private: - int createAlgorithm(Context &context, const YamlObject &data) + int createSelfEnumeratingAlgorithm(Context &context, const std::string &name) { - const auto &[name, algoData] = *data.asDict().begin(); + YamlObject dummy; - /* - * Optionally, algorithms can be disabled via the tuning file - * by including enabled: false as a parameter within the - * algorithm tuning data. This is not an error, so we return 0. - */ - if (!algoData["enabled"].get(true)) { - LOG(IPAModuleAlgo, Info) - << "Algorithm '" << name << "' disabled via tuning file"; - return 0; + std::unique_ptr> algo = createAlgorithm(name); + if (!algo) { + LOG(IPAModuleAlgo, Error) + << "Algorithm '" << name << "' not found"; + return -EINVAL; } + context.selfInitialising = true; + + return createAlgorithmCommon(context, dummy, name); + } + +private: + + int createAlgorithmCommon(Context &context, const YamlObject &algoData, const std::string &name) + { std::unique_ptr> algo = createAlgorithm(name); if (!algo) { LOG(IPAModuleAlgo, Error) @@ -104,9 +108,28 @@ private: << "Instantiated algorithm '" << name << "'"; algorithms_.push_back(std::move(algo)); + return 0; } + int createAlgorithm(Context &context, const YamlObject &data) + { + const auto &[name, algoData] = *data.asDict().begin(); + + /* + * Optionally, algorithms can be disabled via the tuning file + * by including enabled: false as a parameter within the + * algorithm tuning data. This is not an error, so we return 0. + */ + if (!algoData["enabled"].get(true)) { + LOG(IPAModuleAlgo, Info) + << "Algorithm '" << name << "' disabled via tuning file"; + return 0; + } + + return createAlgorithmCommon(context, algoData, name); + } + static std::unique_ptr> createAlgorithm(const std::string &name) { for (const AlgorithmFactoryBase *factory : factories()) { From patchwork Fri Dec 12 00:29: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: 25537 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 2094ABD1F1 for ; Fri, 12 Dec 2025 00:34:34 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C411E6191A; Fri, 12 Dec 2025 01:34:33 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="Jmu2sQwh"; dkim-atps=neutral Received: from mail-pf1-x430.google.com (mail-pf1-x430.google.com [IPv6:2607:f8b0:4864:20::430]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 750E761899 for ; Fri, 12 Dec 2025 01:34:32 +0100 (CET) Received: by mail-pf1-x430.google.com with SMTP id d2e1a72fcca58-7e1651ae0d5so592571b3a.1 for ; Thu, 11 Dec 2025 16:34:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499671; x=1766104471; 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=vdieV2jp4Gung7/4hWVYp0Lav9rda27DBFfiiAcRIr4=; b=Jmu2sQwhj+KSwMr5a4pSMQn3Ucy6unGtn+CPwiqpbHw50swdmzdIWoC55QpDqeJXmy YOIRk2vb8PA4sD0+jDvnH96fMFyA87Dff7tftC9z8BUksKHd/JGB7S/om9PzAs8IiXS1 07q3KFcibXhFJQJBaNHdPUZMP/BALukTwn7YvLSXi4KW507HMzdVS69/Askrr6BadXEZ O9rrcK7rpjjTDhO2DLgoO/4854qpoaqN1azJNYOlS+drJu5k/NqoIUs4GaOST0RHcq/d O7qDgRumjsATvI8OtoD6NmArcsCqVOMFKlZh1dK7g6lW66tPmP+MaCYqhh5wnSibf3Lf PCZg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499671; x=1766104471; 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=vdieV2jp4Gung7/4hWVYp0Lav9rda27DBFfiiAcRIr4=; b=aPcocLd2zCDx1ZVM6TkZez2FiZmryTOoYsc+7ca2WWhy8TgJ/b/Xtq33QB+fs3CBuu SgUFGTCxYmx/I43pYlb0l/fqJJHORb9NAJd4slYNsG+bSfQhYUvh4GJJ9G8wloBa2mqy vVmWY9wscQNfM2Pf5vIQjKKIiqYmF8+TLaTcOaufkiZ7IY8N/qF0TnLgoXMTJ87IKpe4 /fwFcFwpJvLEoSFxuZ0LZgowN2nhh+CL1ub+86sLABNjyd8YI4wBd5u3+wkvFwPNgi10 PWR4QS4bx9SPUpqazBxUh4gLaxfoRNGIkxxOCudEkZ2kVgVDnAeKTzHT3VMR1QWHND+1 qA6w== X-Gm-Message-State: AOJu0Yx4ON6pe2RCNSvBfioWry+aUqITHvb3l3Y85npDN6jjedStCIeJ mNf8/kEOtFjbNT59P8v5BTT1MqT+2TZdcFHKe7V3LqPSSwx4Gnnw0MnyxPoesrB/nYVnrPpFz7M mEPWJ X-Gm-Gg: AY/fxX4nLrDHbFl1gapB42e/uUNbvxFPRV3AtLfaRP2HBNhCCf3i/tbebenAdMfKv4D qR+DdfWvLpbOQDLNgiiSqwgk+gASv43gjWHDvbfapyY0LV04IB7CJlKdCg2Tzo2Px04rmg9tvB/ s74QteuCL3EJoVLJZeSU1hjecr7HKUM6Zx7h9G+yc/19fa3AMIbnzagE4MzZ31OmUUplCv55fN7 vo7sxd3HjyeDwm7yIOtvFRCuiG38x4FtI8V0APPlpZUibljc/Gz08cRxjGrj9HOe5ewuILkn5vQ I8HhUGTMo9WqZsn0vU+p9K02pcIISNb3RUbajk0+2jeJ5/Xa3qWfE5DoxoOKpMa8fJT+zJhLv/m FZdwfrhDJLSDSY7q3OT3n+De078+XgpXPIjszMTsRDATLM1/ug3W7rDbOO/h6184F7JjKpY+ohH 0YRyXpmz9JIUK7gSAh20sbEokK+atmOXgizJGUFf8XX8NNEVFBkmDvWQt7TWs= X-Google-Smtp-Source: AGHT+IHqwt5CAVe7ZDyfevN6c7WNCwRiQ1GiRyTnazLeT2F9Ubh2ivAeCIGvuB2HIlVsB+2En/YlNg== X-Received: by 2002:a05:6a20:7f86:b0:366:14b2:30d with SMTP id adf61e73a8af0-369afff1ea6mr312858637.64.1765499670778; Thu, 11 Dec 2025 16:34:30 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.34.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:34:30 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v8 22/26] ipa: simple: Add a flag to indicate gpuIspEnabled Date: Fri, 12 Dec 2025 00:29:33 +0000 Message-ID: <20251212002937.3118-23-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Flag gpuIspEnabled in the simple IPA context. This flag will allow to selectively avoid some calculations or to generate a default CCM. Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- include/libcamera/ipa/soft.mojom | 3 ++- src/ipa/simple/ipa_context.h | 1 + src/ipa/simple/soft_simple.cpp | 3 +++ src/libcamera/software_isp/software_isp.cpp | 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 03d8007ea..20c75de4e 100644 --- a/src/ipa/simple/ipa_context.h +++ b/src/ipa/simple/ipa_context.h @@ -104,6 +104,7 @@ struct IPAContext { ControlInfoMap::Map ctrlMap; bool ccmEnabled = false; bool selfInitialising = 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 7fde57aec..5dbb0e3d6 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -121,6 +121,8 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, } stats->statsReady.connect(this, &SoftwareIsp::statsReady); + bool gpuIspEnabled; + #if HAVE_DEBAYER_EGL std::optional softISPMode = configuration.envOption("LIBCAMERA_SOFTISP_MODE", { "software_isp", "mode" }); if (softISPMode) { @@ -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 Fri Dec 12 00:29: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: 25538 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 8319DBD1F1 for ; Fri, 12 Dec 2025 00:34:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4642461931; Fri, 12 Dec 2025 01:34:36 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="IFFdT5HB"; dkim-atps=neutral Received: from mail-pf1-x42d.google.com (mail-pf1-x42d.google.com [IPv6:2607:f8b0:4864:20::42d]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 72D02618CD for ; Fri, 12 Dec 2025 01:34:34 +0100 (CET) Received: by mail-pf1-x42d.google.com with SMTP id d2e1a72fcca58-7aa9be9f03aso567454b3a.2 for ; Thu, 11 Dec 2025 16:34:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499673; x=1766104473; 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=IFFdT5HBz/kOeeEF2sIQiheN+fu+cBnkvNHkXyywFAi5tMdFavrRTtABnHuZuHMjLm CIhRssY5Gldp7pzycJccTiDGbTYjWY7218+ZA/a5EPozY1NLtTJfxojB6MY9EPXW8eFC NzZTApFKqYPUSr1Y8br69pWpoQ9DTsa04gYkAv45waLHeYXs9PbfsrB6JfNPJT3DgWFF ONj9BZhqkiKPypdZkTJce3bHU0CYh6DUUpKxG75BWEAkPyhi2nFGNYYvSIG0fVlupuuz UbpOPIAbXGweViuFM3YQPJj/NanmDMGad9z/tosVg9SqpOBgF1ZFZipTqKtBOK6tELlM 7kTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499673; x=1766104473; 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=wttlW+UWb9G6XTnnqrneqdzhol1OEb9GErG6CPg4FR3uTI552XEFDynzMtT3cJ7UWR 1hvqsZayp3xZnnygO1WwD6te82YLRbi7bB2HS7FJEEJ+RIaXdlkfvHG6+NnL96VO9ltJ d5SYyuACVmmVcElbH2Uy8xE4eoFWPrzHmuTncO06NDyRmPRUtVad2ftsRLw8ocGntBZL /FSiMyYmFc+2v406S8uHbuS7HcbZe7sXxCXaGpcTH+6Cwaa2JpDQeeXgZWbu4u1RcFyN 57pHWfAllgrhJewKkwMMyTb9Wju9QEaUjMv4tpYrXQdL2GpHt4k8YY+djDNIw44kDihz 3SxQ== X-Gm-Message-State: AOJu0YxAOQNRxKWDP6PNfe94dBcJGK0/u8ETCYYcX6Z2kvL8/0F8r8tQ 2V++oTx/QFhfixuwkhK5Z5KGoqX1ekWgrtHUmbM044cyOMwkAJKjnBiTYXzC+bUj86gaA6/46XQ dbuqA X-Gm-Gg: AY/fxX42WMYmdJ0GFuFdckElx2k/IaCZCSHPENq7ZQ4rpPQFknw6pVMl7vHaWI8WgWu TUokHsgqD+HnTCxgzV3tHO7JBMcQFCxJoJbikwjz9rtWsnLO1/6KhZlraVHdVO9gP4/R3q54Pvc bNr2styu4olAzIg/TaMTOviuFI20Svh9kKjyutTZozKxY7yuv2Wj3wds6DUP/il33hr8KDfTb8y ISOPqU96Tp7ak9CAlYo+On/lL0Dq8iBeQCj/Qcv7nB7MlEJVuvJRabBhtR6qO8gD7d5KmMtlrF0 2Ba/sYBcgKsFtSixrnswxeeYLewnrzn7NF3MfE///oI1v5Bfxn2wMGLU0UJxEVGSUaVc1ImihF3 9RPl+tyMIwvR//Unl2r1ZnEISMvpDp8OrebphJq/QUyO8bJE+gAZOzYxevkwde5Fk8W20+/+z7s IH44+H9SmThLjo209m20CB2Xb2u6z0hk0V3z9bAnzB7RgvngwuxvuYV7n6yTo= X-Google-Smtp-Source: AGHT+IH1d2HXS2kAWO0gTMGz57YexCcreP+fXehL8YDbpvb9A6rQDSugRlvYQdo1wzRgupKnOggQoA== X-Received: by 2002:a05:6a20:258b:b0:350:55e0:5522 with SMTP id adf61e73a8af0-369af336eb4mr307752637.37.1765499672813; Thu, 11 Dec 2025 16:34:32 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.34.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:34:32 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v8 23/26] ipa: software_isp: Call createSelfEnumeratingAlgorithm() to statically instantiate CCM algo Date: Fri, 12 Dec 2025 00:29:34 +0000 Message-ID: <20251212002937.3118-24-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-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 Fri Dec 12 00:29: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: 25539 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 1CDDCBD1F1 for ; Fri, 12 Dec 2025 00:34:40 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D027E61925; Fri, 12 Dec 2025 01:34:39 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="N0qJADf+"; dkim-atps=neutral Received: from mail-pf1-x434.google.com (mail-pf1-x434.google.com [IPv6:2607:f8b0:4864:20::434]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F26C06191A for ; Fri, 12 Dec 2025 01:34:37 +0100 (CET) Received: by mail-pf1-x434.google.com with SMTP id d2e1a72fcca58-7baf61be569so781715b3a.3 for ; Thu, 11 Dec 2025 16:34:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499676; x=1766104476; 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=0x9sYofuRKBarctBdgKuhUSV0fpuyAnEk7YI+eA7X6s=; b=N0qJADf+pAbtIGAWqHwQz6dhJafgy2ugKOqKOOuseDocugzToWSit+jC92oWIwO3Qx k+1518pgNxjZ5RiLpw2GfRnItU/afI8nr6OiriPo7QybKc5/EE8nR8Cc9KAsgUe1/jgO WJtnTUNvXLQMZlGMGIPwl3m/blZeioEbs1gaIpVrnAvZ8jRIjG2TqyLOlgDIkQivQIS8 B/zWEPNmcQvAZi6ppfpdA8/jZkA2kyWl8o4Kba+CeFLty810sd+iBUeZrXCbYdgPxxMV eByd9yiKCipJOH/A9bPurSe1SfLp6TU90C2IiZhrCrNbHk4QVc9FgmKgcskM7L5wqVZt TFXQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499676; x=1766104476; 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=0x9sYofuRKBarctBdgKuhUSV0fpuyAnEk7YI+eA7X6s=; b=efrs88P9AX0hlFS3hpO62toVfTzfGXLAdM7Vk6t3aOIDpfXFtpX6/F+seIuuplD1MY 2O26puunal1cxxgyRCeeL4z9csM3NGBYHnBa/NL1H6KMoqd3bKqpKW4oCVh2SieyoQug Ai2Yid6N462yF1RrJqhO2g/SrYhhaHaIQpJGkfOW9Oawkui10iymBZ2o2+vQ2OLTvQUZ WYAyqGhkjAfao+KTWV53owPDeCMy/bHYQx2Y4M8mAeMtHfzP/e8EI5kEmNHZKt/mHJZQ pSd4Zv8Jv37zCFXZFWY2uOmgnG7uJGLlW4bIK2V/DuQYHGcZyIJWGrqwVNm1LjzY7DL0 5M8w== X-Gm-Message-State: AOJu0Yz3w1uaixdKSgAzy5tN9eLs6mrE4m9BiWZcdICtZL5iiPXJDIUr kVaTeYN98D/S3atWWX7j8rquskflyVZYLrTgyfqsYjEHkMfoaHBKokffZ3lDhHJxzp0Dlm+MZhr mFX3F X-Gm-Gg: AY/fxX6j40SSIm15JseH6HpJMETyRFXeeMdASMohAuUZiafDaQ8WgPXBL304roddI4P L+Aiwas/d6BoDWO+qomBTzJ7uWi4g7bV6IVZnVEzUhDTDFtWujrSjOLWSROiCC06IvAvY6/lQf5 rOrsI0uCZT+2BEx26Qe6lZIEbw4spRZXSNO1uBA+aE2+QEJ95Hg5WNolBw7W5MvNStX36GxrAMP zA7UMyb1O6+pdHbUVgTyNyOinjgeisrSXZoYKaO5HVAWJeL/tkJY3Ho+aVh9y2lEKsoNswE4P7K l7rzRKMWo4ulxCBkwpT27VGA6zJvX/9vWtQynsa5ZNTP60WZzY8lWfNi2AjHEgeprVsUJ6SOhIK tA6YJab5b40QUCl7kgXkaP3hvcVfI7vlPgPU6FuYELvHs7fOJbDocPK0YtxIYGLdlrBy60/lLi9 oaPr1xVkgUJFP3/DYfDLX4vWgfULac8+OpiDUxXf19anlkvPsso/hKCgVodtK/4fRNBMsjsA== X-Google-Smtp-Source: AGHT+IGUw1KdU7VqkmWHA9in62nj+LUg9oDUHiiMOBlLI6S7XbKMUf4eiFy+vtAOg5BVaG4tnaMPkA== X-Received: by 2002:a05:6a21:e082:b0:366:14ac:8c67 with SMTP id adf61e73a8af0-369affed061mr301899637.61.1765499676289; Thu, 11 Dec 2025 16:34:36 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.34.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:34:35 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v8 24/26] libcamera: software_isp: lut: Skip calculation lookup tables if gpuIspEnabled is true Date: Fri, 12 Dec 2025 00:29:35 +0000 Message-ID: <20251212002937.3118-25-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" On my reference platform Qualcomm RB5 sm8520 the qcam application CPU occupancy drops from ~100% to about 95% of a single core so this one change sheds aprox 5% CPU usage. Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/ipa/simple/algorithms/lut.cpp | 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 9aaab54f1..adf411768 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 Fri Dec 12 00:29: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: 25540 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 9E065BD1F1 for ; Fri, 12 Dec 2025 00:34:42 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5457661925; Fri, 12 Dec 2025 01:34:42 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="y4b8f3hM"; dkim-atps=neutral Received: from mail-pf1-x42d.google.com (mail-pf1-x42d.google.com [IPv6:2607:f8b0:4864:20::42d]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AB77A6191A for ; Fri, 12 Dec 2025 01:34:40 +0100 (CET) Received: by mail-pf1-x42d.google.com with SMTP id d2e1a72fcca58-7aa9be9f03aso567502b3a.2 for ; Thu, 11 Dec 2025 16:34:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499679; x=1766104479; 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=NauU1uWfSPSZd8EiGg8FTzmSYzjHvu/p8kn7jtnbOq8=; b=y4b8f3hMPlnuUEPuVPgZVaCwwP6o8mPwbm6dn9T8QFLKzfYnyiU65JlCTdWOu5IBGg RyCIn2AIaFKnWBpJ31KBnLFslG1iJnXJ9JyIs1wtfX9Nij6MTPWaoox3rpIlrdczRSPH 8gEbbqB75ySGDQT6j8ybpjY2B+qDNitR1s1ww5K457WguUX4hDIhGu4WE/s9fCvA7D9v QWQjCzCCxSTuD51KjxM+spnWb8vDrX4rzRKaRKExVmY84r6Sv9V4bgypcsdoHjiluR77 rVN904VlwxuFQR0AfHxlBLpPIV8rv6f8i7hE5QC7GRuRJi0PgwLw/bUDT6IjnN6mOMZk 3WSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499679; x=1766104479; 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=NauU1uWfSPSZd8EiGg8FTzmSYzjHvu/p8kn7jtnbOq8=; b=wdVK/vsQG5IQzFqZNBucMq8c7KVgB4DM5Letjo3zFTHbS3271JT2N8dfrmDyU28FAs jL5IVapGN6atmba9uDeE6oFd1sWO6BeLt7oMQA9ioefSt723YcMsG7lAZo9nsZhvy7wV oSxo+tTBr7FIvNo9mxC4ok5P8vK87V7vuw0xnEsEnGgR/kVE7rC7iFYgflS9kijie+0Y WgEd7jAbnvSgmfYfajJZL/OJ51oR5CmSlkJfuYoubePOB8dmbV42nYADRBnmfv1wiMlG p7YAp1RrblOFF5Qwx/q0jd3KL4zcI3RfLUmilIdT5YoavXoXbjnoDSlKJ3CxBNOLouYq Fz0g== X-Gm-Message-State: AOJu0Yzuov4HqOsaopL+YwOWAAx1wq7w6U0T0RXFa33MrClpsNuufA/Y 2Ha37QG9p+oeLXLxpZCRD6NOYSr7yqd5IcvYOg90jqjAeCs2ZYCZAKp0xIa+z9Vz6Aj9FuSJYgW U/BAz X-Gm-Gg: AY/fxX74YxfQb0bNAmuHApZqX9SzD1tOmWByuwS/iDeUwFQlAnXu/Ff865s5CnHQ5+V m+9LAiUoHErSCIvlUlyFu8LbszMsxC2tKGauw35t28kLELwq+TDIyruaBBxoA8vw6zfGW6dpYvJ ppa9f0CT4kxvwgxvAL9+Ebfpqxxph9zPvWxPvgdWPNbVDY8CqT6/Z8ftKRd+VffvMbShsiMOE9n 96ghiqfBCr0DGrzfQwjyvOiLR7WiPanQlFwJnL66q0fVJANuvwJQFEPed9ajOOW9nuf23egjVpV alaIT73aspX2B7WT6lZm3nTyP7zQ2Yw85QmWGRAHoQ0nNE4SdjnVd434tApailjBX6WwY2TOkRf 8euc99wIPcfU3wPNLSM82L0eRnECBzS7UTfFPLA5P/S7s2FR4uY4OhIp0BAG8dkFeFAguuwLBfX jWFxvuEB2ObYDwMEKEIJBFJyxrGwRHmuKIkMa8mchxLju9I3Tdn/RTKfBW0W82bOwaegnv6w== X-Google-Smtp-Source: AGHT+IH/meynhM/ohq1MTMkGDS8PZlwnsRYSr9mdOVbCjFcTh+2Rku+9kyCwccadSPR15KVJabT6hA== X-Received: by 2002:a05:6a20:12c1:b0:2ea:41f1:d54a with SMTP id adf61e73a8af0-369afa01494mr317739637.55.1765499679020; Thu, 11 Dec 2025 16:34:39 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.34.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:34:38 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Hans de Goede , Milan Zamazal Subject: [PATCH v8 25/26] libcamera: software_isp: lut: Change default Gamma to 1.0/2.2 Date: Fri, 12 Dec 2025 00:29:36 +0000 Message-ID: <20251212002937.3118-26-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Change the default softisp Gamma from 0.5 to 1.0/2.2. Reviewed-by: Hans de Goede Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- src/ipa/simple/algorithms/lut.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ipa/simple/algorithms/lut.cpp b/src/ipa/simple/algorithms/lut.cpp index adf411768..618219b17 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 Fri Dec 12 00:29: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: 25541 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 397DEBD1F1 for ; Fri, 12 Dec 2025 00:34:46 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E1D716191A; Fri, 12 Dec 2025 01:34:45 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="rrF9xmyR"; dkim-atps=neutral Received: from mail-pj1-x1033.google.com (mail-pj1-x1033.google.com [IPv6:2607:f8b0:4864:20::1033]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B53906191A for ; Fri, 12 Dec 2025 01:34:43 +0100 (CET) Received: by mail-pj1-x1033.google.com with SMTP id 98e67ed59e1d1-340c39ee02dso566198a91.1 for ; Thu, 11 Dec 2025 16:34:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1765499682; x=1766104482; 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=Hi3XytMpe+nkrlzIOzSyi4eb7BfcFLWPKSiPZLNjUc0=; b=rrF9xmyRJpaYTojCjkrFlHUfRn3unJh3NRbZNe8CB6p90eIXmsJaqe808ayfip7aTY gFzlBRC3QMgwq5mqjwRKQ0vuZn8du96xFTlmpCpKmmaS2jTGIBtdeEoQlgqczmMgZOQm flwr5tAIW7sC6WEuLJl8QcuI27ouTzA8vaKFpMek/VTY+Mn0NSgoUTocHZGNy/TYxEse gy+Zu/IygsAyAcq/J4OyhkTXkspfFdZHj9243XilIng+mpPvEaltdEGe7eA02X1rBR2T kcqSGP0f4qmPEUGMCue+/0FApqu2gmpwXPy8nhrBFC7917m1tT0dKRt1xTBwMhEY/TSq 9//g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765499682; x=1766104482; 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=Hi3XytMpe+nkrlzIOzSyi4eb7BfcFLWPKSiPZLNjUc0=; b=e1+O7WIAxaTRcGLP/FqlDIyuf6kP+/Ey8f4z512I2kkVCs4rxrlWtvFHLOB5Qb0wzu mwa1Jv21ErQJJFUs1Ad7mKbNHxPlmgc8v9A1uArZ2Pr8jaUDtw2788XvWVBZc7ueiQjX ePNGRLdiRMrCgRoAivwf/DK1HQUIiZgvTwVj2iM1g9Xiicx48L0IPpx1g7cTjzPz68YM m3KnwspIdfP8gpK586LVKX4dmY1bOQZfKA8xe5qUg1ABC5LMfPdjdeEIBJRRhJEckEVC pWC6B5aHXH59UlDRhv0xQgaFd3YHfi1esvuu+kFREkyxuBhvKbZo+ZBqTQj4cUmSEeQE BiRQ== X-Gm-Message-State: AOJu0YxVBc4WjtSCwL7oFbe3F5g/VMSgFJLilqBFgH/hb2/bJy0Zewk3 foNFgUEBj2eKk7ZcINqptvagqBTM8/r4iZXquPGjPJVmKYgMOLHFZuwL7o0PEVz3horDEu+zmDV QS7nf X-Gm-Gg: AY/fxX5yJ09PfOUe3VYl9pDolGpRSHuz2zp6fbn4GVYWmYeUL/VSA3O3plujLSuNCSg a+0iPlOagtxFWdo4ERQwXfmXhyHwfDrIaywOGPfuD/0zNAky/Rci/0p9YfaMwPDTe6dhVk2N6rO ymKmRRdL65mRrY21Rse9L5RQTx4i3qP9GqJJlv5cOgWVrCpZYwZ6faunNoB0ypwyaCwcjyoer7y kA5uGLjZBkJT73DJhvNm21zwJAQkwt5+G0UcEu9ohf4t5GhK6bxEhUW+W2x9KsRS6lDoDCzdWbs /RwqtgGOYU0oB2/OAWwX5pYL2v+9Wk4AjgV8Zb1us37WpHKQnLWRLdRVuuxiiJfCNjoodl693B5 eglgSN9mZ5sZbORkXg4kLCoYOrCD3WwB0NcuYmedEvxhcuQpShRUoQOMl3XX8UVhR/qIwn6sDxh bS1TOiQ7H9/MXz6O+WilgWCyLmEKTK+CFI7D5bnz//N7QRlQnAMtWUVSaaXYw= X-Google-Smtp-Source: AGHT+IGp0lu5ISEAIWN0lq8iVQjVh7wDvdDBaoqv92xa7bFpjT9aDHNfUMOimWHheYdBeUAT04s5Kw== X-Received: by 2002:a17:90b:53c3:b0:34a:a16e:9fa8 with SMTP id 98e67ed59e1d1-34abd799168mr401688a91.33.1765499682022; Thu, 11 Dec 2025 16:34:42 -0800 (PST) Received: from inspiron14p-linux (p99250-ipoefx.ipoe.ocn.ne.jp. [153.246.134.249]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c0c26eb0f6bsm3317282a12.14.2025.12.11.16.34.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Dec 2025 16:34:41 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Kieran Bingham Subject: [PATCH v8 26/26] libcamera: software_isp: Add a gpuisp todo list Date: Fri, 12 Dec 2025 00:29:37 +0000 Message-ID: <20251212002937.3118-27-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20251212002937.3118-1-bryan.odonoghue@linaro.org> References: <20251212002937.3118-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 | 40 ++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/libcamera/software_isp/gpuisp-todo.txt diff --git a/src/libcamera/software_isp/gpuisp-todo.txt b/src/libcamera/software_isp/gpuisp-todo.txt new file mode 100644 index 000000000..e32d7dcf8 --- /dev/null +++ b/src/libcamera/software_isp/gpuisp-todo.txt @@ -0,0 +1,40 @@ +List the TODOs in perceived order of ease. + + +Denoising: + - WIP + +Dead pixel correction: + - WIP + +Lense shading correction: + - WIP + +Use dma-buf handle to generate upload texture: + - eglCreateImageKHR can be used to generate the upload texture i.e. + to feed the bayer data into the GPU. + +processFrame() to run in its own thread: + - processFrame() runs in the context of the Debayer::process() + thread. Robert Mader suggested and it seems like a good + suggestion too to run processFrame() in its own thread. + +Multi-pass shaders: + - This needs some rewiring the idea is to have a list + of algorithms as is done in cpuisp iterating through the + list in a for() loop. + - The logic managing the loop has an initial input buffer + and the final output buffer. + - The higher level logic must then inform each of the + algorithms either to generate an internal working buffer + or pass the final output buffer to the last shader + in the list + - This will allow for multi-pass shaders with the final + algorithm presenting data not to its internal buffer + but to the final output buffer + +24 bit output support: + - Need to impelment compute shader to do this. + +Lense flare correction: + - Not WIP still TBD