#include "cl_viv_vx_ext.h"

_viv_uniform VXC_512Bits uniResize2xUp_4x8;
_viv_uniform VXC_512Bits uniResize2xUpRound_2x8;
_viv_uniform int out_height;

__kernel void resize_bilinear_U8toU8_UP_2X_half
    (
    __read_only  image2d_array_t   input,
    __write_only image2d_array_t   output,
                             int   align_corners,
                             int   half_pixel_centers
    )
{
    int4 coord_out  =  (int4)(get_global_id(0), 0, get_global_id(1), 0);
    int4 coord_in   = (int4)(get_global_id(0), -1, get_global_id(1), 0);
    coord_in.x = (coord_out.x * 2 - 1) >> 2;
    coord_in.x  = coord_out.x == 0 ? -1 : coord_in.x;

    vxc_uchar16 in0, in1, tmp, result;
    vxc_ushort8 result_s, round_s = 8;

    int8 input_desc;
    _viv_asm(COPY, input_desc, input, sizeof(input_desc));
    int baseAddr = (int)coord_in.z * input_desc.s4 + input_desc.s0;
    _viv_asm(MOV, coord_in.w, baseAddr);
    VXC_OP4(img_load_3d, in0, input, coord_in.xyww, VXC_5BITOFFSET_XY(0, 0),
            VXC_MODIFIER(0, 15, 0, VXC_RM_TowardZero, 0));
    VXC_OP4(img_load_3d, in1, input, coord_in.xyww, VXC_5BITOFFSET_XY(0, 1),
            VXC_MODIFIER(0, 15, 0, VXC_RM_TowardZero, 0));

    int8 output_desc;
    _viv_asm(COPY, output_desc, output, sizeof(output_desc));
    baseAddr = (int)coord_out.z * output_desc.s4 + output_desc.s0;
    _viv_asm(MOV, coord_out.w, baseAddr);

    while (coord_out.y < out_height)
    {
        VXC_DP4x8(result_s, in0, in1, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0), uniResize2xUp_4x8);
        VXC_DP2x8(result, result_s, round_s, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0), uniResize2xUpRound_2x8);
        VXC_OP4_NoDest(img_store_3d, output, coord_out.xyww, result,
            VXC_MODIFIER(0, 7, 0,VXC_RM_TowardZero, 0));
        coord_out.y++;
        VXC_OP4(img_load_3d, in0, input, coord_in.xyww, VXC_5BITOFFSET_XY(0, 2),
            VXC_MODIFIER(0, 15, 0, VXC_RM_TowardZero, 0));
        VXC_DP4x8(result_s, in0, in1, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0), uniResize2xUp_4x8);
        VXC_DP2x8(result, result_s, round_s, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0), uniResize2xUpRound_2x8);
        VXC_OP4_NoDest(img_store_3d, output, coord_out.xyww, result,
            VXC_MODIFIER(0, 7, 0,VXC_RM_TowardZero, 0));
        coord_out.y++;
        VXC_DP4x8(result_s, in1, in0, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0), uniResize2xUp_4x8);
        VXC_DP2x8(result, result_s, round_s, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0), uniResize2xUpRound_2x8);
        VXC_OP4_NoDest(img_store_3d, output, coord_out.xyww, result,
            VXC_MODIFIER(0, 7, 0,VXC_RM_TowardZero, 0));
        VXC_OP4(img_load_3d, in1, input, coord_in.xyww, VXC_5BITOFFSET_XY(0, 3),
            VXC_MODIFIER(0, 15, 0, VXC_RM_TowardZero, 0));
        coord_out.y++;
        VXC_DP4x8(result_s, in1, in0, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0), uniResize2xUp_4x8);
        VXC_DP2x8(result, result_s, round_s, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0), uniResize2xUpRound_2x8);
        VXC_OP4_NoDest(img_store_3d, output, coord_out.xyww, result,
            VXC_MODIFIER(0, 7, 0,VXC_RM_TowardZero, 0));
        coord_in.y += 2;
        coord_out.y++;
    }
}
