#define texture texture2D

varying vec2 vTexCoord;
uniform vec3 uVideoAdj;
uniform vec2 uTextureSize;
uniform sampler2D uRGB;
uniform int uTrc;
uniform mat3 uColorPrimariesMatrix;
uniform float uMaxLuminance;
uniform int uNegative;
uniform float uGamma;

#ifdef GL3
vec4 getRGBAtOffset(float x, float y)
{
    return texture(uRGB, vTexCoord + vec2(x, y));
}
#endif

void main()
{
    float brightness = uVideoAdj[0];
    float contrast = uVideoAdj[1];
    vec4 RGB = texture(uRGB, vTexCoord);
#ifdef GL3
    float sharpness = uVideoAdj[2];
    if (sharpness != 0.0)
    {
        // Kernel 3x3
        // 1 2 1
        // 2 4 2
        // 1 2 1
        vec2 single = 1.0 / uTextureSize;
        vec4 blur = (
            getRGBAtOffset(-single.x, -single.y) / 16.0 + getRGBAtOffset(0.0, -single.y) / 8.0 + getRGBAtOffset(single.x, -single.y) / 16.0 +
            getRGBAtOffset(-single.x,  0.0     ) /  8.0 + RGB                            / 4.0 + getRGBAtOffset(single.x,  0.0     ) /  8.0 +
            getRGBAtOffset(-single.x,  single.y) / 16.0 + getRGBAtOffset(0.0,  single.y) / 8.0 + getRGBAtOffset(single.x,  single.y) / 16.0
        );
        // Subtract blur from original image, multiply and then add it to the original image
        RGB = clamp(RGB + (RGB - blur) * sharpness, 0.0, 1.0);
    }
    if (uTrc == AVCOL_TRC_BT709 || uTrc == AVCOL_TRC_BT2020_10 || uTrc == AVCOL_TRC_BT2020_12)
    {
        colorspace_trc_gamma24(RGB.rgb, uColorPrimariesMatrix);
    }
    else if (uTrc == AVCOL_TRC_SMPTE2084)
    {
        colorspace_trc_smpte2084(RGB.rgb, uColorPrimariesMatrix, uMaxLuminance);
    }
    else if (uTrc == AVCOL_TRC_ARIB_STD_B67)
    {
        colorspace_trc_hlg(RGB.rgb, uColorPrimariesMatrix);
    }
    if (uNegative != 0)
    {
        RGB = 1.0 - RGB;
    }
#endif
    RGB = clamp((RGB - 0.5) * contrast + 0.5, 0.0, 1.0) + brightness;

#ifdef GL3
    if (uGamma != 1.0)
    {
        RGB = pow(clamp(RGB, 0.0, 1.0), vec4(vec3(1.0 / uGamma), 1.0));
    }
#endif

    gl_FragColor = RGB;
}
