From patchwork Thu Jan 29 08:28:12 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 26034 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 D2959C3226 for ; Thu, 29 Jan 2026 08:28:40 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 827E761FD2; Thu, 29 Jan 2026 09:28:40 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="V8OiMJw5"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id CB0B961FDE for ; Thu, 29 Jan 2026 09:28:35 +0100 (CET) Received: from neptunite.flets-east.jp (unknown [IPv6:2404:7a81:160:2100:2eea:f891:1bd7:2691]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 2EF28281C; Thu, 29 Jan 2026 09:27:56 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1769675278; bh=jSvnCM+GocAbdguq/5jzEL8b/HNcAV3hEIrhsSHdWss=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=V8OiMJw5ycrd64D+uRVXN/HWfgrTX0IP6WbC85yaYFfork07rnsjefH6cWJ/h8Fya EkAwcLi2QVDVre92Z4x7meU5F3z694E0EQw+VYYBNhiXlFMLKw9L5lrFMy7BfYo6EN cKtO0Gq0zFC7+UAwdE5wqkU2KR3vPkFR51Ic8eKk= From: Paul Elder To: libcamera-devel@lists.libcamera.org Cc: Paul Elder Subject: [PATCH v6 6/8] libcamera: camera: Hook into the LayerManager Date: Thu, 29 Jan 2026 17:28:12 +0900 Message-ID: <20260129082814.1777779-7-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20260129082814.1777779-1-paul.elder@ideasonboard.com> References: <20260129082814.1777779-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 has been chosen based on the capabilities that we want to expose to Layer implementations. Signed-off-by: Paul Elder --- Changes in v6: - merge the metadata returned by the layers in requestCompleted into the request's metadata to forward it to the application No change in v5 No change in v4 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 | 32 ++++++++++++++++++++++++++--- 2 files changed, 33 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 a2132e61a7bd..4ed9a21726d9 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,23 @@ 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(); + ControlList metadata = layers_->requestCompleted(request); + request->_d()->metadata().merge(metadata, + ControlList::MergePolicy::OverwriteExisting); camera->requestCompleted.emit(request); } void Camera::Private::emitDisconnected() { Camera *camera = _o(); + layers_->disconnected(); camera->disconnected.emit(); } @@ -976,6 +984,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 +1077,8 @@ int Camera::acquire() return -EBUSY; } + d->layers_->acquire(); + d->setState(Private::CameraAcquired); return 0; @@ -1097,6 +1111,8 @@ int Camera::release() d->pipe_->invokeMethod(&PipelineHandler::release, ConnectionTypeBlocking, this); + d->layers_->release(); + d->setState(Private::CameraAvailable); return 0; @@ -1114,7 +1130,7 @@ int Camera::release() */ const ControlInfoMap &Camera::controls() const { - return _d()->controlInfo_; + return _d()->layers_->controls(); } /** @@ -1127,7 +1143,7 @@ const ControlInfoMap &Camera::controls() const */ const ControlList &Camera::properties() const { - return _d()->properties_; + return _d()->layers_->properties(); } /** @@ -1276,6 +1292,8 @@ int Camera::configure(CameraConfiguration *config) d->activeStreams_.insert(stream); } + d->layers_->configure(config, d->controlInfo_); + d->setState(Private::CameraConfigured); return 0; @@ -1316,6 +1334,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; } @@ -1417,6 +1437,8 @@ int Camera::queueRequest(Request *request) /* Pre-process AeEnable. */ patchControlList(request->controls()); + d->layers_->queueRequest(request); + d->pipe_->invokeMethod(&PipelineHandler::queueRequest, ConnectionTypeQueued, request); @@ -1453,8 +1475,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, ©); @@ -1505,6 +1529,8 @@ int Camera::stop() d->setState(Private::CameraStopping); + d->layers_->stop(); + d->pipe_->invokeMethod(&PipelineHandler::stop, ConnectionTypeBlocking, this);