From patchwork Thu Nov 20 23:33: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: 25125 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 9F459BD80A for ; Thu, 20 Nov 2025 23:33:57 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6BC4960A86; Fri, 21 Nov 2025 00:33:57 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="A7Ws+7lz"; dkim-atps=neutral Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A71EF606A0 for ; Fri, 21 Nov 2025 00:33:55 +0100 (CET) Received: by mail-wm1-x329.google.com with SMTP id 5b1f17b1804b1-4775e891b5eso6648935e9.2 for ; Thu, 20 Nov 2025 15:33:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681635; x=1764286435; 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=iucmzPJRyyFFPoxeUBz8sxRzHoEk6MZ17eyAcHe13fo=; b=A7Ws+7lz6a/vOyISpy2QZv2HJ49Rb/l5csw4/9lnmnjYXJA2ncWhmyeq8kpgjlOZqD Jw0jn4970bjZC83OyEIczHpvYnQxUlUI28ZvWIFLe06pR2pByLjq2Qx6hJTtqeDtUprH KatteMbdSDgrfuI/4dCsXcWqTxgJeGLnlebI4cslx55QaNPcPNzoyjRG2mxt5VJDpLMu eqtBo7+C0yZiGMDlUbKE0Z82Vf8RGW+9ujtuySf3oU9eSobt5MyYX3ESbHteCzEmLc+d Jhw5sxHk7BHtouh1imgVqX1Eic8Z2cizMcvzGphm+8s2PM3Vn5CFA5zg0mbamfYKMOBc 16lw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681635; x=1764286435; 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=iucmzPJRyyFFPoxeUBz8sxRzHoEk6MZ17eyAcHe13fo=; b=sVi/YO/Rjog60Fi89OGuo666eNgYfDQRy2WGGdi6o7lWlW8iTwWHJgANIIJTF2T01t 41GO4zzYKmDIkGrZkl9T/n7S3koCRLkKhIYaSphVoe0P/Pg3EJOT5X5pYYsxP0TzsTLT S2XWJ6e7kSSolLrtKu8aiM5iHchVHNzgbwxtL2exH8uLaNw3oHDAOOVe7vW20vwcjlnS P3+y0ICjRSbtTs7H+wRBS6o3ILlkU/ZeC5CcxXWil0ezcZUPzDZcx1IgsNuc9Ygz7Elh Gdhb2S2yYgQ4xfNkMOB+jyvGON/VLUb48CIoE6lVO0jATMB7RAXps8hIYbDVqejNOV26 ysgQ== X-Gm-Message-State: AOJu0YyJ7VW8CeM8hAefeC1lLNd58s4HSdpiV7YqmRSRjeatuOPBccFa JyXlHsvbuHMhl7dTUNllJ9LFljawpxZn/KbULsakieToxxkBVsvbc+xNhQyt+MoCp7cnlz78Vs6 Uva5SgNY= X-Gm-Gg: ASbGnct1wy1Vl5/9pbzzwYcut2cb/e5FMdHg7uA6UVWjpCpE/AF+6go62CSB72749DV Ep5xkANczYu9j+tKG9X8Ezl4FZNe1HCBS9jWRuOdr4d3xs8yqIOvTdqnApvWxeRjuaOjN5D+IIx hwCcDDxXqVKrSbBLmyconUJD9jEqds7vsuv1Q/6F3JCL0AC+k680D/+JQ9PWtJhw6AiHF9Cjl37 kPSz4XjS6dCnLED57knr1WXCWOkonoiq2sZf+LejluGJlvYPU6hCbhNnSWuUuqhV9l8zeYSeRsi ZZLH1+ZxUkyf57F18m0ewoPanVyJRT2Q2FpUpiTdvLY+cS1+wn1hCQBSa3y3tWf/hIu8/JW8uBk uuqlP3q80QxckvNiekk9geQ1fJGQxASbGCOLAyBXJXeDgsPA/dAfTYthcT5T+qbtWFFNZ3Fx13a eF6ymLNaMqfehR1JOn+O7T/9wY4HcEXrlI3kTVbAVX1GXeaz2s5hqxgrZs3UNl4cQqD41QPWv0K PIOBQ== X-Google-Smtp-Source: AGHT+IGTjWV6hXGyzKVwyiIRM0X5EfxOZv+NuPQ3cTbMfZ65g9VNhW1w13Q1e0v6kRfyIBNVm93GGA== X-Received: by 2002:a05:600c:4e87:b0:46d:a04:50c6 with SMTP id 5b1f17b1804b1-477c01ebc76mr3292465e9.30.1763681635017; Thu, 20 Nov 2025 15:33:55 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.33.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:33:53 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Kieran Bingham Subject: [PATCH v4 01/23] libcamera: software_isp: gbm: Add a GBM helper class for GPU surface access Date: Thu, 20 Nov 2025 23:33:25 +0000 Message-ID: <20251120233347.5046-2-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-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 | 84 ++++++++++++++++++++++++++ include/libcamera/internal/meson.build | 1 + src/libcamera/gbm.cpp | 61 +++++++++++++++++++ src/libcamera/meson.build | 11 ++++ 4 files changed, 157 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..8a908ddc8 --- /dev/null +++ b/include/libcamera/internal/gbm.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Linaro Ltd. + * + * Authors: + * Bryan O'Donoghue + * + * gbm.h - Helper class for managing GBM interactions. + */ + +#pragma once + +#include + +#include + +#include + +namespace libcamera { + +LOG_DECLARE_CATEGORY(GBM) + +/** + * \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. + */ +class GBM +{ +public: + /** + *\brief GBM constructor. + * + * Creates a GBM instance with unitialised state. + */ + GBM(); + + /** + *\brief GBM destructor + * + * Cleans up the GBM device if it was successfully created, and closes + * the associated file descriptor. + */ + ~GBM(); + + /** + * \brief Create and initialize a GBM device + * + * Opens the DRI render node (/dev/dri/renderD128) and creates a GBM + * device using the libgbm library. Sets the default pixel format to + * ARGB8888. + * + * \return 0 on success, or a negative error code on failure + */ + int createDevice(); + + + /** + * \brief Retrieve the GBM device handle + * + * \return Pointer to the gbm_device structure, or nullptr if the device + * has not been created + */ + struct gbm_device *getDevice() { return gbm_device_; } + + /** + * \brief Retrieve the pixel format + * + * \return The PixelFormat used by this GBM instance (ARGB8888) + */ + PixelFormat getPixelFormat() { return format_; } + +private: + int fd_; + struct gbm_device *gbm_device_; + PixelFormat format_; +}; + +} // namespace libcamera diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build index ecb7c9fa8..01a365955 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -24,6 +24,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..fa15b709a --- /dev/null +++ b/src/libcamera/gbm.cpp @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Linaro Ltd. + * + * Authors: + * Bryan O'Donoghue + * + * egl.cpp - Helper class for managing GBM interactions. + */ + +#include "libcamera/internal/gbm.h" + +#include +#include +#include +#include +#include + +#include +#include + +namespace libcamera { + +LOG_DEFINE_CATEGORY(GBM) + +GBM::GBM() +{ + fd_ = 0; + gbm_device_ = NULL; +} + +GBM::~GBM() +{ + if (gbm_device_) + gbm_device_destroy(gbm_device_); +} + +int GBM::createDevice() +{ + const char *dri_node = "/dev/dri/renderD128"; //TODO: get from an env or config setting + + fd_ = open(dri_node, O_RDWR | O_CLOEXEC); + if (fd_ < 0) { + LOG(GBM, Error) << "Open " << dri_node << " fail " << fd_; + return fd_; + } + + gbm_device_ = gbm_create_device(fd_); + if (!gbm_device_) { + LOG(GBM, Error) << "gbm_crate_device fail"; + goto fail; + } + + format_ = libcamera::formats::ARGB8888; + + return 0; +fail: + close(fd_); + return -errno; +} +} //namespace libcamera diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 5b9b86f21..fe60c8752 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -69,6 +69,16 @@ libcamera_deps = [] libatomic = cc.find_library('atomic', required : false) libthreads = dependency('threads') +libgbm = cc.find_library('gbm', required: false) +gbm_works = cc.check_header('gbm.h', required: false) + +if libgbm.found() and gbm_works + config_h.set('HAVE_GBM', 1) + libcamera_internal_sources += files([ + 'gbm.cpp', + ]) +endif + subdir('base') subdir('converter') subdir('ipa') @@ -176,6 +186,7 @@ libcamera_deps += [ libcamera_base_private, libcrypto, libdl, + libgbm, liblttng, libudev, libyaml, From patchwork Thu Nov 20 23:33: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: 25126 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 B894ABD80A for ; Thu, 20 Nov 2025 23:33:59 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5642D60AA2; Fri, 21 Nov 2025 00:33:59 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="M5EviVFD"; dkim-atps=neutral Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F1AAA606A0 for ; Fri, 21 Nov 2025 00:33:56 +0100 (CET) Received: by mail-wr1-x436.google.com with SMTP id ffacd0b85a97d-42b3377aaf2so817003f8f.2 for ; Thu, 20 Nov 2025 15:33:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681636; x=1764286436; 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=TASlZ6cZIH16m9npbiHdHq/EFViri8eYf2kDahigXSk=; b=M5EviVFDiPDXj0smBqj9xBiJMTzXf/RlPvn/u86qmO9JKxWmeuqX1W3bllf/Z1i5zq 5iqCkCS5puqgaHiex+CZpqtOpw8wqAlw8o0dKSan3KaeLbvkP7Mop44CoeduWeLXu1XM c8bSTtjRVeg9cYAF/z8JHZk+1lTitQ7oBCZVe1tHsphpceJvD87ryqPM+yRsoM1Gu6Wp 7zcGov6gkGNHQ02pucyWyZxweQ8V3x8hwl1ie03tFFNfOsVSvyUbBohGeVikNEG0Mjs3 bwOq607aTM2LvoFAsHxFNY70bvP4xosEbrzvtba+Nu3eJ+T2yI1D9yIwBQv567Pwv2kJ W/UQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681636; x=1764286436; 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=TASlZ6cZIH16m9npbiHdHq/EFViri8eYf2kDahigXSk=; b=S3IjubfoXm0H8bT9JXyqy/ldNx2TwHgb4e13lfIWQduQxILNlDA30JQcl2pqWgK8ZW nvUjn3vTxZMr7DpRC73M2wUg0VzSWRR8F2ManABBQ/s//H/ffKyCjw+R/bdXRYkQI8tW ySdaV9uDSgp3/96llkMETvVmXJ8Y5RDwHKZpXJELSDLuWWpi4E1cbFw16Zr7eQYYkpvS ftLMpUvtP8vjGI4XWn/U+kN5/Ejbv5Gdb7xuyHPayEkaX+QN2iq6Nfi1iGiNItKWYz2R SS3AFCQs20k5PyCR4V6WWU4S0RL4jb7xgFzmllOEGXqYBATSty3DX3H1Fhu7wAO6eRxW 1Uyg== X-Gm-Message-State: AOJu0YzfHUi9PxKLH6NVkJlbQ6CJJQEgm5R4KBq492DnVDbJiVhsfiaq DcF7IwkQQi3fFVxxg7/SHOmn8Q76vm53cdL+mV9446avLiyo+NEpwgYd3KDU4g0e6HF3bGXao4J 5YEgyKFE= X-Gm-Gg: ASbGncsMMofWSxW+Lx4QblP6SnFflSq256wzTlpPcGP8Sh+BIiCmYxAOH17smY1slZK c1tKxV8NxQCY5q+ke2v4vm8LaVUSgNakceU/eXwXpBaPVEOEFhjvETrhY8ztkY3P4+/HjXWZMot Y9UM1hO0CjzACrb1+TFMYm4VS98AUoo86VI33LaHkrlzd5M5+ywQ8wqtw3phKqAT6V5FvKrt9wY 0mXGRIeXfcjNnbxyT7JmUu2venNi9wjHbShKMue56IjpVMBr8haO0tSgS5+OJEHh7+YMxFhGuIk tRdABcg50QfT7VgAqLCcmBmo8b3k5jdemLSSDTDXRO3dEbFiV6Vw8AlIKveQgAyBc1fbI0CsODO k1Ddk/IMWEU5MJFzOnsnR+VFNg7Ty70FQAzOgiKSasdmuTZKVpCgNXZs3H9AI/gBoOOvOqyU/eq H9s3uY4YbxJ7Tf/NdOP0Zm3TUyRiWj7XNvJ8RHWcbZpo1wk2blnV4LdEM9iurTqzWU0eQ= X-Google-Smtp-Source: AGHT+IHRpCWnSr76s3sp0y/ct8mSv//fq54IY20iDGYStu754HONEItN5QaUMW1ZFCl5eHM7fySSVg== X-Received: by 2002:a5d:588c:0:b0:429:c774:dc08 with SMTP id ffacd0b85a97d-42cc1d22e1fmr102679f8f.53.1763681636380; Thu, 20 Nov 2025 15:33:56 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.33.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:33:55 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v4 02/23] libcamera: software_isp: Make isStandardBayerOrder static Date: Thu, 20 Nov 2025 23:33:26 +0000 Message-ID: <20251120233347.5046-3-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Make this member function static so that it may be called from static members of derived classes. Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/debayer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h index 530564c02..60c0adbb6 100644 --- a/src/libcamera/software_isp/debayer.h +++ b/src/libcamera/software_isp/debayer.h @@ -118,7 +118,7 @@ private: protected: void setParams(DebayerParams ¶ms); void dmaSyncBegin(std::vector &dmaSyncers, FrameBuffer *input, FrameBuffer *output); - bool isStandardBayerOrder(BayerFormat::Order order); + static bool isStandardBayerOrder(BayerFormat::Order order); }; } /* namespace libcamera */ From patchwork Thu Nov 20 23:33: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: 25127 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 5C59FBD80A for ; Thu, 20 Nov 2025 23:34:01 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 12DA060AA1; Fri, 21 Nov 2025 00:34:01 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="L1/ShFaG"; dkim-atps=neutral Received: from mail-wm1-x334.google.com (mail-wm1-x334.google.com [IPv6:2a00:1450:4864:20::334]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 1AB4260A9E for ; Fri, 21 Nov 2025 00:33:59 +0100 (CET) Received: by mail-wm1-x334.google.com with SMTP id 5b1f17b1804b1-47789cd2083so8817395e9.2 for ; Thu, 20 Nov 2025 15:33:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681638; x=1764286438; 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=bFUOmUx0zszm7BNPxcIwief7r1L7RB2Y00Bti/kN9ek=; b=L1/ShFaGv2JjjhfyQqkre74CnXxBAkw0k+ZpRUI5ME0N6dF1BY2uDPoX6/6GU8//f4 TEY6hQLWLsCVVlqS98HElJuxW2O2XwwT4zoYOkj7mde83yzVN/6+QGfmNPhdoxcsEsdV 8esxfUCKDOjTJ0xzsH3/xpXQRINddpygVBN1PJ1VmnE92yCTSJJG+AvrYlvB0JxrkB0i dxASywLPKqLVgo53gJB1AIR5EWEslofhYJx5jChyK+pcBEMXhfCq4WNbP8COO5Ltx9hl UEo017yCLXNbk+VosKs02gZRnjVPJ/HV5/9KJXINYMAMb6z+sI48uluN8AnhXD54Pu0q ODKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681638; x=1764286438; 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=bFUOmUx0zszm7BNPxcIwief7r1L7RB2Y00Bti/kN9ek=; b=JHNZDPjCDPsChDAdN0Asme/p16tPsIdFgzvK29AjHU+xxOQkA+lPMSjnfefpsJy9sW rPL6vv6cxdY1yCQIi5We59hZBn5sD0YY8yIaSb77vLjEKLWbplne3EEKtGWMGG7st4iU VNAJl36+YZcWEaiVkgMnpxKh5kllgpdYMEuwAI7HlxZVJhInzAerYgPnwAuKKQruQmQV cugy3psBvgOxIaaegoUFJCmCwHBYjis8ML6FCzM5sjoVi4YZKPEKfMubisPjw8yZfbgm oUSEPzKeg4qLDnVjS4nMX+qiAq5zVSVzuYjyw3ZW0R9QX3H9mlcBMZvKdvotvsbmqWNJ zTZQ== X-Gm-Message-State: AOJu0Yxfmqx4kl9PfQVC2oK1KblpP+t2JwoBQdY1KnwhATaxR7DIHJei hiRLY5o1QK9ysn8o2gh9317XIWB4L54vyEuho/XaQTsaRhCyhb4oG43AkjGMBv4qkoBwndrMwbJ 0tlDH3A4= X-Gm-Gg: ASbGncs07MjiUfP+YmnQuS31O64I7BfxQCrSXHVU8h4ucOUy05INUFjXZZ+3SuGRAfj 279hW4q7hOsTY/SL3cJzSShYxqoJa4LptLJZ9CH0V6/IskTbcGp02hFcg2QnWKCJkciqfR0/PT0 flXLMJBAqmBrKMZr70aKuUAPXGP/zmfoexDtmXktXkKIU8PSJoTbdzPDnQ6gdmnJ+RnuapKr0dr /TaFUVlRa24yRLy119JCXgdO5KfsfTksheAUJAmONEOQ2HAjv98m0KBjgl/RcbdPMgc2Asmyt/T fKJIcmFcwxip32vVqvzYTP309+9CWqLv1wR/W0t0TVIQozfI5zZPVCv9wGaehBeu/1mI/ZYkgr6 rnLnm7yU5pFbzQmpt2416XuNg3Vs6i3LxsPRNVGc8baeMHJcaaK2enIHFHYnKPHotIuWbT6lasz r44UtXWtHp6QY9CNcB6p7ZbiyI18x3T4hDvAPayUG/w0o1eMFHzO6m3Y7acNQClydphu0= X-Google-Smtp-Source: AGHT+IEja66UCWu12pQu3PMRTLwAoCmQ1gmwJibUDClZd1qRDRkrhprSwCZ12DJge1DaU4rYQXIlFw== X-Received: by 2002:a05:600c:a01:b0:477:55ce:f3c2 with SMTP id 5b1f17b1804b1-477c111d3camr603115e9.14.1763681638111; Thu, 20 Nov 2025 15:33:58 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.33.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:33:57 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Kieran Bingham Subject: [PATCH v4 03/23] libcamera: software_isp: egl: Add a eGL base helper class Date: Thu, 20 Nov 2025 23:33:27 +0000 Message-ID: <20251120233347.5046-4-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-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 Signed-off-by: Bryan O'Donoghue --- include/libcamera/internal/egl.h | 412 +++++++++++++++++++++++++++++ src/libcamera/egl.cpp | 436 +++++++++++++++++++++++++++++++ src/libcamera/meson.build | 23 ++ 3 files changed, 871 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..e61a394af --- /dev/null +++ b/include/libcamera/internal/egl.h @@ -0,0 +1,412 @@ +/* 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 "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, 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 + * \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. + */ +class eGL +{ +public: + /** + * \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(); + + /** + * \brief Destroy the EGL helper + * + * Destroys the EGL context and surface if they were successfully created. + */ + ~eGL(); + + /** + * \brief Initialise the EGL context + * \param[in] gbmContext Pointer to initialised GBM context + * + * Sets up the EGL display from the GBM device, creates an OpenGL ES 2.0 + * context, and retrieves function pointers for required extensions + * including: + * - eglCreateImageKHR / eglDestroyImageKHR + * - glEGLImageTargetTexture2DOES + * - eglCreateSyncKHR / eglDestroySyncKHR / eglClientWaitSyncKHR + * + * \return 0 on success, or -ENODEV on failure + */ + int initEGLContext(GBM *gbmContext); + + /** + * \brief Clean up EGL resources + * + * Destroys the EGL sync object. Must be called from the same thread + * that created the EGL context. + */ + void cleanUp(); + + /** + * \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 createInputDMABufTexture2D(eGLImage *eglImage, int fd); + + /** + * \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 createOutputDMABufTexture2D(eGLImage *eglImage, int fd); + + /** + * \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 destroyDMABufTexture(eGLImage *eglImage); + + /** + * \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 createTexture2D(eGLImage *eglImage, GLint format, uint32_t width, uint32_t height, void *data); + + /** + * \brief Create a 1D texture from a memory buffer + * \param[in,out] eglImage EGL image to associate with the texture + * \param[in] format OpenGL internal format + * \param[in] width Texture width in pixels + * \param[in] data Pointer to pixel data + * + * Creates a 1D texture (implemented as a 2D texture with height=1) from + * a CPU-accessible memory buffer. Useful for lookup tables in shaders. + */ + void createTexture1D(eGLImage *eglImage, GLint format, uint32_t width, void *data); + + /** + * \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 pushEnv(std::vector &shaderEnv, const char *str); + + /** + * \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 makeCurrent(); + + /** + * \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 compileVertexShader(GLuint &shaderId, unsigned char *shaderData, + unsigned int shaderDataLen, + Span 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 compileFragmentShader(GLuint &shaderId, unsigned char *shaderData, + unsigned int shaderDataLen, + Span shaderEnv); + + /** + * \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 linkProgram(GLuint &programId, GLuint fragmentshaderId, GLuint vertexshaderId); + + /** + * \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 dumpShaderSource(GLuint shaderId); + + /** + * \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 useProgram(GLuint 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 deleteProgram(GLuint programId); + + /** + * \brief Synchronise rendering output + * + * Flushes OpenGL commands and waits for rendering to complete using an + * EGL fence sync object. This ensures all rendering operations have + * finished before the CPU accesses the output buffers. + * + * \return 0 on success + */ + int syncOutput(); + +private: + LIBCAMERA_DISABLE_COPY_AND_MOVE(eGL) + + int fd_; /**< File descriptor \todo remove this */ + pid_t tid_; /**< Thread ID of the thread associated with this EGL context */ + + EGLDisplay display_; /**< EGL display handle */ + EGLContext context_; /**< EGL context handle */ + EGLSurface surface_; /**< EGL sufrace handle */ + EGLSyncKHR sync_; /**< EGL sync object for output sychonisation */ + + /** + * \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 compileShader(int shaderType, GLuint &shaderId, unsigned char *shaderData, + unsigned int shaderDataLen, + Span shaderEnv); + + /** + * \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 createDMABufTexture2D(eGLImage *eglImage, int fd, bool output); + + PFNEGLEXPORTDMABUFIMAGEMESAPROC eglExportDMABUFImageMESA; + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; + + PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; + PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; + + PFNEGLCREATESYNCKHRPROC eglCreateSyncKHR; + PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR; + PFNEGLCLIENTWAITSYNCKHRPROC eglClientWaitSyncKHR; +}; +} //namespace libcamera diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp new file mode 100644 index 000000000..52d6a6249 --- /dev/null +++ b/src/libcamera/egl.cpp @@ -0,0 +1,436 @@ +/* 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/base/thread.h" +#include "libcamera/internal/egl.h" + +#include +#include +#include +#include + +#include +#include +#include + +namespace libcamera { + +LOG_DEFINE_CATEGORY(eGL) + +eGL::eGL() +{ + context_ = EGL_NO_CONTEXT; + surface_ = EGL_NO_SURFACE; + display_ = EGL_NO_DISPLAY; +} + +eGL::~eGL() +{ + if (context_ != EGL_NO_CONTEXT) + eglDestroyContext(display_, context_); + + if (surface_ != EGL_NO_SURFACE) + eglDestroySurface(display_, surface_); + +} + +int eGL::syncOutput(void) +{ + ASSERT(tid_ == Thread::currentId()); + + glFlush(); + eglClientWaitSyncKHR(display_, sync_, 0, EGL_FOREVER_KHR); + + return 0; +} + +// Create linear image attached to previous BO object +int eGL::createDMABufTexture2D(eGLImage *eglImage, int fd, bool output) +{ + int ret = 0; + + ASSERT(tid_ == Thread::currentId()); + + // clang-format off + EGLint image_attrs[] = { + EGL_WIDTH, (EGLint)eglImage->width_, + EGL_HEIGHT, (EGLint)eglImage->height_, + EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_ARGB8888, + EGL_DMA_BUF_PLANE0_FD_EXT, fd, + EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, + EGL_DMA_BUF_PLANE0_PITCH_EXT, (EGLint)eglImage->stride_, + EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, 0, + EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, 0, + EGL_NONE, + }; + // clang-format on + + eglImage->image_ = eglCreateImageKHR(display_, EGL_NO_CONTEXT, + EGL_LINUX_DMA_BUF_EXT, + NULL, image_attrs); + + if (eglImage->image_ == EGL_NO_IMAGE_KHR) { + LOG(eGL, Error) << "eglCreateImageKHR fail"; + ret = -ENODEV; + goto done; + } + + // Bind texture unit and texture + glActiveTexture(eglImage->texture_unit_); + glBindTexture(GL_TEXTURE_2D, eglImage->texture_); + + // Generate texture with filter semantics + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglImage->image_); + + // Nearest filtering + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + // Wrap to edge to avoid edge artifacts + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + if (output) { + // Generate a framebuffer from our texture direct to dma-buf handle buffer + glBindFramebuffer(GL_FRAMEBUFFER, eglImage->fbo_); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, eglImage->texture_, 0); + + GLenum err = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (err!= GL_FRAMEBUFFER_COMPLETE) { + LOG(eGL, Error) << "glFrameBufferTexture2D error " << err; + eglDestroyImageKHR(display_, eglImage->image_); + ret = -ENODEV; + goto done; + } + } +done: + return ret; +} + +int eGL::createInputDMABufTexture2D(eGLImage *eglImage, int fd) +{ + ASSERT(tid_ == Thread::currentId()); + + return createDMABufTexture2D(eglImage, fd, false); +} +int eGL::createOutputDMABufTexture2D(eGLImage *eglImage, int fd) +{ + ASSERT(tid_ == Thread::currentId()); + + return createDMABufTexture2D(eglImage, fd, true); +} + +void eGL::destroyDMABufTexture(eGLImage *eglImage) +{ + eglDestroyImage(display_, eglImage->image_); +} + +// Generate a 2D texture from an input buffer directly +void eGL::createTexture2D(eGLImage *eglImage, GLint format, uint32_t width, uint32_t height, void *data) +{ + ASSERT(tid_ == Thread::currentId()); + + glActiveTexture(eglImage->texture_unit_); + glBindTexture(GL_TEXTURE_2D, eglImage->texture_); + + // Generate texture, bind, associate image to texture, configure, unbind + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); + + // Nearest filtering + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + // Wrap to edge to avoid edge artifacts + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); +} + +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; + } + + eglCreateSyncKHR = (PFNEGLCREATESYNCKHRPROC)eglGetProcAddress("eglCreateSyncKHR"); + if (!eglCreateSyncKHR) { + LOG(eGL, Error) << "eglCreateSyncKHR not found"; + goto fail; + } + + eglDestroySyncKHR = (PFNEGLDESTROYSYNCKHRPROC)eglGetProcAddress("eglDestroySyncKHR"); + if (!eglDestroySyncKHR) { + LOG(eGL, Error) << "eglDestroySyncKHR not found"; + goto fail; + } + + eglClientWaitSyncKHR = (PFNEGLCLIENTWAITSYNCKHRPROC)eglGetProcAddress("eglClientWaitSyncKHR"); + if (!eglClientWaitSyncKHR) { + LOG(eGL, Error) << "eglClientWaitSyncKHR 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(); + + sync_ = eglCreateSyncKHR(display_, EGL_SYNC_FENCE_KHR, NULL); + if (sync_ == EGL_NO_SYNC_KHR) { + LOG(eGL, Error) << "eglCreateSyncKHR fail"; + goto fail; + } + + return 0; +fail: + + return -ENODEV; +} + +void eGL::cleanUp(void) +{ + ASSERT(tid_ == Thread::currentId()); + + if (sync_) { + makeCurrent(); + eglDestroySyncKHR(display_, sync_); + } + +} + +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"; + } +} + +void eGL::useProgram(GLuint programId) +{ + ASSERT(tid_ == Thread::currentId()); + + glUseProgram(programId); +} + +void eGL::deleteProgram(GLuint programId) +{ + ASSERT(tid_ == Thread::currentId()); + + glDeleteProgram(programId); +} + +void eGL::pushEnv(std::vector &shaderEnv, const char *str) +{ + std::string addStr = str; + + addStr.push_back('\n'); + shaderEnv.push_back(std::move(addStr)); +} + +int eGL::compileVertexShader(GLuint &shaderId, unsigned char *shaderData, + unsigned int shaderDataLen, + Span shaderEnv) +{ + return compileShader(GL_VERTEX_SHADER, shaderId, shaderData, shaderDataLen, shaderEnv); +} + +int eGL::compileFragmentShader(GLuint &shaderId, unsigned char *shaderData, + unsigned int shaderDataLen, + Span shaderEnv) +{ + return compileShader(GL_FRAGMENT_SHADER, shaderId, shaderData, shaderDataLen, shaderEnv); +} + +int eGL::compileShader(int shaderType, GLuint &shaderId, unsigned char *shaderData, + unsigned int shaderDataLen, + Span shaderEnv) +{ + GLint success; + size_t i; + + ASSERT(tid_ == Thread::currentId()); + + auto count = 1 + shaderEnv.size(); + auto shaderSourceData = std::make_unique(count); + auto shaderDataLengths = std::make_unique(count); + + // Prefix defines before main body of shader + for (i = 0; i < shaderEnv.size(); i++) { + shaderSourceData[i] = shaderEnv[i].c_str(); + shaderDataLengths[i] = shaderEnv[i].length(); + } + + // Now the main body of the shader program + shaderSourceData[i] = reinterpret_cast(shaderData); + shaderDataLengths[i] = shaderDataLen; + + // And create the shader + shaderId = glCreateShader(shaderType); + glShaderSource(shaderId, count, shaderSourceData.get(), shaderDataLengths.get()); + glCompileShader(shaderId); + + // Check status + glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success); + if (success == GL_FALSE) { + GLint sizeLog = 0; + + glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &sizeLog); + auto infoLog = std::make_unique(sizeLog); + + glGetShaderInfoLog(shaderId, sizeLog, &sizeLog, infoLog.get()); + LOG(eGL, Error) << infoLog.get(); + } + + return (success == GL_TRUE) ? 0 : -EINVAL; +} + +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(); + } + } +} + +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 fe60c8752..b7be38a8f 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') @@ -186,7 +207,9 @@ libcamera_deps += [ libcamera_base_private, libcrypto, libdl, + libegl, libgbm, + libglesv2, liblttng, libudev, libyaml, From patchwork Thu Nov 20 23:33: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: 25128 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 38DC9C3333 for ; Thu, 20 Nov 2025 23:34:03 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EC98660A8B; Fri, 21 Nov 2025 00:34:02 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="MYCAeMtQ"; dkim-atps=neutral Received: from mail-wr1-x429.google.com (mail-wr1-x429.google.com [IPv6:2a00:1450:4864:20::429]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 61381609DE for ; Fri, 21 Nov 2025 00:34:01 +0100 (CET) Received: by mail-wr1-x429.google.com with SMTP id ffacd0b85a97d-42b3c965ca9so842991f8f.1 for ; Thu, 20 Nov 2025 15:34:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681641; x=1764286441; 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=aOWsQHS70g1fB8m4fPc/5abKue0LOycI9h8pUVaouv4=; b=MYCAeMtQ/NQqFDetGG6BSXr4mFesc4MtHS7bEtD11vFrNwAzKB63qJtGJGs+zmYz/R is90A+XW3DIEqy6oaizX3ol0jUgIlS3HOxGW1ZjLZtVd2U8xZEQs3AlTWfLiUHitfZef 045uqBgHJY+SAsm5bCsXnw6nvMgljdOdCG1xByiVQlHwEzLpFQglO8lTQAoLwrARRf5j JH+JL+Lzek5QpuGuNQIJvHh2//3sYOv0Gnn6dtFLhFoInoh/8IuzGhMtGFQlk+aYnewC xWVjirs6YNHu/qwAQnDwYG9BXa2XpEEP1JmCn8A2uFE8ZKKta5qUyvVT4xYrix3ZTA1b 76Ng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681641; x=1764286441; 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=aOWsQHS70g1fB8m4fPc/5abKue0LOycI9h8pUVaouv4=; b=qVhPyT1kxT7DVxZYAMdBOsWhiMumLaDFYwpGtPaaq0FJOznDdWLrZz4JbiptLzvi9Q EVYAYRpBy/eeZw4yl2Thr/z+HG7RCPZZKRkmuCMqX1Lkfgv/aLPpoKEQfZQVa9cLMcMG 96uM1USA88zW5QI7WAkkfj9YQC3Te6JVz6UlLV+P5XGYPM19mJ7gANDgDnpqqPCmuJT3 7zfbQEaBPQWNjpTks791qlJOL4/q0aNFa2R0YSaPDjvV3dmu+gzFP4IJoSGql/6ymD7o fC6YDEhNf42u+rmAIzjljBaauj7msV/l1CGvaFduWYKdL6QXdvc0VRuf5/Kg9CehD1Z0 fcTA== X-Gm-Message-State: AOJu0YwRctssXMnjD2hBdLxwpfZIzu5cETVQB/C1plmvIgtXploaXAvQ yT3bxZqcoZuMRUvx5Jn2kdu8XbQBH8erQ8N5n/phuhmytb2lf2roQFMvO23nQmvoP1Tu4x/TmZY iVfHz6kM= X-Gm-Gg: ASbGncujbA1JEypQbl9BYNoGAwQozSFnxisfrUgCrq4DjJJ7PzjPO5eUWHIxgsJJjMm eUUT7K6JqmjtJSapTmIujGz2Aghd/tHTHwmw6b/IX0NdPzBUml2fnrEmx1VuqY5tV97VlHh2O0A 92BolLcdZNmPlOi2eJDJhiOE9vCkszcYzMzApXqjCTaNgOvB+wYOOvQZm1Jg+zS1Vf3BbnX4LvI PJDUiiQ3F4eEpvRjH+ikmDU3ndcu9MQNeludahakIVkAm3XVbS+Mh+rVI465z0GjI/JcEnaaOPC xSWhoLY3n5fvsbE3RCW1+mkdzqzT9bCuyrAev1UweZAdQL0Gl4vBruMUmK2EP4u/iea+xl1zHSQ fhOzxb8UwbF5p7AXx09Sw++f3GWtOUK6vorxl81rOR8VsgV8U6gVOcF7ao6c6c+ToFa7ISND1HH 9qitluHu+Gop/FHevMxffV8oz8C5ieoTqkA8wVagRE7XCI1d2YEGezL7k+ZFMHu9q+nko= X-Google-Smtp-Source: AGHT+IH+RXn1P/aXsympVnstSWgpDaGfODJMfhpIUkNEszSe0On9EzAZYrqGWGHJYdldvCAuxTaTtA== X-Received: by 2002:a05:6000:2489:b0:427:854:770 with SMTP id ffacd0b85a97d-42cc1d35781mr98446f8f.43.1763681640654; Thu, 20 Nov 2025 15:34:00 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.33.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:33:59 -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 v4 04/23] libcamera: shaders: Rename bayer_8 to bayer_unpacked Date: Thu, 20 Nov 2025 23:33:28 +0000 Message-ID: <20251120233347.5046-5-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-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 --- .../{bayer_8.frag => bayer_unpacked.frag} | 0 .../{bayer_8.vert => bayer_unpacked.vert} | 0 include/libcamera/internal/shaders/meson.build | 4 ++-- src/apps/qcam/assets/shader/shaders.qrc | 4 ++-- src/apps/qcam/viewfinder_gl.cpp | 16 ++++++++-------- 5 files changed, 12 insertions(+), 12 deletions(-) rename include/libcamera/internal/shaders/{bayer_8.frag => bayer_unpacked.frag} (100%) rename include/libcamera/internal/shaders/{bayer_8.vert => bayer_unpacked.vert} (100%) diff --git a/include/libcamera/internal/shaders/bayer_8.frag b/include/libcamera/internal/shaders/bayer_unpacked.frag similarity index 100% rename from include/libcamera/internal/shaders/bayer_8.frag rename to include/libcamera/internal/shaders/bayer_unpacked.frag diff --git a/include/libcamera/internal/shaders/bayer_8.vert b/include/libcamera/internal/shaders/bayer_unpacked.vert similarity index 100% rename from include/libcamera/internal/shaders/bayer_8.vert rename to include/libcamera/internal/shaders/bayer_unpacked.vert diff --git a/include/libcamera/internal/shaders/meson.build b/include/libcamera/internal/shaders/meson.build index 386b342d0..dd441a577 100644 --- a/include/libcamera/internal/shaders/meson.build +++ b/include/libcamera/internal/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', ]) diff --git a/src/apps/qcam/assets/shader/shaders.qrc b/src/apps/qcam/assets/shader/shaders.qrc index 04f9d7061..32dfa51bf 100644 --- a/src/apps/qcam/assets/shader/shaders.qrc +++ b/src/apps/qcam/assets/shader/shaders.qrc @@ -6,8 +6,8 @@ ../../../../../include/libcamera/internal/shaders/YUV_3_planes.frag ../../../../../include/libcamera/internal/shaders/YUV_packed.frag ../../../../../include/libcamera/internal/shaders/bayer_1x_packed.frag - ../../../../../include/libcamera/internal/shaders/bayer_8.frag - ../../../../../include/libcamera/internal/shaders/bayer_8.vert + ../../../../../include/libcamera/internal/shaders/bayer_unpacked.frag + ../../../../../include/libcamera/internal/shaders/bayer_unpacked.vert ../../../../../include/libcamera/internal/shaders/identity.vert diff --git a/src/apps/qcam/viewfinder_gl.cpp b/src/apps/qcam/viewfinder_gl.cpp index 70f600650..95965ab71 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_ = ":include/libcamera/internal/shaders/bayer_8.vert"; - fragmentShaderFile_ = ":include/libcamera/internal/shaders/bayer_8.frag"; + vertexShaderFile_ = ":include/libcamera/internal/shaders/bayer_unpacked.vert"; + fragmentShaderFile_ = ":include/libcamera/internal/shaders/bayer_unpacked.frag"; textureMinMagFilters_ = GL_NEAREST; break; case libcamera::formats::SGBRG8: firstRed_.setX(0.0); firstRed_.setY(1.0); - vertexShaderFile_ = ":include/libcamera/internal/shaders/bayer_8.vert"; - fragmentShaderFile_ = ":include/libcamera/internal/shaders/bayer_8.frag"; + vertexShaderFile_ = ":include/libcamera/internal/shaders/bayer_unpacked.vert"; + fragmentShaderFile_ = ":include/libcamera/internal/shaders/bayer_unpacked.frag"; textureMinMagFilters_ = GL_NEAREST; break; case libcamera::formats::SGRBG8: firstRed_.setX(1.0); firstRed_.setY(0.0); - vertexShaderFile_ = ":include/libcamera/internal/shaders/bayer_8.vert"; - fragmentShaderFile_ = ":include/libcamera/internal/shaders/bayer_8.frag"; + vertexShaderFile_ = ":include/libcamera/internal/shaders/bayer_unpacked.vert"; + fragmentShaderFile_ = ":include/libcamera/internal/shaders/bayer_unpacked.frag"; textureMinMagFilters_ = GL_NEAREST; break; case libcamera::formats::SRGGB8: firstRed_.setX(0.0); firstRed_.setY(0.0); - vertexShaderFile_ = ":include/libcamera/internal/shaders/bayer_8.vert"; - fragmentShaderFile_ = ":include/libcamera/internal/shaders/bayer_8.frag"; + vertexShaderFile_ = ":include/libcamera/internal/shaders/bayer_unpacked.vert"; + fragmentShaderFile_ = ":include/libcamera/internal/shaders/bayer_unpacked.frag"; textureMinMagFilters_ = GL_NEAREST; break; case libcamera::formats::SBGGR10_CSI2P: From patchwork Thu Nov 20 23:33: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: 25129 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 483E5BD80A for ; Thu, 20 Nov 2025 23:34:05 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1078C60AA8; Fri, 21 Nov 2025 00:34:05 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="IAExF8gt"; dkim-atps=neutral Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7A82E60A80 for ; Fri, 21 Nov 2025 00:34:02 +0100 (CET) Received: by mail-wr1-x434.google.com with SMTP id ffacd0b85a97d-42b3b0d76fcso786271f8f.3 for ; Thu, 20 Nov 2025 15:34:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681642; x=1764286442; 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=buEiyoEdUhxS/yYb2bTkOxK93yYKxPrmnkJn21GpZJI=; b=IAExF8gtuOGXKkRgYMSupBcCrq+yf71bbBvgkPXdGNHYAmlILOnhMEUXnHaR/eAftE aV5SRdHLgPZN693tLCGrYMdNdh5Zx2SxqM5c3Jk1tDZmWpyij43ComSc1Mrqw0uoeYOr VRafTToH0Jmp+GsCPu90Fc2mLP70iYHQ0nzsZM6JRQbu7aNyB2BjMEK48fDC6hffHVg/ Jxrdgjc2yt3neTHiuuw7kiCH0PMtBPYQbSOl8a9Se981mFixQioSPcSegBFugOVovKkE Zom0aFlon8NtMzq2mftKEWY99KvA2CpTRoH2CuZGA4za2VBvRa1HOoMSOWQqcTLWuSxu 4RWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681642; x=1764286442; 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=buEiyoEdUhxS/yYb2bTkOxK93yYKxPrmnkJn21GpZJI=; b=AbRYWPrmGJOgxd4NCLiQXl8asrPuNZq1JTOYQiejyTkBZtV4sEh850b3MDdKSWb63t G50yzVwxhlZXROeOgma5mVp6E4WJRnxE4UfqgH9PzIq4wnHPBQKeGZHeeGLKXHuKW1rE Re7PDRmScA8B/uAWCDOmK58/jFcJGYYmk+HH67v8Ht+vZw1DnxOIIOTBdwVu3YIEooM2 x0RTDQ47MoxaPu4lxWiAPpd+D6pK/sDEpdXF0f2XZoGfGYMHwko2q24eNB5LAjQKkciD kw0MqTpvXR/seg8wojcARp2N5UP0PN+3B2gul3KBAxSSF2f/tnfJvaH2XA/8VAbBIZ+R aV6Q== X-Gm-Message-State: AOJu0Ywp4ivU46cs/BD1qfY//jC1goGZUQzUVsXRwuI+9Bvtkpl7NejZ JqYyfXmiQ79sP09y10uPlppkm1e2hvOYIYEM0whID0Q8hTSbvOO+4pr0OAHS0TWtNFVm6GAxAeC yArFGnEo= X-Gm-Gg: ASbGnctcBmaPpZVCHSiuLtJENGILGA2bviacW4vI1QSz46zygrHupmy2/TiwyJNl8oD 2Q00Vb05BqYwcmnSj+z0zPKXKqvAhVLBRmMS3x7v2OWWc8xGYNf7VzCIGnAcHLPa8oKqNZB/Pus 1/1+hcjWsKa35anL9bCU+6hbbqt8LbURPFnOnkwx9R6+YNAYobBO2AY73HDRrMaygMxUZencR/J iFZ5/2Z+F0FF8l/2U4phmLDYb6fbN736HeXRitOCzfEyUE0eo5T3tUSkUkdZe0qmnzkKGQsNSm9 uXj6pnS5e4zc3huEHGfyyRHbC5Z1L5XlGyC3UU8XsUfgTxIGKr2i3jlfh09PgPeNXhKvi5TzZO4 2R07j6AicpC+z7TFKamML+p07jp1bxQbRCAOGonjBDUAOYGaglCGfcSRA6q0ZVG9340Scf0NEzL lQDFQQMaH9T1XZR4dkrlKo3197jT8yPS4eQZ99k8QVtwJJH6r5/SN87tcja3Lm4qXIm5Q= X-Google-Smtp-Source: AGHT+IHOSsRxc6ytA8Wsy9C3fCVJir6A66FnKF0qRVez7q7V63jqqJ8OS4tq1d/fPHwmBW4bYyi+Hw== X-Received: by 2002:a05:6000:26cb:b0:429:d186:8c49 with SMTP id ffacd0b85a97d-42cc1d526b1mr74872f8f.56.1763681641859; Thu, 20 Nov 2025 15:34:01 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.34.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:34:01 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Kieran Bingham Subject: [PATCH v4 05/23] libcamera: shaders: Use highp not mediump for float precision Date: Thu, 20 Nov 2025 23:33:29 +0000 Message-ID: <20251120233347.5046-6-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-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 get better sample resolution with highp instead of mediump. Acked-by: Kieran Bingham Signed-off-by: Bryan O'Donoghue --- include/libcamera/internal/shaders/RGB.frag | 2 +- include/libcamera/internal/shaders/YUV_2_planes.frag | 2 +- include/libcamera/internal/shaders/YUV_3_planes.frag | 2 +- include/libcamera/internal/shaders/YUV_packed.frag | 2 +- include/libcamera/internal/shaders/bayer_1x_packed.frag | 2 +- include/libcamera/internal/shaders/bayer_unpacked.frag | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/libcamera/internal/shaders/RGB.frag b/include/libcamera/internal/shaders/RGB.frag index 4c374ac98..724395894 100644 --- a/include/libcamera/internal/shaders/RGB.frag +++ b/include/libcamera/internal/shaders/RGB.frag @@ -6,7 +6,7 @@ */ #ifdef GL_ES -precision mediump float; +precision highp float; #endif varying vec2 textureOut; diff --git a/include/libcamera/internal/shaders/YUV_2_planes.frag b/include/libcamera/internal/shaders/YUV_2_planes.frag index 1d5d12062..d286f1179 100644 --- a/include/libcamera/internal/shaders/YUV_2_planes.frag +++ b/include/libcamera/internal/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/include/libcamera/internal/shaders/YUV_3_planes.frag b/include/libcamera/internal/shaders/YUV_3_planes.frag index 8f788e90a..8e3e0b4a5 100644 --- a/include/libcamera/internal/shaders/YUV_3_planes.frag +++ b/include/libcamera/internal/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/include/libcamera/internal/shaders/YUV_packed.frag b/include/libcamera/internal/shaders/YUV_packed.frag index b9ef9d41b..3c9e3e397 100644 --- a/include/libcamera/internal/shaders/YUV_packed.frag +++ b/include/libcamera/internal/shaders/YUV_packed.frag @@ -6,7 +6,7 @@ */ #ifdef GL_ES -precision mediump float; +precision highp float; #endif varying vec2 textureOut; diff --git a/include/libcamera/internal/shaders/bayer_1x_packed.frag b/include/libcamera/internal/shaders/bayer_1x_packed.frag index f53f55758..19b13ad08 100644 --- a/include/libcamera/internal/shaders/bayer_1x_packed.frag +++ b/include/libcamera/internal/shaders/bayer_1x_packed.frag @@ -20,7 +20,7 @@ */ #ifdef GL_ES -precision mediump float; +precision highp float; #endif /* diff --git a/include/libcamera/internal/shaders/bayer_unpacked.frag b/include/libcamera/internal/shaders/bayer_unpacked.frag index 7e35ca88e..aa7a1b004 100644 --- a/include/libcamera/internal/shaders/bayer_unpacked.frag +++ b/include/libcamera/internal/shaders/bayer_unpacked.frag @@ -16,7 +16,7 @@ Copyright (C) 2021, Linaro //Pixel Shader #ifdef GL_ES -precision mediump float; +precision highp float; #endif /** Monochrome RGBA or GL_LUMINANCE Bayer encoded texture.*/ From patchwork Thu Nov 20 23:33: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: 25130 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 B784CBD80A for ; Thu, 20 Nov 2025 23:34:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 17D5460A8A; Fri, 21 Nov 2025 00:34:06 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="H6Vggu0u"; dkim-atps=neutral Received: from mail-wm1-x330.google.com (mail-wm1-x330.google.com [IPv6:2a00:1450:4864:20::330]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6E04960AAF for ; Fri, 21 Nov 2025 00:34:03 +0100 (CET) Received: by mail-wm1-x330.google.com with SMTP id 5b1f17b1804b1-477a2ab455fso15608005e9.3 for ; Thu, 20 Nov 2025 15:34:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681643; x=1764286443; 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=8LAYBbEVeoy2BI04tnQYlfHshsWQZXR3yj5shjq0yvA=; b=H6Vggu0uQdHILCsCLzBEk8q2CDb71nuKpJPiwey3bcdmpisJeLawO17K5ffo4aD6Ic d7Kdxilut3/J4oxXQXth8RGv7JyzpdB3lqSxmuJk4S5NmVzOLuT3puFTDmZLcR1bmhSF nU/EGxdVeM7xMqlYnSNbilhE3AFAmmc4rzK74CUEsSveOiGPzHq2FpQctVVpZB0xfh40 Il/gQcl1zbX25FqpVNaAFSMH7VbapM6HNYynS0O7l6I6Bn4E6Qb8r0f/QyhCY5wMayRL 6cxvZZtunVZncnMdLb3r+VezG5/LvCXVL4JpGFKRMLOJrgIZZ9kmiRp4zfx1F066/JEc YbQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681643; x=1764286443; 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=8LAYBbEVeoy2BI04tnQYlfHshsWQZXR3yj5shjq0yvA=; b=UOvPHNw7UIAG1WbxwMcYQDLK43t24EOJ+RFN80arzD2/nShtFt6CuVOzXbZ//H5znM Esxmr1OGhtZIVF4ILZBSHkSrysmwQ8ASRSoASP3GGnWMIEu+1VmpGpFvrmfNKKWbKs07 OlJG2Lc0fq8cG7V9yojha5su1ZuYA8/9hnRHT3KUblaR0XjJnN05Kv5CGMIyC0xbQp9O /+MnZy+E42IxbKLQotKxMZxdWzZJBOgPFZkpdwscX/tSln7R1GKoq0uesed0TC8HIO3k lQRWTqilBmHbDXhTdX9RnyNFznhx9DVVbHO3x8mG19vMMNf3+YLBWgnXph48WzYiPS7+ yGpQ== X-Gm-Message-State: AOJu0YxkveaF43UFBOY4vzlj0ky9lZCdLp8/DvrUeS78NOm94kAtf8mg jkLIQzLkdU7BjOLMaCFpOFCWOxBP45AoTi70R+XgBDpXHCtCECw196IEDxY5OzgJqOEpRqW8XJa RhLgo6uA= X-Gm-Gg: ASbGnct9RZe7rlAKdMLuyloi01yh4eb9JZQhtDeujtUOvkqW44Ay2Fyqgz8wMQ88Sp1 7yRk/5V5+nVQShQY7HRv2Ln/eSwgXe/j7uY8qK60jIbOArtjcqTAS3xHxKjrDL+d44snLNc0/2/ VBjEyiS/y1pGQmcXdd/6HX1bwH2iumgAGs+Cl4gkVn/Bthw/nK+VpgQmGmde3dLyIBVxEg7uuxi 8hME0VcmlaJLKmbpu+kTbjv5JlKNoveuibdCzia8FPkd7pR0HxbPHaJBKid61Q6+j7ULWmmYJvz SwSzkqdJ/YXgnhTLax0d4epth/NNh0fevPit1BcUpqORY6MTGrgepHVkeOphWCKe4mvh78acoAU VvTYhbMnWNvJGBcfJifns9qYjSECDhLvW6R9wajYWqNpMWx0RnDFnTJCzUFAN0kLDmu8FoEOGUT UbTIamyRtxB/sRzhDo7cUfITeV83Ns3iOIb45Uu1uL7CVB2W62rg/2N9uN6lrFbmeKy2Y= X-Google-Smtp-Source: AGHT+IHx3vrcZuLGdHapd7L/UfdiMYhJs6hSH1/M882yAfd978/ekZ8pen5Amxg+/I4LOrceD2ZUFw== X-Received: by 2002:a05:600c:1f94:b0:477:af07:dd21 with SMTP id 5b1f17b1804b1-477c1123edfmr591855e9.25.1763681642758; Thu, 20 Nov 2025 15:34:02 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.34.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:34:02 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v4 06/23] libcamera: shaders: Extend debayer shaders to apply RGB gain values on output Date: Thu, 20 Nov 2025 23:33:30 +0000 Message-ID: <20251120233347.5046-7-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Extend out the bayer fragment shaders to take 3 x 256 byte inputs as textures from the CPU. We then use an index to the table to recover the colour-corrected values provided by the SoftIPA thread. Reviewed-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- .../internal/shaders/bayer_1x_packed.frag | 56 +++++++++++++++++ .../internal/shaders/bayer_unpacked.frag | 62 ++++++++++++++++++- 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/include/libcamera/internal/shaders/bayer_1x_packed.frag b/include/libcamera/internal/shaders/bayer_1x_packed.frag index 19b13ad08..90bd64570 100644 --- a/include/libcamera/internal/shaders/bayer_1x_packed.frag +++ b/include/libcamera/internal/shaders/bayer_1x_packed.frag @@ -65,6 +65,10 @@ uniform vec2 tex_step; uniform vec2 tex_bayer_first_red; uniform sampler2D tex_y; +uniform sampler2D red_param; +uniform sampler2D green_param; +uniform sampler2D blue_param; +uniform mat3 ccm; void main(void) { @@ -212,5 +216,57 @@ void main(void) vec3(patterns.y, C, patterns.x) : vec3(patterns.wz, C)); +#if defined(APPLY_CCM_PARAMETERS) + /* + * CCM is a 3x3 in the format + * + * +--------------+----------------+---------------+ + * | RedRedGain | RedGreenGain | RedBlueGain | + * +--------------+----------------+---------------+ + * | GreenRedGain | GreenGreenGain | GreenBlueGain | + * +--------------+----------------+---------------+ + * | BlueRedGain | BlueGreenGain | BlueBlueGain | + * +--------------+----------------+---------------+ + * + * Rout = RedRedGain * Rin + RedGreenGain * Gin + RedBlueGain * Bin + * Gout = GreenRedGain * Rin + GreenGreenGain * Gin + GreenBlueGain * Bin + * Bout = BlueRedGain * Rin + BlueGreenGain * Gin + BlueBlueGain * Bin + * + * We upload to the GPU without transposition glUniformMatrix3f(.., .., GL_FALSE, ccm); + * + * CPU + * float ccm [] = { + * RedRedGain, RedGreenGain, RedBlueGain, + * GreenRedGain, GreenGreenGain, GreenBlueGain, + * BlueRedGain, BlueGreenGain, BlueBlueGain, + * }; + * + * GPU + * ccm = { + * RedRedGain, GreenRedGain, BlueRedGain, + * RedGreenGain, GreenGreenGain, BlueGreenGain, + * RedBlueGain, GreenBlueGain, BlueBlueGain, + * } + * + * However the indexing for the mat data-type is column major hence + * ccm[0][0] = RedRedGain, ccm[0][1] = RedGreenGain, ccm[0][2] = RedBlueGain + * + */ + float rin, gin, bin; + rin = rgb.r; + gin = rgb.g; + bin = rgb.b; + + rgb.r = (rin * ccm[0][0]) + (gin * ccm[0][1]) + (bin * ccm[0][2]); + rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); + rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + +#elif defined(APPLY_RGB_PARAMETERS) + /* Apply bayer params */ + rgb.r = texture2D(red_param, vec2(rgb.r, 0.5)).r; + rgb.g = texture2D(green_param, vec2(rgb.g, 0.5)).g; + rgb.b = texture2D(blue_param, vec2(rgb.b, 0.5)).b; +#endif + gl_FragColor = vec4(rgb, 1.0); } diff --git a/include/libcamera/internal/shaders/bayer_unpacked.frag b/include/libcamera/internal/shaders/bayer_unpacked.frag index aa7a1b004..7c3d12b03 100644 --- a/include/libcamera/internal/shaders/bayer_unpacked.frag +++ b/include/libcamera/internal/shaders/bayer_unpacked.frag @@ -21,11 +21,17 @@ precision highp float; /** Monochrome RGBA or GL_LUMINANCE Bayer encoded texture.*/ uniform sampler2D tex_y; +uniform sampler2D red_param; +uniform sampler2D green_param; +uniform sampler2D blue_param; varying vec4 center; varying vec4 yCoord; varying vec4 xCoord; +uniform mat3 ccm; void main(void) { + vec3 rgb; + #define fetch(x, y) texture2D(tex_y, vec2(x, y)).r float C = texture2D(tex_y, center.xy).r; // ( 0, 0) @@ -97,11 +103,65 @@ void main(void) { PATTERN.xw += kB.xw * B; PATTERN.xz += kF.xz * F; - gl_FragColor.rgb = (alternate.y == 0.0) ? + rgb = (alternate.y == 0.0) ? ((alternate.x == 0.0) ? vec3(C, PATTERN.xy) : vec3(PATTERN.z, C, PATTERN.w)) : ((alternate.x == 0.0) ? vec3(PATTERN.w, C, PATTERN.z) : vec3(PATTERN.yx, C)); + +#if defined(APPLY_CCM_PARAMETERS) + /* + * CCM is a 3x3 in the format + * + * +--------------+----------------+---------------+ + * | RedRedGain | RedGreenGain | RedBlueGain | + * +--------------+----------------+---------------+ + * | GreenRedGain | GreenGreenGain | GreenBlueGain | + * +--------------+----------------+---------------+ + * | BlueRedGain | BlueGreenGain | BlueBlueGain | + * +--------------+----------------+---------------+ + * + * Rout = RedRedGain * Rin + RedGreenGain * Gin + RedBlueGain * Bin + * Gout = GreenRedGain * Rin + GreenGreenGain * Gin + GreenBlueGain * Bin + * Bout = BlueRedGain * Rin + BlueGreenGain * Gin + BlueBlueGain * Bin + * + * We upload to the GPU without transposition glUniformMatrix3f(.., .., GL_FALSE, ccm); + * + * CPU + * float ccm [] = { + * RedRedGain, RedGreenGain, RedBlueGain, + * GreenRedGain, GreenGreenGain, GreenBlueGain, + * BlueRedGain, BlueGreenGain, BlueBlueGain, + * }; + * + * GPU + * ccm = { + * RedRedGain, GreenRedGain, BlueRedGain, + * RedGreenGain, GreenGreenGain, BlueGreenGain, + * RedBlueGain, GreenBlueGain, BlueBlueGain, + * } + * + * However the indexing for the mat data-type is column major hence + * ccm[0][0] = RedRedGain, ccm[0][1] = RedGreenGain, ccm[0][2] = RedBlueGain + * + */ + float rin, gin, bin; + rin = rgb.r; + gin = rgb.g; + bin = rgb.b; + + rgb.r = (rin * ccm[0][0]) + (gin * ccm[0][1]) + (bin * ccm[0][2]); + rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); + rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + +#elif defined(APPLY_RGB_PARAMETERS) + /* Apply bayer params */ + rgb.r = texture2D(red_param, vec2(rgb.r, 0.5)).r; + rgb.g = texture2D(green_param, vec2(rgb.g, 0.5)).g; + rgb.b = texture2D(blue_param, vec2(rgb.b, 0.5)).b; +#endif + + gl_FragColor.rgb = rgb; } From patchwork Thu Nov 20 23:33: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: 25131 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 1369DBD80A for ; Thu, 20 Nov 2025 23:34:09 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C2B8560AB1; Fri, 21 Nov 2025 00:34:08 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="No9sczOh"; dkim-atps=neutral Received: from mail-wm1-x32a.google.com (mail-wm1-x32a.google.com [IPv6:2a00:1450:4864:20::32a]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2D73660A8B for ; Fri, 21 Nov 2025 00:34:06 +0100 (CET) Received: by mail-wm1-x32a.google.com with SMTP id 5b1f17b1804b1-4779aa4f928so13902015e9.1 for ; Thu, 20 Nov 2025 15:34:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681645; x=1764286445; 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=Ftr53nnZFbN48TlKdqsyBREu/6cYVA4gRslhx9V2PI8=; b=No9sczOhtJmp564JYv22mwUy9omlno3R3ToKxZYy7rz36uPjVTLQuLXo2YLrCxX9D5 SuFYXnI3irIA/VNSuQ4S/dkihQR1URTJjfJy1vYMeeIrNJHghPrXELz/oWGKeZJsKLHI 4eErwzFmUFD+OFn+vk5iQrRUxPb/U2/esnHpIbqhe9V1JoZ12xqjjMPosJt+nE/BUuck vkMelK9pQJZDaL6mcrK+Lrh02on7jWYg9Y6hOExp4pLQF9fxLm6oJyXSnqiAyKamE4Em LWEWsmyVa9egsnAm/MOAoiRndJ6iVMahfKKHCkXqJxc1kXHmVU/E1qFYmDmQRDpIpagf RPwg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681645; x=1764286445; 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=Ftr53nnZFbN48TlKdqsyBREu/6cYVA4gRslhx9V2PI8=; b=tBOY4oSguEZVbyJ5t7frS2lJdCMJerbRrg/oHCxALwUQUTeVo8onBeHqZWLLfBr4E6 ycEK5Y0O2xtwfnv5j42U5EQBgkk/u2ytgH6/fSDiypDHetmuk7JorwgChZ9y9/V0Rn6w ODd8Bg9honoW2fXs9+uUcIJvxnkBqujAfV6zvD1/wMjkIxBqxKfdzBJHSVuH+XP9C/cQ wJl5Y2j6Q4VRlnS/puVb+nLP+3R0ESwJFO6ZK/4H14oXWidgH9Wji//rG/amntYbn21/ dSm3mwrN2kw8Y5VkZyLxQXliCcln3fAFza4NMtz1xhVwtYXQVf669Vfk772ltMC3kEsk 05sw== X-Gm-Message-State: AOJu0YwlDGfRnhastuGwDN9UOQN0jpTLMsHk8j69M2obYSmEizNF5S9N WExWSgpyfAdK/lxobHFMlxhHP0l/IKYuDKRdxaDhRqQwkvoOZHsElkZe52hPyyV+uc0TZZSq2sx RHKAh2bk= X-Gm-Gg: ASbGncvryXEeGDkeLKdToi9jL8HkyZQyizaYsu9IxllCqO85/djhjxlUYbae3VFqwDM mWUgpKzfi3g3iYwgDaNmf8YfM9Mp5VKpgta2CKZIHGgmxcmh+0Oc+DvH3RAiSeBfCkafugQiURL rRBjIvRy0VCqg5aj9cow/TDtnv2OvPrNW0p07ehjRcauZFmLSO4kC/Y/q1VICRlDl2lyzKo/jl3 1WKnhe+4nF+2RfvRdDMoAbcI9Te47L+bXHyQw+sxXcQHvj26jtVPohpVZwO1ojAJXeJTOWlD14U i9F9iTKqE285wDE31TxRe0Sw5zBz0X2YAaY/iHOWzLSO0+A3csdBp3uFYotDx+qDp/mVg5V242X RLLnU/Q/FInKz4guR50rzjz4MyIN6dXGOOx+FNXtN/evMNf0rR1oVvTJLfsPScCeRB9ZoG34VQL /hy/ckYorc+zL4XwMFh4q61NPzTx8U7z5yI+tBVFRbn9ivjxBGN+cH8CZbJ2CRyQCkT2U= X-Google-Smtp-Source: AGHT+IEVkcdjtGpUOagEpkIKZMk9mBXMBmpv5g3wo6+3WuibeHByLVGZKfZkhAdi7dzdH4X7m62bHw== X-Received: by 2002:a05:6000:401e:b0:425:8bc2:9c43 with SMTP id ffacd0b85a97d-42cc1ac93a2mr115331f8f.1.1763681645422; Thu, 20 Nov 2025 15:34:05 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.34.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:34:04 -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 v4 07/23] libcamera: shaders: Extend bayer shaders to support swapping R and B on output Date: Thu, 20 Nov 2025 23:33:31 +0000 Message-ID: <20251120233347.5046-8-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-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 --- include/libcamera/internal/shaders/bayer_1x_packed.frag | 4 ++++ include/libcamera/internal/shaders/bayer_unpacked.frag | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/libcamera/internal/shaders/bayer_1x_packed.frag b/include/libcamera/internal/shaders/bayer_1x_packed.frag index 90bd64570..c0632eb1f 100644 --- a/include/libcamera/internal/shaders/bayer_1x_packed.frag +++ b/include/libcamera/internal/shaders/bayer_1x_packed.frag @@ -268,5 +268,9 @@ void main(void) rgb.b = texture2D(blue_param, vec2(rgb.b, 0.5)).b; #endif +#if defined (SWAP_BLUE) + gl_FragColor = vec4(rgb.bgr, 1.0); +#else gl_FragColor = vec4(rgb, 1.0); +#endif } diff --git a/include/libcamera/internal/shaders/bayer_unpacked.frag b/include/libcamera/internal/shaders/bayer_unpacked.frag index 7c3d12b03..b545fbbdc 100644 --- a/include/libcamera/internal/shaders/bayer_unpacked.frag +++ b/include/libcamera/internal/shaders/bayer_unpacked.frag @@ -163,5 +163,9 @@ void main(void) { rgb.b = texture2D(blue_param, vec2(rgb.b, 0.5)).b; #endif - gl_FragColor.rgb = rgb; +#if defined (SWAP_BLUE) + gl_FragColor = vec4(rgb.bgr, 1.0); +#else + gl_FragColor = vec4(rgb, 1.0); +#endif } From patchwork Thu Nov 20 23:33: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: 25132 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 D2543BD80A for ; Thu, 20 Nov 2025 23:34:11 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 95BD160AB4; Fri, 21 Nov 2025 00: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="n56n8PlF"; dkim-atps=neutral Received: from mail-wm1-x335.google.com (mail-wm1-x335.google.com [IPv6:2a00:1450:4864:20::335]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F3B22609DE for ; Fri, 21 Nov 2025 00:34:07 +0100 (CET) Received: by mail-wm1-x335.google.com with SMTP id 5b1f17b1804b1-477a2ab455fso15608335e9.3 for ; Thu, 20 Nov 2025 15:34:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681647; x=1764286447; 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=nlJ5B/c2yaAnhmfTCvr9ddm6I4kgAbJyB0Cat+eLPzM=; b=n56n8PlFm7oGfWGILC6Ey00juVfoBRQIMmohaOsLAAu9T1H//B9TDiYZ8VfWk6RB+U Un9C2ma0as1YPrOWANVrRg9qQVukHnDckSx8kTiygYM4yFhozscXM+MirT77com+VHAU 8lGg/xGmZMZqEKLNHXo3l2JhzJoNqHEH0lev9g/9NoMNQMfoF2uBZ204d2JP+NxmRABE JxVxdXSn9SxkMZqXMHRW8Rg0roJMuied3fku5RY6QMNUcjgm52PNCE+bFTuiQZOpClJG dhLXtNwYXuy5ImI9BgCQM51kDV13RYmtFYOEszYMzDoblPdEn1sagoaCESlxPNWogoKt UHvQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681647; x=1764286447; 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=nlJ5B/c2yaAnhmfTCvr9ddm6I4kgAbJyB0Cat+eLPzM=; b=p6ddXF3Uj77pO5ZGTqk2fPFt3wcSVpYxrAMTyKbk4Pzh9+uhgzzXtP6D2EKU8KWuLn /00TQAKlT3QD+Icd8XzKC4E7O/N6LmsPX/QLUXA32TjFb5ta4sYojh//RxZC+PEYqCCV lR/Jm3lBhJ5pP932zFG/UNpPf4XbGmjkS4XwGrfPgop+AsGyOlQWNl8SAkqsQNnGiTcA 2M8s1tqpyNSHV2G/5Mv4nWOFDdznlBkA0jMaL4Pyt2XnFjdztcBFfTm5ApRLqnq+LCX1 kMTa56cjwprZyGexqPnBhhomm059OIwgzp/qh9LwjwKQEJexu24VTkcDSeP+IXHgzUjX ++bA== X-Gm-Message-State: AOJu0Yx0v0vf/pAU96569sv7HxIb2pCuW8x1gwfX8t7AFkKmPkCbZG9t FkEzWbaN7kq4STnRwI9pQtS5qJLRi7PLC4YOYGxC3w2qF4CTegoSLL5Bx8TrpQ/LkqdvNa5lQ4E H7S3GpQo= X-Gm-Gg: ASbGnctIAALcmOtiDD4QDlwmNdLHtZ1UU+MibEjXXxDT+WuItYhdqFcvh5a5XCcRJ8n vbEecNzN2RQtbwQbANL56B85iPUNMl/ZupZYojAbE1HgpRgzJ280QWtT/lEohCk3lPJivKJomTG HOK/1bpm21iVN7b6BbFUKfxwwqF4dDVOO9cvuow3piTPN5xyuraG3TPJ03W24TIaKx8CYkqPfOK G1deVmS/JXTDcaapdFNHotjwjCzYFHIRTLhueGZd8NndhoaljjEX+2Ux8s8dB8em95B8ynfTj+F lnd/Yn+gZ2QQxpgxz5wokZ+1C+DuM8cRlbD7QLHvJdT39seE2RoLjj5XTwFxHhPmWEIHueoIfrN LLSPfkXXuD8woh8vF3+sZZ3MCPTBRGlwgudUcB+UF6ClMGP0cVzH4QC35x5450N886Q9o7FfmRy L28Xp5bJBfGwA1VNN8vMGwvFTkDx/3qyR+XRaCxH0UHxy/MuyJ+KhVENsFZKOkxDBB4jc= X-Google-Smtp-Source: AGHT+IHCkvf4/vf7Hfey7psADN1avGaq5Mt2xaOjJdqEWi9ohy/cGgPb35FzuKN1F/dgtXvWUP8QhA== X-Received: by 2002:a05:6000:2893:b0:42b:31a5:f032 with SMTP id ffacd0b85a97d-42cc1d2d586mr113212f8f.28.1763681647249; Thu, 20 Nov 2025 15:34:07 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.34.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:34:06 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v4 08/23] libcamera: shaders: Add support for black level compenstation Date: Thu, 20 Nov 2025 23:33:32 +0000 Message-ID: <20251120233347.5046-9-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add the ability to apply a int blacklevel gain against the demosaiced data prior to application of colour correction data. We calculate the index into the RGB black-level table so that we can apply the black level when we sample the input prior to the demosiac operation. Don't do this when using the lookup tables as the black level is already calculated in those. Signed-off-by: Bryan O'Donoghue --- include/libcamera/internal/shaders/bayer_1x_packed.frag | 4 ++++ include/libcamera/internal/shaders/bayer_unpacked.frag | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/include/libcamera/internal/shaders/bayer_1x_packed.frag b/include/libcamera/internal/shaders/bayer_1x_packed.frag index c0632eb1f..6bca07b6e 100644 --- a/include/libcamera/internal/shaders/bayer_1x_packed.frag +++ b/include/libcamera/internal/shaders/bayer_1x_packed.frag @@ -69,6 +69,7 @@ uniform sampler2D red_param; uniform sampler2D green_param; uniform sampler2D blue_param; uniform mat3 ccm; +uniform vec3 blacklevel; void main(void) { @@ -217,6 +218,9 @@ void main(void) vec3(patterns.wz, C)); #if defined(APPLY_CCM_PARAMETERS) + + rgb = rgb - blacklevel; + /* * CCM is a 3x3 in the format * diff --git a/include/libcamera/internal/shaders/bayer_unpacked.frag b/include/libcamera/internal/shaders/bayer_unpacked.frag index b545fbbdc..ae214a9ae 100644 --- a/include/libcamera/internal/shaders/bayer_unpacked.frag +++ b/include/libcamera/internal/shaders/bayer_unpacked.frag @@ -28,6 +28,7 @@ varying vec4 center; varying vec4 yCoord; varying vec4 xCoord; uniform mat3 ccm; +uniform vec3 blacklevel; void main(void) { vec3 rgb; @@ -112,6 +113,9 @@ void main(void) { vec3(PATTERN.yx, C)); #if defined(APPLY_CCM_PARAMETERS) + + rgb = rgb - blacklevel; + /* * CCM is a 3x3 in the format * From patchwork Thu Nov 20 23:33: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: 25133 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 3FE07BD80A for ; Thu, 20 Nov 2025 23:34:13 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C2B5D60AB1; Fri, 21 Nov 2025 00: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="Wv3AWEi1"; dkim-atps=neutral Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B74F560A8A for ; Fri, 21 Nov 2025 00:34:09 +0100 (CET) Received: by mail-wr1-x42c.google.com with SMTP id ffacd0b85a97d-42b31c610fcso1230216f8f.0 for ; Thu, 20 Nov 2025 15:34:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681649; x=1764286449; 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=suq5XMZu0qhDPnhx2EUi5HyBXr7OCjnwhdm8i1aWyHM=; b=Wv3AWEi1xY+eJUeom6gFKowaKJmWXX9fe/N/wEdYNW937Q35cR5hzgPpofpaARnoUc S3Qs23kVDtmLQKw+bKowslq23vx/lnnPjhSJb8AR8NtG3xZh6vFjRvx/RiE09WgfgEd3 fCXhR7dOC1B2ZLvaNf6kFvrO+Vp31+Gq3RN8b8jZg5zZ7G5cRJt56i+yRoidF1McRUaX 3kl8QmGuEPa/LXeL6obU4Si2lkFBH9L9Y+wpsO/THuPar8a7Z7e6woPcYM9Ctl7XAR/y NDBxiWBV83VMD7h6lK7QiW7ONNKsrK6qc936GliH4+b22xt8lXuhndDWgZ0zyWCalOw+ 35hw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681649; x=1764286449; 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=suq5XMZu0qhDPnhx2EUi5HyBXr7OCjnwhdm8i1aWyHM=; b=Vaw+REP1UD+jp+iHmhDXRj3KqM91TWVFKPEIjM1cDnJLJQiAZ8FoY6b8uyZMTFC6tq tUoCGB3tHzPzLqjctulRqFgMqR4Eyze0gXO8/zH2amTZjYD+yzleDPBlpkOIyWQw71jO ug4ti0A+qW0VQxGTMYAxP1kHcMgJkkKUHQe482pqJ/Q5IHZzhPYXIJC7zSFjZQqDNYXI iL/N4rhhu7FYopgFpt7hP+ubNqvewoOKE7AGZg32JeBXAuCu7Oj6bm59/4qAE1cnnXWH oxS1xCqGCshMgESE3ZVDtZp7BVZUFe6ok7MYa6Le8GIY9xzfQKNemgGznx4PqTbD26vM Aogg== X-Gm-Message-State: AOJu0Yzq+Fi9EGcFPfRs3ZRCGsH9YoVZA8lB/ok7n4Ffg6K8Gu9DVN7/ azeMltvNdMUbKRmL8g5CZ3rjG8jTVUbXSP7Ae2NLaCeiiE9U7RPvaTrrRUQzivX1vYrmz/fZBc0 yJvO0oJs= X-Gm-Gg: ASbGnct8A4ql2BxdZefWTwooMq9GMY9bA4lTeM4Q/dh7fRm+iKr8H7nOHN47Mn34PWC RQ4ECbqubSrD3AcYkK9oM/yM4QBQeS8PxvPSqDjrm/5qQ+G6vdssQFP71yeB0ognMv5aMzb5Ygz qBYTAwae89tX0RWfcrzt6TFrw+aDRVHfY1rSI9GlL+p4nduoKweZgMmud8UZ8tpXV6qQllHnImM gYPp45d4wLJrAPMXDRVlDKm384R2o+HoOtn5Od6yQlmqPIdlLmGkFH6uuyhZ5Rog3X6/IAErwCl UlxwV5YBd9qXYI8fOUGyrCdFrjZpnSN8JF+WM1m46/o7n/nH8Mz15HNEMAIZf7K/UysCgnr9rAY 4gIMJFfx3oh+R+IuDAaDpGsuCwJmDu2LgYwo0E4/kQgw94U/wbidd0EZw9lBgXHVQIiy1Kz4PQA NARJbSEG8eKGfvoVoH/ImXoB6eNkP83d/R5gc2fKjrf+r6Lz7XvOAY9DqUI9x8HTTHKv8= X-Google-Smtp-Source: AGHT+IGvvPlhCTahDkElwU2H00SFfjpQXLJaaMWSkfr7p6Fweyasl5rfR04ivoIjgW/ok4TPImS9tg== X-Received: by 2002:a05:6000:2f86:b0:42b:32a0:3490 with SMTP id ffacd0b85a97d-42cc1d19ed4mr87002f8f.49.1763681649078; Thu, 20 Nov 2025 15:34:09 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.34.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:34:07 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v4 09/23] libcamera: shaders: Add support for Gamma Date: Thu, 20 Nov 2025 23:33:33 +0000 Message-ID: <20251120233347.5046-10-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add gamma compentation to the debayer shaders after colour correction is applied. Similarly only apply the calculated Gamma curve when using the CCM as the lookup tables already contain the data. Suggested-by: Milan Zamazal Signed-off-by: Bryan O'Donoghue --- include/libcamera/internal/shaders/bayer_1x_packed.frag | 4 ++++ include/libcamera/internal/shaders/bayer_unpacked.frag | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/include/libcamera/internal/shaders/bayer_1x_packed.frag b/include/libcamera/internal/shaders/bayer_1x_packed.frag index 6bca07b6e..069b880ff 100644 --- a/include/libcamera/internal/shaders/bayer_1x_packed.frag +++ b/include/libcamera/internal/shaders/bayer_1x_packed.frag @@ -70,6 +70,7 @@ uniform sampler2D green_param; uniform sampler2D blue_param; uniform mat3 ccm; uniform vec3 blacklevel; +uniform float gamma; void main(void) { @@ -265,6 +266,9 @@ void main(void) rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + /* Apply gamma after colour correction */ + rgb = pow(rgb, vec3(gamma)); + #elif defined(APPLY_RGB_PARAMETERS) /* Apply bayer params */ rgb.r = texture2D(red_param, vec2(rgb.r, 0.5)).r; diff --git a/include/libcamera/internal/shaders/bayer_unpacked.frag b/include/libcamera/internal/shaders/bayer_unpacked.frag index ae214a9ae..950a4733e 100644 --- a/include/libcamera/internal/shaders/bayer_unpacked.frag +++ b/include/libcamera/internal/shaders/bayer_unpacked.frag @@ -29,6 +29,7 @@ varying vec4 yCoord; varying vec4 xCoord; uniform mat3 ccm; uniform vec3 blacklevel; +uniform float gamma; void main(void) { vec3 rgb; @@ -160,6 +161,9 @@ void main(void) { rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + /* Apply gamma after colour correction */ + rgb = pow(rgb, vec3(gamma)); + #elif defined(APPLY_RGB_PARAMETERS) /* Apply bayer params */ rgb.r = texture2D(red_param, vec2(rgb.r, 0.5)).r; From patchwork Thu Nov 20 23:33: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: 25134 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 DDA29BD80A for ; Thu, 20 Nov 2025 23:34:15 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 85E0D60AB7; Fri, 21 Nov 2025 00: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="j26uB8Ol"; dkim-atps=neutral Received: from mail-wm1-x332.google.com (mail-wm1-x332.google.com [IPv6:2a00:1450:4864:20::332]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0E37960AB6 for ; Fri, 21 Nov 2025 00:34:12 +0100 (CET) Received: by mail-wm1-x332.google.com with SMTP id 5b1f17b1804b1-477770019e4so13868375e9.3 for ; Thu, 20 Nov 2025 15:34:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681651; x=1764286451; 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=+zNFNWqqCErC8Ch/EK/IOgEBm/xZ3w406eAq/j9ZXn4=; b=j26uB8OlBzNfZCRxkKdsOkTd704+5yd0lmr7vUNLIXFkVFJTkCTQQ9/2OHmT99h3/e IpsYuOWapidkNh2aKlRwNiCmVprTUss37hJ06OGB8+tsHAjlFLI2iGOZNGE/BVQXFDmr QMNe7LP9seLo8zkf117B4ecmXREWUP5+GIRPpp9/XUoZV7sdks3kZrSAuK+Qlj98cHTO Wk082pgeReZ06G2fBZdaiiUfSGymuZ1PMuOjhvljdjTxie1wLYCQQB1j3ig5AeJ5esGl hEJZACh9/HaoYIT8sZ1j6T4r//jlNKpFutk23DdkLHBmEVLfPKrdV45GHJ29OgFsvPnm z5ag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681651; x=1764286451; 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=+zNFNWqqCErC8Ch/EK/IOgEBm/xZ3w406eAq/j9ZXn4=; b=YAw1QVTI0lu8w6XR7yfSb0eHUdbVtqV0OPjK/FS9GAdcaoxEdt3b9a2Bp7jkUn4m5S Z2NCuB07yZ4vbZB4yCjaCTySWSqnEnBC/7ERvov3YRXPMPSsQ6idK1hK9j0fdLVMlfYS skLzao0pX2/W6pCznmCTQpOK1DI+PityuWhfZCwGpQ6dyK7zzBrjjQObysLCg5o0tPdh 1YuPcszdhWOlF76D9Unx6Mtiam5yvmlvmxayBcYukvzgYyIV2Zq28J6de0Ox0z3WPpmh ayjTeVXTqADk+QSWwYbLYMZOmjjyuX6L7yK+okYQWi4c0hs7D52+/R7Ce44+I/Jux5ko +cRA== X-Gm-Message-State: AOJu0YwpuW7NbPmV7Htiqalo1wIURMb8avmfsn8MYN4yw+fOYXYkAdFD motkHzEsNEsCLLKMIItb6+T41fedvNkW4KAzrcdTH5+EXtpusB6TOp5nWCNJKY2srLRrj2+FCED XcXzFmko= X-Gm-Gg: ASbGnctfd62/GR+rtlEHObDNZOuZhCbox/8BlHlznMb8rMIDkJBPwi+cA3RrHqr3wLe od4yT+lpPzaebagZK5voOMwNWwVgmcqYy9tzw7AneRpuPvfvlgq16vxIOso6wOVEaw1vQHBh7Vq C/vfiDBiknGbIprDdbQumyL+9YV4Yj9AGQuBS66jyk1CLHlvwefCWsX+TNs1yzYj3aHbzcA+eVd YsogmhVXZLlc8MJsEVXKw27ckQdXUiBgfkcD7e0jzHF3n007Wa4raiN0A3bJM8zxwS4qc2QJ7xY GD1zdNS6P1R8Q6jc9EAA2i7b6N5CmDyiFR9OJZDx1yMv0D65YBNS39qvBb2XEpUZXFRVdobDSkw K8oCm23Vi4DdBhzNqm7xBZL+ob3Nm2rqmL+SCGXgsYot5+M0kNPiMjH70g9NTsF4NfuB9B7Grk8 IlTb4XzvgcGd9ROEaEfIncfJ0atuYSugFicW5hI9RIrZcR+41nZqj3BbRJgJUpvI+n36k= X-Google-Smtp-Source: AGHT+IETi4YtTjSl7/B9HEMOiZ/6yoOHfYyu0IADJryaAza1VauySKo30bX2PQkvl6ygayZsnFFOVA== X-Received: by 2002:a05:600c:1d01:b0:465:a51d:d4 with SMTP id 5b1f17b1804b1-477c016bbe2mr3239775e9.6.1763681651380; Thu, 20 Nov 2025 15:34:11 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.34.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:34:10 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Milan Zamazal Subject: [PATCH v4 10/23] libcamera: shaders: Add support for contrast Date: Thu, 20 Nov 2025 23:33:34 +0000 Message-ID: <20251120233347.5046-11-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-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 33905b0b43c989c89a177c0e27dcd1acc80e750a Signed-off-by: Bryan O'Donoghue --- .../internal/shaders/bayer_1x_packed.frag | 19 +++++++++++++++++++ .../internal/shaders/bayer_unpacked.frag | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/include/libcamera/internal/shaders/bayer_1x_packed.frag b/include/libcamera/internal/shaders/bayer_1x_packed.frag index 069b880ff..741896d01 100644 --- a/include/libcamera/internal/shaders/bayer_1x_packed.frag +++ b/include/libcamera/internal/shaders/bayer_1x_packed.frag @@ -71,6 +71,19 @@ uniform sampler2D blue_param; uniform mat3 ccm; uniform vec3 blacklevel; uniform float gamma; +uniform float contrast; + +float apply_contrast(float normalise, float contrast_in) +{ + // Convert 0..2 contrast to 0..infinity; avoid actual infinity at tan(pi/2) + float contrastExp = tan(clamp(contrast_in * 0.78539816339744830962, 0.0, 1.5707963267948966 - 0.00001)); + + // Apply simple S-curve + if (normalise < 0.5) + return 0.5 * pow(normalise / 0.5, contrastExp); + else + return 1.0 - 0.5 * pow((1.0 - normalise) / 0.5, contrastExp); +} void main(void) { @@ -266,6 +279,12 @@ void main(void) rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + /* Contrast */ + rgb = clamp(rgb, 0.0, 1.0); + rgb.r = apply_contrast(rgb.r, contrast); + rgb.g = apply_contrast(rgb.g, contrast); + rgb.b = apply_contrast(rgb.b, contrast); + /* Apply gamma after colour correction */ rgb = pow(rgb, vec3(gamma)); diff --git a/include/libcamera/internal/shaders/bayer_unpacked.frag b/include/libcamera/internal/shaders/bayer_unpacked.frag index 950a4733e..16262feb2 100644 --- a/include/libcamera/internal/shaders/bayer_unpacked.frag +++ b/include/libcamera/internal/shaders/bayer_unpacked.frag @@ -30,6 +30,19 @@ varying vec4 xCoord; uniform mat3 ccm; uniform vec3 blacklevel; uniform float gamma; +uniform float contrast; + +float apply_contrast(float normalise, float contrast_in) +{ + // Convert 0..2 contrast to 0..infinity; avoid actual infinity at tan(pi/2) + float contrastExp = tan(clamp(contrast_in * 0.78539816339744830962, 0.0, 1.5707963267948966 - 0.00001)); + + // Apply simple S-curve + if (normalise < 0.5) + return 0.5 * pow(normalise / 0.5, contrastExp); + else + return 1.0 - 0.5 * pow((1.0 - normalise) / 0.5, contrastExp); +} void main(void) { vec3 rgb; @@ -161,6 +174,12 @@ void main(void) { rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + /* Contrast */ + rgb = clamp(rgb, 0.0, 1.0); + rgb.r = apply_contrast(rgb.r, contrast); + rgb.g = apply_contrast(rgb.g, contrast); + rgb.b = apply_contrast(rgb.b, contrast); + /* Apply gamma after colour correction */ rgb = pow(rgb, vec3(gamma)); From patchwork Thu Nov 20 23:33: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: 25135 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 C6900BD80A for ; Thu, 20 Nov 2025 23:34:16 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8B12B60AAB; Fri, 21 Nov 2025 00:34:16 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="MsmWUBz8"; dkim-atps=neutral Received: from mail-wm1-x331.google.com (mail-wm1-x331.google.com [IPv6:2a00:1450:4864:20::331]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 28B5B60AA2 for ; Fri, 21 Nov 2025 00:34:14 +0100 (CET) Received: by mail-wm1-x331.google.com with SMTP id 5b1f17b1804b1-47778b23f64so8188475e9.0 for ; Thu, 20 Nov 2025 15:34:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681653; x=1764286453; 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=FL3Kok5kdPBn6nF4Kp6wV9C5qL/tIIY/ODlwHYZlWRQ=; b=MsmWUBz8VD8Z3VVQJqZdAJV/B7HkXKNoM4MmuqdzqAOktsnYusaxiz+gW4nG8omJ3i Qcr4uGIDUUxR3A8GIqwbj4dTf3no2IDWPs37ZN69xaBUQd2+yxBFb60VXQ0CQt7CzGea tI7URK2JN/okL/9PMZSdSMrdt88QyfqMBLf+jJok3HUWLxl/+EYRtedjr3iTaaifS2Bl ezcqvStmPT14k6IFZ9EH3eqTI4MjIyXCBV4TzkrCH/d6o8dxiDrXtEVh/kQFvcb85S+h NAGIF3ljyeym6G03wCgMxbWOokFC/sDfmXZX9oYn4vwxVNzDF8DdGeXcy1kpOMYnb38V ZSng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681653; x=1764286453; 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=FL3Kok5kdPBn6nF4Kp6wV9C5qL/tIIY/ODlwHYZlWRQ=; b=o3eJRZeQQDGA7DazOyAj/mZZHUbeq9qcDuHYanf7B0ZCxlacI3R8tHbxY2CtM16gaE VKaADWtsTfVr/5Iq/YEw0KWUWWGswvOIVLgjI29z2XxTpwfG2DUZow2L3KxFtA9uV08x cOT5q1nTATJ7S5qMUhSchCx3rdXN/x36yuTitbslPGZJQwfJrTuROk+FAu9j7KEx/t+q xKB4u2agWEMfB46x+DjUb9uSXN3GMt9L/NTq9Iu6I2s5yF6MpEE2i0k3am0h/DSrKJUA woqPxlMh6kzptldrGYfAZ3RmLxojJnSMa7/V+Tmf6wCwUVRmJxdhyaFGrobezQ3azg9A stZw== X-Gm-Message-State: AOJu0YwkR8/J4USeuuIcjsL6suswMteixMDHUgEQqMNlPkxn3dDp+tL9 uyQ5toW8kQ8x1uJ+iBYIRFaGgggkBGLsbJ+c4Cmy52JHW2O7jnGqg+LkwaTZB5aI186I9YbVMsQ VvhM7oCo= X-Gm-Gg: ASbGncs2Ck2/muGr7Nwi1TtkTu8LONYXUkoWf7trkaTUkYVkfv/E9vqsor/gYzSM8f5 LxBiNAAajIIXmX3zqEGVw1lh3dzhmE5LSxKNSQsufHFaRoNKxAWOKAZAgDxjAGRjdR7DvmjhWFx WEG6MWo1nQ4rXCBfrUjCgxsMkJ7VT6UPp5suNwLbFiYX0Jg3D8QFF8HV1mUQmTZcP/sRPAyXZlS Xdme4p/tHVsxKfsoyg7dYjtqVUMTRtdXhXfSk+2fZsVeR+sEWS6+NollrItcRg297Nwcc31eTVf Krji3S68H+Kly4wziS7RFtxua6v65jeF8Il38+RYScsIA6ZZYTXnRxg+/BL+TrSQBWp+cxROotf Q2Ik8TDszi/bYybtCQm1RejBZsm+zeijxCcQjeccqUiOnv9d2pT9g2PX+e4nt8n9MS3P6cDGCf9 EbcXXZyPKwBCtInA+XdAC2FqDQcsKuscMcTAVWthoZZfjPe76J3Tj/7i8VZTyvI90wV18= X-Google-Smtp-Source: AGHT+IEC61KkESHvBiVrUJPhFkJjaS8t3UhL7wL6DQVbcsFTIiydJOkKTCzw3OCR2+3/DsE3xxt/cw== X-Received: by 2002:a05:600c:a01:b0:477:55ce:f3c2 with SMTP id 5b1f17b1804b1-477c111d3camr607845e9.14.1763681653321; Thu, 20 Nov 2025 15:34:13 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.34.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:34:12 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Robert Mader Subject: [PATCH v4 11/23] libcamera: software_isp: debayer_egl: Add an eGL debayer class Date: Thu, 20 Nov 2025 23:33:35 +0000 Message-ID: <20251120233347.5046-12-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-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] Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/debayer_egl.cpp | 668 +++++++++++++++++++++ src/libcamera/software_isp/debayer_egl.h | 177 ++++++ src/libcamera/software_isp/meson.build | 8 + 3 files changed, 853 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..cf40478fa --- /dev/null +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -0,0 +1,668 @@ +/* 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 +#include +#include + +#include + +#include "libcamera/base/utils.h" +#include "libcamera/internal/glsl_shaders.h" +#include "debayer_egl.h" + +namespace libcamera { + +DebayerEGL::DebayerEGL(std::unique_ptr stats, const GlobalConfiguration &configuration) + : Debayer(configuration), stats_(std::move(stats)) +{ + eglImageBayerIn_ = eglImageBayerOut_= eglImageRedLookup_ = eglImageBlueLookup_ = eglImageGreenLookup_ = NULL; +} + +DebayerEGL::~DebayerEGL() +{ + if (eglImageBlueLookup_) + delete eglImageBlueLookup_; + + if (eglImageGreenLookup_) + delete eglImageGreenLookup_; + + if (eglImageRedLookup_) + delete eglImageRedLookup_; + + if (eglImageBayerOut_) + delete eglImageBayerOut_; + + if (eglImageBayerIn_) + delete eglImageBayerIn_; +} + +int DebayerEGL::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config) +{ + BayerFormat bayerFormat = + BayerFormat::fromPixelFormat(inputFormat); + + if ((bayerFormat.bitDepth == 8 || bayerFormat.bitDepth == 10) && + bayerFormat.packing == BayerFormat::Packing::None && + isStandardBayerOrder(bayerFormat.order)) { + config.bpp = (bayerFormat.bitDepth + 7) & ~7; + config.patternSize.width = 2; + config.patternSize.height = 2; + config.outputFormats = std::vector({ formats::XRGB8888, + formats::ARGB8888, + formats::XBGR8888, + formats::ABGR8888 }); + return 0; + } + + if (bayerFormat.bitDepth == 10 && + bayerFormat.packing == BayerFormat::Packing::CSI2 && + isStandardBayerOrder(bayerFormat.order)) { + config.bpp = 10; + config.patternSize.width = 4; /* 5 bytes per *4* pixels */ + config.patternSize.height = 2; + config.outputFormats = std::vector({ formats::XRGB8888, + formats::ARGB8888, + formats::XBGR8888, + formats::ABGR8888 }); + return 0; + } + + LOG(Debayer, Error) + << "Unsupported input format " << inputFormat.toString(); + + return -EINVAL; +} + +int DebayerEGL::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config) +{ + if (outputFormat == formats::XRGB8888 || outputFormat == formats::ARGB8888 || + outputFormat == formats::XBGR8888 || outputFormat == formats::ABGR8888) { + config.bpp = 32; + return 0; + } + + LOG(Debayer, Error) + << "Unsupported output format " << outputFormat.toString(); + + return -EINVAL; +} + +int DebayerEGL::getShaderVariableLocations(void) +{ + attributeVertex_ = glGetAttribLocation(programId_, "vertexIn"); + attributeTexture_ = glGetAttribLocation(programId_, "textureIn"); + + textureUniformBayerDataIn_ = glGetUniformLocation(programId_, "tex_y"); + textureUniformRedLookupDataIn_ = glGetUniformLocation(programId_, "red_param"); + textureUniformGreenLookupDataIn_ = glGetUniformLocation(programId_, "green_param"); + textureUniformBlueLookupDataIn_ = glGetUniformLocation(programId_, "blue_param"); + ccmUniformDataIn_ = glGetUniformLocation(programId_, "ccm"); + blackLevelUniformDataIn_ = glGetUniformLocation(programId_, "blacklevel"); + gammaUniformDataIn_ = glGetUniformLocation(programId_, "gamma"); + contrastUniformDataIn_ = glGetUniformLocation(programId_, "contrast"); + + textureUniformStep_ = glGetUniformLocation(programId_, "tex_step"); + textureUniformSize_ = glGetUniformLocation(programId_, "tex_size"); + textureUniformStrideFactor_ = glGetUniformLocation(programId_, "stride_factor"); + textureUniformBayerFirstRed_ = glGetUniformLocation(programId_, "tex_bayer_first_red"); + textureUniformProjMatrix_ = glGetUniformLocation(programId_, "proj_matrix"); + + LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ + << " tex_y " << textureUniformBayerDataIn_ + << " red_param " << textureUniformRedLookupDataIn_ + << " green_param " << textureUniformGreenLookupDataIn_ + << " blue_param " << textureUniformBlueLookupDataIn_ + << " ccm " << ccmUniformDataIn_ + << " blacklevel " << blackLevelUniformDataIn_ + << " gamma " << gammaUniformDataIn_ + << " contrast " << contrastUniformDataIn_ + << " tex_step " << textureUniformStep_ + << " tex_size " << textureUniformSize_ + << " stride_factor " << textureUniformStrideFactor_ + << " tex_bayer_first_red " << textureUniformBayerFirstRed_ + << " proj_matrix " << textureUniformProjMatrix_; + return 0; +} + +int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputFormat) +{ + std::vector shaderEnv; + unsigned int fragmentShaderDataLen; + unsigned char *fragmentShaderData; + unsigned int vertexShaderDataLen; + unsigned char *vertexShaderData; + GLenum err; + + // Target gles 100 glsl requires "#version x" as first directive in shader + egl_.pushEnv(shaderEnv, "#version 100"); + + // Specify GL_OES_EGL_image_external + egl_.pushEnv(shaderEnv, "#extension GL_OES_EGL_image_external: enable"); + + // Tell shaders how to re-order output taking account of how the + // pixels are actually stored by GBM + switch (outputFormat) { + case formats::ARGB8888: + case formats::XRGB8888: + break; + case formats::ABGR8888: + case formats::XBGR8888: + egl_.pushEnv(shaderEnv, "#define SWAP_BLUE"); + break; + default: + goto invalid_fmt; + } + + // Pixel location parameters + glFormat_ = GL_LUMINANCE; + bytesPerPixel_ = 1; + 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; + } + 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; + } + break; + default: + goto invalid_fmt; + break; + }; + + if (ccmEnabled_) { + // Run the CCM if available + egl_.pushEnv(shaderEnv, "#define APPLY_CCM_PARAMETERS"); + } else { + // Flag to shaders that we have parameter gain tables + egl_.pushEnv(shaderEnv, "#define APPLY_RGB_PARAMETERS"); + } + + if (egl_.compileVertexShader(vertexShaderId_, vertexShaderData, vertexShaderDataLen, shaderEnv)) + goto compile_fail; + + if (egl_.compileFragmentShader(fragmentShaderId_, fragmentShaderData, fragmentShaderDataLen, shaderEnv)) + goto compile_fail; + + if (egl_.linkProgram(programId_, vertexShaderId_, fragmentShaderId_)) + goto link_fail; + + egl_.dumpShaderSource(vertexShaderId_); + egl_.dumpShaderSource(fragmentShaderId_); + + /* Ensure we set the programId_ */ + egl_.useProgram(programId_); + err = glGetError(); + if (err != GL_NO_ERROR) + goto program_fail; + + if (getShaderVariableLocations()) + goto parameters_fail; + + return 0; + +parameters_fail: + LOG(Debayer, Error) << "Program parameters fail"; + return -ENODEV; + +program_fail: + LOG(Debayer, Error) << "Use program error " << err; + return -ENODEV; + +link_fail: + LOG(Debayer, Error) << "Linking program fail"; + return -ENODEV; + +compile_fail: + LOG(Debayer, Error) << "Compile debayer shaders fail"; + return -ENODEV; + +invalid_fmt: + LOG(Debayer, Error) << "Unsupported input output format combination"; + return -EINVAL; +} + +int DebayerEGL::configure(const StreamConfiguration &inputCfg, + const std::vector> &outputCfgs, + bool ccmEnabled) +{ + GLint maxTextureImageUnits; + + if (getInputConfig(inputCfg.pixelFormat, inputConfig_) != 0) + return -EINVAL; + + if (stats_->configure(inputCfg) != 0) + return -EINVAL; + + const Size &stats_pattern_size = stats_->patternSize(); + if (inputConfig_.patternSize.width != stats_pattern_size.width || + inputConfig_.patternSize.height != stats_pattern_size.height) { + LOG(Debayer, Error) + << "mismatching stats and debayer pattern sizes for " + << inputCfg.pixelFormat.toString(); + return -EINVAL; + } + + inputConfig_.stride = inputCfg.stride; + width_ = inputCfg.size.width; + height_ = inputCfg.size.height; + ccmEnabled_ = ccmEnabled; + + if (outputCfgs.size() != 1) { + LOG(Debayer, Error) + << "Unsupported number of output streams: " + << outputCfgs.size(); + return -EINVAL; + } + + if (gbmSurface_.createDevice()) + return -ENODEV; + + if (egl_.initEGLContext(&gbmSurface_)) + return -ENODEV; + + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits); + + LOG(Debayer, Debug) << "Available fragment shader texture units " << maxTextureImageUnits; + + if (!ccmEnabled && maxTextureImageUnits < DEBAYER_EGL_MIN_SIMPLE_RGB_GAIN_TEXTURE_UNITS) { + LOG(Debayer, Error) << "Fragment shader texture unit count " << maxTextureImageUnits + << " required minimum for RGB gain table lookup " << DEBAYER_EGL_MIN_SIMPLE_RGB_GAIN_TEXTURE_UNITS + << " try using an identity CCM "; + return -ENODEV; + } + + StreamConfiguration &outputCfg = outputCfgs[0]; + SizeRange outSizeRange = sizes(inputCfg.pixelFormat, inputCfg.size); + std::tie(outputConfig_.stride, outputConfig_.frameSize) = + strideAndFrameSize(outputCfg.pixelFormat, outputCfg.size); + + if (!outSizeRange.contains(outputCfg.size) || outputConfig_.stride != outputCfg.stride) { + LOG(Debayer, Error) + << "Invalid output size/stride: " + << "\n " << outputCfg.size << " (" << outSizeRange << ")" + << "\n " << outputCfg.stride << " (" << outputConfig_.stride << ")"; + return -EINVAL; + } + + window_.x = ((inputCfg.size.width - outputCfg.size.width) / 2) & + ~(inputConfig_.patternSize.width - 1); + window_.y = ((inputCfg.size.height - outputCfg.size.height) / 2) & + ~(inputConfig_.patternSize.height - 1); + window_.width = outputCfg.size.width; + window_.height = outputCfg.size.height; + + /* + * Don't pass x,y from window_ since process() already adjusts for it. + * But crop the window to 2/3 of its width and height for speedup. + */ + stats_->setWindow(Rectangle(window_.size())); + + // Raw bayer input as texture + eglImageBayerIn_ = new eGLImage(width_, height_, 32, inputCfg.stride, GL_TEXTURE0, 0); + if (!eglImageBayerIn_) + return -ENOMEM; + + // Only do the RGB lookup table textures if CCM is disabled + if (!ccmEnabled_) { + + /// RGB correction tables as 2d textures + // eGL doesn't support glTexImage1D so we do a little hack with 2D to compensate + eglImageRedLookup_ = new eGLImage(DebayerParams::kRGBLookupSize, 1, 32, GL_TEXTURE1, 1); + if (!eglImageRedLookup_) + return -ENOMEM; + + eglImageGreenLookup_ = new eGLImage(DebayerParams::kRGBLookupSize, 1, 32, GL_TEXTURE2, 2); + if (!eglImageGreenLookup_) + return -ENOMEM; + + eglImageBlueLookup_ = new eGLImage(DebayerParams::kRGBLookupSize, 1, 32, GL_TEXTURE3, 3); + if (!eglImageBlueLookup_) + return -ENOMEM; + } + + eglImageBayerOut_ = new eGLImage(outputCfg.size.width, outputCfg.size.height, 32, outputCfg.stride, GL_TEXTURE4, 4); + if (!eglImageBayerOut_) + return -ENOMEM; + + if (initBayerShaders(inputCfg.pixelFormat, outputCfg.pixelFormat)) + return -EINVAL; + + return 0; +} + +Size DebayerEGL::patternSize(PixelFormat inputFormat) +{ + DebayerEGL::DebayerInputConfig config; + + if (getInputConfig(inputFormat, config) != 0) + return {}; + + return config.patternSize; +} + +std::vector DebayerEGL::formats(PixelFormat inputFormat) +{ + DebayerEGL::DebayerInputConfig config; + + if (getInputConfig(inputFormat, config) != 0) + return std::vector(); + + return config.outputFormats; +} + +std::tuple +DebayerEGL::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) +{ + DebayerEGL::DebayerOutputConfig config; + + if (getOutputConfig(outputFormat, config) != 0) + return std::make_tuple(0, 0); + + /* Align stride to 256 bytes as a generic GPU memory access alignment */ + unsigned int stride = libcamera::utils::alignUp(size.width * config.bpp / 8, 256); + + return std::make_tuple(stride, stride * size.height); +} + +void DebayerEGL::setShaderVariableValues(DebayerParams ¶ms) +{ + /* + * Raw Bayer 8-bit, and packed raw Bayer 10-bit/12-bit formats + * are stored in a GL_LUMINANCE texture. The texture width is + * equal to the stride. + */ + GLfloat firstRed[] = { firstRed_x_, firstRed_y_ }; + GLfloat imgSize[] = { (GLfloat)width_, + (GLfloat)height_ }; + GLfloat Step[] = { static_cast(bytesPerPixel_) / (inputConfig_.stride - 1), + 1.0f / (height_ - 1) }; + GLfloat Stride = 1.0f; + GLfloat scaleX = (GLfloat)window_.width / width_; + GLfloat scaleY = (GLfloat)window_.height / height_; + GLfloat transX = -(1.0f - scaleX); + GLfloat transY = -(1.0f - scaleY); + GLfloat scale = std::max(scaleX, scaleY); + GLfloat projMatrix[] = { + scale, 0, 0, 0, + 0, scale, 0, 0, + 0, 0, 1, 0, + transX, transY, 0, 1 + }; + + // vertexIn - bayer_8.vert + glEnableVertexAttribArray(attributeVertex_); + glVertexAttribPointer(attributeVertex_, 2, GL_FLOAT, GL_TRUE, + 2 * sizeof(GLfloat), vcoordinates); + + // textureIn - bayer_8.vert + glEnableVertexAttribArray(attributeTexture_); + glVertexAttribPointer(attributeTexture_, 2, GL_FLOAT, GL_TRUE, + 2 * sizeof(GLfloat), tcoordinates); + + // Set the sampler2D to the respective texture unit for each texutre + // To simultaneously sample multiple textures we need to use multiple + // texture units + glUniform1i(textureUniformBayerDataIn_, eglImageBayerIn_->texture_unit_uniform_id_); + + // These values are: + // firstRed = tex_bayer_first_red - bayer_8.vert + // imgSize = tex_size - bayer_8.vert + // step = tex_step - bayer_8.vert + // Stride = stride_factor identity.vert + // textureUniformProjMatri = No scaling + glUniform2fv(textureUniformBayerFirstRed_, 1, firstRed); + glUniform2fv(textureUniformSize_, 1, imgSize); + glUniform2fv(textureUniformStep_, 1, Step); + glUniform1f(textureUniformStrideFactor_, Stride); + glUniformMatrix4fv(textureUniformProjMatrix_, 1, GL_FALSE, projMatrix); + + LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ + << " tex_y " << textureUniformBayerDataIn_ + << " red_param " << textureUniformRedLookupDataIn_ + << " green_param " << textureUniformGreenLookupDataIn_ + << " blue_param " << textureUniformBlueLookupDataIn_ + << " tex_step " << textureUniformStep_ + << " tex_size " << textureUniformSize_ + << " stride_factor " << textureUniformStrideFactor_ + << " tex_bayer_first_red " << textureUniformBayerFirstRed_; + + LOG (Debayer, Debug) << "textureUniformY_ = 0 " + << " firstRed.x " << firstRed[0] + << " firstRed.y " << firstRed[1] + << " textureUniformSize_.width " << imgSize[0] + << " textureUniformSize_.height " << imgSize[1] + << " textureUniformStep_.x " << Step[0] + << " textureUniformStep_.y " << Step[1] + << " textureUniformStrideFactor_ " << Stride + << " textureUniformProjMatrix_ " << textureUniformProjMatrix_; + + if (!ccmEnabled_) { + glUniform1i(textureUniformRedLookupDataIn_, eglImageRedLookup_->texture_unit_uniform_id_); + glUniform1i(textureUniformGreenLookupDataIn_, eglImageGreenLookup_->texture_unit_uniform_id_); + glUniform1i(textureUniformBlueLookupDataIn_, eglImageBlueLookup_->texture_unit_uniform_id_); + + egl_.createTexture2D(eglImageRedLookup_, GL_LUMINANCE, DebayerParams::kRGBLookupSize, 1, ¶ms.red); + egl_.createTexture2D(eglImageGreenLookup_, GL_LUMINANCE, DebayerParams::kRGBLookupSize, 1, ¶ms.green); + egl_.createTexture2D(eglImageBlueLookup_, GL_LUMINANCE, DebayerParams::kRGBLookupSize, 1, ¶ms.blue); + + LOG (Debayer, Debug) << "textureUniformRedLookupDataIn_ " << textureUniformRedLookupDataIn_ + << " textureUniformGreenLookupDataIn_ " << textureUniformGreenLookupDataIn_ + << " textureUniformBlueLookupDataIn_ " << textureUniformBlueLookupDataIn_; + } else { + GLfloat ccm[9] = { + params.ccm[0][0], params.ccm[0][1], params.ccm[0][2], + params.ccm[1][0], params.ccm[1][1], params.ccm[1][2], + params.ccm[2][0], params.ccm[2][1], params.ccm[2][2], + }; + glUniformMatrix3fv(ccmUniformDataIn_, 1, GL_FALSE, ccm); + LOG (Debayer, Debug) << " ccmUniformDataIn_ " << ccmUniformDataIn_ << " data " << params.ccm; + } + + /* + * 0 = Red, 1 = Green, 2 = Blue + */ + glUniform3f(blackLevelUniformDataIn_, params.blackLevel[0], params.blackLevel[1], params.blackLevel[2]); + LOG (Debayer, Debug) << " blackLevelUniformDataIn_ " << blackLevelUniformDataIn_ << " data " << params.blackLevel; + + /* + * Gamma + */ + glUniform1f(gammaUniformDataIn_, params.gamma); + LOG (Debayer, Debug) << " gammaUniformDataIn_ " << gammaUniformDataIn_ << " data " << params.gamma; + + /* + * Contrast + */ + glUniform1f(contrastUniformDataIn_, params.contrast); + LOG (Debayer, Debug) << " contrastUniformDataIn_ " << contrastUniformDataIn_ << " data " << params.contrast; + + return; +} + +int DebayerEGL::debayerGPU(MappedFrameBuffer &in, int out_fd, DebayerParams ¶ms) +{ + /* eGL context switch */ + egl_.makeCurrent(); + + /* Greate a standard texture input */ + egl_.createTexture2D(eglImageBayerIn_, glFormat_, inputConfig_.stride / bytesPerPixel_, height_, in.planes()[0].data()); + + /* Generate the output render framebuffer as render to texture */ + egl_.createOutputDMABufTexture2D(eglImageBayerOut_, out_fd); + + setShaderVariableValues(params); + glViewport(0, 0, width_, height_); + glClear(GL_COLOR_BUFFER_BIT); + glDrawArrays(GL_TRIANGLE_FAN, 0, DEBAYER_OPENGL_COORDS); + + GLenum err = glGetError(); + if (err != GL_NO_ERROR) { + LOG(eGL, Error) << "Drawing scene fail " << err; + return -ENODEV; + } else { + egl_.syncOutput(); + } + + return 0; +} + +void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, DebayerParams params) +{ + bench_.startFrame(); + + std::vector dmaSyncers; + + dmaSyncBegin(dmaSyncers, input, nullptr); + + setParams(params); + + /* Copy metadata from the input buffer */ + FrameMetadata &metadata = output->_d()->metadata(); + metadata.status = input->metadata().status; + metadata.sequence = input->metadata().sequence; + metadata.timestamp = input->metadata().timestamp; + + MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read); + if (!in.isValid()) { + LOG(Debayer, Error) << "mmap-ing buffer(s) failed"; + goto error; + } + + if (debayerGPU(in, output->planes()[0].fd.get(), params)) { + LOG(Debayer, Error) << "debayerGPU failed"; + goto error; + } + + bench_.finishFrame(); + + metadata.planes()[0].bytesused = output->planes()[0].length; + + /* Calculate stats for the whole frame */ + stats_->processFrame(frame, 0, input); + dmaSyncers.clear(); + + outputBufferReady.emit(output); + inputBufferReady.emit(input); + + return; + +error: + bench_.finishFrame(); + metadata.status = FrameMetadata::FrameError; + return; +} + +void DebayerEGL::stop() +{ + egl_.cleanUp(); +} + +SizeRange DebayerEGL::sizes(PixelFormat inputFormat, const Size &inputSize) +{ + Size patternSize = this->patternSize(inputFormat); + unsigned int borderHeight = patternSize.height; + + if (patternSize.isNull()) + return {}; + + /* No need for top/bottom border with a pattern height of 2 */ + if (patternSize.height == 2) + borderHeight = 0; + + /* + * For debayer interpolation a border is kept around the entire image + * and the minimum output size is pattern-height x pattern-width. + */ + if (inputSize.width < (3 * patternSize.width) || + inputSize.height < (2 * borderHeight + patternSize.height)) { + LOG(Debayer, Warning) + << "Input format size too small: " << inputSize.toString(); + return {}; + } + + return SizeRange(Size(patternSize.width, patternSize.height), + Size((inputSize.width - 2 * patternSize.width) & ~(patternSize.width - 1), + (inputSize.height - 2 * borderHeight) & ~(patternSize.height - 1)), + patternSize.width, patternSize.height); +} + +} /* namespace libcamera */ diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h new file mode 100644 index 000000000..33067c463 --- /dev/null +++ b/src/libcamera/software_isp/debayer_egl.h @@ -0,0 +1,177 @@ +/* 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 +#include + +#include + +#include "debayer.h" + +#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" + +namespace libcamera { + +#define DEBAYER_EGL_MIN_SIMPLE_RGB_GAIN_TEXTURE_UNITS 4 +#define DEBAYER_OPENGL_COORDS 4 + +/** + * \class DebayerEGL + * \brief Class for debayering using an EGL Shader + * + * Implements an EGL shader based debayering solution. + */ +class DebayerEGL : public Debayer +{ +public: + /** + * \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(std::unique_ptr stats, const GlobalConfiguration &configuration); + ~DebayerEGL(); + + /* + * Setup the Debayer object according to the passed in parameters. + * Return 0 on success, a negative errno value on failure + * (unsupported parameters). + */ + int configure(const StreamConfiguration &inputCfg, + const std::vector> &outputCfgs, + bool ccmEnabled); + + /* + * Get width and height at which the bayer-pattern repeats. + * Return pattern-size or an empty Size for an unsupported inputFormat. + */ + Size patternSize(PixelFormat inputFormat); + + std::vector formats(PixelFormat input); + std::tuple strideAndFrameSize(const PixelFormat &outputFormat, const Size &size); + + void process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, DebayerParams params); + void stop(); + + const SharedFD &getStatsFD() { return stats_->getStatsFD(); } + + /** + * \brief Get the output frame size. + * + * \return The output frame size. + */ + unsigned int frameSize() { return outputConfig_.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 + eGLImage *eglImageBayerIn_; + eGLImage *eglImageBayerOut_; + + eGLImage *eglImageRedLookup_; + eGLImage *eglImageGreenLookup_; + eGLImage *eglImageBlueLookup_; + + // Shader parameters + float firstRed_x_; + float firstRed_y_; + GLint attributeVertex_; + GLint attributeTexture_; + GLint textureUniformStep_; + GLint textureUniformSize_; + GLint textureUniformStrideFactor_; + GLint textureUniformBayerFirstRed_; + GLint textureUniformProjMatrix_; + + GLint textureUniformBayerDataIn_; + + // These textures will either point to simple RGB gains or to CCM lookup tables + GLint textureUniformRedLookupDataIn_; + GLint textureUniformGreenLookupDataIn_; + GLint textureUniformBlueLookupDataIn_; + + // Represent per-frame CCM as a uniform vector of floats 3 x 3 + GLint ccmUniformDataIn_; + bool ccmEnabled_; + + // Black Level compensation + GLint blackLevelUniformDataIn_; + + // Gamma + GLint gammaUniformDataIn_; + + // Contrast + GLint contrastUniformDataIn_; + + Rectangle window_; + std::unique_ptr stats_; + eGL egl_; + GBM gbmSurface_; + uint32_t width_; + uint32_t height_; + GLint glFormat_; + unsigned int bytesPerPixel_; + GLfloat vcoordinates[DEBAYER_OPENGL_COORDS][2] = { + { -1.0f, -1.0f }, + { -1.0f, +1.0f }, + { +1.0f, +1.0f }, + { +1.0f, -1.0f }, + }; + GLfloat tcoordinates[DEBAYER_OPENGL_COORDS][2] = { + { 0.0f, 0.0f }, + { 0.0f, 1.0f }, + { 1.0f, 1.0f }, + { 1.0f, 0.0f }, + }; +}; + +} /* namespace libcamera */ diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build index 59fa5f02a..c61ac7d59 100644 --- a/src/libcamera/software_isp/meson.build +++ b/src/libcamera/software_isp/meson.build @@ -2,6 +2,7 @@ softisp_enabled = pipelines.contains('simple') summary({'SoftISP support' : softisp_enabled}, section : 'Configuration') +summary({'SoftISP GPU acceleration' : gles_headless_enabled}, section : 'Configuration') if not softisp_enabled subdir_done() @@ -14,3 +15,10 @@ libcamera_internal_sources += files([ 'software_isp.cpp', 'swstats_cpu.cpp', ]) + +if softisp_enabled and gles_headless_enabled + config_h.set('HAVE_DEBAYER_EGL', 1) + libcamera_internal_sources += files([ + 'debayer_egl.cpp', + ]) +endif From patchwork Thu Nov 20 23:33: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: 25136 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 7AFFFBD80A for ; Thu, 20 Nov 2025 23:34:18 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2FF9460AB4; Fri, 21 Nov 2025 00:34:18 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="Rwpz8LST"; dkim-atps=neutral Received: from mail-wr1-x42f.google.com (mail-wr1-x42f.google.com [IPv6:2a00:1450:4864:20::42f]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5404160A9E for ; Fri, 21 Nov 2025 00:34:16 +0100 (CET) Received: by mail-wr1-x42f.google.com with SMTP id ffacd0b85a97d-42b3c965cc4so761815f8f.0 for ; Thu, 20 Nov 2025 15:34:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681655; x=1764286455; 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=G8zMAGQq6mymklwrKMC5SwdL3ECQAZ0ptGN/pXi2LRU=; b=Rwpz8LSTz2TF1W4uS462QWUInXtNEnJ8hJ8ZSWL7Fm+pgOrOeQabHgzyGroLF7+bWm dVmixV13mHBSLGDGbvpwEXdm3n8tdfdjYPW5SfabKYv1qsjC3TqpYcV/xMmxFaDU/9kj Mzyzc5cINlhSo9yOHg6+bb6Z+ayzQ4u4u/kGRKW+J6Dj0Psaa5cQcFs41qK+UBaqU8Un 7pvyLxPj2Yg1l+6UjxzJbhjPxYzc4oIKpKz1JMj0dhuTPjYzxJwSVEUY52TQxNeBcSaL sDxmjze0lugCYNTuW4pjqh7Rw/cD4XNYc98WRjrH2tX0Sa4fXQyWhmOull93tSC5jx0v ynMQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681655; x=1764286455; 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=G8zMAGQq6mymklwrKMC5SwdL3ECQAZ0ptGN/pXi2LRU=; b=qCanOI3Bh+9ZWHPF+etZodnoSgTDmmq7KjEGArryAlBX8VHzU+xI/niUtmTmJQMzXA S53NoEu4Dw0uPj1xuIqBQ7CwYiKYoajdvELuSaFrMiMp5/9Y9iSehhdO2OYBq5egwL0r 2SkU3APG6rtxdxASa4AiAhH6UM/Rt1CnBvPatyciyyMQtmeX63prQNnm4J8k58nyrOX/ MMnEBjHq0HjouwOxyMzgm9ZP9wwPa4h/NiWBM+ZpOEHOYl9c6bGgB0XTi4m6ryD69+MG Hrg8a4nTZdelF1ZxAAVlCgyP1T2cTdRksEFoJTOaaS1aXknrtvoQ/+0rzDlXKLfUmakc 2A/g== X-Gm-Message-State: AOJu0YzaH9EXmajoAriVGI1VXbqbS9diFdz86/tOpuYNIkMNuOGBj/8Z uPN5HmIyse5udw8EdnFSThhUHxn801xWbC3pSNORMgShGOsjALWHrGTyBR6oQTSOqSPlItwsYoW mhGKTMZw= X-Gm-Gg: ASbGncvsLEgnSRphvjEcBzFCgiHOKU2H8aUDFrKCnWZ7tWEtI/IfMoiCr5pU4sQ4o4d 7qqy4kmEFDUxELMVjARmmAASt05HbAWCFyIw1H+LQU/+/ZDrhU2RRAb6mIbvzMOvCla58Gvv/HZ e2AX515Qg/fO6NmJt75LN0fd1d5J6Eygzf/eieJijyKjy4rQydf6ehchsxwTfwpeICtxk0ZdFvk Y8ZW0Djz5FzEnqM5zBZhmmg9J+4yU65I9ybwpnuq4yKEgzfOdaBdmm/tqnbuyA3SO+OxUarGIzB b7+w1pU2FKaCDcXWYYJJH0/swkXGnKIDGzDB90y30e8xBjaRwqSsPO3zWXXEvewsht/8CCGW5VT 07PeIT4HG6uZQf/aBGdEPCXAkUxpb+xLZLZVCI7zA4jhMGOBa7gaFRQBnrkvWXOpfzvtN3uI/Xl sqzXsXLD/gFQGMw/zabeubGOSCjlaDuN4zh5adDlJx7gmaTTKSQvbtqGLTDnNam4eIosI= X-Google-Smtp-Source: AGHT+IHxbEOjEy0v74DHsvBQdcNGg4lHoqrJjhMg0Ubs1s9LpmIlhWPlJ3T3/8V0az0HruGhTY1rnw== X-Received: by 2002:a5d:5f88:0:b0:42b:3383:bcf4 with SMTP id ffacd0b85a97d-42cba63b5bfmr5407313f8f.1.1763681655552; Thu, 20 Nov 2025 15:34:15 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.34.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:34:14 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v4 12/23] libcamera: software_isp: debayer_egl: Make DebayerEGL an environment option Date: Thu, 20 Nov 2025 23:33:36 +0000 Message-ID: <20251120233347.5046-13-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" If GPUISP support is available make it so an environment variable can switch it on. Given we don't have full feature parity with CPUISP just yet on pixel format output, we should default to CPUISP mode giving the user the option to switch on GPUISP by setting LIBCAMERA_SOFTISP_MODE=gpu Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/software_isp.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index aa4a40cb6..7d21f191c 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,20 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, } stats->statsReady.connect(this, &SoftwareIsp::statsReady); - debayer_ = std::make_unique(std::move(stats), configuration); +#if HAVE_DEBAYER_EGL + const char *softISPMode = utils::secure_getenv("LIBCAMERA_SOFTISP_MODE"); + + if (softISPMode && !strcmp(softISPMode, "gpu")) + debayer_ = std::make_unique(std::move(stats), configuration); +#endif + if (!debayer_) + debayer_ = std::make_unique(std::move(stats), configuration); + + if (!debayer_) { + LOG(SoftwareIsp, Error) << "Failed to create Debayer object"; + return; + } + debayer_->inputBufferReady.connect(this, &SoftwareIsp::inputReady); debayer_->outputBufferReady.connect(this, &SoftwareIsp::outputReady); From patchwork Thu Nov 20 23:33: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: 25137 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 AFC14BD80A for ; Thu, 20 Nov 2025 23:34:20 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 51D2E60AC8; Fri, 21 Nov 2025 00: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="O2YUoith"; dkim-atps=neutral Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E2FF160AA2 for ; Fri, 21 Nov 2025 00:34:17 +0100 (CET) Received: by mail-wr1-x42e.google.com with SMTP id ffacd0b85a97d-42b3b29153fso858624f8f.3 for ; Thu, 20 Nov 2025 15:34:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681657; x=1764286457; 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=w7kqIVIEHI/hwzMu7gLLNDIA8aJkeSYOyl1cHM2SUhY=; b=O2YUoithUS8Nb81yXVROini0oJocs08eovJxV8mBWaR4XUNqX/7WXvnsHdKt8/C0Mv rqkjDsoNyYq6PunE8AjVeMFSqxgXAk1dmjJXEf+nS50J/uIilp7fzSy95+lhhe4v2MoL LNVjztt/cP8PJcyDwrQYUSzyAb6SCbhW88P7jUVnzajsGvazA7zejtw9oKqtZcjcfDfa Nst6aChJR9hWNKyOJSuQ2taxTBLZxTKatjakLy/ZAVCV6tNGUaq9xPtj3OBlW0n16m2R emMBEZjG1i22l4RQyVC9QEW3mTTloSkqUxIruW1zjIqZHPYbHmiilMhLs4YwZQ9ODPTg tGBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681657; x=1764286457; 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=w7kqIVIEHI/hwzMu7gLLNDIA8aJkeSYOyl1cHM2SUhY=; b=pdQBDl4aTh/2GRoBYXF+DzExkGETjvxpksY3f3fzvLvQgZJY6SFrH7+VN2gqwIZApv abLqkY+2r0H3Ygydzm0o+bzIrkOcco4NpnlfdLdCwgRVlK20lvL+HVSQ8GnPWNJlqVhC C3zHbpwLFyz4swwS9fgQVqiDJrfAGEka2gtQNL6c9RDje+Sj2VqP042G9DIMqRks0+TM H8+ssDYASdWb3kN4TVJS8ag/3n9oF3wxTmbD+vg7vnKlB2LHLAPCntcNAYikbDCk8cOe Ymc+aAzK5GATTAWGj3P4XJCT+UGKJAm3WeMwTAs7aL/yq1E/uh891hkgaBaeX7+h0mEE Dk/g== X-Gm-Message-State: AOJu0YyrvJM549RE1vI8Sf9h5As1XN5p2thB3bRnIYWltqojylhJowuh 7FF4jDJZBmZwPV6E3xFJewbU61GP+sfZmCdF5ZQH9HWn3mKNZVYI+0IrxU/PCB1egfw9Q1SFwfG a/AyEwfw= X-Gm-Gg: ASbGncvBXwGvKg1sSqG1/zx0fThq4cWpnH8HXyM47oZKYXoZYj2eBVPwSvuoTQuFhVz sAoOlagd0BnY7UgT07To0ubG3iDXayy8u8P2Qa2HzGTzX5wFiaa47NLPyjzZLOZOGXfLAIbQZ/2 sepdymaj3zInP+d8ZZo8TJ1w0yPVY6Wp441JI8XCUHHVB8koo+io0sBKSM39jd3Ec1x6aQY3PBX t2hBVJxZ/TF5edojq7D2NrCWaCsG/NZ5WpNqS0JGua4uX8LnRa2G+HpT2MNGJrrPWjylfThEEHV yq6+UZT1Aohd9jEaTkdANb458ysEfqEoummN1e4S/RmdoIPMiiofYI2wK/ZWUAGRo4ohwzEkz2c vYBDVE62HvCPXAvfTtBRYSKNnTWi7d4hiQWvzXiymJpjJNwN3yFPz3iaG5mxCDYNMpjSRaM/5bA va3SLb54jfJN1E2xH8v4MOjZuAhmRCIca7Bo73gBeA9LXMZcVVphwuytf2+LeYPhTP7L8= X-Google-Smtp-Source: AGHT+IFB1izsyEpkjdRGqy6ctUKF+EqW3cffPdIFHiBGGwQguZlmu0FgtXN8rU83kQ/Ca8GWOiNoCA== X-Received: by 2002:a5d:64e6:0:b0:42b:36f4:cd20 with SMTP id ffacd0b85a97d-42cc1d2e292mr84540f8f.27.1763681657247; Thu, 20 Nov 2025 15:34:17 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.34.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:34:16 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v4 13/23] libcamera: software_isp: debayer_egl: Make gpuisp default softisp mode Date: Thu, 20 Nov 2025 23:33:37 +0000 Message-ID: <20251120233347.5046-14-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" In some cases the GPU can deliver 15x performance in Debayer with the CCM on, reference hardware Qualcomm RB5 with IMX512 sensor. Given this large performance difference it makes sense to make GPUISP the default for the Software ISP. If LIBCAMERA_SOFTISP_MODE is omitted gpu will be the default. If libcamera is compiled without gpuisp support, CPU Debayer will be used. It is still possible to select CPU mode with LIBCAMERA_SOFISP_MODE=cpu. Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/software_isp.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index 7d21f191c..9944ca573 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -121,10 +121,17 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, } stats->statsReady.connect(this, &SoftwareIsp::statsReady); -#if HAVE_DEBAYER_EGL const char *softISPMode = utils::secure_getenv("LIBCAMERA_SOFTISP_MODE"); + if (softISPMode) { + if (strcmp(softISPMode, "gpu") && strcmp(softISPMode, "cpu")) { + LOG(SoftwareIsp, Error) << "LIBCAMERA_SOFISP_MODE " << softISPMode << " invalid. " + << "must be \"cpu\" or \"gpu\""; + return; + } + } - if (softISPMode && !strcmp(softISPMode, "gpu")) +#if HAVE_DEBAYER_EGL + if (!softISPMode || !strcmp(softISPMode, "gpu")) debayer_ = std::make_unique(std::move(stats), configuration); #endif if (!debayer_) From patchwork Thu Nov 20 23:33:38 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25138 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 B8E88BD80A for ; Thu, 20 Nov 2025 23:34:22 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5D7F960B0B; Fri, 21 Nov 2025 00: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="iomcvW2P"; dkim-atps=neutral Received: from mail-wm1-x334.google.com (mail-wm1-x334.google.com [IPv6:2a00:1450:4864:20::334]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B83D260A9E for ; Fri, 21 Nov 2025 00:34:19 +0100 (CET) Received: by mail-wm1-x334.google.com with SMTP id 5b1f17b1804b1-4779aa4f928so13903275e9.1 for ; Thu, 20 Nov 2025 15:34:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681659; x=1764286459; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=U4gZBzqGbQfvRAdn9kIktQq170/k2VAqruGy17o40mc=; b=iomcvW2PZSqpWl99asYmYACa/mZ6kGkSWbPfr1mQQBOetAm9p+vuIYIQD2TZjDzJQ5 +fkhcGKj+xgtZvgYnMlZ3tgPtsVG1Wfx+PrYFnOY6BgbH5l6W9RX94NWa2RveUdkGSPc yQxWogYDnJRjLaB0grbRSU3tKE5TYuQpDGWhmE1vuDJZet2pPare5gEOo7CsTHZ6LoPW pC19CsXcgbqCBoG8r1JM/0e9z8toAQnBxKoTCJ4uE+/W/783IuKyBMl48QlLMarLU3// soYb4QHWGUEmpo2u/fXBrf1/kkyVfTL9d7V6ZObUgTBhO597lgwqu6lIsdRLxGuBSEQE tjhQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681659; x=1764286459; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=U4gZBzqGbQfvRAdn9kIktQq170/k2VAqruGy17o40mc=; b=pUsvD0IjL/K+EO8eaKMIXLtaOjTvsNSYHqCK+YOu86hWZGeQCseCDAg7PfGUwh3lkt IEhXX2EJyx99yG0lMt/MJYA7/saggrmzcvBptLV+9kB817RbfmKAO3c8BIvxG8HMnTTI sbPF5kH//HZ2rUo1fBvHN+eM1qn3GkGw362UbyvWcERR/L3ke5YGNVFpUuatzCQMOSg9 2cK7PsOreVdR5nPdxliT87reD1AxemBHFw0OfyfkdSPuW8G0IorlhRBNMKB+cvmf/7ar 4TIfyGj/G+L5TM+08SWjwqeu4ZgBByQio0bR/B9DVPZwOe0MAAc+d4JkNT8KRVy0vMyQ LBPA== X-Gm-Message-State: AOJu0YwymB107nCnPUdMbKfXB9eWNbE+qNW2d3OseoZN3pJM5z6IZWs8 BMK6jvyJl0L42I9rcTtWfXdETWuBescXHRS+vJ6v2DXYy/V4ttVShouD7bsDa+EdtRQ2cBq2KdS 2xCWwdnY= X-Gm-Gg: ASbGncuTXmEp0gKFs5lDL4Sz39/OtlunN+1SaPEWVN1ZYPH6xyZlNu2a4AEBFBGQDAY HBRSvpyzgcDMnlys+j9jUGezk1/BKARwKbtFILXQR/RoPBfyLTJEGs7CKyXiFgOYQCR9zxG5EHJ TRHzhmS+RVcb7fbSD4zFThzB3/sNBYawM+UMV7yluYJfZhh+J4gQABXV2wL+3pRTcaInwoJMMUQ GBkxxE3SAMawiXXqHqs5N7sRjcb8eSyZf+BwKX1STWLsSVmNXY8caFG8uwVDdDq8jRAMU0NizDG uVkBkHmbfN4vCnHJ1hIvmRt3O4KyZJCLw2KupO+KVFl79Jyw8hLtLXir5YU/jblrispzC02RtWG clhkJ+xM7aUHDDQrbOiTF2ouIcIJN0VcOuYZ7ZmQwysR8xfBIbHTRkpLx5r6f8eX4me7QeCi1YW YXjY28/9ffuX/eVfGZY6J5nxNhN5hf5KWjH0NTjngna8qpgRonMOZj1KEzbVQP4n5XCVQ= X-Google-Smtp-Source: AGHT+IHHhEiVs7+Pxy6H5m+Lik7EgWWji3ChGHb8KMZJsQQ5PHzSdmIoLZDHuonNghWtGknp0VtZnQ== X-Received: by 2002:a05:600c:19d2:b0:476:4efc:8ed4 with SMTP id 5b1f17b1804b1-477c0184965mr3221425e9.11.1763681659053; Thu, 20 Nov 2025 15:34:19 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.34.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:34:17 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Kieran Bingham Subject: [PATCH v4 14/23] libcamera: software_isp: debayer_cpu: Make getInputConfig and getOutputConfig static Date: Thu, 20 Nov 2025 23:33:38 +0000 Message-ID: <20251120233347.5046-15-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Make getInputConfig and getOutputConfig static so as to allow for interrogation of the supported pixel formats prior to object instantiation. Do this so as to allow the higher level logic make an informed choice between CPU and GPU ISP based on which pixel formats are supported. Currently CPU ISP supports more diverse input and output schemes. Acked-by: Kieran Bingham Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/debayer_cpu.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h index 2d385cf01..a395fc97c 100644 --- a/src/libcamera/software_isp/debayer_cpu.h +++ b/src/libcamera/software_isp/debayer_cpu.h @@ -98,8 +98,8 @@ private: template void debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]); - int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config); - int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config); + static int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config); + static int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config); int setupStandardBayerOrder(BayerFormat::Order order); int setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat, From patchwork Thu Nov 20 23:33:39 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25139 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 F2171BD80A for ; Thu, 20 Nov 2025 23:34:23 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9BA9C60AD2; Fri, 21 Nov 2025 00:34:23 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="YF3aef3H"; dkim-atps=neutral Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8331760A9E for ; Fri, 21 Nov 2025 00:34:21 +0100 (CET) Received: by mail-wr1-x436.google.com with SMTP id ffacd0b85a97d-429c48e05aeso968675f8f.1 for ; Thu, 20 Nov 2025 15:34:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681661; x=1764286461; 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=EbZ/Wuv7VrFPMAILTWJXMItIZK7H6ypYImRnfvuiCeU=; b=YF3aef3HMWLV4PkvzYWMu1zRA74QFsEV0H9fhRJRF9hKWNKWZzUnYmUt73D1FXH2Bu eFrjbSFd4Ve3Kqw3fkaHh7SQtnXdFxly6ts+h2eo49uEh6bzq4BX+S8O6e6y4ic+nl/b t5mB/2gkJsmWjaHVCn8erzL3uNcy8uzzflYJ1vrV/FZXsL4Jn2BjlZEabsHgtkjT25YN qJ74AtLNKroUbpchtHDBlJKKCCXBjq33rleMWQKkOhn4zswYiJHDw7hWM9Mzb5BJTdju zkwSDtFCsp9/0qisKgvrURg8xHyAul+lbsXJMRHQ7e+7jw+6rKHG9cwzHkzJdr8yXBHU U+GA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681661; x=1764286461; 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=EbZ/Wuv7VrFPMAILTWJXMItIZK7H6ypYImRnfvuiCeU=; b=iR403bpQ4++rvMOODmHa2y2l5RLxJP1A2sZkCmfWBCwYZrVMk7fOcv+ZIvZkIUxLqH JhJAaZUXRNw2yyN1JXjfR26wQFHWRSU/kIGYWe1JS55Bl04IPicioeQKis1WCyRTp8yp fL5XM2LFceEwt9bWrCtfwHVIAq4oWqHiM88RDPCJJdflIRhOoe0lth/jZzBPsVEs+3F1 kjZcnFhSfHhm8bFz+bLamMbE/xqFqnDORH4rZ5Jr0K4YUUUW9Y8O774AM9azoXOf1D8l FaxmwFXPNsM9qQInahz6B37WglMRsX0KLE5J9SFh2jjfc54tDYJqbVHZqnJ7qWTn1xD5 /maA== X-Gm-Message-State: AOJu0YyIAA7/EV1WthKov1lsncB+up6hM6K+6TQyBP+lbbzb6+W2Poo4 AgfQeJv9QIsFmNHqmdFFYo3iuESqD7rd/dNlneZp/pGQws+DIE65QNjuWQscVDBNx+Q4zcBN3BC 7O/aDB+M= X-Gm-Gg: ASbGnctLKJ/pkUZARuWzErHlYKFWCwC+hmxm9YNObq96N0w8hDfdVcegqBUvvulfJkv tHDjMnqT7FX4RWic1NBDtMIX3s9nqgQ8JEBejO4GCcoBYkrfCvnx5H7EeRfnac32c1bMRTxPZI3 VPNqU24tQPYnkzgnyP2kjroitOZZhcMWZ9Jv436UNZxHBiWY11LaYM29eG2LAUlBGzyMQRAnd0I bMAJORSvfVuAR7MzNZIYh4HrlR6Z1yscTquAIQMuMEMNIu9RcsdDtZISjAmG/D5/phQoKKetVHd 8L1CZAZAiqYCbgm0LZGk71XkpnrvsJ9TlCWuqVjs4I/LDzbbtFnuIF+uDrFlh87gqNbtbfDGIFX QTSstmBD92d1DML2SEXOkVJ5BcyFCKm/txHsYJTuxzkgtU11qyDDTxPGG893nZaaS99IOTAEdw0 ohbawOFWez9huKgXXjZ6OMB49tttk2AYjmEZuUjz4hkMwtLjBTHCdAIeoX/fGWnzdJ2Wg= X-Google-Smtp-Source: AGHT+IGXGbawGYEbrqSXCDOpenbBj8HkBy7Cxa9Tmi7n+jBH75BL295qfKiP4oDXfoCiMfud6kH8NQ== X-Received: by 2002:a05:6000:228a:b0:428:3d14:7378 with SMTP id ffacd0b85a97d-42cba7b465bmr5092916f8f.24.1763681660908; Thu, 20 Nov 2025 15:34:20 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.34.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:34:19 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Milan Zamazal , Bryan O'Donoghue Subject: [PATCH v4 15/23] libcamera: software_isp: GPU support for unpacked 10/12-bit formats Date: Thu, 20 Nov 2025 23:33:39 +0000 Message-ID: <20251120233347.5046-16-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-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 --- include/libcamera/internal/shaders/bayer_unpacked.frag | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/include/libcamera/internal/shaders/bayer_unpacked.frag b/include/libcamera/internal/shaders/bayer_unpacked.frag index 16262feb2..c519fad1f 100644 --- a/include/libcamera/internal/shaders/bayer_unpacked.frag +++ b/include/libcamera/internal/shaders/bayer_unpacked.frag @@ -47,9 +47,17 @@ float apply_contrast(float normalise, float contrast_in) void main(void) { vec3 rgb; + #if defined(RAW10P) + #define pixel(p) p.r / 4.0 + p.g * 64.0 + #define fetch(x, y) pixel(texture2D(tex_y, vec2(x, y))) + #elif defined(RAW12P) + #define pixel(p) p.r / 16.0 + p.g * 16.0 + #define fetch(x, y) pixel(texture2D(tex_y, vec2(x, y))) + #else #define fetch(x, y) texture2D(tex_y, vec2(x, y)).r + #endif - float C = texture2D(tex_y, center.xy).r; // ( 0, 0) + float C = fetch(center.x, center.y); // ( 0, 0) const vec4 kC = vec4( 4.0, 6.0, 5.0, 5.0) / 8.0; // Determine which of four types of pixels we are on. From patchwork Thu Nov 20 23:33:40 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25140 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 9C110BD80A for ; Thu, 20 Nov 2025 23:34:25 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 52CA260ABD; Fri, 21 Nov 2025 00:34:25 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="CqnKy3nW"; dkim-atps=neutral Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3B18E60AC8 for ; Fri, 21 Nov 2025 00:34:23 +0100 (CET) Received: by mail-wr1-x436.google.com with SMTP id ffacd0b85a97d-42b32900c8bso864615f8f.0 for ; Thu, 20 Nov 2025 15:34:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681662; x=1764286462; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=wNqHKfrdqEnCd6e0vklefM1kTOpuhhmzodWah3Zo3gc=; b=CqnKy3nWwYwaUhj3zsRDEw6nyIp5iJ6dDwxpN47JKFSsCcXzuyqdfWj2FYJpAA5m1m RmQQ4HYmdrF4dhPeyOwq3Ff1oWCH53AXHLlba4A0FfLXqb9JLyPCYq/zkk0lwW4Gc8L3 gpvkrlqkuwFUPtn7llyvKC5lbD6oeBscAx3l9jgeVXBkKOp4ucqXHVGqYMshvTLVwmWD DWr/osD4/5NSUsUTYJYgJB0+pHFd5N3rYzTIgdM4Yf3jJX+YunW3r6NwxZ+z9YiVqL4u qv+clywr1AtMPTNGoJ1lMYvQ8YgE4M5S4LV5J5CI7wj25UUk2jBuhSWhl3k/JDJ+TKuU IQLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681662; x=1764286462; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=wNqHKfrdqEnCd6e0vklefM1kTOpuhhmzodWah3Zo3gc=; b=MsnnOiIjJlRma1J8p75yqusquIhNYu9J0UrVqdzb5F0Frg5VOqekjdpcDAUMkHYPBL 4nESSWoCTcc4vKu8rqtgmzIs6c3CupfFhbVuS/cQpcV96OmXiOtzkQ72smR0U1Sf3QUK Wlw+ji8LpktDRKbBR8QL+lIhs40Oip4EvO4SuYHJFatkNVfLGfxIBRFPokWadtv0ROIk dkOAZ42DmIMsN7KvDewEcrinu2BKWUoVYNCz4HmcGlcLfmcLen6d9L1xzsAjD766kxVN HsT8KZqtBtgj4nANr9BN5Zb/UoDuTUeVVahyvmUk6QfDcXmx/F/Vfgg4qu1gEK47Y5ml hiaw== X-Gm-Message-State: AOJu0YxLYs5LSCs1FVagKol/+LIuRbEvubibWnEestWntVBeCGNQ1vzh AdVnW5CEaZURcRCj4oPpxgR6RBJ+u9hghKrfkbKBz6N/mP9n9IaCP/Iauq0H4F7sMH7Ke2+sspx g4wm8V5k= X-Gm-Gg: ASbGncsgn5ZxQIWYxg01k53Aqk7+MmkWLtev81BXfvUeKj51iE7O5fEMfNjgdm8Av9E vuSdgM+DzuQQ+eVGmDmB8C19jTs4QxJtJ8iAKeNfPWwRzyqdALJwI9WJbhTf1UFoPbyxLglfpui XDpAXzOKjgXxrurrLHGP1YLK4QAoVP6SyTw5+C36bsysN6pvi+fKklPIoEJn5JGKofurhMzA8Ey Z2gKAln83r2Xqeh/+QhtSZZyTjDxqX9XW34rH7jmCgYWFBi+zVHAPsNUk4kbC/1lCY8BG02kZo5 vBq+aZmTVyGm/1I/t27NXmWXdiUeebyngvdinQx7ZkD4NhiTJhZH8/wOQkbBLrc/7pItqJ1cjza 3HK6j0WeEkg0oLADiDQbvNZF+cNIJUWF15ulCPIBK5LHQSCNsgg9iZrtiexlSnEa+3dtTqjVg2I InvQb31ANoXI8GyAg7McysLh1m9b7h+eSG7qQbujFQkbKbHvcSJTT6C6RmNcWqquyC1ng= X-Google-Smtp-Source: AGHT+IEmPtujz+inUvV9REl0YbdLSmwuUj/KiK1njySFp2i+qVnTqISaODHpTwM+UouG0/IA6Uk51w== X-Received: by 2002:a05:6000:400f:b0:42b:3c3e:5d53 with SMTP id ffacd0b85a97d-42cc1cedbf7mr78922f8f.16.1763681662475; Thu, 20 Nov 2025 15:34:22 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.34.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:34:21 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue , Kieran Bingham Subject: [PATCH v4 16/23] libcamera: software_isp: Add a gpuisp todo list Date: Thu, 20 Nov 2025 23:33:40 +0000 Message-ID: <20251120233347.5046-17-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" List the series of things to do in GPU ISP in perceived order of difficulty. Acked-by: Kieran Bingham Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/gpuisp-todo.txt | 83 ++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/libcamera/software_isp/gpuisp-todo.txt diff --git a/src/libcamera/software_isp/gpuisp-todo.txt b/src/libcamera/software_isp/gpuisp-todo.txt new file mode 100644 index 000000000..768dcc320 --- /dev/null +++ b/src/libcamera/software_isp/gpuisp-todo.txt @@ -0,0 +1,83 @@ +List the TODOs in perceived order of ease. + +Version 3: +Use dma-buf handle to generate upload texture: + - eglCreateImageKHR can be used to generate the upload texture i.e. + to feed the bayer data into the GPU. + +Denoising: + - As below still TBD + +Dead pixel correction: + - As below still TBD + +Lense shading correction: + - This is WIP but as yet still TBD + +Lense flare correction: + - Not WIP still TBD + +processFrame() to run in its own thread: + - processFrame() runs in the context of the Debayer::process() + thread. Robert Mader suggested and it seems like a good + suggestion too to run processFrame() in its own thread. + +Version 2: +Make GPUISP default: + - Right now the environment variable allows over-riding to swtich + from CPU to GPU. + - Once we support 24 BPP output on GPUISP we will have the same + pixel format support as CPU and can set the default to GPU without + regressing functionality + +glTexture1D: + - Initial code was developed for < GLES 2.O but since we have fixed + on GLES >= 2.0 this means we can use glTexture1D + - Provided this is so amend the shaders to do val = texture(x, y, 0); + not texture(x, y, 0.5) the 0.5 is because of using glTexture2D + +Denoising: + - Run a denoise algorithm in the shaders + - Supply a control to influence the noise-floor ? + +Dead pixel correction: + - Add logic to correct dead pixels in the fragment shaders + +Version 1: +24 bit output support: + - Take the BPP we already capture and get a 24 bit GBM surface + - Pass a compile-time parameter to the shaders to tell them to do + gl_FragColor = rgb not gl_FragColor = rgba + - Version 2: + This is not possible. + gl_FragColor expects vec4 not vec3 on the output. + If you really want RGB888 run cpuisp. + +Surfaceless GBM: + - We get a GBM surface and then have to swap buffers + If we rework for surfaceless GBM and EGL then the swap buffer can + be dropped. + - Version 2: + Complete GBM surface removed, memcpy() phase removed also + +dma-buf texture upload: + - Currently we pass the input buffer to glCreateTexture2D. + We should be able to make the upload of the input buffer go faster + by using eglCreateImageKHR and enumerated the dma-buf contents. + - Version 2: + Complete sm8250 test platform shows 20x performance increase + with CCM. + +Render-to-texture: + - Right now we render to the GBM provided surface framebuffer + and then memcpy from that buffer to the target output buffer. + This necessitates flushing the cache on the target buffer in + addition to the memcpy(). + - Render-to-texture where we generate the target framebuffer + directly from a dma-buf handle will mitigate the memcpy() phase. + - It should be the case then that the consumer of the output buffer + i.e. the thing that's not libcamera is responsible to flush the cache + if-and-only-if that user writes to the buffer. + - We need to flush the cache on the buffer because we are memcpying() to it. + - Version 2: + Done in version 2 From patchwork Thu Nov 20 23:33:41 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25141 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 48B58BD80A for ; Thu, 20 Nov 2025 23:34:28 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E6EA860B31; Fri, 21 Nov 2025 00:34:27 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="WuZjIvgr"; dkim-atps=neutral Received: from mail-wr1-x430.google.com (mail-wr1-x430.google.com [IPv6:2a00:1450:4864:20::430]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 1695C60AB1 for ; Fri, 21 Nov 2025 00:34:25 +0100 (CET) Received: by mail-wr1-x430.google.com with SMTP id ffacd0b85a97d-429c7869704so1235286f8f.2 for ; Thu, 20 Nov 2025 15:34:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681664; x=1764286464; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=mmy0r+9dV3Qznnotmc5WkFhDt1dkOI+Qma0jEOM5Zrc=; b=WuZjIvgrR5CdD2WSWGDmQYr4xxvt8Vzda09P/4i+DYsWwc9dChzwfR6PiBTghoS7k8 lobDuArlcinyBTnYIrHDQxl7E9aoJpAsFCIf4hXJ2xSrXE0J2GJqqNhkP25Q5x5PZCU8 5Zo7fgEL+/nvOIX6LjwpIq0g0qe+8NIRGcYF347FsUGKZgFkdXNNCsVmpvbJsv/JQBk8 qigi9CvhftjKRPgMzkh76gGxXgViWNHGsYV9INqglTXEIXQ1hHDmnIxIPTfpAM0nBCo8 Rpa+RSCwDP/R+pgNKjJ4Rx2xrcuisd416ptAZPEEZmEHEEnrFJtWYNWXuMzW75CseLt0 zD0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681664; x=1764286464; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=mmy0r+9dV3Qznnotmc5WkFhDt1dkOI+Qma0jEOM5Zrc=; b=ScfMNjj1xeGsTTTKWN5S6ZE7/WNWL32REywwiBwrtJtTLG+kZOJ3lt0+XqpWvyKgVA W9wG43D4GTActe/YW0tjnSfY+HNuBrMPcFLkiL+rGTvzznkEVylP5mTMRjeeWxZemKGg YfxGD6Uwf6J8zPJO+Biyvnk6D+t3WAlpkwdmQPB3aQ7O+dZCvsodjfEYgo4lswt7yJ23 i7ZHST1c72/9jZvq8hHXl9oe6xajICLrfItHPGcjFByzEUSEgaLhUkjm5IbAvmOWhTAf dbQypHhcNgz6777V+RO1mH7+QTttIUcGAmdkhgQy7OecdKxBxn7KOEAixp1IdZvmPVqY 963g== X-Gm-Message-State: AOJu0Yxa+a6ETBhyeWQBM6E7lMFv8PGVLPHJDxwTz+RNA+Elklxo00F9 vcolFA2kmC67JrBZsQYCvCjCzjPyrRLGDphgM7mP3Jd189TRmLCXFMBmuoN2ElSlDsZjiP85RF6 mZiR9H2c= X-Gm-Gg: ASbGncu9K8HRBA3LENdbqTPdGhdBTi4SP/ick0p+SfNXJSCfdudJx2C2Um8xHWijZ1E spNVoqFAVlxhmBbh/SDiNolMv+pzzd2DH8rVHhF80gu7ceBqZ7d9MBLf1ZJ4+zvcrLqFzN1pbpS EZnYIFf+pf/hGWVK5PVivJvB19NercgebMY+HH3xY23UBEKKHbOLBIzL4fyYCzlhM7iKYZ1Rdcg lj+5rKWTeb9/cO3gAIAGt+WSTHeHO+DkzvArxXFEBdgZawiMpXLoJBKUfehlXO/6OksQ0N2ylJ2 5xeZpBrkjSN9qBqTWxMgrjOjdL4OgkBYpQUFSpE9WgZ6DFVDcqzBb6t9mGBLlsMUG2xd6g3UcQw YKY4a7Q+D2lPyfIAf1Sr0xWvq0YQaddUCMfjZPISm4iMdxOBWH2wfFKlKxFDwyezTZVrS4QRry6 zJUDszVSvWWhN5U4fDiHj6qboGCyIvoGfomZFJAhUDu/u8OxgZG8Yu7xaA3jrUkq4riNs= X-Google-Smtp-Source: AGHT+IH/9+fg18mKdVDpnCeyVgKHZpbfDEoxBwZsSrdvahkXu1ws53ckJKq6eOA5I8gpN1yJGrUUvQ== X-Received: by 2002:a05:6000:144c:b0:42b:2f3d:2967 with SMTP id ffacd0b85a97d-42cc1d3a3cbmr83387f8f.51.1763681664325; Thu, 20 Nov 2025 15:34:24 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.34.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:34:23 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v4 17/23] libcamera: software_isp: lut: Change default Gamma to 1.0/2.2 Date: Thu, 20 Nov 2025 23:33:41 +0000 Message-ID: <20251120233347.5046-18-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Change the default softisp Gamma from 0.5 to 1.0/2.2. Signed-off-by: Bryan O'Donoghue --- src/ipa/simple/algorithms/lut.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ipa/simple/algorithms/lut.cpp b/src/ipa/simple/algorithms/lut.cpp index 9aaab54f1..7f223e812 100644 --- a/src/ipa/simple/algorithms/lut.cpp +++ b/src/ipa/simple/algorithms/lut.cpp @@ -35,7 +35,7 @@ int Lut::configure(IPAContext &context, [[maybe_unused]] const IPAConfigInfo &configInfo) { /* Gamma value is fixed */ - context.configuration.gamma = 0.5; + context.configuration.gamma = 1.0/2.2; context.activeState.knobs.contrast = std::optional(); updateGammaTable(context); From patchwork Thu Nov 20 23:33:42 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25142 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 A9EB4BD80A for ; Thu, 20 Nov 2025 23:34:29 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5145860B30; Fri, 21 Nov 2025 00:34:29 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="HYuTH9RO"; dkim-atps=neutral Received: from mail-wm1-x330.google.com (mail-wm1-x330.google.com [IPv6:2a00:1450:4864:20::330]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 19DF860AAB for ; Fri, 21 Nov 2025 00:34:26 +0100 (CET) Received: by mail-wm1-x330.google.com with SMTP id 5b1f17b1804b1-47118259fd8so12449555e9.3 for ; Thu, 20 Nov 2025 15:34:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681665; x=1764286465; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=16pZ/JdoiYUGtAtk/R99scAohK2wEjdJ1P32w9Duc1Y=; b=HYuTH9ROZRxk52UhAZTMckRfGkePe72EfHEn1Shyc7Sa9fotaAZthzRv0KEFZkaZ3e ChECImeLI6Gnkq7FAhVuJt1AUcQI/D5qqcUXM6SW1yCFs7/BSNlyPrCStXXzWRqkMbvJ 2tqiA3yLAp+ykM26SHO+f4nU+SRNYbN9gsRK1+L3NTcar5bh2xrRIOaOW5F8ueyit42G jeK74xY11YvQl/hcyH9SSUY60Of3oYxbzQHwkwytngyrg/kldtkWWN2aYu5YMXCx017N 3Qq+RS1fKoLCJ9hW6ZXeTXLye6veNhO73eoFrngX+x4bN+MS7bcUAGV2fhOW8k0qixrY jHqQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681665; x=1764286465; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=16pZ/JdoiYUGtAtk/R99scAohK2wEjdJ1P32w9Duc1Y=; b=RvBCnWJ/KHLEZOpdiPft+Hzks80Z6+82KWV9EBWOnlJ3ZrNHHXl1RSUx0HmiiBn/dG AzLQdL8VceO0roO/f7mFU7qMdj9OXDDl5ANEaR/jLjBBBSkM4vxTu4puNQ58DOtWO8nV HtpMQFioKudYcTQKF7rxhxrKnKVnp3NV7wLXuSrsNlzg4OtjZb+p/lIDiZzS13iZauoD AxGgE6BYGW98g6ZsEdU0jxKdu9gmtTh8PVSufxO8t9+rl42ImkKfu4DwB/Ng92G0fz1m hPeQjPFB+O9X8wzW9RTM9FZt/QukG9XQCCsZ7I1kDOm9Yc3zbGTo7Y0Q3EaTDSUZe3TU wFSg== X-Gm-Message-State: AOJu0YzE3u/3HybtHYY3Xjtr0X9HhkuNkoHBS/sPod1wC+qs5q1MRnyK UsQeOGRAH85lkDZCWSjSjRDTllqldM68xJoNCYEtkNctIcB1fB/vNoGl38Nt/pZXlBZi6WQqQFy zLIHa3V4= X-Gm-Gg: ASbGnctuW7j5ww1k8s8NC8GedDiLDluy8Od2tjKcGrwgRa6EnBL5DZXwewQy3FUmrt7 GVBFoHMiQq/qf635x9M+Cwn9mpqWHU2LEtNEKrfNRQcXP9/uIFzYyhu1UOg+mnub24tbA26UuE2 nYLCZ5Z9m2BgEk+Vjl2chZ+LRCHjrs16fgNV7APpFNaZxunmtXm8Cwxu2KAHAXIB29+YADYGRih ZHzDIQTT3IB61eawTj99HzQI4csFxYeGIJ8LaxF6AgUJL1vwQEsdlkFawjUQneftQV+05yp9u+Y Bu2whLuVy5ro0Atjm75lspQwdWq+twCcXkeUDfamOCy8aFvz6nRml9US5SzQ3Nr19aUk/E9gsX9 bqAXEJmp6+JHbN/qXRGQAvS9Rk6sW88N1VCtwBYvpLWCTcPbATX/EcjiT3frz5mG6Qhnn817266 Syg9Nwj3lDdUoNTm5fxQLeTszw9t2DczlufovVTvEp2LQB9VQhir0+TOAsOf6yWu8pjKM= X-Google-Smtp-Source: AGHT+IEdl30USogqQJSCxFyuRgbIhrtp1NYuu50AEr+QIbOv48iKxFdSCfST8lfTP93VpiucxLMLcA== X-Received: by 2002:a05:600c:3115:b0:477:b48d:ba7a with SMTP id 5b1f17b1804b1-477c01fd202mr2764685e9.32.1763681665351; Thu, 20 Nov 2025 15:34:25 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.34.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:34:24 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v4 18/23] ipa: Add a new Algorithm::init() to support self-initalising algorithms Date: Thu, 20 Nov 2025 23:33:42 +0000 Message-ID: <20251120233347.5046-19-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add in an algorithm init() routine which can be called in the absence of a Yaml input. Do this to allow an algorithm to set up a default set of parameters. Signed-off-by: Bryan O'Donoghue --- src/ipa/libipa/algorithm.cpp | 13 ++++++++++++- src/ipa/libipa/algorithm.h | 5 +++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/ipa/libipa/algorithm.cpp b/src/ipa/libipa/algorithm.cpp index 201efdfdb..da44c77ca 100644 --- a/src/ipa/libipa/algorithm.cpp +++ b/src/ipa/libipa/algorithm.cpp @@ -38,7 +38,7 @@ namespace ipa { */ /** - * \fn Algorithm::init() + * \fn Algorithm::init(typename Module::Context &context, const YamlObject &tuningData) * \brief Initialize the Algorithm with tuning data * \param[in] context The shared IPA context * \param[in] tuningData The tuning data for the algorithm @@ -50,6 +50,17 @@ namespace ipa { * \return 0 if successful, an error code otherwise */ +/** + * \fn Algorithm::init(typename Module::Context &context) + * \brief Initialize the algorithm with default parameters + * + * This method is called when no tuning data is available. The algorithm + * should initialize with sensible default values. + * + * \param context The IPA context containing algorithm state + * \return 0 on success, negative error code on failure + */ + /** * \fn Algorithm::configure() * \brief Configure the Algorithm given an IPAConfigInfo diff --git a/src/ipa/libipa/algorithm.h b/src/ipa/libipa/algorithm.h index 9a19dbd61..9fcbe23a9 100644 --- a/src/ipa/libipa/algorithm.h +++ b/src/ipa/libipa/algorithm.h @@ -32,6 +32,11 @@ public: return 0; } + virtual int init([[maybe_unused]] typename Module::Context &context) + { + return 0; + } + virtual int configure([[maybe_unused]] typename Module::Context &context, [[maybe_unused]] const typename Module::Config &configInfo) { From patchwork Thu Nov 20 23:33:43 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25143 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 7781AC3333 for ; Thu, 20 Nov 2025 23:34:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E3E0760B13; Fri, 21 Nov 2025 00:34:29 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="k8qw85dL"; dkim-atps=neutral Received: from mail-wm1-x32d.google.com (mail-wm1-x32d.google.com [IPv6:2a00:1450:4864:20::32d]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C734260B2F for ; Fri, 21 Nov 2025 00:34:27 +0100 (CET) Received: by mail-wm1-x32d.google.com with SMTP id 5b1f17b1804b1-477632b0621so10049225e9.2 for ; Thu, 20 Nov 2025 15:34:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681667; x=1764286467; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=XGZEOlg3N1WKIZQYXL2EvkWqNCC95nhRh04jkinhjFs=; b=k8qw85dLpTQOP9pqInRJxtJ/hxqlnnwZ0EZy6J1heSxXCsAGDFqqci0Yjm66B/h2h8 lawwP09gXj5DlnZOwTR6+MH3vmq0SZSNo+ETJOJq5ONSyblKPA3LD81QMBIgav/1qpvs cTGGWuDqGfM4ULbuZjyAKMTGrXSRZwQH1DY0X+GrPvUqgpeyLVj864Nol18aOQn7I7jd 2ioQjXkwzg7s7uAIociiV8LUxN8JkNQ0pC1Fl3ouaz29x+Vg7p6D6JmYeAkfGC4iV38G aBJth73J5fTXfL9y8FmjpHyypfsqSpyPvAHFlRzFo4K4esQWc4NzVOAsfHhIRVF9tCsM dDyg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681667; x=1764286467; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=XGZEOlg3N1WKIZQYXL2EvkWqNCC95nhRh04jkinhjFs=; b=er7dvRhPdFvTUfrIqFI5BibtQfo+U48CSseu89mTrsY/99gHSI5Ry/fLY9omNx3Dhd I3aNOfi1kLUFbcGkEh++ay3FPpO1Fm6MNWvMtokBvHKSqMudt5tOSmCxVfSe0FyZAhUi xU6GF1JMzv2rwoAFFIdRpJkVQUi8Y67x0pA+axzyRg17osAdz3FN1vtIhjXoFGos4Xf7 Y4ZXJHKpD/iTmi9pyoJRrY4qMurkWkAQ/w5yp825zeS6vxYeVg6XuyFsS1RK/7+jVvyY JfU9sZGVgT7a1/Sd8D00MosUfuXVYl2Hv3qfboGB6rIijNrMBkHSemGMsr6sYCgbkP4M Nh0Q== X-Gm-Message-State: AOJu0Yx8m9kQPT0FWY8eTL1Tip7zGryQs60KGvQ18BP08KuiTxuvsf44 EidoQJxpK4E2Jio2dYicp8qmuK6OyF666VKdJ5M4GzCOFiyTiArdI9CPO8XOQ3BX6WSOoe8Nnqq 30HL5SjA= X-Gm-Gg: ASbGncsNZ3is9ObCPdO0PSMOcjlYKIs9UMldfijNSnKBwN5yV9wa1klFibIU/T0UrXx +9Axn0CSj9sfKZcb1GHbx2K1iLWYNSDdKZKEA0mPQeiPOixIkU/XxsbJx+/vUwQRYYKqOayZin9 xBzVSGcg7QTsxccVPwnJHyYjJANlPxW6Ml+rLINEp40uPUZe091cnTBuOwp3McymqxpHx2rsTMy BsrD3sd3j0Ot+YQzbTRT1JamYeSqLYGRjadhqkcyDjnPCIvG0v0AHvC8YI8b/wpoDO0ycwlhO12 ARF4nIVWrByCW1MhnZg58gnu31kwS8HaOW4jq7VLoyeVPCv8ckcFmRKwhwDdflA8KaEgSrlb4V4 Y1fPOJQPylaad6EGT7JjBMwYpo4g3cgfJzMehzVTU/MfvhZhJ1Eq4avs9LxLAgGXo4zuI2zl9iZ ADJgsnaz/2/rHey5d8m6mzqS2UxUnHsabIn/xUXpZqhJSNugTmRwVKLerde1mnNkzu5S8= X-Google-Smtp-Source: AGHT+IEyxYWhBLs+mYoK5yV1RRcDhGwLGb6tSsX/59VJERBwFX/Za5QOr+PG0pS3FGmfG9HLY/jPIw== X-Received: by 2002:a05:6000:1889:b0:42b:3155:21da with SMTP id ffacd0b85a97d-42cc1cd8f1cmr100347f8f.2.1763681667116; Thu, 20 Nov 2025 15:34:27 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.34.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:34:25 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v4 19/23] libcamera: software_isp: Implement a static init() routine Date: Thu, 20 Nov 2025 23:33:43 +0000 Message-ID: <20251120233347.5046-20-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" This is an overloaded init() routine that allows the CCM class to self enumerate a default identity CCM at colour temperature 6500k. This is required for the case where we are running GPUISP but don't have a CCM for the sensor. In this case we want to generate a default CCM and use it instead of using the CPUISP's lookup tables. Signed-off-by: Bryan O'Donoghue --- src/ipa/simple/algorithms/ccm.cpp | 18 ++++++++++++++++++ src/ipa/simple/algorithms/ccm.h | 1 + 2 files changed, 19 insertions(+) diff --git a/src/ipa/simple/algorithms/ccm.cpp b/src/ipa/simple/algorithms/ccm.cpp index 0a98406c1..e3da6adfc 100644 --- a/src/ipa/simple/algorithms/ccm.cpp +++ b/src/ipa/simple/algorithms/ccm.cpp @@ -42,6 +42,24 @@ int Ccm::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData return 0; } +int Ccm::init([[maybe_unused]] IPAContext &context) +{ + /* Initialize with identity CCM at standard D65 color temperature */ + float identity[] = { 1, 0, 0, + 0, 1, 0, + 0, 0, 1 }; + Matrix identityMatrix(identity); + + std::map> ccmData; + ccmData[6500] = identityMatrix; + + ccm_ = Interpolator>(std::move(ccmData)); + + context.ccmEnabled = true; + context.ctrlMap[&controls::Saturation] = ControlInfo(0.0f, 2.0f, 1.0f); + return 0; +} + int Ccm::configure(IPAContext &context, [[maybe_unused]] const IPAConfigInfo &configInfo) { diff --git a/src/ipa/simple/algorithms/ccm.h b/src/ipa/simple/algorithms/ccm.h index 8279a3d59..b46f17726 100644 --- a/src/ipa/simple/algorithms/ccm.h +++ b/src/ipa/simple/algorithms/ccm.h @@ -26,6 +26,7 @@ public: ~Ccm() = default; int init(IPAContext &context, const YamlObject &tuningData) override; + int init(IPAContext &context) override; int configure(IPAContext &context, const IPAConfigInfo &configInfo) override; void queueRequest(typename Module::Context &context, From patchwork Thu Nov 20 23:33:44 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 25144 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 68B76BD80A for ; Thu, 20 Nov 2025 23:34:32 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1D55360B2C; Fri, 21 Nov 2025 00:34:32 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="hIVrk7IG"; dkim-atps=neutral Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C609160B0F for ; Fri, 21 Nov 2025 00:34:29 +0100 (CET) Received: by mail-wm1-x329.google.com with SMTP id 5b1f17b1804b1-477aa218f20so9456615e9.0 for ; Thu, 20 Nov 2025 15:34:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681669; x=1764286469; 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=iNwDqYtrwFynDjTjOkZDZulmG3M2dsjYpQnAK/LBTzY=; b=hIVrk7IGumWN1kaHw7Pa+N4PbPveAcnZrTxYWIpR1bUYU3mv1qwrNg2D3wr5RxzFZz kgI5FXcFGgj/l8fbNFUVV8aIB+4tHDjeGlZZkzR3G7z6N+aiPMIF8javq+VsLRD0Y6IZ tMcMm3IBwRobubHyLskDUrU3ca9lgE8TjQ5raUAa3tN2jUA58qoBUIbtfei2M7dhDOTD sebtSj8M9K072wZ3DjYwOmiFhLDrZ1z3YtcOXotSOzO00P7X9SHIvvq7dKPVWZYdLPGp xEcJHB6AQ5jGtof9fNhoOT7VqawxZngDI+U9QpO/mkBU/OHPrK5w6mGWGmI5XqjIKFL4 RGpA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681669; x=1764286469; 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=iNwDqYtrwFynDjTjOkZDZulmG3M2dsjYpQnAK/LBTzY=; b=qYFm7dq0A5viFADhqsBYk4npMivcIiIAmvLBuF6ba3f3nNq2mXFPMfJUn5/jsrSXIu nRBMs95u21/0QxYnB7cHOCyiY58FYIlN7f3sIPV8wj5QGqsVZW8Au/n+BstBdpn+4B1M Gxsz7bLauR467EPbaZ1Sottg7+JMQhNeBciZmrb+bYNv7DwwmFVYc6N0Ijwg/xqDNUTd 1z6EN3OUhe9Bsc6Fukr8U2UFw1EA9UeGXz9c3YpgsHuS4Ny6EgvLQy4cIzkrTaWTrTJ2 u4nob4HGE5oOKtXDsRRZ+P2sPwN8XeHdgtSHFwH37fCVIWiV6N1VdMLDGYbfZQcEKUNX yFAg== X-Gm-Message-State: AOJu0YxDNboiXJsCeGR31q1eQk+SQtkEqiaLzrEDL0R1msoG97rqkz6K yf4EJYJ32IAVmxGx6T+b4ukNJ4geFzq3FR/7v0Y3Nho3NY2tczsMI1CeHQduAyN5eifcfDlDyqT PUkCfVyI= X-Gm-Gg: ASbGnctfklBRcNbcqG/LlPa/eMM87ffk9TQm+BsPPJSUONcydhgQPs0rtJO3Jq5gtZm puRzAesFxlvKlvk99v2SON4bFlwBIK8M2SPro2CEFEoezcpdMIqiOjOuVMvcOLsmGEuRjyXcuEj INg96fOU/PscuOuTTprDnnXkL4lRwPpv03WgVRoeakHoWOfAr3l8LoC4usJiI90pdHOTCmczbeT TkWjVsHK0bgHdk6H9X1iyLJ0rQ/1DWGxpq33bL/FtyeSpDuzq07T83FcHCmWUS5BIFbzJSoqi+6 mfJhBcQQIU1Mq0RkgWBbo2Fd89usUbbxSiXeYY/+cJenpFvX48yEzIjQpnUvd7kjJrv/Iya7TXU moKrcQ1vghtSqinJwgI/BjitFgA8fetidPZ4cTy5tTzvphYYICMldpzEM5w7Sw500O7Wq5RQjn7 enlVHKbFQc+lk36A7GXXZUTTLSQSDpy8yIx6jZoA4Sg55PzbS1iFS5SgBVVRoGMsRtXwSP5RVAX oPBGg== X-Google-Smtp-Source: AGHT+IEr4H/IWiEHFlIVyWI5PyR0HKNEGfOBV9nuxkrror6iFpjv7btoXKRNMQHSMrg8E0icV9mvyQ== X-Received: by 2002:a05:600c:4694:b0:477:7a1a:4b81 with SMTP id 5b1f17b1804b1-477c0170599mr3060255e9.9.1763681669131; Thu, 20 Nov 2025 15:34:29 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.34.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:34:28 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v4 20/23] ipa: simple: Add a flag to indicate gpuIspEnabled Date: Thu, 20 Nov 2025 23:33:44 +0000 Message-ID: <20251120233347.5046-21-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Flag gpuIspEnabled in the simple IPA context. This flag will allow to selectively avoid some calculations or to generate a default CCM. Signed-off-by: Bryan O'Donoghue --- include/libcamera/ipa/soft.mojom | 2 +- src/ipa/simple/ipa_context.h | 1 + src/ipa/simple/soft_simple.cpp | 7 +++++-- src/libcamera/software_isp/software_isp.cpp | 13 ++++++++++--- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/include/libcamera/ipa/soft.mojom b/include/libcamera/ipa/soft.mojom index 77328c5fd..ab7eeb5d5 100644 --- a/include/libcamera/ipa/soft.mojom +++ b/include/libcamera/ipa/soft.mojom @@ -18,7 +18,7 @@ interface IPASoftInterface { libcamera.SharedFD fdParams, libcamera.IPACameraSensorInfo sensorInfo, libcamera.ControlInfoMap sensorControls) - => (int32 ret, libcamera.ControlInfoMap ipaControls, bool ccmEnabled); + => (int32 ret, libcamera.ControlInfoMap ipaControls, bool ccmEnabled, bool gpuIspEnabled); start() => (int32 ret); stop(); configure(IPAConfigInfo configInfo) diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h index c3081e306..ee8fb6b03 100644 --- a/src/ipa/simple/ipa_context.h +++ b/src/ipa/simple/ipa_context.h @@ -103,6 +103,7 @@ struct IPAContext { FCQueue frameContexts; ControlInfoMap::Map ctrlMap; bool ccmEnabled = false; + bool gpuIspEnabled = false; }; } /* namespace ipa::soft */ diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp index b147aca2e..523ff07b3 100644 --- a/src/ipa/simple/soft_simple.cpp +++ b/src/ipa/simple/soft_simple.cpp @@ -56,7 +56,8 @@ public: const IPACameraSensorInfo &sensorInfo, const ControlInfoMap &sensorControls, ControlInfoMap *ipaControls, - bool *ccmEnabled) override; + bool *ccmEnabled, + bool *gpuIspEnabled) override; int configure(const IPAConfigInfo &configInfo) override; int start() override; @@ -96,7 +97,8 @@ int IPASoftSimple::init(const IPASettings &settings, const IPACameraSensorInfo &sensorInfo, const ControlInfoMap &sensorControls, ControlInfoMap *ipaControls, - bool *ccmEnabled) + bool *ccmEnabled, + bool *gpuIspEnabled) { camHelper_ = CameraSensorHelperFactoryBase::create(settings.sensorModel); if (!camHelper_) { @@ -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 9944ca573..7f3f7b0bc 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -130,12 +130,18 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, } } + bool gpuIspEnabled; + #if HAVE_DEBAYER_EGL - if (!softISPMode || !strcmp(softISPMode, "gpu")) + if (!softISPMode || !strcmp(softISPMode, "gpu")) { debayer_ = std::make_unique(std::move(stats), configuration); + gpuIspEnabled = true; + } #endif - if (!debayer_) + if (!debayer_) { debayer_ = std::make_unique(std::move(stats), configuration); + gpuIspEnabled = false; + } if (!debayer_) { LOG(SoftwareIsp, Error) << "Failed to create Debayer object"; @@ -173,7 +179,8 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, sensorInfo, sensor->controls(), ipaControls, - &ccmEnabled_); + &ccmEnabled_, + &gpuIspEnabled); if (ret) { LOG(SoftwareIsp, Error) << "IPA init failed"; debayer_.reset(); From patchwork Thu Nov 20 23:33:45 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: 25145 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 399DEBD80A for ; Thu, 20 Nov 2025 23:34:34 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E680160B0F; Fri, 21 Nov 2025 00: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="O2/sxY9e"; dkim-atps=neutral Received: from mail-wm1-x32d.google.com (mail-wm1-x32d.google.com [IPv6:2a00:1450:4864:20::32d]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DE61960AB1 for ; Fri, 21 Nov 2025 00:34:31 +0100 (CET) Received: by mail-wm1-x32d.google.com with SMTP id 5b1f17b1804b1-477a219dbcaso13868525e9.3 for ; Thu, 20 Nov 2025 15:34:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681671; x=1764286471; 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=TkT+a2CnUga2pQvVkMr1EpE/d+TJ7UNDIhvUEz6eS0s=; b=O2/sxY9eGLmHh0HfIXCthu2t9y/p2di8r9LZZnMgRvXCJOESwQ1dMSamYaOrgeW6ro 9bjRQpBQQxP6H/AE5oYLZtkbBs/FdPHqx4kbknyudvhFyZs0GcWqa2eJgjOC1Xmqoe3T jrNEbVCBhLEWvt1I2toERHy1NZtSo4AAEg7ql9W0fE0p/HS46rf7ckwFhqGTLlzsR4Hu baZ6Qyx6l/XCi5P0vOYDkj10yxak8+SNSfRy6NiqaEptG94e+Qwq8dzzCGQ6qEK/uPIc lZCMm6kDlTqAWpdgfkNx1up+7+QOgivNBMOAsJBvGFgg2ucS84Uuu4gxTUAWEeCRRDp+ okfQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681671; x=1764286471; 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=TkT+a2CnUga2pQvVkMr1EpE/d+TJ7UNDIhvUEz6eS0s=; b=eOFphUV1Tytkz36Yx8G1Gqd0iLllHuWRsE0a/ygHOARXxTpM1BHuW6IGRV9HGnYvtC RTEJk3HFqBFTrdhuNdnFAFfhmY+1EKpyjQ4lSQqP3fe9iYAFwAiN50Tti+pJhJbOjLoG VlkizFLLJataVhqGZNrQMk2zDFRr1shDp3+4H655YQVsKcvTjudmqLiJf2BsDm3OTAo/ WTYsDLPr7Cd4KJBDxd5JN5Q22SY83Tkqz9RjZfd38b5eanS4msiQigaSWqyqlshBrQhg qFyYiYKkePEVoulP7eMbsoUhneJGPTcL3MVsYRfM5m5Zeh9LF1OvmGJ6xiwKaiElE/Fo lWvw== X-Gm-Message-State: AOJu0Yygm9C5nR97s+aw+ujTDWzxlW41eDD4dIHM4JVoEZ8BeK1ViJWz c7WEAY9aQTpR23tvAJEXKpeRLt9DknvS2qXZdObAi/viutELXhI6KJ/cXpZ+XQEVkQhonyGTo9r iaS70+s8= X-Gm-Gg: ASbGncthvHbzzN1FjGVL9RuDkBZrcJ3+Zj+Rb8NFGq3Xso0uFx0N2/xEI6OwgvBrxrQ taLo2O595Hrgj3NpTaQUwy9VZ8uubX9x3Hw9SQI01KydMvw/oVwq35SaLnEJN1+G53o3LBJvI7s hKeqbDVxxmCgR0nKY6lK1ofLiEQ3ioHpqUkfLmczyzFSkwIg7BO7YeLOIlXsf10/3d0DSG6AsNE r03u7dBEEbhwXuFjRXjkkts85yM5GN0mSqs2b7Ef7Na4DJ5XYKLYP9lrdbNYxOms+ceZltw8qrZ UiLAEd1oZQ4x+gMBD+ZsR/9MediOKtjIiGb5IdKi+G7c3yF86Ri/g/+6Z92yX1YwfYWQZVgYkDj U2nvbtUrAbpixiLz93yWMJiHI85ZUlLgDiOBvgPoLib80zCO+SIZj8f8Wg4IDTum6T9Y1wdvWiu cAbZ0InSfA8cZbILIbc75lqcdEu5gxGzSEPpNhgKhKj1iVWwjYId8weRgPnDf/QMTm2L4= X-Google-Smtp-Source: AGHT+IFMHx96olIGmPLnBgM6g1PRvACossLASN4JRzbSuK3kw+bE7TBrQUO2rzzvqvR1p4dOECR2SA== X-Received: by 2002:a05:600c:3110:b0:477:b734:8c52 with SMTP id 5b1f17b1804b1-477c0185bebmr3513425e9.14.1763681671261; Thu, 20 Nov 2025 15:34:31 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.34.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:34:30 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v4 21/23] ipa: libipa: module: Add createSelfEnumeratingAlgorithm Date: Thu, 20 Nov 2025 23:33:45 +0000 Message-ID: <20251120233347.5046-22-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Signed-off-by: Bryan O'Donoghue --- src/ipa/libipa/module.h | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/ipa/libipa/module.h b/src/ipa/libipa/module.h index 0fb51916f..d11e189bc 100644 --- a/src/ipa/libipa/module.h +++ b/src/ipa/libipa/module.h @@ -70,6 +70,47 @@ public: factories().push_back(factory); } + /** + * \fn int Module::createSelfEnumeratingAlgorithm(Context &context, const std::string &name) + * \brief Create and initialise a self-enumerating algorithm by name + * + * This function creates an algorithm instance from the registered algorithm + * factories using only the algorithm name, without requiring YAML configuration + * data. + * + * This is useful for algorithms that don't require external configuration + * parameters and can self-configure or use default values. + * + * \param[in] context The IPA context to pass to the algorithm's init function + * \param[in] name The name of the algorithm to instantiate + * + * \return 0 on success, negative errno value on failure: + * -EINVAL if the algorithm is not found in the factory registry + * Other negative values if algorithm initialisation fails + */ + int createSelfEnumeratingAlgorithm(Context &context, const std::string &name) + { + std::unique_ptr> algo = createAlgorithm(name); + if (!algo) { + LOG(IPAModuleAlgo, Error) + << "Algorithm '" << name << "' not found"; + return -EINVAL; + } + + int ret = algo->init(context); + if (ret) { + LOG(IPAModuleAlgo, Error) + << "Algorithm '" << name << "' failed to initialize"; + return ret; + } + + LOG(IPAModuleAlgo, Debug) + << "Instantiated algorithm '" << name << "'"; + + algorithms_.push_back(std::move(algo)); + return 0; + } + private: int createAlgorithm(Context &context, const YamlObject &data) { From patchwork Thu Nov 20 23:33:46 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: 25146 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 02647BD80A for ; Thu, 20 Nov 2025 23:34:37 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C2A4960AB1; Fri, 21 Nov 2025 00: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="O+esMvw8"; dkim-atps=neutral Received: from mail-wm1-x336.google.com (mail-wm1-x336.google.com [IPv6:2a00:1450:4864:20::336]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9553060AB7 for ; Fri, 21 Nov 2025 00:34:34 +0100 (CET) Received: by mail-wm1-x336.google.com with SMTP id 5b1f17b1804b1-47796a837c7so9457975e9.0 for ; Thu, 20 Nov 2025 15:34:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681674; x=1764286474; 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=9VmQKr/hU7sWeTMeG+xxd0aodCmXF/U2cLs3hX39Jp0=; b=O+esMvw8DoJa4Ad5w6GI2J4Cw74dWsI8u/1n1nBMt/A3lbs5OUZdlBp5e6lKd4zERo xafg4ErPIzhfBxIOOO5rUuETOw6Hv0x3lCJcPKG5AnLvoqM4CeLDojQdyO73eU4Pd0ev +dAKc9IN3Sr1nHs8kFncNLc9pOBc8xpg20ynK8IebG1DFihndLsNrc1rAAHrZ/aDQper ay4MLkYsVmaejusNyKxuNV+WOj5RTvhDA74DJwCErIOk1KL9DyYVuDS7IAI19QJN0xTN 878YdtP9KTl1sGWqbZpbG2OUNXO24bjnZQl3MhWvPqsRtnbE70tV/s4wOAttaa8987E8 U7FQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681674; x=1764286474; 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=9VmQKr/hU7sWeTMeG+xxd0aodCmXF/U2cLs3hX39Jp0=; b=NADtWQ9tNsAPQjrwlCUwmPKrHysskzxJQffjbFHW46ODdPyJpdX2F9sBbxRu36DlZh c72DbONkqp5nPcEBClrjNNYjkonY8490MhSYxZxz55GMCLRTnu3cpvDj3aoYbAOcjJrV k3aYM3RH8Qr7MCaVyhG7Y0ZkXjZALXa9qxGPWyZkfeT260MbAH4rVbTZB1Dz2O2pibzo DDmh0XdQ04vB5WnrIcVCeGl1GiowoiCg9+tgGJPufAJ+w1D+ajdO5Ey8DOPYE+DRPjdF kGuBVca2zZ7GZupIihJu4xBJh7LCZ9TuyCjksKRjK/zDPOhqIwQcpkckLDEw7kjrJy++ B5mQ== X-Gm-Message-State: AOJu0YyIlz333xZkKvzpOSBe1rjFb2+du5OdmAFN9gLA5cmdtAfhgWmc u3DbcTxLArxs1HJlAagtjKkMcK9fjP4fKXsvj8Vv2mJAFEXqxhvTVvEFeLyIJPPeaPzZX/3HT7C rsDLlUKU= X-Gm-Gg: ASbGncvMVW0IhwXRGpKP/D+Q1K/qdbQLpILDW7MQVyGtrqAWhxygv0jJow0/jcnEX+m OfD4JGOqVEGUVswnHpNGzzELy6EcgGnWgTonrDfCwkIKevVbTeE5mtZJ7S2IsAcraxWVY/3DHSy Ku8klagBbAoomuFx9Mv7WNfMss3PM+c1RqQwKfkIJ0RljR3ozMdGDkcKZPJBmD0NCIYwMIj6uVy 7uJhzj6Ukz537dpXKLe+9hHdkRM+PNFAodPp6vFM43O0T/zSFqSgmZtC1lKBDbJ9FhH3pbOqRPG r0za/kDuD7ihrtEv/nXBTit9Wh7O7C85Z9wBDmxQksY2rRP/FJszzRt0Cay6zXcjhYevMs9L0ii Jy3Nbx+t3R0JuINjH56fYHvGrT2xJt8lRViO66NoQ+ZJTwpKuXqNSwbC2eivlvM14iNlMM2AEV9 uz44hnB2PvIYi8eaj4FPz2oI3/15nSYsWMfvKaVNrqEN7lvCvcZ6HDbsdCvzkQCts/uHA= X-Google-Smtp-Source: AGHT+IEdgNne4FiVJ6M/NsFGwXj2YPXV913UW8VzRNforkkTL5WJWBQstKvle9TfhCDFzu1SU55xUQ== X-Received: by 2002:a05:600c:1d0e:b0:477:89d5:fdb2 with SMTP id 5b1f17b1804b1-477c017d9damr3359855e9.14.1763681673929; Thu, 20 Nov 2025 15:34:33 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.34.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:34:32 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v4 22/23] ipa: software_isp: Call createSelfEnumeratingAlgorithm() to statically instantiate CCM algo Date: Thu, 20 Nov 2025 23:33:46 +0000 Message-ID: <20251120233347.5046-23-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-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 523ff07b3..ddfc14c67 100644 --- a/src/ipa/simple/soft_simple.cpp +++ b/src/ipa/simple/soft_simple.cpp @@ -137,6 +137,12 @@ int IPASoftSimple::init(const IPASettings &settings, if (ret) return ret; + if (context_.gpuIspEnabled && !data->contains("ccm")) { + ret = createSelfEnumeratingAlgorithm(context_, std::string("Ccm")); + if (ret) + return ret; + } + *ccmEnabled = context_.ccmEnabled; params_ = nullptr; From patchwork Thu Nov 20 23:33:47 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: 25147 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 B4D72BD80A for ; Thu, 20 Nov 2025 23:34:39 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 81C0D60BDD; Fri, 21 Nov 2025 00: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="kvvfOO3+"; dkim-atps=neutral Received: from mail-wm1-x336.google.com (mail-wm1-x336.google.com [IPv6:2a00:1450:4864:20::336]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 886CF60A81 for ; Fri, 21 Nov 2025 00:34:37 +0100 (CET) Received: by mail-wm1-x336.google.com with SMTP id 5b1f17b1804b1-477aa218f20so9457165e9.0 for ; Thu, 20 Nov 2025 15:34:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1763681676; x=1764286476; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=24wXGFYfJlCqjSrTdSPnfcrWmHqpLPl1rwQ64/Nr/cU=; b=kvvfOO3+gqUyFx3zRC8D6RPBtPPpCM/NbRmguuTRGatba4YDabEaSBVpU1DEUmBBqR jlDgjs50w9k2woivSJRDWs+YI+nfQA0VJC/fPkClLw8jSsmAukujLqCotc7PLtmyjn+5 Jjmx3l31zdfd7b3gty4z0eJG21LrnWseNEL3sBfnUk5QpYECJbgePGmKtD7Wjd8eAj9J J0X4vV2rsYeM0QKkNgl1FA4zKFNmGfWCyBJoeTKYLdYwIxw1w2ojj5vzybyFvb1Yljj3 zKHfHWLr/3ujn7Obsq2rFKIGrkGMd3ZoAhqfEDT3n2A/urHBMnl9UlCs4KS2SedGb5mC REZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763681676; x=1764286476; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=24wXGFYfJlCqjSrTdSPnfcrWmHqpLPl1rwQ64/Nr/cU=; b=lze1JV7g6Vp1By7pRtIKB5183ASPOiuvYvrgfjvM311HrkCtcQjJAOKHJy1Zo19Tee QfH6om6QhMNK5i+ntWyIoyPukywd8YoDtZtPywuKXQzeItUsCqaU+7B6i5xP8D3Phbwm fmtkbxsoypous+cpCry6RlfFs1GQ0HjFLi3wHZFrSqapFIMXu0mU4XTXwB9vLwWH3D5x He7ypz/ss6Qn59Xexv2d9rFJUzKAZMKIDJfwuvAIFFteoS1eUuizhNY8bIiZjUj5gijY 4h3KDp4WhMYaTtSzRyEh35kpKSefh1ukjo20rPfK2Sj45D1HQP/7eh+avRCS16r/Ml+k SGig== X-Gm-Message-State: AOJu0Yy/9xCrlmEDYxcMwFboYLvFld95/aCVC1H8t58aHwyyl1sQBdM0 ojsVe3efPuRKRR0wMlddaBBLdlsVSVjTk17TbWr+VXxXtKvdSKaOOUgE55h6P5KUkzzNr7j2zEj K88ecIww= X-Gm-Gg: ASbGncsheChv0GHonWcu/v4q5LNTsn/krMHx6CN7hEQiiHx4oWT3aHA5vTG+Suq0Eag Z3jERCFAoAxK/65l9ICLJpw1Xt1wu3YCUB2/3Duaj9W3zLiWaC2unSbKw2kokYHdW5rNBGROPw+ ifZJ99W8GvvMweMvAJXnb7jhkAuPbha0Z3UHCA6GsuBOxAfCPFDkhfXQdH61H4ZeWe7jV2D42mE 4Xgr9w02Zzca/Dw5Z/UxFbzHEF85Fu3XLkUq32B/VWiaJ3BLUzKKvL0apE+CB6TiftxQ9pCsQWF BSvcjk4PuNQe6UppEE2Mt88rZRBlO5wQnMEe91UpJ+evDyi6UuePRvvmLBuUOQpI4glcsQU6Z9f X/G5oHhuTNQ554bLOa3aAu+/jc1axyOfirCZDIPAP+fZUI0J1UJYmqk/McjaaG65v42bRUvkqOW 0l/E4pFYq5q1O1MLPRy9LBsQe0ww3YsHPvtyQFNF4W/PLzxTMni57hwoU1PjjM9SJMjcg= X-Google-Smtp-Source: AGHT+IGA5odhzQMJfqG2PjkGPrl3xueKaJtHABi9J3j/Es6ViwTE+h5HZ8Y85WidHT0xCPjmS9kTAg== X-Received: by 2002:a05:600c:3baa:b0:475:de12:d3b5 with SMTP id 5b1f17b1804b1-477c01ecc7cmr3070765e9.34.1763681676444; Thu, 20 Nov 2025 15:34:36 -0800 (PST) Received: from inspiron14p-linux.ht.home (188-141-3-146.dynamic.upc.ie. [188.141.3.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa3a81sm7984139f8f.26.2025.11.20.15.34.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Nov 2025 15:34:35 -0800 (PST) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: pavel@ucw.cz, Bryan O'Donoghue Subject: [PATCH v4 23/23] libcamera: software_isp: lut: Skip calculation lookup tables if gpuIspEnabled is true. Date: Thu, 20 Nov 2025 23:33:47 +0000 Message-ID: <20251120233347.5046-24-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251120233347.5046-1-bryan.odonoghue@linaro.org> References: <20251120233347.5046-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" On my reference platform Qualcomm RB5 sm8520 the qcam application CPU occupancy drops from ~100% to about 95% of a single core so this one change sheds aprox 5% CPU usage. Signed-off-by: Bryan O'Donoghue --- src/ipa/simple/algorithms/lut.cpp | 70 ++++++++++++++++--------------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/src/ipa/simple/algorithms/lut.cpp b/src/ipa/simple/algorithms/lut.cpp index 7f223e812..618219b17 100644 --- a/src/ipa/simple/algorithms/lut.cpp +++ b/src/ipa/simple/algorithms/lut.cpp @@ -56,32 +56,34 @@ void Lut::queueRequest(typename Module::Context &context, void Lut::updateGammaTable(IPAContext &context) { - auto &gammaTable = context.activeState.gamma.gammaTable; const auto blackLevel = context.activeState.blc.level; - const unsigned int blackIndex = blackLevel * gammaTable.size() / 256; const auto contrast = context.activeState.knobs.contrast.value_or(1.0); - const float divisor = gammaTable.size() - blackIndex - 1.0; - for (unsigned int i = blackIndex; i < gammaTable.size(); i++) { - double normalized = (i - blackIndex) / divisor; - /* Convert 0..2 to 0..infinity; avoid actual inifinity at tan(pi/2) */ - double contrastExp = tan(std::clamp(contrast * M_PI_4, 0.0, M_PI_2 - 0.00001)); - /* Apply simple S-curve */ - if (normalized < 0.5) - normalized = 0.5 * std::pow(normalized / 0.5, contrastExp); - else - normalized = 1.0 - 0.5 * std::pow((1.0 - normalized) / 0.5, contrastExp); - gammaTable[i] = UINT8_MAX * - std::pow(normalized, context.configuration.gamma); + if (!context.gpuIspEnabled) { + auto &gammaTable = context.activeState.gamma.gammaTable; + const unsigned int blackIndex = blackLevel * gammaTable.size() / 256; + const float divisor = gammaTable.size() - blackIndex - 1.0; + for (unsigned int i = blackIndex; i < gammaTable.size(); i++) { + double normalized = (i - blackIndex) / divisor; + /* Convert 0..2 to 0..infinity; avoid actual inifinity at tan(pi/2) */ + double contrastExp = tan(std::clamp(contrast * M_PI_4, 0.0, M_PI_2 - 0.00001)); + /* Apply simple S-curve */ + if (normalized < 0.5) + normalized = 0.5 * std::pow(normalized / 0.5, contrastExp); + else + normalized = 1.0 - 0.5 * std::pow((1.0 - normalized) / 0.5, contrastExp); + gammaTable[i] = UINT8_MAX * + std::pow(normalized, context.configuration.gamma); + } + /* + * Due to CCM operations, the table lookup may reach indices below the black + * level. Let's set the table values below black level to the minimum + * non-black value to prevent problems when the minimum value is + * significantly non-zero (for example, when the image should be all grey). + */ + std::fill(gammaTable.begin(), gammaTable.begin() + blackIndex, + gammaTable[blackIndex]); } - /* - * Due to CCM operations, the table lookup may reach indices below the black - * level. Let's set the table values below black level to the minimum - * non-black value to prevent problems when the minimum value is - * significantly non-zero (for example, when the image should be all grey). - */ - std::fill(gammaTable.begin(), gammaTable.begin() + blackIndex, - gammaTable[blackIndex]); context.activeState.gamma.blackLevel = blackLevel; context.activeState.gamma.contrast = contrast; @@ -134,17 +136,19 @@ void Lut::prepare(IPAContext &context, auto &green = params->greenCcm; auto &blue = params->blueCcm; params->ccm = ccm; - for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) { - red[i].r = ccmValue(i, ccm[0][0]); - red[i].g = ccmValue(i, ccm[1][0]); - red[i].b = ccmValue(i, ccm[2][0]); - green[i].r = ccmValue(i, ccm[0][1]); - green[i].g = ccmValue(i, ccm[1][1]); - green[i].b = ccmValue(i, ccm[2][1]); - blue[i].r = ccmValue(i, ccm[0][2]); - blue[i].g = ccmValue(i, ccm[1][2]); - blue[i].b = ccmValue(i, ccm[2][2]); - params->gammaLut[i] = gammaTable[i / div]; + if (!context.gpuIspEnabled) { + for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) { + red[i].r = ccmValue(i, ccm[0][0]); + red[i].g = ccmValue(i, ccm[1][0]); + red[i].b = ccmValue(i, ccm[2][0]); + green[i].r = ccmValue(i, ccm[0][1]); + green[i].g = ccmValue(i, ccm[1][1]); + green[i].b = ccmValue(i, ccm[2][1]); + blue[i].r = ccmValue(i, ccm[0][2]); + blue[i].g = ccmValue(i, ccm[1][2]); + blue[i].b = ccmValue(i, ccm[2][2]); + params->gammaLut[i] = gammaTable[i / div]; + } } }