android13/hardware/rockchip/camera/common/camera_buffer_manager_grall...

443 lines
14 KiB
C++

/*
* Copyright 2017 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <utils/Log.h>
#include "common/camera_buffer_manager_gralloc_impl.h"
#include <linux/videodev2.h>
#include "arc/common.h"
namespace arc {
namespace {
struct dma_buf_sync {
__u64 flags;
};
#define DMA_BUF_SYNC_READ (1 << 0)
#define DMA_BUF_SYNC_WRITE (2 << 0)
#define DMA_BUF_SYNC_RW (DMA_BUF_SYNC_READ | DMA_BUF_SYNC_WRITE)
#define DMA_BUF_SYNC_START (0 << 2)
#define DMA_BUF_SYNC_END (1 << 2)
#define DMA_BUF_SYNC_VALID_FLAGS_MASK \
(DMA_BUF_SYNC_RW | DMA_BUF_SYNC_END)
#define DMA_BUF_BASE 'b'
#define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync)
}
gralloc_module_t* CameraBufferManagerImpl::gm_module_ = nullptr;
struct alloc_device_t* CameraBufferManagerImpl::alloc_device_ = nullptr;
// static
CameraBufferManager* CameraBufferManager::GetInstance() {
static CameraBufferManagerImpl instance;
if (!instance.alloc_device_) {
gralloc_module_t** gm_module_ =
&CameraBufferManagerImpl::gm_module_;
struct alloc_device_t** alloc_device_ =
&CameraBufferManagerImpl::alloc_device_;
int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
(const hw_module_t **)gm_module_);
if (ret < 0) {
LOGF(ERROR) << "Unable to get gralloc module(error" << ret << ")";
return nullptr;
}
ret = gralloc_open((const struct hw_module_t*)*gm_module_, alloc_device_);
if (ret < 0) {
LOGF(ERROR) << " Unable to open gralloc alloc device (error " << ret << ")";
alloc_device_ = nullptr;
return nullptr;
}
}
return &instance;
}
//static
int CameraBufferManagerImpl::GetHalPixelFormat(buffer_handle_t buffer) {
int hal_pixel_format;
gralloc_module_t* gm_module_ =
CameraBufferManagerImpl::gm_module_;
if (gm_module_ && gm_module_->perform) {
int ret = gm_module_->perform(gm_module_,
GRALLOC_MODULE_PERFORM_GET_HADNLE_FORMAT,
buffer, &hal_pixel_format);
if (ret < 0) {
LOGF(ERROR) << "get format error " << ret;
return -EINVAL;
}
} else {
LOGF(ERROR) << "can't get format";
return -EINVAL;
}
return hal_pixel_format;
}
// static
uint32_t CameraBufferManager::GetNumPlanes(buffer_handle_t buffer) {
int hal_pixel_format = CameraBufferManagerImpl::GetHalPixelFormat(buffer);
/* only support one physical plane now */
switch (hal_pixel_format) {
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_RGBX_8888:
case HAL_PIXEL_FORMAT_BGRA_8888:
case HAL_PIXEL_FORMAT_RGB_888:
case HAL_PIXEL_FORMAT_RGB_565:
case HAL_PIXEL_FORMAT_YCbCr_422_I:
case HAL_PIXEL_FORMAT_YCrCb_NV12:
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
case HAL_PIXEL_FORMAT_YCrCb_420_SP: // NV21
case HAL_PIXEL_FORMAT_YCbCr_420_888:
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: //NV12
default :
return 1;
}
LOGF(ERROR) << "Unknown format: " << hal_pixel_format << " - " << FormatToString(hal_pixel_format);
return 0;
}
// static
uint32_t CameraBufferManager::GetV4L2PixelFormat(buffer_handle_t buffer) {
int hal_pixel_format = CameraBufferManagerImpl::GetHalPixelFormat(buffer);
switch (hal_pixel_format) {
case HAL_PIXEL_FORMAT_RGBA_8888:
return V4L2_PIX_FMT_ABGR32;
// There is no standard V4L2 pixel format corresponding to
// DRM_FORMAT_xBGR8888. We use our own V4L2 format extension
// V4L2_PIX_FMT_RGBX32 here.
case HAL_PIXEL_FORMAT_RGBX_8888:
case HAL_PIXEL_FORMAT_BGRA_8888:
return V4L2_PIX_FMT_RGBX32;
case HAL_PIXEL_FORMAT_BLOB:
return V4L2_PIX_FMT_JPEG;
// Semi-planar formats.
case HAL_PIXEL_FORMAT_YCrCb_NV12:
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
case HAL_PIXEL_FORMAT_YCbCr_420_888:
return V4L2_PIX_FMT_NV12;
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
return V4L2_PIX_FMT_NV21;
default:
return V4L2_PIX_FMT_NV12;
}
LOGF(ERROR) << "Could not convert format "
<< FormatToString(hal_pixel_format) << " to V4L2 pixel format";
return 0;
}
// static
size_t CameraBufferManager::GetPlaneStride(buffer_handle_t buffer,
size_t plane) {
if (plane >= GetNumPlanes(buffer)) {
LOGF(ERROR) << "Invalid plane: " << plane;
return 0;
}
gralloc_module_t* gm_module_ =
CameraBufferManagerImpl::gm_module_;
int plane_stride = 0;
if (gm_module_ && gm_module_->perform) {
int ret = gm_module_->perform(gm_module_,
GRALLOC_MODULE_PERFORM_GET_HADNLE_BYTE_STRIDE,
buffer, &plane_stride);
if (ret < 0) {
LOGF(ERROR) << "get stride error " << ret;
return 0;
}
}
return plane_stride;
}
// static
size_t CameraBufferManager::GetPlaneSize(buffer_handle_t buffer, size_t plane) {
if (plane >= GetNumPlanes(buffer)) {
LOGF(ERROR) << "Invalid plane: " << plane;
return 0;
}
// only support one physical plane, so plane size is
// the same as frame size
unsigned int size = 0;
gralloc_module_t* gm_module_ =
CameraBufferManagerImpl::gm_module_;
if (gm_module_ && gm_module_->perform) {
//GRALLOC_MODULE_PERFORM_GET_HADNLE_SIZE gets the whole buffer size
//while it should get the plane size here, but dut to we now support one
//plane only, so it's ok to use buffer size to replace plane size
gm_module_->perform(gm_module_,
GRALLOC_MODULE_PERFORM_GET_HADNLE_SIZE,
buffer,
&size);
}
return size;
}
CameraBufferManagerImpl::CameraBufferManagerImpl()
{
}
CameraBufferManagerImpl::~CameraBufferManagerImpl() {
}
int CameraBufferManagerImpl::Allocate(size_t width,
size_t height,
uint32_t format,
uint32_t usage,
BufferType type,
buffer_handle_t* out_buffer,
uint32_t* out_stride) {
if (type == GRALLOC) {
return AllocateGrallocBuffer(width, height, format, usage, out_buffer,
out_stride);
} else {
NOTREACHED() << "Invalid buffer type: " << type;
return -EINVAL;
}
}
int CameraBufferManagerImpl::Free(buffer_handle_t buffer) {
base::AutoLock l(lock_);
auto context_it = buffer_context_.find(buffer);
if (context_it == buffer_context_.end()) {
LOGF(ERROR) << "Unknown buffer 0x" << std::hex << buffer;
return -EINVAL;
}
auto buffer_context = context_it->second.get();
if (buffer_context->type == GRALLOC) {
return alloc_device_->free(alloc_device_, buffer);
} else {
// TODO(jcliang): Implement deletion of SharedMemory.
return -EINVAL;
}
}
int CameraBufferManagerImpl::Register(buffer_handle_t buffer) {
base::AutoLock l(lock_);
auto context_it = buffer_context_.find(buffer);
if (context_it != buffer_context_.end()) {
context_it->second->usage++;
return 0;
}
std::unique_ptr<BufferContext> buffer_context(new struct BufferContext);
buffer_context->type = GRALLOC;
int ret = gm_module_->registerBuffer(gm_module_, buffer);
if (ret) {
LOGF(ERROR) << "Failed to register gralloc buffer";
return ret;
}
buffer_context->usage = 1;
buffer_context_[buffer] = std::move(buffer_context);
return 0;
}
int CameraBufferManagerImpl::Deregister(buffer_handle_t buffer) {
base::AutoLock l(lock_);
auto context_it = buffer_context_.find(buffer);
if (context_it == buffer_context_.end()) {
LOGF(ERROR) << "Unknown buffer 0x" << std::hex << buffer;
return -EINVAL;
}
auto buffer_context = context_it->second.get();
if (buffer_context->type == GRALLOC) {
if (!--buffer_context->usage) {
// Unmap all the existing mapping of bo.
buffer_context_.erase(context_it);
int ret = gm_module_->unregisterBuffer(gm_module_, buffer);
if (ret) {
LOGF(ERROR) << "Failed to unregister gralloc buffer";
return ret;
}
}
return 0;
} else {
NOTREACHED() << "Invalid buffer type: " << buffer_context->type;
return -EINVAL;
}
}
int CameraBufferManagerImpl::Lock(buffer_handle_t buffer,
uint32_t flags,
uint32_t x,
uint32_t y,
uint32_t width,
uint32_t height,
void** out_addr) {
base::AutoLock l(lock_);
auto context_it = buffer_context_.find(buffer);
if (context_it == buffer_context_.end()) {
LOGF(ERROR) << "Unknown buffer 0x" << std::hex << buffer;
return -EINVAL;
}
auto buffer_context = context_it->second.get();
uint32_t num_planes = GetNumPlanes(buffer);
if (!num_planes) {
return -EINVAL;
}
if (num_planes > 1) {
LOGF(ERROR) << "Lock called on multi-planar buffer 0x" << std::hex
<< buffer;
return -EINVAL;
}
if (buffer_context->type == GRALLOC) {
void* vir_addr = nullptr;
if (gm_module_->lock) {
int ret = gm_module_->lock(gm_module_, buffer, flags,
x, y, width, height, &vir_addr);
if (ret < 0)
return -EINVAL;
}
*out_addr = vir_addr;
} else {
NOTREACHED() << "Invalid buffer type: " << buffer_context->type;
return -EINVAL;
}
return 0;
}
int CameraBufferManagerImpl::LockYCbCr(buffer_handle_t buffer,
uint32_t flags,
uint32_t x,
uint32_t y,
uint32_t width,
uint32_t height,
struct android_ycbcr* out_ycbcr) {
base::AutoLock l(lock_);
auto context_it = buffer_context_.find(buffer);
if (context_it == buffer_context_.end()) {
LOGF(ERROR) << "Unknown buffer 0x" << std::hex << buffer;
return -EINVAL;
}
auto buffer_context = context_it->second.get();
uint32_t num_planes = GetNumPlanes(buffer);
if (!num_planes) {
return -EINVAL;
}
if (num_planes < 2) {
LOGF(ERROR) << "LockYCbCr called on single-planar buffer 0x" << std::hex
<< buffer_context->buffer_id;
return -EINVAL;
}
DCHECK_LE(num_planes, 3u);
if (buffer_context->type == GRALLOC) {
if (gm_module_->lock_ycbcr) {
int ret = gm_module_->lock_ycbcr(gm_module_, buffer, flags,
x, y, width, height, out_ycbcr);
if (ret < 0)
return -EINVAL;
}
} else {
NOTREACHED() << "Invalid buffer type: " << buffer_context->type;
return -EINVAL;
}
return 0;
}
int CameraBufferManagerImpl::Unlock(buffer_handle_t buffer) {
base::AutoLock l(lock_);
auto context_it = buffer_context_.find(buffer);
if (context_it == buffer_context_.end()) {
LOGF(ERROR) << "Unknown buffer 0x" << std::hex << buffer;
return -EINVAL;
}
auto buffer_context = context_it->second.get();
if (buffer_context->type == GRALLOC && gm_module_->unlock)
return gm_module_->unlock(gm_module_, buffer);
return 0;
}
int CameraBufferManagerImpl::FlushCache(buffer_handle_t buffer) {
int fd = -1;
if (gm_module_ && gm_module_->perform)
gm_module_->perform(gm_module_,
GRALLOC_MODULE_PERFORM_GET_HADNLE_PRIME_FD,
buffer, &fd);
if (fd == -1) {
LOGF(ERROR) << "get fd error for buffer 0x" << std::hex << buffer;
return -EINVAL;
}
struct dma_buf_sync sync_args;
sync_args.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW;
if (ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync_args))
return -EINVAL;
return 0;
}
int CameraBufferManagerImpl::GetHandleFd(buffer_handle_t buffer) {
int fd = -1;
if (gm_module_ && gm_module_->perform)
gm_module_->perform(gm_module_,
GRALLOC_MODULE_PERFORM_GET_HADNLE_PRIME_FD,
buffer, &fd);
if (fd == -1) {
LOGF(ERROR) << "get fd error for buffer 0x" << std::hex << buffer;
return -EINVAL;
}
return fd;
}
int CameraBufferManagerImpl::AllocateGrallocBuffer(size_t width,
size_t height,
uint32_t format,
uint32_t usage,
buffer_handle_t* out_buffer,
uint32_t* out_stride) {
base::AutoLock l(lock_);
std::unique_ptr<BufferContext> buffer_context(new struct BufferContext);
buffer_context->buffer_id = reinterpret_cast<uint64_t>(buffer_context.get());
buffer_context->type = GRALLOC;
int ret = alloc_device_->alloc(alloc_device_, width, height,
format, usage, out_buffer,
reinterpret_cast<int*>(out_stride));
if (ret < 0)
return -EINVAL;
buffer_context->usage = 1;
buffer_context_[*out_buffer] = std::move(buffer_context);
return 0;
}
} // namespace arc