1// Texture IDs 2#if PIXFMT == V4L2_PIX_FMT_SBGGR8 || PIXFMT == V4L2_PIX_FMT_SGBRG8 || \ 3 PIXFMT == V4L2_PIX_FMT_SGRBG8 || PIXFMT == V4L2_PIX_FMT_SRGGB8 || \ 4 PIXFMT == V4L2_PIX_FMT_SBGGR10 || PIXFMT == V4L2_PIX_FMT_SGBRG10 || \ 5 PIXFMT == V4L2_PIX_FMT_SGRBG10 || PIXFMT == V4L2_PIX_FMT_SRGGB10 || \ 6 PIXFMT == V4L2_PIX_FMT_SBGGR12 || PIXFMT == V4L2_PIX_FMT_SGBRG12 || \ 7 PIXFMT == V4L2_PIX_FMT_SGRBG12 || PIXFMT == V4L2_PIX_FMT_SRGGB12 || \ 8 PIXFMT == V4L2_PIX_FMT_SBGGR16 || PIXFMT == V4L2_PIX_FMT_SGBRG16 || \ 9 PIXFMT == V4L2_PIX_FMT_SGRBG16 || PIXFMT == V4L2_PIX_FMT_SRGGB16 || \ 10 PIXFMT == V4L2_PIX_FMT_GREY || PIXFMT == V4L2_PIX_FMT_Y16 || \ 11 PIXFMT == V4L2_PIX_FMT_Y16_BE || PIXFMT == V4L2_PIX_FMT_Z16 || \ 12 PIXFMT == V4L2_PIX_FMT_Y10 || PIXFMT == V4L2_PIX_FMT_Y12 13uniform highp usampler2D tex; 14#else 15uniform sampler2D tex; 16#endif 17uniform sampler2D ytex; 18uniform sampler2D uvtex; 19uniform sampler2D utex; 20uniform sampler2D vtex; 21 22in vec2 vs_TexCoord; 23 24out vec4 fs_FragColor; 25 26// YUV (aka Y'CbCr) to R'G'B' matrices 27 28const mat3 yuv2rgb = mat3( 29#if YCBCRENC == V4L2_YCBCR_ENC_SMPTE240M 30 // Old obsolete HDTV standard. Replaced by REC 709. 31 // SMPTE 240M has its own luma coefficients 32 1.0, 1.0, 1.0, 33 0.0, -0.2253, 1.8270, 34 1.5756, -0.4768, 0.0 35#elif YCBCRENC == V4L2_YCBCR_ENC_BT2020 36 // BT.2020 luma coefficients 37 1.0, 1.0, 1.0, 38 0.0, -0.1646, 1.8814, 39 1.4719, -0.5703, 0.0 40#elif YCBCRENC == V4L2_YCBCR_ENC_601 || YCBCRENC == V4L2_YCBCR_ENC_XV601 41 // These colorspaces all use the BT.601 luma coefficients 42 1.0, 1.0, 1.0, 43 0.0, -0.344, 1.773, 44 1.403, -0.714, 0.0 45#else 46 // The HDTV colorspaces all use REC 709 luma coefficients 47 1.0, 1.0, 1.0, 48 0.0, -0.1870, 1.8556, 49 1.5701, -0.4664, 0.0 50#endif 51); 52 53// Various colorspace conversion matrices that transfer the source chromaticities 54// to the sRGB/Rec.709 chromaticities 55 56const mat3 colconv = mat3( 57#if COLSP == V4L2_COLORSPACE_SMPTE170M || COLSP == V4L2_COLORSPACE_SMPTE240M 58 // Current SDTV standard, although slowly being replaced by REC 709. 59 // Uses the SMPTE 170M aka SMPTE-C aka SMPTE RP 145 conversion matrix. 60 0.939536, 0.017743, -0.001591, 61 0.050215, 0.965758, -0.004356, 62 0.001789, 0.016243, 1.005951 63#elif COLSP == V4L2_COLORSPACE_470_SYSTEM_M 64 // Old obsolete NTSC standard. Replaced by REC 709. 65 // Uses the NTSC 1953 conversion matrix and the Bradford method to 66 // compensate for the different whitepoints. 67 1.4858417, -0.0251179, -0.0272254, 68 -0.4033361, 0.9541568, -0.0440815, 69 -0.0825056, 0.0709611, 1.0713068 70#elif COLSP == V4L2_COLORSPACE_470_SYSTEM_BG 71 // Old obsolete PAL/SECAM standard. Replaced by REC 709. 72 // Uses the EBU Tech. 3213 conversion matrix. 73 1.0440, 0, 0, 74 -0.0440, 1, -0.0119, 75 0, 0, 1.0119 76#elif COLSP == V4L2_COLORSPACE_OPRGB 77 1.3982832, 0, 0, 78 -0.3982831, 1, -0.0429383, 79 0, 0, 1.0429383 80#elif COLSP == V4L2_COLORSPACE_DCI_P3 81 // Uses the Bradford method to compensate for the different whitepoints. 82 1.1574000, -0.0415052, -0.0180562, 83 -0.1548597, 1.0455684, -0.0785993, 84 -0.0025403, -0.0040633, 1.0966555 85#elif COLSP == V4L2_COLORSPACE_BT2020 86 1.6603627, -0.1245635, -0.0181566, 87 -0.5875400, 1.1329114, -0.1006017, 88 -0.0728227, -0.0083478, 1.1187583 89#else 90 // Identity matrix 91 1.0 92#endif 93); 94 95void main() 96{ 97 const float texl_w = 1.0 / tex_w; 98 const float texl_h = 1.0 / tex_h; 99 float alpha = 0.0; 100 vec2 xy = vs_TexCoord; 101 float xcoord = floor(xy.x * tex_w); 102 float ycoord = floor(xy.y * tex_h); 103 bool xeven = mod(xcoord, 2.0) == 0.0; 104 bool yeven = mod(ycoord, 2.0) == 0.0; 105 vec3 yuv; 106 vec3 rgb; 107 108#if FIELD == V4L2_FIELD_SEQ_TB 109 xy.y = (mod(ycoord, 2.0) == 0.0) ? xy.y / 2.0 : xy.y / 2.0 + 0.5; 110#elif FIELD == V4L2_FIELD_SEQ_BT 111 xy.y = (mod(ycoord, 2.0) == 0.0) ? xy.y / 2.0 + 0.5 : xy.y / 2.0; 112#endif 113 114#if IS_RGB 115 116// Bayer pixel formats 117#if PIXFMT == V4L2_PIX_FMT_SBGGR8 || PIXFMT == V4L2_PIX_FMT_SBGGR10 || PIXFMT == V4L2_PIX_FMT_SBGGR12 || PIXFMT == V4L2_PIX_FMT_SBGGR16 118 uvec4 urgb; 119 vec2 cell = vec2(xeven ? xy.x : xy.x - texl_w, yeven ? xy.y : xy.y - texl_h); 120 urgb.r = texture(tex, vec2(cell.x + texl_w, cell.y + texl_h)).r; 121 urgb.g = texture(tex, vec2((cell.y == xy.y) ? cell.x + texl_w : cell.x, xy.y)).r; 122 urgb.b = texture(tex, cell).r; 123#elif PIXFMT == V4L2_PIX_FMT_SGBRG8 || PIXFMT == V4L2_PIX_FMT_SGBRG10 || PIXFMT == V4L2_PIX_FMT_SGBRG12 || PIXFMT == V4L2_PIX_FMT_SGBRG16 124 uvec4 urgb; 125 vec2 cell = vec2(xeven ? xy.x : xy.x - texl_w, yeven ? xy.y : xy.y - texl_h); 126 urgb.r = texture(tex, vec2(cell.x, cell.y + texl_h)).r; 127 urgb.g = texture(tex, vec2((cell.y == xy.y) ? cell.x : cell.x + texl_w, xy.y)).r; 128 urgb.b = texture(tex, vec2(cell.x + texl_w, cell.y)).r; 129#elif PIXFMT == V4L2_PIX_FMT_SGRBG8 || PIXFMT == V4L2_PIX_FMT_SGRBG10 || PIXFMT == V4L2_PIX_FMT_SGRBG12 || PIXFMT == V4L2_PIX_FMT_SGRBG16 130 uvec4 urgb; 131 vec2 cell = vec2(xeven ? xy.x : xy.x - texl_w, yeven ? xy.y : xy.y - texl_h); 132 urgb.r = texture(tex, vec2(cell.x + texl_w, cell.y)).r; 133 urgb.g = texture(tex, vec2((cell.y == xy.y) ? cell.x : cell.x + texl_w, xy.y)).r; 134 urgb.b = texture(tex, vec2(cell.x, cell.y + texl_h)).r; 135#elif PIXFMT == V4L2_PIX_FMT_SRGGB8 || PIXFMT == V4L2_PIX_FMT_SRGGB10 || PIXFMT == V4L2_PIX_FMT_SRGGB12 || PIXFMT == V4L2_PIX_FMT_SRGGB16 136 uvec4 urgb; 137 vec2 cell = vec2(xeven ? xy.x : xy.x - texl_w, yeven ? xy.y : xy.y - texl_h); 138 urgb.b = texture(tex, vec2(cell.x + texl_w, cell.y + texl_h)).r; 139 urgb.g = texture(tex, vec2((cell.y == xy.y) ? cell.x + texl_w : cell.x, xy.y)).r; 140 urgb.r = texture(tex, cell).r; 141#elif PIXFMT == V4L2_PIX_FMT_RGB32 || PIXFMT == V4L2_PIX_FMT_XRGB32 || PIXFMT == V4L2_PIX_FMT_ARGB32 || \ 142 PIXFMT == V4L2_PIX_FMT_RGB444 || PIXFMT == V4L2_PIX_FMT_XRGB444 || PIXFMT == V4L2_PIX_FMT_ARGB444 143 vec4 cell = texture(tex, xy); 144#if V4L2_PIX_FMT_ARGB444 || PIXFMT == V4L2_PIX_FMT_ARGB32 145 alpha = cell.r; 146#endif 147 rgb.rgb = cell.gba; 148#elif PIXFMT == V4L2_PIX_FMT_BGR32 || PIXFMT == V4L2_PIX_FMT_XBGR32 || PIXFMT == V4L2_PIX_FMT_ABGR32 || \ 149 PIXFMT == V4L2_PIX_FMT_BGRX444 || PIXFMT == V4L2_PIX_FMT_BGRA444 || \ 150 PIXFMT == V4L2_PIX_FMT_XBGR555 || PIXFMT == V4L2_PIX_FMT_ABGR555 || \ 151 PIXFMT == V4L2_PIX_FMT_RGBX555 || PIXFMT == V4L2_PIX_FMT_RGBA555 152 vec4 cell = texture(tex, xy); 153#if PIXFMT == V4L2_PIX_FMT_ABGR32 || PIXFMT == V4L2_PIX_FMT_BGRA444 || PIXFMT == V4L2_PIX_FMT_RGBA555 || PIXFMT == V4L2_PIX_FMT_ABGR555 154 alpha = cell.a; 155#endif 156 rgb.rgb = cell.bgr; 157#elif PIXFMT == V4L2_PIX_FMT_RGBX32 || PIXFMT == V4L2_PIX_FMT_RGBA32 || \ 158 PIXFMT == V4L2_PIX_FMT_RGBX444 || PIXFMT == V4L2_PIX_FMT_RGBA444 || \ 159 PIXFMT == V4L2_PIX_FMT_RGB555 || PIXFMT == V4L2_PIX_FMT_XRGB555 || PIXFMT == V4L2_PIX_FMT_ARGB555 || \ 160 PIXFMT == V4L2_PIX_FMT_BGRX555 || PIXFMT == V4L2_PIX_FMT_BGRA555 161 vec4 cell = texture(tex, xy); 162#if PIXFMT == V4L2_PIX_FMT_RGBA32 || PIXFMT == V4L2_PIX_FMT_RGBA444 || PIXFMT == V4L2_PIX_FMT_ARGB555 || PIXFMT == V4L2_PIX_FMT_BGRA555 163 alpha = cell.a; 164#endif 165 rgb.rgb = cell.rgb; 166#elif PIXFMT == V4L2_PIX_FMT_BGRX32 || PIXFMT == V4L2_PIX_FMT_BGRA32 || \ 167 PIXFMT == V4L2_PIX_FMT_XBGR444 || PIXFMT == V4L2_PIX_FMT_ABGR444 168 vec4 cell = texture(tex, xy); 169#if PIXFMT == V4L2_PIX_FMT_BGRA32 || PIXFMT == V4L2_PIX_FMT_ABGR444 170 alpha = cell.r; 171#endif 172 rgb.rgb = cell.abg; 173#elif PIXFMT == V4L2_PIX_FMT_GREY 174 rgb.rgb = vec3(float(texture(tex, xy).r) / 255.0); 175#elif PIXFMT == V4L2_PIX_FMT_Y10 176 rgb.rgb = vec3(float(texture(tex, xy).r) / 1023.0); 177#elif PIXFMT == V4L2_PIX_FMT_Y12 178 rgb.rgb = vec3(float(texture(tex, xy).r) / 4095.0); 179#elif PIXFMT == V4L2_PIX_FMT_Y16 || PIXFMT == V4L2_PIX_FMT_Z16 180 rgb.rgb = vec3(float(texture(tex, xy).r) / 65535.0); 181#elif PIXFMT == V4L2_PIX_FMT_Y16_BE 182 uint low = texture(tex, xy).r >> 8; 183 uint high = (texture(tex, xy).r & 0xFFu) << 8; 184 rgb.rgb = vec3(float(high | low) / 65535.0); 185#else 186 vec4 color = texture(tex, xy); 187 188// RGB pixel formats with an alpha component 189#if PIXFMT == V4L2_PIX_FMT_ARGB555 || PIXFMT == V4L2_PIX_FMT_ARGB555X || \ 190 PIXFMT == V4L2_PIX_FMT_RGBA555 || PIXFMT == V4L2_PIX_FMT_ABGR555 || \ 191 PIXFMT == V4L2_PIX_FMT_BGRA555 192 alpha = color.a; 193#endif 194 195#if PIXFMT == V4L2_PIX_FMT_BGR666 196 vec3 frgb = floor(color.rgb * 255.0); 197 frgb.r = floor(frgb.r / 64.0) + mod(frgb.g, 16.0) * 4.0; 198 frgb.g = floor(frgb.g / 16.0) + mod(frgb.b, 4.0) * 16.0; 199 frgb.b = floor(frgb.b / 4.0); 200 rgb = frgb / 63.0; 201#elif PIXFMT == V4L2_PIX_FMT_BGR24 202 rgb = color.bgr; 203#else 204 rgb = color.rgb; 205#endif 206 207#endif 208 209#if PIXFMT == V4L2_PIX_FMT_SBGGR8 || PIXFMT == V4L2_PIX_FMT_SGBRG8 || \ 210 PIXFMT == V4L2_PIX_FMT_SGRBG8 || PIXFMT == V4L2_PIX_FMT_SRGGB8 211 rgb = vec3(urgb) / 255.0; 212#elif PIXFMT == V4L2_PIX_FMT_SBGGR10 || PIXFMT == V4L2_PIX_FMT_SGBRG10 || \ 213 PIXFMT == V4L2_PIX_FMT_SGRBG10 || PIXFMT == V4L2_PIX_FMT_SRGGB10 214 rgb = vec3(urgb) / 1023.0; 215#elif PIXFMT == V4L2_PIX_FMT_SBGGR12 || PIXFMT == V4L2_PIX_FMT_SGBRG12 || \ 216 PIXFMT == V4L2_PIX_FMT_SGRBG12 || PIXFMT == V4L2_PIX_FMT_SRGGB12 217 rgb = vec3(urgb) / 4095.0; 218#elif PIXFMT == V4L2_PIX_FMT_SBGGR16 || PIXFMT == V4L2_PIX_FMT_SGBRG16 || \ 219 PIXFMT == V4L2_PIX_FMT_SGRBG16 || PIXFMT == V4L2_PIX_FMT_SRGGB16 220 rgb = vec3(urgb) / 65535.0; 221#endif 222 223#if QUANT == V4L2_QUANTIZATION_LIM_RANGE 224 rgb -= 16.0 / 255.0; 225 rgb *= 255.0 / 219.0; 226#endif 227 228#else // IS_RGB 229 230#if PIXFMT == V4L2_PIX_FMT_YUYV 231 vec4 luma_chroma = texture(tex, xeven ? xy : vec2(xy.x - texl_w, xy.y)); 232 yuv.r = xeven ? luma_chroma.r : luma_chroma.b; 233 yuv.gb = luma_chroma.ga; 234#elif PIXFMT == V4L2_PIX_FMT_YVYU 235 vec4 luma_chroma = texture(tex, xeven ? xy : vec2(xy.x - texl_w, xy.y)); 236 yuv.r = xeven ? luma_chroma.r : luma_chroma.b; 237 yuv.gb = luma_chroma.ag; 238#elif PIXFMT == V4L2_PIX_FMT_UYVY 239 vec4 luma_chroma = texture(tex, xeven ? xy : vec2(xy.x - texl_w, xy.y)); 240 yuv.r = xeven ? luma_chroma.g : luma_chroma.a; 241 yuv.gb = luma_chroma.rb; 242#elif PIXFMT == V4L2_PIX_FMT_VYUY 243 vec4 luma_chroma = texture(tex, xeven ? xy : vec2(xy.x - texl_w, xy.y)); 244 yuv.r = xeven ? luma_chroma.g : luma_chroma.a; 245 yuv.gb = luma_chroma.br; 246#elif PIXFMT == V4L2_PIX_FMT_NV16 || PIXFMT == V4L2_PIX_FMT_NV16M || \ 247 PIXFMT == V4L2_PIX_FMT_NV12 || PIXFMT == V4L2_PIX_FMT_NV12M 248 yuv.r = texture(ytex, xy).r; 249 if (xeven) { 250 yuv.g = texture(uvtex, xy).r; 251 yuv.b = texture(uvtex, vec2(xy.x + texl_w, xy.y)).r; 252 } else { 253 yuv.g = texture(uvtex, vec2(xy.x - texl_w, xy.y)).r; 254 yuv.b = texture(uvtex, xy).r; 255 } 256#elif PIXFMT == V4L2_PIX_FMT_NV61 || PIXFMT == V4L2_PIX_FMT_NV61M || \ 257 PIXFMT == V4L2_PIX_FMT_NV21 || PIXFMT == V4L2_PIX_FMT_NV21M 258 yuv.r = texture(ytex, xy).r; 259 if (xeven) { 260 yuv.g = texture(uvtex, vec2(xy.x + texl_w, xy.y)).r; 261 yuv.b = texture(uvtex, xy).r; 262 } else { 263 yuv.g = texture(uvtex, xy).r; 264 yuv.b = texture(uvtex, vec2(xy.x - texl_w, xy.y)).r; 265 } 266#elif PIXFMT == V4L2_PIX_FMT_NV24 267 yuv.r = texture(ytex, xy).r; 268 yuv.g = texture(uvtex, xy).r; 269 yuv.b = texture(uvtex, xy).g; 270#elif PIXFMT == V4L2_PIX_FMT_NV42 271 yuv.r = texture(ytex, xy).r; 272 yuv.g = texture(uvtex, xy).g; 273 yuv.b = texture(uvtex, xy).r; 274#elif PIXFMT == V4L2_PIX_FMT_YUV555 275 vec4 color = texture(tex, xy); 276 alpha = color.a; 277 yuv = color.rgb; 278#elif PIXFMT == V4L2_PIX_FMT_YUV444 || PIXFMT == V4L2_PIX_FMT_YUV32 || \ 279 PIXFMT == V4L2_PIX_FMT_XYUV32 || PIXFMT == V4L2_PIX_FMT_AYUV32 280 vec4 color = texture(tex, xy); 281#if PIXFMT == V4L2_PIX_FMT_AYUV32 282 alpha = color.r; 283#endif 284 yuv.r = color.g; 285 yuv.g = color.b; 286 yuv.b = color.a; 287#elif PIXFMT == V4L2_PIX_FMT_VUYA32 || PIXFMT == V4L2_PIX_FMT_VUYX32 288 vec4 color = texture(tex, xy); 289#if PIXFMT == V4L2_PIX_FMT_VUYA32 290 alpha = color.a; 291#endif 292 yuv.r = color.b; 293 yuv.g = color.g; 294 yuv.b = color.r; 295#elif PIXFMT == V4L2_PIX_FMT_YUV565 296 yuv = texture(tex, xy).rgb; 297#elif PIXFMT == V4L2_PIX_FMT_YUV422P || PIXFMT == V4L2_PIX_FMT_YUV420 || PIXFMT == V4L2_PIX_FMT_YVU420 || \ 298 PIXFMT == V4L2_PIX_FMT_YUV420M || PIXFMT == V4L2_PIX_FMT_YVU420M || \ 299 PIXFMT == V4L2_PIX_FMT_YUV422M || PIXFMT == V4L2_PIX_FMT_YVU422M || \ 300 PIXFMT == V4L2_PIX_FMT_YUV444M || PIXFMT == V4L2_PIX_FMT_YVU444M 301 yuv = vec3(texture(ytex, xy).r, texture(utex, xy).r, texture(vtex, xy).r); 302#endif 303 304#if IS_HSV 305 vec4 color = texture(tex, xy); 306 307#if PIXFMT == V4L2_PIX_FMT_HSV32 308 color = color.gbar; 309#endif 310 // From http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl 311 float hue = color.r; 312 313#if HSVENC == V4L2_HSV_ENC_180 314 hue = (hue * 256.0) / 180.0; 315#endif 316 vec3 c = vec3(hue, color.g, color.b); 317 vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); 318 vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); 319 rgb = c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); 320#else // IS_HSV 321 yuv.gb -= 0.5; 322#endif 323 324#if QUANT != V4L2_QUANTIZATION_FULL_RANGE || YCBCRENC == V4L2_YCBCR_ENC_XV601 || YCBCRENC == V4L2_YCBCR_ENC_XV709 325 /* 326 * xv709 and xv601 have full range quantization, but they still 327 * need to be normalized as if they were limited range. But the 328 * result are values outside the normal 0-1 range, which is the 329 * point of these extended gamut encodings. 330 */ 331 const vec3 scale = vec3(255.0 / 219.0, 255.0 / 224.0, 255.0 / 224.0); 332 const vec3 offset = vec3(16.0 / 255.0, 0.0, 0.0); 333 334 yuv -= offset; 335 yuv *= scale; 336#endif 337 338#if YCBCRENC == V4L2_YCBCR_ENC_BT2020_CONST_LUM 339 // BT.2020_CONST_LUM luma coefficients 340 float y = yuv.r; 341 float u = yuv.g; 342 float v = yuv.b; 343 float b = u <= 0.0 ? y + 1.9404 * u : y + 1.5816 * u; 344 float r = v <= 0.0 ? y + 1.7184 * v : y + 0.9936 * v; 345 float lin_r = (r < 0.081) ? r / 4.5 : pow((r + 0.099) / 1.099, 1.0 / 0.45); 346 float lin_b = (b < 0.081) ? b / 4.5 : pow((b + 0.099) / 1.099, 1.0 / 0.45); 347 float lin_y = (y < 0.081) ? y / 4.5 : pow((y + 0.099) / 1.099, 1.0 / 0.45); 348 float lin_g = lin_y / 0.6780 - lin_r * 0.2627 / 0.6780 - lin_b * 0.0593 / 0.6780; 349 float g = (lin_g < 0.018) ? lin_g * 4.5 : 1.099 * pow(lin_g, 0.45) - 0.099; 350 rgb = vec3(r, g, b); 351#elif !IS_HSV 352 rgb = yuv2rgb * yuv; 353#endif 354#endif // !IS_RGB 355 356// Convert non-linear R'G'B' to linear RGB, taking into account the 357// colorspace. 358#if XFERFUNC == V4L2_XFER_FUNC_SMPTE240M 359 360// Old obsolete HDTV standard. Replaced by REC 709. 361// This is the transfer function for SMPTE 240M 362#define XFER(c) (((c) < 0.0913) ? (c) / 4.0 : pow(((c) + 0.1115) / 1.1115, 1.0 / 0.45)) 363 364 rgb = vec3(XFER(rgb.r), XFER(rgb.g), XFER(rgb.b)); 365 366#elif XFERFUNC == V4L2_XFER_FUNC_SRGB 367 368// This is used for sRGB as specified by the IEC FDIS 61966-2-1 standard 369#define XFER(c) (((c) < -0.04045) ? -pow((-(c) + 0.055) / 1.055, 2.4) : \ 370 (((c) <= 0.04045) ? (c) / 12.92 : pow(((c) + 0.055) / 1.055, 2.4))) 371 372 rgb = vec3(XFER(rgb.r), XFER(rgb.g), XFER(rgb.b)); 373 374#elif XFERFUNC == V4L2_XFER_FUNC_OPRGB 375 376 // Avoid powers of negative numbers 377 rgb = max(rgb, vec3(0.0)); 378 rgb = pow(rgb, vec3(2.19921875)); 379 380#elif XFERFUNC == V4L2_XFER_FUNC_DCI_P3 381 382 // Avoid powers of negative numbers 383 rgb = max(rgb, vec3(0.0)); 384 rgb = pow(rgb, vec3(2.6)); 385 386#elif XFERFUNC == V4L2_XFER_FUNC_SMPTE2084 387 const vec3 m1 = vec3(1.0 / ((2610.0 / 4096.0) / 4.0)); 388 const vec3 m2 = vec3(1.0 / (128.0 * 2523.0 / 4096.0)); 389 const vec3 c1 = vec3(3424.0 / 4096.0); 390 const vec3 c2 = vec3(32.0 * 2413.0 / 4096.0); 391 const vec3 c3 = vec3(32.0 * 2392.0 / 4096.0); 392 393 // Avoid powers of negative numbers 394 rgb = max(rgb, vec3(0.0)); 395 rgb = pow(rgb, m2); 396 // The factor 100 is because SMPTE-2084 maps to 0-10000 cd/m^2 397 // whereas other transfer functions map to 0-100 cd/m^2. 398 rgb = pow(max(rgb - c1, vec3(0.0)) / (c2 - rgb * c3), m1) * 100.0; 399 400#elif XFERFUNC != V4L2_XFER_FUNC_NONE 401 402// All others use the transfer function specified by REC 709 403#define XFER(c) (((c) <= -0.081) ? -pow(((c) - 0.099) / -1.099, 1.0 / 0.45) : \ 404 (((c) < 0.081) ? (c) / 4.5 : pow(((c) + 0.099) / 1.099, 1.0 / 0.45))) 405 406 rgb = vec3(XFER(rgb.r), XFER(rgb.g), XFER(rgb.b)); 407 408#endif 409 410// Convert the given colorspace to the REC 709/sRGB colorspace. All colors are 411// specified as linear RGB. 412#if COLSP == V4L2_COLORSPACE_SMPTE170M || COLSP == V4L2_COLORSPACE_SMPTE240M || \ 413 COLSP == V4L2_COLORSPACE_470_SYSTEM_M || COLSP == V4L2_COLORSPACE_470_SYSTEM_BG || \ 414 COLSP == V4L2_COLORSPACE_OPRGB || COLSP == V4L2_COLORSPACE_DCI_P3 || \ 415 COLSP == V4L2_COLORSPACE_BT2020 416 rgb = colconv * rgb; 417#endif 418 419// Convert linear RGB to non-linear R'G'B', assuming an sRGB display colorspace. 420 421#define XFER_SRGB(c) (((c) < -0.0031308) ? -1.055 * pow(-(c), 1.0 / 2.4) + 0.055 : \ 422 (((c) <= 0.0031308) ? (c) * 12.92 : 1.055 * pow(c, 1.0 / 2.4) - 0.055)) 423 424 rgb = vec3(XFER_SRGB(rgb.r), XFER_SRGB(rgb.g), XFER_SRGB(rgb.b)); 425 426 fs_FragColor = vec4(rgb, alpha); 427} 428