blob: dd1c142f1b6b02e94d61b64ef6e6d1c725eecb7f [file] [log] [blame]
// 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 "camera3_test_gralloc.h"
#include <algorithm>
#include "arc/camera_buffer_mapper.h"
#include "common/camera_buffer_mapper_internal.h"
#include <drm_fourcc.h>
namespace camera3_test {
void BufferHandleDeleter::operator()(buffer_handle_t* handle) {
if (handle) {
auto hnd = camera_buffer_handle_t::FromBufferHandle(*handle);
if (hnd) {
if (hnd->buffer_id) {
arc::CameraBufferMapper::GetInstance()->Deregister(*handle);
gbm_bo_destroy(reinterpret_cast<struct gbm_bo*>(hnd->buffer_id));
} else {
LOG(ERROR) << "Buffer handle mapping fails";
}
delete hnd;
}
delete handle;
}
}
Camera3TestGralloc* Camera3TestGralloc::GetInstance() {
static Camera3TestGralloc gralloc;
if (!gralloc.gbm_dev_) {
gralloc.gbm_dev_ = ::arc::internal::CreateGbmDevice();
if (!gralloc.gbm_dev_) {
LOG(ERROR) << "Can't create gbm device";
return nullptr;
}
uint32_t formats[] = {DRM_FORMAT_YVU420, DRM_FORMAT_NV12, DRM_FORMAT_YUV420,
DRM_FORMAT_NV21};
size_t i = 0;
for (; i < arraysize(formats); i++) {
if (gbm_device_is_format_supported(gralloc.gbm_dev_, formats[i],
GBM_BO_USE_RENDERING)) {
gralloc.flexible_yuv_420_format_ = formats[i];
break;
}
}
if (i == arraysize(formats)) {
LOG(ERROR) << "Can't detect flexible YUV 420 format";
close(gbm_device_get_fd(gralloc.gbm_dev_));
gbm_device_destroy(gralloc.gbm_dev_);
gralloc.gbm_dev_ = nullptr;
return nullptr;
}
}
return &gralloc;
}
Camera3TestGralloc::~Camera3TestGralloc() {
if (gbm_dev_) {
close(gbm_device_get_fd(gbm_dev_));
gbm_device_destroy(gbm_dev_);
}
}
BufferHandleUniquePtr Camera3TestGralloc::Allocate(int32_t width,
int32_t height,
int32_t format,
int32_t usage) {
uint64_t gbm_usage;
uint32_t gbm_format;
struct gbm_bo* bo;
gbm_format = GrallocConvertFormat(format);
gbm_usage = GrallocConvertFlags(format, usage);
if (gbm_format == 0 ||
!gbm_device_is_format_supported(gbm_dev_, gbm_format, gbm_usage)) {
LOG(ERROR) << "Unsupported format " << gbm_format;
return BufferHandleUniquePtr(nullptr);
}
bo = gbm_bo_create(gbm_dev_, width, height, gbm_format, gbm_usage);
if (!bo) {
LOG(ERROR) << "Failed to create bo (" << width << "x" << height << ")";
return BufferHandleUniquePtr(nullptr);
}
camera_buffer_handle_t* hnd = new camera_buffer_handle_t();
hnd->base.version = sizeof(hnd->base);
hnd->base.numInts = kCameraBufferHandleNumInts;
hnd->base.numFds = kCameraBufferHandleNumFds;
hnd->magic = kCameraBufferMagic;
hnd->buffer_id = reinterpret_cast<uint64_t>(bo);
hnd->type = arc::GRALLOC;
hnd->drm_format = gbm_bo_get_format(bo);
hnd->hal_pixel_format = format;
hnd->width = gbm_bo_get_width(bo);
hnd->height = gbm_bo_get_height(bo);
for (size_t i = 0; i < gbm_bo_get_num_planes(bo); ++i) {
hnd->fds[i].reset(gbm_bo_get_plane_fd(bo, i));
hnd->strides[i] = gbm_bo_get_plane_stride(bo, i);
hnd->offsets[i] = gbm_bo_get_plane_offset(bo, i);
}
BufferHandleUniquePtr handle(new buffer_handle_t);
*handle = reinterpret_cast<buffer_handle_t>(hnd);
buffer_mapper_->Register(*handle);
return handle;
}
int Camera3TestGralloc::Lock(buffer_handle_t buffer,
uint32_t flags,
uint32_t x,
uint32_t y,
uint32_t width,
uint32_t height,
void** out_addr) {
return buffer_mapper_->Lock(buffer, flags, x, y, width, height, out_addr);
}
int Camera3TestGralloc::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) {
return buffer_mapper_->LockYCbCr(buffer, flags, x, y, width, height,
out_ycbcr);
}
int Camera3TestGralloc::Unlock(buffer_handle_t buffer) {
return buffer_mapper_->Unlock(buffer);
}
int Camera3TestGralloc::GetFormat(buffer_handle_t buffer) {
auto hnd = camera_buffer_handle_t::FromBufferHandle(buffer);
return (hnd && hnd->buffer_id) ? hnd->hal_pixel_format : -EINVAL;
}
uint64_t Camera3TestGralloc::GrallocConvertFlags(int32_t format,
int32_t flags) {
return (format == HAL_PIXEL_FORMAT_BLOB) ? GBM_BO_USE_LINEAR
: GBM_BO_USE_RENDERING;
}
uint32_t Camera3TestGralloc::GrallocConvertFormat(int32_t format) {
switch (format) {
case HAL_PIXEL_FORMAT_BGRA_8888:
return DRM_FORMAT_ARGB8888;
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
return DRM_FORMAT_XBGR8888;
case HAL_PIXEL_FORMAT_RGBA_8888:
return DRM_FORMAT_ABGR8888;
case HAL_PIXEL_FORMAT_RGBX_8888:
return DRM_FORMAT_XBGR8888;
case HAL_PIXEL_FORMAT_YCbCr_420_888:
return flexible_yuv_420_format_;
case HAL_PIXEL_FORMAT_YV12:
return DRM_FORMAT_YVU420;
case HAL_PIXEL_FORMAT_BLOB:
return DRM_FORMAT_R8;
default:
NOTREACHED();
return 0;
}
}
} // namespace camera3_test