From patchwork Mon Aug 3 16:18:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 9143 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 A654DBD87B for ; Mon, 3 Aug 2020 16:18:25 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C621561A12; Mon, 3 Aug 2020 18:18:24 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Aw8K6VsO"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DDD9D60905 for ; Mon, 3 Aug 2020 18:18:22 +0200 (CEST) Received: from Q.local (cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 6AA0FA62; Mon, 3 Aug 2020 18:18:22 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1596471502; bh=ma1nnWQzZHdN8csH7HZAqALRKraHiWDg3KbQNBH+Il0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Aw8K6VsOTxeIJNVAK9vU+c68dnNj3a7mkHo1WmROd+L2eLGOVjtMAbJUULwNZhlyE M28Mv1kjnhccMe6iyoavUVGJEYrwD7sFQGj2y9pXW4VW3a/WbLLzhm+5v/RyOsMVnW D2VWEHNbNg9WUcLGk/XfigkQzLNv7FIc/f0oWtv0= From: Kieran Bingham To: libcamera devel Date: Mon, 3 Aug 2020 17:18:07 +0100 Message-Id: <20200803161816.107113-4-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200803161816.107113-1-kieran.bingham@ideasonboard.com> References: <20200803161816.107113-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 03/12] libcamera: buffer: Create a MappedBuffer 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" Provide a MappedFrameBuffer helper class which will map all of the Planes within a FrameBuffer and provide CPU addressable pointers for those planes. The MappedFrameBuffer implements the interface of the MappedBuffer allowing other buffer types to be constructed of the same form, with a common interface and cleanup. This allows MappedBuffer instances to be created from Camera3Buffer types. Mappings are removed upon destruction. Signed-off-by: Kieran Bingham --- include/libcamera/internal/buffer.h | 46 ++++++++++ src/libcamera/buffer.cpp | 134 ++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 include/libcamera/internal/buffer.h diff --git a/include/libcamera/internal/buffer.h b/include/libcamera/internal/buffer.h new file mode 100644 index 000000000000..c04c294fecda --- /dev/null +++ b/include/libcamera/internal/buffer.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2020, Google Inc. + * + * buffer.h - Internal buffer handling + */ +#ifndef __LIBCAMERA_INTERNAL_BUFFER_H__ +#define __LIBCAMERA_INTERNAL_BUFFER_H__ + +#include + +#include +#include + +namespace libcamera { + +using MappedPlane = Span; + +class MappedBuffer +{ +public: + MappedBuffer(); + ~MappedBuffer(); + + MappedBuffer(MappedBuffer &&rhs); + MappedBuffer &operator=(MappedBuffer &&rhs); + + bool isValid() const { return valid_; } + int error() const { return error_; } + const std::vector &maps() const { return maps_; } + +protected: + int error_; + bool valid_; + std::vector maps_; +}; + +class MappedFrameBuffer : public MappedBuffer +{ +public: + MappedFrameBuffer(const FrameBuffer *buffer, int flags); +}; + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_INTERNAL_BUFFER_H__ */ diff --git a/src/libcamera/buffer.cpp b/src/libcamera/buffer.cpp index 8278f8a92af4..2f667db42922 100644 --- a/src/libcamera/buffer.cpp +++ b/src/libcamera/buffer.cpp @@ -6,6 +6,7 @@ */ #include +#include "libcamera/internal/buffer.h" #include #include @@ -290,4 +291,137 @@ int FrameBuffer::copyFrom(const FrameBuffer *src) return 0; } +/** + * \class MappedBuffer + * \brief Provide + * + * The MappedBuffer interface provides access to a set of MappedPlanes which + * are available for access by a CPU. + * + * The MappedBuffer interface does not implement any valid constructor but + * defines the move operators and destructors for the derived implementations, + * which are able to construct according to their derived types and given + * flags. + */ + +/** + * \brief Construct an empty MappedBuffer + * + * A default constructor is required to allow subclassing the MappedBuffer + * class. Construct an initialised, but invalid MappedBuffer. + */ +MappedBuffer::MappedBuffer() + : error_(0), valid_(false) +{ +} + +/** + * \brief Construct a MappedBuffer by taking the \a rhs mappings + * \param[in] rhs The other MappedBuffer + * + * Moving a MappedBuffer moves the mappings contained in the \a rhs to the new + * MappedBuffer and invalidates the \a rhs. No mappings are unmapped or + * destroyed in this process. + */ +MappedBuffer::MappedBuffer(MappedBuffer &&rhs) +{ + *this = std::move(rhs); +} + +/** + * \brief Move assingment operator, move a MappedBuffer by taking the \a rhs mappings + * \param[in] rhs The other MappedBuffer + * + * Moving a MappedBuffer moves the mappings contained in the \a rhs to the new + * MappedBuffer and invalidates the \a rhs. No mappings are unmapped or + * destroyed in this process. + */ +MappedBuffer &MappedBuffer::operator=(MappedBuffer &&rhs) +{ + error_ = rhs.error_; + valid_ = rhs.valid_; + maps_ = std::move(rhs.maps_); + rhs.valid_ = false; + rhs.error_ = 0; + + return *this; +} + +MappedBuffer::~MappedBuffer() +{ + for (MappedPlane map : maps_) + munmap(map.data(), map.size()); +} + +/** + * \fn MappedBuffer::isValid() + * \brief Check if the MappedBuffer instance is valid + * \return True if the MappedBuffer has valid mappings, false otherwise + */ + +/** + * \fn MappedBuffer::error() + * \brief Retrieve the map error status + * + * This function retrieves the error status from the MappedBuffer. + * The error status is a negative number as defined by errno.h. If + * no error occurred, this function returns 0. + */ + +/** + * \var MappedBuffer::valid_ + * \brief Stores the status of the mapping + * + * MappedBuffer implementations shall set this to represent if the mapping + * was successfully completed without errors. + */ + +/** + * \var MappedBuffer::error_ + * \brief Stores the error value if present + * + * MappedBuffer implementations shall set this to a negative value as defined + * by errno.h if an error occured during the mapping process + */ + +/** + * \class MappedFrameBuffer + * \brief Maps a FrameBuffer using the MappedBuffer interface + * + * The MappedFrameBuffer interface maps a FrameBuffer instance + * + * The MappedBuffer interface does not implement any constructor but defines + * the move operators and destructors for the derived implementations, which + * are able to construct according to their derived types and given flags. + */ + +/** + * \brief Map all planes of a FrameBuffer + * \param[in] buffer FrameBuffer to be mapped + * \param[in] flags Protection flags to apply to map + * + * Construct an object to map a frame buffer for CPU access. + * The flags are passed directly to mmap and should be either PROT_READ, + * PROT_WRITE, or a bitwise-or combination of both. + */ +MappedFrameBuffer::MappedFrameBuffer(const FrameBuffer *buffer, int flags) +{ + maps_.reserve(buffer->planes().size()); + + for (const FrameBuffer::Plane &plane : buffer->planes()) { + void *address = mmap(nullptr, plane.length, flags, + MAP_SHARED, plane.fd.fd(), 0); + + if (address == MAP_FAILED) { + error_ = -errno; + LOG(Buffer, Error) << "Failed to mmap plane"; + break; + } + + maps_.emplace_back(static_cast(address), plane.length); + } + + valid_ = buffer->planes().size() == maps_.size(); +} + } /* namespace libcamera */