| /* |
| * cl_memory.cpp - CL memory |
| * |
| * 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 <[email protected]> |
| */ |
| |
| #include "cl_utils.h" |
| #include "cl_memory.h" |
| #if HAVE_LIBDRM |
| #include "intel/cl_va_memory.h" |
| #endif |
| |
| namespace XCam { |
| |
| CLImageDesc::CLImageDesc () |
| : format {CL_R, CL_UNORM_INT8} |
| , width (0) |
| , height (0) |
| , row_pitch (0) |
| , slice_pitch (0) |
| , array_size (0) |
| , size (0) |
| { |
| } |
| |
| bool |
| CLImageDesc::operator == (const CLImageDesc& desc) const |
| { |
| if (desc.format.image_channel_data_type == this->format.image_channel_data_type && |
| desc.format.image_channel_order == this->format.image_channel_order && |
| desc.width == this->width && |
| desc.height == this->height && |
| desc.row_pitch == this->row_pitch && |
| desc.slice_pitch == this->slice_pitch && |
| desc.array_size == this->array_size)// && |
| //desc.size == this->size) |
| return true; |
| return false; |
| } |
| |
| CLMemory::CLMemory (const SmartPtr<CLContext> &context) |
| : _context (context) |
| , _mem_id (NULL) |
| , _mem_fd (-1) |
| , _mem_need_destroy (true) |
| , _mapped_ptr (NULL) |
| { |
| XCAM_ASSERT (context.ptr () && context->is_valid ()); |
| } |
| |
| CLMemory::~CLMemory () |
| { |
| release_fd (); |
| |
| if (_mapped_ptr) |
| enqueue_unmap (_mapped_ptr); |
| |
| if (_mem_id && _mem_need_destroy) { |
| _context->destroy_mem (_mem_id); |
| } |
| } |
| |
| int32_t |
| CLMemory::export_fd () |
| { |
| if (_mem_fd >= 0) |
| return _mem_fd; |
| |
| #if HAVE_LIBDRM |
| SmartPtr<CLIntelContext> context = _context.dynamic_cast_ptr<CLIntelContext> (); |
| _mem_fd = context->export_mem_fd (_mem_id); |
| #endif |
| if (_mem_fd < 0) |
| XCAM_LOG_ERROR ("invalid fd:%d", _mem_fd); |
| |
| return _mem_fd; |
| } |
| |
| void |
| CLMemory::release_fd () |
| { |
| if (_mem_fd <= 0) |
| return; |
| |
| close (_mem_fd); |
| _mem_fd = -1; |
| } |
| |
| XCamReturn |
| CLMemory::enqueue_unmap ( |
| void *ptr, |
| CLEventList &event_waits, |
| SmartPtr<CLEvent> &event_out) |
| { |
| SmartPtr<CLContext> context = get_context (); |
| cl_mem mem_id = get_mem_id (); |
| |
| XCAM_ASSERT (is_valid ()); |
| if (!is_valid ()) |
| return XCAM_RETURN_ERROR_PARAM; |
| |
| XCAM_ASSERT (ptr == _mapped_ptr); |
| if (ptr == _mapped_ptr) |
| _mapped_ptr = NULL; |
| |
| return context->enqueue_unmap (mem_id, ptr, event_waits, event_out); |
| } |
| |
| bool CLMemory::get_cl_mem_info ( |
| cl_image_info param_name, size_t param_size, |
| void *param, size_t *param_size_ret) |
| { |
| cl_mem mem_id = get_mem_id (); |
| cl_int error_code = CL_SUCCESS; |
| if (!mem_id) |
| return false; |
| |
| error_code = clGetMemObjectInfo (mem_id, param_name, param_size, param, param_size_ret); |
| XCAM_FAIL_RETURN( |
| WARNING, |
| error_code == CL_SUCCESS, |
| false, |
| "clGetMemObjectInfo failed on param:%d, errno:%d", param_name, error_code); |
| return true; |
| } |
| |
| CLBuffer::CLBuffer (const SmartPtr<CLContext> &context) |
| : CLMemory (context) |
| { |
| } |
| |
| CLBuffer::CLBuffer ( |
| const SmartPtr<CLContext> &context, uint32_t size, |
| cl_mem_flags flags, void *host_ptr) |
| : CLMemory (context) |
| , _flags (flags) |
| , _size (size) |
| { |
| init_buffer (context, size, flags, host_ptr); |
| } |
| |
| bool |
| CLBuffer::init_buffer ( |
| const SmartPtr<CLContext> &context, uint32_t size, |
| cl_mem_flags flags, void *host_ptr) |
| { |
| cl_mem mem_id = NULL; |
| |
| mem_id = context->create_buffer (size, flags, host_ptr); |
| if (mem_id == NULL) { |
| XCAM_LOG_WARNING ("CLBuffer create buffer failed"); |
| return false; |
| } |
| |
| set_mem_id (mem_id); |
| return true; |
| } |
| |
| CLSubBuffer::CLSubBuffer ( |
| const SmartPtr<CLContext> &context, SmartPtr<CLBuffer> main_buf, |
| cl_mem_flags flags, uint32_t offset, uint32_t size) |
| : CLBuffer (context) |
| , _main_buf (main_buf) |
| , _flags (flags) |
| , _size (size) |
| { |
| init_sub_buffer (context, main_buf, flags, offset, size); |
| } |
| |
| bool |
| CLSubBuffer::init_sub_buffer ( |
| const SmartPtr<CLContext> &context, |
| SmartPtr<CLBuffer> main_buf, |
| cl_mem_flags flags, |
| uint32_t offset, |
| uint32_t size) |
| { |
| cl_mem sub_mem = NULL; |
| cl_mem main_mem = main_buf->get_mem_id (); |
| XCAM_FAIL_RETURN (ERROR, main_mem != NULL, false, "get memory from main image failed"); |
| |
| cl_buffer_region region; |
| region.origin = offset; |
| region.size = size; |
| |
| sub_mem = context->create_sub_buffer (main_mem, region, flags); |
| if (sub_mem == NULL) { |
| XCAM_LOG_WARNING ("CLBuffer create sub buffer failed"); |
| return false; |
| } |
| |
| set_mem_id (sub_mem); |
| return true; |
| } |
| |
| XCamReturn |
| CLBuffer::enqueue_read ( |
| void *ptr, uint32_t offset, uint32_t size, |
| CLEventList &event_waits, |
| SmartPtr<CLEvent> &event_out) |
| { |
| SmartPtr<CLContext> context = get_context (); |
| cl_mem mem_id = get_mem_id (); |
| |
| XCAM_ASSERT (is_valid ()); |
| if (!is_valid ()) |
| return XCAM_RETURN_ERROR_PARAM; |
| |
| return context->enqueue_read_buffer (mem_id, ptr, offset, size, true, event_waits, event_out); |
| } |
| |
| XCamReturn |
| CLBuffer::enqueue_write ( |
| void *ptr, uint32_t offset, uint32_t size, |
| CLEventList &event_waits, |
| SmartPtr<CLEvent> &event_out) |
| { |
| SmartPtr<CLContext> context = get_context (); |
| cl_mem mem_id = get_mem_id (); |
| |
| XCAM_ASSERT (is_valid ()); |
| if (!is_valid ()) |
| return XCAM_RETURN_ERROR_PARAM; |
| |
| return context->enqueue_write_buffer (mem_id, ptr, offset, size, true, event_waits, event_out); |
| } |
| |
| XCamReturn |
| CLBuffer::enqueue_map ( |
| void *&ptr, uint32_t offset, uint32_t size, |
| cl_map_flags map_flags, |
| CLEventList &event_waits, |
| SmartPtr<CLEvent> &event_out) |
| { |
| SmartPtr<CLContext> context = get_context (); |
| cl_mem mem_id = get_mem_id (); |
| XCamReturn ret = XCAM_RETURN_NO_ERROR; |
| |
| XCAM_ASSERT (is_valid ()); |
| if (!is_valid ()) |
| return XCAM_RETURN_ERROR_PARAM; |
| |
| ret = context->enqueue_map_buffer (mem_id, ptr, offset, size, true, map_flags, event_waits, event_out); |
| XCAM_FAIL_RETURN ( |
| WARNING, |
| ret == XCAM_RETURN_NO_ERROR, |
| ret, |
| "enqueue_map failed "); |
| |
| set_mapped_ptr (ptr); |
| return ret; |
| } |
| |
| CLImage::CLImage (const SmartPtr<CLContext> &context) |
| : CLMemory (context) |
| { |
| } |
| |
| uint32_t |
| CLImage::get_pixel_bytes () const |
| { |
| return calculate_pixel_bytes(_image_desc.format); |
| } |
| |
| bool |
| CLImage::get_cl_image_info (cl_image_info param_name, size_t param_size, void *param, size_t *param_size_ret) |
| { |
| cl_mem mem_id = get_mem_id (); |
| cl_int error_code = CL_SUCCESS; |
| if (!mem_id) |
| return false; |
| |
| error_code = clGetImageInfo (mem_id, param_name, param_size, param, param_size_ret); |
| XCAM_FAIL_RETURN( |
| WARNING, |
| error_code == CL_SUCCESS, |
| false, |
| "clGetImageInfo failed on param:%d, errno:%d", param_name, error_code); |
| return true; |
| } |
| |
| uint32_t |
| CLImage::calculate_pixel_bytes (const cl_image_format &fmt) |
| { |
| uint32_t a = 0, b = 0; |
| switch (fmt.image_channel_order) { |
| case CL_R: |
| case CL_A: |
| case CL_Rx: |
| a = 1; |
| break; |
| case CL_RG: |
| case CL_RA: |
| case CL_RGx: |
| a = 2; |
| break; |
| case CL_RGB: |
| case CL_RGBx: |
| a = 3; |
| break; |
| case CL_RGBA: |
| case CL_BGRA: |
| case CL_ARGB: |
| a = 4; |
| break; |
| default: |
| XCAM_LOG_DEBUG ("calculate_pixel_bytes with wrong channel_order:0x%04x", fmt.image_channel_order); |
| return 0; |
| } |
| |
| switch (fmt.image_channel_data_type) { |
| case CL_UNORM_INT8: |
| case CL_SNORM_INT8: |
| case CL_SIGNED_INT8: |
| case CL_UNSIGNED_INT8: |
| b = 1; |
| break; |
| case CL_SNORM_INT16: |
| case CL_UNORM_INT16: |
| case CL_SIGNED_INT16: |
| case CL_UNSIGNED_INT16: |
| case CL_HALF_FLOAT: |
| b = 2; |
| break; |
| case CL_UNORM_INT24: |
| b = 3; |
| break; |
| case CL_SIGNED_INT32: |
| case CL_UNSIGNED_INT32: |
| case CL_FLOAT: |
| b = 4; |
| break; |
| default: |
| XCAM_LOG_DEBUG ("calculate_pixel_bytes with wrong channel_data_type:0x%04x", fmt.image_channel_data_type); |
| return 0; |
| } |
| |
| return a * b; |
| } |
| |
| bool |
| CLImage::video_info_2_cl_image_desc ( |
| const VideoBufferInfo & video_info, |
| CLImageDesc &image_desc) |
| { |
| image_desc.width = video_info.width; |
| image_desc.height = video_info.height; |
| image_desc.array_size = 0; |
| image_desc.row_pitch = video_info.strides[0]; |
| XCAM_ASSERT (image_desc.row_pitch >= image_desc.width); |
| image_desc.slice_pitch = 0; |
| |
| switch (video_info.format) { |
| case XCAM_PIX_FMT_RGB48: |
| //cl_image_info.fmt.image_channel_order = CL_RGB; |
| //cl_image_info.fmt.image_channel_data_type = CL_UNORM_INT16; |
| XCAM_LOG_WARNING ( |
| "video_info to cl_image_info doesn't support XCAM_PIX_FMT_RGB48, maybe try XCAM_PIX_FMT_RGBA64 instread\n" |
| " **** XCAM_PIX_FMT_RGB48 need check with cl implementation ****"); |
| return false; |
| break; |
| case V4L2_PIX_FMT_GREY: |
| image_desc.format.image_channel_order = CL_R; |
| image_desc.format.image_channel_data_type = CL_UNORM_INT8; |
| break; |
| |
| case XCAM_PIX_FMT_RGBA64: |
| image_desc.format.image_channel_order = CL_RGBA; |
| image_desc.format.image_channel_data_type = CL_UNORM_INT16; |
| break; |
| |
| case V4L2_PIX_FMT_RGB24: |
| image_desc.format.image_channel_order = CL_RGB; |
| image_desc.format.image_channel_data_type = CL_UNORM_INT8; |
| break; |
| |
| case V4L2_PIX_FMT_RGB565: |
| image_desc.format.image_channel_order = CL_RGB; |
| image_desc.format.image_channel_data_type = CL_UNORM_SHORT_565; |
| break; |
| case V4L2_PIX_FMT_XBGR32: |
| case V4L2_PIX_FMT_ABGR32: |
| case V4L2_PIX_FMT_BGR32: |
| image_desc.format.image_channel_order = CL_BGRA; |
| image_desc.format.image_channel_data_type = CL_UNORM_INT8; |
| break; |
| // cl doesn'tn support ARGB32 up to now, how about consider V4L2_PIX_FMT_RGBA32 |
| case V4L2_PIX_FMT_RGB32: |
| case V4L2_PIX_FMT_ARGB32: |
| case V4L2_PIX_FMT_XRGB32: |
| image_desc.format.image_channel_order = CL_ARGB; |
| image_desc.format.image_channel_data_type = CL_UNORM_INT8; |
| break; |
| |
| case V4L2_PIX_FMT_RGBA32: |
| image_desc.format.image_channel_order = CL_RGBA; |
| image_desc.format.image_channel_data_type = CL_UNORM_INT8; |
| break; |
| |
| case V4L2_PIX_FMT_SBGGR10: |
| case V4L2_PIX_FMT_SGBRG10: |
| case V4L2_PIX_FMT_SGRBG10: |
| case V4L2_PIX_FMT_SRGGB10: |
| case V4L2_PIX_FMT_SBGGR12: |
| case V4L2_PIX_FMT_SGBRG12: |
| case V4L2_PIX_FMT_SGRBG12: |
| case V4L2_PIX_FMT_SRGGB12: |
| case V4L2_PIX_FMT_SBGGR16: |
| case XCAM_PIX_FMT_SGRBG16: |
| image_desc.format.image_channel_order = CL_R; |
| image_desc.format.image_channel_data_type = CL_UNORM_INT16; |
| break; |
| |
| case V4L2_PIX_FMT_SBGGR8: |
| case V4L2_PIX_FMT_SGBRG8: |
| case V4L2_PIX_FMT_SGRBG8: |
| case V4L2_PIX_FMT_SRGGB8: |
| image_desc.format.image_channel_order = CL_R; |
| image_desc.format.image_channel_data_type = CL_UNORM_INT8; |
| break; |
| |
| case V4L2_PIX_FMT_NV12: |
| image_desc.format.image_channel_order = CL_R; |
| image_desc.format.image_channel_data_type = CL_UNORM_INT8; |
| image_desc.array_size = 2; |
| image_desc.slice_pitch = video_info.strides [0] * video_info.aligned_height; |
| break; |
| |
| case V4L2_PIX_FMT_YUYV: |
| image_desc.format.image_channel_order = CL_RGBA; |
| image_desc.format.image_channel_data_type = CL_UNORM_INT8; |
| image_desc.width /= 2; |
| break; |
| |
| case XCAM_PIX_FMT_LAB: |
| image_desc.format.image_channel_order = CL_R; |
| image_desc.format.image_channel_data_type = CL_FLOAT; |
| break; |
| |
| case XCAM_PIX_FMT_RGB48_planar: |
| case XCAM_PIX_FMT_RGB24_planar: |
| image_desc.format.image_channel_order = CL_RGBA; |
| if (XCAM_PIX_FMT_RGB48_planar == video_info.format) |
| image_desc.format.image_channel_data_type = CL_UNORM_INT16; |
| else |
| image_desc.format.image_channel_data_type = CL_UNORM_INT8; |
| image_desc.width = video_info.aligned_width / 4; |
| image_desc.array_size = 3; |
| image_desc.slice_pitch = video_info.strides [0] * video_info.aligned_height; |
| break; |
| |
| case XCAM_PIX_FMT_SGRBG16_planar: |
| case XCAM_PIX_FMT_SGRBG8_planar: |
| image_desc.format.image_channel_order = CL_RGBA; |
| if (XCAM_PIX_FMT_SGRBG16_planar == video_info.format) |
| image_desc.format.image_channel_data_type = CL_UNORM_INT16; |
| else |
| image_desc.format.image_channel_data_type = CL_UNORM_INT8; |
| image_desc.width = video_info.aligned_width / 4; |
| image_desc.array_size = 4; |
| image_desc.slice_pitch = video_info.strides [0] * video_info.aligned_height; |
| break; |
| |
| default: |
| XCAM_LOG_WARNING ( |
| "video_info to cl_image_info doesn't support format:%s", |
| xcam_fourcc_to_string (video_info.format)); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| void |
| CLImage::init_desc_by_image () |
| { |
| size_t width = 0, height = 0, row_pitch = 0, slice_pitch = 0, array_size = 0, mem_size = 0; |
| cl_image_format format = {CL_R, CL_UNORM_INT8}; |
| |
| get_cl_image_info (CL_IMAGE_FORMAT, sizeof(format), &format); |
| get_cl_image_info (CL_IMAGE_WIDTH, sizeof(width), &width); |
| get_cl_image_info (CL_IMAGE_HEIGHT, sizeof(height), &height); |
| get_cl_image_info (CL_IMAGE_ROW_PITCH, sizeof(row_pitch), &row_pitch); |
| get_cl_image_info (CL_IMAGE_SLICE_PITCH, sizeof(slice_pitch), &slice_pitch); |
| get_cl_image_info (CL_IMAGE_ARRAY_SIZE, sizeof(array_size), &array_size); |
| get_cl_mem_info (CL_MEM_SIZE, sizeof(mem_size), &mem_size); |
| |
| _image_desc.format = format; |
| _image_desc.width = width; |
| _image_desc.height = height; |
| _image_desc.row_pitch = row_pitch; |
| _image_desc.slice_pitch = slice_pitch; |
| _image_desc.array_size = array_size; |
| _image_desc.size = mem_size; |
| } |
| |
| XCamReturn |
| CLImage::enqueue_map ( |
| void *&ptr, |
| size_t *origin, size_t *region, |
| size_t *row_pitch, size_t *slice_pitch, |
| cl_map_flags map_flags, |
| CLEventList &event_waits, |
| SmartPtr<CLEvent> &event_out) |
| { |
| SmartPtr<CLContext> context = get_context (); |
| cl_mem mem_id = get_mem_id (); |
| XCamReturn ret = XCAM_RETURN_NO_ERROR; |
| |
| XCAM_ASSERT (is_valid ()); |
| if (!is_valid ()) |
| return XCAM_RETURN_ERROR_PARAM; |
| |
| ret = context->enqueue_map_image (mem_id, ptr, origin, region, row_pitch, slice_pitch, true, map_flags, event_waits, event_out); |
| XCAM_FAIL_RETURN ( |
| WARNING, |
| ret == XCAM_RETURN_NO_ERROR, |
| ret, |
| "enqueue_map failed "); |
| |
| set_mapped_ptr (ptr); |
| return ret; |
| } |
| |
| CLImage2D::CLImage2D ( |
| const SmartPtr<CLContext> &context, |
| const VideoBufferInfo &video_info, |
| cl_mem_flags flags) |
| : CLImage (context) |
| { |
| CLImageDesc cl_desc; |
| |
| if (!video_info_2_cl_image_desc (video_info, cl_desc)) { |
| XCAM_LOG_WARNING ("CLVaImage create va image failed on default videoinfo"); |
| return; |
| } |
| |
| init_image_2d (context, cl_desc, flags); |
| } |
| |
| CLImage2D::CLImage2D ( |
| const SmartPtr<CLContext> &context, |
| const CLImageDesc &cl_desc, |
| cl_mem_flags flags, |
| SmartPtr<CLBuffer> bind_buf) |
| : CLImage (context) |
| { |
| _bind_buf = bind_buf; |
| init_image_2d (context, cl_desc, flags); |
| } |
| |
| bool CLImage2D::init_image_2d ( |
| const SmartPtr<CLContext> &context, |
| const CLImageDesc &desc, |
| cl_mem_flags flags) |
| { |
| cl_mem mem_id = 0; |
| cl_image_desc cl_desc; |
| |
| xcam_mem_clear (cl_desc); |
| cl_desc.image_type = CL_MEM_OBJECT_IMAGE2D; |
| cl_desc.image_width = desc.width; |
| cl_desc.image_height = desc.height; |
| cl_desc.image_depth = 1; |
| cl_desc.image_array_size = 0; |
| cl_desc.image_row_pitch = 0; |
| cl_desc.image_slice_pitch = 0; |
| cl_desc.num_mip_levels = 0; |
| cl_desc.num_samples = 0; |
| cl_desc.buffer = NULL; |
| if (_bind_buf.ptr ()) { |
| if (desc.row_pitch) |
| cl_desc.image_row_pitch = desc.row_pitch; |
| else { |
| cl_desc.image_row_pitch = calculate_pixel_bytes(desc.format) * desc.width; |
| } |
| XCAM_ASSERT (cl_desc.image_row_pitch); |
| cl_desc.buffer = _bind_buf->get_mem_id (); |
| XCAM_ASSERT (cl_desc.buffer); |
| } |
| |
| mem_id = context->create_image (flags, desc.format, cl_desc); |
| if (mem_id == NULL) { |
| XCAM_LOG_WARNING ("CLImage2D create image 2d failed"); |
| return false; |
| } |
| set_mem_id (mem_id); |
| init_desc_by_image (); |
| return true; |
| } |
| |
| CLImage2DArray::CLImage2DArray ( |
| const SmartPtr<CLContext> &context, |
| const VideoBufferInfo &video_info, |
| cl_mem_flags flags, |
| uint32_t extra_array_size) |
| : CLImage (context) |
| { |
| CLImageDesc cl_desc; |
| |
| XCAM_ASSERT (video_info.components >= 2); |
| |
| if (!video_info_2_cl_image_desc (video_info, cl_desc)) { |
| XCAM_LOG_WARNING ("CLVaImage create va image failed on default videoinfo"); |
| return; |
| } |
| XCAM_ASSERT (cl_desc.array_size >= 2); |
| |
| //special process for BYT platform for slice-pitch |
| //if (video_info.format == V4L2_PIX_FMT_NV12) |
| cl_desc.height = XCAM_ALIGN_UP (cl_desc.height, 16); |
| |
| cl_desc.array_size += extra_array_size; |
| |
| init_image_2d_array (context, cl_desc, flags); |
| } |
| |
| bool CLImage2DArray::init_image_2d_array ( |
| const SmartPtr<CLContext> &context, |
| const CLImageDesc &desc, |
| cl_mem_flags flags) |
| { |
| cl_mem mem_id = 0; |
| cl_image_desc cl_desc; |
| |
| xcam_mem_clear (cl_desc); |
| cl_desc.image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY; |
| cl_desc.image_width = desc.width; |
| cl_desc.image_height = desc.height; |
| cl_desc.image_depth = 1; |
| cl_desc.image_array_size = desc.array_size; |
| cl_desc.image_row_pitch = 0; |
| cl_desc.image_slice_pitch = 0; |
| cl_desc.num_mip_levels = 0; |
| cl_desc.num_samples = 0; |
| cl_desc.buffer = NULL; |
| |
| mem_id = context->create_image (flags, desc.format, cl_desc); |
| if (mem_id == NULL) { |
| XCAM_LOG_WARNING ("CLImage2D create image 2d failed"); |
| return false; |
| } |
| set_mem_id (mem_id); |
| init_desc_by_image (); |
| return true; |
| } |
| |
| |
| }; |