/* * drm_bo_buffer.cpp - drm bo buffer * * Copyright (c) 2015 Intel Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Author: Wind Yuan */ #include "drm_bo_buffer.h" #include "x3a_stats_pool.h" #define OCL_TILING_NONE 0 namespace XCam { DrmBoData::DrmBoData (SmartPtr &display, drm_intel_bo *bo) : _display (display) , _bo (bo) , _buf (NULL) , _prime_fd (-1) , _need_close_fd (true) { XCAM_ASSERT (display.ptr ()); XCAM_ASSERT (bo); } DrmBoData::~DrmBoData () { unmap (); if (_bo) drm_intel_bo_unreference (_bo); if (_prime_fd != -1 && _need_close_fd) close (_prime_fd); } uint8_t * DrmBoData::map () { if (_buf) { return _buf; } uint32_t tiling_mode, swizzle_mode; drm_intel_bo_get_tiling (_bo, &tiling_mode, &swizzle_mode); if (tiling_mode != OCL_TILING_NONE) { if (drm_intel_gem_bo_map_gtt (_bo) != 0) return NULL; } else { if (drm_intel_bo_map (_bo, 1) != 0) return NULL; } _buf = (uint8_t *)_bo->virt; return _buf; } bool DrmBoData::unmap () { if (!_buf || !_bo) return true; uint32_t tiling_mode, swizzle_mode; drm_intel_bo_get_tiling (_bo, &tiling_mode, &swizzle_mode); if (tiling_mode != OCL_TILING_NONE) { if (drm_intel_gem_bo_unmap_gtt (_bo) != 0) return false; } else { if (drm_intel_bo_unmap (_bo) != 0) return false; } _buf = NULL; return true; } int DrmBoData::get_fd () { if (_prime_fd == -1) { if (drm_intel_bo_gem_export_to_prime (_bo, &_prime_fd) < 0) { _prime_fd = -1; XCAM_LOG_ERROR ("DrmBoData: failed to obtain prime fd: %s", strerror(errno)); } _need_close_fd = true; } return _prime_fd; } bool DrmBoData::set_prime_fd (int fd, bool need_close) { if (_prime_fd != -1) { XCAM_LOG_ERROR ("DrmBoData: set_dma_fd failed, the current prime fd was already set"); return false; } _prime_fd = fd; _need_close_fd = need_close; return true; } DrmBoBuffer::DrmBoBuffer (const VideoBufferInfo &info, const SmartPtr &data) : BufferProxy (info, data) , SwappedBuffer (info, data) { XCAM_ASSERT (data.ptr ()); } drm_intel_bo * DrmBoBuffer::get_bo () { SmartPtr data = get_buffer_data (); SmartPtr bo = data.dynamic_cast_ptr (); XCAM_FAIL_RETURN( WARNING, bo.ptr(), NULL, "DrmBoBuffer get_buffer_data failed with NULL"); return bo->get_bo (); } SmartPtr DrmBoBuffer::find_3a_stats () { return find_typed_attach (); } SmartPtr DrmBoBuffer::create_new_swap_buffer ( const VideoBufferInfo &info, SmartPtr &data) { XCAM_ASSERT (get_buffer_data ().ptr () == data.ptr ()); SmartPtr bo = data.dynamic_cast_ptr (); XCAM_FAIL_RETURN( WARNING, bo.ptr(), NULL, "DrmBoBuffer create_new_swap_buffer failed with NULL buffer data"); return new DrmBoBuffer (info, bo); } DrmBoBufferPool::DrmBoBufferPool (SmartPtr &display) : _swap_flags (SwappedBuffer::SwapNone) , _swap_init_order ((uint32_t)(SwappedBuffer::OrderY0Y1) | (uint32_t)(SwappedBuffer::OrderUV0UV1)) , _display (display) { xcam_mem_clear (_swap_offsets); XCAM_ASSERT (display.ptr ()); XCAM_LOG_DEBUG ("DrmBoBufferPool constructed"); } DrmBoBufferPool::~DrmBoBufferPool () { _display.release (); XCAM_LOG_DEBUG ("DrmBoBufferPool destructed"); } bool DrmBoBufferPool::update_swap_init_order (uint32_t init_order) { VideoBufferInfo info = get_video_info (); XCAM_ASSERT (info.format); if ((_swap_flags & (uint32_t)(SwappedBuffer::SwapY)) && !(init_order & (uint32_t)(SwappedBuffer::OrderYMask))) { XCAM_LOG_WARNING ("update swap init order failed, need init Y order, error order:0x%04x", init_order); return false; } if ((_swap_flags & (uint32_t)(SwappedBuffer::SwapUV)) && !(init_order & (uint32_t)(SwappedBuffer::OrderUVMask))) { XCAM_LOG_WARNING ("update swap init order failed, need init UV order, error order:0x%04x", init_order); return false; } _swap_init_order = init_order; XCAM_FAIL_RETURN ( WARNING, init_swap_order (info), false, "CL3aImageProcessor post_config failed"); update_video_info_unsafe (info); return true; } bool DrmBoBufferPool::fixate_video_info (VideoBufferInfo &info) { if (info.format != V4L2_PIX_FMT_NV12) return true; VideoBufferInfo out_info; out_info.init (info.format, info.width, info.height, info.aligned_width, info.aligned_height); if (_swap_flags & (uint32_t)(SwappedBuffer::SwapY)) { _swap_offsets[SwappedBuffer::SwapYOffset0] = out_info.offsets[0]; _swap_offsets[SwappedBuffer::SwapYOffset1] = out_info.size; out_info.size += out_info.strides[0] * out_info.aligned_height; } if (_swap_flags & (uint32_t)(SwappedBuffer::SwapUV)) { _swap_offsets[SwappedBuffer::SwapUVOffset0] = out_info.offsets[1]; _swap_offsets[SwappedBuffer::SwapUVOffset1] = out_info.size; out_info.size += out_info.strides[1] * (out_info.aligned_height + 1) / 2; } if(!init_swap_order (out_info)) { XCAM_LOG_ERROR ("DrmBoBufferPool: fix video info faield to init swap order"); return false; } info = out_info; return true; } bool DrmBoBufferPool::init_swap_order (VideoBufferInfo &info) { if (_swap_flags & (uint32_t)(SwappedBuffer::SwapY)) { if ((_swap_init_order & (uint32_t)(SwappedBuffer::OrderYMask)) == (uint32_t)(SwappedBuffer::OrderY0Y1)) { info.offsets[0] = _swap_offsets[SwappedBuffer::SwapYOffset0]; } else if ((_swap_init_order & (uint32_t)(SwappedBuffer::OrderYMask)) == (uint32_t)(SwappedBuffer::OrderY1Y0)) { info.offsets[0] = _swap_offsets[SwappedBuffer::SwapYOffset1]; } else { XCAM_LOG_WARNING ("BufferPool: There's unknown init_swap_order(Y):0x%04x", _swap_init_order); return false; } } if (_swap_flags & (uint32_t)(SwappedBuffer::SwapUV)) { if ((_swap_init_order & (uint32_t)(SwappedBuffer::OrderUVMask)) == (uint32_t)(SwappedBuffer::OrderUV0UV1)) { info.offsets[1] = _swap_offsets[SwappedBuffer::SwapUVOffset0]; } else if ((_swap_init_order & (uint32_t)(SwappedBuffer::OrderUVMask)) == (uint32_t)(SwappedBuffer::OrderUV1UV0)) { info.offsets[1] = _swap_offsets[SwappedBuffer::SwapUVOffset1]; } else { XCAM_LOG_WARNING ("BufferPool: There's unknown init_swap_order(UV):0x%04x", _swap_init_order); return false; } } return true; } SmartPtr DrmBoBufferPool::allocate_data (const VideoBufferInfo &buffer_info) { SmartPtr bo = _display->create_drm_bo (_display, buffer_info); return bo; } SmartPtr DrmBoBufferPool::create_buffer_from_data (SmartPtr &data) { const VideoBufferInfo & info = get_video_info (); SmartPtr bo_data = data.dynamic_cast_ptr (); XCAM_ASSERT (bo_data.ptr ()); SmartPtr out_buf = new DrmBoBuffer (info, bo_data); XCAM_ASSERT (out_buf.ptr ()); out_buf->set_swap_info (_swap_flags, _swap_offsets); return out_buf; } };