summaryrefslogtreecommitdiff
path: root/src/android/mm/generic_frame_buffer_allocator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/android/mm/generic_frame_buffer_allocator.cpp')
-rw-r--r--src/android/mm/generic_frame_buffer_allocator.cpp143
1 files changed, 143 insertions, 0 deletions
diff --git a/src/android/mm/generic_frame_buffer_allocator.cpp b/src/android/mm/generic_frame_buffer_allocator.cpp
new file mode 100644
index 00000000..acb2fa2b
--- /dev/null
+++ b/src/android/mm/generic_frame_buffer_allocator.cpp
@@ -0,0 +1,143 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2021, Google Inc.
+ *
+ * generic_camera_buffer.cpp - Allocate FrameBuffer using gralloc API
+ */
+
+#include <memory>
+#include <vector>
+
+#include <libcamera/base/log.h>
+#include <libcamera/base/shared_fd.h>
+
+#include "libcamera/internal/formats.h"
+#include "libcamera/internal/framebuffer.h"
+
+#include <hardware/camera3.h>
+#include <hardware/gralloc.h>
+#include <hardware/hardware.h>
+
+#include "../camera_device.h"
+#include "../frame_buffer_allocator.h"
+
+using namespace libcamera;
+
+LOG_DECLARE_CATEGORY(HAL)
+
+namespace {
+class GenericFrameBufferData : public FrameBuffer::Private
+{
+ LIBCAMERA_DECLARE_PUBLIC(FrameBuffer)
+
+public:
+ GenericFrameBufferData(struct alloc_device_t *allocDevice,
+ buffer_handle_t handle)
+ : allocDevice_(allocDevice), handle_(handle)
+ {
+ ASSERT(allocDevice_);
+ ASSERT(handle_);
+ }
+
+ ~GenericFrameBufferData() override
+ {
+ /*
+ * allocDevice_ is used to destroy handle_. allocDevice_ is
+ * owned by PlatformFrameBufferAllocator::Private.
+ * GenericFrameBufferData must be destroyed before it is
+ * destroyed.
+ *
+ * \todo Consider managing alloc_device_t with std::shared_ptr
+ * if this is difficult to maintain.
+ *
+ * \todo Thread safety against alloc_device_t is not documented.
+ * Is it no problem to call alloc/free in parallel?
+ */
+ allocDevice_->free(allocDevice_, handle_);
+ }
+
+private:
+ struct alloc_device_t *allocDevice_;
+ const buffer_handle_t handle_;
+};
+} /* namespace */
+
+class PlatformFrameBufferAllocator::Private : public Extensible::Private
+{
+ LIBCAMERA_DECLARE_PUBLIC(PlatformFrameBufferAllocator)
+
+public:
+ Private(CameraDevice *const cameraDevice)
+ : cameraDevice_(cameraDevice),
+ hardwareModule_(cameraDevice->camera3Device()->common.module),
+ allocDevice_(nullptr)
+ {
+ ASSERT(hardwareModule_);
+ }
+
+ ~Private() override;
+
+ std::unique_ptr<libcamera::FrameBuffer>
+ allocate(int halPixelFormat, const libcamera::Size &size, uint32_t usage);
+
+private:
+ const CameraDevice *const cameraDevice_;
+ struct hw_module_t *const hardwareModule_;
+ struct alloc_device_t *allocDevice_;
+};
+
+PlatformFrameBufferAllocator::Private::~Private()
+{
+ if (allocDevice_)
+ gralloc_close(allocDevice_);
+}
+
+std::unique_ptr<libcamera::FrameBuffer>
+PlatformFrameBufferAllocator::Private::allocate(int halPixelFormat,
+ const libcamera::Size &size,
+ uint32_t usage)
+{
+ if (!allocDevice_) {
+ int ret = gralloc_open(hardwareModule_, &allocDevice_);
+ if (ret) {
+ LOG(HAL, Fatal) << "gralloc_open() failed: " << ret;
+ return nullptr;
+ }
+ }
+
+ int stride = 0;
+ buffer_handle_t handle = nullptr;
+ int ret = allocDevice_->alloc(allocDevice_, size.width, size.height,
+ halPixelFormat, usage, &handle, &stride);
+ if (ret) {
+ LOG(HAL, Error) << "failed buffer allocation: " << ret;
+ return nullptr;
+ }
+ if (!handle) {
+ LOG(HAL, Fatal) << "invalid buffer_handle_t";
+ return nullptr;
+ }
+
+ /* This code assumes the planes are mapped consecutively. */
+ const libcamera::PixelFormat pixelFormat =
+ cameraDevice_->capabilities()->toPixelFormat(halPixelFormat);
+ const auto &info = PixelFormatInfo::info(pixelFormat);
+ std::vector<FrameBuffer::Plane> planes(info.numPlanes());
+
+ SharedFD fd{ handle->data[0] };
+ size_t offset = 0;
+ for (auto [i, plane] : utils::enumerate(planes)) {
+ const size_t planeSize = info.planeSize(size.height, i, stride);
+
+ plane.fd = fd;
+ plane.offset = offset;
+ plane.length = planeSize;
+ offset += planeSize;
+ }
+
+ return std::make_unique<FrameBuffer>(
+ std::make_unique<GenericFrameBufferData>(allocDevice_, handle),
+ planes);
+}
+
+PUBLIC_FRAME_BUFFER_ALLOCATOR_IMPLEMENTATION