| // 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 |