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@intel.com>
19 * Wind Yuan <feng.yuan@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
CLGaussImageKernelImpl(SmartPtr<CLGaussImageHandler> & handler,const SmartPtr<CLContext> & context,uint32_t radius,float sigma)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>
get_input_buf()62 CLGaussImageKernelImpl::get_input_buf ()
63 {
64 return _handler->get_input_buf ();
65 }
66 SmartPtr<VideoBuffer>
get_output_buf()67 CLGaussImageKernelImpl::get_output_buf ()
68 {
69 return _handler->get_output_buf ();;
70 }
71
CLGaussImageKernel(const SmartPtr<CLContext> & context,uint32_t radius,float sigma)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
~CLGaussImageKernel()81 CLGaussImageKernel::~CLGaussImageKernel ()
82 {
83 xcam_free (_g_table);
84 }
85
86 bool
set_gaussian(uint32_t radius,float sigma)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
prepare_arguments(CLArgList & args,CLWorkSize & work_size)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
CLGaussImageHandler(const SmartPtr<CLContext> & context,const char * name)170 CLGaussImageHandler::CLGaussImageHandler (const SmartPtr<CLContext> &context, const char *name)
171 : CLImageHandler (context, name)
172 {
173 }
174
175 bool
set_gaussian_table(int size,float sigma)176 CLGaussImageHandler::set_gaussian_table (int size, float sigma)
177 {
178 _gauss_kernel->set_gaussian (size, sigma);
179 return true;
180 }
181
182 bool
set_gauss_kernel(SmartPtr<CLGaussImageKernel> & kernel)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>
create_cl_gauss_image_handler(const SmartPtr<CLContext> & context,uint32_t radius,float sigma)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