blob: db234163040e677f227f356a6d92b5d0d230efd5 [file] [log] [blame]
/*
* gl_blender_shaders_priv.cpp - gl blender shaders private class implementation
*
* Copyright (c) 2018 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: Yinhang Liu <[email protected]>
*/
#include "gl_blender_shaders_priv.h"
namespace XCam {
namespace XCamGLShaders {
enum {
ShaderGaussScalePyr = 0,
ShaderLapTransPyr,
ShaderBlendPyr,
ShaderReconstructPyr
};
static const GLShaderInfo shaders_info[] = {
{
GL_COMPUTE_SHADER,
"shader_gauss_scale_pyr",
#include "shader_gauss_scale_pyr.comp.slx"
, 0
},
{
GL_COMPUTE_SHADER,
"shader_lap_trans_pyr",
#include "shader_lap_trans_pyr.comp.slx"
, 0
},
{
GL_COMPUTE_SHADER,
"shader_blend_pyr",
#include "shader_blend_pyr.comp.slx"
, 0
},
{
GL_COMPUTE_SHADER,
"shader_reconstruct_pyr",
#include "shader_reconstruct_pyr.comp.slx"
, 0
}
};
bool
GLGaussScalePyrShader::check_desc (
const GLBufferDesc &in_desc, const GLBufferDesc &out_desc, const Rect &merge_area)
{
XCAM_FAIL_RETURN (
ERROR,
merge_area.pos_y == 0 && merge_area.height == (int32_t)in_desc.height &&
merge_area.pos_x + merge_area.width <= (int32_t)in_desc.width &&
merge_area.width == (int32_t)out_desc.width * 2 &&
merge_area.height == (int32_t)out_desc.height * 2,
false, "invalid buffer size: input:%dx%d, output:%dx%d, merge_area:%dx%d",
in_desc.width, in_desc.height, out_desc.width, out_desc.height, merge_area.width, merge_area.height);
return true;
}
XCamReturn
GLGaussScalePyrShader::prepare_arguments (const SmartPtr<Worker::Arguments> &base, GLCmdList &cmds)
{
SmartPtr<GLGaussScalePyrShader::Args> args = base.dynamic_cast_ptr<GLGaussScalePyrShader::Args> ();
XCAM_ASSERT (args.ptr () && args->in_glbuf.ptr () && args->out_glbuf.ptr ());
const GLBufferDesc &in_desc = args->in_glbuf->get_buffer_desc ();
const GLBufferDesc &out_desc = args->out_glbuf->get_buffer_desc ();
const Rect &merge_area = args->merge_area;
XCAM_FAIL_RETURN (
ERROR, check_desc (in_desc, out_desc, merge_area), XCAM_RETURN_ERROR_PARAM,
"GLGaussScalePyrShader(%s) check buffer description failed, level:%d idx:%d",
XCAM_STR (get_name ()), args->level, (int)args->idx);
cmds.push_back (new GLCmdBindBufRange (args->in_glbuf, 0, NV12PlaneYIdx));
cmds.push_back (new GLCmdBindBufRange (args->in_glbuf, 1, NV12PlaneUVIdx));
cmds.push_back (new GLCmdBindBufRange (args->out_glbuf, 2, NV12PlaneYIdx));
cmds.push_back (new GLCmdBindBufRange (args->out_glbuf, 3, NV12PlaneUVIdx));
size_t unit_bytes = sizeof (uint32_t);
uint32_t in_img_width = XCAM_ALIGN_UP (in_desc.width, unit_bytes) / unit_bytes;
uint32_t in_offset_x = XCAM_ALIGN_UP (merge_area.pos_x, unit_bytes) / unit_bytes;
uint32_t out_img_width = XCAM_ALIGN_UP (out_desc.width, unit_bytes) / unit_bytes;
uint32_t merge_width = XCAM_ALIGN_UP (merge_area.width, unit_bytes) / unit_bytes;
cmds.push_back (new GLCmdUniformT<uint32_t> ("in_img_width", in_img_width));
cmds.push_back (new GLCmdUniformT<uint32_t> ("in_img_height", in_desc.height));
cmds.push_back (new GLCmdUniformT<uint32_t> ("in_offset_x", in_offset_x));
cmds.push_back (new GLCmdUniformT<uint32_t> ("out_img_width", out_img_width));
cmds.push_back (new GLCmdUniformT<uint32_t> ("merge_width", merge_width));
GLGroupsSize groups_size;
groups_size.x = XCAM_ALIGN_UP (out_img_width, 8) / 8;
groups_size.y = XCAM_ALIGN_UP (out_desc.height, 16) / 16;
groups_size.z = 1;
SmartPtr<GLComputeProgram> prog;
XCAM_FAIL_RETURN (
ERROR, get_compute_program (prog), XCAM_RETURN_ERROR_PARAM,
"GLGaussScalePyrShader(%s) get compute program failed", XCAM_STR (get_name ()));
prog->set_groups_size (groups_size);
return XCAM_RETURN_NO_ERROR;
}
bool
GLLapTransPyrShader::check_desc (
const GLBufferDesc &in_desc, const GLBufferDesc &out_desc,
const GLBufferDesc &gs_desc, const Rect &merge_area)
{
XCAM_FAIL_RETURN (
ERROR,
merge_area.pos_y == 0 && merge_area.height == (int32_t)in_desc.height &&
merge_area.pos_x + merge_area.width <= (int32_t)in_desc.width &&
merge_area.width == (int32_t)out_desc.width && merge_area.height == (int32_t)out_desc.height &&
merge_area.width == (int32_t)gs_desc.width * 2 && merge_area.height == (int32_t)gs_desc.height * 2,
false,
"invalid buffer size: intput:%dx%d, output:%dx%d, gaussscale:%dx%d, in_area:%dx%d",
in_desc.width, in_desc.height, out_desc.width, out_desc.height,
gs_desc.width, gs_desc.height, merge_area.width, merge_area.height);
return true;
}
XCamReturn
GLLapTransPyrShader::prepare_arguments (const SmartPtr<Worker::Arguments> &base, GLCmdList &cmds)
{
SmartPtr<GLLapTransPyrShader::Args> args = base.dynamic_cast_ptr<GLLapTransPyrShader::Args> ();
XCAM_ASSERT (args.ptr () && args->in_glbuf.ptr () && args->gaussscale_glbuf.ptr () && args->out_glbuf.ptr ());
const GLBufferDesc &in_desc = args->in_glbuf->get_buffer_desc ();
const GLBufferDesc &gs_desc = args->gaussscale_glbuf->get_buffer_desc ();
const GLBufferDesc &out_desc = args->out_glbuf->get_buffer_desc ();
const Rect &merge_area = args->merge_area;
XCAM_FAIL_RETURN (
ERROR, check_desc (in_desc, out_desc, gs_desc, merge_area), XCAM_RETURN_ERROR_PARAM,
"GLLapTransPyrShader(%s) check buffer description failed, level:%d idx:%d",
XCAM_STR (get_name ()), args->level, (int)args->idx);
cmds.push_back (new GLCmdBindBufRange (args->in_glbuf, 0, NV12PlaneYIdx));
cmds.push_back (new GLCmdBindBufRange (args->in_glbuf, 1, NV12PlaneUVIdx));
cmds.push_back (new GLCmdBindBufRange (args->gaussscale_glbuf, 2, NV12PlaneYIdx));
cmds.push_back (new GLCmdBindBufRange (args->gaussscale_glbuf, 3, NV12PlaneUVIdx));
cmds.push_back (new GLCmdBindBufRange (args->out_glbuf, 4, NV12PlaneYIdx));
cmds.push_back (new GLCmdBindBufRange (args->out_glbuf, 5, NV12PlaneUVIdx));
size_t unit_bytes = sizeof (uint32_t) * 2;
uint32_t in_img_width = XCAM_ALIGN_UP (in_desc.width, unit_bytes) / unit_bytes;
uint32_t in_offset_x = XCAM_ALIGN_UP (merge_area.pos_x, unit_bytes) / unit_bytes;
uint32_t gaussscale_img_width = XCAM_ALIGN_UP (gs_desc.width, sizeof (uint32_t)) / sizeof (uint32_t);
uint32_t merge_width = XCAM_ALIGN_UP (merge_area.width, unit_bytes) / unit_bytes;
cmds.push_back (new GLCmdUniformT<uint32_t> ("in_img_width", in_img_width));
cmds.push_back (new GLCmdUniformT<uint32_t> ("in_img_height", in_desc.height));
cmds.push_back (new GLCmdUniformT<uint32_t> ("in_offset_x", in_offset_x));
cmds.push_back (new GLCmdUniformT<uint32_t> ("gaussscale_img_width", gaussscale_img_width));
cmds.push_back (new GLCmdUniformT<uint32_t> ("gaussscale_img_height", gs_desc.height));
cmds.push_back (new GLCmdUniformT<uint32_t> ("merge_width", merge_width));
GLGroupsSize groups_size;
groups_size.x = XCAM_ALIGN_UP (merge_width, 8) / 8;
groups_size.y = XCAM_ALIGN_UP (merge_area.height, 32) / 32;
groups_size.z = 1;
SmartPtr<GLComputeProgram> prog;
XCAM_FAIL_RETURN (
ERROR, get_compute_program (prog), XCAM_RETURN_ERROR_PARAM,
"GLLapTransPyrShader(%s) get compute program failed", XCAM_STR (get_name ()));
prog->set_groups_size (groups_size);
return XCAM_RETURN_NO_ERROR;
}
bool
GLBlendPyrShader::check_desc (
const GLBufferDesc &in0_desc, const GLBufferDesc &in1_desc,
const GLBufferDesc &out_desc, const GLBufferDesc &mask_desc)
{
XCAM_FAIL_RETURN (
ERROR,
in0_desc.width == in1_desc.width && in0_desc.height == in1_desc.height &&
in0_desc.width == out_desc.width && in0_desc.height == out_desc.height &&
in0_desc.width == mask_desc.width,
false,
"invalid buffer size: intput0:%dx%d, intput1:%dx%d, output:%dx%d, mask:%dx%d",
in0_desc.width, in0_desc.height, in1_desc.width, in1_desc.height,
out_desc.width, out_desc.height, mask_desc.width, mask_desc.height);
XCAM_FAIL_RETURN (
ERROR, mask_desc.height == 1, false,
"mask buffer only supports one-dimensional array");
return true;
}
XCamReturn
GLBlendPyrShader::prepare_arguments (const SmartPtr<Worker::Arguments> &base, GLCmdList &cmds)
{
SmartPtr<GLBlendPyrShader::Args> args = base.dynamic_cast_ptr<GLBlendPyrShader::Args> ();
XCAM_ASSERT (args.ptr () && args->in0_glbuf.ptr () && args->in1_glbuf.ptr () && args->out_glbuf.ptr ());
XCAM_ASSERT (args->mask_glbuf.ptr ());
const GLBufferDesc &in0_desc = args->in0_glbuf->get_buffer_desc ();
const GLBufferDesc &in1_desc = args->in1_glbuf->get_buffer_desc ();
const GLBufferDesc &out_desc = args->out_glbuf->get_buffer_desc ();
const GLBufferDesc &mask_desc = args->mask_glbuf->get_buffer_desc ();
XCAM_FAIL_RETURN (
ERROR, check_desc (in0_desc, in1_desc, out_desc, mask_desc), XCAM_RETURN_ERROR_PARAM,
"GLBlendPyrShader(%s) check buffer description failed", XCAM_STR (get_name ()));
cmds.push_back (new GLCmdBindBufRange (args->in0_glbuf, 0, NV12PlaneYIdx));
cmds.push_back (new GLCmdBindBufRange (args->in0_glbuf, 1, NV12PlaneUVIdx));
cmds.push_back (new GLCmdBindBufRange (args->in1_glbuf, 2, NV12PlaneYIdx));
cmds.push_back (new GLCmdBindBufRange (args->in1_glbuf, 3, NV12PlaneUVIdx));
cmds.push_back (new GLCmdBindBufRange (args->out_glbuf, 4, NV12PlaneYIdx));
cmds.push_back (new GLCmdBindBufRange (args->out_glbuf, 5, NV12PlaneUVIdx));
cmds.push_back (new GLCmdBindBufBase (args->mask_glbuf, 6));
size_t unit_bytes = sizeof (uint32_t) * 2;
uint32_t in_img_width = XCAM_ALIGN_UP (in0_desc.width, unit_bytes) / unit_bytes;
cmds.push_back (new GLCmdUniformT<uint32_t> ("in_img_width", in_img_width));
GLGroupsSize groups_size;
groups_size.x = XCAM_ALIGN_UP (in_img_width, 8) / 8;
groups_size.y = XCAM_ALIGN_UP (in0_desc.height, 16) / 16;
groups_size.z = 1;
SmartPtr<GLComputeProgram> prog;
XCAM_FAIL_RETURN (
ERROR, get_compute_program (prog), XCAM_RETURN_ERROR_PARAM,
"GLBlendPyrShader(%s) get compute program failed", XCAM_STR (get_name ()));
prog->set_groups_size (groups_size);
return XCAM_RETURN_NO_ERROR;
}
bool
GLReconstructPyrShader::check_desc (
const GLBufferDesc &lap0_desc, const GLBufferDesc &lap1_desc, const GLBufferDesc &out_desc,
const GLBufferDesc &prev_blend_desc, const GLBufferDesc &mask_desc, const Rect &merge_area)
{
XCAM_FAIL_RETURN (
ERROR,
merge_area.pos_y == 0 && merge_area.height == (int32_t)out_desc.height &&
merge_area.pos_x + merge_area.width <= (int32_t)out_desc.width &&
merge_area.width == (int32_t)lap0_desc.width && merge_area.height == (int32_t)lap0_desc.height &&
lap0_desc.width == lap1_desc.width && lap0_desc.height == lap1_desc.height &&
lap0_desc.width == prev_blend_desc.width * 2 && lap0_desc.height == prev_blend_desc.height * 2 &&
lap0_desc.width == mask_desc.width,
false,
"invalid buffer size: lap0:%dx%d, lap1:%dx%d, output:%dx%d, prev_blend:%dx%d, mask:%dx%d, merge_area:%dx%d",
lap0_desc.width, lap0_desc.height, lap1_desc.width, lap1_desc.height,
out_desc.width, out_desc.height, prev_blend_desc.width, prev_blend_desc.height,
mask_desc.width, mask_desc.height, merge_area.width, merge_area.height);
XCAM_FAIL_RETURN (
ERROR, mask_desc.height == 1, false,
"mask buffer only supports one-dimensional array");
return true;
}
XCamReturn
GLReconstructPyrShader::prepare_arguments (const SmartPtr<Worker::Arguments> &base, GLCmdList &cmds)
{
SmartPtr<GLReconstructPyrShader::Args> args = base.dynamic_cast_ptr<GLReconstructPyrShader::Args> ();
XCAM_ASSERT (args.ptr () && args->lap0_glbuf.ptr () && args->lap1_glbuf.ptr () && args->out_glbuf.ptr ());
XCAM_ASSERT (args->mask_glbuf.ptr ());
const GLBufferDesc &lap0_desc = args->lap0_glbuf->get_buffer_desc ();
const GLBufferDesc &lap1_desc = args->lap1_glbuf->get_buffer_desc ();
const GLBufferDesc &out_desc = args->out_glbuf->get_buffer_desc ();
const GLBufferDesc &prev_blend_desc = args->prev_blend_glbuf->get_buffer_desc ();
const GLBufferDesc &mask_desc = args->mask_glbuf->get_buffer_desc ();
const Rect &merge_area = args->merge_area;
XCAM_FAIL_RETURN (
ERROR, check_desc (lap0_desc, lap1_desc, out_desc, prev_blend_desc, mask_desc, merge_area),
XCAM_RETURN_ERROR_PARAM,
"GLReconstructPyrShader(%s) check buffer description failed, level:%d",
XCAM_STR (get_name ()), args->level);
cmds.push_back (new GLCmdBindBufRange (args->lap0_glbuf, 0, NV12PlaneYIdx));
cmds.push_back (new GLCmdBindBufRange (args->lap0_glbuf, 1, NV12PlaneUVIdx));
cmds.push_back (new GLCmdBindBufRange (args->lap1_glbuf, 2, NV12PlaneYIdx));
cmds.push_back (new GLCmdBindBufRange (args->lap1_glbuf, 3, NV12PlaneUVIdx));
cmds.push_back (new GLCmdBindBufRange (args->out_glbuf, 4, NV12PlaneYIdx));
cmds.push_back (new GLCmdBindBufRange (args->out_glbuf, 5, NV12PlaneUVIdx));
cmds.push_back (new GLCmdBindBufRange (args->prev_blend_glbuf, 6, NV12PlaneYIdx));
cmds.push_back (new GLCmdBindBufRange (args->prev_blend_glbuf, 7, NV12PlaneUVIdx));
cmds.push_back (new GLCmdBindBufBase (args->mask_glbuf, 8));
size_t unit_bytes = sizeof (uint32_t) * 2;
uint32_t lap_img_width = XCAM_ALIGN_UP (lap0_desc.width, unit_bytes) / unit_bytes;
uint32_t out_img_width = XCAM_ALIGN_UP (out_desc.width, unit_bytes) / unit_bytes;
uint32_t out_offset_x = XCAM_ALIGN_UP (merge_area.pos_x, unit_bytes) / unit_bytes;
uint32_t prev_blend_img_width = XCAM_ALIGN_UP (prev_blend_desc.width, sizeof (uint32_t)) / sizeof (uint32_t);
cmds.push_back (new GLCmdUniformT<uint32_t> ("lap_img_width", lap_img_width));
cmds.push_back (new GLCmdUniformT<uint32_t> ("lap_img_height", lap0_desc.height));
cmds.push_back (new GLCmdUniformT<uint32_t> ("out_img_width", out_img_width));
cmds.push_back (new GLCmdUniformT<uint32_t> ("out_offset_x", out_offset_x));
cmds.push_back (new GLCmdUniformT<uint32_t> ("prev_blend_img_width", prev_blend_img_width));
cmds.push_back (new GLCmdUniformT<uint32_t> ("prev_blend_img_height", prev_blend_desc.height));
GLGroupsSize groups_size;
groups_size.x = XCAM_ALIGN_UP (lap_img_width, 8) / 8;
groups_size.y = XCAM_ALIGN_UP (lap0_desc.height, 32) / 32;
groups_size.z = 1;
SmartPtr<GLComputeProgram> prog;
XCAM_FAIL_RETURN (
ERROR, get_compute_program (prog), XCAM_RETURN_ERROR_PARAM,
"GLReconstructPyrShader(%s) get compute program failed", XCAM_STR (get_name ()));
prog->set_groups_size (groups_size);
return XCAM_RETURN_NO_ERROR;
}
SmartPtr<GLGaussScalePyrShader>
create_gauss_scale_pyr_shader (SmartPtr<Worker::Callback> &cb)
{
XCAM_ASSERT (cb.ptr ());
SmartPtr<GLGaussScalePyrShader> shader = new GLGaussScalePyrShader (cb);
XCAM_ASSERT (shader.ptr ());
XCamReturn ret = shader->create_compute_program (shaders_info[ShaderGaussScalePyr], "gauss_scale_pyr_program");
XCAM_FAIL_RETURN (
ERROR, ret == XCAM_RETURN_NO_ERROR, NULL,
"create gauss scale pyramid program failed");
return shader;
}
SmartPtr<GLLapTransPyrShader>
create_lap_trans_pyr_shader (SmartPtr<Worker::Callback> &cb)
{
XCAM_ASSERT (cb.ptr ());
SmartPtr<GLLapTransPyrShader> shader = new GLLapTransPyrShader (cb);
XCAM_ASSERT (shader.ptr ());
XCamReturn ret = shader->create_compute_program (shaders_info[ShaderLapTransPyr], "lap_trans_pyr_program");
XCAM_FAIL_RETURN (
ERROR, ret == XCAM_RETURN_NO_ERROR, NULL,
"create laplace transformation pyramid program failed");
return shader;
}
SmartPtr<GLBlendPyrShader>
create_blend_pyr_shader (SmartPtr<Worker::Callback> &cb)
{
XCAM_ASSERT (cb.ptr ());
SmartPtr<GLBlendPyrShader> shader = new GLBlendPyrShader (cb);
XCAM_ASSERT (shader.ptr ());
XCamReturn ret = shader->create_compute_program (shaders_info[ShaderBlendPyr], "blend_pyr_program");
XCAM_FAIL_RETURN (
ERROR, ret == XCAM_RETURN_NO_ERROR, NULL,
"create blend pyramid program failed");
return shader;
}
SmartPtr<GLReconstructPyrShader>
create_reconstruct_pyr_shader (SmartPtr<Worker::Callback> &cb)
{
XCAM_ASSERT (cb.ptr ());
SmartPtr<GLReconstructPyrShader> shader = new GLReconstructPyrShader (cb);
XCAM_ASSERT (shader.ptr ());
XCamReturn ret = shader->create_compute_program (shaders_info[ShaderReconstructPyr], "reconstruct_pyr_program");
XCAM_FAIL_RETURN (
ERROR, ret == XCAM_RETURN_NO_ERROR, NULL,
"create reconstruct pyramid program failed");
return shader;
}
}
}