Home | History | Annotate | Download | only in ocl
      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