From patchwork Mon Jun 29 16:29:47 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 27103 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 782A2C3261 for ; Mon, 29 Jun 2026 16:31:13 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EE3F165F62; Mon, 29 Jun 2026 18:31:11 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="dBozKsfz"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6911365F4A for ; Mon, 29 Jun 2026 18:30:26 +0200 (CEST) Received: from pb-laptop.local (185.221.140.128.nat.pool.zt.hu [185.221.140.128]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 4AA8E8D4 for ; Mon, 29 Jun 2026 18:29:43 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1782750583; bh=12oFyoKAW4MODUKyk8bIBhs5scOxY/rAvy72r05GWkc=; h=From:To:Subject:Date:In-Reply-To:References:From; b=dBozKsfzM35H/sNeSBSXHfj+KjxONVZ9VTX2Aqbn3HkEmoyYndkWz909r8VwppmkN ut50dBaNs7aYBNEQgpqBpIQaARK86H+oEhgurfZ+Aqti2MK5FKrNROVDU5tOs1M1/A 5kl9DQ6oF0chWbb1fk/bJcDyXoTLmmz9m33ilZ2s= From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= To: libcamera-devel@lists.libcamera.org Subject: [RFC PATCH v1 24/54] libcamera: request: Remove fence support Date: Mon, 29 Jun 2026 18:29:47 +0200 Message-ID: <20260629163017.863145-25-barnabas.pocze@ideasonboard.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260629163017.863145-1-barnabas.pocze@ideasonboard.com> References: <20260629163017.863145-1-barnabas.pocze@ideasonboard.com> 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" With the split of buffers and requests, fences will need to be handled outside of requests. So remove the current fence support, all the miscellaneous things related to it: * Request::{prepared,prepared_} * PipelineHandler::registerRequest() Signed-off-by: Barnabás Pőcze --- include/libcamera/internal/pipeline_handler.h | 1 - include/libcamera/internal/request.h | 15 -- src/libcamera/camera.cpp | 7 +- src/libcamera/fence.cpp | 5 - src/libcamera/framebuffer.cpp | 10 +- src/libcamera/pipeline_handler.cpp | 24 +--- src/libcamera/request.cpp | 131 ------------------ 7 files changed, 5 insertions(+), 188 deletions(-) diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h index 81ec359981..f90cae253f 100644 --- a/include/libcamera/internal/pipeline_handler.h +++ b/include/libcamera/internal/pipeline_handler.h @@ -59,7 +59,6 @@ public: void stop(Camera *camera); bool hasPendingRequests(const Camera *camera) const; - void registerRequest(Request *request); void queueRequest(Request *request); static bool completeBuffer(Request *request, FrameBuffer *buffer) diff --git a/include/libcamera/internal/request.h b/include/libcamera/internal/request.h index 382ed28bca..8f570e4f79 100644 --- a/include/libcamera/internal/request.h +++ b/include/libcamera/internal/request.h @@ -7,19 +7,13 @@ #pragma once -#include -#include -#include #include #include #include -#include #include -using namespace std::chrono_literals; - namespace libcamera { class Camera; @@ -43,26 +37,17 @@ public: void cancel(); void reset(); - void prepare(std::chrono::milliseconds timeout = 0ms); - Signal<> prepared; - private: friend class PipelineHandler; friend std::ostream &operator<<(std::ostream &out, const Request &r); void doCancelRequest(); - void emitPrepareCompleted(); - void notifierActivated(FrameBuffer *buffer); - void timeout(); Camera *camera_; bool cancelled_; uint32_t sequence_ = 0; - bool prepared_ = false; std::unordered_set pending_; - std::map notifiers_; - std::unique_ptr timer_; ControlList metadata_; }; diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp index 31ab59e0b7..27dae3a403 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -1294,12 +1294,7 @@ std::unique_ptr Camera::createRequest(uint64_t cookie) if (ret < 0) return nullptr; - std::unique_ptr request = std::make_unique(this, cookie); - - /* Associate the request with the pipeline handler. */ - d->pipe_->registerRequest(request.get()); - - return request; + return std::make_unique(this, cookie); } /** diff --git a/src/libcamera/fence.cpp b/src/libcamera/fence.cpp index 73299b4027..92d1b37366 100644 --- a/src/libcamera/fence.cpp +++ b/src/libcamera/fence.cpp @@ -28,8 +28,6 @@ namespace libcamera { * the Fence to be signalled before allowing the camera device to actually * access the memory area described by the FrameBuffer. * - * \sa Request::addBuffer() - * * By using a fence, applications can then synchronize between frame buffer * consumers and producers, as for example a display device and a camera, to * guarantee that a new data transfers only happen once the existing frames have @@ -68,9 +66,6 @@ namespace libcamera { * * A failure in waiting for a Fence to complete will result in the Request to * complete in failed state. - * - * \sa Request::prepare() - * \sa PipelineHandler::doQueueRequests() */ /** diff --git a/src/libcamera/framebuffer.cpp b/src/libcamera/framebuffer.cpp index baa298a8e3..55ca24c8a3 100644 --- a/src/libcamera/framebuffer.cpp +++ b/src/libcamera/framebuffer.cpp @@ -191,9 +191,7 @@ FrameBuffer::Private::~Private() * * If buffer with a Fence completes with errors due to a failure in handling * the fence, applications are responsible for releasing the Fence before - * calling Request::addBuffer() again. - * - * \sa Request::addBuffer() + * reusing the buffer. * * \return A const pointer to the Fence if any, nullptr otherwise */ @@ -203,15 +201,13 @@ FrameBuffer::Private::~Private() * \brief Move a \a fence in this buffer * \param[in] fence The Fence * - * This function associates a Fence with this Framebuffer. The intended caller - * is the Request::addBuffer() function. + * This function associates a Fence with this Framebuffer. It is only intended + * to be called by the libcamera core. * * Once a FrameBuffer is associated with a Fence, the FrameBuffer will only be * made available to the hardware device once the Fence has been correctly * signalled. * - * \sa Request::prepare() - * * If the FrameBuffer completes successfully the core releases the Fence and the * Buffer can be reused immediately. If handling of the Fence fails during the * request preparation, the Fence is not released and is left in the diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp index 54ef8296a4..29a21a0d70 100644 --- a/src/libcamera/pipeline_handler.cpp +++ b/src/libcamera/pipeline_handler.cpp @@ -7,7 +7,6 @@ #include "libcamera/internal/pipeline_handler.h" -#include #include #include @@ -443,25 +442,6 @@ bool PipelineHandler::hasPendingRequests(const Camera *camera) const return !camera->_d()->queuedRequests_.empty(); } -/** - * \fn PipelineHandler::registerRequest() - * \brief Register a request for use by the pipeline handler - * \param[in] request The request to register - * - * This function is called when the request is created, and allows the pipeline - * handler to perform any one-time initialization it requries for the request. - */ -void PipelineHandler::registerRequest(Request *request) -{ - /* - * Connect the request prepared signal to notify the pipeline handler - * when a request is ready to be processed. - */ - request->_d()->prepared.connect(this, [this, request]() { - doQueueRequests(request->_d()->camera()); - }); -} - /** * \fn PipelineHandler::queueRequest() * \brief Queue a request @@ -493,7 +473,7 @@ void PipelineHandler::queueRequest(Request *request) Camera::Private *data = camera->_d(); data->waitingRequests_.push(request); - request->_d()->prepare(300ms); + doQueueRequests(camera); } /** @@ -533,8 +513,6 @@ void PipelineHandler::doQueueRequests(Camera *camera) break; Request *request = data->waitingRequests_.front(); - if (!request->_d()->prepared_) - break; /* * Pop the request first, in case doQueueRequests() is called diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp index 8a3934add3..8819ba0ce3 100644 --- a/src/libcamera/request.cpp +++ b/src/libcamera/request.cpp @@ -7,7 +7,6 @@ #include "libcamera/internal/request.h" -#include #include #include @@ -155,8 +154,6 @@ void Request::Private::doCancelRequest() cancelled_ = true; pending_.clear(); - notifiers_.clear(); - timer_.reset(); } /** @@ -187,135 +184,7 @@ void Request::Private::reset() { sequence_ = 0; cancelled_ = false; - prepared_ = false; pending_.clear(); - notifiers_.clear(); - timer_.reset(); -} - -/* - * Helper function to save some lines of code and make sure prepared_ is set - * to true before emitting the signal. - */ -void Request::Private::emitPrepareCompleted() -{ - prepared_ = true; - prepared.emit(); -} - -/** - * \brief Prepare the Request to be queued to the device - * \param[in] timeout Optional expiration timeout - * - * Prepare a Request to be queued to the hardware device by ensuring it is - * ready for the incoming memory transfers. - * - * This currently means waiting on each frame buffer acquire fence to be - * signalled. An optional expiration timeout can be specified. If not all the - * fences have been signalled correctly before the timeout expires the Request - * is cancelled. - * - * The function immediately emits the prepared signal if all the prepare - * operations have been completed synchronously. If instead the prepare - * operations require to wait the completion of asynchronous events, such as - * fences notifications or timer expiration, the prepared signal is emitted upon - * the asynchronous event completion. - * - * As we currently only handle fences, the function emits the prepared signal - * immediately if there are no fences to wait on. Otherwise the prepared signal - * is emitted when all fences have been signalled or the optional timeout has - * expired. - * - * If not all the fences have been correctly signalled or the optional timeout - * has expired the Request will be cancelled and the Request::prepared signal - * emitted. - * - * The intended user of this function is the PipelineHandler base class, which - * 'prepares' a Request before queuing it to the hardware device. - */ -void Request::Private::prepare(std::chrono::milliseconds timeout) -{ - /* Create and connect one notifier for each synchronization fence. */ - for (FrameBuffer *buffer : pending_) { - const Fence *fence = buffer->_d()->fence(); - if (!fence) - continue; - - auto [it, inserted] = notifiers_.try_emplace(buffer, fence->fd().get(), EventNotifier::Type::Read); - ASSERT(inserted); - - it->second.activated.connect(this, [this, buffer] { - notifierActivated(buffer); - }); - } - - if (notifiers_.empty()) { - emitPrepareCompleted(); - return; - } - - /* - * In case a timeout is specified, create a timer and set it up. - * - * The timer must be created here instead of in the Request constructor, - * in order to be bound to the pipeline handler thread. - */ - if (timeout != 0ms) { - timer_ = std::make_unique(); - timer_->timeout.connect(this, &Request::Private::timeout); - timer_->start(timeout); - } -} - -/** - * \var Request::Private::prepared - * \brief Request preparation completed Signal - * - * The signal is emitted once the request preparation has completed and is ready - * to be queued. The Request might complete with errors in which case it is - * cancelled. - * - * The intended slot for this signal is the PipelineHandler::doQueueRequests() - * function which queues Request after they have been prepared or cancel them - * if they have failed preparing. - */ - -void Request::Private::notifierActivated(FrameBuffer *buffer) -{ - /* Close the fence if successfully signalled. */ - ASSERT(buffer); - buffer->releaseFence(); - - /* Remove the entry from the map and check if other fences are pending. */ - auto it = notifiers_.find(buffer); - ASSERT(it != notifiers_.end()); - notifiers_.erase(it); - - Request *request = _o(); - LOG(Request, Debug) - << "Request " << request->cookie() << " buffer " << buffer - << " fence signalled"; - - if (!notifiers_.empty()) - return; - - /* All fences completed, delete the timer and emit the prepared signal. */ - timer_.reset(); - emitPrepareCompleted(); -} - -void Request::Private::timeout() -{ - /* A timeout can only happen if there are fences not yet signalled. */ - ASSERT(!notifiers_.empty()); - notifiers_.clear(); - - Request *request = _o(); - LOG(Request, Debug) << "Request prepare timeout: " << request->cookie(); - - cancel(); - - emitPrepareCompleted(); } #endif /* __DOXYGEN_PUBLIC__ */