From patchwork Mon Jul 28 11:55:53 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 24003 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 0CE0EC3323 for ; Mon, 28 Jul 2025 11:56:23 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8482769181; Mon, 28 Jul 2025 13:56:22 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="c7j4q5VN"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5DD8D6916B for ; Mon, 28 Jul 2025 13:56:19 +0200 (CEST) Received: from neptunite.hamster-moth.ts.net (unknown [IPv6:2404:7a81:160:2100:5715:34ad:7742:5049]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 171716DC; Mon, 28 Jul 2025 13:55:35 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1753703737; bh=W4CwzKBDSYQp/Kc+V5aoL8GkbwqY/RTbwOrCxp6yn0w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=c7j4q5VN0YDmEDy2JI5HQfPweMUsMqC0bz+OJCgvwWkIlTSvjIDKc4O2sob6in8XQ ui1FDNaBd4Yg9fhVoGvii/6fwVv8ccKgKmFh3oDOX3wiHSE6uS8PhjS6WYMOifBcCD fCVqW6U2OouY8Kk1DJ+NQJu/VavkCkvh0tkIIvCw= From: Paul Elder To: libcamera-devel@lists.libcamera.org Cc: Paul Elder , kieran.bingham@ideasonboard.com, barnabas.pocze@ideasonboard.com Subject: [PATCH v3 6/8] libcamera: camera: Hook into the LayerManager Date: Mon, 28 Jul 2025 20:55:53 +0900 Message-ID: <20250728115556.2886082-7-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250728115556.2886082-1-paul.elder@ideasonboard.com> References: <20250728115556.2886082-1-paul.elder@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" Add hooks into the CameraManager to call into the LayerManager on all relevant public-facing interface of Camera. The entry point for each function into the LayerManager is has been chosen based on the capabilities that we want to allow to Layer implementations. Signed-off-by: Paul Elder --- Changes in v3: - send the copy of controls returned by LayerManager::start() - each Camera now has a LayerController that it can call into, shortening each hook call significantly Changes in v2: - move the LayerManager out of Camera into the CameraManager - remove hooks for generateConfiguration() and streams() - Camera now passes itself into the layer hooks, as it is required for the LayerManager to fetch the closure based on the camera to pass to each layer --- include/libcamera/internal/camera.h | 4 ++++ src/libcamera/camera.cpp | 30 ++++++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/include/libcamera/internal/camera.h b/include/libcamera/internal/camera.h index d28cd921a0f9..fdabc460a357 100644 --- a/include/libcamera/internal/camera.h +++ b/include/libcamera/internal/camera.h @@ -19,6 +19,8 @@ #include +#include "libcamera/internal/layer_manager.h" + namespace libcamera { class CameraControlValidator; @@ -78,6 +80,8 @@ private: std::atomic state_; std::unique_ptr validator_; + + std::unique_ptr layers_; }; } /* namespace libcamera */ diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp index 99aed4f0703a..241e646dcd31 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -27,6 +28,8 @@ #include "libcamera/internal/camera.h" #include "libcamera/internal/camera_controls.h" +#include "libcamera/internal/camera_manager.h" +#include "libcamera/internal/layer_manager.h" #include "libcamera/internal/pipeline_handler.h" #include "libcamera/internal/request.h" @@ -774,18 +777,21 @@ void Camera::Private::setState(State state) void Camera::Private::emitBufferCompleted(Request *request, FrameBuffer *buffer) { Camera *camera = _o(); + layers_->bufferCompleted(request, buffer); camera->bufferCompleted.emit(request, buffer); } void Camera::Private::emitRequestCompleted(Request *request) { Camera *camera = _o(); + layers_->requestCompleted(request); camera->requestCompleted.emit(request); } void Camera::Private::emitDisconnected() { Camera *camera = _o(); + layers_->disconnected(); camera->disconnected.emit(); } @@ -976,6 +982,10 @@ Camera::Camera(std::unique_ptr d, const std::string &id, _d()->id_ = id; _d()->streams_ = streams; _d()->validator_ = std::make_unique(this); + _d()->layers_ = + _d()->pipe()->cameraManager()->_d()->layerManager()->createController(this, + _d()->properties_, + _d()->controlInfo_); } Camera::~Camera() @@ -1065,6 +1075,8 @@ int Camera::acquire() return -EBUSY; } + d->layers_->acquire(); + d->setState(Private::CameraAcquired); return 0; @@ -1097,6 +1109,8 @@ int Camera::release() d->pipe_->invokeMethod(&PipelineHandler::release, ConnectionTypeBlocking, this); + d->layers_->release(); + d->setState(Private::CameraAvailable); return 0; @@ -1114,7 +1128,7 @@ int Camera::release() */ const ControlInfoMap &Camera::controls() const { - return _d()->controlInfo_; + return _d()->layers_->controls(); } /** @@ -1127,7 +1141,7 @@ const ControlInfoMap &Camera::controls() const */ const ControlList &Camera::properties() const { - return _d()->properties_; + return _d()->layers_->properties(); } /** @@ -1276,6 +1290,8 @@ int Camera::configure(CameraConfiguration *config) d->activeStreams_.insert(stream); } + d->layers_->configure(config, d->controlInfo_); + d->setState(Private::CameraConfigured); return 0; @@ -1316,6 +1332,8 @@ std::unique_ptr Camera::createRequest(uint64_t cookie) /* Associate the request with the pipeline handler. */ d->pipe_->registerRequest(request.get()); + d->layers_->createRequest(cookie, request.get()); + return request; } @@ -1411,6 +1429,8 @@ int Camera::queueRequest(Request *request) /* Pre-process AeEnable. */ patchControlList(request->controls()); + d->layers_->queueRequest(request); + d->pipe_->invokeMethod(&PipelineHandler::queueRequest, ConnectionTypeQueued, request); @@ -1447,8 +1467,10 @@ int Camera::start(const ControlList *controls) ASSERT(d->requestSequence_ == 0); + ControlList *newControls = d->layers_->start(controls); + if (controls) { - ControlList copy(*controls); + ControlList copy(*newControls); patchControlList(copy); ret = d->pipe_->invokeMethod(&PipelineHandler::start, ConnectionTypeBlocking, this, ©); @@ -1499,6 +1521,8 @@ int Camera::stop() d->setState(Private::CameraStopping); + d->layers_->stop(); + d->pipe_->invokeMethod(&PipelineHandler::stop, ConnectionTypeBlocking, this);