186 lines
5.8 KiB
C++
186 lines
5.8 KiB
C++
/*
|
|
* cl_blender.cpp - CL blender
|
|
*
|
|
* 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: Wind Yuan <feng.yuan@intel.com>
|
|
*/
|
|
|
|
#include "cl_blender.h"
|
|
#include "cl_device.h"
|
|
|
|
namespace XCam {
|
|
|
|
CLBlenderScaleKernel::CLBlenderScaleKernel (const SmartPtr<CLContext> &context, bool is_uv)
|
|
: CLImageKernel (context)
|
|
, _is_uv (is_uv)
|
|
{
|
|
}
|
|
|
|
XCamReturn
|
|
CLBlenderScaleKernel::prepare_arguments (CLArgList &args, CLWorkSize &work_size)
|
|
{
|
|
SmartPtr<CLContext> context = get_context ();
|
|
|
|
SmartPtr<CLImage> image_in = get_input_image ();
|
|
SmartPtr<CLImage> image_out = get_output_image ();
|
|
XCAM_ASSERT (image_in.ptr () && image_out.ptr ());
|
|
int output_offset_x;
|
|
uint32_t output_width, output_height;
|
|
get_output_info (output_width, output_height, output_offset_x);
|
|
|
|
args.push_back (new CLMemArgument (image_in));
|
|
args.push_back (new CLMemArgument (image_out));
|
|
args.push_back (new CLArgumentT<int> (output_offset_x));
|
|
args.push_back (new CLArgumentT<uint32_t> (output_width));
|
|
args.push_back (new CLArgumentT<uint32_t> (output_height));
|
|
|
|
work_size.dim = XCAM_DEFAULT_IMAGE_DIM;
|
|
work_size.local[0] = 8;
|
|
work_size.local[1] = 4;
|
|
work_size.global[0] = XCAM_ALIGN_UP (output_width, work_size.local[0]);
|
|
work_size.global[1] = XCAM_ALIGN_UP (output_height, work_size.local[1]);
|
|
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
|
|
CLBlender::CLBlender (
|
|
const SmartPtr<CLContext> &context, const char *name,
|
|
bool need_uv, CLBlenderScaleMode scale_mode)
|
|
: CLImageHandler (context, name)
|
|
, Blender (XCAM_CL_BLENDER_ALIGNMENT_X, XCAM_CL_BLENDER_ALIGNMENT_Y)
|
|
, _need_uv (need_uv)
|
|
, _swap_input_index (false)
|
|
, _scale_mode (scale_mode)
|
|
{
|
|
XCAM_ASSERT (get_alignment_x () == XCAM_CL_BLENDER_ALIGNMENT_X);
|
|
XCAM_ASSERT (get_alignment_y () == XCAM_CL_BLENDER_ALIGNMENT_Y);
|
|
}
|
|
|
|
bool
|
|
CLBlender::set_input_merge_area (const Rect &area, uint32_t index)
|
|
{
|
|
Rect tmp_area = area;
|
|
if (_scale_mode == CLBlenderScaleGlobal)
|
|
tmp_area.width = get_merge_window ().width;
|
|
|
|
bool ret = Blender::set_input_merge_area (tmp_area, index);
|
|
|
|
if (ret && _scale_mode == CLBlenderScaleGlobal) {
|
|
XCAM_ASSERT (fabs((int32_t)(area.width - get_merge_window ().width)) < XCAM_CL_BLENDER_ALIGNMENT_X);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
XCamReturn
|
|
CLBlender::prepare_buffer_pool_video_info (
|
|
const VideoBufferInfo &input,
|
|
VideoBufferInfo &output)
|
|
{
|
|
uint32_t output_width, output_height;
|
|
get_output_size (output_width, output_height);
|
|
XCAM_ASSERT (output_height == input.height);
|
|
|
|
// aligned at least XCAM_BLENDER_ALIGNED_WIDTH
|
|
uint32_t aligned_width = XCAM_MAX (16, XCAM_CL_BLENDER_ALIGNMENT_X);
|
|
output.init (
|
|
input.format, output_width, output_height,
|
|
XCAM_ALIGN_UP(output_width, aligned_width), XCAM_ALIGN_UP(output_height, 16));
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
|
|
XCamReturn
|
|
CLBlender::prepare_parameters (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
|
|
{
|
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
|
XCAM_ASSERT (input.ptr () && output.ptr ());
|
|
SmartPtr<VideoBuffer> input0, input1;
|
|
|
|
SmartPtr<VideoBuffer> next = input->find_typed_attach<VideoBuffer> ();
|
|
XCAM_FAIL_RETURN(
|
|
WARNING,
|
|
next.ptr (),
|
|
XCAM_RETURN_ERROR_PARAM,
|
|
"CLBlender(%s) does NOT find second buffer in attachment", get_name());
|
|
|
|
if (_swap_input_index) {
|
|
input0 = next;
|
|
input1 = input;
|
|
} else {
|
|
input0 = input;
|
|
input1 = next;
|
|
}
|
|
|
|
SmartPtr<CLContext> context = get_context ();
|
|
const VideoBufferInfo &in0_info = input0->get_video_info ();
|
|
const VideoBufferInfo &in1_info = input1->get_video_info ();
|
|
const VideoBufferInfo &out_info = output->get_video_info ();
|
|
|
|
if (!get_input_valid_area (0).width) {
|
|
Rect area;
|
|
area.width = in0_info.width;
|
|
area.height = in0_info.height;
|
|
set_input_valid_area (area, 0);
|
|
}
|
|
if (!get_input_valid_area (1).width) {
|
|
Rect area;
|
|
area.width = in1_info.width;
|
|
area.height = in1_info.height;
|
|
set_input_valid_area (area, 1);
|
|
}
|
|
|
|
if (!is_merge_window_set ()) {
|
|
Rect merge_window;
|
|
XCAM_FAIL_RETURN (
|
|
WARNING,
|
|
auto_calc_merge_window (get_input_valid_area(0).width, get_input_valid_area(1).width, out_info.width, merge_window),
|
|
XCAM_RETURN_ERROR_PARAM,
|
|
"CLBlender(%s) auto calculate merge window failed", get_name ());
|
|
|
|
merge_window.pos_y = 0;
|
|
merge_window.height = out_info.height;
|
|
set_merge_window (merge_window);
|
|
|
|
Rect area;
|
|
area.width = merge_window.width;
|
|
area.height = merge_window.height;
|
|
area.pos_x = merge_window.pos_x;
|
|
set_input_merge_area (area, 0);
|
|
area.pos_x = 0;
|
|
set_input_merge_area (area, 1);
|
|
}
|
|
|
|
ret = allocate_cl_buffers (context, input0, input1, output);
|
|
return ret;
|
|
}
|
|
|
|
SmartPtr<Blender>
|
|
create_ocl_blender ()
|
|
{
|
|
SmartPtr<CLContext> context = CLDevice::instance ()->get_context ();
|
|
XCAM_FAIL_RETURN (
|
|
ERROR, context.ptr (), NULL,
|
|
"create ocl blender failed to get cl context");
|
|
SmartPtr<CLBlender> blender = create_pyramid_blender (context, 2, true, false).dynamic_cast_ptr<CLBlender> ();
|
|
XCAM_FAIL_RETURN (
|
|
ERROR, blender.ptr (), NULL,
|
|
"create ocl blender failed to get pyramid blender");
|
|
return blender;
|
|
}
|
|
|
|
};
|
|
|