1 /* 2 * cl_gauss_handler.cpp - CL gauss handler 3 * 4 * Copyright (c) 2016 Intel Corporation 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 * Author: wangfei <feix.w.wang (at) intel.com> 19 * Wind Yuan <feng.yuan (at) intel.com> 20 */ 21 22 #include "cl_utils.h" 23 #include "cl_gauss_handler.h" 24 #include <algorithm> 25 26 #define XCAM_GAUSS_SCALE(radius) ((radius) * 2 + 1) 27 28 namespace XCam { 29 30 const static XCamKernelInfo kernel_gauss_info = { 31 "kernel_gauss", 32 #include "kernel_gauss.clx" 33 , 0, 34 }; 35 36 class CLGaussImageKernelImpl 37 : public CLGaussImageKernel 38 { 39 public: 40 CLGaussImageKernelImpl ( 41 SmartPtr<CLGaussImageHandler> &handler, 42 const SmartPtr<CLContext> &context, uint32_t radius, float sigma); 43 44 virtual SmartPtr<VideoBuffer> get_input_buf (); 45 virtual SmartPtr<VideoBuffer> get_output_buf (); 46 private: 47 SmartPtr<CLGaussImageHandler> _handler; 48 }; 49 50 CLGaussImageKernelImpl::CLGaussImageKernelImpl ( 51 SmartPtr<CLGaussImageHandler> &handler, 52 const SmartPtr<CLContext> &context, 53 uint32_t radius, 54 float sigma 55 ) 56 : CLGaussImageKernel (context, radius, sigma) 57 , _handler (handler) 58 { 59 } 60 61 SmartPtr<VideoBuffer> 62 CLGaussImageKernelImpl::get_input_buf () 63 { 64 return _handler->get_input_buf (); 65 } 66 SmartPtr<VideoBuffer> 67 CLGaussImageKernelImpl::get_output_buf () 68 { 69 return _handler->get_output_buf ();; 70 } 71 72 CLGaussImageKernel::CLGaussImageKernel ( 73 const SmartPtr<CLContext> &context, uint32_t radius, float sigma) 74 : CLImageKernel (context, "kernel_gauss") 75 , _g_radius (radius) 76 , _g_table (NULL) 77 { 78 set_gaussian(radius, sigma); 79 } 80 81 CLGaussImageKernel::~CLGaussImageKernel () 82 { 83 xcam_free (_g_table); 84 } 85 86 bool 87 CLGaussImageKernel::set_gaussian (uint32_t radius, float sigma) 88 { 89 uint32_t i, j; 90 uint32_t scale = XCAM_GAUSS_SCALE (radius); 91 float dis = 0.0f, sum = 0.0f; 92 uint32_t scale_size = scale * scale * sizeof (_g_table[0]); 93 94 xcam_free (_g_table); 95 _g_table_buffer.release (); 96 _g_radius = radius; 97 _g_table = (float*) xcam_malloc0 (scale_size); 98 XCAM_ASSERT (_g_table); 99 100 for(i = 0; i < scale; i++) { 101 for(j = 0; j < scale; j++) { 102 dis = ((float)i - radius) * ((float)i - radius) + ((float)j - radius) * ((float)j - radius); 103 _g_table[i * scale + j] = exp(-dis / (2.0f * sigma * sigma)); 104 sum += _g_table[i * scale + j]; 105 } 106 } 107 108 for(i = 0; i < scale * scale; i++) { 109 _g_table[i] = _g_table[i] / sum; 110 } 111 112 _g_table_buffer = new CLBuffer( 113 get_context (), scale_size, 114 CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR , _g_table); 115 116 return true; 117 } 118 119 XCamReturn 120 CLGaussImageKernel::prepare_arguments (CLArgList &args, CLWorkSize &work_size) 121 { 122 SmartPtr<CLContext> context = get_context (); 123 SmartPtr<VideoBuffer> input = get_input_buf (); 124 SmartPtr<VideoBuffer> output = get_output_buf (); 125 126 XCAM_FAIL_RETURN ( 127 WARNING, 128 input.ptr () && output.ptr (), 129 XCAM_RETURN_ERROR_MEM, 130 "cl image kernel(%s) get input/output buffer failed", get_kernel_name ()); 131 132 const VideoBufferInfo & video_info_in = input->get_video_info (); 133 const VideoBufferInfo & video_info_out = output->get_video_info (); 134 CLImageDesc cl_desc_in, cl_desc_out; 135 136 cl_desc_in.format.image_channel_data_type = CL_UNORM_INT8; 137 cl_desc_in.format.image_channel_order = CL_R; 138 cl_desc_in.width = video_info_in.width; 139 cl_desc_in.height = video_info_in.height; 140 cl_desc_in.row_pitch = video_info_in.strides[0]; 141 SmartPtr<CLImage> image_in = convert_to_climage (context, input, cl_desc_in, video_info_in.offsets[0]); 142 143 cl_desc_out.format.image_channel_data_type = CL_UNORM_INT8; 144 cl_desc_out.format.image_channel_order = CL_RGBA; 145 cl_desc_out.width = video_info_out.width / 4; 146 cl_desc_out.height = video_info_out.height; 147 cl_desc_out.row_pitch = video_info_out.strides[0]; 148 SmartPtr<CLImage> image_out = convert_to_climage (context, output, cl_desc_out, video_info_out.offsets[0]); 149 150 XCAM_FAIL_RETURN ( 151 WARNING, 152 image_in->is_valid () && image_out->is_valid (), 153 XCAM_RETURN_ERROR_MEM, 154 "cl image kernel(%s) in/out memory not available", get_kernel_name ()); 155 156 //set args; 157 args.push_back (new CLMemArgument (image_in)); 158 args.push_back (new CLMemArgument (image_out)); 159 args.push_back (new CLMemArgument (_g_table_buffer)); 160 161 work_size.dim = XCAM_DEFAULT_IMAGE_DIM; 162 work_size.global[0] = XCAM_ALIGN_UP(cl_desc_out.width, 8); 163 work_size.global[1] = XCAM_ALIGN_UP (cl_desc_out.height / 2, 4); 164 work_size.local[0] = 8; 165 work_size.local[1] = 4; 166 167 return XCAM_RETURN_NO_ERROR; 168 } 169 170 CLGaussImageHandler::CLGaussImageHandler (const SmartPtr<CLContext> &context, const char *name) 171 : CLImageHandler (context, name) 172 { 173 } 174 175 bool 176 CLGaussImageHandler::set_gaussian_table (int size, float sigma) 177 { 178 _gauss_kernel->set_gaussian (size, sigma); 179 return true; 180 } 181 182 bool 183 CLGaussImageHandler::set_gauss_kernel(SmartPtr<CLGaussImageKernel> &kernel) 184 { 185 SmartPtr<CLImageKernel> image_kernel = kernel; 186 add_kernel (image_kernel); 187 _gauss_kernel = kernel; 188 return true; 189 } 190 191 SmartPtr<CLImageHandler> 192 create_cl_gauss_image_handler (const SmartPtr<CLContext> &context, uint32_t radius, float sigma) 193 { 194 SmartPtr<CLGaussImageHandler> gauss_handler; 195 SmartPtr<CLGaussImageKernel> gauss_kernel; 196 char build_options[1024]; 197 198 xcam_mem_clear (build_options); 199 snprintf (build_options, sizeof (build_options), " -DGAUSS_RADIUS=%d ", radius); 200 201 gauss_handler = new CLGaussImageHandler (context, "cl_handler_gauss"); 202 gauss_kernel = new CLGaussImageKernelImpl (gauss_handler, context, radius, sigma); 203 XCAM_ASSERT (gauss_kernel.ptr ()); 204 XCAM_FAIL_RETURN ( 205 ERROR, gauss_kernel->build_kernel (kernel_gauss_info, build_options) == XCAM_RETURN_NO_ERROR, NULL, 206 "build gaussian kernel(%s) failed", kernel_gauss_info.kernel_name); 207 208 XCAM_ASSERT (gauss_kernel->is_valid ()); 209 gauss_handler->set_gauss_kernel (gauss_kernel); 210 211 return gauss_handler; 212 } 213 214 } 215