| /* |
| * cl_gauss_handler.cpp - CL gauss handler |
| * |
| * Copyright (c) 2016 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: wangfei <[email protected]> |
| * Wind Yuan <[email protected]> |
| */ |
| |
| #include "cl_utils.h" |
| #include "cl_gauss_handler.h" |
| #include <algorithm> |
| |
| #define XCAM_GAUSS_SCALE(radius) ((radius) * 2 + 1) |
| |
| namespace XCam { |
| |
| const static XCamKernelInfo kernel_gauss_info = { |
| "kernel_gauss", |
| #include "kernel_gauss.clx" |
| , 0, |
| }; |
| |
| class CLGaussImageKernelImpl |
| : public CLGaussImageKernel |
| { |
| public: |
| CLGaussImageKernelImpl ( |
| SmartPtr<CLGaussImageHandler> &handler, |
| const SmartPtr<CLContext> &context, uint32_t radius, float sigma); |
| |
| virtual SmartPtr<VideoBuffer> get_input_buf (); |
| virtual SmartPtr<VideoBuffer> get_output_buf (); |
| private: |
| SmartPtr<CLGaussImageHandler> _handler; |
| }; |
| |
| CLGaussImageKernelImpl::CLGaussImageKernelImpl ( |
| SmartPtr<CLGaussImageHandler> &handler, |
| const SmartPtr<CLContext> &context, |
| uint32_t radius, |
| float sigma |
| ) |
| : CLGaussImageKernel (context, radius, sigma) |
| , _handler (handler) |
| { |
| } |
| |
| SmartPtr<VideoBuffer> |
| CLGaussImageKernelImpl::get_input_buf () |
| { |
| return _handler->get_input_buf (); |
| } |
| SmartPtr<VideoBuffer> |
| CLGaussImageKernelImpl::get_output_buf () |
| { |
| return _handler->get_output_buf ();; |
| } |
| |
| CLGaussImageKernel::CLGaussImageKernel ( |
| const SmartPtr<CLContext> &context, uint32_t radius, float sigma) |
| : CLImageKernel (context, "kernel_gauss") |
| , _g_radius (radius) |
| , _g_table (NULL) |
| { |
| set_gaussian(radius, sigma); |
| } |
| |
| CLGaussImageKernel::~CLGaussImageKernel () |
| { |
| xcam_free (_g_table); |
| } |
| |
| bool |
| CLGaussImageKernel::set_gaussian (uint32_t radius, float sigma) |
| { |
| uint32_t i, j; |
| uint32_t scale = XCAM_GAUSS_SCALE (radius); |
| float dis = 0.0f, sum = 0.0f; |
| uint32_t scale_size = scale * scale * sizeof (_g_table[0]); |
| |
| xcam_free (_g_table); |
| _g_table_buffer.release (); |
| _g_radius = radius; |
| _g_table = (float*) xcam_malloc0 (scale_size); |
| XCAM_ASSERT (_g_table); |
| |
| for(i = 0; i < scale; i++) { |
| for(j = 0; j < scale; j++) { |
| dis = ((float)i - radius) * ((float)i - radius) + ((float)j - radius) * ((float)j - radius); |
| _g_table[i * scale + j] = exp(-dis / (2.0f * sigma * sigma)); |
| sum += _g_table[i * scale + j]; |
| } |
| } |
| |
| for(i = 0; i < scale * scale; i++) { |
| _g_table[i] = _g_table[i] / sum; |
| } |
| |
| _g_table_buffer = new CLBuffer( |
| get_context (), scale_size, |
| CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR , _g_table); |
| |
| return true; |
| } |
| |
| XCamReturn |
| CLGaussImageKernel::prepare_arguments (CLArgList &args, CLWorkSize &work_size) |
| { |
| SmartPtr<CLContext> context = get_context (); |
| SmartPtr<VideoBuffer> input = get_input_buf (); |
| SmartPtr<VideoBuffer> output = get_output_buf (); |
| |
| XCAM_FAIL_RETURN ( |
| WARNING, |
| input.ptr () && output.ptr (), |
| XCAM_RETURN_ERROR_MEM, |
| "cl image kernel(%s) get input/output buffer failed", get_kernel_name ()); |
| |
| const VideoBufferInfo & video_info_in = input->get_video_info (); |
| const VideoBufferInfo & video_info_out = output->get_video_info (); |
| CLImageDesc cl_desc_in, cl_desc_out; |
| |
| cl_desc_in.format.image_channel_data_type = CL_UNORM_INT8; |
| cl_desc_in.format.image_channel_order = CL_R; |
| cl_desc_in.width = video_info_in.width; |
| cl_desc_in.height = video_info_in.height; |
| cl_desc_in.row_pitch = video_info_in.strides[0]; |
| SmartPtr<CLImage> image_in = convert_to_climage (context, input, cl_desc_in, video_info_in.offsets[0]); |
| |
| cl_desc_out.format.image_channel_data_type = CL_UNORM_INT8; |
| cl_desc_out.format.image_channel_order = CL_RGBA; |
| cl_desc_out.width = video_info_out.width / 4; |
| cl_desc_out.height = video_info_out.height; |
| cl_desc_out.row_pitch = video_info_out.strides[0]; |
| SmartPtr<CLImage> image_out = convert_to_climage (context, output, cl_desc_out, video_info_out.offsets[0]); |
| |
| XCAM_FAIL_RETURN ( |
| WARNING, |
| image_in->is_valid () && image_out->is_valid (), |
| XCAM_RETURN_ERROR_MEM, |
| "cl image kernel(%s) in/out memory not available", get_kernel_name ()); |
| |
| //set args; |
| args.push_back (new CLMemArgument (image_in)); |
| args.push_back (new CLMemArgument (image_out)); |
| args.push_back (new CLMemArgument (_g_table_buffer)); |
| |
| work_size.dim = XCAM_DEFAULT_IMAGE_DIM; |
| work_size.global[0] = XCAM_ALIGN_UP(cl_desc_out.width, 8); |
| work_size.global[1] = XCAM_ALIGN_UP (cl_desc_out.height / 2, 4); |
| work_size.local[0] = 8; |
| work_size.local[1] = 4; |
| |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| CLGaussImageHandler::CLGaussImageHandler (const SmartPtr<CLContext> &context, const char *name) |
| : CLImageHandler (context, name) |
| { |
| } |
| |
| bool |
| CLGaussImageHandler::set_gaussian_table (int size, float sigma) |
| { |
| _gauss_kernel->set_gaussian (size, sigma); |
| return true; |
| } |
| |
| bool |
| CLGaussImageHandler::set_gauss_kernel(SmartPtr<CLGaussImageKernel> &kernel) |
| { |
| SmartPtr<CLImageKernel> image_kernel = kernel; |
| add_kernel (image_kernel); |
| _gauss_kernel = kernel; |
| return true; |
| } |
| |
| SmartPtr<CLImageHandler> |
| create_cl_gauss_image_handler (const SmartPtr<CLContext> &context, uint32_t radius, float sigma) |
| { |
| SmartPtr<CLGaussImageHandler> gauss_handler; |
| SmartPtr<CLGaussImageKernel> gauss_kernel; |
| char build_options[1024]; |
| |
| xcam_mem_clear (build_options); |
| snprintf (build_options, sizeof (build_options), " -DGAUSS_RADIUS=%d ", radius); |
| |
| gauss_handler = new CLGaussImageHandler (context, "cl_handler_gauss"); |
| gauss_kernel = new CLGaussImageKernelImpl (gauss_handler, context, radius, sigma); |
| XCAM_ASSERT (gauss_kernel.ptr ()); |
| XCAM_FAIL_RETURN ( |
| ERROR, gauss_kernel->build_kernel (kernel_gauss_info, build_options) == XCAM_RETURN_NO_ERROR, NULL, |
| "build gaussian kernel(%s) failed", kernel_gauss_info.kernel_name); |
| |
| XCAM_ASSERT (gauss_kernel->is_valid ()); |
| gauss_handler->set_gauss_kernel (gauss_kernel); |
| |
| return gauss_handler; |
| } |
| |
| } |