| /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
| /* |
| * Copyright (C) 2021, Google Inc. |
| * |
| * cros_frame_buffer.cpp - Allocate FrameBuffer for Chromium OS using |
| * CameraBufferManager |
| */ |
| |
| #include <memory> |
| #include <vector> |
| |
| #include <libcamera/base/log.h> |
| #include <libcamera/base/shared_fd.h> |
| |
| #include "libcamera/internal/framebuffer.h" |
| |
| #include "../camera_device.h" |
| #include "../frame_buffer_allocator.h" |
| #include "cros-camera/camera_buffer_manager.h" |
| |
| using namespace libcamera; |
| |
| LOG_DECLARE_CATEGORY(HAL) |
| |
| namespace { |
| class CrosFrameBufferData : public FrameBuffer::Private |
| { |
| LIBCAMERA_DECLARE_PUBLIC(FrameBuffer) |
| |
| public: |
| CrosFrameBufferData(cros::ScopedBufferHandle scopedHandle) |
| : FrameBuffer::Private(), scopedHandle_(std::move(scopedHandle)) |
| { |
| } |
| |
| private: |
| cros::ScopedBufferHandle scopedHandle_; |
| }; |
| } /* namespace */ |
| |
| class PlatformFrameBufferAllocator::Private : public Extensible::Private |
| { |
| LIBCAMERA_DECLARE_PUBLIC(PlatformFrameBufferAllocator) |
| |
| public: |
| Private([[maybe_unused]] CameraDevice *const cameraDevice) |
| { |
| } |
| |
| std::unique_ptr<libcamera::FrameBuffer> |
| allocate(int halPixelFormat, const libcamera::Size &size, uint32_t usage); |
| }; |
| |
| std::unique_ptr<libcamera::FrameBuffer> |
| PlatformFrameBufferAllocator::Private::allocate(int halPixelFormat, |
| const libcamera::Size &size, |
| uint32_t usage) |
| { |
| cros::ScopedBufferHandle scopedHandle = |
| cros::CameraBufferManager::AllocateScopedBuffer( |
| size.width, size.height, halPixelFormat, usage); |
| if (!scopedHandle) { |
| LOG(HAL, Error) << "Failed to allocate buffer handle"; |
| return nullptr; |
| } |
| |
| buffer_handle_t handle = *scopedHandle; |
| SharedFD fd{ handle->data[0] }; |
| if (!fd.isValid()) { |
| LOG(HAL, Fatal) << "Invalid fd"; |
| return nullptr; |
| } |
| |
| /* This code assumes all the planes are located in the same buffer. */ |
| const size_t numPlanes = cros::CameraBufferManager::GetNumPlanes(handle); |
| std::vector<FrameBuffer::Plane> planes(numPlanes); |
| for (auto [i, plane] : utils::enumerate(planes)) { |
| plane.fd = fd; |
| plane.offset = cros::CameraBufferManager::GetPlaneOffset(handle, i); |
| plane.length = cros::CameraBufferManager::GetPlaneSize(handle, i); |
| } |
| |
| return std::make_unique<FrameBuffer>( |
| std::make_unique<CrosFrameBufferData>(std::move(scopedHandle)), |
| planes); |
| } |
| |
| PUBLIC_FRAME_BUFFER_ALLOCATOR_IMPLEMENTATION |