| /* |
| * 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; |
| } |
| |
| } |
| |
| } |