/* * cl_image_bo_buffer.cpp - cl image 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 "cl_image_bo_buffer.h" #include "cl_memory.h" #include "swapped_buffer.h" namespace XCam { CLImageBoData::CLImageBoData (SmartPtr &display, SmartPtr &image, drm_intel_bo *bo) : DrmBoData (display, bo) , _image (image) { XCAM_ASSERT (image->get_mem_id ()); } int CLImageBoData::get_fd () { if (!_image.ptr()) return -1; return _image->export_fd (); } CLImageBoBuffer::CLImageBoBuffer (const VideoBufferInfo &info, const SmartPtr &data) : BufferProxy (info, data) , DrmBoBuffer (info, data) { } SmartPtr CLImageBoBuffer::get_cl_image () { SmartPtr data = get_buffer_data (); SmartPtr image = data.dynamic_cast_ptr (); XCAM_FAIL_RETURN( WARNING, image.ptr(), NULL, "CLImageBoBuffer get_buffer_data failed with NULL"); return image->get_image (); } SmartPtr CLImageBoBuffer::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, "CLImageBoBuffer create_new_swap_buffer failed with NULL buffer data"); return new CLImageBoBuffer (info, bo); } CLBoBufferPool::CLBoBufferPool (SmartPtr &display, SmartPtr &context) : DrmBoBufferPool (display) , _context (context) { XCAM_ASSERT (context.ptr ()); XCAM_LOG_DEBUG ("CLBoBufferPool constructed"); } CLBoBufferPool::~CLBoBufferPool () { XCAM_LOG_DEBUG ("CLBoBufferPool destructed"); } SmartPtr CLBoBufferPool::create_image_bo (const VideoBufferInfo &info) { int32_t mem_fd = -1; SmartPtr display = get_drm_display (); drm_intel_bo *bo = NULL; CLImageDesc desc; SmartPtr data; SmartPtr image; uint32_t swap_flags = get_swap_flags (); uint32_t extra_array_size = 0; if (swap_flags & (uint32_t)(SwappedBuffer::SwapY)) ++extra_array_size; if (swap_flags & (uint32_t)(SwappedBuffer::SwapUV)) ++extra_array_size; if (info.components == 1) image = new CLImage2D (_context, info, CL_MEM_READ_WRITE); else image = new CLImage2DArray (_context, info, CL_MEM_READ_WRITE, extra_array_size); XCAM_FAIL_RETURN ( WARNING, image.ptr () && image->get_mem_id (), NULL, "CLBoBufferPool create image failed"); desc = image->get_image_desc (); mem_fd = image->export_fd (); XCAM_FAIL_RETURN ( WARNING, mem_fd >= 0, NULL, "CLBoBufferPool export image fd failed"); bo = display->create_drm_bo_from_fd (mem_fd, desc.size); XCAM_FAIL_RETURN ( WARNING, bo, NULL, "CLBoBufferPool bind fd to bo failed"); data = new CLImageBoData (display, image, bo); XCAM_FAIL_RETURN ( WARNING, data.ptr (), NULL, "CLBoBufferPool bind CLImage to CLImageBoData failed"); return data; } bool CLBoBufferPool::fixate_video_info (VideoBufferInfo &info) { bool need_reset_info = false; uint32_t i = 0; SmartPtr image; uint32_t swap_flags = get_swap_flags (); SmartPtr image_data = create_image_bo (info); XCAM_FAIL_RETURN ( WARNING, image_data.ptr (), NULL, "CLBoBufferPool fixate_video_info failed"); image = image_data->get_image (); XCAM_ASSERT (image.ptr ()); CLImageDesc desc = image->get_image_desc (); if (desc.row_pitch != info.strides [0] || desc.size != info.size) need_reset_info = true; for (i = 1; i < info.components && !need_reset_info; ++i) { XCAM_ASSERT (desc.slice_pitch && desc.array_size >= info.components); if (desc.row_pitch != info.strides [i] || info.offsets [i] != desc.slice_pitch * i) need_reset_info = true; } if (need_reset_info) { VideoBufferPlanarInfo plane_info; info.get_planar_info (plane_info, 0); uint32_t aligned_width = desc.row_pitch / plane_info.pixel_bytes; uint32_t aligned_height = info.aligned_height; if (info.components > 0) aligned_height = desc.slice_pitch / desc.row_pitch; info.init (info.format, info.width, info.height, aligned_width, aligned_height, desc.size); for (i = 1; i < info.components; ++i) { info.offsets[i] = desc.slice_pitch * i; info.strides[i] = desc.row_pitch; } } if (swap_flags && desc.array_size >= 2) { if (swap_flags & (uint32_t)(SwappedBuffer::SwapY)) { _swap_offsets[SwappedBuffer::SwapYOffset0] = info.offsets[0]; _swap_offsets[SwappedBuffer::SwapYOffset1] = desc.slice_pitch * 2; } if (swap_flags & (uint32_t)(SwappedBuffer::SwapUV)) { _swap_offsets[SwappedBuffer::SwapUVOffset0] = info.offsets[1]; _swap_offsets[SwappedBuffer::SwapUVOffset1] = desc.slice_pitch * (desc.array_size - 1); } } if(!init_swap_order (info)) { XCAM_LOG_ERROR ("CLBoBufferPool: fix video info faield to init swap order"); return false; } add_data_unsafe (image_data); return true; } SmartPtr CLBoBufferPool::allocate_data (const VideoBufferInfo &buffer_info) { SmartPtr image_data = create_image_bo (buffer_info); return image_data; } SmartPtr CLBoBufferPool::create_buffer_from_data (SmartPtr &data) { const VideoBufferInfo & info = get_video_info (); SmartPtr image_data = data.dynamic_cast_ptr (); XCAM_ASSERT (image_data.ptr ()); SmartPtr out_buf = new CLImageBoBuffer (info, image_data); XCAM_ASSERT (out_buf.ptr ()); out_buf->set_swap_info (_swap_flags, _swap_offsets); return out_buf; } };