// Copyright 2019 Tencent
// SPDX-License-Identifier: BSD-3-Clause

#version 450

layout (constant_id = 0) const int w = 0;
layout (constant_id = 1) const int h = 0;
layout (constant_id = 2) const int outw = 0;
layout (constant_id = 3) const int outh = 0;
layout (constant_id = 4) const int type_to = 0;
layout (constant_id = 5) const int rotate_from = 0;
layout (constant_id = 6) const int need_resize = 0;

layout (binding = 0) uniform sampler2D android_hardware_buffer_image;
layout (binding = 1) writeonly buffer vkmat_blob { sfp vkmat_blob_data[]; };
layout (binding = 2) writeonly buffer vkmat_pack4_blob { sfpvec4 vkmat_pack4_blob_data[]; };

void main()
{
    int gx = int(gl_GlobalInvocationID.x);
    int gy = int(gl_GlobalInvocationID.y);
    int gz = int(gl_GlobalInvocationID.z);

    if (gx >= outw || gy >= outh || gz >= 1)
        return;

    vec2 pos;

    if (rotate_from == 1)
    {
        pos = vec2(gx, gy);
    }

    if (rotate_from == 2)
    {
        pos = vec2(outw - 1 - gx, gy);
    }

    if (rotate_from == 3)
    {
        pos = vec2(outw - 1 - gx, outh - 1 - gy);
    }

    if (rotate_from == 4)
    {
        pos = vec2(gx, outh - 1 - gy);
    }

    if (rotate_from == 5)
    {
        pos = vec2(gy, gx);
    }

    if (rotate_from == 6)
    {
        pos = vec2(gy, outw - 1 - gx);
    }

    if (rotate_from == 7)
    {
        pos = vec2(outh - 1 - gy, outw - 1 - gx);
    }

    if (rotate_from == 8)
    {
        pos = vec2(outh - 1 - gy, gx);
    }

    if (need_resize == 1)
    {
        if (rotate_from < 5) // 1 2 3 4
        {
            pos.x = pos.x * (float(w) / outw);
            pos.y = pos.y * (float(h) / outh);
        }
        else // 5 6 7 8
        {
            pos.x = pos.x * (float(w) / outh);
            pos.y = pos.y * (float(h) / outw);
        }
    }

    vec3 rgb = texture(android_hardware_buffer_image, pos).rgb * 255.f;

    const int outcstep = outw * outh / 4 * 4;

    if (type_to == 1) // PIXEL_RGB
    {
        ivec3 v_offset = (gy * outw + gx) + ivec3(0, 1, 2) * outcstep;

        buffer_st1(vkmat_blob_data, v_offset.r, afp(rgb.r));
        buffer_st1(vkmat_blob_data, v_offset.g, afp(rgb.g));
        buffer_st1(vkmat_blob_data, v_offset.b, afp(rgb.b));
    }

    if (type_to == 2) // PIXEL_BGR
    {
        ivec3 v_offset = (gy * outw + gx) + ivec3(0, 1, 2) * outcstep;

        buffer_st1(vkmat_blob_data, v_offset.r, afp(rgb.b));
        buffer_st1(vkmat_blob_data, v_offset.g, afp(rgb.g));
        buffer_st1(vkmat_blob_data, v_offset.b, afp(rgb.r));
    }

    if (type_to == 3) // PIXEL_GRAY
    {
        // coeffs for r g b = 0.299f, 0.587f, 0.114f
        float v = clamp(rgb.r * 0.299f + rgb.g * 0.587f + rgb.b * 0.114f, 0.f, 255.f);

        int v_offset = gy * outw + gx;

        buffer_st1(vkmat_blob_data, v_offset, afp(v));
    }

    if (type_to == 4) // PIXEL_RGBA
    {
        vec4 rgba;
        rgba.rgb = rgb;
        rgba.a = 255.f;

        int v_offset = gy * outw + gx;

        buffer_st4(vkmat_pack4_blob_data, v_offset, afpvec4(rgba));
    }

    if (type_to == 5) // PIXEL_BGRA
    {
        vec4 rgba;
        rgba.bgr = rgb;
        rgba.a = 255.f;

        int v_offset = gy * outw + gx;

        buffer_st4(vkmat_pack4_blob_data, v_offset, afpvec4(rgba));
    }
}
