From b3383da79f1d513b0d76db220a7104e1c1035e30 Mon Sep 17 00:00:00 2001 From: Kieran Bingham Date: Fri, 17 Jul 2020 16:55:59 +0100 Subject: libcamera: buffer: Create a MappedBuffer 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. Reviewed-by: Laurent Pinchart Signed-off-by: Kieran Bingham --- include/libcamera/internal/buffer.h | 47 +++++++++++ src/libcamera/buffer.cpp | 151 +++++++++++++++++++++++++++++++++++- 2 files changed, 197 insertions(+), 1 deletion(-) 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 00000000..b7b0173f --- /dev/null +++ b/include/libcamera/internal/buffer.h @@ -0,0 +1,47 @@ +/* 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 +#include + +namespace libcamera { + +class MappedBuffer +{ +public: + using Plane = Span; + + ~MappedBuffer(); + + MappedBuffer(MappedBuffer &&other); + MappedBuffer &operator=(MappedBuffer &&other); + + bool isValid() const { return error_ == 0; } + int error() const { return error_; } + const std::vector &maps() const { return maps_; } + +protected: + MappedBuffer(); + + int error_; + 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 8278f8a9..d040ac9a 100644 --- a/src/libcamera/buffer.cpp +++ b/src/libcamera/buffer.cpp @@ -6,6 +6,7 @@ */ #include +#include "libcamera/internal/buffer.h" #include #include @@ -15,8 +16,11 @@ #include "libcamera/internal/log.h" /** - * \file buffer.h + * \file libcamera/buffer.h * \brief Buffer handling + * + * \file libcamera/internal/buffer.h + * \brief Internal buffer handling support */ namespace libcamera { @@ -290,4 +294,149 @@ int FrameBuffer::copyFrom(const FrameBuffer *src) return 0; } +/** + * \class MappedBuffer + * \brief Provide an interface to support managing memory mapped buffers + * + * The MappedBuffer interface provides access to a set of MappedPlanes which + * are available for access by the CPU. + * + * This class is not meant to be constructed directly, but instead derived + * classes should be used to implement the correct mapping of a source buffer. + * + * This allows treating CPU accessible memory through a generic interface + * regardless of whether it originates from a libcamera FrameBuffer or other + * source. + */ + +/** + * \typedef MappedBuffer::Plane + * \brief A mapped region of memory accessible to the CPU + * + * The MappedBuffer::Plane uses the Span interface to describe the mapped memory + * region. + */ + +/** + * \brief Construct an empty MappedBuffer + */ +MappedBuffer::MappedBuffer() + : error_(0) +{ +} + +/** + * \brief Move constructor, construct the MappedBuffer with the contents of \a + * other using move semantics + * \param[in] other The other MappedBuffer + * + * Moving a MappedBuffer moves the mappings contained in the \a other to the new + * MappedBuffer and invalidates the \a other. + * + * No mappings are unmapped or destroyed in this process. + */ +MappedBuffer::MappedBuffer(MappedBuffer &&other) +{ + *this = std::move(other); +} + +/** + * \brief Move assignment operator, replace the mappings with those of \a other +* \param[in] other The other MappedBuffer + * + * Moving a MappedBuffer moves the mappings contained in the \a other to the new + * MappedBuffer and invalidates the \a other. + * + * No mappings are unmapped or destroyed in this process. + */ +MappedBuffer &MappedBuffer::operator=(MappedBuffer &&other) +{ + error_ = other.error_; + maps_ = std::move(other.maps_); + other.error_ = -ENOENT; + + return *this; +} + +MappedBuffer::~MappedBuffer() +{ + for (Plane &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. + * + * \return The map error code + */ + +/** + * \fn MappedBuffer::maps() + * \brief Retrieve the mapped planes + * + * This function retrieves the successfully mapped planes stored as a vector + * of Span to provide access to the mapped memory. + * + * \return A vector of the mapped planes + */ + +/** + * \var MappedBuffer::error_ + * \brief Stores the error value if present + * + * MappedBuffer derived classes shall set this to a negative value as defined + * by errno.h if an error occured during the mapping process. + */ + +/** + * \var MappedBuffer::maps_ + * \brief Stores the internal + * + * MappedBuffer derived classes shall store the mappings they create in this + * vector which is parsed during destruct to unmap any memory mappings which + * completed successfully. + */ + +/** + * \class MappedFrameBuffer + * \brief Map a FrameBuffer using the MappedBuffer interface + */ + +/** + * \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); + } +} + } /* namespace libcamera */ -- cgit v1.2.1