summaryrefslogtreecommitdiff
path: root/src/libcamera-helpers
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcamera-helpers')
-rw-r--r--src/libcamera-helpers/mapped_framebuffer.cpp (renamed from src/libcamera-helpers/mapped_buffer.cpp)110
-rw-r--r--src/libcamera-helpers/meson.build2
2 files changed, 92 insertions, 20 deletions
diff --git a/src/libcamera-helpers/mapped_buffer.cpp b/src/libcamera-helpers/mapped_framebuffer.cpp
index 6f3248e..a657408 100644
--- a/src/libcamera-helpers/mapped_buffer.cpp
+++ b/src/libcamera-helpers/mapped_framebuffer.cpp
@@ -2,26 +2,27 @@
/*
* Copyright (C) 2021, Google Inc.
*
- * mapped_buffer.cpp - Mapped Buffer handling
+ * mapped_framebuffer.cpp - Mapped Framebuffer support
*/
-#include "libcamera-helpers/mapped_buffer.h"
+#include "libcamera-helpers/mapped_framebuffer.h"
+#include <algorithm>
#include <errno.h>
-#include <string.h>
+#include <map>
#include <sys/mman.h>
#include <unistd.h>
#include <libcamera/base/log.h>
/**
- * \file libcamera-helpers/mapped_buffer.h
- * \brief Mapped Buffer handling
+ * \file libcamera-helpers/mapped_framebuffer.h
+ * \brief Frame buffer memory mapping support
*/
namespace libcamera {
-LOG_DEFINE_CATEGORY(MappedBuffer)
+LOG_DECLARE_CATEGORY(Buffer)
/**
* \class MappedBuffer
@@ -81,6 +82,7 @@ MappedBuffer::MappedBuffer(MappedBuffer &&other)
MappedBuffer &MappedBuffer::operator=(MappedBuffer &&other)
{
error_ = other.error_;
+ planes_ = std::move(other.planes_);
maps_ = std::move(other.maps_);
other.error_ = -ENOENT;
@@ -129,10 +131,18 @@ MappedBuffer::~MappedBuffer()
*/
/**
- * \var MappedBuffer::maps_
+ * \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.
*/
@@ -143,28 +153,90 @@ MappedBuffer::~MappedBuffer()
*/
/**
+ * \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 flags are passed directly to mmap and should be either PROT_READ,
- * PROT_WRITE, or a bitwise-or combination of both.
+ * 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, int flags)
+MappedFrameBuffer::MappedFrameBuffer(const FrameBuffer *buffer, MapFlags flags)
{
- maps_.reserve(buffer->planes().size());
+ 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<int, MappedBufferInfo> 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<size_t>(plane.offset + plane.length));
+ }
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;
+ 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<uint8_t *>(address);
+ maps_.emplace_back(info.address, info.mapLength);
}
- maps_.emplace_back(static_cast<uint8_t *>(address), plane.length);
+ planes_.emplace_back(info.address + plane.offset, plane.length);
}
}
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',
])