From f4999536b4f75eef1a489936b0c9795fdc234574 Mon Sep 17 00:00:00 2001 From: Kieran Bingham Date: Fri, 15 Oct 2021 15:16:56 +0100 Subject: libcamera-helpers: Integrate latest MappedFrameBuffer The MappedFrameBuffer helper class has been updated in the libcamera source code. This makes use of the new enum MapFlags type, and corrects the mapping changes that were made during 8708904fad6f ("libcamera: mapped_framebuffer: Return plane begin address by MappedBuffer::maps()") This update also brings back isolated IPA functionality to this external IPA, which is otherwise broken due to the offset/plane changes. The files are renamed to mapped_framebuffer to match the naming in libcamera, but are kept within the 'libcamera-helper' hierarchy of the IPA. Also, a minor todo is added to IPAIPU3::mapBuffers, to highlight that we could potentially map Statistics buffers as read only rather than read/write if we could correctly identify them. Signed-off-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- include/libcamera-helpers/mapped_buffer.h | 53 ------ include/libcamera-helpers/mapped_framebuffer.h | 65 +++++++ ipu3.cpp | 8 +- src/libcamera-helpers/mapped_buffer.cpp | 171 ----------------- src/libcamera-helpers/mapped_framebuffer.cpp | 243 +++++++++++++++++++++++++ src/libcamera-helpers/meson.build | 2 +- 6 files changed, 315 insertions(+), 227 deletions(-) delete mode 100644 include/libcamera-helpers/mapped_buffer.h create mode 100644 include/libcamera-helpers/mapped_framebuffer.h delete mode 100644 src/libcamera-helpers/mapped_buffer.cpp create mode 100644 src/libcamera-helpers/mapped_framebuffer.cpp diff --git a/include/libcamera-helpers/mapped_buffer.h b/include/libcamera-helpers/mapped_buffer.h deleted file mode 100644 index 6cfc572..0000000 --- a/include/libcamera-helpers/mapped_buffer.h +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2020, Google Inc. - * - * buffer.h - Internal buffer handling - */ -#ifndef __LIBCAMERA_MAPPED_BUFFER_H__ -#define __LIBCAMERA_MAPPED_BUFFER_H__ - -#include -#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_; - -private: - LIBCAMERA_DISABLE_COPY(MappedBuffer) -}; - -class MappedFrameBuffer : public MappedBuffer -{ -public: - MappedFrameBuffer(const FrameBuffer *buffer, int flags); -}; - -} /* namespace libcamera */ - -#endif /* __LIBCAMERA_MAPPED_BUFFER_H__ */ - diff --git a/include/libcamera-helpers/mapped_framebuffer.h b/include/libcamera-helpers/mapped_framebuffer.h new file mode 100644 index 0000000..4215527 --- /dev/null +++ b/include/libcamera-helpers/mapped_framebuffer.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Google Inc. + * + * mapped_framebuffer.h - Frame buffer memory mapping support + */ +#ifndef __LIBCAMERA_HELPER_MAPPED_FRAMEBUFFER_H__ +#define __LIBCAMERA_HELPER_MAPPED_FRAMEBUFFER_H__ + +#include +#include + +#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_; } + /* \todo rename to planes(). */ + const std::vector &maps() const { return planes_; } + +protected: + MappedBuffer(); + + int error_; + std::vector planes_; + std::vector maps_; + +private: + LIBCAMERA_DISABLE_COPY(MappedBuffer) +}; + +class MappedFrameBuffer : public MappedBuffer +{ +public: + enum class MapFlag { + Read = 1 << 0, + Write = 1 << 1, + ReadWrite = Read | Write, + }; + + using MapFlags = Flags; + + MappedFrameBuffer(const FrameBuffer *buffer, MapFlags flags); +}; + +LIBCAMERA_FLAGS_ENABLE_OPERATORS(MappedFrameBuffer::MapFlag) + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_HELPER_MAPPED_FRAMEBUFFER_H__ */ diff --git a/ipu3.cpp b/ipu3.cpp index b60c58c..7589eec 100644 --- a/ipu3.cpp +++ b/ipu3.cpp @@ -20,7 +20,7 @@ #include -#include "libcamera-helpers/mapped_buffer.h" +#include "libcamera-helpers/mapped_framebuffer.h" /* IA AIQ Wrapper API */ #include "aic/aic.h" @@ -258,10 +258,14 @@ int IPAIPU3::configure(const IPAConfigInfo &configInfo) void IPAIPU3::mapBuffers(const std::vector &buffers) { + /* + * todo: Statistics buffers could be mapped read-only if they + * could be easily identified. + */ for (const IPABuffer &buffer : buffers) { const FrameBuffer fb(buffer.planes); buffers_.emplace(buffer.id, - MappedFrameBuffer(&fb, PROT_READ | PROT_WRITE)); + MappedFrameBuffer(&fb, MappedFrameBuffer::MapFlag::ReadWrite)); } } diff --git a/src/libcamera-helpers/mapped_buffer.cpp b/src/libcamera-helpers/mapped_buffer.cpp deleted file mode 100644 index 6f3248e..0000000 --- a/src/libcamera-helpers/mapped_buffer.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2021, Google Inc. - * - * mapped_buffer.cpp - Mapped Buffer handling - */ - -#include "libcamera-helpers/mapped_buffer.h" - -#include -#include -#include -#include - -#include - -/** - * \file libcamera-helpers/mapped_buffer.h - * \brief Mapped Buffer handling - */ - -namespace libcamera { - -LOG_DEFINE_CATEGORY(MappedBuffer) - -/** - * \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 mapped planes - * - * 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(MappedBuffer, Error) << "Failed to mmap plane"; - break; - } - - maps_.emplace_back(static_cast(address), plane.length); - } -} - -} /* namespace libcamera */ diff --git a/src/libcamera-helpers/mapped_framebuffer.cpp b/src/libcamera-helpers/mapped_framebuffer.cpp new file mode 100644 index 0000000..a657408 --- /dev/null +++ b/src/libcamera-helpers/mapped_framebuffer.cpp @@ -0,0 +1,243 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Google Inc. + * + * mapped_framebuffer.cpp - Mapped Framebuffer support + */ + +#include "libcamera-helpers/mapped_framebuffer.h" + +#include +#include +#include +#include +#include + +#include + +/** + * \file libcamera-helpers/mapped_framebuffer.h + * \brief Frame buffer memory mapping support + */ + +namespace libcamera { + +LOG_DECLARE_CATEGORY(Buffer) + +/** + * \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_; + planes_ = std::move(other.planes_); + 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::planes_ + * \brief Stores the internal mapped planes + * + * MappedBuffer derived classes shall store the mappings they create in this + * vector which points the beginning of mapped plane addresses. + */ + +/** + * \var MappedBuffer::maps_ + * \brief Stores the mapped buffer + * + * 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 + */ + +/** + * \enum MappedFrameBuffer::MapFlag + * \brief Specify the mapping mode for the FrameBuffer + * \var MappedFrameBuffer::Read + * \brief Create a read-only mapping + * \var MappedFrameBuffer::Write + * \brief Create a write-only mapping + * \var MappedFrameBuffer::ReadWrite + * \brief Create a mapping that can be both read and written + */ + +/** + * \typedef MappedFrameBuffer::MapFlags + * \brief A bitwise combination of MappedFrameBuffer::MapFlag values + */ + +/** + * \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 mapping can be + * made as Read only, Write only or support Read and Write operations by setting + * the MapFlag flags accordingly. + */ +MappedFrameBuffer::MappedFrameBuffer(const FrameBuffer *buffer, MapFlags flags) +{ + ASSERT(!buffer->planes().empty()); + planes_.reserve(buffer->planes().size()); + + int mmapFlags = 0; + + if (flags & MapFlag::Read) + mmapFlags |= PROT_READ; + + if (flags & MapFlag::Write) + mmapFlags |= PROT_WRITE; + + struct MappedBufferInfo { + uint8_t *address = nullptr; + size_t mapLength = 0; + size_t dmabufLength = 0; + }; + std::map mappedBuffers; + + for (const FrameBuffer::Plane &plane : buffer->planes()) { + const int fd = plane.fd.fd(); + if (mappedBuffers.find(fd) == mappedBuffers.end()) { + const size_t length = lseek(fd, 0, SEEK_END); + mappedBuffers[fd] = MappedBufferInfo{ nullptr, 0, length }; + } + + const size_t length = mappedBuffers[fd].dmabufLength; + + if (plane.offset > length || + plane.offset + plane.length > length) { + LOG(Buffer, Fatal) << "plane is out of buffer: " + << "buffer length=" << length + << ", plane offset=" << plane.offset + << ", plane length=" << plane.length; + return; + } + size_t &mapLength = mappedBuffers[fd].mapLength; + mapLength = std::max(mapLength, + static_cast(plane.offset + plane.length)); + } + + for (const FrameBuffer::Plane &plane : buffer->planes()) { + const int fd = plane.fd.fd(); + auto &info = mappedBuffers[fd]; + if (!info.address) { + void *address = mmap(nullptr, info.mapLength, mmapFlags, + MAP_SHARED, fd, 0); + if (address == MAP_FAILED) { + error_ = -errno; + LOG(Buffer, Error) << "Failed to mmap plane: " + << strerror(-error_); + return; + } + + info.address = static_cast(address); + maps_.emplace_back(info.address, info.mapLength); + } + + planes_.emplace_back(info.address + plane.offset, plane.length); + } +} + +} /* namespace libcamera */ diff --git a/src/libcamera-helpers/meson.build b/src/libcamera-helpers/meson.build index 444f212..084bf65 100644 --- a/src/libcamera-helpers/meson.build +++ b/src/libcamera-helpers/meson.build @@ -2,5 +2,5 @@ # Implementation of internal libcamera internals libcamera_helpers = files([ - 'mapped_buffer.cpp', + 'mapped_framebuffer.cpp', ]) -- cgit v1.2.1