From patchwork Thu Jun 18 12:22:14 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26935 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 D951CC3301 for ; Thu, 18 Jun 2026 12:23:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 71CCD62C6D; Thu, 18 Jun 2026 14:23:04 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="HDZAXm9Y"; 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 11EFB629A8 for ; Thu, 18 Jun 2026 14:22:59 +0200 (CEST) Received: by mail-wm1-x335.google.com with SMTP id 5b1f17b1804b1-490be29c1c5so7263125e9.2 for ; Thu, 18 Jun 2026 05:22:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785379; x=1782390179; 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=lU+S6rm4EDKAJ6Icy3YR22fQP98Ke30bgUg2epSurEg=; b=HDZAXm9YutX0ACE/VQGOvCpu95OMz9EgRwU3zqLuyTKITmfJSw+mG591hk9R3Lru0u Snn5pYqg7u7Tk7aSseGMX5Y8Ym7zckesYsTtXWohlGJ0MfAAHXjKvVoKRpVCkU2VKRk+ aQzugDTolewHK/vh6IN6eNfxBZp4xvLg7xHlgxXLqrncSKHGCz2fP7T+d/1rlIGBDYTd 1Y34SN2yJbblSMme6/Aqg2sIGHWeU0Yt7hG38QhO9vviXtC7tCjKVMGhBtNA+heTgLO0 GNbhDNg7a7u6C8W9mOr8Wg99uOXXYEiCXkRDTJcPpWZuXW9t3Vn20B4XPf1tMJva651x YtZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785379; x=1782390179; 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=lU+S6rm4EDKAJ6Icy3YR22fQP98Ke30bgUg2epSurEg=; b=lX0DgDSbOIUI3UAHntCgqybekDCQ72Soj6be7xdj18EnS4C7prFCg5SGNl9FIPsU02 hw/jIUsSqJrXbuVkJ7kGIuK+nh3Hyfxb1iFpl1nQ2GLhda/sfhlh+yb5BwZaN5CnFvDL imsnRjPQC5uxYMfPEZ6xGbt5dUJKLO10S0kj22+lCo/l7/X539ivMhpnvk5sHSxPY8NL O48/qvusDe2VfKKxW/SOUh2GOD7IrRcFbp2HR7CxmmJdzq5jiVeTZDhIMEO2q1JbjlgD SGjnZr89zut3PnYq033/Tr5QlZNUQqCxOFpObq1JDi9Of2F3E3GaiZNdRuCyTb7Xv0oE AIKQ== X-Gm-Message-State: AOJu0YxxYWr1OeE+mY8bJxY/9Jywa3x66DV5wqCNacerpZlROGLQDWLp RDQXfktdDqbUkZ9T/5RNL+RIX/96vyzhzNqmwc8qK/0FpIC7EOd1I1NhOTHX9ks4L7n0J2Pv2fu fj2+aa4A= X-Gm-Gg: AfdE7cnBvsSLPrFcrsSO5PZVcgDnD9Vj6NhJGmMoj+PMSpSkPz4bJJsNe95paT3COTg 9aIfHXaJkWLBfaWQkw/JNEv0A8YgDNXSXIJdnuUVLlhmndhkOnv0SU9rt+mGdYLObEIVff+oRss 8gAIA0yEhcDNEc+ChdxWLCOhLW5aTs3JKONiZLgx4PU3kei0ixjXwTS1JdQQ1aTlflJHFA1SwN5 dPaVzjfZl2aqGeLYuHeAJ6rM0N5wCyjhFcvnd7T9Biv3u5g+2TIRluVSE6Zi8KykzoJWkRxsAPg enMj0xG+LFNzNdqYlEBgtU6TKOOLVFt95Iei+3e4mGKO2hyAVxVqgB3pguYsm3GvtrI8yWvGx6q neCZWBXIIzGOBckQDxYNBurguGB5DgwwpvIC1QXF+e9H5ce7S8aSMVeNMStwhbqTEKStYejihSQ ggRHC5CwPBpfMdtwr+xpgh1mlcIcaW X-Received: by 2002:a05:600c:a114:b0:490:e243:4806 with SMTP id 5b1f17b1804b1-492333bf4ebmr114850085e9.9.1781785377832; Thu, 18 Jun 2026 05:22:57 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.22.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:22:57 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 01/30] libcamera: software_isp: Rename Bayer classes to SoftwareIspPipeline Date: Thu, 18 Jun 2026 13:22:14 +0100 Message-ID: <20260618122245.946138-2-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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" The GPUISP multi-pass really wants to run a series of shaders inside of its process() block. Looking at the classes we have now the Debayer class really implements high level logic for the ISP that just so happens to be centered around Bayer operations. We have already done alot of work to make softisp mesa/thread safe so the logical step to take is to start adding in support for more shaders to our existing EGL implementation. It feels lazy sticking to the debayer_-> object and naming convention and moreover it won't be accurate in later patches. Its a little less satisfying for the DebayerCpu to rename it to SoftwareIspPipelineCpu but it also isn't a lie. SoftIsp itself doesn't especially need to know what is happening inside of the invokeMethod(process) signal save that "sutff" happens and data is returned. For obvious reasons we started with a base class of type Debayer but, now that we are expanding the capabilities of SoftIsp to go beyond things that happen in the demosiac phase - we also need to outgrow the constraining name Bayer - no disrespect to Bruce Bayer himself intended. Signed-off-by: Bryan O'Donoghue --- .../internal/software_isp/software_isp.h | 4 +- src/libcamera/software_isp/meson.build | 6 +- src/libcamera/software_isp/software_isp.cpp | 60 +++---- ...{debayer.cpp => software_isp_pipeline.cpp} | 77 +++++---- .../{debayer.h => software_isp_pipeline.h} | 8 +- ..._cpu.cpp => software_isp_pipeline_cpu.cpp} | 160 +++++++++--------- ...ayer_cpu.h => software_isp_pipeline_cpu.h} | 10 +- ..._egl.cpp => software_isp_pipeline_gpu.cpp} | 51 +++--- ...ayer_egl.h => software_isp_pipeline_gpu.h} | 8 +- 9 files changed, 192 insertions(+), 192 deletions(-) rename src/libcamera/software_isp/{debayer.cpp => software_isp_pipeline.cpp} (73%) rename src/libcamera/software_isp/{debayer.h => software_isp_pipeline.h} (93%) rename src/libcamera/software_isp/{debayer_cpu.cpp => software_isp_pipeline_cpu.cpp} (84%) rename src/libcamera/software_isp/{debayer_cpu.h => software_isp_pipeline_cpu.h} (95%) rename src/libcamera/software_isp/{debayer_egl.cpp => software_isp_pipeline_gpu.cpp} (90%) rename src/libcamera/software_isp/{debayer_egl.h => software_isp_pipeline_gpu.h} (93%) diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h index 86cb8f8de..f29e478a5 100644 --- a/include/libcamera/internal/software_isp/software_isp.h +++ b/include/libcamera/internal/software_isp/software_isp.h @@ -36,9 +36,9 @@ namespace libcamera { -class Debayer; class FrameBuffer; class PixelFormat; +class SoftwareIspPipeline; class Stream; struct StreamConfiguration; @@ -93,7 +93,7 @@ private: void statsReady(uint32_t frame, uint32_t bufferId); void inputReady(FrameBuffer *input); void outputReady(FrameBuffer *output); - std::unique_ptr debayer_; + std::unique_ptr pipeline_; Thread ispWorkerThread_; SharedMemObject sharedParams_; DebayerParams debayerParams_; diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build index 15f9e4032..51cc6ac3e 100644 --- a/src/libcamera/software_isp/meson.build +++ b/src/libcamera/software_isp/meson.build @@ -21,8 +21,8 @@ summary({'SoftISP GPU acceleration' : mesa_works}, libcamera_internal_sources += files([ 'benchmark.cpp', - 'debayer.cpp', - 'debayer_cpu.cpp', + 'software_isp_pipeline.cpp', + 'software_isp_pipeline_cpu.cpp', 'software_isp.cpp', 'swstats_cpu.cpp', ]) @@ -31,7 +31,7 @@ if mesa_works config_h.set('HAVE_DEBAYER_EGL', 1) libcamera_internal_sources += files([ '../egl.cpp', - 'debayer_egl.cpp', + 'software_isp_pipeline_gpu.cpp', ]) libcamera_deps += [ libegl, diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index 781cf02f8..c99d8654c 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -27,9 +27,9 @@ #include "libcamera/internal/framebuffer.h" #include "libcamera/internal/software_isp/debayer_params.h" -#include "debayer_cpu.h" +#include "software_isp_pipeline_cpu.h" #if HAVE_DEBAYER_EGL -#include "debayer_egl.h" +#include "software_isp_pipeline_gpu.h" #endif /** @@ -120,20 +120,20 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, } if (!softISPMode || softISPMode == "gpu") - debayer_ = std::make_unique(std::move(stats), cm); + pipeline_ = std::make_unique(std::move(stats), cm); #endif - if (!debayer_) - debayer_ = std::make_unique(std::move(stats), cm); + if (!pipeline_) + pipeline_ = std::make_unique(std::move(stats), cm); - debayer_->inputBufferReady.connect(this, &SoftwareIsp::inputReady); - debayer_->outputBufferReady.connect(this, &SoftwareIsp::outputReady); + pipeline_->inputBufferReady.connect(this, &SoftwareIsp::inputReady); + pipeline_->outputBufferReady.connect(this, &SoftwareIsp::outputReady); ipa_ = pipe->createIPA(0, 0); if (!ipa_) { LOG(SoftwareIsp, Error) << "Creating IPA for software ISP failed"; - debayer_.reset(); + pipeline_.reset(); return; } @@ -152,7 +152,7 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, } ret = ipa_->init(IPASettings{ ipaTuningFile, sensor->model() }, - debayer_->getStatsFD(), + pipeline_->getStatsFD(), sharedParams_.fd(), sensorInfo, sensor->controls(), @@ -160,7 +160,7 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, &ccmEnabled_); if (ret) { LOG(SoftwareIsp, Error) << "IPA init failed"; - debayer_.reset(); + pipeline_.reset(); return; } @@ -171,13 +171,13 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, }); ipa_->setSensorControls.connect(this, &SoftwareIsp::setSensorCtrls); - debayer_->moveToThread(&ispWorkerThread_); + pipeline_->moveToThread(&ispWorkerThread_); } SoftwareIsp::~SoftwareIsp() { - /* make sure to destroy the DebayerCpu before the ispWorkerThread_ is gone */ - debayer_.reset(); + /* make sure to destroy the SoftwareIspPipeline before the ispWorkerThread_ is gone */ + pipeline_.reset(); } /** @@ -212,7 +212,7 @@ void SoftwareIsp::processStats(const uint32_t frame, const uint32_t bufferId, */ bool SoftwareIsp::isValid() const { - return !!debayer_; + return !!pipeline_; } /** @@ -222,9 +222,9 @@ bool SoftwareIsp::isValid() const */ std::vector SoftwareIsp::formats(PixelFormat inputFormat) { - ASSERT(debayer_); + ASSERT(pipeline_); - return debayer_->formats(inputFormat); + return pipeline_->formats(inputFormat); } /** @@ -235,9 +235,9 @@ std::vector SoftwareIsp::formats(PixelFormat inputFormat) */ SizeRange SoftwareIsp::sizes(PixelFormat inputFormat, const Size &inputSize) { - ASSERT(debayer_); + ASSERT(pipeline_); - return debayer_->sizes(inputFormat, inputSize); + return pipeline_->sizes(inputFormat, inputSize); } /** @@ -250,9 +250,9 @@ SizeRange SoftwareIsp::sizes(PixelFormat inputFormat, const Size &inputSize) std::tuple SoftwareIsp::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) { - ASSERT(debayer_); + ASSERT(pipeline_); - return debayer_->strideAndFrameSize(outputFormat, size); + return pipeline_->strideAndFrameSize(outputFormat, size); } /** @@ -267,13 +267,13 @@ int SoftwareIsp::configure(const StreamConfiguration &inputCfg, const std::vector> &outputCfgs, const ipa::soft::IPAConfigInfo &configInfo) { - ASSERT(ipa_ && debayer_); + ASSERT(ipa_ && pipeline_); int ret = ipa_->configure(configInfo); if (ret < 0) return ret; - ret = debayer_->configure(inputCfg, outputCfgs, ccmEnabled_); + ret = pipeline_->configure(inputCfg, outputCfgs, ccmEnabled_); if (ret < 0) return ret; @@ -296,13 +296,13 @@ int SoftwareIsp::configure(const StreamConfiguration &inputCfg, int SoftwareIsp::exportBuffers(const Stream *stream, unsigned int count, std::vector> *buffers) { - ASSERT(debayer_ != nullptr); + ASSERT(pipeline_ != nullptr); /* single output for now */ if (stream == nullptr) return -EINVAL; - return dmaHeap_.exportBuffers(count, { debayer_->frameSize() }, buffers); + return dmaHeap_.exportBuffers(count, { pipeline_->frameSize() }, buffers); } /** @@ -364,8 +364,8 @@ int SoftwareIsp::start() ispWorkerThread_.start(); - return debayer_->invokeMethod(&Debayer::start, - ConnectionTypeBlocking); + return pipeline_->invokeMethod(&SoftwareIspPipeline::start, + ConnectionTypeBlocking); } /** @@ -376,8 +376,8 @@ int SoftwareIsp::start() */ void SoftwareIsp::stop() { - debayer_->invokeMethod(&Debayer::stop, - ConnectionTypeBlocking); + pipeline_->invokeMethod(&SoftwareIspPipeline::stop, + ConnectionTypeBlocking); ispWorkerThread_.exit(); ispWorkerThread_.wait(); @@ -410,8 +410,8 @@ void SoftwareIsp::stop() void SoftwareIsp::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output) { ipa_->computeParams(frame); - debayer_->invokeMethod(&Debayer::process, - ConnectionTypeQueued, frame, input, output, debayerParams_); + pipeline_->invokeMethod(&SoftwareIspPipeline::process, + ConnectionTypeQueued, frame, input, output, debayerParams_); } void SoftwareIsp::saveIspParams() diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/software_isp_pipeline.cpp similarity index 73% rename from src/libcamera/software_isp/debayer.cpp rename to src/libcamera/software_isp/software_isp_pipeline.cpp index 2d7abfb83..85fd4b120 100644 --- a/src/libcamera/software_isp/debayer.cpp +++ b/src/libcamera/software_isp/software_isp_pipeline.cpp @@ -6,10 +6,10 @@ * Authors: * Hans de Goede * - * debayer base class + * SoftwareIspPipeline base class */ -#include "debayer.h" +#include "software_isp_pipeline.h" namespace libcamera { @@ -44,7 +44,7 @@ namespace libcamera { */ /** - * \class Debayer + * \class SoftwareIspPipeline * \brief Base debayering class * * Base class that provides functions for setting up the debayering process. @@ -56,17 +56,16 @@ LOG_DEFINE_CATEGORY(Debayer) * \brief Construct a Debayer object * \param[in] cm The camera manager */ -Debayer::Debayer(const CameraManager &cm) +SoftwareIspPipeline::SoftwareIspPipeline(const CameraManager &cm) : bench_(cm, "Debayer") { } - -Debayer::~Debayer() +SoftwareIspPipeline::~SoftwareIspPipeline() { } /** - * \fn int Debayer::configure() + * \fn int SoftwareIspPipeline::configure() * \brief Configure the debayer object according to the passed in parameters * \param[in] inputCfg The input configuration * \param[in] outputCfgs The output configurations @@ -76,7 +75,7 @@ Debayer::~Debayer() */ /** - * \fn Size Debayer::patternSize(PixelFormat inputFormat) + * \fn Size SoftwareIspPipeline::patternSize(PixelFormat inputFormat) * \brief Get the width and height at which the bayer pattern repeats * \param[in] inputFormat The input format * @@ -86,7 +85,7 @@ Debayer::~Debayer() */ /** - * \fn std::vector Debayer::formats(PixelFormat inputFormat) + * \fn std::vector SoftwareIspPipeline::formats(PixelFormat inputFormat) * \brief Get the supported output formats * \param[in] inputFormat The input format * @@ -94,7 +93,7 @@ Debayer::~Debayer() */ /** - * \fn std::tuple Debayer::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) + * \fn std::tuple SoftwareIspPipeline::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) * \brief Get the stride and the frame size * \param[in] outputFormat The output format * \param[in] size The output size @@ -104,7 +103,7 @@ Debayer::~Debayer() */ /** - * \fn void Debayer::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, DebayerParams params) + * \fn void SoftwareIspPipeline::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, DebayerParams params) * \brief Process the bayer data into the requested format * \param[in] frame The frame number * \param[in] input The input buffer @@ -116,7 +115,7 @@ Debayer::~Debayer() */ /** - * \fn virtual SizeRange Debayer::sizes(PixelFormat inputFormat, const Size &inputSize) + * \fn virtual SizeRange SoftwareIspPipeline::sizes(PixelFormat inputFormat, const Size &inputSize) * \brief Get the supported output sizes for the given input format and size * \param[in] inputFormat The input format * \param[in] inputSize The input size @@ -125,7 +124,7 @@ Debayer::~Debayer() */ /** - * \fn const SharedFD &Debayer::getStatsFD() + * \fn const SharedFD &SoftwareIspPipeline::getStatsFD() * \brief Get the file descriptor for the statistics * * This file descriptor provides access to the output statistics buffer @@ -135,7 +134,7 @@ Debayer::~Debayer() */ /** - * \fn unsigned int Debayer::frameSize() + * \fn unsigned int SoftwareIspPipeline::frameSize() * \brief Get the output frame size * * \return The total output frame size in bytes as configured for the @@ -143,17 +142,17 @@ Debayer::~Debayer() */ /** - * \var Signal Debayer::inputBufferReady + * \var Signal SoftwareIspPipeline::inputBufferReady * \brief Signals when the input buffer is ready */ /** - * \var Signal Debayer::outputBufferReady + * \var Signal SoftwareIspPipeline::outputBufferReady * \brief Signals when the output buffer is ready */ /** - * \struct Debayer::DebayerInputConfig + * \struct SoftwareIspPipeline::DebayerInputConfig * \brief Structure describing the incoming Bayer parameters * * The DebayerInputConfig structure defines the characteristics of the raw @@ -162,40 +161,40 @@ Debayer::~Debayer() * - Memory layout parameters such as stride and bytes per pixel (\ref bpp) * - A list of supported output pixel formats. * - * \var Debayer::DebayerInputConfig::patternSize + * \var SoftwareIspPipeline::DebayerInputConfig::patternSize * Size of the Bayer pattern in pixels. For standard Bayer formats such as * BGGR, GRBG, GBRG, and RGGB, this is typically 2×2 pixels. * - * \var Debayer::DebayerInputConfig::bpp + * \var SoftwareIspPipeline::DebayerInputConfig::bpp * Number of bytes used per pixel in memory. This reflects storage size, * not precision. * - * \var Debayer::DebayerInputConfig::stride + * \var SoftwareIspPipeline::DebayerInputConfig::stride * Line stride in bytes for the Bayer input frame. * - * \var Debayer::DebayerInputConfig::outputFormats + * \var SoftwareIspPipeline::DebayerInputConfig::outputFormats * List of pixel formats supported as output for this input configuration. */ /** - * \struct Debayer::DebayerOutputConfig + * \struct SoftwareIspPipeline::DebayerOutputConfig * \brief Structure describing the output frame configuration * * Defines how the output of the debayer process is laid out in memory. * It includes per-pixel size, stride, and total frame size. * - * \var Debayer::DebayerOutputConfig::bpp + * \var SoftwareIspPipeline::DebayerOutputConfig::bpp * Bytes used per pixel in the output format. * - * \var Debayer::DebayerOutputConfig::stride + * \var SoftwareIspPipeline::DebayerOutputConfig::stride * Line stride in bytes for the output frame. * - * \var Debayer::DebayerOutputConfig::frameSize + * \var SoftwareIspPipeline::DebayerOutputConfig::frameSize * Total frame size in bytes for the output buffer. */ /** - * \var Debayer::inputConfig_ + * \var SoftwareIspPipeline::inputConfig_ * \brief Input configuration parameters for the current debayer operation * * Holds metadata describing the incoming Bayer image layout, including @@ -204,7 +203,7 @@ Debayer::~Debayer() */ /** - * \var Debayer::outputConfig_ + * \var SoftwareIspPipeline::outputConfig_ * \brief Output configuration data for the debayered frame * * Contains bytes per pixel, stride, and total frame size for the @@ -212,22 +211,22 @@ Debayer::~Debayer() */ /** - * \var Debayer::inputPixelFormat_ + * \var SoftwareIspPipeline::inputPixelFormat_ * \brief The incoming pixel format */ /** - * \var Debayer::outputPixelFormat_ + * \var SoftwareIspPipeline::outputPixelFormat_ * \brief The output pixel format */ /** - * \var Debayer::outputSize_ + * \var SoftwareIspPipeline::outputSize_ * \brief Output size object */ /** - * \var Debayer::swapRedBlueGains_ + * \var SoftwareIspPipeline::swapRedBlueGains_ * \brief Flag indicating whether red and blue channel gains should be swapped * * Used when the Bayer pattern order indicates that red/blue color channels are @@ -235,7 +234,7 @@ Debayer::~Debayer() */ /** - * \var Debayer::bench_ + * \var SoftwareIspPipeline::bench_ * \brief Benchmarking utility instance for performance measurements * * Used internally to track timing and performance metrics during @@ -243,7 +242,7 @@ Debayer::~Debayer() */ /** - * \fn int Debayer::start() + * \fn int SoftwareIspPipeline::start() * \brief Execute a start signal in the debayer object from workerthread context * * The start() method is invoked so that a Debayer object can initialise @@ -255,11 +254,11 @@ Debayer::~Debayer() */ /** - * \fn void Debayer::stop() + * \fn void SoftwareIspPipeline::stop() * \brief Stop the debayering process and perform cleanup * * The stop() method is invoked as the logically corollary of start(). - * Debayer::stop() will be called by software_isp::stop() allowing for any + * SoftwareIspPipeline::stop() will be called by software_isp::stop() allowing for any * cleanup which should happend with stop(). * * The stop method similar to start() is useful for DebayerEGL as it allows @@ -268,10 +267,10 @@ Debayer::~Debayer() */ /** - * \fn void Debayer::dmaSyncBegin(DebayerParams ¶ms) + * \fn void SoftwareIspPipeline::dmaSyncBegin(DebayerParams ¶ms) * \brief Common CPU/GPU Dma Sync Buffer begin */ -void Debayer::dmaSyncBegin(std::vector &dmaSyncers, FrameBuffer *input, FrameBuffer *output) +void SoftwareIspPipeline::dmaSyncBegin(std::vector &dmaSyncers, FrameBuffer *input, FrameBuffer *output) { for (const FrameBuffer::Plane &plane : input->planes()) dmaSyncers.emplace_back(plane.fd, DmaSyncer::SyncType::Read); @@ -283,10 +282,10 @@ void Debayer::dmaSyncBegin(std::vector &dmaSyncers, FrameBuffer *inpu } /** - * \fn void Debayer::isStandardBayerOrder(BayerFormat::Order order) + * \fn void SoftwareIspPipeline::isStandardBayerOrder(BayerFormat::Order order) * \brief Common method to validate standard 2x2 Bayer pattern of 2 Green, 1 Blue, 1 Red pixels */ -bool Debayer::isStandardBayerOrder(BayerFormat::Order order) +bool SoftwareIspPipeline::isStandardBayerOrder(BayerFormat::Order order) { return order == BayerFormat::BGGR || order == BayerFormat::GBRG || order == BayerFormat::GRBG || order == BayerFormat::RGGB; diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/software_isp_pipeline.h similarity index 93% rename from src/libcamera/software_isp/debayer.h rename to src/libcamera/software_isp/software_isp_pipeline.h index a2a17ec18..63b7dddd7 100644 --- a/src/libcamera/software_isp/debayer.h +++ b/src/libcamera/software_isp/software_isp_pipeline.h @@ -6,7 +6,7 @@ * Authors: * Hans de Goede * - * debayering base class + * SoftwareIspPipeline base class */ #pragma once @@ -32,11 +32,11 @@ class FrameBuffer; LOG_DECLARE_CATEGORY(Debayer) -class Debayer : public Object +class SoftwareIspPipeline : public Object { public: - Debayer(const CameraManager &cm); - virtual ~Debayer() = 0; + SoftwareIspPipeline(const CameraManager &cm); + virtual ~SoftwareIspPipeline() = 0; virtual int configure(const StreamConfiguration &inputCfg, const std::vector> &outputCfgs, diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/software_isp_pipeline_cpu.cpp similarity index 84% rename from src/libcamera/software_isp/debayer_cpu.cpp rename to src/libcamera/software_isp/software_isp_pipeline_cpu.cpp index d2596d32b..affe4f180 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/software_isp_pipeline_cpu.cpp @@ -9,7 +9,7 @@ * CPU based debayering class */ -#include "debayer_cpu.h" +#include "software_isp_pipeline_cpu.h" #include #include @@ -38,7 +38,7 @@ namespace libcamera { class DebayerCpuThread : public Thread, public Object { public: - DebayerCpuThread(DebayerCpu *debayer, unsigned int threadIndex, + DebayerCpuThread(SoftwareIspPipelineCpu *pipeline, unsigned int threadIndex, bool enableInputMemcpy); void configure(unsigned int yStart, unsigned int yEnd); @@ -54,7 +54,7 @@ private: /* Max. supported Bayer pattern height is 4, debayering this requires 5 lines */ static constexpr unsigned int kMaxLineBuffers = 5; - DebayerCpu *debayer_; + SoftwareIspPipelineCpu *pipeline_; unsigned int threadIndex_; unsigned int yStart_; unsigned int yEnd_; @@ -67,33 +67,33 @@ private: /** * \brief Construct a DebayerCpuThread object - * \param[in] debayer pointer back to the DebayerCpuObject this thread belongs to + * \param[in] debayer pointer back to the SoftwareIspPipelineCpu this thread belongs to * \param[in] threadIndex 0 .. n thread-index value for the thread * \param[in] enableInputMemcpy when set copy input data to a heap buffer before use */ -DebayerCpuThread::DebayerCpuThread(DebayerCpu *debayer, unsigned int threadIndex, +DebayerCpuThread::DebayerCpuThread(SoftwareIspPipelineCpu *pipeline, unsigned int threadIndex, bool enableInputMemcpy) : Thread("DebayerCpu:" + std::to_string(threadIndex)), - debayer_(debayer), threadIndex_(threadIndex), + pipeline_(pipeline), threadIndex_(threadIndex), enableInputMemcpy_(enableInputMemcpy) { moveToThread(this); } /** - * \class DebayerCpu + * \class SoftwareIspPipelineCpu * \brief Class for debayering on the CPU * * Implementation for CPU based debayering */ /** - * \brief Constructs a DebayerCpu object + * \brief Constructs a SoftwareIspPipelineCpu object * \param[in] stats Pointer to the stats object to use * \param[in] cm The camera manager */ -DebayerCpu::DebayerCpu(std::unique_ptr stats, const CameraManager &cm) - : Debayer(cm), stats_(std::move(stats)) +SoftwareIspPipelineCpu::SoftwareIspPipelineCpu(std::unique_ptr stats, const CameraManager &cm) + : SoftwareIspPipeline(cm), stats_(std::move(stats)) { /* * Reading from uncached buffers may be very slow. @@ -121,7 +121,7 @@ DebayerCpu::DebayerCpu(std::unique_ptr stats, const CameraManager &c LOG(Debayer, Debug) << "Thread count " << threadCount; } -DebayerCpu::~DebayerCpu() = default; +SoftwareIspPipelineCpu::~SoftwareIspPipelineCpu() = default; #define DECLARE_SRC_POINTERS(pixel_t) \ const pixel_t *prev = (const pixel_t *)src[0] + xShift_; \ @@ -193,7 +193,7 @@ DebayerCpu::~DebayerCpu() = default; curr[x] / (div)) template -void DebayerCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) +void SoftwareIspPipelineCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) { DECLARE_SRC_POINTERS(uint8_t) @@ -204,7 +204,7 @@ void DebayerCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) } template -void DebayerCpu::debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) +void SoftwareIspPipelineCpu::debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) { DECLARE_SRC_POINTERS(uint8_t) @@ -215,7 +215,7 @@ void DebayerCpu::debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) } template -void DebayerCpu::debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) +void SoftwareIspPipelineCpu::debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) { DECLARE_SRC_POINTERS(uint16_t) @@ -227,7 +227,7 @@ void DebayerCpu::debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) } template -void DebayerCpu::debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) +void SoftwareIspPipelineCpu::debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) { DECLARE_SRC_POINTERS(uint16_t) @@ -239,7 +239,7 @@ void DebayerCpu::debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) } template -void DebayerCpu::debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) +void SoftwareIspPipelineCpu::debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) { DECLARE_SRC_POINTERS(uint16_t) @@ -251,7 +251,7 @@ void DebayerCpu::debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) } template -void DebayerCpu::debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) +void SoftwareIspPipelineCpu::debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) { DECLARE_SRC_POINTERS(uint16_t) @@ -263,7 +263,7 @@ void DebayerCpu::debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) } template -void DebayerCpu::debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) +void SoftwareIspPipelineCpu::debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) { const int widthInBytes = window_.width * 5 / 4; const uint8_t *prev = src[0]; @@ -289,7 +289,7 @@ void DebayerCpu::debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) } template -void DebayerCpu::debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) +void SoftwareIspPipelineCpu::debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) { const int widthInBytes = window_.width * 5 / 4; const uint8_t *prev = src[0]; @@ -310,7 +310,7 @@ void DebayerCpu::debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) } template -void DebayerCpu::debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[]) +void SoftwareIspPipelineCpu::debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[]) { const int widthInBytes = window_.width * 5 / 4; const uint8_t *prev = src[0]; @@ -331,7 +331,7 @@ void DebayerCpu::debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[]) } template -void DebayerCpu::debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]) +void SoftwareIspPipelineCpu::debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]) { const int widthInBytes = window_.width * 5 / 4; const uint8_t *prev = src[0]; @@ -352,7 +352,7 @@ void DebayerCpu::debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]) } template -void DebayerCpu::debayer12P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) +void SoftwareIspPipelineCpu::debayer12P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) { const int widthInBytes = window_.width * 3 / 2; const uint8_t *prev = src[0]; @@ -370,7 +370,7 @@ void DebayerCpu::debayer12P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) } template -void DebayerCpu::debayer12P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) +void SoftwareIspPipelineCpu::debayer12P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) { const int widthInBytes = window_.width * 3 / 2; const uint8_t *prev = src[0]; @@ -388,7 +388,7 @@ void DebayerCpu::debayer12P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) } template -void DebayerCpu::debayer12P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[]) +void SoftwareIspPipelineCpu::debayer12P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[]) { const int widthInBytes = window_.width * 3 / 2; const uint8_t *prev = src[0]; @@ -406,7 +406,7 @@ void DebayerCpu::debayer12P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[]) } template -void DebayerCpu::debayer12P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]) +void SoftwareIspPipelineCpu::debayer12P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]) { const int widthInBytes = window_.width * 3 / 2; const uint8_t *prev = src[0]; @@ -428,7 +428,7 @@ void DebayerCpu::debayer12P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]) * Return 0 on success, a negative errno value on failure * (unsupported parameters). */ -int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config) +int SoftwareIspPipelineCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config) { BayerFormat bayerFormat = BayerFormat::fromPixelFormat(inputFormat); @@ -474,7 +474,7 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf return -EINVAL; } -int DebayerCpu::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config) +int SoftwareIspPipelineCpu::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config) { if (outputFormat == formats::RGB888 || outputFormat == formats::BGR888) { config.bpp = 24; @@ -496,7 +496,7 @@ int DebayerCpu::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &c * Check for standard Bayer orders and set xShift_ and swap debayer0/1, so that * a single pair of BGGR debayer functions can be used for all 4 standard orders. */ -int DebayerCpu::setupStandardBayerOrder(BayerFormat::Order order) +int SoftwareIspPipelineCpu::setupStandardBayerOrder(BayerFormat::Order order) { switch (order) { case BayerFormat::BGGR: @@ -520,13 +520,13 @@ int DebayerCpu::setupStandardBayerOrder(BayerFormat::Order order) #define SET_DEBAYER_METHODS(method0, method1) \ debayer0_ = addAlphaByte \ - ? (ccmEnabled ? &DebayerCpu::method0 : &DebayerCpu::method0) \ - : (ccmEnabled ? &DebayerCpu::method0 : &DebayerCpu::method0); \ + ? (ccmEnabled ? &SoftwareIspPipelineCpu::method0 : &SoftwareIspPipelineCpu::method0) \ + : (ccmEnabled ? &SoftwareIspPipelineCpu::method0 : &SoftwareIspPipelineCpu::method0); \ debayer1_ = addAlphaByte \ - ? (ccmEnabled ? &DebayerCpu::method1 : &DebayerCpu::method1) \ - : (ccmEnabled ? &DebayerCpu::method1 : &DebayerCpu::method1); + ? (ccmEnabled ? &SoftwareIspPipelineCpu::method1 : &SoftwareIspPipelineCpu::method1) \ + : (ccmEnabled ? &SoftwareIspPipelineCpu::method1 : &SoftwareIspPipelineCpu::method1); -int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, +int SoftwareIspPipelineCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat, bool ccmEnabled) { @@ -639,9 +639,9 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, return invalidFmt(); } -int DebayerCpu::configure(const StreamConfiguration &inputCfg, - const std::vector> &outputCfgs, - bool ccmEnabled) +int SoftwareIspPipelineCpu::configure(const StreamConfiguration &inputCfg, + const std::vector> &outputCfgs, + bool ccmEnabled) { if (getInputConfig(inputCfg.pixelFormat, inputConfig_) != 0) return -EINVAL; @@ -733,14 +733,14 @@ int DebayerCpu::configure(const StreamConfiguration &inputCfg, */ void DebayerCpuThread::configure(unsigned int yStart, unsigned int yEnd) { - Debayer::DebayerInputConfig &inputConfig = debayer_->inputConfig_; + SoftwareIspPipelineCpu::DebayerInputConfig &inputConfig = pipeline_->inputConfig_; yStart_ = yStart; yEnd_ = yEnd; /* pad with patternSize.Width on both left and right side */ lineBufferPadding_ = inputConfig.patternSize.width * inputConfig.bpp / 8; - lineBufferLength_ = debayer_->window_.width * inputConfig.bpp / 8 + + lineBufferLength_ = pipeline_->window_.width * inputConfig.bpp / 8 + 2 * lineBufferPadding_; if (enableInputMemcpy_) { @@ -753,9 +753,9 @@ void DebayerCpuThread::configure(unsigned int yStart, unsigned int yEnd) * Get width and height at which the bayer-pattern repeats. * Return pattern-size or an empty Size for an unsupported inputFormat. */ -Size DebayerCpu::patternSize(PixelFormat inputFormat) +Size SoftwareIspPipelineCpu::patternSize(PixelFormat inputFormat) { - DebayerCpu::DebayerInputConfig config; + SoftwareIspPipelineCpu::DebayerInputConfig config; if (getInputConfig(inputFormat, config) != 0) return {}; @@ -763,9 +763,9 @@ Size DebayerCpu::patternSize(PixelFormat inputFormat) return config.patternSize; } -std::vector DebayerCpu::formats(PixelFormat inputFormat) +std::vector SoftwareIspPipelineCpu::formats(PixelFormat inputFormat) { - DebayerCpu::DebayerInputConfig config; + SoftwareIspPipelineCpu::DebayerInputConfig config; if (getInputConfig(inputFormat, config) != 0) return std::vector(); @@ -774,9 +774,9 @@ std::vector DebayerCpu::formats(PixelFormat inputFormat) } std::tuple -DebayerCpu::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) +SoftwareIspPipelineCpu::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) { - DebayerCpu::DebayerOutputConfig config; + SoftwareIspPipelineCpu::DebayerOutputConfig config; if (getOutputConfig(outputFormat, config) != 0) return std::make_tuple(0, 0); @@ -789,7 +789,7 @@ DebayerCpu::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size void DebayerCpuThread::setupInputMemcpy(const uint8_t *linePointers[]) { - const unsigned int patternHeight = debayer_->inputConfig_.patternSize.height; + const unsigned int patternHeight = pipeline_->inputConfig_.patternSize.height; if (!enableInputMemcpy_) return; @@ -807,18 +807,18 @@ void DebayerCpuThread::setupInputMemcpy(const uint8_t *linePointers[]) void DebayerCpuThread::shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src) { - const unsigned int patternHeight = debayer_->inputConfig_.patternSize.height; + const unsigned int patternHeight = pipeline_->inputConfig_.patternSize.height; for (unsigned int i = 0; i < patternHeight; i++) linePointers[i] = linePointers[i + 1]; linePointers[patternHeight] = - src + (patternHeight / 2) * (int)debayer_->inputConfig_.stride; + src + (patternHeight / 2) * (int)pipeline_->inputConfig_.stride; } void DebayerCpuThread::memcpyNextLine(const uint8_t *linePointers[]) { - const unsigned int patternHeight = debayer_->inputConfig_.patternSize.height; + const unsigned int patternHeight = pipeline_->inputConfig_.patternSize.height; if (!enableInputMemcpy_) return; @@ -839,30 +839,30 @@ void DebayerCpuThread::memcpyNextLine(const uint8_t *linePointers[]) */ void DebayerCpuThread::process(uint32_t frame, const uint8_t *src, uint8_t *dst) { - Rectangle &window = debayer_->window_; + Rectangle &window = pipeline_->window_; /* Adjust src to top left corner of the window */ - src += (window.y + yStart_) * debayer_->inputConfig_.stride + - window.x * debayer_->inputConfig_.bpp / 8; + src += (window.y + yStart_) * pipeline_->inputConfig_.stride + + window.x * pipeline_->inputConfig_.bpp / 8; /* Adjust dst for yStart_ */ - dst += yStart_ * debayer_->outputConfig_.stride; + dst += yStart_ * pipeline_->outputConfig_.stride; - if (debayer_->inputConfig_.patternSize.height == 2) + if (pipeline_->inputConfig_.patternSize.height == 2) process2(frame, src, dst); else process4(frame, src, dst); - debayer_->workPendingMutex_.lock(); - debayer_->workPending_ &= ~(1 << threadIndex_); - debayer_->workPendingMutex_.unlock(); - debayer_->workPendingCv_.notify_one(); + pipeline_->workPendingMutex_.lock(); + pipeline_->workPending_ &= ~(1 << threadIndex_); + pipeline_->workPendingMutex_.unlock(); + pipeline_->workPendingCv_.notify_one(); } void DebayerCpuThread::process2(uint32_t frame, const uint8_t *src, uint8_t *dst) { - unsigned int outputStride = debayer_->outputConfig_.stride; - unsigned int inputStride = debayer_->inputConfig_.stride; - Rectangle &window = debayer_->window_; + unsigned int outputStride = pipeline_->outputConfig_.stride; + unsigned int inputStride = pipeline_->inputConfig_.stride; + Rectangle &window = pipeline_->window_; unsigned int yEnd = yEnd_; /* Holds [0] previous- [1] current- [2] next-line */ const uint8_t *linePointers[3]; @@ -895,14 +895,14 @@ void DebayerCpuThread::process2(uint32_t frame, const uint8_t *src, uint8_t *dst for (unsigned int y = yStart_; y < yEnd; y += 2) { shiftLinePointers(linePointers, src); memcpyNextLine(linePointers); - debayer_->stats_->processLine0(frame, y, linePointers, threadIndex_); - debayer_->debayer0(dst, linePointers); + pipeline_->stats_->processLine0(frame, y, linePointers, threadIndex_); + pipeline_->debayer0(dst, linePointers); src += inputStride; dst += outputStride; shiftLinePointers(linePointers, src); memcpyNextLine(linePointers); - debayer_->debayer1(dst, linePointers); + pipeline_->debayer1(dst, linePointers); src += inputStride; dst += outputStride; } @@ -910,15 +910,15 @@ void DebayerCpuThread::process2(uint32_t frame, const uint8_t *src, uint8_t *dst if (window.y == 0 && yEnd_ == window.height) { shiftLinePointers(linePointers, src); memcpyNextLine(linePointers); - debayer_->stats_->processLine0(frame, yEnd, linePointers, threadIndex_); - debayer_->debayer0(dst, linePointers); + pipeline_->stats_->processLine0(frame, yEnd, linePointers, threadIndex_); + pipeline_->debayer0(dst, linePointers); src += inputStride; dst += outputStride; shiftLinePointers(linePointers, src); /* next line may point outside of src, use prev. */ linePointers[2] = linePointers[0]; - debayer_->debayer1(dst, linePointers); + pipeline_->debayer1(dst, linePointers); src += inputStride; dst += outputStride; } @@ -926,8 +926,8 @@ void DebayerCpuThread::process2(uint32_t frame, const uint8_t *src, uint8_t *dst void DebayerCpuThread::process4(uint32_t frame, const uint8_t *src, uint8_t *dst) { - unsigned int outputStride = debayer_->outputConfig_.stride; - unsigned int inputStride = debayer_->inputConfig_.stride; + unsigned int outputStride = pipeline_->outputConfig_.stride; + unsigned int inputStride = pipeline_->inputConfig_.stride; /* * This holds pointers to [0] 2-lines-up [1] 1-line-up [2] current-line @@ -951,33 +951,33 @@ void DebayerCpuThread::process4(uint32_t frame, const uint8_t *src, uint8_t *dst for (unsigned int y = yStart_; y < yEnd_; y += 4) { shiftLinePointers(linePointers, src); memcpyNextLine(linePointers); - debayer_->stats_->processLine0(frame, y, linePointers, threadIndex_); - debayer_->debayer0(dst, linePointers); + pipeline_->stats_->processLine0(frame, y, linePointers, threadIndex_); + pipeline_->debayer0(dst, linePointers); src += inputStride; dst += outputStride; shiftLinePointers(linePointers, src); memcpyNextLine(linePointers); - debayer_->debayer1(dst, linePointers); + pipeline_->debayer1(dst, linePointers); src += inputStride; dst += outputStride; shiftLinePointers(linePointers, src); memcpyNextLine(linePointers); - debayer_->stats_->processLine2(frame, y, linePointers, threadIndex_); - debayer_->debayer2(dst, linePointers); + pipeline_->stats_->processLine2(frame, y, linePointers, threadIndex_); + pipeline_->debayer2(dst, linePointers); src += inputStride; dst += outputStride; shiftLinePointers(linePointers, src); memcpyNextLine(linePointers); - debayer_->debayer3(dst, linePointers); + pipeline_->debayer3(dst, linePointers); src += inputStride; dst += outputStride; } } -void DebayerCpu::updateGammaTable(const DebayerParams ¶ms) +void SoftwareIspPipelineCpu::updateGammaTable(const DebayerParams ¶ms) { const RGB blackLevel = params.blackLevel; /* Take let's say the green channel black level */ @@ -1007,7 +1007,7 @@ void DebayerCpu::updateGammaTable(const DebayerParams ¶ms) gammaTable_[blackIndex]); } -void DebayerCpu::updateLookupTables(const DebayerParams ¶ms) +void SoftwareIspPipelineCpu::updateLookupTables(const DebayerParams ¶ms) { const bool gammaUpdateNeeded = params.gamma != params_.gamma || @@ -1069,7 +1069,7 @@ void DebayerCpu::updateLookupTables(const DebayerParams ¶ms) params_ = params; } -void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms) +void SoftwareIspPipelineCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms) { bench_.startFrame(); @@ -1128,7 +1128,7 @@ void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output inputBufferReady.emit(input); } -int DebayerCpu::start() +int SoftwareIspPipelineCpu::start() { for (auto &thread : threads_) thread->start(); @@ -1136,7 +1136,7 @@ int DebayerCpu::start() return 0; } -void DebayerCpu::stop() +void SoftwareIspPipelineCpu::stop() { for (auto &thread : threads_) thread->exit(); @@ -1145,7 +1145,7 @@ void DebayerCpu::stop() thread->wait(); } -SizeRange DebayerCpu::sizes(PixelFormat inputFormat, const Size &inputSize) +SizeRange SoftwareIspPipelineCpu::sizes(PixelFormat inputFormat, const Size &inputSize) { Size patternSize = this->patternSize(inputFormat); unsigned int borderHeight = patternSize.height; diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/software_isp_pipeline_cpu.h similarity index 95% rename from src/libcamera/software_isp/debayer_cpu.h rename to src/libcamera/software_isp/software_isp_pipeline_cpu.h index 5281c65cb..fee1c979f 100644 --- a/src/libcamera/software_isp/debayer_cpu.h +++ b/src/libcamera/software_isp/software_isp_pipeline_cpu.h @@ -24,16 +24,16 @@ #include "libcamera/internal/software_isp/debayer_params.h" #include "libcamera/internal/software_isp/swstats_cpu.h" -#include "debayer.h" +#include "software_isp_pipeline.h" namespace libcamera { class DebayerCpuThread; -class DebayerCpu : public Debayer +class SoftwareIspPipelineCpu : public SoftwareIspPipeline { public: - DebayerCpu(std::unique_ptr stats, const CameraManager &cm); - ~DebayerCpu(); + SoftwareIspPipelineCpu(std::unique_ptr stats, const CameraManager &cm); + ~SoftwareIspPipelineCpu(); int configure(const StreamConfiguration &inputCfg, const std::vector> &outputCfgs, @@ -79,7 +79,7 @@ private: * pointers are passed holding: src[0] = 2-lines-up, src[1] = 1-line-up * src[2] = current-line, src[3] = 1-line-down, src[4] = 2-lines-down. */ - using debayerFn = void (DebayerCpu::*)(uint8_t *dst, const uint8_t *src[]); + using debayerFn = void (SoftwareIspPipelineCpu::*)(uint8_t *dst, const uint8_t *src[]); void debayer0(uint8_t *dst, const uint8_t *src[]) { (this->*debayer0_)(dst, src); } void debayer1(uint8_t *dst, const uint8_t *src[]) { (this->*debayer1_)(dst, src); } diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp similarity index 90% rename from src/libcamera/software_isp/debayer_egl.cpp rename to src/libcamera/software_isp/software_isp_pipeline_gpu.cpp index 8e52b45ae..53bb5e61f 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp @@ -7,7 +7,7 @@ * */ -#include "debayer_egl.h" +#include "software_isp_pipeline_gpu.h" #include #include @@ -28,27 +28,28 @@ namespace libcamera { /** - * \class DebayerEGL + * \class SoftwareIspPipelineGpu * \brief Class for debayering using an EGL Shader * * Implements an EGL shader based debayering solution. */ /** - * \brief Construct a DebayerEGL object + * \fn SoftwareIspPipelineGpu::SoftwareIspPipelineGpu(std::unique_ptr stats, const CameraManager &cm) + * \brief Construct a SoftwareIspPipelineGpu object * \param[in] stats Statistics processing object * \param[in] cm The camera manager */ -DebayerEGL::DebayerEGL(std::unique_ptr stats, const CameraManager &cm) - : Debayer(cm), stats_(std::move(stats)) +SoftwareIspPipelineGpu::SoftwareIspPipelineGpu(std::unique_ptr stats, const CameraManager &cm) + : SoftwareIspPipeline(cm), stats_(std::move(stats)) { } -DebayerEGL::~DebayerEGL() +SoftwareIspPipelineGpu::~SoftwareIspPipelineGpu() { } -int DebayerEGL::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config) +int SoftwareIspPipelineGpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config) { BayerFormat bayerFormat = BayerFormat::fromPixelFormat(inputFormat); @@ -94,7 +95,7 @@ int DebayerEGL::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf return -EINVAL; } -int DebayerEGL::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config) +int SoftwareIspPipelineGpu::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config) { if (outputFormat == formats::XRGB8888 || outputFormat == formats::ARGB8888 || outputFormat == formats::XBGR8888 || outputFormat == formats::ABGR8888) { @@ -108,7 +109,7 @@ int DebayerEGL::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &c return -EINVAL; } -int DebayerEGL::getShaderVariableLocations(void) +int SoftwareIspPipelineGpu::getShaderVariableLocations(void) { attributeVertex_ = glGetAttribLocation(programId_, "vertexIn"); attributeTexture_ = glGetAttribLocation(programId_, "textureIn"); @@ -139,7 +140,7 @@ int DebayerEGL::getShaderVariableLocations(void) return 0; } -int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputFormat) +int SoftwareIspPipelineGpu::initBayerShaders(PixelFormat inputFormat, PixelFormat outputFormat) { std::vector shaderEnv; unsigned int fragmentShaderDataLen = 0; @@ -290,9 +291,9 @@ int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputForm return getShaderVariableLocations(); } -int DebayerEGL::configure(const StreamConfiguration &inputCfg, - const std::vector> &outputCfgs, - [[maybe_unused]] bool ccmEnabled) +int SoftwareIspPipelineGpu::configure(const StreamConfiguration &inputCfg, + const std::vector> &outputCfgs, + [[maybe_unused]] bool ccmEnabled) { if (getInputConfig(inputCfg.pixelFormat, inputConfig_) != 0) return -EINVAL; @@ -353,9 +354,9 @@ int DebayerEGL::configure(const StreamConfiguration &inputCfg, return 0; } -Size DebayerEGL::patternSize(PixelFormat inputFormat) +Size SoftwareIspPipelineGpu::patternSize(PixelFormat inputFormat) { - DebayerEGL::DebayerInputConfig config; + SoftwareIspPipelineGpu::DebayerInputConfig config; if (getInputConfig(inputFormat, config) != 0) return {}; @@ -363,9 +364,9 @@ Size DebayerEGL::patternSize(PixelFormat inputFormat) return config.patternSize; } -std::vector DebayerEGL::formats(PixelFormat inputFormat) +std::vector SoftwareIspPipelineGpu::formats(PixelFormat inputFormat) { - DebayerEGL::DebayerInputConfig config; + SoftwareIspPipelineGpu::DebayerInputConfig config; if (getInputConfig(inputFormat, config) != 0) return std::vector(); @@ -374,9 +375,9 @@ std::vector DebayerEGL::formats(PixelFormat inputFormat) } std::tuple -DebayerEGL::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) +SoftwareIspPipelineGpu::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) { - DebayerEGL::DebayerOutputConfig config; + SoftwareIspPipelineGpu::DebayerOutputConfig config; if (getOutputConfig(outputFormat, config) != 0) return std::make_tuple(0, 0); @@ -387,7 +388,7 @@ DebayerEGL::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size return std::make_tuple(stride, stride * size.height); } -void DebayerEGL::setShaderVariableValues(const DebayerParams ¶ms) +void SoftwareIspPipelineGpu::setShaderVariableValues(const DebayerParams ¶ms) { /* * Raw Bayer 8-bit, and packed raw Bayer 10-bit/12-bit formats @@ -510,7 +511,7 @@ void DebayerEGL::setShaderVariableValues(const DebayerParams ¶ms) return; } -int DebayerEGL::debayerGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms, std::optional *inMapped, std::optional *inDmaSyncer) +int SoftwareIspPipelineGpu::debayerGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms, std::optional *inMapped, std::optional *inDmaSyncer) { bool dmabuf_import_succeeded = false; @@ -555,7 +556,7 @@ int DebayerEGL::debayerGPU(FrameBuffer *input, FrameBuffer *output, const Debaye return 0; } -void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms) +void SoftwareIspPipelineGpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms) { bench_.startFrame(); @@ -607,7 +608,7 @@ error: return; } -int DebayerEGL::start() +int SoftwareIspPipelineGpu::start() { GLint maxTextureImageUnits; @@ -630,7 +631,7 @@ int DebayerEGL::start() return 0; } -void DebayerEGL::stop() +void SoftwareIspPipelineGpu::stop() { eglImageBayerOut_.reset(); eglImageBayerIn_.reset(); @@ -639,7 +640,7 @@ void DebayerEGL::stop() glDeleteProgram(programId_); } -SizeRange DebayerEGL::sizes(PixelFormat inputFormat, const Size &inputSize) +SizeRange SoftwareIspPipelineGpu::sizes(PixelFormat inputFormat, const Size &inputSize) { Size patternSize = this->patternSize(inputFormat); unsigned int borderHeight = patternSize.height; diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/software_isp_pipeline_gpu.h similarity index 93% rename from src/libcamera/software_isp/debayer_egl.h rename to src/libcamera/software_isp/software_isp_pipeline_gpu.h index 875e7cfc5..eb365d198 100644 --- a/src/libcamera/software_isp/debayer_egl.h +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.h @@ -27,7 +27,7 @@ #include #include -#include "debayer.h" +#include "software_isp_pipeline.h" namespace libcamera { @@ -36,11 +36,11 @@ namespace libcamera { class CameraManager; -class DebayerEGL : public Debayer +class SoftwareIspPipelineGpu : public SoftwareIspPipeline { public: - DebayerEGL(std::unique_ptr stats, const CameraManager &cm); - ~DebayerEGL(); + SoftwareIspPipelineGpu(std::unique_ptr stats, const CameraManager &cm); + ~SoftwareIspPipelineGpu(); int configure(const StreamConfiguration &inputCfg, const std::vector> &outputCfgs, From patchwork Thu Jun 18 12:22:15 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26934 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 AE650C328C for ; Thu, 18 Jun 2026 12:23:03 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 35A5C629DE; Thu, 18 Jun 2026 14:23:01 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="dAs88bqi"; 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 1254D629B6 for ; Thu, 18 Jun 2026 14:22:59 +0200 (CEST) Received: by mail-wm1-x330.google.com with SMTP id 5b1f17b1804b1-490aebf33e9so3915585e9.3 for ; Thu, 18 Jun 2026 05:22:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785379; x=1782390179; 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=FqNWrQwNLFM731dd+9mymOcD0H2BPBsCagCZYSKCaps=; b=dAs88bqiter0TL8WEk0fbXtK3mDNz+WvOqdMGrs/R4O4Sl25wUr3cOWzv9A2HxAcrE 7mvF3HB5LyM4Ti89NlHbriPVj+veezETpRf+T8/658ExDt2bFlheVpFay2hWvWtSzB4s XPZQ+Q9spUwiTgkRmkH7OkQknxDPJKJ6KmageBwBWq7OGFGOSx0LyPvJDOXquwvhggbU hE1Y+8lD/3ViDguCTWGafPtRNgf/JCHTqK15TVM9SI0n57V+62kLFZsvMpsEBgmhxlTx +1wNcwfH+lDycjAEum5zmP934VgojZXe6yya3hmtCfE5KNbhQJCBzcLOkkV94OT5uUDZ +KSQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785379; x=1782390179; 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=FqNWrQwNLFM731dd+9mymOcD0H2BPBsCagCZYSKCaps=; b=CElM4zLVOlKifJjbXL+EOy8OCmBw10YBAM5u21UJceSDux0FEDI4+nPhSTKtv3ne5y qac/GwI3UOIDan8xeI2ra5zebTAD8PbyeHDDQyz1P55RnTpxF37iKGMaS9mEEqIqBnaJ ScsuJFX+yS+U9OJz+OIUgBeHjnA1/eWFgjZJLREL7c1ICfaat5G7xmGIdiS9aWGgyws6 NrygrbDlq94OlkAgnLHoEYIG3GYyrTOU6QTUVtiSkvrLgyP7lNhJ+GpTGUvGBW0S7eDD sIXpHYFC5zjyI54gaIvXww5reoqQgp2CzsaqUBQPgJ0T/o7radI/k+iih+nRiivf+Lxq t3zg== X-Gm-Message-State: AOJu0YzUnQ9zH3/V20hRNNzMKjYSSqjDwiu6bXBML4mV5q+mal9DaVBN 98m4DAXb9LuBE7eEAsB9NIW4VtzQoOmukO/16MUE7yYnwb2AxSH8xxiDt/If3AMsvY/lGezrCHS tQI2ZZH4= X-Gm-Gg: AfdE7cnchjGOORSmf2wpWZJG5QCkfWBEqQZqhT+gv83faDNCSdIawoi4lgzDg5INinX JVJ+FjbD/QgTtCaH8KksUowQXhNPPv8IjFW+UNU5vDrAXXu9uARyVvjMkZwh63C9npszqZMAwir h7VDzY6wQlNc9jCzUjvrN3zuFGHsjY0PhxN0V3Q9aB2ywM3RyJPaoP1+gJb1nwVxO4Wk4SlxlOv qUueSyuEbjorSnYbq+z9NXPE11SfE4Lb3LWH1N7Oek80lyvFjdVitmtmY+FO2ucZ4OEZv/fjEQn hsWIwSWPpgMPBI4Gp6kmXmyadsxl8OHq4Zx+wpVENZXsDGvXIxNkmDo93/65PTBRNwWDVP/XwnI 0BXhQNkM2JPWeZuPKOMs6v5IESEpiduuNAB4p9sbqrobZFc77NtUtxpcraHqyVvMCLwSPtLMJR+ 2D2vPMju6VKWv/DKuEcuUTp9IdeQD7 X-Received: by 2002:a05:600c:1c25:b0:488:ac01:72de with SMTP id 5b1f17b1804b1-492333e8f29mr129461395e9.5.1781785378539; Thu, 18 Jun 2026 05:22:58 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.22.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:22:58 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 02/30] libcamera: software_isp: gpu: Change the name of eglImageBayerOut_ to eglImageRGBAOut_ Date: Thu, 18 Jun 2026 13:22:15 +0100 Message-ID: <20260618122245.946138-3-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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 our mutli-pass shader design we will use textures to pass the output of one compute or fragment shader to the next. Each phase will have its own distinct name and output. A better more accurate name for the thing which we render into is eglImageRGBAOut_ which has a very obvious meaning - its our RGBA output. We aren't outputting Bayer data here, we are outputting RGBA data so denote it as such by way of its name. Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/software_isp_pipeline_gpu.cpp | 6 +++--- src/libcamera/software_isp/software_isp_pipeline_gpu.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp index 53bb5e61f..c68a04fff 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp @@ -538,7 +538,7 @@ int SoftwareIspPipelineGpu::debayerGPU(FrameBuffer *input, FrameBuffer *output, } /* Generate the output render framebuffer as render to texture */ - egl_.createOutputDMABufTexture2D(*eglImageBayerOut_, output->planes()[0].fd.get()); + egl_.createOutputDMABufTexture2D(*eglImageRGBAOut_, output->planes()[0].fd.get()); setShaderVariableValues(params); glViewport(0, 0, width_, height_); @@ -626,14 +626,14 @@ int SoftwareIspPipelineGpu::start() eglImageBayerIn_ = std::make_unique(glFormat_, inputConfig_.stride / bytesPerPixel_, height_, inputConfig_.stride, GL_TEXTURE0, 0); /* Texture we will render to */ - eglImageBayerOut_ = std::make_unique(GL_RGBA, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE1, 1); + eglImageRGBAOut_ = std::make_unique(GL_RGBA, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE1, 1); return 0; } void SoftwareIspPipelineGpu::stop() { - eglImageBayerOut_.reset(); + eglImageRGBAOut_.reset(); eglImageBayerIn_.reset(); if (programId_) diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.h b/src/libcamera/software_isp/software_isp_pipeline_gpu.h index eb365d198..6f161e063 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.h +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.h @@ -74,7 +74,7 @@ private: /* Pointer to object representing input texture */ std::unique_ptr eglImageBayerIn_; - std::unique_ptr eglImageBayerOut_; + std::unique_ptr eglImageRGBAOut_; /* Shader parameters */ float firstRed_x_; From patchwork Thu Jun 18 12:22:16 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26936 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 0EDAEBF415 for ; Thu, 18 Jun 2026 12:23:09 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 52A7362B29; Thu, 18 Jun 2026 14:23:06 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="yIsO7i5s"; dkim-atps=neutral Received: from mail-wr1-x435.google.com (mail-wr1-x435.google.com [IPv6:2a00:1450:4864:20::435]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2B8F662987 for ; Thu, 18 Jun 2026 14:23:00 +0200 (CEST) Received: by mail-wr1-x435.google.com with SMTP id ffacd0b85a97d-45eeba68948so678305f8f.1 for ; Thu, 18 Jun 2026 05:23:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785379; x=1782390179; 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=1J5bcMG3cS5HzAUNVk+psEM90P+jr41K1tK0MCZOzXo=; b=yIsO7i5sXz5VY6ao1dJ+hePHxUC6mh1g59mlwT0sH484QWw2wJGcITJbTJdZC2t3Kg 4EKxvNFEPRupDFsGWyaNCe2EY7T/H68FZeTgqZyTGCzqvE4xMHTYQKJ/MDbho7nxxve3 ZZ2wsp2F9txunWvidfLilW7/XkvvsL/rqmQ8Vm2zUuwng7YMJDDlYe5q8oyhSQBMkjB6 BJ5IA7wDK+lxa1KxR3UUI6iIxvnQi/diQHB6tJ0rXvUNsAAqYLidrqrAwN9BrYPC4aTt js0VA5Qe2BNQDCLLDSSnezFKtKkgcV+RjRNxQZhZ5XzHj6ni3dtNuMTCID0oegUQRasL Yl3g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785379; x=1782390179; 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=1J5bcMG3cS5HzAUNVk+psEM90P+jr41K1tK0MCZOzXo=; b=rVMOAbF25YZOHAdY0OyKtMRcTQa9J4GoCVag6b920rOma15OFxNLiFvWaBvoXOwPMm W5MctHMA4U5L3ZbPjfvT/KUNTsAp5kTj13ReeQd+OHTAOfvjZ9RU9mSCbpQrpLjvGqFm h3LZsgCogYEvfDBxgUeEHLEqn3q8QjZKiP1dYZUGEUIunkhnfNKxpKYIs+k9/521Wrn0 3+P8fzmdHQXsc/Y6X4cEvN31c/D6TISsJYVqkhTRiRGmW0DvaGTag9uzXdI66KugH2Qh Jvcae+ESzBgaWlgNPsrzqSIxujzFAbP8QTItLhrV0wUxIymlSd8ufhXivbc9d8I8hCvu hvoA== X-Gm-Message-State: AOJu0YzgmFoJeQbsATUkNhA4D+miPhTDfNCYqOBenkTOjO0ZAfeP3zHt ljSlSZDCMB08I/fDnxICFtUEW8gxH3QaDOAAp0jt83bWi8g7jBuOQSTuBhPvd4JR/CzMqCJmJs4 EKhjg0t0= X-Gm-Gg: AfdE7clf8N1hLthzSi3F1+c+bcblyMuckZTQJfrmSGyR+WK/dfLIi5klZfBFSO9WMB0 oqlHpcMgczDWy2/b35k2F0mRsoH2nkdVjSVHVAzA7WDqEUQhFnU8j4H1rl/35juJlCMOS9re/ZA ASZ9q7F67SYMF9a8VnKejQrDVJqefsXRcAazkyW57j1VtMnAqOXlwn9H4PvlPybQz0Lmg5UzCfy l3cxzVnwaUd4iUrDSIrEOW3ojuXX/DBXu5WprFNiM4EcrX7fhUM5QHRoNxTHxQVjKnFRACP8UMN zREh7KAeas4zPsJoUatWTlOC3Iw/uJF/7VWkuDfBsmPsmsNSpQl6Aadj7AC4jsoRnEqLiZphvdZ XSV2q808LAwGDyhaWBhMJ7M2d8CwV+kEnZpjksYfteXXpusAA07zj45m1dPhJVNf44u6SyS+61K HAnk3MTBWLn1emr7O/jD56xtbB1tQM X-Received: by 2002:a05:600c:247:b0:490:bd66:e522 with SMTP id 5b1f17b1804b1-492333d8c06mr108522325e9.29.1781785379367; Thu, 18 Jun 2026 05:22:59 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.22.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:22:58 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 03/30] libcamera: software_isp: gpu: rename debayerGPU to processGPU Date: Thu, 18 Jun 2026 13:22:16 +0100 Message-ID: <20260618122245.946138-4-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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 function will do more than debayer, rename it to reflect. Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/software_isp_pipeline_gpu.cpp | 4 ++-- src/libcamera/software_isp/software_isp_pipeline_gpu.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp index c68a04fff..6f988d672 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp @@ -511,7 +511,7 @@ void SoftwareIspPipelineGpu::setShaderVariableValues(const DebayerParams ¶ms return; } -int SoftwareIspPipelineGpu::debayerGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms, std::optional *inMapped, std::optional *inDmaSyncer) +int SoftwareIspPipelineGpu::processGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms, std::optional *inMapped, std::optional *inDmaSyncer) { bool dmabuf_import_succeeded = false; @@ -569,7 +569,7 @@ void SoftwareIspPipelineGpu::process(uint32_t frame, FrameBuffer *input, FrameBu std::optional inMapped; std::optional inDmaSyncer; - if (debayerGPU(input, output, params, &inMapped, &inDmaSyncer)) { + if (processGPU(input, output, params, &inMapped, &inDmaSyncer)) { LOG(Debayer, Error) << "debayerGPU failed"; goto error; } diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.h b/src/libcamera/software_isp/software_isp_pipeline_gpu.h index 6f161e063..f0515d889 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.h +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.h @@ -65,7 +65,8 @@ private: int initBayerShaders(PixelFormat inputFormat, PixelFormat outputFormat); int getShaderVariableLocations(); void setShaderVariableValues(const DebayerParams ¶ms); - int debayerGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms, std::optional *mappedInputBuffer, std::optional *inputBufferDmaSyncer); + int processGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms, std::optional *mappedInputBuffer, std::optional *inputBufferDmaSyncer); + void configureTexture(GLuint &texture); /* Shader program identifiers */ GLuint vertexShaderId_ = 0; From patchwork Thu Jun 18 12:22:17 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26937 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 D31FFC3302 for ; Thu, 18 Jun 2026 12:23:10 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B1B7D62B41; Thu, 18 Jun 2026 14:23:07 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="Ko3rLRBk"; dkim-atps=neutral Received: from mail-wm1-x32c.google.com (mail-wm1-x32c.google.com [IPv6:2a00:1450:4864:20::32c]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A0C65629AB for ; Thu, 18 Jun 2026 14:23:00 +0200 (CEST) Received: by mail-wm1-x32c.google.com with SMTP id 5b1f17b1804b1-49230a567a9so4339415e9.0 for ; Thu, 18 Jun 2026 05:23:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785380; x=1782390180; 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=vRWhBE/nddyiuyjIUBDoioByaHPkqc4AcaoqAb/P8s0=; b=Ko3rLRBkLH2LospBm+bTfOQ4pCyPMgz5ZES2WRbTUY5Yuklc9TmttFEEkuhUVY+wBm bVBDtqyJl12nu55JnaZzIXo/DvLioRwIIUnaWtlv5bo9fUj8+D57vaAVYZYH7IOb6onw O6j7atuCjTJ2R6InFC8JFIiiZsH0laeCd5fcWO57BFIZAGp2JVRz4Awjkj5oC8790yFI 1KKNgsMnhUlOr1WjwBVLoeiUjfD5SiZARsGe+zcwABr2t7jogaRuJF1cNI6IdC8F7Bvv 54l9L86OZ9peZ4Czyrp7f9R8DzRPMYeDxeATV16f2tfwTzPz2AeJlo9nGtiqjSb4VAhC 36bw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785380; x=1782390180; 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=vRWhBE/nddyiuyjIUBDoioByaHPkqc4AcaoqAb/P8s0=; b=fRzYRGJb8OomdLKa5OWlfANVj3Xzks/5Rq1OTTm+F4Yij+wAPFsxuuecXm8tQSXLm4 UrBhoSrLsk5NNS3mxZgwkw7VKElMIn1HhH/K8zYLoq/0z2RB311u3cmZfOUk31R+fUA4 h9FMXdPsUtW+7KJsGMSN+AIa5yhbwEsGO0IoBpgnVUZxbCrnYIIAMB+FkZw3g30Fuf8t grnIPPqWW1xji7h+hUovmG0E9GtfY9RQnXaYVsKA9YGKCQ7HG+ft2BqCGXEa4ItSyAdq ddQ9ygGQQY6BDtpVOgrpnl69lhMalrdqN6wJTM40UFsIyPPw6pxiEvtL38jaCeEOZ8uB W/Wg== X-Gm-Message-State: AOJu0YwSCLzmZqkLMnoYaYa2qenpk+5Mvt+AHUKbfWkfNiYySre43sux hFXLgeQKeBPWE34Fjka4xKoptTTIlzm1H1E3mPtjsvca3c3RLtl/3B0TvpHEd4AHBWflDTKWh1n EVK8kvqA= X-Gm-Gg: AfdE7cmp55t0OXLGbk7NIZhXkj9meR7AUmDzy5WbWpGFre/r+RKvkJI+UFtxvecruKb w1DzQEOQR1O8Z26FZ40vdqrfqhlo7i9tMIBBwMZjendvtsUypMdyDUoHJd6TpzNxYl3leO4a8YB EmfOGw0qRClHHQ+g/kM4r0qhmIrW3tNfR9yo6AWMn4bclWUFZhFsviAGK3FcCqUIZNY0bEwrbCP CSA+nLCqMelVcpTNGdZRr45S5OcdsbFK7VQhbP/2aPtVRGWWPPAIgt/AKAQHANQ2zdB4Obre2wo qkNc0SbjtVrwCu8syOGe6oMjyv2149TaDKmLBz9G5SjMlDMjGsPFUiyamNlr/HyKrRlEKND69P7 SEfjIwWh+RqI+cAPN75SgybcTG2ouOo8Owj0lMvZH444VRsKZ2Hc816oTndO2587r8veUPMXfOG kZ6iEBaVEhx7P2jxoG90ehqMEWCbc2 X-Received: by 2002:a05:600c:8217:b0:492:3754:15f2 with SMTP id 5b1f17b1804b1-4923754161dmr77053665e9.32.1781785380068; Thu, 18 Jun 2026 05:23:00 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.22.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:22:59 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 04/30] libcamera: software_isp: egl: Add new helper attachTextureToFBO Date: Thu, 18 Jun 2026 13:22:17 +0100 Message-ID: <20260618122245.946138-5-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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 method does what it says on the tin. It attaches a texture to a framebuffer object, splitting existing code into a helper function which we will use in subsequent patches. Signed-off-by: Bryan O'Donoghue --- include/libcamera/internal/egl.h | 2 ++ src/libcamera/egl.cpp | 42 +++++++++++++++++++++++--------- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h index 57f90d93f..d88617afa 100644 --- a/include/libcamera/internal/egl.h +++ b/include/libcamera/internal/egl.h @@ -108,6 +108,8 @@ public: int createOutputDMABufTexture2D(eGLImage &eglImage, int fd); void createTexture2D(eGLImage &eglImage, void *data); + int attachTextureToFBO(eGLImage &eglImage); + void pushEnv(std::vector &shaderEnv, const char *str); void makeCurrent(); diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index c185bb7ad..3ea694d7c 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -112,6 +112,32 @@ void eGL::flushOutput() glFlush(); } +/** + * \brief Attach a texture to a frame-buffer-object + * + * \param[in,out] eglImage EGL image containing texture to attach to FBO + * + * Helper function to make attachment of texture to FBO easy to reuse. + * + * \return 0 on success, or -ENODEV on failure + */ +int eGL::attachTextureToFBO(eGLImage &eglImage) +{ + int ret = 0; + + // 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; + ret = -ENODEV; + } + + return ret; +} + /** * \brief Create a DMA-BUF backed 2D texture * \param[in,out] eglImage EGL image to associate with the DMA-BUF @@ -127,6 +153,7 @@ void eGL::flushOutput() int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) { EGLint drm_format; + int ret; ASSERT(tid_ == Thread::currentId()); @@ -186,19 +213,10 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) 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); + if (output) + ret = attachTextureToFBO(eglImage); - GLenum err = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (err != GL_FRAMEBUFFER_COMPLETE) { - LOG(eGL, Error) << "glFrameBufferTexture2D error " << err; - return -ENODEV; - } - } - - return 0; + return ret; } /** From patchwork Thu Jun 18 12:22:18 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26938 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 E5ABBC3303 for ; Thu, 18 Jun 2026 12:23:11 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CA52C62B40; Thu, 18 Jun 2026 14:23:08 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="LDM7INbL"; dkim-atps=neutral Received: from mail-wm1-x32e.google.com (mail-wm1-x32e.google.com [IPv6:2a00:1450:4864:20::32e]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 62AF3629E3 for ; Thu, 18 Jun 2026 14:23:01 +0200 (CEST) Received: by mail-wm1-x32e.google.com with SMTP id 5b1f17b1804b1-490ae94a89eso6312135e9.1 for ; Thu, 18 Jun 2026 05:23:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785381; x=1782390181; 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=oDBiA8HS3JX8yt0LRD4gcwtMzbFmINhfLsRnr0WONfg=; b=LDM7INbLkyCzNtMJbULJ64T5NHnvBS5P5Ew801Zv8eTQZHsIjWTl4vDj070Ups0NR9 Sr/QPpz3/bM+1yVwN/XEQpvfL3JL/m37l/nNWsdMY9YNuM++Sf+C1WMbMnLctOK8KPHv Gftxdzh0s2optc/Q0O6tpiWfPk98P7uN2qXZ6PLvsjZVNbmQRfE82OHGZqn9YxAZZjyn VCkZLoWxlYjPWPEnzZiBvGUO0GHMlQX+q09vFIVY1/FfRpHhPgDe06nXxVOYMlenxE2C MFsflgzbQg45V80zoupl+MhOLXcSOxzMyS4A57VP85gZrUWVs6SPrm1+mmw6hrykLCXk oj6Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785381; x=1782390181; 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=oDBiA8HS3JX8yt0LRD4gcwtMzbFmINhfLsRnr0WONfg=; b=efdnOrxdaXUT+3qWtgmPf/lr334AFCQ9pWerw8W/7nYzzK3CFXwcbP54xuObDmz+7t t11vj9+AxfiQo43Oech/IsvXOu2g0pxIruj96zSW6gRa5TS/20U7y26wgcyx4peK9idH MzbJPiQU/M2ULEkXZwOaBXm1E1WYzH5fzaJdRVl75DJYCXsj1rZa1liWtIhRCq6hoRNR q2eg/Jfmsg0zR9b12Rd97gZUMa2FzOT2uCtgMXPFJMVXfXT8ljTqtLPosk7/ZtwsbP+v UltPP3Io2xReKKVNmR2DxpxXMZsDemGclczqItfD22P0H4FBBGudIQkSFciN/njw9HEI vSDQ== X-Gm-Message-State: AOJu0Yx0F2JXc8ieArI0+uLixi99CNRTjHVyEs8vX/TjsT/k3sHkBjX9 hoe2yJ0FvaW/rU1jWgG7WSG0z5OeF2PoeCIH8urETznFovMqCQ6lbqH12wXohzkX5TrUPmWBSml i/XzDUBg= X-Gm-Gg: AfdE7ckaOBUYvvV+VbrUuuHqWQzySqIuOg2JUAkB9L8XcwxwhqywQIj/tGzeRI8pWY3 g/k8z/jzKcLNZOoZayHnf1drIkNpJEpXvsoKBiwNOaGieZEeMqAtXiYQ4diQwX5TVchulEtGE9u Yq6O2/oamHs4wNAu/nGQKxFmFYnrTITGeVRq53GqiRSw3pBYiWlm3fzONDPY4KN0paebVDrLJWs ShFMcvD5zW728apVoj8aD6HQHvm00Xa29GGyBV1mleqoGU4dgl+Qh068sPNexVnWYRb/7cDVAK8 LT/BrUZXx19z6EAyZ3pbA4JyX5NzQcq8Y7WsgIYgTAPVdv+KsEDySSrxpSTMvZPIm4RVP5j0I7u 7ILqhpf7lWQvz51HL1w1OeWxREwzzfKwArkkHUZHDlQlKQINECn/UyIwFl3kPcZdPZS2yLRjsy6 9H3nrt1Z9l8Rpcuzaw0xzfE6AMFix/ X-Received: by 2002:a05:600d:8486:10b0:490:6e12:542d with SMTP id 5b1f17b1804b1-4923821b94emr41777835e9.19.1781785380904; Thu, 18 Jun 2026 05:23:00 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:00 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 05/30] libcamera: software_isp: gpu_pipeline_shader_pass: Add base class GpuPipelineShaderPass Date: Thu, 18 Jun 2026 13:22:18 +0100 Message-ID: <20260618122245.946138-6-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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 --- .../software_isp/gpu_pipeline_shader_pass.cpp | 74 +++++++++++++++++ .../software_isp/gpu_pipeline_shader_pass.h | 83 +++++++++++++++++++ src/libcamera/software_isp/meson.build | 1 + 3 files changed, 158 insertions(+) create mode 100644 src/libcamera/software_isp/gpu_pipeline_shader_pass.cpp create mode 100644 src/libcamera/software_isp/gpu_pipeline_shader_pass.h diff --git a/src/libcamera/software_isp/gpu_pipeline_shader_pass.cpp b/src/libcamera/software_isp/gpu_pipeline_shader_pass.cpp new file mode 100644 index 000000000..669a1c1b6 --- /dev/null +++ b/src/libcamera/software_isp/gpu_pipeline_shader_pass.cpp @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2026, Linaro Ltd + * + * Simple software ISP implementation + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "libcamera/internal/framebuffer.h" +#include "libcamera/internal/ipa_manager.h" +#include "libcamera/internal/software_isp/debayer_params.h" + +#include "gpu_pipeline_shader_pass.h" + +/** + * \file software_isp.cpp + * \brief Simple software ISP implementation + */ + +namespace libcamera { + +LOG_DEFINE_CATEGORY(GpuShaderPass) + +int GpuIspShaderPass::process(eGLImage &eglImageIn, eGLImage &eglImageOut, uint32_t width, uint32_t height, const DebayerParams ¶ms) +{ + /* Switch to the output framebuffer */ + egl_.useProgram(programId_); + egl_.attachTextureToFBO(eglImageOut); + + setShaderVariableValues(params, eglImageIn); + 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(GpuShaderPass, Error) << "Drawing scene fail " << err; + return -ENODEV; + } + + return 0; +} + +int GpuIspShaderPass::start() +{ + return 0; +} + +void GpuIspShaderPass::stop() +{ + if (programId_) + glDeleteProgram(programId_); +} + +void GpuIspShaderPass::configure(const struct PassConfig &passInputCfg, const struct PassConfig &passOutputCfg) +{ + passInputCfg_ = passInputCfg; + passOutputCfg_ = passOutputCfg; +} + +} diff --git a/src/libcamera/software_isp/gpu_pipeline_shader_pass.h b/src/libcamera/software_isp/gpu_pipeline_shader_pass.h new file mode 100644 index 000000000..d4d4cf34d --- /dev/null +++ b/src/libcamera/software_isp/gpu_pipeline_shader_pass.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2026, Linaro Ltd + * + * Authors: + * Bryan O'Donoghue + * + * GpuIspIspShaderPass base class + */ + +#pragma once + +#include + +#include +#include +#include + +#include +#include + +#include "libcamera/internal/egl.h" +#include "libcamera/internal/software_isp/debayer_params.h" + +#include +#include +#include + +#include "../glsl_shaders.h" + +namespace libcamera { + +#define DEBAYER_OPENGL_COORDS 4 + +class FrameBuffer; + +struct PassConfig { + Size size; + unsigned int stride; + PixelFormat format; + Rectangle window; +}; + +class GpuIspShaderPass : public Object +{ +public: + GpuIspShaderPass(eGL& egl) : egl_(egl) {} + ~GpuIspShaderPass() {} + + virtual int process(eGLImage &eglImageIn, eGLImage &eglImageOut, uint32_t width, uint32_t height, const DebayerParams ¶ms); + virtual int start(); + virtual void stop(); + virtual void configure(const struct PassConfig &passInputCfg, const struct PassConfig &passOutputCfg); + virtual int initShaders(PixelFormat inputFormat, PixelFormat outputFormat) = 0; + virtual int getShaderVariableLocations(void) = 0; + virtual void setShaderVariableValues(const DebayerParams ¶ms, eGLImage &eglImageIn) = 0; + virtual const char *name() const { return "GpuIspShaderPass"; } + + unsigned int getBytesPerPixel() { return bytesPerPixel_; }; + + /* glFormat_ is a special case we are moving to one shader which will use GL_R + * so rather than do a hack make ShaderPasses do the Textrue allocation and thus have + * access to glFormat_. Make glFormat_ available to the upper level class. + * This variabile will be dropped at the end of the series anyway. + */ + GLint glFormat_; + +protected: + eGL& egl_; + + /* Shader calculates this getter provides ability to interrogate if needed */ + unsigned int bytesPerPixel_; + + /* Shader program identifiers */ + GLuint vertexShaderId_ = 0; + GLuint fragmentShaderId_ = 0; + GLuint programId_ = 0; + + struct PassConfig passInputCfg_; + struct PassConfig passOutputCfg_; +}; + +} /* namespace libcamera */ diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build index 51cc6ac3e..f8bce5203 100644 --- a/src/libcamera/software_isp/meson.build +++ b/src/libcamera/software_isp/meson.build @@ -32,6 +32,7 @@ if mesa_works libcamera_internal_sources += files([ '../egl.cpp', 'software_isp_pipeline_gpu.cpp', + 'gpu_pipeline_shader_pass.cpp', ]) libcamera_deps += [ libegl, From patchwork Thu Jun 18 12:22:19 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26940 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 34029C3304 for ; Thu, 18 Jun 2026 12:23:16 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 34FDE62C7B; Thu, 18 Jun 2026 14:23:15 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="xfbELInR"; dkim-atps=neutral Received: from mail-wm1-x32b.google.com (mail-wm1-x32b.google.com [IPv6:2a00:1450:4864:20::32b]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6459D62987 for ; Thu, 18 Jun 2026 14:23:03 +0200 (CEST) Received: by mail-wm1-x32b.google.com with SMTP id 5b1f17b1804b1-4908b92904fso11839545e9.0 for ; Thu, 18 Jun 2026 05:23:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785383; x=1782390183; 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=2KNw94Q/s6NvGxjf3HPcINyW9wFENRp5rFz7Yc/uVaI=; b=xfbELInREjxuHpoktCuVVRGFKJ/hM3egk521oXOakuWiEiyE+d2nlkyqrWXY2q3qh4 MJ1c8h0YlFKoVV7PbGe9mN/BYpUvyOPX9iq8ZM7SD2845YraG6pu1NPLOoSU3ytvfoKu pnqdOkbHOAUS0K4MqixFrTZX1r/Q9eSQftL9NOZWG3iRv0OIqpNmdjhwvAakZz6c4Icm d7BZ1bWciESCxvg0p1kmS4mfwQkVDkcHhSrM89+VNxsLho0LStD41+09S2J8gPnwUZ/+ dASrMzi+k8CFswEA10kqGayrWJqOpe+wrZHFPEsHEqHE16jbKMkDZraGCReJZsh+LVpP b0nQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785383; x=1782390183; 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=2KNw94Q/s6NvGxjf3HPcINyW9wFENRp5rFz7Yc/uVaI=; b=BUmP9CNntAlroNsZr4M0BBaWN/HBGHOvcvfMhLNnKaKuDTLqwSZFNQzebdN3YoWn4i uJWRSVQzNfr+Hu4+/kpuRvBe9BYwhA7dop6RkU66g8wy1S7LTBqvoQGTYe5svvydHU70 VhYqNegWgdDarIungO4b7V0vystrpljrvh+17gRpb+0Txvv9t+5onnoOdwBdph1sFomf iVe/XMW355ux+9VwzCB7h9+YJOeM6H1vOzftYts3N82Fi7WnrlGcNX1Ah41zRVm8DMAj fVXN70xU4nH8zdueAQR394EECHXZYjIRTNVLCnkUKBeorEcIbN3/CK2TgycaWZeBpg3D kkng== X-Gm-Message-State: AOJu0YxBKUevHWz6SEffmHiMm/zv5cQWlQQo0TeCoTbes3r6qbDDQ4bD IlrnWbYR17d7pwrFOmT2eELFo7UBeg56V2pgm5fX6WDHKl51jFBrFbHYS7zH6l8fcZGJqSNFkm1 6k0jVmqI= X-Gm-Gg: AfdE7cm9UsnqQuE/+cpGLGKVNebujjCICrym2lO4lLk620+aaxw5kc4MRPbaGEDu7/0 9lZta9qoLbxb5rnPHc2u6myuR6fLmHYSDinAII6dQqC0rA9gX1N7RHMf/tO0D6tmtfygeqmy+2u j/PlRGLWvA0CfqOfnxEsfNJRU8M2CW9wdaWfW0UTtQ/Z1sFwi6dgPvMD48Nfcwk1NnpanSm6O16 6iB3jWuVYHW9qjF9dz7MPk6CidKxLqWYP6OshvLitXmTBU4Mavfxixf+W1nXc2japb9rvh6A6vv PJc90aq3/Po9drW6AC2FG1WqGhdDnQhGWprpOO8pyN2PIKhy7JSwIdTBU/T8tIYQl/KDom2s+6G SEhRCblswzR6vtICQcbME3cLP163O1t2gvbDi9gUrAUO33m/XhblGdE07lk/hGXDFGSr5YbXwCa ebYZ3buSDl3yt1357uiI81NO9iB0Jw X-Received: by 2002:a05:600c:1389:b0:490:d3ef:fa4a with SMTP id 5b1f17b1804b1-49234105541mr113887085e9.14.1781785381717; Thu, 18 Jun 2026 05:23:01 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:01 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 06/30] libcamera: software_isp: gpu_pipeline_shader_pass: Add GpuPipelineShaderPassDemosiac Date: Thu, 18 Jun 2026 13:22:19 +0100 Message-ID: <20260618122245.946138-7-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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 --- .../gpu_pipeline_shader_pass_demosiac.cpp | 357 ++++++++++++++++++ .../gpu_pipeline_shader_pass_demosiac.h | 72 ++++ src/libcamera/software_isp/meson.build | 1 + 3 files changed, 430 insertions(+) create mode 100644 src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.cpp create mode 100644 src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.h diff --git a/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.cpp b/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.cpp new file mode 100644 index 000000000..02d9da2f0 --- /dev/null +++ b/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.cpp @@ -0,0 +1,357 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2026, Linaro Ltd + * + * GPU ISP Demosiac pass + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "libcamera/internal/bayer_format.h" +#include "libcamera/internal/framebuffer.h" +#include "libcamera/internal/ipa_manager.h" +#include "libcamera/internal/software_isp/debayer_params.h" + +#include "gpu_pipeline_shader_pass_demosiac.h" + +/** + * \file software_isp.cpp + * \brief Simple software ISP implementation + */ + +namespace libcamera { + +LOG_DEFINE_CATEGORY(GpuShaderDemosiac) + +int GpuIspShaderPassDemosiac::start() +{ + return 0; +} + +void GpuIspShaderPassDemosiac::stop() +{ +} + +int GpuIspShaderPassDemosiac::initShaders(PixelFormat inputFormat, PixelFormat outputFormat) +{ + std::vector shaderEnv; + unsigned int fragmentShaderDataLen = 0; + const unsigned char *fragmentShaderData = 0; + unsigned int vertexShaderDataLen = 0; + const unsigned char *vertexShaderData = 0; + GLenum err; + + /* Target gles 100 glsl requires "#version x" as first directive in shader */ + egl_.pushEnv(shaderEnv, "#version 100"); + + /* Specify GL_OES_EGL_image_external */ + egl_.pushEnv(shaderEnv, "#extension GL_OES_EGL_image_external: enable"); + + /* + * Tell shaders how to re-order output taking account of how the pixels + * are actually stored by EGL. + */ + switch (outputFormat) { + case formats::ARGB8888: + case formats::XRGB8888: + break; + case formats::ABGR8888: + case formats::XBGR8888: + egl_.pushEnv(shaderEnv, "#define SWAP_BLUE"); + break; + default: + LOG(GpuShaderDemosiac, Error) << "Unsupported output format"; + return -EINVAL; + } + + /* Pixel location parameters */ + glFormat_ = GL_LUMINANCE; + bytesPerPixel_ = 1; + shaderStridePixels_ = passInputCfg_.stride; + + switch (inputFormat) { + case libcamera::formats::SBGGR8: + case libcamera::formats::SBGGR10_CSI2P: + case libcamera::formats::SBGGR12_CSI2P: + firstRed_x_ = 1.0; + firstRed_y_ = 1.0; + break; + case libcamera::formats::SGBRG8: + case libcamera::formats::SGBRG10_CSI2P: + case libcamera::formats::SGBRG12_CSI2P: + firstRed_x_ = 0.0; + firstRed_y_ = 1.0; + break; + case libcamera::formats::SGRBG8: + case libcamera::formats::SGRBG10_CSI2P: + case libcamera::formats::SGRBG12_CSI2P: + firstRed_x_ = 1.0; + firstRed_y_ = 0.0; + break; + case libcamera::formats::SRGGB8: + case libcamera::formats::SRGGB10_CSI2P: + case libcamera::formats::SRGGB12_CSI2P: + firstRed_x_ = 0.0; + firstRed_y_ = 0.0; + break; + default: + LOG(GpuShaderDemosiac, Error) << "Unsupported input format"; + return -EINVAL; + }; + + /* Shader selection */ + switch (inputFormat) { + case libcamera::formats::SBGGR8: + case libcamera::formats::SGBRG8: + case libcamera::formats::SGRBG8: + case libcamera::formats::SRGGB8: + fragmentShaderData = bayer_unpacked_frag; + fragmentShaderDataLen = bayer_unpacked_frag_len; + vertexShaderData = bayer_unpacked_vert; + vertexShaderDataLen = bayer_unpacked_vert_len; + break; + case libcamera::formats::SBGGR10_CSI2P: + case libcamera::formats::SGBRG10_CSI2P: + case libcamera::formats::SGRBG10_CSI2P: + case libcamera::formats::SRGGB10_CSI2P: + egl_.pushEnv(shaderEnv, "#define RAW10P"); + if (BayerFormat::fromPixelFormat(inputFormat).packing == BayerFormat::Packing::None) { + fragmentShaderData = bayer_unpacked_frag; + fragmentShaderDataLen = bayer_unpacked_frag_len; + vertexShaderData = bayer_unpacked_vert; + vertexShaderDataLen = bayer_unpacked_vert_len; + glFormat_ = GL_RG; + bytesPerPixel_ = 2; + } else { + fragmentShaderData = bayer_1x_packed_frag; + fragmentShaderDataLen = bayer_1x_packed_frag_len; + vertexShaderData = identity_vert; + vertexShaderDataLen = identity_vert_len; + shaderStridePixels_ = passInputCfg_.size.width; + } + break; + case libcamera::formats::SBGGR12_CSI2P: + case libcamera::formats::SGBRG12_CSI2P: + case libcamera::formats::SGRBG12_CSI2P: + case libcamera::formats::SRGGB12_CSI2P: + egl_.pushEnv(shaderEnv, "#define RAW12P"); + if (BayerFormat::fromPixelFormat(inputFormat).packing == BayerFormat::Packing::None) { + fragmentShaderData = bayer_unpacked_frag; + fragmentShaderDataLen = bayer_unpacked_frag_len; + vertexShaderData = bayer_unpacked_vert; + vertexShaderDataLen = bayer_unpacked_vert_len; + glFormat_ = GL_RG; + bytesPerPixel_ = 2; + } else { + fragmentShaderData = bayer_1x_packed_frag; + fragmentShaderDataLen = bayer_1x_packed_frag_len; + vertexShaderData = identity_vert; + vertexShaderDataLen = identity_vert_len; + shaderStridePixels_ = passInputCfg_.size.width; + } + break; + }; + + /* TODO: move from here to the end of the method into a helper function in the base class + * this logic will be common to all pipeline instances + */ + if (egl_.compileVertexShader(vertexShaderId_, vertexShaderData, vertexShaderDataLen, shaderEnv)) { + LOG(GpuShaderDemosiac, Error) << "Compile vertex shader fail"; + return -ENODEV; + } + utils::scope_exit vShaderGuard([&] { glDeleteShader(vertexShaderId_); }); + + if (egl_.compileFragmentShader(fragmentShaderId_, fragmentShaderData, fragmentShaderDataLen, shaderEnv)) { + LOG(GpuShaderDemosiac, Error) << "Compile fragment shader fail"; + return -ENODEV; + } + utils::scope_exit fShaderGuard([&] { glDeleteShader(fragmentShaderId_); }); + + if (egl_.linkProgram(programId_, vertexShaderId_, fragmentShaderId_)) { + LOG(GpuShaderDemosiac, Error) << "Linking program fail"; + return -ENODEV; + } + + egl_.dumpShaderSource(vertexShaderId_); + egl_.dumpShaderSource(fragmentShaderId_); + + /* Ensure we set the programId_ */ + egl_.useProgram(programId_); + err = glGetError(); + if (err != GL_NO_ERROR) { + LOG(GpuShaderDemosiac, Error) << "Use program error " << err; + return -ENODEV; + } + + return getShaderVariableLocations(); +} + +int GpuIspShaderPassDemosiac::getShaderVariableLocations(void) +{ + attributeVertex_ = glGetAttribLocation(programId_, "vertexIn"); + attributeTexture_ = glGetAttribLocation(programId_, "textureIn"); + + textureUniformBayerDataIn_ = glGetUniformLocation(programId_, "tex_y"); + ccmUniformDataIn_ = glGetUniformLocation(programId_, "ccm"); + blackLevelUniformDataIn_ = glGetUniformLocation(programId_, "blacklevel"); + gammaUniformDataIn_ = glGetUniformLocation(programId_, "gamma"); + contrastExpUniformDataIn_ = glGetUniformLocation(programId_, "contrastExp"); + + textureUniformStep_ = glGetUniformLocation(programId_, "tex_step"); + textureUniformSize_ = glGetUniformLocation(programId_, "tex_size"); + textureUniformStrideFactor_ = glGetUniformLocation(programId_, "stride_factor"); + textureUniformBayerFirstRed_ = glGetUniformLocation(programId_, "tex_bayer_first_red"); + textureUniformProjMatrix_ = glGetUniformLocation(programId_, "proj_matrix"); + + LOG(GpuShaderDemosiac, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ + << " tex_y " << textureUniformBayerDataIn_ + << " ccm " << ccmUniformDataIn_ + << " blacklevel " << blackLevelUniformDataIn_ + << " gamma " << gammaUniformDataIn_ + << " contrastExp " << contrastExpUniformDataIn_ + << " tex_step " << textureUniformStep_ + << " tex_size " << textureUniformSize_ + << " stride_factor " << textureUniformStrideFactor_ + << " tex_bayer_first_red " << textureUniformBayerFirstRed_ + << " proj_matrix " << textureUniformProjMatrix_; + + /* TODO: trap errors */ + return 0; +} + +void GpuIspShaderPassDemosiac::setShaderVariableValues(const DebayerParams ¶ms, eGLImage &eglImageIn) +{ + /* + * 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)passInputCfg_.size.width, + (GLfloat)passInputCfg_.size.height }; + GLfloat Step[] = { static_cast(bytesPerPixel_) / (passInputCfg_.stride - 1), + 1.0f / (passInputCfg_.size.height - 1) }; + GLfloat Stride = (GLfloat)passInputCfg_.size.width / (shaderStridePixels_ / bytesPerPixel_); + /* + * Scale input to output size, keeping the aspect ratio and preferring + * cropping over black bars. + */ + GLfloat scale = std::max((GLfloat)passInputCfg_.window.width / passInputCfg_.size.width, + (GLfloat)passInputCfg_.window.height / passInputCfg_.size.height); + GLfloat trans = -(1.0f - scale); + GLfloat projMatrix[] = { + scale, 0, 0, 0, + 0, scale, 0, 0, + 0, 0, 1, 0, + trans, trans, 0, 1 + }; + /* Static const coordinates */ + static const GLfloat vcoordinates[4][2] = { + { -1.0f, -1.0f }, + { -1.0f, +1.0f }, + { +1.0f, +1.0f }, + { +1.0f, -1.0f }, + }; + static const GLfloat tcoordinates[4][2] = { + { 0.0f, 0.0f }, + { 0.0f, 1.0f }, + { 1.0f, 1.0f }, + { 1.0f, 0.0f }, + }; + + /* vertexIn - bayer_8.vert */ + glEnableVertexAttribArray(attributeVertex_); + glVertexAttribPointer(attributeVertex_, 2, GL_FLOAT, GL_TRUE, + 2 * sizeof(GLfloat), vcoordinates); + + /* textureIn - bayer_8.vert */ + glEnableVertexAttribArray(attributeTexture_); + glVertexAttribPointer(attributeTexture_, 2, GL_FLOAT, GL_TRUE, + 2 * sizeof(GLfloat), tcoordinates); + + /* + * Set the sampler2D to the respective texture unit for each texutre + * To simultaneously sample multiple textures we need to use multiple + * texture units + */ + glUniform1i(textureUniformBayerDataIn_, eglImageIn.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(GpuShaderDemosiac, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ + << " tex_y " << textureUniformBayerDataIn_ + << " tex_step " << textureUniformStep_ + << " tex_size " << textureUniformSize_ + << " stride_factor " << textureUniformStrideFactor_ + << " tex_bayer_first_red " << textureUniformBayerFirstRed_; + + LOG(GpuShaderDemosiac, Debug) << "textureUniformY_ = 0 " + << " firstRed.x " << firstRed[0] + << " firstRed.y " << firstRed[1] + << " textureUniformSize_.width " << imgSize[0] + << " textureUniformSize_.height " << imgSize[1] + << " textureUniformStep_.x " << Step[0] + << " textureUniformStep_.y " << Step[1] + << " textureUniformStrideFactor_ " << Stride + << " textureUniformProjMatrix_ " << textureUniformProjMatrix_; + + GLfloat ccm[9] = { + params.combinedMatrix[0][0], + params.combinedMatrix[0][1], + params.combinedMatrix[0][2], + params.combinedMatrix[1][0], + params.combinedMatrix[1][1], + params.combinedMatrix[1][2], + params.combinedMatrix[2][0], + params.combinedMatrix[2][1], + params.combinedMatrix[2][2], + }; + glUniformMatrix3fv(ccmUniformDataIn_, 1, GL_FALSE, ccm); + LOG(GpuShaderDemosiac, Debug) << " ccmUniformDataIn_ " << ccmUniformDataIn_ << " data " << params.combinedMatrix; + + /* + * 0 = Red, 1 = Green, 2 = Blue + */ + glUniform3f(blackLevelUniformDataIn_, params.blackLevel[0], params.blackLevel[1], params.blackLevel[2]); + LOG(GpuShaderDemosiac, Debug) << " blackLevelUniformDataIn_ " << blackLevelUniformDataIn_ << " data " << params.blackLevel; + + /* + * Gamma + */ + glUniform1f(gammaUniformDataIn_, params.gamma); + LOG(GpuShaderDemosiac, Debug) << " gammaUniformDataIn_ " << gammaUniformDataIn_ << " data " << params.gamma; + + /* + * Contrast + */ + glUniform1f(contrastExpUniformDataIn_, params.contrastExp); + LOG(GpuShaderDemosiac, Debug) << " contrastExpUniformDataIn_ " << contrastExpUniformDataIn_ << " data " << params.contrastExp; + + return; +} + +} diff --git a/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.h b/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.h new file mode 100644 index 000000000..11bb04c30 --- /dev/null +++ b/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2026, Linaro Ltd + * + * Authors: + * Bryan O'Donoghue + * + * GpuIspIspShaderPass base class + */ + +#pragma once + +#include + +#include +#include +#include + +#include +#include + +#include "libcamera/internal/egl.h" +#include "libcamera/internal/software_isp/debayer_params.h" + +#include "gpu_pipeline_shader_pass.h" + +namespace libcamera { + +class FrameBuffer; + +class GpuIspShaderPassDemosiac : public GpuIspShaderPass +{ +public: + GpuIspShaderPassDemosiac(eGL& egl) : GpuIspShaderPass(egl) {}; + + int start(); + void stop(); + + /* Things that every ISP pipeline pass will need to do */ + int initShaders(PixelFormat inputFormat, PixelFormat outputFormat); + int getShaderVariableLocations(void); + void setShaderVariableValues(const DebayerParams ¶ms, eGLImage &eglImageIn); + const char *name() const override { return "GpuIspShaderPassDemosiac"; } +private: + /* Shader parameters */ + float firstRed_x_; + float firstRed_y_; + GLint attributeVertex_; + GLint attributeTexture_; + GLint textureUniformStep_; + GLint textureUniformSize_; + GLint textureUniformStrideFactor_; + GLint textureUniformBayerFirstRed_; + GLint textureUniformProjMatrix_; + GLint textureUniformBayerDataIn_; + + uint32_t shaderStridePixels_; + + /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */ + GLint ccmUniformDataIn_; + + /* Black Level compensation */ + GLint blackLevelUniformDataIn_; + + /* Gamma */ + GLint gammaUniformDataIn_; + + /* Contrast */ + GLint contrastExpUniformDataIn_; +}; + +} /* namespace libcamera */ diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build index f8bce5203..3e7d21318 100644 --- a/src/libcamera/software_isp/meson.build +++ b/src/libcamera/software_isp/meson.build @@ -33,6 +33,7 @@ if mesa_works '../egl.cpp', 'software_isp_pipeline_gpu.cpp', 'gpu_pipeline_shader_pass.cpp', + 'gpu_pipeline_shader_pass_demosiac.cpp', ]) libcamera_deps += [ libegl, From patchwork Thu Jun 18 12:22:20 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26939 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 5F770C328C for ; Thu, 18 Jun 2026 12:23:14 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id BDD6363282; Thu, 18 Jun 2026 14:23:13 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="ihEb2XJ1"; 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 21716629A8 for ; Thu, 18 Jun 2026 14:23:03 +0200 (CEST) Received: by mail-wm1-x331.google.com with SMTP id 5b1f17b1804b1-490a76757e5so5337325e9.2 for ; Thu, 18 Jun 2026 05:23:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785383; x=1782390183; 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=VB0s4jG0bcGQ61Eh7lGd1mDOIM5NsnJDGJohBvZSWks=; b=ihEb2XJ1Wy75pBV8OLmM7xQKROslUCHR6mguTV4pgzfi+d6JOcfJBU0Y0D9T2NyAgE 2Ip+a0Saq5j1Xku2GnVaNKqlNVwpG03WCssNKTVESnYurRNBXo7pntJG97F8za1d6ow7 fOO9zj7wCWgmrmtje2qsXPwHkwVUB0Ak7Alp2fd2yMYmR0PTjw7ZesDQJuXV+XyqQp0/ iCWu7OXaURM5UfL5TrIv2zc3cq6d14+/pyh0B2NUOCyMPaFtx8ZQD8uPh9dx8/DCvfqg wo9x35wPRvFxADKHfqPw66BepKc90cRSU33NzTMtqWDOIZeIjYZWIklIqdXaMW9ILMlX jAJg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785383; x=1782390183; 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=VB0s4jG0bcGQ61Eh7lGd1mDOIM5NsnJDGJohBvZSWks=; b=oX1+okDic/oG2JnrOAdxHSLhQLoCgTybLIiwARaXngEFLAPdVFqCylCzhfWSi1lRKB bgjDllfK2MNjqdOnwqY/5kt9Jgge5VpuRH+1OeoVCRnv5WGjvK/1X+8IlNNFAZvS6wSl NBjch4muEsp3M2WKw1J2vc/R1xV7tpHtBelKE1C4pWCHedO8v6O3mb5IAPmFrynQc/IM ZRY1+L60U+jBnQ7+MDJP3bKMNknOFxWHhJQTo477iBymtl+vEGpCcXOf805pASuVbF0q eMqp0e+WLuqcjFcpBaUkfdEC7n7BRjepR0OTQ3MEBIUqrMWY04YyKTAp8xnqFfFJQv4m C3jw== X-Gm-Message-State: AOJu0YygPpTc+l4ggEZ7p98EuZSMBx89jXaHK/4LuJzObvyixkQDx6CT 8WTLVxPSTSSOZfR+/CptxYe5znZtlA2A/+sZZnxo3LED++3L5gXDSMPdxzz0hZJssNbcvZPdC/b 3KhTumsU= X-Gm-Gg: AfdE7ckvayd1tRoDXyOFi2FBNQRoUVBY/KLX+N0JRcGf827/83vOArm4BPMBFvAcXFv TP5q9le2A+eQ0nUNAZP1bFdIuXWlSSZThNkx9YYyl44S6xKICErkJlfDkuAT6yL2TLm/Bv8WSH6 HeLnB28rOlAFRvf9rAmcRo68FxHQBOAWDWnY/ObQrvLZyRhlmIyxwaEj95XjNgLUywLRnFOPLeh vYcShumhkBXQEcHh79V5lOKe4UM8HjbIkpt1nu5KXfwibLOU2NROzl6llqH/ZT6HrQmowlecASp tDSX3U3EyIQ0JdjbT6gEIZMpsPV8f7LlsB9WVxuocYu1Z2znHFmIqm7N26/Z5qMvRUfLTRUyOhZ 9wjiI+/RHflgQOfyHOqrpqBSw+AlzRUDeXVQqmtqA7SyDY3oGPxjtMg7gxEnUw689zKMlDkw5Kx 0oYrebTdVHOiIdKQM7/6OembkSV7B5 X-Received: by 2002:a05:600c:5394:b0:490:aef9:aa3b with SMTP id 5b1f17b1804b1-4923822b876mr56053925e9.32.1781785382457; Thu, 18 Jun 2026 05:23:02 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:02 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 07/30] libcamera: software_isp: gpu: Switch to using GpuIspShaderPassDemosiac Date: Thu, 18 Jun 2026 13:22:20 +0100 Message-ID: <20260618122245.946138-8-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Switch to using GpuIspShaderPassDemosiac as the first instance of our multi-pass GPUISP implementation. Subsequent patches will move elements of this leviathan into discreet elements with an objective of eliminating register spill, separation of concerns and de-spaghettification. Code red patches are always best. Signed-off-by: Bryan O'Donoghue --- src/libcamera/egl.cpp | 6 +- .../software_isp_pipeline_gpu.cpp | 325 +----------------- .../software_isp/software_isp_pipeline_gpu.h | 41 +-- 3 files changed, 20 insertions(+), 352 deletions(-) diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index 3ea694d7c..4da335a53 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -153,7 +153,6 @@ int eGL::attachTextureToFBO(eGLImage &eglImage) int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) { EGLint drm_format; - int ret; ASSERT(tid_ == Thread::currentId()); @@ -213,10 +212,7 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) 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) - ret = attachTextureToFBO(eglImage); - - return ret; + return 0; } /** diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp index 6f988d672..6f329cf40 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp @@ -41,7 +41,7 @@ namespace libcamera { * \param[in] cm The camera manager */ SoftwareIspPipelineGpu::SoftwareIspPipelineGpu(std::unique_ptr stats, const CameraManager &cm) - : SoftwareIspPipeline(cm), stats_(std::move(stats)) + : SoftwareIspPipeline(cm), stats_(std::move(stats)), gpuIspShaderPassDemosiac_(egl_) { } @@ -109,186 +109,13 @@ int SoftwareIspPipelineGpu::getOutputConfig(PixelFormat outputFormat, DebayerOut return -EINVAL; } -int SoftwareIspPipelineGpu::getShaderVariableLocations(void) -{ - attributeVertex_ = glGetAttribLocation(programId_, "vertexIn"); - attributeTexture_ = glGetAttribLocation(programId_, "textureIn"); - - textureUniformBayerDataIn_ = glGetUniformLocation(programId_, "tex_y"); - ccmUniformDataIn_ = glGetUniformLocation(programId_, "ccm"); - blackLevelUniformDataIn_ = glGetUniformLocation(programId_, "blacklevel"); - gammaUniformDataIn_ = glGetUniformLocation(programId_, "gamma"); - contrastExpUniformDataIn_ = glGetUniformLocation(programId_, "contrastExp"); - - textureUniformStep_ = glGetUniformLocation(programId_, "tex_step"); - textureUniformSize_ = glGetUniformLocation(programId_, "tex_size"); - textureUniformStrideFactor_ = glGetUniformLocation(programId_, "stride_factor"); - textureUniformBayerFirstRed_ = glGetUniformLocation(programId_, "tex_bayer_first_red"); - textureUniformProjMatrix_ = glGetUniformLocation(programId_, "proj_matrix"); - - LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ - << " tex_y " << textureUniformBayerDataIn_ - << " ccm " << ccmUniformDataIn_ - << " blacklevel " << blackLevelUniformDataIn_ - << " gamma " << gammaUniformDataIn_ - << " contrastExp " << contrastExpUniformDataIn_ - << " tex_step " << textureUniformStep_ - << " tex_size " << textureUniformSize_ - << " stride_factor " << textureUniformStrideFactor_ - << " tex_bayer_first_red " << textureUniformBayerFirstRed_ - << " proj_matrix " << textureUniformProjMatrix_; - return 0; -} - int SoftwareIspPipelineGpu::initBayerShaders(PixelFormat inputFormat, PixelFormat outputFormat) { - std::vector shaderEnv; - unsigned int fragmentShaderDataLen = 0; - const unsigned char *fragmentShaderData = 0; - unsigned int vertexShaderDataLen = 0; - const unsigned char *vertexShaderData = 0; - GLenum err; - - /* Target gles 100 glsl requires "#version x" as first directive in shader */ - egl_.pushEnv(shaderEnv, "#version 100"); - - /* Specify GL_OES_EGL_image_external */ - egl_.pushEnv(shaderEnv, "#extension GL_OES_EGL_image_external: enable"); - - /* - * Tell shaders how to re-order output taking account of how the pixels - * are actually stored by EGL. - */ - switch (outputFormat) { - case formats::ARGB8888: - case formats::XRGB8888: - break; - case formats::ABGR8888: - case formats::XBGR8888: - egl_.pushEnv(shaderEnv, "#define SWAP_BLUE"); - break; - default: - LOG(Debayer, Error) << "Unsupported output format"; - return -EINVAL; - } - - /* Pixel location parameters */ - glFormat_ = GL_LUMINANCE; - bytesPerPixel_ = 1; - shaderStridePixels_ = inputConfig_.stride; - - switch (inputFormat) { - case libcamera::formats::SBGGR8: - case libcamera::formats::SBGGR10_CSI2P: - case libcamera::formats::SBGGR12_CSI2P: - firstRed_x_ = 1.0; - firstRed_y_ = 1.0; - break; - case libcamera::formats::SGBRG8: - case libcamera::formats::SGBRG10_CSI2P: - case libcamera::formats::SGBRG12_CSI2P: - firstRed_x_ = 0.0; - firstRed_y_ = 1.0; - break; - case libcamera::formats::SGRBG8: - case libcamera::formats::SGRBG10_CSI2P: - case libcamera::formats::SGRBG12_CSI2P: - firstRed_x_ = 1.0; - firstRed_y_ = 0.0; - break; - case libcamera::formats::SRGGB8: - case libcamera::formats::SRGGB10_CSI2P: - case libcamera::formats::SRGGB12_CSI2P: - firstRed_x_ = 0.0; - firstRed_y_ = 0.0; - break; - default: - LOG(Debayer, Error) << "Unsupported input format"; - return -EINVAL; - }; - - /* Shader selection */ - switch (inputFormat) { - case libcamera::formats::SBGGR8: - case libcamera::formats::SGBRG8: - case libcamera::formats::SGRBG8: - case libcamera::formats::SRGGB8: - fragmentShaderData = bayer_unpacked_frag; - fragmentShaderDataLen = bayer_unpacked_frag_len; - vertexShaderData = bayer_unpacked_vert; - vertexShaderDataLen = bayer_unpacked_vert_len; - break; - case libcamera::formats::SBGGR10_CSI2P: - case libcamera::formats::SGBRG10_CSI2P: - case libcamera::formats::SGRBG10_CSI2P: - case libcamera::formats::SRGGB10_CSI2P: - egl_.pushEnv(shaderEnv, "#define RAW10P"); - if (BayerFormat::fromPixelFormat(inputFormat).packing == BayerFormat::Packing::None) { - fragmentShaderData = bayer_unpacked_frag; - fragmentShaderDataLen = bayer_unpacked_frag_len; - vertexShaderData = bayer_unpacked_vert; - vertexShaderDataLen = bayer_unpacked_vert_len; - glFormat_ = GL_RG; - bytesPerPixel_ = 2; - } else { - fragmentShaderData = bayer_1x_packed_frag; - fragmentShaderDataLen = bayer_1x_packed_frag_len; - vertexShaderData = identity_vert; - vertexShaderDataLen = identity_vert_len; - shaderStridePixels_ = width_; - } - break; - case libcamera::formats::SBGGR12_CSI2P: - case libcamera::formats::SGBRG12_CSI2P: - case libcamera::formats::SGRBG12_CSI2P: - case libcamera::formats::SRGGB12_CSI2P: - egl_.pushEnv(shaderEnv, "#define RAW12P"); - if (BayerFormat::fromPixelFormat(inputFormat).packing == BayerFormat::Packing::None) { - fragmentShaderData = bayer_unpacked_frag; - fragmentShaderDataLen = bayer_unpacked_frag_len; - vertexShaderData = bayer_unpacked_vert; - vertexShaderDataLen = bayer_unpacked_vert_len; - glFormat_ = GL_RG; - bytesPerPixel_ = 2; - } else { - fragmentShaderData = bayer_1x_packed_frag; - fragmentShaderDataLen = bayer_1x_packed_frag_len; - vertexShaderData = identity_vert; - vertexShaderDataLen = identity_vert_len; - shaderStridePixels_ = width_; - } - break; - }; - - if (egl_.compileVertexShader(vertexShaderId_, vertexShaderData, vertexShaderDataLen, shaderEnv)) { - LOG(Debayer, Error) << "Compile vertex shader fail"; - return -ENODEV; - } - utils::scope_exit vShaderGuard([&] { glDeleteShader(vertexShaderId_); }); - - if (egl_.compileFragmentShader(fragmentShaderId_, fragmentShaderData, fragmentShaderDataLen, shaderEnv)) { - LOG(Debayer, Error) << "Compile fragment shader fail"; - return -ENODEV; - } - utils::scope_exit fShaderGuard([&] { glDeleteShader(fragmentShaderId_); }); + int ret; - if (egl_.linkProgram(programId_, vertexShaderId_, fragmentShaderId_)) { - LOG(Debayer, Error) << "Linking program fail"; - return -ENODEV; - } - - egl_.dumpShaderSource(vertexShaderId_); - egl_.dumpShaderSource(fragmentShaderId_); - - /* Ensure we set the programId_ */ - egl_.useProgram(programId_); - err = glGetError(); - if (err != GL_NO_ERROR) { - LOG(Debayer, Error) << "Use program error " << err; - return -ENODEV; - } + ret = gpuIspShaderPassDemosiac_.initShaders(inputFormat, outputFormat); - return getShaderVariableLocations(); + return ret; } int SoftwareIspPipelineGpu::configure(const StreamConfiguration &inputCfg, @@ -351,6 +178,12 @@ int SoftwareIspPipelineGpu::configure(const StreamConfiguration &inputCfg, */ stats_->setWindow(Rectangle(window_.size())); + /* Configure for one pass */ + PassConfig rawSensorIn = { inputCfg.size, inputConfig_.stride, inputPixelFormat_, window_ }; + PassConfig rgbaOut = { outputCfg.size, outputConfig_.stride, outputPixelFormat_, Rectangle(outputSize_) }; + + gpuIspShaderPassDemosiac_.configure(rawSensorIn, rgbaOut); + return 0; } @@ -388,132 +221,10 @@ SoftwareIspPipelineGpu::strideAndFrameSize(const PixelFormat &outputFormat, cons return std::make_tuple(stride, stride * size.height); } -void SoftwareIspPipelineGpu::setShaderVariableValues(const DebayerParams ¶ms) -{ - /* - * Raw Bayer 8-bit, and packed raw Bayer 10-bit/12-bit formats - * are stored in a GL_LUMINANCE texture. The texture width is - * equal to the stride. - */ - GLfloat firstRed[] = { firstRed_x_, firstRed_y_ }; - GLfloat imgSize[] = { (GLfloat)width_, - (GLfloat)height_ }; - GLfloat Step[] = { static_cast(bytesPerPixel_) / (inputConfig_.stride - 1), - 1.0f / (height_ - 1) }; - GLfloat Stride = (GLfloat)width_ / (shaderStridePixels_ / bytesPerPixel_); - /* - * Scale input to output size, keeping the aspect ratio and preferring - * cropping over black bars. - */ - GLfloat scale = std::max((GLfloat)window_.width / width_, - (GLfloat)window_.height / height_); - GLfloat trans = -(1.0f - scale); - GLfloat projMatrix[] = { - scale, 0, 0, 0, - 0, scale, 0, 0, - 0, 0, 1, 0, - trans, trans, 0, 1 - }; - /* Static const coordinates */ - static const GLfloat vcoordinates[4][2] = { - { -1.0f, -1.0f }, - { -1.0f, +1.0f }, - { +1.0f, +1.0f }, - { +1.0f, -1.0f }, - }; - static const GLfloat tcoordinates[4][2] = { - { 0.0f, 0.0f }, - { 0.0f, 1.0f }, - { 1.0f, 1.0f }, - { 1.0f, 0.0f }, - }; - - /* vertexIn - bayer_8.vert */ - glEnableVertexAttribArray(attributeVertex_); - glVertexAttribPointer(attributeVertex_, 2, GL_FLOAT, GL_TRUE, - 2 * sizeof(GLfloat), vcoordinates); - - /* textureIn - bayer_8.vert */ - glEnableVertexAttribArray(attributeTexture_); - glVertexAttribPointer(attributeTexture_, 2, GL_FLOAT, GL_TRUE, - 2 * sizeof(GLfloat), tcoordinates); - - /* - * Set the sampler2D to the respective texture unit for each texutre - * To simultaneously sample multiple textures we need to use multiple - * texture units - */ - glUniform1i(textureUniformBayerDataIn_, eglImageBayerIn_->texture_unit_uniform_id_); - - /* - * These values are: - * firstRed = tex_bayer_first_red - bayer_8.vert - * imgSize = tex_size - bayer_8.vert - * step = tex_step - bayer_8.vert - * Stride = stride_factor identity.vert - * textureUniformProjMatri = No scaling - */ - glUniform2fv(textureUniformBayerFirstRed_, 1, firstRed); - glUniform2fv(textureUniformSize_, 1, imgSize); - glUniform2fv(textureUniformStep_, 1, Step); - glUniform1f(textureUniformStrideFactor_, Stride); - glUniformMatrix4fv(textureUniformProjMatrix_, 1, GL_FALSE, projMatrix); - - LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ - << " tex_y " << textureUniformBayerDataIn_ - << " tex_step " << textureUniformStep_ - << " tex_size " << textureUniformSize_ - << " stride_factor " << textureUniformStrideFactor_ - << " tex_bayer_first_red " << textureUniformBayerFirstRed_; - - LOG(Debayer, Debug) << "textureUniformY_ = 0 " - << " firstRed.x " << firstRed[0] - << " firstRed.y " << firstRed[1] - << " textureUniformSize_.width " << imgSize[0] - << " textureUniformSize_.height " << imgSize[1] - << " textureUniformStep_.x " << Step[0] - << " textureUniformStep_.y " << Step[1] - << " textureUniformStrideFactor_ " << Stride - << " textureUniformProjMatrix_ " << textureUniformProjMatrix_; - - GLfloat ccm[9] = { - params.combinedMatrix[0][0], - params.combinedMatrix[0][1], - params.combinedMatrix[0][2], - params.combinedMatrix[1][0], - params.combinedMatrix[1][1], - params.combinedMatrix[1][2], - params.combinedMatrix[2][0], - params.combinedMatrix[2][1], - params.combinedMatrix[2][2], - }; - glUniformMatrix3fv(ccmUniformDataIn_, 1, GL_FALSE, ccm); - LOG(Debayer, Debug) << " ccmUniformDataIn_ " << ccmUniformDataIn_ << " data " << params.combinedMatrix; - - /* - * 0 = Red, 1 = Green, 2 = Blue - */ - glUniform3f(blackLevelUniformDataIn_, params.blackLevel[0], params.blackLevel[1], params.blackLevel[2]); - LOG(Debayer, Debug) << " blackLevelUniformDataIn_ " << blackLevelUniformDataIn_ << " data " << params.blackLevel; - - /* - * Gamma - */ - glUniform1f(gammaUniformDataIn_, params.gamma); - LOG(Debayer, Debug) << " gammaUniformDataIn_ " << gammaUniformDataIn_ << " data " << params.gamma; - - /* - * Contrast - */ - glUniform1f(contrastExpUniformDataIn_, params.contrastExp); - LOG(Debayer, Debug) << " contrastExpUniformDataIn_ " << contrastExpUniformDataIn_ << " data " << params.contrastExp; - - return; -} - int SoftwareIspPipelineGpu::processGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms, std::optional *inMapped, std::optional *inDmaSyncer) { bool dmabuf_import_succeeded = false; + int pipelineResult = 0; /* eGL context switch */ egl_.makeCurrent(); @@ -540,20 +251,17 @@ int SoftwareIspPipelineGpu::processGPU(FrameBuffer *input, FrameBuffer *output, /* Generate the output render framebuffer as render to texture */ egl_.createOutputDMABufTexture2D(*eglImageRGBAOut_, output->planes()[0].fd.get()); - setShaderVariableValues(params); - glViewport(0, 0, width_, height_); - glClear(GL_COLOR_BUFFER_BIT); - glDrawArrays(GL_TRIANGLE_FAN, 0, DEBAYER_OPENGL_COORDS); + pipelineResult = gpuIspShaderPassDemosiac_.process(*eglImageBayerIn_, *eglImageRGBAOut_, width_, height_, params); GLenum err = glGetError(); if (err != GL_NO_ERROR) { LOG(eGL, Error) << "Drawing scene fail " << err; - return -ENODEV; + pipelineResult = -ENODEV; } else { egl_.flushOutput(); } - return 0; + return pipelineResult; } void SoftwareIspPipelineGpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms) @@ -623,7 +331,7 @@ int SoftwareIspPipelineGpu::start() return -EINVAL; /* Raw bayer input as texture */ - eglImageBayerIn_ = std::make_unique(glFormat_, inputConfig_.stride / bytesPerPixel_, height_, inputConfig_.stride, GL_TEXTURE0, 0); + eglImageBayerIn_ = std::make_unique(gpuIspShaderPassDemosiac_.glFormat_, inputConfig_.stride / gpuIspShaderPassDemosiac_.getBytesPerPixel(), height_, inputConfig_.stride, GL_TEXTURE0, 0); /* Texture we will render to */ eglImageRGBAOut_ = std::make_unique(GL_RGBA, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE1, 1); @@ -636,8 +344,7 @@ void SoftwareIspPipelineGpu::stop() eglImageRGBAOut_.reset(); eglImageBayerIn_.reset(); - if (programId_) - glDeleteProgram(programId_); + gpuIspShaderPassDemosiac_.stop(); } SizeRange SoftwareIspPipelineGpu::sizes(PixelFormat inputFormat, const Size &inputSize) diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.h b/src/libcamera/software_isp/software_isp_pipeline_gpu.h index f0515d889..6a9df2f04 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.h +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.h @@ -23,16 +23,12 @@ #include "libcamera/internal/software_isp/benchmark.h" #include "libcamera/internal/software_isp/swstats_cpu.h" -#include -#include -#include - #include "software_isp_pipeline.h" +#include "gpu_pipeline_shader_pass_demosiac.h" namespace libcamera { #define DEBAYER_EGL_MIN_SIMPLE_RGB_GAIN_TEXTURE_UNITS 4 -#define DEBAYER_OPENGL_COORDS 4 class CameraManager; @@ -68,48 +64,17 @@ private: int processGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms, std::optional *mappedInputBuffer, std::optional *inputBufferDmaSyncer); void configureTexture(GLuint &texture); - /* Shader program identifiers */ - GLuint vertexShaderId_ = 0; - GLuint fragmentShaderId_ = 0; - GLuint programId_ = 0; - /* Pointer to object representing input texture */ std::unique_ptr eglImageBayerIn_; std::unique_ptr eglImageRGBAOut_; - /* Shader parameters */ - float firstRed_x_; - float firstRed_y_; - GLint attributeVertex_; - GLint attributeTexture_; - GLint textureUniformStep_; - GLint textureUniformSize_; - GLint textureUniformStrideFactor_; - GLint textureUniformBayerFirstRed_; - GLint textureUniformProjMatrix_; - - GLint textureUniformBayerDataIn_; - - /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */ - GLint ccmUniformDataIn_; - - /* Black Level compensation */ - GLint blackLevelUniformDataIn_; - - /* Gamma */ - GLint gammaUniformDataIn_; - - /* Contrast */ - GLint contrastExpUniformDataIn_; - Rectangle window_; std::unique_ptr stats_; eGL egl_; uint32_t width_; uint32_t height_; - GLint glFormat_; - unsigned int bytesPerPixel_; - uint32_t shaderStridePixels_; + + GpuIspShaderPassDemosiac gpuIspShaderPassDemosiac_; }; } /* namespace libcamera */ From patchwork Thu Jun 18 12:22:21 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26941 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 224A5C3305 for ; Thu, 18 Jun 2026 12:23:18 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F1EA362C79; Thu, 18 Jun 2026 14:23:16 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="J5cEd2K9"; dkim-atps=neutral Received: from mail-wm1-x32e.google.com (mail-wm1-x32e.google.com [IPv6:2a00:1450:4864:20::32e]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C05E9629B6 for ; Thu, 18 Jun 2026 14:23:03 +0200 (CEST) Received: by mail-wm1-x32e.google.com with SMTP id 5b1f17b1804b1-490acbb0f89so5106725e9.0 for ; Thu, 18 Jun 2026 05:23:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785383; x=1782390183; 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=d21tRCpqwbmy/o8WfjExXx9hFYuN0xrdYpsc/2pnRDI=; b=J5cEd2K9DDZiLHGq1jmKnDpFtW/hD6/hoFVkOhE1bHeoFmyUQFiQ8PB4BBv80zAN1Q bHDpiSybu1+lqGKpctKrkFC0iCh6KMdTsA4KlRaQ4nedZFK+UpNCn5r9iUt9G/rWe6cS Sx4mSLAnUuA1m53pKVMPA+lTi0QWw1PBaRgZHPbsujg4hnvnSJt+WS34FGlFMvR3z3w7 U1uFjmHVEiDU0CE+ACzIXUbP1ziOsI1PZxAXZNuiBoNTaOEaM7hLPyquTl/6ALlmiQls CUGc3IboRlGFAknDtwsCgIvmsn9ZDPxYTUfj2Zd2j6nwsK4V+x49ChQp0a7Oqipd6RDI sKKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785383; x=1782390183; 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=d21tRCpqwbmy/o8WfjExXx9hFYuN0xrdYpsc/2pnRDI=; b=aDi9n8fVIvbQ9TY20S61cWeLv0axC60yn9MGHJBbfwcy+C6q3sqBxxqJNj8JI6D7UE 3Wx9DHIROHEka2UcS4MGTAZbPevYE9ScOY4ZP9GkogwVrFgIlhh7DHWa3yHI2esjnesK ITYlsNZIF94k2so7BELP4zI5Z6ld+VMGLmcCszJIGdvei/TD1hDzWxBj9c6Lma/JdPAJ 7qIwstI4G/22BmnuS5D9muCQd6WC7PXnpPsM/oRsAOripjVLMVBSuTQmvYjRK9mX7B6K d4wlOpnJIueDmVCsB8bip07+w2psotkZZUmpQOiesmRNAz+Xg6IHzV4jf+LDZDj7fG0r XOMA== X-Gm-Message-State: AOJu0YyMgQtnRHKR6YyONAzODlx0HKeqF5zBZA4CN6YRlgMm6KhY6Hn3 eAqemO+mXzUulvl2SybrCCzj/bI/bdn2qoD3HP8Kexs9hR2zcXS569pgkKeMGjrb0NXdRzYSTh/ LkeuwE7o= X-Gm-Gg: AfdE7clMa0L3STGhWZYmmUAInteahkZgHXsRRkDVfW77AnyRyec/ShvQHFiH3JYJuJg 6ZpkHwwF2eg/HCEI32maT7giW3FKDme3s1p0HsGqETVCBZ8sWkIOTRcNsLrLqdYrPRHTU0IPp3O 0PKmtdv6tLPJiYttGHyt+tAq+HWs6n/eG07xvn4RdVDaKPeLnwypKt5Stjxh/Mm2V0p9iNOBX/F hzbt87InsBpkg0TBrNPHdu8j26Luw4LiU5cFN9uUULWXXoMX/qgkYU3uk6mwfucBsOkDE2e/ErR buATtvjZl4CyqQcaTRGVOhn6ENs3wDoHbtAzvnw+inThzeMCGxUKpASI8R9wJmWG7pX/GjGmuKz AB8lIpYidvqqCTGcVXug5Be7Nz/cY+te0gwCXQrUeiZeoQ6pl+HYCHKHzVeZMjBK9V7XzlOpKRK hh9sn6JedVZAFKlGdENabr8+Ub7lt/ X-Received: by 2002:a05:600c:350f:b0:490:b724:5085 with SMTP id 5b1f17b1804b1-4923822c4d2mr58834695e9.33.1781785383203; Thu, 18 Jun 2026 05:23:03 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:02 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 08/30] libcamera: software_isp: gpu: Drop unused method definitions Date: Thu, 18 Jun 2026 13:22:21 +0100 Message-ID: <20260618122245.946138-9-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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/libcamera/software_isp/software_isp_pipeline_gpu.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.h b/src/libcamera/software_isp/software_isp_pipeline_gpu.h index 6a9df2f04..6bd8adc8f 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.h +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.h @@ -62,7 +62,6 @@ private: int getShaderVariableLocations(); void setShaderVariableValues(const DebayerParams ¶ms); int processGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms, std::optional *mappedInputBuffer, std::optional *inputBufferDmaSyncer); - void configureTexture(GLuint &texture); /* Pointer to object representing input texture */ std::unique_ptr eglImageBayerIn_; From patchwork Thu Jun 18 12:22:22 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26942 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 69F0EC3301 for ; Thu, 18 Jun 2026 12:23:19 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 509BE656BD; Thu, 18 Jun 2026 14:23:18 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="xvaTIubi"; dkim-atps=neutral Received: from mail-wm1-x32e.google.com (mail-wm1-x32e.google.com [IPv6:2a00:1450:4864:20::32e]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 94A7362C6E for ; Thu, 18 Jun 2026 14:23:04 +0200 (CEST) Received: by mail-wm1-x32e.google.com with SMTP id 5b1f17b1804b1-490b8ac62baso19678345e9.0 for ; Thu, 18 Jun 2026 05:23:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785384; x=1782390184; 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=Im+zzqwJ00458QMQzuv8XikugjegTVaGOsoHOKzuyZo=; b=xvaTIubilviPD2qvOjRw10ApZdNOGJCcjzAoUW2Mj+/1LEAyPG8mDdww6Rrzy6wkWZ HhzbjVdXJBSj1DD9+CWYqN/Sl//CSB7WHuvMJ++AlQxqctOnjX7PX73Pk360i6YhNfb5 xr7/0qQeIAdUU3tG2Kb6ag/D3ZFju/ccyoiTZOe27YDJUifA4QgmskN+dksWcavCZxEZ KeMd4xa2i6yaVOUtfls9TwaOPYcLxSwbwvS5ZaD4PdnWNuQFkQmWXALffMqP4FbE5HCS IkUJwVrfGInKQCmbpYJS0qXcnCyKDCdD+GzcWPzpsTQ+Q5xaOpTGtnipopFp2bKS9ljE 7FnQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785384; x=1782390184; 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=Im+zzqwJ00458QMQzuv8XikugjegTVaGOsoHOKzuyZo=; b=Fy8luTS5rnxw9WekCnNWky/1By7ThBwm6dyZMD+EXAqa5LTI5w7mKe7IZbtPnJQ8Hc Lf9lntdGyNM8UxsJPc+aoBU9Cn3ScDqSr7ycGChwSQzYriJ2HNiVQiKIxuTNsQaC4Rnf McSJ0rtxrhTwxAJfXJ/Cb3BY6015pQY8jyHNkRuVRHwaGAv/VD5sJTVeR+z7bTsCSbT5 VTmCs/FfcWlLtrci2XrPXIhlUoFi1c5bzWxKuWxUUMvdssHcK4Uua/D0Ep+asrsFx+2S ygmeoUcUsqcfrEZHjxYYfFvjGmBXrR+id7nYKrLxlT5aFJBnvlK0y481xOkZ4giKUBml PYlQ== X-Gm-Message-State: AOJu0YxcwmemWrtajJUUCaz+sZ18rGMt8NugaV3UlW6s9JrILkxARor8 Jdb/qXn9IGX/lmbiSfZeiWPe1F/m09cfvCK3ue6MidJNIiM/APZocDjC9dtiaOPL97sm4w7+4Bo wQvgPhXk= X-Gm-Gg: AfdE7clNrP1tI6tYfz34GImUtBF+xbqMpFT0dw0tTx76CY6thPiOAKSm/rMF+QxOwdf aTVX4DU9KkO9s6eoU3K+A4WTRLsf5SOFb1d5FfisbIuulteivR8lKvO/w1bsaZuD1QrJWJoBOSY lGiEosfycLO0h5wRqftvUkklI3/044XsWcsdI24oti1DsEBGBcc1NmLi2r0x/Sro4GxQg19bBOY JxeUCo4BYVSd8v+7euPCNeDiJyPP5paXpS5b0mWw/t+pSkgYp818Bcqz12Odh2UcUcu4ZIhVm66 t1GkBAVy+K/LxhWuYj3hUgnHgBDidDrxVLgkcNvu/n6LOSFGdAGj0VWL6B5LKm0h3oc0Hcq0+8T bM+v8p82UU91J1lLmW8MotDpTrDNv7g4TRs+l2z+jtKktbR2jj/Hn7YTdX6SWtyOWh2JGgFqmoJ HXhMtChBANdhzryrVhNHThTj7dysnm X-Received: by 2002:a05:600c:4ec6:b0:490:3cf0:8d81 with SMTP id 5b1f17b1804b1-492381864b5mr51320325e9.13.1781785383996; Thu, 18 Jun 2026 05:23:03 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:03 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 09/30] libcamera: software_isp: gpu: Make Rectangle window_ a local variable in configure() Date: Thu, 18 Jun 2026 13:22:22 +0100 Message-ID: <20260618122245.946138-10-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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" Class member window_ is only used in one method now so make it a local to that method instead. Signed-off-by: Bryan O'Donoghue --- .../software_isp/software_isp_pipeline_gpu.cpp | 16 +++++++++------- .../software_isp/software_isp_pipeline_gpu.h | 1 - 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp index 6f329cf40..7de77319d 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp @@ -122,6 +122,8 @@ int SoftwareIspPipelineGpu::configure(const StreamConfiguration &inputCfg, const std::vector> &outputCfgs, [[maybe_unused]] bool ccmEnabled) { + Rectangle window; + if (getInputConfig(inputCfg.pixelFormat, inputConfig_) != 0) return -EINVAL; @@ -165,21 +167,21 @@ int SoftwareIspPipelineGpu::configure(const StreamConfiguration &inputCfg, outputPixelFormat_ = outputCfg.pixelFormat; outputSize_ = outputCfg.size; - window_.x = ((inputCfg.size.width - outputCfg.size.width) / 2) & + window.x = ((inputCfg.size.width - outputCfg.size.width) / 2) & ~(inputConfig_.patternSize.width - 1); - window_.y = ((inputCfg.size.height - outputCfg.size.height) / 2) & + window.y = ((inputCfg.size.height - outputCfg.size.height) / 2) & ~(inputConfig_.patternSize.height - 1); - window_.width = outputCfg.size.width; - window_.height = outputCfg.size.height; + window.width = outputCfg.size.width; + window.height = outputCfg.size.height; /* - * Don't pass x,y from window_ since process() already adjusts for it. + * 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())); + stats_->setWindow(Rectangle(window.size())); /* Configure for one pass */ - PassConfig rawSensorIn = { inputCfg.size, inputConfig_.stride, inputPixelFormat_, window_ }; + PassConfig rawSensorIn = { inputCfg.size, inputConfig_.stride, inputPixelFormat_, window }; PassConfig rgbaOut = { outputCfg.size, outputConfig_.stride, outputPixelFormat_, Rectangle(outputSize_) }; gpuIspShaderPassDemosiac_.configure(rawSensorIn, rgbaOut); diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.h b/src/libcamera/software_isp/software_isp_pipeline_gpu.h index 6bd8adc8f..1b77bc71d 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.h +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.h @@ -67,7 +67,6 @@ private: std::unique_ptr eglImageBayerIn_; std::unique_ptr eglImageRGBAOut_; - Rectangle window_; std::unique_ptr stats_; eGL egl_; uint32_t width_; From patchwork Thu Jun 18 12:22:23 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26943 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 BD6BAC3306 for ; Thu, 18 Jun 2026 12:23:20 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C65E462FE1; Thu, 18 Jun 2026 14:23:19 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="SmELQWAg"; 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 5CD1C62C6A for ; Thu, 18 Jun 2026 14:23:05 +0200 (CEST) Received: by mail-wm1-x334.google.com with SMTP id 5b1f17b1804b1-490b211ee6aso5484755e9.3 for ; Thu, 18 Jun 2026 05:23:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785385; x=1782390185; 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=EnOXXDwDQkS4RkeO0LXcAjFKNLZWffOHcAAqtwXY+iY=; b=SmELQWAgY+xgxDCfYU60R9K/ija50q280AF3H6LlEehyiezpCGBdD2m6bbsUDFrtw1 Xqk2a+C8lNb3TGaDDxj0/YqxgEEsqyBQM8FNVzT8hb9n0rT09Pxot4aSFqAYt4YvzxHB 7GRy1JnEGuXpBWSYsHhmWEOKmvT0O2mOqGpzwmNylL0HS4ISt4YxiYLBlQtaqj7dvmej gHy2iGRbm1bzjOrruEaF6mSiw0NwUjDYhhq766o2T2n6XNvuKjR9Vh33qRi2VBfkPKPD WvxssLleNRCONlaAzbZgqA0Nvde9Fu8wyNHW7fUlRSgOzL2AZVAG7VXwPZYsFDIoPN+u K/Jw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785385; x=1782390185; 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=EnOXXDwDQkS4RkeO0LXcAjFKNLZWffOHcAAqtwXY+iY=; b=jsFYvCiG5Tm6u7LfgRWL2XBNZ2QrG0dAGvhU4ZmqauAIasfT/9J2pMhLtY7mRd/qlV 1qvB5ZzM7jVxJpdSqbGYaC3tmMw2BPpsWwQrvvkJHQJYHJRHczrc19A5XWOmmH3h34ox 3R4sNwgen2QoPvEKykVt2OJo1EuXAvxFa5tUUi5lXaHgat+GvS2uBLqnzqIO3vQ/tHJW SybGxeNgtv7ByTR5SPWtMD9WHnYM5tQBkGNrGzoZSWy+cOg4vpjtZ+qTkNuXVaWuByrU qKFF12QCwaTcOEPnGcbDT0QKRceo0ozxLPnfCDYp8CgbDUEph31QebowozxKuYb2QJvU +yCQ== X-Gm-Message-State: AOJu0YzgvQE6sYPA1eZEV7MaPJRJnAd3MizkPpFDvmwDBQNX7ArVS5nj LezL9skEbkUcic1zqeli9E1/Fk1rUgppcqxeHYX1MwG0NicBMuSwcnEgZ3I+RjSFKA2Jl3A5iir xdwktzFM= X-Gm-Gg: AfdE7cl7g/z/FhktoAjDEaqeDTtX6YSjjuFOmPJy7qF41woj9/2c4TOY4YsSWvEN6Jy 2v6gnFzRxEgG26CEmLH9FKzMGb2W88Ff10Q/jVt04cmhcRaF3UkCQtmTeCMPCIsskHC4f0cagh/ T1v+2yR6l1phyuPf3cc24OEABhdb/uBIJU1AHocSc4LgX/C8644k1WdzHf7zvVDQwuDelHJnUbg nvLlnlvsPXlb6VG/3yr8UMpfaP785r+fdXnwrHEMapfPCixH+NSeve0f3ckB7SqqJuD8vqWFDm+ INhvddOtjRs7ywAWuMpuTVee4IUGclm5/qQIIPkdhQnneQC6zqua/+C62tQqb883d5sCHgZaDZ8 BVX50BfD8aUrHMzdyyT7FDRRAm4YHybvXe26QsZBTc7oG3KUz9GjgPeEAV5H52Z/HlwX9JfnPOQ TBKXW8DRN/deGYg/sG3u9mVhNOxFtG X-Received: by 2002:a05:600c:1e0f:b0:490:e5c1:b88d with SMTP id 5b1f17b1804b1-492333babfbmr148393635e9.1.1781785384740; Thu, 18 Jun 2026 05:23:04 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:04 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 10/30] libcamera: software_isp: gpu_pipeline_shader_pass: Move common attribute and uniform variables to base shader class Date: Thu, 18 Jun 2026 13:22:23 +0100 Message-ID: <20260618122245.946138-11-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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" Every shader pass will want to set these variables so define them in the base class not in the demosiac class. Render therefore unto Cesar the things which are Cesar's. Signed-off-by: Bryan O'Donoghue --- .../software_isp/gpu_pipeline_shader_pass.h | 13 +++++++++++++ .../gpu_pipeline_shader_pass_demosiac.h | 10 ---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/libcamera/software_isp/gpu_pipeline_shader_pass.h b/src/libcamera/software_isp/gpu_pipeline_shader_pass.h index d4d4cf34d..d55b27a85 100644 --- a/src/libcamera/software_isp/gpu_pipeline_shader_pass.h +++ b/src/libcamera/software_isp/gpu_pipeline_shader_pass.h @@ -78,6 +78,19 @@ protected: struct PassConfig passInputCfg_; struct PassConfig passOutputCfg_; + + /* Common shader attributes */ + GLint attributeVertex_; + GLint attributeTexture_; + GLint textureUniformProjMatrix_; + GLint textureUniformBayerDataIn_; + GLint textureUniformStrideFactor_; + uint32_t shaderStridePixels_; + + /* Bayer shader parameters - useful to potentially more than one shader */ + GLint textureUniformBayerFirstRed_; + float firstRed_x_; + float firstRed_y_; }; } /* namespace libcamera */ diff --git a/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.h b/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.h index 11bb04c30..60f175ad3 100644 --- a/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.h +++ b/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.h @@ -43,18 +43,8 @@ public: const char *name() const override { return "GpuIspShaderPassDemosiac"; } private: /* Shader parameters */ - float firstRed_x_; - float firstRed_y_; - GLint attributeVertex_; - GLint attributeTexture_; GLint textureUniformStep_; GLint textureUniformSize_; - GLint textureUniformStrideFactor_; - GLint textureUniformBayerFirstRed_; - GLint textureUniformProjMatrix_; - GLint textureUniformBayerDataIn_; - - uint32_t shaderStridePixels_; /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */ GLint ccmUniformDataIn_; From patchwork Thu Jun 18 12:22:24 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26944 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 284FFC3307 for ; Thu, 18 Jun 2026 12:23:22 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1CF1A656C5; Thu, 18 Jun 2026 14:23:21 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="ivn+yGV0"; 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 25674629CE for ; Thu, 18 Jun 2026 14:23:06 +0200 (CEST) Received: by mail-wm1-x331.google.com with SMTP id 5b1f17b1804b1-490a76757e5so5337745e9.2 for ; Thu, 18 Jun 2026 05:23:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785386; x=1782390186; 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=PNdjgk6oCBe7hqWUf41J1Jprz/dS4FsZEgZzAJ6B81A=; b=ivn+yGV0KSWZcRqF14yNXpc5vNc4KeIvDRosSvBn/xT+E1f9duzpLgOobgxBRzqdZE qIT5/ShDkAR877HcsiOZOEUBDHh4XmHAQFOhAENiEXGQo+3195rG5HfAxiMjHfRx2SEK ogkHqK0aKX1d2DWk+YaV0laXXvnKWuLysBJIxCG2cASCotpvkK4+7bK/GD+52ZPMg7kQ NuyETyZdcih0YwxSUxD16iJWsrVxoeC0auFsVCCnmqw2LodwLlny6oQtlKe6rcvZkn2i m+oHo4QbaKtEVEVyUak2xzraPgy3cpuIQHIKAIVQX+Ap6Xv2zh9Lh8MkkXWzYzik+Dle OEfA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785386; x=1782390186; 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=PNdjgk6oCBe7hqWUf41J1Jprz/dS4FsZEgZzAJ6B81A=; b=DBevMqwBT7wZbySeRjIpkV18MMcZm12N/Zb2IVAkzcm2LrLoDr1IrrevuxyqhAx6pM uebNJaikUKGRfwXbKyr5AlpgdwaGchvMMKVwNzO9LW4EYfXygqegXb1gzfBwKaFf2lqR kZw9qMtEjuFZzMxgQcHljScxvi8aqA2R7QzUQ8jeUS7LpW767FtTFbIsTgFzumNJJf/Q +7EV6vtPqiQn9kIeKJDFVcAiFQfSOFm6Hjvwu0hNjsHNMFT1GZjNhR+vqA6RuoKNSA6o K+fRKSYQsOP2deN0mzBiu4G+4pEFGLS3Icj9IfPTAoxWCMq3/gjLjTgPbiCT/rXtt9gf p8dA== X-Gm-Message-State: AOJu0YwDr/Q8i1cTkyf2wepx+GKAGdxz/G9cCVoqhjDFhSha/HPV9D1h CaDf9tFM5C5gAL9mpkmXPYNlXJZTkmgM9wkWOsiSDr4pygU/XVNc0bNO86C1vv+MsX0ZReV6ZDQ VPQJplsg= X-Gm-Gg: AfdE7clrITOQ27CsZRffvI8bFF7VK6TJJ6sp6i1AZPs5oQalna5OcZeQoupSUzYA1mW ednsSu6E+1JNoOPZALD29o+7DyhIYsWVrB2ysbPm7wyDBGr8aZn9xxqzb/l5yjNP1UZJCJnpB8r wGBzGsntY21j8WUg5in7l01tchegLLUdAYraKL0hdtlsTPWNsd13COQB4BbbQHGUYT49WRsA46f pzx9tw0b9HK6/FyKPHJk4K8s6uk8Zayyw+VKP/icUlEW6A3jMgp2kcM+Lf1RgPqRwYIKFA3uyyn gl6xL3YUL3QJMVOXxe5t6vzA5LoZdsQO2mk7XjyVAmAq2tgkzXJUC8PUAOQTplmLQ7f8u6gzaIT v5em5tL+Oze4J/aoaJ3wBvJKUOU9ybZg8vJALBgpX9FOm44NwkvjKAarN2rb9uYy0/7ExfqeFQm +8sG3YrIlU1A7/biPmYOUku5aAv+PQBoAqgYXiqJc= X-Received: by 2002:a05:600c:83cf:b0:492:2e1c:1d19 with SMTP id 5b1f17b1804b1-49238225f8bmr54202185e9.31.1781785385527; Thu, 18 Jun 2026 05:23:05 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:05 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 11/30] libcamera: software_isp: gpu_pipeline_shader_pass: Move common shader selection logic into base class in new method initShaders() Date: Thu, 18 Jun 2026 13:22:24 +0100 Message-ID: <20260618122245.946138-12-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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" Shader initialisation has some common and some pass-specific logic that needs to happen. - Common: Environment setup such as defining top-level defines as flags to include features when compiling shaders. This will have to be consistent from one shader feeding the next. - Shader specific: Selecting which vertex, fragment and potentially compute shaders to run - populating the shader compile environment with any defines specific to that shader. - Common: Compiling and linking a shader program. Error checking and associating a compiled vertex/fragment or compute shader with a given programId_. Move the common code to the base class and have the base class call out to a pure virtual funtion that the derived class must implement. In this way GpuIspShaderPass::initShaders() calls the derived class GpuIspShaderPassDerivedClass::selectShader() while encapsulating that call in the afore mentioned common pieces of logic. Signed-off-by: Bryan O'Donoghue --- .../software_isp/gpu_pipeline_shader_pass.cpp | 118 ++++++++++++++- .../software_isp/gpu_pipeline_shader_pass.h | 11 +- .../gpu_pipeline_shader_pass_demosiac.cpp | 139 +++--------------- .../gpu_pipeline_shader_pass_demosiac.h | 3 +- 4 files changed, 151 insertions(+), 120 deletions(-) diff --git a/src/libcamera/software_isp/gpu_pipeline_shader_pass.cpp b/src/libcamera/software_isp/gpu_pipeline_shader_pass.cpp index 669a1c1b6..d0d13eef9 100644 --- a/src/libcamera/software_isp/gpu_pipeline_shader_pass.cpp +++ b/src/libcamera/software_isp/gpu_pipeline_shader_pass.cpp @@ -36,16 +36,29 @@ LOG_DEFINE_CATEGORY(GpuShaderPass) int GpuIspShaderPass::process(eGLImage &eglImageIn, eGLImage &eglImageOut, uint32_t width, uint32_t height, const DebayerParams ¶ms) { - /* Switch to the output framebuffer */ + GLenum err; + egl_.useProgram(programId_); + err = glGetError(); + if (err != GL_NO_ERROR) + LOG(GpuShaderPass, Error) << "Switch program @ error " << err; + + /* Switch to the output framebuffer */ egl_.attachTextureToFBO(eglImageOut); + err = glGetError(); + if (err != GL_NO_ERROR) + LOG(GpuShaderPass, Error) << "attachTextureToFBO @ error " << err; setShaderVariableValues(params, eglImageIn); + err = glGetError(); + if (err != GL_NO_ERROR) + LOG(GpuShaderPass, Error) << "setShaderVariables @ error " << err; + glViewport(0, 0, width, height); glClear(GL_COLOR_BUFFER_BIT); - glDrawArrays(GL_TRIANGLE_FAN, 0, DEBAYER_OPENGL_COORDS); - GLenum err = glGetError(); + glDrawArrays(GL_TRIANGLE_FAN, 0, DEBAYER_OPENGL_COORDS); + err = glGetError(); if (err != GL_NO_ERROR) { LOG(GpuShaderPass, Error) << "Drawing scene fail " << err; return -ENODEV; @@ -71,4 +84,103 @@ void GpuIspShaderPass::configure(const struct PassConfig &passInputCfg, const st passOutputCfg_ = passOutputCfg; } +int GpuIspShaderPass::initShaders(PixelFormat inputFormat, PixelFormat outputFormat) +{ + struct ShaderConfig shaderCfg; + GLenum err; + int ret; + + /* Target gles 100 glsl requires "#version x" as first directive in shader */ + egl_.pushEnv(shaderCfg.shaderEnv, "#version 100"); + + /* Specify GL_OES_EGL_image_external */ + egl_.pushEnv(shaderCfg.shaderEnv, "#extension GL_OES_EGL_image_external: enable"); + + /* The BLC and Demosiac shaders want to know this so do it in the base class */ + switch (inputFormat) { + case libcamera::formats::SBGGR8: + case libcamera::formats::SBGGR10_CSI2P: + case libcamera::formats::SBGGR12_CSI2P: + firstRed_x_ = 1.0; + firstRed_y_ = 1.0; + break; + case libcamera::formats::SGBRG8: + case libcamera::formats::SGBRG10_CSI2P: + case libcamera::formats::SGBRG12_CSI2P: + firstRed_x_ = 0.0; + firstRed_y_ = 1.0; + break; + case libcamera::formats::SGRBG8: + case libcamera::formats::SGRBG10_CSI2P: + case libcamera::formats::SGRBG12_CSI2P: + firstRed_x_ = 1.0; + firstRed_y_ = 0.0; + break; + case libcamera::formats::SRGGB8: + case libcamera::formats::SRGGB10_CSI2P: + case libcamera::formats::SRGGB12_CSI2P: + firstRed_x_ = 0.0; + firstRed_y_ = 0.0; + break; + default: + LOG(GpuShaderPass, Error) << "Unsupported input format"; + return -EINVAL; + }; + + /* + * Tell shaders how to re-order output taking account of how the pixels + * are actually stored by EGL. + */ + switch (outputFormat) { + case formats::ARGB8888: + case formats::XRGB8888: + break; + case formats::ABGR8888: + case formats::XBGR8888: + egl_.pushEnv(shaderCfg.shaderEnv, "#define SWAP_BLUE"); + break; + default: + LOG(GpuShaderPass, Error) << "Unsupported output format"; + return -EINVAL; + } + + ret = selectShaders(shaderCfg, inputFormat, outputFormat); + if (ret) { + LOG(GpuShaderPass, Error) << "selectShaders fail"; + return ret; + } + + LOG(GpuShaderPass, Info) << "ShaderPass = " << typeid(this).name(); + + if (egl_.compileVertexShader(vertexShaderId_, shaderCfg.vertexShaderData, shaderCfg.vertexShaderDataLen, shaderCfg.shaderEnv)) { + LOG(GpuShaderPass, Error) << "Compile vertex shader fail"; + return -ENODEV; + } + utils::scope_exit vShaderGuard([&] { glDeleteShader(vertexShaderId_); }); + + if (egl_.compileFragmentShader(fragmentShaderId_, shaderCfg.fragmentShaderData, shaderCfg.fragmentShaderDataLen, shaderCfg.shaderEnv)) { + LOG(GpuShaderPass, Error) << "Compile fragment shader fail"; + return -ENODEV; + } + utils::scope_exit fShaderGuard([&] { glDeleteShader(fragmentShaderId_); }); + + if (egl_.linkProgram(programId_, vertexShaderId_, fragmentShaderId_)) { + LOG(GpuShaderPass, Error) << "Linking program fail"; + return -ENODEV; + } + + egl_.dumpShaderSource(vertexShaderId_); + egl_.dumpShaderSource(fragmentShaderId_); + + /* Ensure we set the programId_ */ + egl_.useProgram(programId_); + err = glGetError(); + if (err != GL_NO_ERROR) { + LOG(GpuShaderPass, Error) << "Use program error " << err; + return -ENODEV; + } + + return getShaderVariableLocations(); +} + } diff --git a/src/libcamera/software_isp/gpu_pipeline_shader_pass.h b/src/libcamera/software_isp/gpu_pipeline_shader_pass.h index d55b27a85..a329845ee 100644 --- a/src/libcamera/software_isp/gpu_pipeline_shader_pass.h +++ b/src/libcamera/software_isp/gpu_pipeline_shader_pass.h @@ -41,6 +41,14 @@ struct PassConfig { Rectangle window; }; +struct ShaderConfig { + std::vector shaderEnv; + const unsigned char *vertexShaderData; + unsigned int vertexShaderDataLen; + const unsigned char *fragmentShaderData; + unsigned int fragmentShaderDataLen; +}; + class GpuIspShaderPass : public Object { public: @@ -51,7 +59,8 @@ public: virtual int start(); virtual void stop(); virtual void configure(const struct PassConfig &passInputCfg, const struct PassConfig &passOutputCfg); - virtual int initShaders(PixelFormat inputFormat, PixelFormat outputFormat) = 0; + virtual int initShaders(PixelFormat inputFormat, PixelFormat outputFormat); + virtual int selectShaders(struct ShaderConfig &shaderCfg, PixelFormat &inputFormat, PixelFormat &outputFormat) = 0; virtual int getShaderVariableLocations(void) = 0; virtual void setShaderVariableValues(const DebayerParams ¶ms, eGLImage &eglImageIn) = 0; virtual const char *name() const { return "GpuIspShaderPass"; } diff --git a/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.cpp b/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.cpp index 02d9da2f0..b0c431c13 100644 --- a/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.cpp +++ b/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.cpp @@ -44,101 +44,41 @@ void GpuIspShaderPassDemosiac::stop() { } -int GpuIspShaderPassDemosiac::initShaders(PixelFormat inputFormat, PixelFormat outputFormat) +int GpuIspShaderPassDemosiac::selectShaders(struct ShaderConfig &shaderCfg, [[maybe_unused]]PixelFormat &inputFormat, [[maybe_unused]]PixelFormat &outputFormat) { - std::vector shaderEnv; - unsigned int fragmentShaderDataLen = 0; - const unsigned char *fragmentShaderData = 0; - unsigned int vertexShaderDataLen = 0; - const unsigned char *vertexShaderData = 0; - GLenum err; - - /* Target gles 100 glsl requires "#version x" as first directive in shader */ - egl_.pushEnv(shaderEnv, "#version 100"); - - /* Specify GL_OES_EGL_image_external */ - egl_.pushEnv(shaderEnv, "#extension GL_OES_EGL_image_external: enable"); - - /* - * Tell shaders how to re-order output taking account of how the pixels - * are actually stored by EGL. - */ - switch (outputFormat) { - case formats::ARGB8888: - case formats::XRGB8888: - break; - case formats::ABGR8888: - case formats::XBGR8888: - egl_.pushEnv(shaderEnv, "#define SWAP_BLUE"); - break; - default: - LOG(GpuShaderDemosiac, Error) << "Unsupported output format"; - return -EINVAL; - } - /* Pixel location parameters */ glFormat_ = GL_LUMINANCE; bytesPerPixel_ = 1; shaderStridePixels_ = passInputCfg_.stride; - switch (inputFormat) { - case libcamera::formats::SBGGR8: - case libcamera::formats::SBGGR10_CSI2P: - case libcamera::formats::SBGGR12_CSI2P: - firstRed_x_ = 1.0; - firstRed_y_ = 1.0; - break; - case libcamera::formats::SGBRG8: - case libcamera::formats::SGBRG10_CSI2P: - case libcamera::formats::SGBRG12_CSI2P: - firstRed_x_ = 0.0; - firstRed_y_ = 1.0; - break; - case libcamera::formats::SGRBG8: - case libcamera::formats::SGRBG10_CSI2P: - case libcamera::formats::SGRBG12_CSI2P: - firstRed_x_ = 1.0; - firstRed_y_ = 0.0; - break; - case libcamera::formats::SRGGB8: - case libcamera::formats::SRGGB10_CSI2P: - case libcamera::formats::SRGGB12_CSI2P: - firstRed_x_ = 0.0; - firstRed_y_ = 0.0; - break; - default: - LOG(GpuShaderDemosiac, Error) << "Unsupported input format"; - return -EINVAL; - }; - /* Shader selection */ switch (inputFormat) { case libcamera::formats::SBGGR8: case libcamera::formats::SGBRG8: case libcamera::formats::SGRBG8: case libcamera::formats::SRGGB8: - fragmentShaderData = bayer_unpacked_frag; - fragmentShaderDataLen = bayer_unpacked_frag_len; - vertexShaderData = bayer_unpacked_vert; - vertexShaderDataLen = bayer_unpacked_vert_len; + shaderCfg.fragmentShaderData = bayer_unpacked_frag; + shaderCfg.fragmentShaderDataLen = bayer_unpacked_frag_len; + shaderCfg.vertexShaderData = bayer_unpacked_vert; + shaderCfg.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"); + egl_.pushEnv(shaderCfg.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; + shaderCfg.fragmentShaderData = bayer_unpacked_frag; + shaderCfg.fragmentShaderDataLen = bayer_unpacked_frag_len; + shaderCfg.vertexShaderData = bayer_unpacked_vert; + shaderCfg.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; + shaderCfg.fragmentShaderData = bayer_1x_packed_frag; + shaderCfg.fragmentShaderDataLen = bayer_1x_packed_frag_len; + shaderCfg.vertexShaderData = identity_vert; + shaderCfg.vertexShaderDataLen = identity_vert_len; shaderStridePixels_ = passInputCfg_.size.width; } break; @@ -146,56 +86,25 @@ int GpuIspShaderPassDemosiac::initShaders(PixelFormat inputFormat, PixelFormat o case libcamera::formats::SGBRG12_CSI2P: case libcamera::formats::SGRBG12_CSI2P: case libcamera::formats::SRGGB12_CSI2P: - egl_.pushEnv(shaderEnv, "#define RAW12P"); + egl_.pushEnv(shaderCfg.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; + shaderCfg.fragmentShaderData = bayer_unpacked_frag; + shaderCfg.fragmentShaderDataLen = bayer_unpacked_frag_len; + shaderCfg.vertexShaderData = bayer_unpacked_vert; + shaderCfg.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; + shaderCfg.fragmentShaderData = bayer_1x_packed_frag; + shaderCfg.fragmentShaderDataLen = bayer_1x_packed_frag_len; + shaderCfg.vertexShaderData = identity_vert; + shaderCfg.vertexShaderDataLen = identity_vert_len; shaderStridePixels_ = passInputCfg_.size.width; } break; }; - /* TODO: move from here to the end of the method into a helper function in the base class - * this logic will be common to all pipeline instances - */ - if (egl_.compileVertexShader(vertexShaderId_, vertexShaderData, vertexShaderDataLen, shaderEnv)) { - LOG(GpuShaderDemosiac, Error) << "Compile vertex shader fail"; - return -ENODEV; - } - utils::scope_exit vShaderGuard([&] { glDeleteShader(vertexShaderId_); }); - - if (egl_.compileFragmentShader(fragmentShaderId_, fragmentShaderData, fragmentShaderDataLen, shaderEnv)) { - LOG(GpuShaderDemosiac, Error) << "Compile fragment shader fail"; - return -ENODEV; - } - utils::scope_exit fShaderGuard([&] { glDeleteShader(fragmentShaderId_); }); - - if (egl_.linkProgram(programId_, vertexShaderId_, fragmentShaderId_)) { - LOG(GpuShaderDemosiac, Error) << "Linking program fail"; - return -ENODEV; - } - - egl_.dumpShaderSource(vertexShaderId_); - egl_.dumpShaderSource(fragmentShaderId_); - - /* Ensure we set the programId_ */ - egl_.useProgram(programId_); - err = glGetError(); - if (err != GL_NO_ERROR) { - LOG(GpuShaderDemosiac, Error) << "Use program error " << err; - return -ENODEV; - } - - return getShaderVariableLocations(); + return 0; } int GpuIspShaderPassDemosiac::getShaderVariableLocations(void) diff --git a/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.h b/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.h index 60f175ad3..c83024bc4 100644 --- a/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.h +++ b/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.h @@ -37,10 +37,11 @@ public: void stop(); /* Things that every ISP pipeline pass will need to do */ - int initShaders(PixelFormat inputFormat, PixelFormat outputFormat); int getShaderVariableLocations(void); void setShaderVariableValues(const DebayerParams ¶ms, eGLImage &eglImageIn); + int selectShaders(struct ShaderConfig &shaderCfg, PixelFormat &inputFormat, PixelFormat &outputFormat); const char *name() const override { return "GpuIspShaderPassDemosiac"; } + private: /* Shader parameters */ GLint textureUniformStep_; From patchwork Thu Jun 18 12:22:25 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26945 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 CC246C3308 for ; Thu, 18 Jun 2026 12:23:23 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1E41762E9D; Thu, 18 Jun 2026 14:23:23 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="f+vB/4Hh"; 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 1BAB462C75 for ; Thu, 18 Jun 2026 14:23:07 +0200 (CEST) Received: by mail-wm1-x329.google.com with SMTP id 5b1f17b1804b1-490c0c92cffso5754315e9.2 for ; Thu, 18 Jun 2026 05:23:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785386; x=1782390186; 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=Wz6jOi4zrOfD7lo4bGTEUJZC6/iyIZAKi0SbTeHzIjE=; b=f+vB/4Hh1F2esUnBoRHyt+pZsko1hitYGwAxkXlHqNiJ6GVIJXviC7jpjn5o1BfiBt 6tpkGHAMhf2YgEovnoZZAXR3kUDs+06siImAKXHEQEZbn0DNLSvGy7WPqueqFFYW8pWi QZ+zORKjB7Fm9hYQsXa/4jIZvrBv4DvaKQ7dxUf89SjEZ7fpBceYtqgHkHei5/VEg8O9 mJKcahkTsNwf3rBlqMbTFzExRuaPbOSabOkkmNiHX1FkC7Hqy6M13+cGQDv0+4eF6OlR 4En597v3jkxuuMl9VEQhVtidykJPkXZ7MrVzbcJd8uSin3PUC9Cu4fB1O0kowtrdQZ/b IMJQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785386; x=1782390186; 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=Wz6jOi4zrOfD7lo4bGTEUJZC6/iyIZAKi0SbTeHzIjE=; b=DLFqHk3XUugHjlW7aPiNZowmjCo/PlmBQGr/ugGyWzJ9lHlKnCUkSsT1r+7twCdxM7 GNaLjoeidMhGpb/miah336rbUFQ0E1lWum0GAbobetreeEAodKOI2OhbqoSwWjuno+d0 qFAooUyU0FX1Cm2KbqFnNDfl6Xzm/R4QXtsYUJ6OgA2/FziZaQNurv0+X8B35iFa6Vfw dio6k6wZbDSe29obgwcLEpW/wSrH9nPqtQ/RPDc8Ra7+bj32WIFmjBtftVqVXs7fvkzR I+UMCgyLyYkEbQw4nyy6zWopPW/cgU+GcqkAJj94uPMMloxRWQCNPEbcweoiyVPDAfo/ cRUA== X-Gm-Message-State: AOJu0Yww/PqHf3VAIW9t9kvSkWO3FOU3qIpmPuI0qk31AC+w76q7SEfh Gt08nQBqaV+WbcU+awfI4697c2jVQGJrXSR0DxIBiTMy0BVrakcUPC4ixCBIx3b1oJ5M/jwdDUu pSh9PPWw= X-Gm-Gg: AfdE7ckIuWFid68HmaJkjPgpDRvjZcWk5v0re4VY9z3+InAHGMnMk62FgTuEHRjoqkK wrx+hJkH3+ylMN4ZkYCk8ELeLS79KVSGfsU7gr+1yssmnGDfc/fmhPUT5qDfjbD3kN2HIX4h1al NfSSdPlN4DhsTmAoo4QifOB2cEdd9DUKtixhr98xf6ZeskA1vQVd82pZMsDbCQOvVLcPq/dGXPj dndUyaDIoK8ZxkoaFKvRS49s1U9JXurZMcZOUF4avXPkQWvk+QH3QfGjT9Vc/QzJMkwdJvUbpXz nnCDW9LGKxx4PNQx8MqU+T5EignMFrY89yYW0pjUIjZEuDgaHShP3JCjdBntaPhPF8fX99PsZIN mBaOG1qfqU74UlYVJY0k4Lms/jwiDilLgrXiuIvL5imtcVpMPqk7zsw6JYZ92k2rpnH/KijdcaQ f659uFbc/UDUKwyLmS0dGHb9A0CSKGzcFLCmSeXLU= X-Received: by 2002:a05:600c:c3cc:10b0:492:3778:d452 with SMTP id 5b1f17b1804b1-4923778d457mr58188275e9.14.1781785386279; Thu, 18 Jun 2026 05:23:06 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:05 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 12/30] libcamera: shaders: Split packed and unpacked demosiac up Date: Thu, 18 Jun 2026 13:22:25 +0100 Message-ID: <20260618122245.946138-13-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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 --- .../bayer_1x_packed_to_blc_glr16f.frag | 97 ++++++++++ .../shaders/bayer_glr16_to_rgba.frag | 183 ++++++++++++++++++ .../shaders/bayer_unpacked_to_blc_glr16f.frag | 46 +++++ src/libcamera/shaders/meson.build | 3 + 4 files changed, 329 insertions(+) create mode 100644 src/libcamera/shaders/bayer_1x_packed_to_blc_glr16f.frag create mode 100644 src/libcamera/shaders/bayer_glr16_to_rgba.frag create mode 100644 src/libcamera/shaders/bayer_unpacked_to_blc_glr16f.frag diff --git a/src/libcamera/shaders/bayer_1x_packed_to_blc_glr16f.frag b/src/libcamera/shaders/bayer_1x_packed_to_blc_glr16f.frag new file mode 100644 index 000000000..d1234007e --- /dev/null +++ b/src/libcamera/shaders/bayer_1x_packed_to_blc_glr16f.frag @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Based on the code from http://jgt.akpeters.com/papers/McGuire08/ + * + * Copyright (c) 2008, Morgan McGuire. All rights reserved. + * + * Modified by Linaro Ltd for 10/12-bit packed raw Bayer format. + * Copyright (C) 2020, Linaro + * + * precursor_packed.frag - Precursor shader to decode MIPI packed raw Bayer + * data and output normalised single-channel float to an R16F FBO. + * Pairs with identity.vert. + */ + +#ifdef GL_ES +precision highp float; +#endif + +/* + * These constants are used to select the bytes containing the HS part of + * the pixel value: + * BPP - bytes per pixel, + * THRESHOLD_L = fract(BPP) * 0.5 + 0.02 + * THRESHOLD_H = 1.0 - fract(BPP) * 1.5 + 0.02 + * Let X is the x coordinate in the texture measured in bytes (so that the + * range is from 0 to (stride_-1)) aligned on the nearest pixel. + * E.g. for RAW10P: + * -------------+-------------------+-------------------+-- + * pixel No | 0 1 2 3 | 4 5 6 7 | ... + * -------------+-------------------+-------------------+-- + * byte offset | 0 1 2 3 4 | 5 6 7 8 9 | ... + * -------------+-------------------+-------------------+-- + * X | 0.0 1.25 2.5 3.75 | 5.0 6.25 7.5 8.75 | ... + * -------------+-------------------+-------------------+-- + * If fract(X) < THRESHOLD_L then the previous byte contains the LS + * bits of the pixel values and needs to be skipped. + * If fract(X) > THRESHOLD_H then the next byte contains the LS bits + * of the pixel values and needs to be skipped. + */ +#if defined(RAW10P) +#define BPP 1.25 +#define THRESHOLD_L 0.14 +#define THRESHOLD_H 0.64 +#elif defined(RAW12P) +#define BPP 1.5 +#define THRESHOLD_L 0.27 +#define THRESHOLD_H 0.27 +#else +#error Invalid raw format +#endif + +varying vec2 textureOut; + +/* the texture size in pixels */ +uniform vec2 tex_size; +uniform vec2 tex_step; + +uniform vec3 blacklevel; + +uniform sampler2D tex_y; + +void main(void) +{ + /* + * center_bytes holds the coordinates of the MS byte of the pixel + * being sampled on the [0, stride-1/height-1] range. + * center_pixel holds the coordinates of the pixel being sampled + * on the [0, width/height-1] range. + */ + vec2 center_bytes; + vec2 center_pixel; + + /* + * The coordinates passed to the shader in textureOut may point + * to a place in between the pixels if the texture format doesn't + * match the image format. In particular, MIPI packed raw Bayer + * formats don't have a matching texture format. + * In this case align the coordinates to the left nearest pixel + * by hand. + */ + center_pixel = floor(textureOut * tex_size); + center_bytes.y = center_pixel.y; + + /* + * Add a small number (a few mantissa's LSBs) to avoid float + * representation issues. + */ + center_bytes.x = BPP * center_pixel.x + 0.02; + center_bytes.x = floor(center_bytes.x); + center_bytes *= tex_step; + + float C = texture2D(tex_y, center_bytes).r; + + C = C - blacklevel[0]; + + gl_FragColor = vec4(C, 0.0, 0.0, 0.0); +} diff --git a/src/libcamera/shaders/bayer_glr16_to_rgba.frag b/src/libcamera/shaders/bayer_glr16_to_rgba.frag new file mode 100644 index 000000000..f3883a82b --- /dev/null +++ b/src/libcamera/shaders/bayer_glr16_to_rgba.frag @@ -0,0 +1,183 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* +From http://jgt.akpeters.com/papers/McGuire08/ + +Efficient, High-Quality Bayer Demosaic Filtering on GPUs + +Morgan McGuire + +This paper appears in issue Volume 13, Number 4. +--------------------------------------------------------- +Copyright (c) 2008, Morgan McGuire. All rights reserved. + +Modified by Linaro Ltd to integrate it into libcamera. +Copyright (C) 2021-2026, Linaro +*/ + +//Pixel Shader +#ifdef GL_ES +precision highp float; +#endif + +/** Monochrome RGBA or GL_LUMINANCE Bayer encoded texture.*/ +uniform sampler2D tex_y; +varying vec4 center; +varying vec4 yCoord; +varying vec4 xCoord; +uniform mat3 ccm; +uniform float gamma; +uniform float contrastExp; + +float apply_contrast(float value) +{ + // Apply simple S-curve + if (value < 0.5) + return 0.5 * pow(value / 0.5, contrastExp); + else + return 1.0 - 0.5 * pow((1.0 - value) / 0.5, contrastExp); +} + +void main(void) { + vec3 rgb; + + /* Sample from R16F input texture */ + #define fetch(x, y) texture2D(tex_y, vec2(x, y)).r + + 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. + vec2 alternate = mod(floor(center.zw), 2.0); + + vec4 Dvec = vec4( + fetch(xCoord[1], yCoord[1]), // (-1,-1) + fetch(xCoord[1], yCoord[2]), // (-1, 1) + fetch(xCoord[2], yCoord[1]), // ( 1,-1) + fetch(xCoord[2], yCoord[2])); // ( 1, 1) + + vec4 PATTERN = (kC.xyz * C).xyzz; + + // Can also be a dot product with (1,1,1,1) on hardware where that is + // specially optimized. + // Equivalent to: D = Dvec[0] + Dvec[1] + Dvec[2] + Dvec[3]; + Dvec.xy += Dvec.zw; + Dvec.x += Dvec.y; + + vec4 value = vec4( + fetch(center.x, yCoord[0]), // ( 0,-2) + fetch(center.x, yCoord[1]), // ( 0,-1) + fetch(xCoord[0], center.y), // (-2, 0) + fetch(xCoord[1], center.y)); // (-1, 0) + + vec4 temp = vec4( + fetch(center.x, yCoord[3]), // ( 0, 2) + fetch(center.x, yCoord[2]), // ( 0, 1) + fetch(xCoord[3], center.y), // ( 2, 0) + fetch(xCoord[2], center.y)); // ( 1, 0) + + // Even the simplest compilers should be able to constant-fold these to + // avoid the division. + // Note that on scalar processors these constants force computation of some + // identical products twice. + const vec4 kA = vec4(-1.0, -1.5, 0.5, -1.0) / 8.0; + const vec4 kB = vec4( 2.0, 0.0, 0.0, 4.0) / 8.0; + const vec4 kD = vec4( 0.0, 2.0, -1.0, -1.0) / 8.0; + + // Conserve constant registers and take advantage of free swizzle on load + #define kE (kA.xywz) + #define kF (kB.xywz) + + value += temp; + + // There are five filter patterns (identity, cross, checker, + // theta, phi). Precompute the terms from all of them and then + // use swizzles to assign to color channels. + // + // Channel Matches + // x cross (e.g., EE G) + // y checker (e.g., EE B) + // z theta (e.g., EO R) + // w phi (e.g., EO R) + #define A (value[0]) + #define B (value[1]) + #define D (Dvec.x) + #define E (value[2]) + #define F (value[3]) + + // Avoid zero elements. On a scalar processor this saves two MADDs + // and it has no effect on a vector processor. + PATTERN.yzw += (kD.yz * D).xyy; + + PATTERN += (kA.xyz * A).xyzx + (kE.xyw * E).xyxz; + PATTERN.xw += kB.xw * B; + PATTERN.xz += kF.xz * F; + + rgb = (alternate.y == 0.0) ? + ((alternate.x == 0.0) ? + vec3(C, PATTERN.xy) : + vec3(PATTERN.z, C, PATTERN.w)) : + ((alternate.x == 0.0) ? + vec3(PATTERN.w, C, PATTERN.z) : + vec3(PATTERN.yx, C)); + + /* + * CCM is a 3x3 in the format + * + * +--------------+----------------+---------------+ + * | RedRedGain | RedGreenGain | RedBlueGain | + * +--------------+----------------+---------------+ + * | GreenRedGain | GreenGreenGain | GreenBlueGain | + * +--------------+----------------+---------------+ + * | BlueRedGain | BlueGreenGain | BlueBlueGain | + * +--------------+----------------+---------------+ + * + * Rout = RedRedGain * Rin + RedGreenGain * Gin + RedBlueGain * Bin + * Gout = GreenRedGain * Rin + GreenGreenGain * Gin + GreenBlueGain * Bin + * Bout = BlueRedGain * Rin + BlueGreenGain * Gin + BlueBlueGain * Bin + * + * We upload to the GPU without transposition glUniformMatrix3f(.., .., GL_FALSE, ccm); + * + * CPU + * float ccm [] = { + * RedRedGain, RedGreenGain, RedBlueGain, + * GreenRedGain, GreenGreenGain, GreenBlueGain, + * BlueRedGain, BlueGreenGain, BlueBlueGain, + * }; + * + * GPU + * ccm = { + * RedRedGain, GreenRedGain, BlueRedGain, + * RedGreenGain, GreenGreenGain, BlueGreenGain, + * RedBlueGain, GreenBlueGain, BlueBlueGain, + * } + * + * However the indexing for the mat data-type is column major hence + * ccm[0][0] = RedRedGain, ccm[0][1] = RedGreenGain, ccm[0][2] = RedBlueGain + * + */ + float rin, gin, bin; + rin = rgb.r; + gin = rgb.g; + bin = rgb.b; + + rgb.r = (rin * ccm[0][0]) + (gin * ccm[0][1]) + (bin * ccm[0][2]); + rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]); + rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]); + + /* + * Contrast + */ + rgb = clamp(rgb, 0.0, 1.0); + rgb.r = apply_contrast(rgb.r); + rgb.g = apply_contrast(rgb.g); + rgb.b = apply_contrast(rgb.b); + + /* Apply gamma after colour correction */ + rgb = pow(rgb, vec3(gamma)); + + #if defined (SWAP_BLUE) + gl_FragColor = vec4(rgb.bgr, 1.0); + #else + gl_FragColor = vec4(rgb, 1.0); + #endif +} diff --git a/src/libcamera/shaders/bayer_unpacked_to_blc_glr16f.frag b/src/libcamera/shaders/bayer_unpacked_to_blc_glr16f.frag new file mode 100644 index 000000000..00ed47ce8 --- /dev/null +++ b/src/libcamera/shaders/bayer_unpacked_to_blc_glr16f.frag @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Based on the code from http://jgt.akpeters.com/papers/McGuire08/ + * + * Copyright (c) 2008, Morgan McGuire. All rights reserved. + * + * Modified by Linaro Ltd to integrate it into libcamera. + * Copyright (C) 2021, Linaro + * + * precursor_unpacked.frag - Precursor shader to decode unpacked raw Bayer + * data (R8, RG8 with split 10/12-bit values) and output normalised + * single-channel float to an R16F FBO. + * Pairs with identity.vert. + */ + +#ifdef GL_ES +precision highp float; +#endif + +varying vec2 textureOut; + +uniform sampler2D tex_y; + +void main(void) +{ + /* + * Reconstruct the pixel value from the texture format. + * + * For RAW10P the 10-bit value is split across two 8-bit channels: + * value = R / 4.0 + G * 64.0 + * For RAW12P the 12-bit value is split across two 8-bit channels: + * value = R / 16.0 + G * 16.0 + * Otherwise the value is a plain single-channel sample. + */ +#if defined(RAW10P) + vec4 p = texture2D(tex_y, textureOut); + float C = p.r / 4.0 + p.g * 64.0; +#elif defined(RAW12P) + vec4 p = texture2D(tex_y, textureOut); + float C = p.r / 16.0 + p.g * 16.0; +#else + float C = texture2D(tex_y, textureOut).r; +#endif + + gl_FragColor = vec4(C, 0.0, 0.0, 1.0); +} diff --git a/src/libcamera/shaders/meson.build b/src/libcamera/shaders/meson.build index dd441a577..0e2b765d7 100644 --- a/src/libcamera/shaders/meson.build +++ b/src/libcamera/shaders/meson.build @@ -3,6 +3,9 @@ # List of shader files to convert to header hex # for the purposes of inclusion in OpenGL debayering shader_files = files([ + 'bayer_1x_packed_to_blc_glr16f.frag', + 'bayer_unpacked_to_blc_glr16f.frag', + 'bayer_glr16_to_rgba.frag', 'bayer_1x_packed.frag', 'bayer_unpacked.frag', 'bayer_unpacked.vert', From patchwork Thu Jun 18 12:22:26 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26946 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 09728BF415 for ; Thu, 18 Jun 2026 12:23:25 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6983F656C7; Thu, 18 Jun 2026 14:23:24 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="osAukbaX"; 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 98D1C62B2B for ; Thu, 18 Jun 2026 14:23:07 +0200 (CEST) Received: by mail-wm1-x32a.google.com with SMTP id 5b1f17b1804b1-490b613a17bso6482045e9.3 for ; Thu, 18 Jun 2026 05:23:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785387; x=1782390187; 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=oHBRpAaxg79VoY7KRUqI2QqDEabR3Qd+XLpjHZnpia4=; b=osAukbaXFwPLDJRWjC/C1Vm8RQpGMY5Er3HZNocTuRT2FeRre11mv4M3WpFgwITupD 7JytcX2lCo05Fyv96EWKpjY1RjqxaYL4xmd9EZq2BzYgnWip2R8YfGI0V05tsz4Pk/wG 5dHZB2ONugEWmxI8GYwKD/3tJSIa2fBSpmYHBbP1rNrh8dEBvSdUm5NfpD/vqVgVTiaV 7z43ns0n5IxkKc5r668KAGrJh3aCyCu39vEEpPuRIifyC+kkznkch4R6YRocN3aywNGR sgdvX+Cvw4RkUKdj8zJ0Dm0WEsRACS0M3cKEYhP+qTDtta1/3jzhY8inOYPGwekKTNov uEUg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785387; x=1782390187; 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=oHBRpAaxg79VoY7KRUqI2QqDEabR3Qd+XLpjHZnpia4=; b=Y+8rHuOhAfDswLtcBFrtUzO3Fkcsi8/vx1G5DOBExi1R8K27SitNg+gBJZU/J3VS+a k3qJgHTwrz8amDZZi1AUO2y8ERuhL/ka0NJkbnJyZYHgxShhLvz1eOfIWWEIZCP5xE/X lGVyYRuRVIUmQu9Km583uZ6Vts5IL4M2UuLf2ormo9E4wncNw2RnbI9eONDhqBqb2XXA lOyNcKvaU5Fm4YnwpaPsc6KbDYKCpKq+1ODAESqC0kzqvVyw5Cfq49kkhEIFoyxlvKpF ADWhnPJbKn1/QoXVjTiLvKoz3q57xjHncrYeKDIXOZ9+yugaYOjjSsjMZopG1li1D8J4 viYg== X-Gm-Message-State: AOJu0YyhFYHq0vCDwsXxVu8HKnBgOmHzc+Yyq8iXF0z7VHl0O7vVP5K1 EwbYVbw727JHDRwm9TmzopU8xEPpYRU8zCGzbwF7cZ1RzzERsFvjI8Xp2CudI+1H5s8g1/iT1kQ goINmlSs= X-Gm-Gg: AfdE7clJSW2MOl/4JKEcbV2HB+lpd1ASKRznhamAXEWBXz3+uIREp8DlwFJDKq1Wmy7 bU1nNKjImrmffYkHSfVoyJIxOFT/ZmJH90Qc+lg3ompCHs95upauog8ZwpEuzwUgekN/u8cAsnk 7j7DOKyzKiAkqIze80pCAQa/ciYyS/ssi9Yrm4itcZ4w/6Ce21KOd9mtHytI7qV78X9JNy19dBA IuzclMKjjlvVOZKNC9UkqIqZRbnZtrHMdSF9lo3l6wuTF+AGOsgqOZmVvjd5ntdfKKk+iBWRYZ3 x5uZN8U3ujrFG6r0dLmuzmNmzd1y11cJOc1etLdlacrqtHZa2rDYEwHJTW/vFdw6L2XAloSzlrz vNpB2fUo09rUJarkhDl74ASAzRgwtPg8rGsLpIu25bOfdjquQkwqpm/ssCaqorks4/Pv0hDjkFb 31BpnWthsDv6kFefpHS/c6woYaLbPk X-Received: by 2002:a05:600c:6085:b0:490:ec79:3077 with SMTP id 5b1f17b1804b1-4923a99cee0mr33476775e9.16.1781785387019; Thu, 18 Jun 2026 05:23:07 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:06 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 13/30] libcamera: shaders: bayer_glr16_to_rgba.frag: Use bilinear filtering Date: Thu, 18 Jun 2026 13:22:26 +0100 Message-ID: <20260618122245.946138-14-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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 --- .../shaders/bayer_glr16_to_rgba.frag | 114 +++++++----------- 1 file changed, 43 insertions(+), 71 deletions(-) diff --git a/src/libcamera/shaders/bayer_glr16_to_rgba.frag b/src/libcamera/shaders/bayer_glr16_to_rgba.frag index f3883a82b..4a2e5af87 100644 --- a/src/libcamera/shaders/bayer_glr16_to_rgba.frag +++ b/src/libcamera/shaders/bayer_glr16_to_rgba.frag @@ -44,81 +44,53 @@ void main(void) { #define fetch(x, y) texture2D(tex_y, vec2(x, y)).r 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. + /* Which of the four CFA phases are we on (0 = even). Same as McGuire. */ vec2 alternate = mod(floor(center.zw), 2.0); + bool even_col = alternate.x < 1.0; + bool even_row = alternate.y < 1.0; - vec4 Dvec = vec4( - fetch(xCoord[1], yCoord[1]), // (-1,-1) - fetch(xCoord[1], yCoord[2]), // (-1, 1) - fetch(xCoord[2], yCoord[1]), // ( 1,-1) - fetch(xCoord[2], yCoord[2])); // ( 1, 1) - - vec4 PATTERN = (kC.xyz * C).xyzz; - - // Can also be a dot product with (1,1,1,1) on hardware where that is - // specially optimized. - // Equivalent to: D = Dvec[0] + Dvec[1] + Dvec[2] + Dvec[3]; - Dvec.xy += Dvec.zw; - Dvec.x += Dvec.y; - - vec4 value = vec4( - fetch(center.x, yCoord[0]), // ( 0,-2) - fetch(center.x, yCoord[1]), // ( 0,-1) - fetch(xCoord[0], center.y), // (-2, 0) - fetch(xCoord[1], center.y)); // (-1, 0) - + /* + * +----+----+----+ + * | D2 | A1 | D3 | + * +----+----+----+ + * | B0 | C | B1 | + * +----+----+----+ + * | D0 | A0 | D1 | + * +----+----+----+ + * + * patterns.x = (A0 + A1) / 2 vertical neighbours + * patterns.y = (B0 + B1) / 2 horizontal neighbours + * patterns.z = (A0+A1+B0+B1) / 4 cross average (green at R/B sites) + * patterns.w = (D0+D1+D2+D3) / 4 diagonal average (other colour at R/B sites) + * + * xCoord[1] = -1, xCoord[2] = +1, yCoord[1] = -1, yCoord[2] = +1 + * (xCoord[0]/[3] and yCoord[0]/[3] = +-2 are unused here; the vertex + * shader still emits them so the VS is identical to the McGuire path). + */ + vec4 patterns = vec4( + fetch(center.x, yCoord[1]), /* A0: ( 0,-1) */ + fetch(xCoord[1], center.y), /* B0: (-1, 0) */ + fetch(xCoord[1], yCoord[1]), /* D0: (-1,-1) */ + fetch(xCoord[2], yCoord[1])); /* D1: ( 1,-1) */ vec4 temp = vec4( - fetch(center.x, yCoord[3]), // ( 0, 2) - fetch(center.x, yCoord[2]), // ( 0, 1) - fetch(xCoord[3], center.y), // ( 2, 0) - fetch(xCoord[2], center.y)); // ( 1, 0) - - // Even the simplest compilers should be able to constant-fold these to - // avoid the division. - // Note that on scalar processors these constants force computation of some - // identical products twice. - const vec4 kA = vec4(-1.0, -1.5, 0.5, -1.0) / 8.0; - const vec4 kB = vec4( 2.0, 0.0, 0.0, 4.0) / 8.0; - const vec4 kD = vec4( 0.0, 2.0, -1.0, -1.0) / 8.0; - - // Conserve constant registers and take advantage of free swizzle on load - #define kE (kA.xywz) - #define kF (kB.xywz) - - value += temp; - - // There are five filter patterns (identity, cross, checker, - // theta, phi). Precompute the terms from all of them and then - // use swizzles to assign to color channels. - // - // Channel Matches - // x cross (e.g., EE G) - // y checker (e.g., EE B) - // z theta (e.g., EO R) - // w phi (e.g., EO R) - #define A (value[0]) - #define B (value[1]) - #define D (Dvec.x) - #define E (value[2]) - #define F (value[3]) - - // Avoid zero elements. On a scalar processor this saves two MADDs - // and it has no effect on a vector processor. - PATTERN.yzw += (kD.yz * D).xyy; - - PATTERN += (kA.xyz * A).xyzx + (kE.xyw * E).xyxz; - PATTERN.xw += kB.xw * B; - PATTERN.xz += kF.xz * F; - - 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)); + fetch(center.x, yCoord[2]), /* A1: ( 0, 1) */ + fetch(xCoord[2], center.y), /* B1: ( 1, 0) */ + fetch(xCoord[2], yCoord[2]), /* D3: ( 1, 1) */ + fetch(xCoord[1], yCoord[2])); /* D2: (-1, 1) */ + + patterns = (patterns + temp) * 0.5; + /* .x=(A0+A1)/2 .y=(B0+B1)/2 .z=(D0+D3)/2 .w=(D1+D2)/2 */ + patterns.w = (patterns.z + patterns.w) * 0.5; /* diagonal avg */ + patterns.z = (patterns.x + patterns.y) * 0.5; /* cross avg */ + + rgb = even_col ? + (even_row ? + vec3(C, patterns.zw) : + vec3(patterns.x, C, patterns.y)) : + (even_row ? + vec3(patterns.y, C, patterns.x) : + vec3(patterns.wz, C)); /* * CCM is a 3x3 in the format From patchwork Thu Jun 18 12:22:27 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26947 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 86C2FC330A for ; Thu, 18 Jun 2026 12:23:26 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9746B656D2; Thu, 18 Jun 2026 14:23:25 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="rcJylJk8"; dkim-atps=neutral Received: from mail-wm1-x32b.google.com (mail-wm1-x32b.google.com [IPv6:2a00:1450:4864:20::32b]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 50FAB62C70 for ; Thu, 18 Jun 2026 14:23:08 +0200 (CEST) Received: by mail-wm1-x32b.google.com with SMTP id 5b1f17b1804b1-490ace40f4bso8810835e9.3 for ; Thu, 18 Jun 2026 05:23:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785388; x=1782390188; 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=1GdJ+uFZzBx4VjBnnpCYkMDySJLH5xPvIqmnSSSWAlo=; b=rcJylJk8NM3QPIU/ACfBHgWLhOq128giTgFDLYX/DWHFGaGJhvMEf8ftKSqr71//Zp w45ZVz/eV3ey/qLEERi7oPIB78u3VG622amMJb1ricGgIwZovas2LRiFfVjFYFNWgXcy /OLfvLztsuh28fyqvLTTxbgcCQdYk4Qa4MB7P/KkcasEhf4zi7jaDI7OJr5wVX/qdcSa 2kNy4mp86z2teRIqZZg6Zopj2b3J0ijq9/Tc5Si5uAJWB0FVvGIEeiDyDVSHaZPO4odv sA4EEDNVYlmijpWAXHWE74+wvhNFdmAwyYLl+C230rYdC++7lGHGRzY+m6BBZddCUZko 5Gmg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785388; x=1782390188; 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=1GdJ+uFZzBx4VjBnnpCYkMDySJLH5xPvIqmnSSSWAlo=; b=jMFkK+EXXO9voF0PDju9r6jp8xxxVkN79Jig5EN41FYJkcx4nquEiTBvTU55vXO8uj rublQZZgRZTPZcBRul/Je/OQuUsfr78UfGujHPTYfq4FFO8deTaVrxMvNOjUrBLlXYUC Lubdm/k7jWtNv/95VaLHeswQZnaivz9Dme9xdB5EZEZ9BCmzH3+4AFZD1j3ncYB64oS1 5jHk8DUN8PijLbHjWGPSroz1K9GWu6CSXLd5QUFtLVvtcxd0ksplGrHqqnqLbmdWR69F mRlo1iEm6algX7xbiNTpxWzc7+aqjPovY7Bqm7Zygy4ar9m9jkAJ9piB6wfZMJX+Q9k6 Nx7w== X-Gm-Message-State: AOJu0YyIi6/DIkDd5lRHKRZEf8FEfJJ2HpnXM4cRW+13TB86BH+oPkPT pzqJ13YNxyky+5l6IOMq7mHGcMk1T1tnmVGAM0v3Z1NHnQucYn6+4c6ckSKmKVrUqlDRZ1tlBmr sXdp6ZxE= X-Gm-Gg: AfdE7ckXq0tBZbJJi9Uqx2MJPDfNi5ZWZTJKVLo70n6Z+ngCPjpHbBIeOFajX/ivuIP lfIIw1yBW0ojcFJGowCqWG122wX+WD37mGvbGAaicmZAtEqzmqTAodg+v45po9h+evbHZWNanky 4jExOGhjRokNXkOSKMeLmx5B6wWz/oVMQWWLfUvP7nrXWABISLtWfbMadOr/dW1SUwRlO+YTOBl nwaNGWN2uoaFcqTdeiywLJcNOf8tI3qaPIzNPkHP/MnXGgJrQlvNIyW6hSVVPf+TFhpfErFhyd+ DT6dIKZEifHJaMf+mhc7DMOEh+pjICWnghOTQtyhN6h6Ksr/ttFv5is66f41jvXY3MuJbUjhTXm J4aLek4N3orO9K4OwIZB+DxGt/eYhSB3/8/saCMYpYoQlwvLtbuqQVj2qnCRkB4bAzRAqemAA/p WxPEu1ZZjQFa+vCVU9tt4CckYLVQrk X-Received: by 2002:a05:600c:630e:b0:490:d38c:7836 with SMTP id 5b1f17b1804b1-492381e8599mr54707075e9.3.1781785387785; Thu, 18 Jun 2026 05:23:07 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:07 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 14/30] libcamera: software_isp: gpu: Add GpuIspShaderPassBlcNormalise Date: Thu, 18 Jun 2026 13:22:27 +0100 Message-ID: <20260618122245.946138-15-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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 GpuIspShaderPassBlcNormalise which takes existing logic to select fragment/vertex shaders based on the incoming CSI2 packign but, select new shaders whose task in life is to apply our blacklevel normalisation step and output a normalised 16 bit float. The unpacked 16f will then be fed into the existing unpacked demosiac shader. This patch compiles but doesn't do anything useful yet. Signed-off-by: Bryan O'Donoghue --- ...gpu_pipeline_shader_pass_blc_normalise.cpp | 228 ++++++++++++++++++ .../gpu_pipeline_shader_pass_blc_normalise.h | 55 +++++ src/libcamera/software_isp/meson.build | 1 + 3 files changed, 284 insertions(+) create mode 100644 src/libcamera/software_isp/gpu_pipeline_shader_pass_blc_normalise.cpp create mode 100644 src/libcamera/software_isp/gpu_pipeline_shader_pass_blc_normalise.h diff --git a/src/libcamera/software_isp/gpu_pipeline_shader_pass_blc_normalise.cpp b/src/libcamera/software_isp/gpu_pipeline_shader_pass_blc_normalise.cpp new file mode 100644 index 000000000..8e8d7b9d6 --- /dev/null +++ b/src/libcamera/software_isp/gpu_pipeline_shader_pass_blc_normalise.cpp @@ -0,0 +1,228 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2026, Linaro Ltd + * + * Authors: + * Bryan O'Donoghue + * + * GpuIspShaderPassBlcNormalise base class + */ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "libcamera/internal/bayer_format.h" +#include "libcamera/internal/egl.h" +#include "libcamera/internal/software_isp/debayer_params.h" + +#include "gpu_pipeline_shader_pass_blc_normalise.h" + +/** + * \file software_isp.cpp + * \brief Simple software ISP implementation + */ + +namespace libcamera { + +LOG_DEFINE_CATEGORY(GpuShaderBlc) + +int GpuIspShaderPassBlcNormalise::start() +{ + return 0; +} + +void GpuIspShaderPassBlcNormalise::stop() +{ +} + +int GpuIspShaderPassBlcNormalise::selectShaders(struct ShaderConfig &shaderCfg, [[maybe_unused]]PixelFormat &inputFormat, [[maybe_unused]]PixelFormat &outputFormat) +{ + /* Pixel location parameters */ + glFormat_ = GL_LUMINANCE; + bytesPerPixel_ = 1; + shaderStridePixels_ = passInputCfg_.stride; + + /* Shader selection */ + switch (inputFormat) { + case libcamera::formats::SBGGR8: + case libcamera::formats::SGBRG8: + case libcamera::formats::SGRBG8: + case libcamera::formats::SRGGB8: + shaderCfg.fragmentShaderData = bayer_unpacked_to_blc_glr16f_frag; + shaderCfg.fragmentShaderDataLen = bayer_unpacked_to_blc_glr16f_frag_len; + shaderCfg.vertexShaderData = bayer_unpacked_vert; + shaderCfg.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(shaderCfg.shaderEnv, "#define RAW10P"); + if (BayerFormat::fromPixelFormat(inputFormat).packing == BayerFormat::Packing::None) { + shaderCfg.fragmentShaderData = bayer_unpacked_to_blc_glr16f_frag; + shaderCfg.fragmentShaderDataLen = bayer_unpacked_to_blc_glr16f_frag_len; + shaderCfg.vertexShaderData = bayer_unpacked_vert; + shaderCfg.vertexShaderDataLen = bayer_unpacked_vert_len; + glFormat_ = GL_RG; + bytesPerPixel_ = 2; + } else { + shaderCfg.fragmentShaderData = bayer_1x_packed_to_blc_glr16f_frag; + shaderCfg.fragmentShaderDataLen = bayer_1x_packed_to_blc_glr16f_frag_len; + shaderCfg.vertexShaderData = identity_vert; + shaderCfg.vertexShaderDataLen = identity_vert_len; + shaderStridePixels_ = passInputCfg_.size.width; + } + break; + case libcamera::formats::SBGGR12_CSI2P: + case libcamera::formats::SGBRG12_CSI2P: + case libcamera::formats::SGRBG12_CSI2P: + case libcamera::formats::SRGGB12_CSI2P: + egl_.pushEnv(shaderCfg.shaderEnv, "#define RAW12P"); + if (BayerFormat::fromPixelFormat(inputFormat).packing == BayerFormat::Packing::None) { + shaderCfg.fragmentShaderData = bayer_unpacked_to_blc_glr16f_frag; + shaderCfg.fragmentShaderDataLen = bayer_unpacked_to_blc_glr16f_frag_len; + shaderCfg.vertexShaderData = bayer_unpacked_vert; + shaderCfg.vertexShaderDataLen = bayer_unpacked_vert_len; + glFormat_ = GL_RG; + bytesPerPixel_ = 2; + } else { + shaderCfg.fragmentShaderData = bayer_1x_packed_to_blc_glr16f_frag; + shaderCfg.fragmentShaderDataLen = bayer_1x_packed_to_blc_glr16f_frag_len; + shaderCfg.vertexShaderData = identity_vert; + shaderCfg.vertexShaderDataLen = identity_vert_len; + shaderStridePixels_ = passInputCfg_.size.width; + } + break; + }; + + return 0; +} + +int GpuIspShaderPassBlcNormalise::getShaderVariableLocations(void) +{ + attributeVertex_ = glGetAttribLocation(programId_, "vertexIn"); + attributeTexture_ = glGetAttribLocation(programId_, "textureIn"); + textureUniformBayerDataIn_ = glGetUniformLocation(programId_, "tex_y"); + 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(GpuShaderBlc, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ + << " tex_y " << textureUniformBayerDataIn_ + << " tex_step " << textureUniformStep_ + << " tex_size " << textureUniformSize_ + << " stride_factor " << textureUniformStrideFactor_ + << " tex_bayer_first_red " << textureUniformBayerFirstRed_ + << " proj_matrix " << textureUniformProjMatrix_; + + /* TODO: trap errors */ + return 0; +} + +void GpuIspShaderPassBlcNormalise::setShaderVariableValues(const DebayerParams ¶ms, eGLImage &eglImageIn) +{ + /* + * 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)passInputCfg_.size.width, + (GLfloat)passInputCfg_.size.height }; + GLfloat Step[] = { static_cast(bytesPerPixel_) / (passInputCfg_.stride - 1), + 1.0f / (passInputCfg_.size.height - 1) }; + GLfloat Stride = (GLfloat)passInputCfg_.size.width / (shaderStridePixels_ / bytesPerPixel_); + /* + * Scale input to output size, keeping the aspect ratio and preferring + * cropping over black bars. + */ + GLfloat scale = std::max((GLfloat)passInputCfg_.window.width / passInputCfg_.size.width, + (GLfloat)passInputCfg_.window.height / passInputCfg_.size.height); + GLfloat trans = -(1.0f - scale); + GLfloat projMatrix[] = { + scale, 0, 0, 0, + 0, scale, 0, 0, + 0, 0, 1, 0, + trans, trans, 0, 1 + }; + /* Static const coordinates */ + static const GLfloat vcoordinates[4][2] = { + { -1.0f, -1.0f }, + { -1.0f, +1.0f }, + { +1.0f, +1.0f }, + { +1.0f, -1.0f }, + }; + static const GLfloat tcoordinates[4][2] = { + { 0.0f, 0.0f }, + { 0.0f, 1.0f }, + { 1.0f, 1.0f }, + { 1.0f, 0.0f }, + }; + + /* vertexIn - bayer_8.vert */ + glEnableVertexAttribArray(attributeVertex_); + glVertexAttribPointer(attributeVertex_, 2, GL_FLOAT, GL_TRUE, + 2 * sizeof(GLfloat), vcoordinates); + + /* textureIn - bayer_8.vert */ + glEnableVertexAttribArray(attributeTexture_); + glVertexAttribPointer(attributeTexture_, 2, GL_FLOAT, GL_TRUE, + 2 * sizeof(GLfloat), tcoordinates); + + /* + * Set the sampler2D to the respective texture unit for each texutre + * To simultaneously sample multiple textures we need to use multiple + * texture units + */ + glUniform1i(textureUniformBayerDataIn_, eglImageIn.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(GpuShaderBlc, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ + << " tex_y " << textureUniformBayerDataIn_ + << " tex_step " << textureUniformStep_ + << " tex_size " << textureUniformSize_ + << " stride_factor " << textureUniformStrideFactor_ + << " tex_bayer_first_red " << textureUniformBayerFirstRed_; + + LOG(GpuShaderBlc, 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_; + + /* + * 0 = Red, 1 = Green, 2 = Blue + */ + glUniform3f(blackLevelUniformDataIn_, params.blackLevel[0], params.blackLevel[1], params.blackLevel[2]); + LOG(GpuShaderBlc, Debug) << " blackLevelUniformDataIn_ " << blackLevelUniformDataIn_ << " data " << params.blackLevel; + + return; +} + +} /* namespace libcamera */ diff --git a/src/libcamera/software_isp/gpu_pipeline_shader_pass_blc_normalise.h b/src/libcamera/software_isp/gpu_pipeline_shader_pass_blc_normalise.h new file mode 100644 index 000000000..64ea2fc11 --- /dev/null +++ b/src/libcamera/software_isp/gpu_pipeline_shader_pass_blc_normalise.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2026, Linaro Ltd + * + * Authors: + * Bryan O'Donoghue + * + * GpuIspPipelineShaderPass base class + */ + +#pragma once + +#include + +#include +#include +#include + +#include +#include + +#include "libcamera/internal/egl.h" +#include "libcamera/internal/software_isp/debayer_params.h" + +#include "gpu_pipeline_shader_pass.h" + +namespace libcamera { + +class FrameBuffer; + +class GpuIspShaderPassBlcNormalise : public GpuIspShaderPass +{ +public: + GpuIspShaderPassBlcNormalise(eGL& egl) : GpuIspShaderPass(egl) {}; + + int start(); + void stop(); + + /* Things that every ISP pipeline pass will need to do */ + int getShaderVariableLocations(void); + void setShaderVariableValues(const DebayerParams ¶ms, eGLImage &eglImageIn); + int selectShaders(struct ShaderConfig &shaderCfg, PixelFormat &inputFormat, PixelFormat &outputFormat); + const char *name() const override { return "GpuIspShaderPassBlcNormalise"; } + +private: + /* Shader parameters */ + GLint textureUniformStep_; + GLint textureUniformSize_; + + /* Black Level compensation */ + GLint blackLevelUniformDataIn_; + +}; + +} /* namespace libcamera */ diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build index 3e7d21318..e9caa3629 100644 --- a/src/libcamera/software_isp/meson.build +++ b/src/libcamera/software_isp/meson.build @@ -34,6 +34,7 @@ if mesa_works 'software_isp_pipeline_gpu.cpp', 'gpu_pipeline_shader_pass.cpp', 'gpu_pipeline_shader_pass_demosiac.cpp', + 'gpu_pipeline_shader_pass_blc_normalise.cpp', ]) libcamera_deps += [ libegl, From patchwork Thu Jun 18 12:22:28 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26948 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 89704C330F for ; Thu, 18 Jun 2026 12:23:27 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id DB047656C7; Thu, 18 Jun 2026 14:23:26 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="ahpWDs48"; 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 BE48562C7C for ; Thu, 18 Jun 2026 14:23:09 +0200 (CEST) Received: by mail-wm1-x32a.google.com with SMTP id 5b1f17b1804b1-490ae94a89eso6313405e9.1 for ; Thu, 18 Jun 2026 05:23:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785389; x=1782390189; 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=Q1uKl0CNvdgfWO0Mn4aUOTwFartpNuJZP4m4+2UlupY=; b=ahpWDs489/0GvtY4G99mdVZPs6nesEQFQi5LVRL8NuULOU7mXtoj1kNvm6n+aAeuZJ c0JqrHZ/G3gdISLDxn57t/J/XnBCKxSGghFhfYo3M/7+gbvxPh+1tv30Igp/IsKzOQGH DVhatu3KLhivAvyb5Baho8OmWkWwNA0o7F+MQhLJK7FRkKHDacG0Brn3bDoVEEgUNOWB fp5t4EDNrExSHR3w83H8MV6K+julCQmtuFLRGR424c4aEEgBDZqpO4QHUvtzmmOjaZp5 GjQDgd1GDPQEUve+dshwr2kj8HvndbGEHrlxmjfWqlRa+dPnMYxUOQ9464g1HgdSrrYy ZpDg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785389; x=1782390189; 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=Q1uKl0CNvdgfWO0Mn4aUOTwFartpNuJZP4m4+2UlupY=; b=eMcrleTd9oTM4G0XFucIXQZeU6oWva8Sc+/ncwAMNWhGZey44FkLP8R4+JGI+6peIH ve4fHy8wmIUH25W8gw6n6ckRQ4e9qrBI9HRNHheoj5wJTtZJQGgnggGEnjKx+B8HPKnk fBpqJ5SdaxtoJ3NAnYbw8j91k7hgZUSgMGS2mgos6J3P6SArDNDFnwjutAQjYaCQGDRe Qf2eXZq7szcNb5HsBtjQ0g0ao18wjOwAPN0VdpoN5BSFhChF3eydCX6bkgA425wgRUFp 8EI5qhYoUa5XdmwMJThOPUYO7R0TU5tIQCl3dAA/qH9pgYcOPXLqCsKmDR2th7z34vkD uHWA== X-Gm-Message-State: AOJu0YxxOG4k/H2zHcWHgaze9kyR1zRhwYPdmjiHVau5iDOwlD7Krym9 BL0giYe9F97ovFoF0Cu66y2KkfiDQpfU/5+Wozfold7Jek3T0fNv0hncWSn6G6Acnb+00qoVuVI TN4vzwJE= X-Gm-Gg: AfdE7cllGKVf75eQpsl40gNTIlJv+QbGM2Pscq49TMzftERFyvKKeGar1iyZu0t9OxM Zk3H1VnzrGB5jmTspuLGsdPBdyZickwtNdhRf1ePTiHN2rTKnB8C9T0gyB0XnOJ1B5N/m+daHgO jcw6hAiCcvj0EbjBci7qYr6I41QzMET9IT9gOZ3otf9RhX7GSskClY88nFoNRAstFa/JDoB7s6v cugHc+tRLuKrzg2PKJyoIH+55qnK4PC2gGmqo8ZTfnL2Labr9NHwa1/r06I1udbBVoixDG7jzs7 LyqkbQh454KkOYBPcpLAgMsVJR1rRP7xOnQzIOyj6MlMbtZgLDuNJFrXMM4YNZgEvBBGWwekYd+ d27fnKICU2Xx4YJOEFxSZaPaMtJMwTfrAQgK8auyoN8HN+0Ks/ybnbYZtLTM+ORuDJ558hdz9FG ZjLT/9hSeP1Kd37qgvAOc7PK25QgaX X-Received: by 2002:a05:600c:19d3:b0:490:ba0a:1178 with SMTP id 5b1f17b1804b1-49238226533mr53189805e9.28.1781785389270; Thu, 18 Jun 2026 05:23:09 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:08 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 15/30] libcamera: software_isp: egl: Extend eGL::createTexture2D to understand floats Date: Thu, 18 Jun 2026 13:22:28 +0100 Message-ID: <20260618122245.946138-16-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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/libcamera/egl.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index 4da335a53..a5e59c09c 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -264,13 +264,29 @@ int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd) */ void eGL::createTexture2D(eGLImage &eglImage, void *data) { + GLenum format; + GLenum type = GL_UNSIGNED_BYTE; + ASSERT(tid_ == Thread::currentId()); glActiveTexture(eglImage.texture_unit_); glBindTexture(GL_TEXTURE_2D, eglImage.texture_); + switch (eglImage.format_) { + case GL_R16F: + format = GL_RED; + type = GL_HALF_FLOAT; + break; + case GL_RG8: + format = GL_RG; + break; + case GL_LUMINANCE: + format = GL_LUMINANCE; + break; + } + // Generate texture, bind, associate image to texture, configure, unbind - glTexImage2D(GL_TEXTURE_2D, 0, eglImage.format_, eglImage.width_, eglImage.height_, 0, eglImage.format_, GL_UNSIGNED_BYTE, data); + glTexImage2D(GL_TEXTURE_2D, 0, eglImage.format_, eglImage.width_, eglImage.height_, 0, format, type, data); // Nearest filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); From patchwork Thu Jun 18 12:22:29 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26949 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 7EF92C3302 for ; Thu, 18 Jun 2026 12:23:28 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D353C656CD; Thu, 18 Jun 2026 14:23:27 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="TDO5eJxD"; dkim-atps=neutral Received: from mail-wr1-x42a.google.com (mail-wr1-x42a.google.com [IPv6:2a00:1450:4864:20::42a]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B24F5629DE for ; Thu, 18 Jun 2026 14:23:10 +0200 (CEST) Received: by mail-wr1-x42a.google.com with SMTP id ffacd0b85a97d-463b2f6fc9dso914691f8f.2 for ; Thu, 18 Jun 2026 05:23:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785390; x=1782390190; 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=TennfyYde0cUPWna4tWRZtcdLSeadO5Wc+toCkxV/Rc=; b=TDO5eJxDkTcr2ww5ycurhwOWwp+vsXVcF6Pj1PVzZgxGd1T8LSekSSB47j12EMoZVL Myc8l2BQz1bqgh6BK8RDDcuk1ji8V+6+t6gfNRW+YvcWoOyhPbXtw6MXMP+7DN8YzQbS hccXea3rjJy2f2RwT035d8VnrK7NEjWRkbiDiRwGzGL0gvA/mnwUtkK1KZThqwu+oDzE 5TxyrgTQTcrnDXJLWpkBKx9wC+h+VA9DobAYSmBwQgEeUw70GNTAvx2PCqTWmMf0eErr 9lr9K1Xi4T5RsZHj1Zgnsk8HoSQqYNn6zNmNO+lDVkAGO2kq3MV2rO14a1EpFUycrjyL r6XA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785390; x=1782390190; 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=TennfyYde0cUPWna4tWRZtcdLSeadO5Wc+toCkxV/Rc=; b=H5w+Da9ewY3W5kMccbAiePrx/2FjbKQRUdhgVsb/Xwbv/Cw4mPGvxRpaiFBrRn4AOk 0wFlThcEaolUQdljxYEV69Rs5gcnSLX9fDIHzEJh22IuvsvbBSYWmSn7sB7Pz/adCU+g sjrR51p3iYMcMsSduIMIRs4CjshcNE79R6PzpNtZl5cbEhBrz5Ybp8uKs1iMZfFQRhaK JOjopB4cfTw43AzMRGTcu5POrXdC8IOwqEBmsn0hTfsQ8zu91Meb14DN0zO7ouBCdR9h 2KI1p1yQT1h0B7NTR9ejr6DcymgG9cClNNC6lUwqtht4sqbt3tYtK5veyLnFOByk1GLa EzNg== X-Gm-Message-State: AOJu0YxI1U1eUB5ExWf2nF0RAqLXyGi+kUrHIjas20PktPF+e3q9SklE Hq+x6R4zuV8WIuz+d1bDQN8QcRt4y6gB28hep8lKKKv5WTeKya5gdimUZlKhhvrWx+zr+R9Lmu4 J6gcps40= X-Gm-Gg: AfdE7ckbWAuQpxNqkQFY0PvdAosFcKWpd4rsUutBibuTl1BDPAwXeMFdACiAN9csrp+ trfiXgSqwTTlgC3FLdKJoDdxhi5epfCxmSEezy3F3jgWBqmaLwue3sLipAdg3GOubNPMWuBZ6Wg hzPLkOogUrglIc8oHHN0p3ilnm+CU54L1fV4qe5RhKSkiPy3kAT5Lnq2a+JFIDpa1VMt9gdh2gZ MR3/Q8r7cd2mxGM0g/lHYH0hVcfjY92fRFz5oOlg+fmcNwcES91ddAOe7W4pWA4NbJSERW9FzDR nF30dlpU/9PouYOr/wkmwx4Ic9hShGtJmXaGDCaWYEMaMVH74T86z5hgr26AzcoP0ZqcpB2/IVC gZ3I4ZJZbh2cfWJsKRcVQjX+iGU6KxOnLob3w5cBOkJXWnIKXtZ83pxMcVh688FuI8V/NJUxliH AWi9Qhj4yTy2K22sIbzQ//uJU6Y3XAJDo4H5nZjk0= X-Received: by 2002:a05:600c:e54a:10b0:490:e104:7943 with SMTP id 5b1f17b1804b1-492333e294dmr102230605e9.18.1781785390069; Thu, 18 Jun 2026 05:23:10 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:09 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 16/30] libcamera: software_isp: egl: Move to GLES 3.0 Date: Thu, 18 Jun 2026 13:22:29 +0100 Message-ID: <20260618122245.946138-17-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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" To make textures of floats we need GLES 3.0. Signed-off-by: Bryan O'Donoghue --- include/libcamera/internal/egl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h index d88617afa..3956c6669 100644 --- a/include/libcamera/internal/egl.h +++ b/include/libcamera/internal/egl.h @@ -26,7 +26,7 @@ #include #include #define GL_GLEXT_PROTOTYPES -#include +#include #include namespace libcamera { From patchwork Thu Jun 18 12:22:30 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26950 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 CF5BFC3310 for ; Thu, 18 Jun 2026 12:23:29 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5FCF262E9D; Thu, 18 Jun 2026 14:23:29 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="afzoI4Ez"; 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 56D0362C6D for ; Thu, 18 Jun 2026 14:23:11 +0200 (CEST) Received: by mail-wr1-x42e.google.com with SMTP id ffacd0b85a97d-45ef189aa1cso661000f8f.0 for ; Thu, 18 Jun 2026 05:23:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785391; x=1782390191; 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=CfDeIMUwfSa5hEgn9yj8YVav8Kysxh3e9PDp4yN9qns=; b=afzoI4EzNHBdsDG24+FQzAKDI+ws0gUawVLkK/Yjz0kMgqg1SrEiGNwuGudUavr2eT wCqjAsB7vDJhvlFh5JYE/HNuKfhhTlMUx0AmX9xMD1i53MLEUY97udDHATejl9EMB/ov jFwNwW2E/tPO0XKAvlLZL5hzP9chy3/L6l266O3/j4oxJIjKozRi20FnbQmhb5tZSy6a rIQYP9mCvK598+pb8hvy84FBgpNXEhLg/Z+dz12WqMlTR7kPOExym8aMy7v5EB9vvN1l AIahiGnwV66MvZQHgFw7aB/P5Mzvb8O/IDHY/binGcC24OzcJ291FTJqQBZeRiC01q8y xFhA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785391; x=1782390191; 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=CfDeIMUwfSa5hEgn9yj8YVav8Kysxh3e9PDp4yN9qns=; b=IWOeKVj929Qw3qCohbG29qGFB/sajZpQW1zvPmb8bIZNOGm8/AG1HNftyhZbMRr7k1 5w1dzTIN5G+dI4AjXEo/CiJZWaPzo9gq1uJ540R3u9j8lEZkWp0Rpalb8JdkAH/Ol9fk Vj8h4sHLBycwHuyR8iwqLLs3CvBALQEkKM6vpag5QccAVURzQmGKUNBTP4mWGtoAUQyd SyvT5cRrVDET9qHag1cWeLLz48xWQz2WyaBccb4E5qhu24pY0uz72T1ZkvCPaxNqs3/4 WO6+VLukR9zcd4y/4isqgwXQv2RBHpTZEMifh3y0ev/sOujlf4AWJQtSG8cX744vF2yh 06Fw== X-Gm-Message-State: AOJu0Yy9o9ayTdPJumGuX+CvVQFMj5gsu4VkmmYY23XitXb+Wju/9ICP UwS3WkkGL2Ix8yMHXwoYnoWAJXNSxzWU6s+Q3GgZKcE2KC+x+PKX+twToeiKjhRvWKKtM+DyitG zW8uJAL8= X-Gm-Gg: AfdE7cnE2GPRDbc1oOWoL2v1lx1SBtNXN+0iUf4tfDEn1KUq9vIjydCHoq+R4dcadL3 SqBEFJgUBvzlX2m7ikqDEVgmbYQR/bCRBAUb/WAEEoFodl0Z9ywe4j1ZQmaf5x1N+N1tldYIJLp MdnCJ0uO6XKhsXyOpmFM6ha2zlQaK6FydoNh3tMjAI3xFExxjZxcYKvqhwc65jeD0/g5YiZMLeg dfh+4ze+wLS2ncGVdqd/mXVZQiEsLVz5bScDpwWIJZZOM0CdUKQ8TL10OC72lTaV55mEw3C83s2 MyZhtAKdk6JewgwH3ru43aGi+jSoq3r5KX4EOQqwJRyeLT1GYRJHNoYWKY3FfI3xTw8/2t2iuBZ VfS0uNvi8nin+97+LI5tWqnIuaddH4ZZcUUsLBQbbGuWvaIcklhRaZAwrUj/6DurXF0kg/nK5Og 9UfRICFnL0jk/HLWSuJpa7SZeRfYJN X-Received: by 2002:a05:600c:4ed4:b0:490:da12:f1fa with SMTP id 5b1f17b1804b1-492333ecc2bmr143344365e9.31.1781785390776; Thu, 18 Jun 2026 05:23:10 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:10 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 17/30] libcamera: software_isp: egl: Rename createTexture2D to createInputTexture2D Date: Thu, 18 Jun 2026 13:22:30 +0100 Message-ID: <20260618122245.946138-18-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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" Right now this routine makes a texture from a supplied data-buffer. It should have a more descriptive and accurate name. Signed-off-by: Bryan O'Donoghue --- include/libcamera/internal/egl.h | 2 +- src/libcamera/egl.cpp | 2 +- src/libcamera/software_isp/software_isp_pipeline_gpu.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h index 3956c6669..182a4dc55 100644 --- a/include/libcamera/internal/egl.h +++ b/include/libcamera/internal/egl.h @@ -106,7 +106,7 @@ public: int createInputDMABufTexture2D(eGLImage &eglImage, int fd); int createOutputDMABufTexture2D(eGLImage &eglImage, int fd); - void createTexture2D(eGLImage &eglImage, void *data); + void createInputTexture2D(eGLImage &eglImage, void *data); int attachTextureToFBO(eGLImage &eglImage); diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index a5e59c09c..ffaa6bc49 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -262,7 +262,7 @@ int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd) * is useful for uploading static data like lookup tables or uniform color * matrices to the GPU. */ -void eGL::createTexture2D(eGLImage &eglImage, void *data) +void eGL::createInputTexture2D(eGLImage &eglImage, void *data) { GLenum format; GLenum type = GL_UNSIGNED_BYTE; diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp index 7de77319d..8bafd70f8 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp @@ -247,7 +247,7 @@ int SoftwareIspPipelineGpu::processGPU(FrameBuffer *input, FrameBuffer *output, LOG(Debayer, Error) << "mmap-ing buffer(s) failed"; return -ENODEV; } - egl_.createTexture2D(*eglImageBayerIn_, inMapped->value().planes()[0].data()); + egl_.createInputTexture2D(*eglImageBayerIn_, inMapped->value().planes()[0].data()); } /* Generate the output render framebuffer as render to texture */ From patchwork Thu Jun 18 12:22:31 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26952 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 ADC64C3318 for ; Thu, 18 Jun 2026 12:23:32 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D492162E9D; Thu, 18 Jun 2026 14:23:31 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="CyL8twYJ"; 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 1275C62C72 for ; Thu, 18 Jun 2026 14:23:12 +0200 (CEST) Received: by mail-wm1-x329.google.com with SMTP id 5b1f17b1804b1-490ae94a89eso6313725e9.1 for ; Thu, 18 Jun 2026 05:23:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785391; x=1782390191; 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=qdWOEHoJeTzCOxcBywajFodiO258hC6oLj6gEahZr7s=; b=CyL8twYJUab2VJlaWrA+3Zx5CqKxDi53guCoQbEVNWTZ6bor2YumV4gxLekQMhZUfx XJSV3MJgKx6DqjlPTCF8sjbwkWi6ulz8nbg5T8dUYRPcLHMcj83UNcD8y9QzmbSj5UCS mpcSN8K30QePfI5DXB/Br5qJJ5P3y4eBBSoFBQF28nTtd6SOxuusXzIWAWUaauCBVkp8 sybdYNAlJLU/UsC/HmV7W27hIi7PdfjWjaznyWsvMbXeHPMKz4YACeAEpnhvDlrf2wNQ WFzfp2rK/KYgftqF/knd+nJylSztYvsdU+tH07uICWjz80m/REGlvXAnjI8TZA01Hro0 ZdjA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785391; x=1782390191; 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=qdWOEHoJeTzCOxcBywajFodiO258hC6oLj6gEahZr7s=; b=qbYxRO1mCOCeSdpTrVNLevd+1jaS+HJub4DELUzqc+OrvAm1OwTWDDATBWun3+69Vd udtq3fUxOyMq9gr/c625PXz/DYv3yz8FOgKfNEWTlqfG/QHmZDEm7XW5fI3XGs1DYKqb WugzUzz0S93yncFxE0R3QUD49UImCxtSWwRIZwiptP4CHKKDnJN/IWoBmmRSwkBzYs4o XfUqpyLgOi0/hSGU+wj2PRT4XB9SRBMPl74AnsQGl7/pTmSp/u9ensJzJVxQXQwnzG2+ WRSFXnZ0DatNRS07dPWLWHI2jf1NydOAY39wIlLFn5hxL+AVzHtepTOck3pqVZ6sOLXz PwnQ== X-Gm-Message-State: AOJu0YyOLk/NwrDCKJDPS7Rl08od3mDxh2/RiIGAs64nf8mRlzlrK9ar vr1tje1x6Lh5BPgOvO1K9K6RXx/iIMQZh0Iqs1mpRaiNsLIZXZNWtn56NhN1PCv6xlKH+bqWAEk 0Z8Ln3yA= X-Gm-Gg: AfdE7cklJWJoZGQK1B0EC3FPzhMcmCG4/4kfsiKHojA/eGUBcu+ZZcY9q1ytg9UurBL fRHhtBXueE6qVq60V7j09f30vOi4Bp6uIw7rJoT8jGIPhe2iXBBiDji6yTOa+mkEw7TYKF/bR8I ZJUFgFKpsdP9qV6OYosRy88tNI8RhUIdB6IClsKDBDj/XeAnKaPeoiyHK6IyYjCpmdIqmTG3b53 sj95vzAZ+bUvlSaY7PML8Pi5yxN2bLNk6+M/qV9Hu59zRSoIJr2Z0diDJr3J3GhEEnWO3UaU2Qx WfV9pUVxtobnN1FHR1zVFE3S59SW9+iGnuSWjTywvhr0SJcnne67qOJDJmHukQqCL4pVAekCalE 41zoFqkudwIdUHnAfoCQP5VrxWIlt2FHDx/DjxFVQ+VDo366hzAwa7+FMuHFoK8A6yA/F/zpOY8 juq0xp28rj4PHRWT/zeWZu+Cktq5zs X-Received: by 2002:a05:600c:a104:b0:490:e170:b7ee with SMTP id 5b1f17b1804b1-4923821be52mr38526925e9.17.1781785391513; Thu, 18 Jun 2026 05:23:11 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:11 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 18/30] libcamera: software_isp: egl: Use Texture Unit 3 for final output texture Date: Thu, 18 Jun 2026 13:22:31 +0100 Message-ID: <20260618122245.946138-19-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-1-bryan.odonoghue@linaro.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" We will use ping/pong buffers as intermediary steps in the GPUISP pipeline. The last texture should logically be texture unit #3. TEXTURE0 = Input TEXTURE1 = Ping TEXTURE2 = Pong TEXTURE3 = Output We don't have ping/pong yet but in preparation make the small change to TEXTURE3 for the existing output framebuffer. Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/software_isp_pipeline_gpu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp index 8bafd70f8..458b65854 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp @@ -336,7 +336,7 @@ int SoftwareIspPipelineGpu::start() eglImageBayerIn_ = std::make_unique(gpuIspShaderPassDemosiac_.glFormat_, inputConfig_.stride / gpuIspShaderPassDemosiac_.getBytesPerPixel(), height_, inputConfig_.stride, GL_TEXTURE0, 0); /* Texture we will render to */ - eglImageRGBAOut_ = std::make_unique(GL_RGBA, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE1, 1); + eglImageRGBAOut_ = std::make_unique(GL_RGBA, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE3, 3); return 0; } From patchwork Thu Jun 18 12:22:32 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26951 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 C3A33C3316 for ; Thu, 18 Jun 2026 12:23:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 29689656D4; Thu, 18 Jun 2026 14:23:30 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="FqAEfm7/"; 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 BD98E629A8 for ; Thu, 18 Jun 2026 14:23:12 +0200 (CEST) Received: by mail-wm1-x330.google.com with SMTP id 5b1f17b1804b1-4905529b933so7824735e9.0 for ; Thu, 18 Jun 2026 05:23:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785392; x=1782390192; 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=wZj9cpOKT3N+cE5reFIhRD3D2OdcaGGh41+idBriHE4=; b=FqAEfm7/PvA1u8bGrQvB2QkFzeHx5L1axDBduWEEyzrYL46SkNMN+f4nErRrMox+CJ oAU6kZ8yNZw/94h6yMzbndpKYC5KzzzzX8MPoU1fYypoZ10T5RatUBfJQyWjoV29C2ei 6LSYZYc2tE7kBF7mkJM/sxqfQXidDxu2mcs7sV/M1uCvlJPq+6bDYC67M7FF/mea4/Rz P67JoYcU3qG+AugZKAVbnXilGuKadEXpQ4n33/9IJ5T2XrXJ1oB0B14to0CqvfwUfe9J xNqhhdDn4aQhq4vy824jgU9vFgTIyWKCXYKxIQLHyhOganXVnmtHQqZoSG9qpgBOHYV/ BwJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785392; x=1782390192; 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=wZj9cpOKT3N+cE5reFIhRD3D2OdcaGGh41+idBriHE4=; b=qynC+Iw4Sj+0MEX7f9p7uRsjZ6Or+3eJ85vskzymafMtWqTHX2Zfeh0AnwuGyq5CS7 psSzavEqn9z/yw8/QbBFm9zPZ2WKq9Wbpxxq50zwJeaICycU75PD/Fbjyp0fFe3GAL5H f/dz7gufYfzqh7GCWLb7VS2yhKc1YNEuPNQ7nGouug43zhETHkcBXONIAiIoPA4HwIzQ B0TuvyvQ8mOOltLvhp3/w+Yopn9W6GtOJsid+2jCHgrUbrGK4Lr9ZOEOLmAhtq55gtWO eVFwPay2SZhAxmi/2T0agh9oJ7QyYXqHWVP4kPQJX7UOd+3Q4UuLbJAJ7SZ/X63CqxQL a6iQ== X-Gm-Message-State: AOJu0YxSBxR5dQe+6vqx2fCY0A/EG7xxUsFHHx3h/7XYEUpjlyYMl7pN FXuTmxuK9KP7DRcLVxNpVej1I00jpisXIISNYRPzeionNpznD9ar6XjzZKZ+oMaWrV1X1PY41fX 2dEEO7uo= X-Gm-Gg: AfdE7clSM3DWQY0Bo9yIM+rR9eQzF1IofZTZYodoIcdHBR/AFO0CyaC2McdVwHatj/O Bb+YRGAxMiID625g/Nrl9f1itYVspI+uGHNj6Z/7rdzYvku7HRzmrbTCuRebOfnxMte8fTbHGuD 83+eTtKYpNE/hgNY75r/wmp+ZgwtTCtmlZWdMRrnHmn1VZUKpLG/zO2/Jry0T+z5L3QJ7OeRVjS VC9kfJbKzhsHnUVtKVdlmsxClXcyDhF1YDyBs3/Ts6FKRhmuqPOaEn3LpMM+RvNwklj71Jcz1aI t9Anf7QMpPBpAotNX9y9P3uDsi/HdGlBU7dyGs/BpZb/MELcmU2lliVCWxLJ+SiF59puhL9hDnj Iyt7MTE5o+jYmRvXT7ATAmDPHE56h70WJA5FhafDV4ZGD7OPBxnfHaPAV42jT3yFzP++geucWTO Bq9ZA809ULu5wCNL4a58JprRS75x5JWHJXQBtDUZw= X-Received: by 2002:a05:600c:828e:b0:490:e5c1:b8bd with SMTP id 5b1f17b1804b1-4923334baa1mr148777985e9.0.1781785392199; Thu, 18 Jun 2026 05:23:12 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:11 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 19/30] libcamera: software_isp: egl: Add Ping/Pong buffers with start/stop bindings only Date: Thu, 18 Jun 2026 13:22:32 +0100 Message-ID: <20260618122245.946138-20-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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 the Ping/Pong texture buffers, don't bind them to anything yet. Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/software_isp_pipeline_gpu.cpp | 6 ++++++ src/libcamera/software_isp/software_isp_pipeline_gpu.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp index 458b65854..18a8ae17a 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp @@ -335,6 +335,10 @@ int SoftwareIspPipelineGpu::start() /* Raw bayer input as texture */ eglImageBayerIn_ = std::make_unique(gpuIspShaderPassDemosiac_.glFormat_, inputConfig_.stride / gpuIspShaderPassDemosiac_.getBytesPerPixel(), height_, inputConfig_.stride, GL_TEXTURE0, 0); + /* Intermediary ping/pong textures */ + eglImagePingPong_[0] = std::make_unique(gpuIspShaderPassDemosiac_.glFormat_, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE1, 1); + eglImagePingPong_[1] = std::make_unique(gpuIspShaderPassDemosiac_.glFormat_, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE2, 2); + /* Texture we will render to */ eglImageRGBAOut_ = std::make_unique(GL_RGBA, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE3, 3); @@ -344,6 +348,8 @@ int SoftwareIspPipelineGpu::start() void SoftwareIspPipelineGpu::stop() { eglImageRGBAOut_.reset(); + eglImagePingPong_[1].reset(); + eglImagePingPong_[0].reset(); eglImageBayerIn_.reset(); gpuIspShaderPassDemosiac_.stop(); diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.h b/src/libcamera/software_isp/software_isp_pipeline_gpu.h index 1b77bc71d..fcd622492 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.h +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.h @@ -65,6 +65,7 @@ private: /* Pointer to object representing input texture */ std::unique_ptr eglImageBayerIn_; + std::unique_ptr eglImagePingPong_[2]; std::unique_ptr eglImageRGBAOut_; std::unique_ptr stats_; From patchwork Thu Jun 18 12:22:33 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26953 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 6E12BC331D for ; Thu, 18 Jun 2026 12:23:33 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B6974656B8; Thu, 18 Jun 2026 14:23:32 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="kP46Al7P"; 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 D3FFC656B4 for ; Thu, 18 Jun 2026 14:23:13 +0200 (CEST) Received: by mail-wm1-x335.google.com with SMTP id 5b1f17b1804b1-490acbb0f89so5107845e9.0 for ; Thu, 18 Jun 2026 05:23:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785393; x=1782390193; 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=otunOUI1agRrvtm6rTUQ9gqlRxTZmvPpP1vnDqvDaf4=; b=kP46Al7PlAPXb0dCxWQ+5i0dAJih47h6tCc8OPcIoDn8PMcaDZSdDiFQgiTLVg0BU2 fau3THDQjOOQYgoRFR9DOoawZYiSZxMouNKPpOvklwZKeNVAnzZFob8pH0wVjUuinV1V QpUjoUXxJRg4yhccYUPm8Rsc3t0q6BOrzAtFIawDk3TfEQQuNnHBW3YqgPV4190FqtC4 8PoqBt+aNIKLMUsbKS2p0P3+JDJt1Eim5w8LnuqD4NUTsF7TMKt2R476OPk0e4Z+b5w6 Z4nPjxKb7Otkb5dhBO4fP2YHhABSt0vQNKL/zBokJ/G86ip+sFapHXht6s4JfWA1EJNr L/Ng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785393; x=1782390193; 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=otunOUI1agRrvtm6rTUQ9gqlRxTZmvPpP1vnDqvDaf4=; b=o30GpiItBWUh4g//tPLCCGd4qo+m/Sb9oWE7BxKvixrEEciDx2f0th4GRKgDoq11GB hNGaHRRXSCzVoSN69S8uVeWHIDznMr5boJWunvP8k4DmUIGMjqBi4yQaN5xw3gO097IH eMtDK7Jx9YCIXExP0Dv8YuGFnrjHnYOLG55z7f7l5qkWnLM45aRLfUUfNAR8SWf/2JCt xvjsvmheO0R8nxBbAKfF60q1d2Oj5fM/lQWezf1lrRday/rPEXgQCAJ9sjk4Tc24RpJ1 QfKXbsuIP9+Jrme7CHdLAJFTCxlsAVj0XRhNLBqf9nsYSoOX0hSCbGWA8vJiribGRsyQ JAaA== X-Gm-Message-State: AOJu0Yw0aFpnvZLbQ3d94p3cwtRLsF0lKSURJZI3sO2wk3dY/d7wJ0EH kOq6eN436HWh7AiG9qlbSZAlPZMPSlfo+mD4ps2QrFZ90SbDRvHTv10tb4hh2LR0y6T+YyJI1pF Rmbmzrag= X-Gm-Gg: AfdE7cknAJ7ajO3KqBJXaWHNVLK7npSeZYF9PVfZg1AbL2woJVPJ76DEEnx1Q9ex/3K xOe2SODVLJxx949qxebrBlFn0G/2fLHR8COMxjy/DA17hkNQrDh0C0xoIxD7j/nDK4JfQv0Y9XP 2O37gl69QzkNKc/Zf31pY9QMZVBUATBYpJttX5Ib5Xu9pQkp7TzOReF2xa6NhjKuzJTYAnrOo6h /nGy/MZ04u3DzfKQZ2k/W3i3HfgB6/oq8pIE4idptMdiTFUwedlC+8g3An2dHcIiLwYZFQ1m0F+ 89ECCXbryEJlw4UxOUwvN78aVudre8mtlCmCffHmreGdh/QrmRFtdvHPDfo3cnQwkAfNg2ag5HE moFn1ONurTR9jLeSCFoLlR0D0haXnZ0TimaT/4u38dWpzelGEjyKVKt6d34gTzMLEbZox6L3G7u FAy809UE4qis5nX9S/W+6YTWdGOM2O X-Received: by 2002:a05:600c:45c5:b0:490:ea88:9d4c with SMTP id 5b1f17b1804b1-4923822b3a3mr54200405e9.32.1781785392988; Thu, 18 Jun 2026 05:23:12 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:12 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 20/30] libcamera: software_isp: gpu: Include GpuIspShaderPassBlcNormalise in init sequence Date: Thu, 18 Jun 2026 13:22:33 +0100 Message-ID: <20260618122245.946138-21-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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/libcamera/software_isp/software_isp_pipeline_gpu.cpp | 6 +++++- src/libcamera/software_isp/software_isp_pipeline_gpu.h | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp index 18a8ae17a..3c9b48154 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp @@ -41,7 +41,7 @@ namespace libcamera { * \param[in] cm The camera manager */ SoftwareIspPipelineGpu::SoftwareIspPipelineGpu(std::unique_ptr stats, const CameraManager &cm) - : SoftwareIspPipeline(cm), stats_(std::move(stats)), gpuIspShaderPassDemosiac_(egl_) + : SoftwareIspPipeline(cm), stats_(std::move(stats)), gpuIspShaderPassBlcNormalise_(egl_), gpuIspShaderPassDemosiac_(egl_) { } @@ -113,6 +113,10 @@ int SoftwareIspPipelineGpu::initBayerShaders(PixelFormat inputFormat, PixelForma { int ret; + ret = gpuIspShaderPassBlcNormalise_.initShaders(inputFormat, outputFormat); + if (ret) + return ret; + ret = gpuIspShaderPassDemosiac_.initShaders(inputFormat, outputFormat); return ret; diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.h b/src/libcamera/software_isp/software_isp_pipeline_gpu.h index fcd622492..8a922f658 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.h +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.h @@ -24,6 +24,7 @@ #include "libcamera/internal/software_isp/swstats_cpu.h" #include "software_isp_pipeline.h" +#include "gpu_pipeline_shader_pass_blc_normalise.h" #include "gpu_pipeline_shader_pass_demosiac.h" namespace libcamera { @@ -73,6 +74,7 @@ private: uint32_t width_; uint32_t height_; + GpuIspShaderPassBlcNormalise gpuIspShaderPassBlcNormalise_; GpuIspShaderPassDemosiac gpuIspShaderPassDemosiac_; }; From patchwork Thu Jun 18 12:22:34 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26954 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 55BE2C3323 for ; Thu, 18 Jun 2026 12:23:34 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5FBAE656CA; Thu, 18 Jun 2026 14:23:33 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="MqNLYLxJ"; dkim-atps=neutral Received: from mail-wr1-x42a.google.com (mail-wr1-x42a.google.com [IPv6:2a00:1450:4864:20::42a]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5FFB5629B6 for ; Thu, 18 Jun 2026 14:23:14 +0200 (CEST) Received: by mail-wr1-x42a.google.com with SMTP id ffacd0b85a97d-4631679f204so858905f8f.0 for ; Thu, 18 Jun 2026 05:23:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785394; x=1782390194; 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=vlemr6TP2yYXWCy4cCKcKNb9td/Kb7P/MkBIEIloaww=; b=MqNLYLxJz6cw53XHwr5qeCG7Oesh2UGnpyEsx+Aro1PXwA2Mk15UTsrtr4PA+jsaOh oYgbaGYAKoA3WltDHVdFP2dhXeCgeMvlfk/GfqMVQlSQ8IBcW4uPUvqqLrtuf6BUOAod GlMUGpP/FFDo+n970ueROCBuRu0Ybc6yp0PORAJb3r1F6Ew4HNlnlVQfXytCmfZR567z 06xExKMOjzSLksGiy9sUmvnvZZRDni1RPITzW66d8yiZQMn963OA27o+zGDoY66ce3xk lEdBiUUaAJk/tyAq4RVPZ6PEFtxrhugK+YczOcJKdq4PPfCKDmJtdr87TRid37QkYC3e gQpg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785394; x=1782390194; 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=vlemr6TP2yYXWCy4cCKcKNb9td/Kb7P/MkBIEIloaww=; b=nF3Eu/hGkiEkDGu/w+nnArY8ZoECi3NTRY/jfxNdszUZ3y6/joFQfPPhvTZSx2sBvb 5Qrx+sfo7VQclrRjysIvzby0F4M6IB8RIWFqsRuY6b9pwEVJWPM/PwNS/DeRCvhl2F6l XVwYatKm1kpEaQ1EeW494OSHPA+mrDsq/0gvBRVxZces4XhQOPiqNbJkBYJ7uF4ntOh6 5mr5f0EmqYNWXGYDPrDHIKzOIS7zfXik2tkIKBN/KNDnVFxRx7OVg6xFmGsY8FURHJep l+ZTR/4m9ev/xQ2ycW9Kq/he+55tuIR8LkAhrygMV0NLpHXu36BfS02q+qwAMQOQ+Zlu KnNA== X-Gm-Message-State: AOJu0Ywt9CnF1i4SKxJbakr1CKkmWFnI5sbja/Ch2IbMHv/u62UOTwit oSlpc5wtWyOsikxrXBup32702MswD0qoQyi9HV+nJqUovl4tmJKwwk8/Sp1vrEjFFWqCn20sa8A q/r9svCg= X-Gm-Gg: AfdE7ck6Tz75w+s2hlBLZFsSrD+CVQe2csBXwnjGieSuts2orGGuF9UHL2npzjpGiAR de2+sMq6Fn/waMZhPjjp7HR145E2oV+BqnAWju7hExfwWmJfvNFR2dcPmO37LGwDKcRwKD955Hv cqeev8iczugTW9/NeMu4LDvcJD1MVW1UVrTNpPpednGVFvU2RMnBv4Dj9XwZT73tlylG6N141y0 U9M+kYh+DNNlKXN+q362R3P1Qm9POUY/Bsb8zb7McRq5lR6aBB/dl/j73ZzxnPnf51DfFQCWvry gtbPO+V+VDerzUOgHCcglgXX1iTXsZ+tMxEpj8hR6BN46qZ4iGluXcFEAcsReiXa9s/VJT2Xid5 ++mFJM8GQGMl6vBkJnwuzYRzu5kW4B9ciCQKX9m3PP0sD7Wwl9VfTPe13SN+pl25h35QSet6wwg lQsVTkaz3+segXsMkovDL7/F92fELP X-Received: by 2002:a05:600c:6089:b0:490:5000:917 with SMTP id 5b1f17b1804b1-4923815425fmr47375175e9.1.1781785393854; Thu, 18 Jun 2026 05:23:13 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:13 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 21/30] libcamera: software_isp: egl: Add createOutputTexture2D Date: Thu, 18 Jun 2026 13:22:34 +0100 Message-ID: <20260618122245.946138-22-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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 --- include/libcamera/internal/egl.h | 1 + src/libcamera/egl.cpp | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h index 182a4dc55..d3749d2e7 100644 --- a/include/libcamera/internal/egl.h +++ b/include/libcamera/internal/egl.h @@ -107,6 +107,7 @@ public: int createInputDMABufTexture2D(eGLImage &eglImage, int fd); int createOutputDMABufTexture2D(eGLImage &eglImage, int fd); void createInputTexture2D(eGLImage &eglImage, void *data); + void createOutputTexture2D(eGLImage &eglImage); int attachTextureToFBO(eGLImage &eglImage); diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index ffaa6bc49..8d135e092 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -297,6 +297,22 @@ void eGL::createInputTexture2D(eGLImage &eglImage, void *data) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } +/** + * \brief Create a 2D texture attached to an FBO for render-to-texture + * \param[in,out] eglImage EGL image to associate with the texture + * \param[in] format OpenGL internal format (e.g., GL_RGB, GL_RGBA) + * + * Creates a 2D texture in VRAM. The texture + * is configured with nearest filtering and clamp-to-edge wrapping. This + * is useful for uploading static data like lookup tables or uniform color + * matrices to the GPU. + */ +void eGL::createOutputTexture2D(eGLImage &eglImage) +{ + createInputTexture2D(eglImage, NULL); + attachTextureToFBO(eglImage); +} + /** * \brief Initialise the EGL context * From patchwork Thu Jun 18 12:22:35 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26955 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 F194CC3329 for ; Thu, 18 Jun 2026 12:23:34 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 27098656E5; Thu, 18 Jun 2026 14:23:34 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="joVLJTRo"; dkim-atps=neutral Received: from mail-wm1-x32c.google.com (mail-wm1-x32c.google.com [IPv6:2a00:1450:4864:20::32c]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3108762C7A for ; Thu, 18 Jun 2026 14:23:15 +0200 (CEST) Received: by mail-wm1-x32c.google.com with SMTP id 5b1f17b1804b1-490b8ac62baso19680925e9.0 for ; Thu, 18 Jun 2026 05:23:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785395; x=1782390195; 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=03Mx98uHM3e9ogtSRRDNl3AXJ1a3/cvpGblz2ZIrnt4=; b=joVLJTRo1VLrodB9whg6jw66eQWhk8SvPnKizuOAGxnVSWF4qm9Q2VYPGsi3eAEQe2 F2y2NYzXwqGgFWThnQICgJ1BQEs93DvrCvJSRwdm+hB4BiGboAx2UKiE43TyKAfbDfPk Y6lzGA2OAy82iBR5Sjz+wwlIG6e9UfYCH/gvlRKB7mOIHKYI+Ui+UUjK4xxpauniS4XJ RtYWuBXHcf4/z7pQ6U9AH417/l5djVxcUt/itd/kLrNXjoDfc+AizHb0+NVR9G7WsxHw wn4kss8n8yNbPlfv7SK8sceD23jG1sXuqwtWfYYN+jNSFJdJPYWJwaLr/japX7a7lMMp DQBw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785395; x=1782390195; 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=03Mx98uHM3e9ogtSRRDNl3AXJ1a3/cvpGblz2ZIrnt4=; b=loGi/Gj0enl5K2X+dgBzwOpuuHGphCLKF3i6m/8A2BozSZ0iqJ5S/XVAnwl7hCMyE/ oPZAwqD2r9OJrkheuK6kroDk1RvNvRftjqXAO9JDxuWRx+abUO64D8T1//Eeyff4DTyo guk5cgai++FlFOGdbvP5aKM7QUWp4kW0qq/wlrhUJglxuk1KGjVWCKh70tyvu6uTQ6sx TtXg7yeOP8jgk2ITwVmnoIEduFBsUsNLVVSs8wEuEbSAW9FobD6vWGp0QB6wuO3jf67B mRqVthBVv6JLK6zJ5tO2uQf/7D5uzQtabQbO3LZBl6sVVm3OC7osamGvExJmIwfqqg1H fBMw== X-Gm-Message-State: AOJu0Yz7sY+QYBKy4k6E+OZBmOgTotKDzyEQi4d8p6F0fnY+Cr/kSTsm VHqixRicEvrPzQiPljoB/rlPn3Gnv+tz/fANE57NBCxmKM8MhacxGYO4dyKuEI0Io1DxfUcqy/i bGGgOIYE= X-Gm-Gg: AfdE7cntK4Beay8fe1nv4nLFjrjLVCzVHT+8VzqYSTnYFsaHvnuWXxnHa0SOB1NGPWl 4dLvgmd1uLsGev1AbFqdz3aM/XsC0NufxProUy/u7YipUoszbquj4dFAf3lhHA82FWtV+/+fmb0 uM94PW/ZEvKytGgUM+KpaTcUgTfZrRVhNDhmoydzxh4TwGnofeUaHoip/TNBuv1AZmq4lB0HiQC BpeD7jo+1kNHw5GuDXjfQU5C2ZvTxp/Dlp40T/jjqKqHaNXlmT9Ai0KIgxVnp1TUvk751iqKe0I eRkN63QHh4uELth2eGE3KMthcAlnE71sPtzIxHutp8hISakdBgu4ou3VnwcoTbHb8gg2oKU95u3 HcQpr+qmGu3B8Lj2/pCWQuM+nCsW4X7C1gJKAK9dYPN/PtgqFdLkKJihmVC2/OFRUb39ziJAZq4 qCtMxlQt431fd/0jiv2Ik2Gzt93EGlq8lwWcO+LHU= X-Received: by 2002:a05:600c:c8f:b0:490:b4cb:3866 with SMTP id 5b1f17b1804b1-4923817fa5cmr50078885e9.10.1781785394565; Thu, 18 Jun 2026 05:23:14 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:14 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 22/30] libcamera: software_isp: gpu: Swtich to two pass logic Date: Thu, 18 Jun 2026 13:22:35 +0100 Message-ID: <20260618122245.946138-23-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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 --- ...gpu_pipeline_shader_pass_blc_normalise.cpp | 54 ++++++++++++++++--- .../gpu_pipeline_shader_pass_demosiac.cpp | 49 ++++------------- .../gpu_pipeline_shader_pass_demosiac.h | 3 -- .../software_isp_pipeline_gpu.cpp | 26 +++++++-- 4 files changed, 80 insertions(+), 52 deletions(-) diff --git a/src/libcamera/software_isp/gpu_pipeline_shader_pass_blc_normalise.cpp b/src/libcamera/software_isp/gpu_pipeline_shader_pass_blc_normalise.cpp index 8e8d7b9d6..c07319ee0 100644 --- a/src/libcamera/software_isp/gpu_pipeline_shader_pass_blc_normalise.cpp +++ b/src/libcamera/software_isp/gpu_pipeline_shader_pass_blc_normalise.cpp @@ -102,6 +102,8 @@ int GpuIspShaderPassBlcNormalise::selectShaders(struct ShaderConfig &shaderCfg, break; }; + LOG(GpuShaderBlc, Info) << "ShaderPass = " << typeid(this).name() << " selected shader pair "; + return 0; } @@ -113,15 +115,14 @@ int GpuIspShaderPassBlcNormalise::getShaderVariableLocations(void) 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"); + blackLevelUniformDataIn_ = glGetUniformLocation(programId_, "blacklevel"); LOG(GpuShaderBlc, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ << " tex_y " << textureUniformBayerDataIn_ << " tex_step " << textureUniformStep_ << " tex_size " << textureUniformSize_ << " stride_factor " << textureUniformStrideFactor_ - << " tex_bayer_first_red " << textureUniformBayerFirstRed_ << " proj_matrix " << textureUniformProjMatrix_; /* TODO: trap errors */ @@ -130,6 +131,8 @@ int GpuIspShaderPassBlcNormalise::getShaderVariableLocations(void) void GpuIspShaderPassBlcNormalise::setShaderVariableValues(const DebayerParams ¶ms, eGLImage &eglImageIn) { + GLenum err; + /* * Raw Bayer 8-bit, and packed raw Bayer 10-bit/12-bit formats * are stored in a GL_LUMINANCE texture. The texture width is @@ -168,15 +171,34 @@ void GpuIspShaderPassBlcNormalise::setShaderVariableValues(const DebayerParams & { 1.0f, 0.0f }, }; + err = glGetError(); + if (err != GL_NO_ERROR) + LOG(GpuShaderBlc, Error) << "setShaderVariables entry @ error " << err; + /* vertexIn - bayer_8.vert */ glEnableVertexAttribArray(attributeVertex_); + + err = glGetError(); + if (err != GL_NO_ERROR) + LOG(GpuShaderBlc, Error) << "setShaderVariables error " << err << " line " << __LINE__; + glVertexAttribPointer(attributeVertex_, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(GLfloat), vcoordinates); + err = glGetError(); + if (err != GL_NO_ERROR) + LOG(GpuShaderBlc, Error) << "setShaderVariables error " << err << " line " << __LINE__; /* textureIn - bayer_8.vert */ glEnableVertexAttribArray(attributeTexture_); + err = glGetError(); + if (err != GL_NO_ERROR) + LOG(GpuShaderBlc, Error) << "setShaderVariables error " << err << " line " << __LINE__; + glVertexAttribPointer(attributeTexture_, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(GLfloat), tcoordinates); + err = glGetError(); + if (err != GL_NO_ERROR) + LOG(GpuShaderBlc, Error) << "setShaderVariables error " << err << " line " << __LINE__; /* * Set the sampler2D to the respective texture unit for each texutre @@ -184,27 +206,43 @@ void GpuIspShaderPassBlcNormalise::setShaderVariableValues(const DebayerParams & * texture units */ glUniform1i(textureUniformBayerDataIn_, eglImageIn.texture_unit_uniform_id_); + err = glGetError(); + if (err != GL_NO_ERROR) + LOG(GpuShaderBlc, Error) << "setShaderVariables error " << err << " line " << __LINE__; /* * 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); + err = glGetError(); + if (err != GL_NO_ERROR) + LOG(GpuShaderBlc, Error) << "setShaderVariables error " << err << " line " << __LINE__; + glUniform2fv(textureUniformStep_, 1, Step); + err = glGetError(); + if (err != GL_NO_ERROR) + LOG(GpuShaderBlc, Error) << "setShaderVariables error " << err << " line " << __LINE__; + glUniform1f(textureUniformStrideFactor_, Stride); + err = glGetError(); + if (err != GL_NO_ERROR) + LOG(GpuShaderBlc, Error) << "setShaderVariables error " << err << " line " << __LINE__; + glUniformMatrix4fv(textureUniformProjMatrix_, 1, GL_FALSE, projMatrix); + err = glGetError(); + if (err != GL_NO_ERROR) + LOG(GpuShaderBlc, Error) << "setShaderVariables error " << err << " line " << __LINE__; + LOG(GpuShaderBlc, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ << " tex_y " << textureUniformBayerDataIn_ << " tex_step " << textureUniformStep_ << " tex_size " << textureUniformSize_ - << " stride_factor " << textureUniformStrideFactor_ - << " tex_bayer_first_red " << textureUniformBayerFirstRed_; + << " stride_factor " << textureUniformStrideFactor_; LOG(GpuShaderBlc, Debug) << "textureUniformY_ = 0 " << " firstRed.x " << firstRed[0] @@ -220,6 +258,10 @@ void GpuIspShaderPassBlcNormalise::setShaderVariableValues(const DebayerParams & * 0 = Red, 1 = Green, 2 = Blue */ glUniform3f(blackLevelUniformDataIn_, params.blackLevel[0], params.blackLevel[1], params.blackLevel[2]); + err = glGetError(); + if (err != GL_NO_ERROR) + LOG(GpuShaderBlc, Error) << "setShaderVariables error " << err << " line " << __LINE__; + LOG(GpuShaderBlc, Debug) << " blackLevelUniformDataIn_ " << blackLevelUniformDataIn_ << " data " << params.blackLevel; return; diff --git a/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.cpp b/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.cpp index b0c431c13..a1ca1916d 100644 --- a/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.cpp +++ b/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.cpp @@ -47,20 +47,20 @@ void GpuIspShaderPassDemosiac::stop() int GpuIspShaderPassDemosiac::selectShaders(struct ShaderConfig &shaderCfg, [[maybe_unused]]PixelFormat &inputFormat, [[maybe_unused]]PixelFormat &outputFormat) { /* Pixel location parameters */ - glFormat_ = GL_LUMINANCE; + glFormat_ = GL_R16F; bytesPerPixel_ = 1; shaderStridePixels_ = passInputCfg_.stride; - /* Shader selection */ + shaderCfg.vertexShaderData = bayer_unpacked_vert; + shaderCfg.vertexShaderDataLen = bayer_unpacked_vert_len; + shaderCfg.fragmentShaderData = bayer_glr16_to_rgba_frag; + shaderCfg.fragmentShaderDataLen = bayer_glr16_to_rgba_frag_len; + switch (inputFormat) { case libcamera::formats::SBGGR8: case libcamera::formats::SGBRG8: case libcamera::formats::SGRBG8: case libcamera::formats::SRGGB8: - shaderCfg.fragmentShaderData = bayer_unpacked_frag; - shaderCfg.fragmentShaderDataLen = bayer_unpacked_frag_len; - shaderCfg.vertexShaderData = bayer_unpacked_vert; - shaderCfg.vertexShaderDataLen = bayer_unpacked_vert_len; break; case libcamera::formats::SBGGR10_CSI2P: case libcamera::formats::SGBRG10_CSI2P: @@ -68,17 +68,9 @@ int GpuIspShaderPassDemosiac::selectShaders(struct ShaderConfig &shaderCfg, [[ma case libcamera::formats::SRGGB10_CSI2P: egl_.pushEnv(shaderCfg.shaderEnv, "#define RAW10P"); if (BayerFormat::fromPixelFormat(inputFormat).packing == BayerFormat::Packing::None) { - shaderCfg.fragmentShaderData = bayer_unpacked_frag; - shaderCfg.fragmentShaderDataLen = bayer_unpacked_frag_len; - shaderCfg.vertexShaderData = bayer_unpacked_vert; - shaderCfg.vertexShaderDataLen = bayer_unpacked_vert_len; glFormat_ = GL_RG; bytesPerPixel_ = 2; } else { - shaderCfg.fragmentShaderData = bayer_1x_packed_frag; - shaderCfg.fragmentShaderDataLen = bayer_1x_packed_frag_len; - shaderCfg.vertexShaderData = identity_vert; - shaderCfg.vertexShaderDataLen = identity_vert_len; shaderStridePixels_ = passInputCfg_.size.width; } break; @@ -88,22 +80,16 @@ int GpuIspShaderPassDemosiac::selectShaders(struct ShaderConfig &shaderCfg, [[ma case libcamera::formats::SRGGB12_CSI2P: egl_.pushEnv(shaderCfg.shaderEnv, "#define RAW12P"); if (BayerFormat::fromPixelFormat(inputFormat).packing == BayerFormat::Packing::None) { - shaderCfg.fragmentShaderData = bayer_unpacked_frag; - shaderCfg.fragmentShaderDataLen = bayer_unpacked_frag_len; - shaderCfg.vertexShaderData = bayer_unpacked_vert; - shaderCfg.vertexShaderDataLen = bayer_unpacked_vert_len; glFormat_ = GL_RG; bytesPerPixel_ = 2; } else { - shaderCfg.fragmentShaderData = bayer_1x_packed_frag; - shaderCfg.fragmentShaderDataLen = bayer_1x_packed_frag_len; - shaderCfg.vertexShaderData = identity_vert; - shaderCfg.vertexShaderDataLen = identity_vert_len; shaderStridePixels_ = passInputCfg_.size.width; } break; }; + LOG(GpuShaderDemosiac, Info) << "ShaderPass = " << typeid(this).name() << " selected shader pair "; + return 0; } @@ -112,26 +98,21 @@ int GpuIspShaderPassDemosiac::getShaderVariableLocations(void) attributeVertex_ = glGetAttribLocation(programId_, "vertexIn"); attributeTexture_ = glGetAttribLocation(programId_, "textureIn"); - textureUniformBayerDataIn_ = glGetUniformLocation(programId_, "tex_y"); ccmUniformDataIn_ = glGetUniformLocation(programId_, "ccm"); - blackLevelUniformDataIn_ = glGetUniformLocation(programId_, "blacklevel"); gammaUniformDataIn_ = glGetUniformLocation(programId_, "gamma"); contrastExpUniformDataIn_ = glGetUniformLocation(programId_, "contrastExp"); - textureUniformStep_ = glGetUniformLocation(programId_, "tex_step"); - textureUniformSize_ = glGetUniformLocation(programId_, "tex_size"); textureUniformStrideFactor_ = glGetUniformLocation(programId_, "stride_factor"); textureUniformBayerFirstRed_ = glGetUniformLocation(programId_, "tex_bayer_first_red"); textureUniformProjMatrix_ = glGetUniformLocation(programId_, "proj_matrix"); + textureUniformBayerDataIn_ = glGetUniformLocation(programId_, "tex_y"); + textureUniformStep_ = glGetUniformLocation(programId_, "tex_step"); + textureUniformSize_ = glGetUniformLocation(programId_, "tex_size"); LOG(GpuShaderDemosiac, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ - << " tex_y " << textureUniformBayerDataIn_ << " ccm " << ccmUniformDataIn_ - << " blacklevel " << blackLevelUniformDataIn_ << " gamma " << gammaUniformDataIn_ << " contrastExp " << contrastExpUniformDataIn_ - << " tex_step " << textureUniformStep_ - << " tex_size " << textureUniformSize_ << " stride_factor " << textureUniformStrideFactor_ << " tex_bayer_first_red " << textureUniformBayerFirstRed_ << " proj_matrix " << textureUniformProjMatrix_; @@ -213,8 +194,6 @@ void GpuIspShaderPassDemosiac::setShaderVariableValues(const DebayerParams ¶ LOG(GpuShaderDemosiac, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ << " tex_y " << textureUniformBayerDataIn_ - << " tex_step " << textureUniformStep_ - << " tex_size " << textureUniformSize_ << " stride_factor " << textureUniformStrideFactor_ << " tex_bayer_first_red " << textureUniformBayerFirstRed_; @@ -242,12 +221,6 @@ void GpuIspShaderPassDemosiac::setShaderVariableValues(const DebayerParams ¶ glUniformMatrix3fv(ccmUniformDataIn_, 1, GL_FALSE, ccm); LOG(GpuShaderDemosiac, Debug) << " ccmUniformDataIn_ " << ccmUniformDataIn_ << " data " << params.combinedMatrix; - /* - * 0 = Red, 1 = Green, 2 = Blue - */ - glUniform3f(blackLevelUniformDataIn_, params.blackLevel[0], params.blackLevel[1], params.blackLevel[2]); - LOG(GpuShaderDemosiac, Debug) << " blackLevelUniformDataIn_ " << blackLevelUniformDataIn_ << " data " << params.blackLevel; - /* * Gamma */ diff --git a/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.h b/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.h index c83024bc4..2302b2ea0 100644 --- a/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.h +++ b/src/libcamera/software_isp/gpu_pipeline_shader_pass_demosiac.h @@ -50,9 +50,6 @@ private: /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */ GLint ccmUniformDataIn_; - /* Black Level compensation */ - GLint blackLevelUniformDataIn_; - /* Gamma */ GLint gammaUniformDataIn_; diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp index 3c9b48154..14f6d2b8c 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp @@ -186,9 +186,12 @@ int SoftwareIspPipelineGpu::configure(const StreamConfiguration &inputCfg, /* Configure for one pass */ PassConfig rawSensorIn = { inputCfg.size, inputConfig_.stride, inputPixelFormat_, window }; + PassConfig pingPongOut = { inputCfg.size, inputCfg.size.width, inputPixelFormat_, Rectangle(inputCfg.size) }; + PassConfig pingPongIn = pingPongOut; PassConfig rgbaOut = { outputCfg.size, outputConfig_.stride, outputPixelFormat_, Rectangle(outputSize_) }; - gpuIspShaderPassDemosiac_.configure(rawSensorIn, rgbaOut); + gpuIspShaderPassBlcNormalise_.configure(rawSensorIn, pingPongOut); + gpuIspShaderPassDemosiac_.configure(pingPongIn, rgbaOut); return 0; } @@ -257,7 +260,17 @@ int SoftwareIspPipelineGpu::processGPU(FrameBuffer *input, FrameBuffer *output, /* Generate the output render framebuffer as render to texture */ egl_.createOutputDMABufTexture2D(*eglImageRGBAOut_, output->planes()[0].fd.get()); - pipelineResult = gpuIspShaderPassDemosiac_.process(*eglImageBayerIn_, *eglImageRGBAOut_, width_, height_, params); + pipelineResult = gpuIspShaderPassBlcNormalise_.process(*eglImageBayerIn_, *eglImagePingPong_[0], width_, height_, params); + if (pipelineResult) { + LOG(Debayer, Error) << "BlcNormalise fail"; + return pipelineResult; + } + + pipelineResult = gpuIspShaderPassDemosiac_.process(*eglImagePingPong_[0], *eglImageRGBAOut_, width_, height_, params); + if (pipelineResult) { + LOG(Debayer, Error) << "Demosiac fail"; + return pipelineResult; + } GLenum err = glGetError(); if (err != GL_NO_ERROR) { @@ -337,15 +350,18 @@ int SoftwareIspPipelineGpu::start() return -EINVAL; /* Raw bayer input as texture */ - eglImageBayerIn_ = std::make_unique(gpuIspShaderPassDemosiac_.glFormat_, inputConfig_.stride / gpuIspShaderPassDemosiac_.getBytesPerPixel(), height_, inputConfig_.stride, GL_TEXTURE0, 0); + eglImageBayerIn_ = std::make_unique(gpuIspShaderPassBlcNormalise_.glFormat_, inputConfig_.stride / gpuIspShaderPassBlcNormalise_.getBytesPerPixel(), height_, inputConfig_.stride, GL_TEXTURE0, 0); /* Intermediary ping/pong textures */ - eglImagePingPong_[0] = std::make_unique(gpuIspShaderPassDemosiac_.glFormat_, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE1, 1); - eglImagePingPong_[1] = std::make_unique(gpuIspShaderPassDemosiac_.glFormat_, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE2, 2); + eglImagePingPong_[0] = std::make_unique(gpuIspShaderPassDemosiac_.glFormat_, width_, height_, outputConfig_.stride, GL_TEXTURE1, 1); + eglImagePingPong_[1] = std::make_unique(gpuIspShaderPassDemosiac_.glFormat_, width_, height_, outputConfig_.stride, GL_TEXTURE2, 2); /* Texture we will render to */ eglImageRGBAOut_ = std::make_unique(GL_RGBA, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE3, 3); + egl_.createOutputTexture2D(*eglImagePingPong_[0]); + egl_.createOutputTexture2D(*eglImagePingPong_[1]); + return 0; } From patchwork Thu Jun 18 12:22:36 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26956 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 26C31C332A for ; Thu, 18 Jun 2026 12:23:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4ECA4656EB; Thu, 18 Jun 2026 14:23:35 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="vMcS6geV"; 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 E03FB656C0 for ; Thu, 18 Jun 2026 14:23:15 +0200 (CEST) Received: by mail-wm1-x335.google.com with SMTP id 5b1f17b1804b1-490ae94a89eso6314345e9.1 for ; Thu, 18 Jun 2026 05:23:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785395; x=1782390195; 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=EZJ9JeeKuy/kalHWvSZKmR3Qkntwk99X5kKkipZh7EM=; b=vMcS6geVpUJlyoxamVHGb2BkV9olOcQVVnIATAT+3X17WXPDV5LpSokxwBpURpHE8e 04nysCj9YDilp0ohH8XZ/IPwvX1SN2/j280S1I2YjDnpTwChoW03RjM6Afegx0onwTT3 E9nWJABIiQNP1wZSHa/ULkC3rldTTZr912dHNG91WtZB8dWMWH9IWwAKcRghxgdCWcSc iGOXgyIEwSEkvAi9bO2vtvpsS5V0MOrJTMcdcZSI28sOFIYp39aUdk8xL06iUhvgP2bz mxmxPErSbMWpElWU8t7X1kgntGV68SexFKb7HMjoR1VKqWn1vG53s9ifrpk9bAZEjjt3 ZRuA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785395; x=1782390195; 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=EZJ9JeeKuy/kalHWvSZKmR3Qkntwk99X5kKkipZh7EM=; b=l0nb8c6ztake8dwhDiOY8JUT9aWvIMVacguEtSmzopl5ApsRHFLpv3FuBrJRML0dxu Gs3zhhfv4c8vdMXyHunl4KxGqZRYjMGMqp9i8liQEOF1hP/oTgV9c+b4d9EY9Qby44mI p82JRrJuf9rTUrIuqkRwG/Kf+BPl2rpcAy5Jt3BSe07jxGFsv2xFz3lXhJ8E4lKps1TE pASTRvrhLlSp5hvfHnL9m1x+qYPV04d7UTIIqaMZ/48qpa1buxuIMB7pYFZ4vXOCT0Bx fZZHwG6WYeJcbf0Ieadk2oCIYnTQaS1JJ/p4FmF7wAN7xNuEHY8kOkg3rFrN4q46DtC6 V5tw== X-Gm-Message-State: AOJu0YxCRgfWunkiMJQQGgKZy0HPPRYEXfRe+s/nRioEPBDVRShnR2ND eUAYvqIVV5FDYV2ritP9TEzP1WJqVDDc5ShwZo9qtQ0yTJSisG/aDb2u8MfKFVtYR9az6156/Nb ja7fHsJY= X-Gm-Gg: AfdE7cksyQInvTBLFi5caOoEFyQ8uLI4KUZ8hw46ato0ttsWlkUWvlgsOgJVg+oMSnt gwVJS3yCMQ8tfAQkqtJRhiWDRT5SRuaGQjYA+DYS0+T90QwgmDWTRqrkbXcpapM/p89MJVFFibY 3C4dz0E2SVC18TOJG6x17XkbBZdmdqF9kEQ6eZ+BFbzWfqgIHSweksx2nh/c77LOr1tq1lY4RPB ttLKekNL4dxjJqsQigL8w/V8TGVxCeJ9OyxtYXI/5lHQy/v8YEMqUgu/kWJ6eRqJVY4wstKYKJz thCgwFMtD29MI0nybJtu8Mf9v9j5uX7KZWbvdxHU8uQSdLsclnW2Ct1dbMzlwKAO+CRhEjmymuh Xxy8ewVjY1ryFLm5Jwo3SNbCrW92EiywoOmP/9yo85OazalbZOEAbsrW6xGdLYbSWQsPzavhkqY tpW2/DSS9tejoz/ulsP2PQaXbzOFCzE8paHy9S3B8= X-Received: by 2002:a05:600c:1550:b0:48f:e26a:1744 with SMTP id 5b1f17b1804b1-492381eba37mr56177075e9.9.1781785395282; Thu, 18 Jun 2026 05:23:15 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:14 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 23/30] libcamera: software_isp: egl: Add method lookups for GPU benchmark rountines Date: Thu, 18 Jun 2026 13:22:36 +0100 Message-ID: <20260618122245.946138-24-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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 lookups for: - glBeingQuery - glEndQuery - glGetAueryObjectuiv - glGetAueryObjectui64v Used in the right way these methods will allows us to interrogate exactly how long each GPUISP pass takes. Signed-off-by: Bryan O'Donoghue --- include/libcamera/internal/egl.h | 5 +++++ src/libcamera/egl.cpp | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h index d3749d2e7..0e57678e8 100644 --- a/include/libcamera/internal/egl.h +++ b/include/libcamera/internal/egl.h @@ -146,5 +146,10 @@ private: PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; PFNGLGETSTRINGPROC glGetString; + PFNGLBEGINQUERYPROC glBeginQuery; + PFNGLENDQUERYPROC glEndQuery; + PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectuiv; + PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectui64v; + PFNGLGENQUERIESPROC glGenQueries; }; } //namespace libcamera diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index 8d135e092..2fc10b800 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -390,6 +390,36 @@ int eGL::initEGLContext() goto fail; } + glBeginQuery = (PFNGLBEGINQUERYPROC)eglGetProcAddress("glBeginQuery"); + if (!glBeginQuery) { + LOG(eGL, Error) << "glBegin not found"; + goto fail; + } + + glEndQuery = (PFNGLENDQUERYPROC)eglGetProcAddress("glEndQuery"); + if (!glEndQuery) { + LOG(eGL, Error) << "glEndQuery not found"; + goto fail; + } + + glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC)eglGetProcAddress("glGetQueryObjectuiv"); + if (!glGetQueryObjectuiv) { + LOG(eGL, Error) << "glGetQueryObjectuiv not found"; + goto fail; + } + + glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUIVPROC)eglGetProcAddress("glGetQueryObjectui64v"); + if (!glGetQueryObjectuiv) { + LOG(eGL, Error) << "glGetQueryObjectui64v not found"; + goto fail; + } + + glGenQueries = (PFNGLGENQUERIESPROC)eglGetProcAddress("glGenQueries"); + if (!glGetQueryObjectuiv) { + LOG(eGL, Error) << "glGenQueries not found"; + goto fail; + } + if (eglChooseConfig(display_, configAttribs, &config, 1, &numConfigs) != EGL_TRUE) { LOG(eGL, Error) << "eglChooseConfig fail"; goto fail; From patchwork Thu Jun 18 12:22:37 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26957 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 22DF9C3303 for ; Thu, 18 Jun 2026 12:23:37 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A8E0F656D4; Thu, 18 Jun 2026 14:23:36 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="PgaR1UcK"; dkim-atps=neutral Received: from mail-wm1-x333.google.com (mail-wm1-x333.google.com [IPv6:2a00:1450:4864:20::333]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 86C7D656C2 for ; Thu, 18 Jun 2026 14:23:16 +0200 (CEST) Received: by mail-wm1-x333.google.com with SMTP id 5b1f17b1804b1-490afc47455so3172485e9.2 for ; Thu, 18 Jun 2026 05:23:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785396; x=1782390196; 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=plXVRNtI9PlRM1WZ1wJrleCdMifWh3iZlB+O97cPEp0=; b=PgaR1UcK0yqmHz/xeFAbehdyQnwLSFcQ8rrPVT1B7ogni8+86Cn9z66Cjrojr8RFYD 9CJPlH4FG7Afevc5pLWb2KKYr3/kiQOdviOvWbpmtiAyB02p1ks7VZJXpCFYg4KNG9bX l2W2Xgpk9yOqSjDbTcBqCB8PleANhGNTvYeggFKI+Qb8/IT89LFK9GDadxevCWAd5+qB zax29RXF8SnNI/F+mZnu0n/sQ4Caau0hrijzxp+aSus+74OqAEReHQaCqwT8lyN+aOqU qtPt28IVxXoLPiExC6DXQ1t1Bbk6dtrpw5t7WLumjgFTu9ddI39KNZeZ1JTeGEg7WxIC 3AxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785396; x=1782390196; 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=plXVRNtI9PlRM1WZ1wJrleCdMifWh3iZlB+O97cPEp0=; b=Isz97a583V7+oTzwjIwLctEtSAApXfQQV23v8Aai07Y5ATLNKoej/NtKb+k/rXNr0S bzdWYqDKNnRuypVEgdmcL66dRbpSBdHiEcCcR1uU1W/ODyhGEH3Rc+FHnOv7JweYGj0i 4gcUaKT3a5nCXmLCk/pCgRP0PTywc52+lr+YOIZtA7ht0tQEXUmdgDCC1YfGNULF7Zs2 3ZjlfBr8gAXQgK00Ql9+cCUKS+GoYt2/PDpxksHTD07vDT5MMp/j49XHUfZVbND9Y1Du U8SVIyWhvoOUDDYse8jY2gBZr67/D7cTKBhoLFsNNKlyp52koGm6gmS3DIwhLVSUM6FR 0WwA== X-Gm-Message-State: AOJu0YyS0/f4JjFsaojkCc5x5mfrzBynddEiMVflq5SYvMTZvGRlIjO3 YMk/Ov6ScfxhvGpzSkEjAr1zbpgF2+wa/XIfxDVRs1zk4NP2B2L2wH5PGlilMuSu4yzZC58jHDS CqJtuji8= X-Gm-Gg: AfdE7ckaJMIKnw2MpxrSuE45O6xGyIElIQHKU+sed95f0ibAgMUqMpjZMcPY/L4jJ76 OkAB+va14yPe1VxIGbZkXI3EQ17YhJ69TytybhnfK4PNt88WzS0O/C8eFlb6Zr+k4LSlttiSmPk kDEjgWa1+bm4GmRJGWJImnaf0FfcsazSuUyGnIDpv+00IrweuOy//I/AbbSGA1dqQsZthCRUEwn Edo9YDYYn2+aSBKFYain3Xw9lHuAJ13WU9FB5/qVCtXB5+iBhfOwMsnsxXW2HsycXhXaL9smzBd Vi7415AFBLg7qwfE2a0apkkdA3W91ZlREqzgWAGFlhyRE4CTNnIwL666WhofdHNMtKUuikvbnjo 1xaMqY0XZyFO3hCzRjyUWOsDET6dxGh5ixYqG8PNOOZVudDr37FyTgdHcqa/gBID7Nzp3Iz97vB NgkFWBhaFtxb/6p5tLhoq9Xjax6XoQ X-Received: by 2002:a05:600c:c171:b0:490:9df1:f0d5 with SMTP id 5b1f17b1804b1-4923a9eac1emr29179725e9.28.1781785395976; Thu, 18 Jun 2026 05:23:15 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:15 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 24/30] libcamera: software_isp: egl: Add eglBenchMark Date: Thu, 18 Jun 2026 13:22:37 +0100 Message-ID: <20260618122245.946138-25-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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 --- include/libcamera/internal/egl.h | 52 ++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h index 0e57678e8..8f905416a 100644 --- a/include/libcamera/internal/egl.h +++ b/include/libcamera/internal/egl.h @@ -127,6 +127,8 @@ public: void syncOutput(); void flushOutput(); + friend class eGLBenchMark; + private: LIBCAMERA_DISABLE_COPY_AND_MOVE(eGL) @@ -152,4 +154,54 @@ private: PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectui64v; PFNGLGENQUERIESPROC glGenQueries; }; + +class eGLBenchMark { +public: + eGLBenchMark() {} + ~eGLBenchMark() {} + + void init(void) + { + glGenQueries(1, &glQueryTimeId_); + } + + void begin(eGL &egl) + { + egl.glBeginQuery(GL_TIME_ELAPSED_EXT, glQueryTimeId_); + } + + void end(eGL &egl) + { + egl.glEndQuery(GL_TIME_ELAPSED_EXT); + } + + GLuint64 getTimeElapsedSync(eGL &egl) + { + // Caution sync will wait until result is available + return getTimeElapsed(egl, true); + } + + GLuint64 getTimeElapsedAsync(eGL &egl) + { + return getTimeElapsed(egl, false); + } + +private: + GLuint glQueryTimeId_; + + GLuint64 getTimeElapsed(eGL &egl, bool sync) + { + GLuint time_elapsed_ns = 0; + GLuint available = 0; + + if (!sync) + egl.glGetQueryObjectuiv(glQueryTimeId_, GL_QUERY_RESULT_AVAILABLE, &available); + + if (available || sync) + egl.glGetQueryObjectui64v(glQueryTimeId_, GL_QUERY_RESULT, &time_elapsed_ns); + + return time_elapsed_ns; + } +}; + } //namespace libcamera From patchwork Thu Jun 18 12:22:38 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26958 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 76ADBC3330 for ; Thu, 18 Jun 2026 12:23:38 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D924F656CA; Thu, 18 Jun 2026 14:23:37 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="VfFO3BN6"; 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 44DC0629CE for ; Thu, 18 Jun 2026 14:23:17 +0200 (CEST) Received: by mail-wm1-x331.google.com with SMTP id 5b1f17b1804b1-490b4a8e28bso6380145e9.1 for ; Thu, 18 Jun 2026 05:23:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785397; x=1782390197; 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=R+IGxiwb/nNpubCez8ipcoHv8HytnsSvPHD8T96HbMI=; b=VfFO3BN6oi+Qg5PsKPnie0FzKqcR258JNA//M5Un70a9HUZd7xAcvYQ26HcHaazu8x hiUXrhWWYhIbyH1t0YoV1A0Xx+Is6mdqUQ0JNT2f4iCXDOQrghzY9V+Dc+C01tTz20QL SASmCSQKk6QZJ65qSf47uNyEOxvyu07dJgXu2n/qPAZvFyzurFgfk1KCZQQuFfd+mO1g 6DMq1O25Pegmow/jR5SwviCXfPr13eexsjMGEpJNW6Ch/qdd14u0KC/ukOSQ6VlsfIn5 3vq4vaJ26HVjF5GSsKATLDRriQDvQWd+DTjC+vCYZxAF5lmw9MIqHQ83zBdjWVK6VZjz /hhA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785397; x=1782390197; 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=R+IGxiwb/nNpubCez8ipcoHv8HytnsSvPHD8T96HbMI=; b=d2cbIliFWsQLsDEGRK5sLEtefMP8Aduosi5zMDxM1abeF4fUWiUnBQfO9HcPhJ6cl/ QSmZAloykl0Y4Zq6AuLmg1pEAgmISHihJv8PE38cM6jaKQAZp624r/jg0UoRH9v7SZm+ gHmomjyI/JVbuJUapMx4AjVRrIqBgBxHE2X1811asbmQQiVPfaqdofVvNzTPufsVWUzE w/Nc6zElD04Msyrx14h6gZqJwjVEj84h5LEV4SiWjlUD3K1zZT0cp+hOrXSVpPm4KUXW L8KhSPGaBlF9UpaDblFh9C7IkUcuNRzqIDjZihtpkldcAswJYYt7DCPuC7qg3sbHvwGo phPA== X-Gm-Message-State: AOJu0Yzob6tjoJ2OKKmlZeg/gaPs1Iie/SHgeDBhrB2PxvvLTLZqqrpA tK9aqFBlSlVg9Qc/htjVwTdI7hmR6FbiZa6CJ+Roti3v3RxrCkrTzenT5bWYtv7p6CVKPWRZA6t LyjhlT24= X-Gm-Gg: AfdE7cmjs47L17g5qBI+qOAmPopVcbIpBGFS3cNyrBI5ws1ailiPsODKOykpadX5iga Si60IdwhFX3EaVCkLCJK2GfT3PUhrgFjMD8174sqa6rEicAZLnVBiFCOT/LBxKOc9z8wseKWGxb G3mi+AkxAhOMCTwZqFd1YZMBId8qzrlUShle7EjdEKbISKHCM+WSqiLD7YoCa3UW8CRIg/xx10a U7paEN4Aibm3wy1ImaZy2YJs5u/E3QwBzs9bPGioM/N+6tVZXZscKr2JWjjUhu53gTGlBy8dLh1 Qe4uwPOAwvI1VDg0aVsQtCllAiBSTXmxdk68otuHS3MOthG/k5ITACnpxf0WN6Sr7VyP3fy2XBO lwod3lQbrb2TdMfUZ84uEsVgKBwu2MV4sZagdaFySclc4qxv2yiFYhzpn3W3JNrnEo1LCXYrGNC T5RLqBtMcCaf+grsU0cvqKLtmbVfUJ X-Received: by 2002:a05:600c:6091:b0:492:3172:bcf0 with SMTP id 5b1f17b1804b1-492333e8d2amr137937185e9.3.1781785396667; Thu, 18 Jun 2026 05:23:16 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:16 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 25/30] libcamera: software_isp: gpu_pipeline_shader_pass: Add shader DEBUG time logging Date: Thu, 18 Jun 2026 13:22:38 +0100 Message-ID: <20260618122245.946138-26-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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 --- .../software_isp/gpu_pipeline_shader_pass.cpp | 10 ++++++++++ src/libcamera/software_isp/gpu_pipeline_shader_pass.h | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/src/libcamera/software_isp/gpu_pipeline_shader_pass.cpp b/src/libcamera/software_isp/gpu_pipeline_shader_pass.cpp index d0d13eef9..57d60f50e 100644 --- a/src/libcamera/software_isp/gpu_pipeline_shader_pass.cpp +++ b/src/libcamera/software_isp/gpu_pipeline_shader_pass.cpp @@ -57,6 +57,8 @@ int GpuIspShaderPass::process(eGLImage &eglImageIn, eGLImage &eglImageOut, uint3 glViewport(0, 0, width, height); glClear(GL_COLOR_BUFFER_BIT); + eglBenchMark_.begin(egl_); + glDrawArrays(GL_TRIANGLE_FAN, 0, DEBAYER_OPENGL_COORDS); err = glGetError(); if (err != GL_NO_ERROR) { @@ -64,9 +66,17 @@ int GpuIspShaderPass::process(eGLImage &eglImageIn, eGLImage &eglImageOut, uint3 return -ENODEV; } + eglBenchMark_.end(egl_); + return 0; } +void GpuIspShaderPass::printShaderBenchMark(void) +{ + LOG(GpuShaderPass, Debug) << + "ShaderPass = " << this->name() << " took " << eglBenchMark_.getTimeElapsedSync(egl_) / 1000 << " us"; +} + int GpuIspShaderPass::start() { return 0; diff --git a/src/libcamera/software_isp/gpu_pipeline_shader_pass.h b/src/libcamera/software_isp/gpu_pipeline_shader_pass.h index a329845ee..0cff531e9 100644 --- a/src/libcamera/software_isp/gpu_pipeline_shader_pass.h +++ b/src/libcamera/software_isp/gpu_pipeline_shader_pass.h @@ -74,8 +74,12 @@ public: */ GLint glFormat_; + void initShaderBenchMark(void) { eglBenchMark_.init(); } + void printShaderBenchMark(void); + protected: eGL& egl_; + eGLBenchMark eglBenchMark_; /* Shader calculates this getter provides ability to interrogate if needed */ unsigned int bytesPerPixel_; From patchwork Thu Jun 18 12:22:39 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26960 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 6C2BFC3333 for ; Thu, 18 Jun 2026 12:23:40 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E5F66656DB; Thu, 18 Jun 2026 14:23:39 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="a2jRMA3N"; 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 DB27D656B8 for ; Thu, 18 Jun 2026 14:23:17 +0200 (CEST) Received: by mail-wr1-x430.google.com with SMTP id ffacd0b85a97d-461edb387ddso993048f8f.3 for ; Thu, 18 Jun 2026 05:23:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785397; x=1782390197; 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=MkNjYBeWEiuiQCIa3/fw0IZi4AbXB6fTVkVhV6295v0=; b=a2jRMA3N5Y/gQCdg2tXgBMVOhI4qsZWZb2FvBhWVlveU693hDydWIAHfDP/wNUwfRo gG87ab2VRr+8M1cE/onIpTKEjDTtU/LIe80Q4rlCiXIImzBsPRnpZ0pXro2wkTbh6zVY YlRi0eT/Lj1jgRUhASxi7jO7yHRBF3+8gIeckppORkqo8DjDVgggS91dEa1/ws3b0j4Y F/LVzovqHSL/XLepy/pFJbV+oPpuJgwokpyCAZ82L2IiLYClhtFUSJv5HQb0fqepPARa 3/YFufP0tnHzicKnhROgytq6qPh9g6/22qQ+DI4qtgzpvIMahDwiXF+5+aZX73WaPOl1 2GVA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785397; x=1782390197; 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=MkNjYBeWEiuiQCIa3/fw0IZi4AbXB6fTVkVhV6295v0=; b=oRQAPyOMEqCMymc+sNIEDI0WOuZtzIVdVJv1S2GYfa32739g7MZAKQUrEKRuR6IDy5 X/AfrhXZ3f4qr5JV/uGfngc1fLHttSuF90DLmS/+brLnde1r0B0Z2UksFIS/M/cMDy7L i4uLRoV0e5Mef6YkoWSHGb5huiVuthzL2RpEgaeM1Gyvh5Rd6uBtNWl5sOMXVxIE6nK7 VbfFTvk07jKWi9YTWNx6HTBH8NbUk6xUa5Q4L5IPXHuaLA22+X3yaqTJLD5+N4pEn8zL yIL2ApNFGg/pJchvn+I5cunvKNJ+gsEGCfAAWhsZnhbcItQ8GVXPsABjMatuIjIYkJ0L gTrg== X-Gm-Message-State: AOJu0YyXLMwqrpFn0VrdfLEGUqgX9KD/XRufeaY2uOCy5CYNwpwl8c9L G4BBcZ+pMe2OgJbV5z+iDsqzYrpdXUjtMNYhRfNHOsy856Ly973t0d0oug9kXC3QIW2+sqnS385 7a+6as2M= X-Gm-Gg: AfdE7cnfqgNE5sKiMBnljNgzA8XS2KRKFtUEri6Hc2B5NaGE7dP3vnPKXqeGG1xjK26 aml8/shmES4GvzPi4JprJw++A8FNhF4BMrpLPqi7zKpw2wzQ47q5V76wZrF3jV7DCFqegOT6wdp govt4rjG1XEOjzc0qrjF8lvoz/kEX02AQL9/sPUsSk/SRZOl3nQlENWJPw5K0ylhXYSa8exFU/u bNlCRz+fMBk/1bystsGo8C9UHv651gWc+EWN8J0KilX3GhoeK/pu0ZXBq8LLG5ieTezhVom9Qbn zJXYJELAKYeuSBUbbMz8FAxCplWncjnnQixJua/3m22JvXOPp2jDimW/i9buMo2cGjMHRbRCAY8 zvCwtpLk+Anyj5dzXI/51TmP3wdzt+kJOJmxs2QedwEGzx1Fj+dwcAN+7RwlVPzdsTFuAV3ebET 59fzmdlBMaam7VVa/Y4CODyn30BUQU X-Received: by 2002:a05:600c:1f83:b0:492:25a0:1730 with SMTP id 5b1f17b1804b1-4923c4adebfmr16858385e9.32.1781785397397; Thu, 18 Jun 2026 05:23:17 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:17 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 26/30] libcamera: software_isp: gpu: Do a synchronous BenchMark print after syncOutput Date: Thu, 18 Jun 2026 13:22:39 +0100 Message-ID: <20260618122245.946138-27-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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" Doing an optional synchronous print after syncOutput. The GPU has finished at this point so we can interrogate how long each shader took to execute. Only really interesting for a debug scenario. Signed-off-by: Bryan O'Donoghue --- .../software_isp/software_isp_pipeline_gpu.cpp | 15 +++++++++++++++ .../software_isp/software_isp_pipeline_gpu.h | 2 ++ 2 files changed, 17 insertions(+) diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp index 14f6d2b8c..d7bed8837 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp @@ -122,6 +122,12 @@ int SoftwareIspPipelineGpu::initBayerShaders(PixelFormat inputFormat, PixelForma return ret; } +void SoftwareIspPipelineGpu::initShaderBenchMarks(void) +{ + gpuIspShaderPassBlcNormalise_.initShaderBenchMark(); + gpuIspShaderPassDemosiac_.initShaderBenchMark(); +} + int SoftwareIspPipelineGpu::configure(const StreamConfiguration &inputCfg, const std::vector> &outputCfgs, [[maybe_unused]] bool ccmEnabled) @@ -283,6 +289,12 @@ int SoftwareIspPipelineGpu::processGPU(FrameBuffer *input, FrameBuffer *output, return pipelineResult; } +void SoftwareIspPipelineGpu::printShaderBenchMarks(void) +{ + gpuIspShaderPassBlcNormalise_.printShaderBenchMark(); + gpuIspShaderPassDemosiac_.printShaderBenchMark(); +} + void SoftwareIspPipelineGpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms) { bench_.startFrame(); @@ -323,6 +335,7 @@ void SoftwareIspPipelineGpu::process(uint32_t frame, FrameBuffer *input, FrameBu egl_.syncOutput(); bench_.finishFrame(); + printShaderBenchMarks(); outputBufferReady.emit(output); inputBufferReady.emit(input); @@ -349,6 +362,8 @@ int SoftwareIspPipelineGpu::start() if (initBayerShaders(inputPixelFormat_, outputPixelFormat_)) return -EINVAL; + initShaderBenchMarks(); + /* Raw bayer input as texture */ eglImageBayerIn_ = std::make_unique(gpuIspShaderPassBlcNormalise_.glFormat_, inputConfig_.stride / gpuIspShaderPassBlcNormalise_.getBytesPerPixel(), height_, inputConfig_.stride, GL_TEXTURE0, 0); diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.h b/src/libcamera/software_isp/software_isp_pipeline_gpu.h index 8a922f658..b32d4cad3 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.h +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.h @@ -63,6 +63,8 @@ private: int getShaderVariableLocations(); void setShaderVariableValues(const DebayerParams ¶ms); int processGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms, std::optional *mappedInputBuffer, std::optional *inputBufferDmaSyncer); + void initShaderBenchMarks(void); + void printShaderBenchMarks(void); /* Pointer to object representing input texture */ std::unique_ptr eglImageBayerIn_; From patchwork Thu Jun 18 12:22:40 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26959 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 98E03C3332 for ; Thu, 18 Jun 2026 12:23:39 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 09F3E656DD; Thu, 18 Jun 2026 14:23:39 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="W0rbTAmm"; 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 9649262C75 for ; Thu, 18 Jun 2026 14:23:18 +0200 (CEST) Received: by mail-wm1-x330.google.com with SMTP id 5b1f17b1804b1-490b12270b3so4543205e9.1 for ; Thu, 18 Jun 2026 05:23:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785398; x=1782390198; 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=jk6VjmJB52VBfryw+VvVOx5GPW7iwAzDIFqNQWEf2q0=; b=W0rbTAmmlkNMdDRYN7Slug0qb4gfL51I5Ib1Tv+RuBWfPxtfrWbHi5GaWkn4wg2AYj d2QcVEyk2tRmaCp23qktEhBEtJEb/nHh29PyAbkcxLVXNwvunsZsfiXu6uW7NAZTZFP3 4CZfQlXaWhmRHoYyQF6MghjG0UKHTNcWVkb/GYfILsH1YGOFqyGHQGRszYtCilsRgLDc QbTkvw3OtIs0o9MaPF4Eb53Mrp1/TaQRjbYb4dEP8jEhkVO59fgEQPvrWctQ5KO6+Uxz dvnuCvKaPTIaRbRMrSD5y3yihhUd0oFYMpb8RL9xwLTNqcgZHcz89cALHZNfbfWQQbbz Y+2g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785398; x=1782390198; 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=jk6VjmJB52VBfryw+VvVOx5GPW7iwAzDIFqNQWEf2q0=; b=rs5x4ajLI6Cc66BAleirndx0AYcu9fBlH6UfAu9i5wmgfq1uNrkUcOmblyUkTTBWK/ 0aTpft6jONJLrWYI+y+vvIqGw2mTVvXsJHJEd72UBuT00fmhHuWOdXlrirfDlCeaSCAa JxeJSY5qqaHcxNNRzGu6+dnyoCkMsZBNtlrBQYQtRBTkG/sZJxCreByh0URTCWZTTcdi Oee0LBG7gv0bZwqs8nOovrmAmfe9ws2cJnkSZSMUTw3wlHE7Cd4Z3En5WihSJMqx7GtG WcjM+StIiBrferGwbDcf6mBEabHrwO0kguP6knyjGcDFEmgHiSgi1OGibnbXLbQGz2pw 9m3A== X-Gm-Message-State: AOJu0YxxEj2vTLtZ5/a8MMxQGt91vTaTxzrpnjbW7NEcsBuzeZ9JLy9V s4nqADHc5cM4CxXUYjWwruXzGy6W/F7AhkygeVZRcoIaIkafFhSM+qXp/f1SOUWn0KcweLUUnl8 sO9ZVcD0= X-Gm-Gg: AfdE7cmdV9BJTVOXz+gs09PEh7DXmzqUo1IDHP8XBsgErFYeJEMjYacc6KUs1K2eV/4 2mfMAbE4gyjFKjswAwDxj4VZe/6i8sKb+6y7jQP4g0ISrXwy7cj2dsx4P7FuOZ4UoSfOzoNMDmF 5Xfxezu0kAFvtpWd3rwMdYeuL4lcHHOTZH6nsg5jahOVYlAhjAk6s0Sov+LitkO2eH7cv1yeHjK v4+OiEW+FQlhQB0Uh9Y3vANf7e7/66qgpYyMwdfua8ueby7hHLCVL2S9e3BAnZqcwsDvs6kr0hm 0COoADtAlbGrneUzWw/nf0Tn3hMLfpspdIjxxoj0Gi7gWNigIFoA2Bd+KQ2yvWRBSI74rcUoPaV y9cQWCpGohXZnKlfXqPupfOnn9oHr1t/hnL01kr+XmeFCmFL8v80FmqffXluX0+n2d5f9DaTvIE s3W/jXNUM02zC1nNHxXWCFopEHtD+5 X-Received: by 2002:a05:600c:4e54:b0:492:328f:8623 with SMTP id 5b1f17b1804b1-49234139d57mr135580655e9.31.1781785398158; Thu, 18 Jun 2026 05:23:18 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:17 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 27/30] libcamera: software_isp: egl: Add updateInputTexture2D Date: Thu, 18 Jun 2026 13:22:40 +0100 Message-ID: <20260618122245.946138-28-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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" The internet box tells me that glTextSubImage2D lets us update a texture's data only, instead of recreating the texture and uploading data. This is a smallish optimisation but we are hunting for every possible cycle and watt so add the routine as precursor to using it in-place of createTexture2D on every upload cycle. Signed-off-by: Bryan O'Donoghue --- include/libcamera/internal/egl.h | 1 + src/libcamera/egl.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h index 8f905416a..c9b3a4e81 100644 --- a/include/libcamera/internal/egl.h +++ b/include/libcamera/internal/egl.h @@ -107,6 +107,7 @@ public: int createInputDMABufTexture2D(eGLImage &eglImage, int fd); int createOutputDMABufTexture2D(eGLImage &eglImage, int fd); void createInputTexture2D(eGLImage &eglImage, void *data); + void updateInputTexture2D(eGLImage &eglImage, void *data); void createOutputTexture2D(eGLImage &eglImage); int attachTextureToFBO(eGLImage &eglImage); diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index 2fc10b800..fc1516634 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -297,6 +297,33 @@ void eGL::createInputTexture2D(eGLImage &eglImage, void *data) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } +void eGL::updateInputTexture2D(eGLImage &eglImage, void *data) +{ + GLenum format; + GLenum type = GL_UNSIGNED_BYTE; + + ASSERT(tid_ == Thread::currentId()); + + glActiveTexture(eglImage.texture_unit_); + glBindTexture(GL_TEXTURE_2D, eglImage.texture_); + + switch (eglImage.format_) { + case GL_R16F: + format = GL_RED; + type = GL_HALF_FLOAT; + break; + case GL_RG8: + format = GL_RG; + break; + case GL_LUMINANCE: + format = GL_LUMINANCE; + break; + } + + // Update an already exsiting texture + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, eglImage.width_, eglImage.height_, format, type, data); +} + /** * \brief Create a 2D texture attached to an FBO for render-to-texture * \param[in,out] eglImage EGL image to associate with the texture From patchwork Thu Jun 18 12:22:41 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26961 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 F0DAEC3334 for ; Thu, 18 Jun 2026 12:23:40 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 862A7656E1; Thu, 18 Jun 2026 14:23:40 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="rDiPphOT"; dkim-atps=neutral Received: from mail-wm1-x32f.google.com (mail-wm1-x32f.google.com [IPv6:2a00:1450:4864:20::32f]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 86C186301A for ; Thu, 18 Jun 2026 14:23:19 +0200 (CEST) Received: by mail-wm1-x32f.google.com with SMTP id 5b1f17b1804b1-490ace40f4bso8813235e9.3 for ; Thu, 18 Jun 2026 05:23:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785399; x=1782390199; 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=++p7rbbpyQ4ktzzlFiMkpZEdxhGxm60fKHrNbbt6c5w=; b=rDiPphOTWXbscs6ah858KkcGdH0F5C/LKNHLYgr0+b3MCBSk9KUiBqnhSdza1wx33S wheDfQgBSVoTX4tUZD7nlF4Xln9zZx28t8wXrTqWlZn3qCoyOGoba0Tpc87FTLj8lYpx ZLIb7l1EImewa+7ZuzVGxihSoxYUgweDjD6hOUs/MdKcHvYDNBjPw7TQoYhSocVh3l4r rgDXeWquIx7uleWprXa3o+4K0ZeMCKWgD8SCeaB2oySnLXELoaEYAnPaih1DocbeUMKc texae6vYi25mmIuFhfKmAbdPSnromSNXGiQOYWwKIUqIlfn5Ntgyl1TA7kLP5jpcZVJa F0wA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785399; x=1782390199; 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=++p7rbbpyQ4ktzzlFiMkpZEdxhGxm60fKHrNbbt6c5w=; b=HFHHqUyeufXLrPC+MVYSjKDdx+GDZHH/1pLbjIu4paFRwe/AV8NgNaQ5Eju7AZQrwc mybdMDh5XlF8ZRIbmOgMC8vd1+dsosUmqGaIEi8pTQduhSpYKvF8Ke3/VVL0P9vG/ckJ rHU0ESWyZW8dP2RzgTX9OFEvohafcQYozvMV0muItf0M3a+z3omlnHcBZYos2DztoiVd mw7eY7Asv+QdSLsHHYtHl6X63ASz8R++X6+tkEhH4T2rxLuQbkhAd5mLrC5dHhYoCn97 OT2bdt0UYYtJGyGFQiUNm6tLhnVm9N6dt39ynB1HtVLYUSHw/mcYlb++HeuHRQQqS3nK JQcw== X-Gm-Message-State: AOJu0YwWy6DfTFLb+05J0ZB0J8x+0m3kqDyT6fsclYBZqcdnGE3mJYGd HDsU4ddX6j6A3kURbB6W/XiMxBtXnjMKcAW7SCS0zAhc/pGrJawBPaAyQVeuthbGMkccQxRvmoh bvNLz+co= X-Gm-Gg: AfdE7cmGscwP6ptLktjSa51kDY8HKD1lgCHKf8MOF4m6EBL193BwpT0GWvpSVdg/FYh Jdv10BO3VBVGrZcvAfYNdfsaIyoRKzc57ncBQHdBRmCwOybKhWkkTvpx7kknssKsXBnLS8zNL+G v2kgFxu7lRPRLbyIpp7ww2groI2PQMRDrqawz8q5M7y4ciVzCLqeQx1w+GosWhNswLeodEIfj1A mHekUsUkJ2uOzXqEPzLpOIjFRBl/xfDp8lW8XVIA3+sFlP8PuNOMclvwx0MBT7DVQVXS/C6PqHP S53DEtCQPvK7NShbjP4iTi596RoaK6apHGL0FyHxnLYUlzgts4azThfogMRrV4fKd8SgZHyrFsv qeCzK6TgY5F390EuTKmBzkttzU7F0tH365Px1AiIytH1EFvy7sj+01Z+CObxKKH4sKbnPG30xMZ vGiV4I7cEIiUy1vSPn6q68Kv3Rxz91Pj0lMCSV/gs= X-Received: by 2002:a05:600c:8010:b0:490:bad9:de43 with SMTP id 5b1f17b1804b1-492381a5b88mr58651855e9.0.1781785399097; Thu, 18 Jun 2026 05:23:19 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:18 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 28/30] libcamera: software_isp: gpu: Switch to using glTexSubImage2D on slow path upload Date: Thu, 18 Jun 2026 13:22:41 +0100 Message-ID: <20260618122245.946138-29-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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 the right thing to do but, isn't the thing that is costing us right now. We know this is slightly faster, emphasis on the slightly anything with less than a millisecond of performance increase is not easily measured. Signed-off-by: Bryan O'Donoghue --- src/libcamera/software_isp/software_isp_pipeline_gpu.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp index d7bed8837..2e5c0e40e 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp @@ -260,7 +260,7 @@ int SoftwareIspPipelineGpu::processGPU(FrameBuffer *input, FrameBuffer *output, LOG(Debayer, Error) << "mmap-ing buffer(s) failed"; return -ENODEV; } - egl_.createInputTexture2D(*eglImageBayerIn_, inMapped->value().planes()[0].data()); + egl_.updateInputTexture2D(*eglImageBayerIn_, inMapped->value().planes()[0].data()); } /* Generate the output render framebuffer as render to texture */ @@ -374,6 +374,7 @@ int SoftwareIspPipelineGpu::start() /* Texture we will render to */ eglImageRGBAOut_ = std::make_unique(GL_RGBA, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE3, 3); + egl_.createInputTexture2D(*eglImageBayerIn_, NULL); egl_.createOutputTexture2D(*eglImagePingPong_[0]); egl_.createOutputTexture2D(*eglImagePingPong_[1]); From patchwork Thu Jun 18 12:22:42 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26962 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 CC6BDC3336 for ; Thu, 18 Jun 2026 12:23:41 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 33295656D5; Thu, 18 Jun 2026 14:23:41 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="ulN39u/v"; dkim-atps=neutral Received: from mail-wm1-x32f.google.com (mail-wm1-x32f.google.com [IPv6:2a00:1450:4864:20::32f]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 565D462C79 for ; Thu, 18 Jun 2026 14:23:20 +0200 (CEST) Received: by mail-wm1-x32f.google.com with SMTP id 5b1f17b1804b1-490be29c1c5so7266975e9.2 for ; Thu, 18 Jun 2026 05:23:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785400; x=1782390200; 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=BSSR9mqCpqCL14/lAv+iQMfbEByDwn/6jQSAQFMK9Uk=; b=ulN39u/vepRrWNuE8EurZwCDWMx+zsS/lvgCxaFMubnBwUcXgfeTjn+qXtXAj5ESWe 5p4/nEP1fnInrdCLwzVDV4Ge1P6ZC+ZpNcopB7nh3BA2ZafQ8R6JOIqxunaRw7ItkyIG FyC2rtseD6NYNWcfZYfhPb8hBpp53Cc7fhTeZQ+fhvIcp817bdDtyQnIfcXH2pSxbate kxg35V3GRU1B3lmwXm5bJGthzwqWKJjTxy0HE/BXXywbPfPN+n02f5NwB2l8d51nEmk1 hH8+bs0KmSWo9ig8Kr5zoAxGaer9D18E6DalWq95HiaRpyKLg4Fmg370V7PnoVCff5L3 kmQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785400; x=1782390200; 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=BSSR9mqCpqCL14/lAv+iQMfbEByDwn/6jQSAQFMK9Uk=; b=ToUvBDiMYNGghmAuWQtMmBWoE++ii/SQmJ7yFaSVF4sOmZx99ZSaJOpMSBvOh0uYwg ILdpmdODOcZyFVh4lp7i8cReJCM29zTXwS5ZN2jmVmu8Wkqs3AH5r0Ht5M4DYKf73lj9 p2WcONx7mghAIYsAq2bDL6NwBevlH/UyGc8LCFvcIVIF08fHNochknhF91GmHrkirQoQ bZKYKGSz+pWZKqNBSYBGfhZ6/gGTHbgrGkkOC9CuDpCfR59aZKZdW6KKls2GY1dx8fT5 HOgM1BqEHItEnJhwa6f72dM5rj82zDKjG0mAP130V/niBuCuguYF0PqQC+r0kLhl6aYR jcLQ== X-Gm-Message-State: AOJu0Yyk0exkg041SkaVAgVktF6xmcmBvUR/wRpQvSDI43ou5CEi5CM7 JQKj1ag8Dskmj2efuZOfxTRqLQD6pDB4wj3RoitIdI8K0g7gLXH0t0Gbgni55b+8EcNSJBGwaP7 d4b8GBS8= X-Gm-Gg: AfdE7cmxL60flH/TpejeMgpr7RHSxIO2vXew8P7VXt3CrjY6thLRYoTQviOtvCutQ7O sixGCX71TXBIGpgrAMSTq8mefCBqJRcnEQ8zhr3yuB7a89FtpxUPU4q+/qQ39pW4RSqj6i62VOE tk/mu6hBa+adubzcBLonNTS2gWJB2Y+xqxxeeZYFffpp/Vv+NHY28ayDHPRk61hHmauqhT5+7nb h+F16wGQai4Srmq1kJPoK/qD6oCpjlCIHjSvOHHF/7WdAgO825uPoOOzQksrL8yQNDH8RBHCS3u Vp+e1Gfs+Jjt5i8gjPSC9zoULno9R81SsAjDiCvpUznyxbi5dn3BUaycVRcy6/Y6GgPnibEXtua yN/1X5s6BxFGbfYShjmVJxHIm3ffHGBQgi8bWRgwfwu4msduhjkHGEriSqEXgkMI2etWkZ6y3U2 4dYNWLPlcQ8VfwgjNh+L9I44Ysk0uL X-Received: by 2002:a05:600c:e54a:10b0:490:e104:7943 with SMTP id 5b1f17b1804b1-492333e294dmr102239425e9.18.1781785399781; Thu, 18 Jun 2026 05:23:19 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:19 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 29/30] libcamera: software_isp: gpu: Cache output framebuffers, only recreate when necessary Date: Thu, 18 Jun 2026 13:22:42 +0100 Message-ID: <20260618122245.946138-30-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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" Once a texture has been created using dma-buf handle, we can switch texture units and ids with our glsl program without re-creating textures. Since we are mapping pages, instead of copying the GPU simply takes the maps it needs and operates on those. Much faster. ➜ libcamera git:(0.7.0-multipass-v4) ✗ grep Bench before.log [15:07:08.009062165] [1195303] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 729270us, 24309 us/frame [15:07:11.686143411] [1195334] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 733995us, 24466 us/frame [15:07:14.980640685] [1195363] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 740157us, 24671 us/frame [15:07:18.163299379] [1195393] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 720094us, 24003 us/frame [15:07:21.366461990] [1195422] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 719166us, 23972 us/frame [15:07:24.718877325] [1195451] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 725425us, 24180 us/frame [15:07:28.924768220] [1195481] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 753400us, 25113 us/frame [15:07:32.336224289] [1195513] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 727160us, 24238 us/frame [15:07:35.638928194] [1195542] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 762408us, 25413 us/frame [15:07:38.868084716] [1195579] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 728991us, 24299 us/frame ➜ libcamera git:(0.7.0-multipass-v4) ✗ grep Bench after.log [16:26:07.109426223] [1202010] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 650120us, 21670 us/frame [16:26:18.925748074] [1202048] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 611062us, 20368 us/frame [16:26:22.712614967] [1202077] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 609333us, 20311 us/frame [16:26:26.551615514] [1202107] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 609791us, 20326 us/frame [16:26:30.085663553] [1202136] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 612838us, 20427 us/frame [16:26:34.945255617] [1202165] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 681918us, 22730 us/frame [16:26:39.031353171] [1202194] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 595551us, 19851 us/frame [16:26:42.610503048] [1202227] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 663929us, 22130 us/frame [16:26:46.100211690] [1202256] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 580685us, 19356 us/frame [16:26:49.394640903] [1202286] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 595072us, 19835 us/frame Signed-off-by: Bryan O'Donoghue --- .../software_isp/software_isp_pipeline_gpu.cpp | 17 ++++++++++------- .../software_isp/software_isp_pipeline_gpu.h | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp index 2e5c0e40e..bc5d59575 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp @@ -263,8 +263,14 @@ int SoftwareIspPipelineGpu::processGPU(FrameBuffer *input, FrameBuffer *output, egl_.updateInputTexture2D(*eglImageBayerIn_, inMapped->value().planes()[0].data()); } - /* Generate the output render framebuffer as render to texture */ - egl_.createOutputDMABufTexture2D(*eglImageRGBAOut_, output->planes()[0].fd.get()); + /* Find an existing eglImage in the cache */ + auto [output_cache, output_miss] = eglImageRGBAOut_.try_emplace(output); + if (output_miss) { + /* Generate the output render framebuffer as render to texture */ + output_cache->second = std::make_unique(GL_RGBA, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE3, 3); + egl_.createOutputDMABufTexture2D(*output_cache->second, output->planes()[0].fd.get()); + } + eGLImage &eglImageRGBAOut = *output_cache->second; pipelineResult = gpuIspShaderPassBlcNormalise_.process(*eglImageBayerIn_, *eglImagePingPong_[0], width_, height_, params); if (pipelineResult) { @@ -272,7 +278,7 @@ int SoftwareIspPipelineGpu::processGPU(FrameBuffer *input, FrameBuffer *output, return pipelineResult; } - pipelineResult = gpuIspShaderPassDemosiac_.process(*eglImagePingPong_[0], *eglImageRGBAOut_, width_, height_, params); + pipelineResult = gpuIspShaderPassDemosiac_.process(*eglImagePingPong_[0], eglImageRGBAOut, width_, height_, params); if (pipelineResult) { LOG(Debayer, Error) << "Demosiac fail"; return pipelineResult; @@ -371,9 +377,6 @@ int SoftwareIspPipelineGpu::start() eglImagePingPong_[0] = std::make_unique(gpuIspShaderPassDemosiac_.glFormat_, width_, height_, outputConfig_.stride, GL_TEXTURE1, 1); eglImagePingPong_[1] = std::make_unique(gpuIspShaderPassDemosiac_.glFormat_, width_, height_, outputConfig_.stride, GL_TEXTURE2, 2); - /* Texture we will render to */ - eglImageRGBAOut_ = std::make_unique(GL_RGBA, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE3, 3); - egl_.createInputTexture2D(*eglImageBayerIn_, NULL); egl_.createOutputTexture2D(*eglImagePingPong_[0]); egl_.createOutputTexture2D(*eglImagePingPong_[1]); @@ -383,7 +386,7 @@ int SoftwareIspPipelineGpu::start() void SoftwareIspPipelineGpu::stop() { - eglImageRGBAOut_.reset(); + eglImageRGBAOut_.clear(); eglImagePingPong_[1].reset(); eglImagePingPong_[0].reset(); eglImageBayerIn_.reset(); diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.h b/src/libcamera/software_isp/software_isp_pipeline_gpu.h index b32d4cad3..995e84295 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.h +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.h @@ -69,7 +69,7 @@ private: /* Pointer to object representing input texture */ std::unique_ptr eglImageBayerIn_; std::unique_ptr eglImagePingPong_[2]; - std::unique_ptr eglImageRGBAOut_; + std::unordered_map> eglImageRGBAOut_; std::unique_ptr stats_; eGL egl_; From patchwork Thu Jun 18 12:22:43 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Bryan O'Donoghue X-Patchwork-Id: 26963 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 9A7CFC3338 for ; Thu, 18 Jun 2026 12:23:42 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E754E656E3; Thu, 18 Jun 2026 14:23:41 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="VM7Z0FcQ"; 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 15843656C4 for ; Thu, 18 Jun 2026 14:23:21 +0200 (CEST) Received: by mail-wm1-x334.google.com with SMTP id 5b1f17b1804b1-490ae94a89eso6315175e9.1 for ; Thu, 18 Jun 2026 05:23:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1781785400; x=1782390200; 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=PAemZUMSTf1dCHeubdqFLgMjI0YFMUlFc/W87+NWYEI=; b=VM7Z0FcQnq9kcqs41MC3Ncjfnkbmimb58hUY1O3VMspqHEbm9NM42jbrGOcKuwBAbo ssbykuTPQG19U7Vm4Kh/7qIyIBnFJiFGBBs8sRzRbjdXRUPd+OnzpYn9h8Jw4I+YisKO dFPU/LhcIyyjabai1HoOB9/eb12c4hdAdNL7gch0HMnUaHjuFgxKVnezmQm8Q70sNmhe /rBg6phfPFT1yZiYnFscPC2RHwA4jJw1vDfoNsqcBdqy2pp5mv3TEmMmO9Wqwd1D/tKJ c1FsBmc37pLaxiEA3ttYf48VlHUGR1Tgotcg0HlnW7q7KA2WOThwDd6PgEeW8gN6bjea J85Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781785400; x=1782390200; 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=PAemZUMSTf1dCHeubdqFLgMjI0YFMUlFc/W87+NWYEI=; b=rQr9qPQxoBhpcsZcluv2eS3ja/tss9YbSEjuDMcy+zF5gijhN991QxZPH4EDffNVya 3F2TEUAUMQ6fnYp3+vU9pxYb00TK6bNzzzRw/dF+8nQbUA35+f/5EzZSLzNwAUFViVRR z59sx05sxKDwLqU0WCMl+XF3AwMS6LW5wP6AaWhOBCJVPpdIAf7yB+7F9iPR8+PJqRki 0HTq8LlGWglh77RODWjSLj1YSPB/u19IlYtirGRsdWcXNVzVls0vnlbeDPm2Bgqwdt6c 25zqybK0cmjbYxRTjZ4kmRgKojsCsHGVCfq/QfQXIWnrFEFrDDlG64NnDivkU4VvCI4P eTLw== X-Gm-Message-State: AOJu0Yy2cPU3kji8cjQ65PE+FiVQlDrQdmZs9TDstqNTm21q9VQfbrQY rZtJkXIPLu5Ldvs4D0dcv+03M3nE3KSmTpKdnmz5/sT3smKljHzrbmb+bn0z7RclwCcF4H+EC6D L6aZh37Y= X-Gm-Gg: AfdE7ck6HTYfQghPHrdLh6luK1MBb5ydH5NjLzkVT1hLwbtzyC4RwsOWFZcD2xUisxW uPJA5R9/dBXv1WG8Cpr/NJ3qrSPhmaQzs9CLh7Nntgw3hms+jK6OslikeWb/zEV2A4WFuOvH7QP fuaCX/5QZZ8qQGOgvb/T7m2Yxk1mGAxQ44WjRNoUoFPQGtGxK37BmVA0gGys0Qm0TkewYzpJp6u aI3s5wNxCa2FMpxy6Io8+8m1+81co0OAlkxONlCxFgU7aPeTT4kexJgMP/gmFCCI2nhAXW7l7xo OwklbRWSKpW+JX5mNaaQp2LyMin4BpDd0+mB5bFi84w02g3gcXNcuA3j9rle9rL1LCAv7HX78PI MnVkxr3NqWQH60mT6OT6pVXDEraPJs6WxOSnhuJ4ywsaPbEp7PdYJpr2lvaILwWBVHPnDIhM8G3 ZGUQyQQDhNxhQ+9EGHZqMjHu6nWf1v X-Received: by 2002:a05:600c:3acd:b0:492:1edf:9fbc with SMTP id 5b1f17b1804b1-492381e4a2cmr48878855e9.1.1781785400445; Thu, 18 Jun 2026 05:23:20 -0700 (PDT) Received: from inspiron14p-linux ([109.76.144.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4922fa3a4easm275198015e9.3.2026.06.18.05.23.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jun 2026 05:23:20 -0700 (PDT) From: Bryan O'Donoghue To: libcamera-devel@lists.libcamera.org Cc: bryan.odonoghue@linaro.org, pavel@ucw.cz Subject: [PATCH 30/30] libcamera: software_isp: gpu: Cache input framebuffers, only do texture creation when required Date: Thu, 18 Jun 2026 13:22:43 +0100 Message-ID: <20260618122245.946138-31-bryan.odonoghue@linaro.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260618122245.946138-1-bryan.odonoghue@linaro.org> References: <20260618122245.946138-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" Implement a cache of input textures - making one texture for each input FrameBuffer we see. ➜ libcamera git:(0.7.0-multipass-v4) ✗ grep Bench after.log [26:30:50.382000193] [1232323] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 594603us, 19820 us/frame [26:30:57.401535061] [1232356] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 573922us, 19130 us/frame [26:31:00.693007555] [1232386] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 619533us, 20651 us/frame [26:31:04.943431215] [1232415] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 595097us, 19836 us/frame [26:31:08.495371222] [1232444] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 596719us, 19890 us/frame [26:31:14.057239566] [1232479] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 586299us, 19543 us/frame [26:31:18.201198235] [1232509] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 639572us, 21319 us/frame [26:31:21.971954439] [1232539] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 610732us, 20357 us/frame [26:31:25.391881496] [1232574] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 596533us, 19884 us/frame [26:31:29.887852761] [1232603] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 552319us, 18410 us/frame ➜ libcamera git:(0.7.0-multipass-v4) ✗ grep Bench before.log [26:32:12.443884778] [1232907] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 591871us, 19729 us/frame [26:32:21.394113992] [1232943] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 634355us, 21145 us/frame [26:32:24.923236983] [1232983] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 601128us, 20037 us/frame [26:32:28.173610317] [1233017] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 578252us, 19275 us/frame [26:32:33.265933583] [1233050] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 598317us, 19943 us/frame [26:32:36.590115049] [1233091] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 586617us, 19553 us/frame [26:32:40.014877516] [1233127] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 594843us, 19828 us/frame [26:33:03.293347156] [1233182] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 586804us, 19560 us/frame [26:33:07.471525107] [1233221] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 615955us, 20531 us/frame [26:33:13.015977863] [1233262] INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 576757us, 19225 us/frame Signed-off-by: Bryan O'Donoghue --- .../software_isp_pipeline_gpu.cpp | 25 ++++++++++++------- .../software_isp/software_isp_pipeline_gpu.h | 2 +- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp index bc5d59575..0bcd4df58 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp @@ -244,9 +244,18 @@ int SoftwareIspPipelineGpu::processGPU(FrameBuffer *input, FrameBuffer *output, /* eGL context switch */ egl_.makeCurrent(); + auto [input_cache, input_miss] = eglImageBayerIn_.try_emplace(input); + if (input_miss) { + /* Raw bayer input as texture */ + input_cache->second = std::make_unique(gpuIspShaderPassBlcNormalise_.glFormat_, + inputConfig_.stride / gpuIspShaderPassBlcNormalise_.getBytesPerPixel(), + height_, inputConfig_.stride, GL_TEXTURE0, 0); + } + eGLImage &eglImageBayerIn = *input_cache->second; + /* Try to create texture for input buffer via dmabuf import */ - if (!eglImageBayerIn_->dmabuf_import_failed_) { - if (egl_.createInputDMABufTexture2D(*eglImageBayerIn_, input->planes()[0].fd.get()) == 0) + if (!eglImageBayerIn.dmabuf_import_failed_) { + if (egl_.createInputDMABufTexture2D(eglImageBayerIn, input->planes()[0].fd.get()) == 0) dmabuf_import_succeeded = true; else LOG(Debayer, Info) << "Importing input buffer with DMABuf import failed, falling back to upload"; @@ -260,7 +269,9 @@ int SoftwareIspPipelineGpu::processGPU(FrameBuffer *input, FrameBuffer *output, LOG(Debayer, Error) << "mmap-ing buffer(s) failed"; return -ENODEV; } - egl_.updateInputTexture2D(*eglImageBayerIn_, inMapped->value().planes()[0].data()); + if (input_miss) + egl_.createInputTexture2D(eglImageBayerIn, NULL); + egl_.updateInputTexture2D(eglImageBayerIn, inMapped->value().planes()[0].data()); } /* Find an existing eglImage in the cache */ @@ -272,7 +283,7 @@ int SoftwareIspPipelineGpu::processGPU(FrameBuffer *input, FrameBuffer *output, } eGLImage &eglImageRGBAOut = *output_cache->second; - pipelineResult = gpuIspShaderPassBlcNormalise_.process(*eglImageBayerIn_, *eglImagePingPong_[0], width_, height_, params); + pipelineResult = gpuIspShaderPassBlcNormalise_.process(eglImageBayerIn, *eglImagePingPong_[0], width_, height_, params); if (pipelineResult) { LOG(Debayer, Error) << "BlcNormalise fail"; return pipelineResult; @@ -370,14 +381,10 @@ int SoftwareIspPipelineGpu::start() initShaderBenchMarks(); - /* Raw bayer input as texture */ - eglImageBayerIn_ = std::make_unique(gpuIspShaderPassBlcNormalise_.glFormat_, inputConfig_.stride / gpuIspShaderPassBlcNormalise_.getBytesPerPixel(), height_, inputConfig_.stride, GL_TEXTURE0, 0); - /* Intermediary ping/pong textures */ eglImagePingPong_[0] = std::make_unique(gpuIspShaderPassDemosiac_.glFormat_, width_, height_, outputConfig_.stride, GL_TEXTURE1, 1); eglImagePingPong_[1] = std::make_unique(gpuIspShaderPassDemosiac_.glFormat_, width_, height_, outputConfig_.stride, GL_TEXTURE2, 2); - egl_.createInputTexture2D(*eglImageBayerIn_, NULL); egl_.createOutputTexture2D(*eglImagePingPong_[0]); egl_.createOutputTexture2D(*eglImagePingPong_[1]); @@ -389,7 +396,7 @@ void SoftwareIspPipelineGpu::stop() eglImageRGBAOut_.clear(); eglImagePingPong_[1].reset(); eglImagePingPong_[0].reset(); - eglImageBayerIn_.reset(); + eglImageBayerIn_.clear(); gpuIspShaderPassDemosiac_.stop(); } diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.h b/src/libcamera/software_isp/software_isp_pipeline_gpu.h index 995e84295..e2aceefdc 100644 --- a/src/libcamera/software_isp/software_isp_pipeline_gpu.h +++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.h @@ -67,7 +67,7 @@ private: void printShaderBenchMarks(void); /* Pointer to object representing input texture */ - std::unique_ptr eglImageBayerIn_; + std::unordered_map> eglImageBayerIn_; std::unique_ptr eglImagePingPong_[2]; std::unordered_map> eglImageRGBAOut_;