1 /* 2 * cl_blender.cpp - CL blender 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: Wind Yuan <feng.yuan (at) intel.com> 19 */ 20 21 #include "cl_blender.h" 22 #include "cl_device.h" 23 24 namespace XCam { 25 26 CLBlenderScaleKernel::CLBlenderScaleKernel (const SmartPtr<CLContext> &context, bool is_uv) 27 : CLImageKernel (context) 28 , _is_uv (is_uv) 29 { 30 } 31 32 XCamReturn 33 CLBlenderScaleKernel::prepare_arguments (CLArgList &args, CLWorkSize &work_size) 34 { 35 SmartPtr<CLContext> context = get_context (); 36 37 SmartPtr<CLImage> image_in = get_input_image (); 38 SmartPtr<CLImage> image_out = get_output_image (); 39 XCAM_ASSERT (image_in.ptr () && image_out.ptr ()); 40 int output_offset_x; 41 uint32_t output_width, output_height; 42 get_output_info (output_width, output_height, output_offset_x); 43 44 args.push_back (new CLMemArgument (image_in)); 45 args.push_back (new CLMemArgument (image_out)); 46 args.push_back (new CLArgumentT<int> (output_offset_x)); 47 args.push_back (new CLArgumentT<uint32_t> (output_width)); 48 args.push_back (new CLArgumentT<uint32_t> (output_height)); 49 50 work_size.dim = XCAM_DEFAULT_IMAGE_DIM; 51 work_size.local[0] = 8; 52 work_size.local[1] = 4; 53 work_size.global[0] = XCAM_ALIGN_UP (output_width, work_size.local[0]); 54 work_size.global[1] = XCAM_ALIGN_UP (output_height, work_size.local[1]); 55 56 return XCAM_RETURN_NO_ERROR; 57 } 58 59 CLBlender::CLBlender ( 60 const SmartPtr<CLContext> &context, const char *name, 61 bool need_uv, CLBlenderScaleMode scale_mode) 62 : CLImageHandler (context, name) 63 , Blender (XCAM_CL_BLENDER_ALIGNMENT_X, XCAM_CL_BLENDER_ALIGNMENT_Y) 64 , _need_uv (need_uv) 65 , _swap_input_index (false) 66 , _scale_mode (scale_mode) 67 { 68 XCAM_ASSERT (get_alignment_x () == XCAM_CL_BLENDER_ALIGNMENT_X); 69 XCAM_ASSERT (get_alignment_y () == XCAM_CL_BLENDER_ALIGNMENT_Y); 70 } 71 72 bool 73 CLBlender::set_input_merge_area (const Rect &area, uint32_t index) 74 { 75 Rect tmp_area = area; 76 if (_scale_mode == CLBlenderScaleGlobal) 77 tmp_area.width = get_merge_window ().width; 78 79 bool ret = Blender::set_input_merge_area (tmp_area, index); 80 81 if (ret && _scale_mode == CLBlenderScaleGlobal) { 82 XCAM_ASSERT (fabs((int32_t)(area.width - get_merge_window ().width)) < XCAM_CL_BLENDER_ALIGNMENT_X); 83 } 84 85 return ret; 86 } 87 88 XCamReturn 89 CLBlender::prepare_buffer_pool_video_info ( 90 const VideoBufferInfo &input, 91 VideoBufferInfo &output) 92 { 93 uint32_t output_width, output_height; 94 get_output_size (output_width, output_height); 95 XCAM_ASSERT (output_height == input.height); 96 97 // aligned at least XCAM_BLENDER_ALIGNED_WIDTH 98 uint32_t aligned_width = XCAM_MAX (16, XCAM_CL_BLENDER_ALIGNMENT_X); 99 output.init ( 100 input.format, output_width, output_height, 101 XCAM_ALIGN_UP(output_width, aligned_width), XCAM_ALIGN_UP(output_height, 16)); 102 return XCAM_RETURN_NO_ERROR; 103 } 104 105 XCamReturn 106 CLBlender::prepare_parameters (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output) 107 { 108 XCamReturn ret = XCAM_RETURN_NO_ERROR; 109 XCAM_ASSERT (input.ptr () && output.ptr ()); 110 SmartPtr<VideoBuffer> input0, input1; 111 112 SmartPtr<VideoBuffer> next = input->find_typed_attach<VideoBuffer> (); 113 XCAM_FAIL_RETURN( 114 WARNING, 115 next.ptr (), 116 XCAM_RETURN_ERROR_PARAM, 117 "CLBlender(%s) does NOT find second buffer in attachment", get_name()); 118 119 if (_swap_input_index) { 120 input0 = next; 121 input1 = input; 122 } else { 123 input0 = input; 124 input1 = next; 125 } 126 127 SmartPtr<CLContext> context = get_context (); 128 const VideoBufferInfo &in0_info = input0->get_video_info (); 129 const VideoBufferInfo &in1_info = input1->get_video_info (); 130 const VideoBufferInfo &out_info = output->get_video_info (); 131 132 if (!get_input_valid_area (0).width) { 133 Rect area; 134 area.width = in0_info.width; 135 area.height = in0_info.height; 136 set_input_valid_area (area, 0); 137 } 138 if (!get_input_valid_area (1).width) { 139 Rect area; 140 area.width = in1_info.width; 141 area.height = in1_info.height; 142 set_input_valid_area (area, 1); 143 } 144 145 if (!is_merge_window_set ()) { 146 Rect merge_window; 147 XCAM_FAIL_RETURN ( 148 WARNING, 149 auto_calc_merge_window (get_input_valid_area(0).width, get_input_valid_area(1).width, out_info.width, merge_window), 150 XCAM_RETURN_ERROR_PARAM, 151 "CLBlender(%s) auto calculate merge window failed", get_name ()); 152 153 merge_window.pos_y = 0; 154 merge_window.height = out_info.height; 155 set_merge_window (merge_window); 156 157 Rect area; 158 area.width = merge_window.width; 159 area.height = merge_window.height; 160 area.pos_x = merge_window.pos_x; 161 set_input_merge_area (area, 0); 162 area.pos_x = 0; 163 set_input_merge_area (area, 1); 164 } 165 166 ret = allocate_cl_buffers (context, input0, input1, output); 167 return ret; 168 } 169 170 SmartPtr<Blender> 171 create_ocl_blender () 172 { 173 SmartPtr<CLContext> context = CLDevice::instance ()->get_context (); 174 XCAM_FAIL_RETURN ( 175 ERROR, context.ptr (), NULL, 176 "create ocl blender failed to get cl context"); 177 SmartPtr<CLBlender> blender = create_pyramid_blender (context, 2, true, false).dynamic_cast_ptr<CLBlender> (); 178 XCAM_FAIL_RETURN ( 179 ERROR, blender.ptr (), NULL, 180 "create ocl blender failed to get pyramid blender"); 181 return blender; 182 } 183 184 }; 185 186