77 lines
2.6 KiB
GLSL
77 lines
2.6 KiB
GLSL
#version 450
|
|
|
|
layout(set = 0, binding = 0, std430) readonly buffer V210 {
|
|
uint words[];
|
|
};
|
|
|
|
layout(push_constant) uniform PC {
|
|
uint width;
|
|
uint height;
|
|
uint strideBytes;
|
|
uint winW;
|
|
uint winH;
|
|
} pc;
|
|
|
|
layout(location = 0) out vec4 fragColor;
|
|
|
|
void main() {
|
|
// Letterbox: fit video into the window, preserving aspect ratio.
|
|
float sx = float(pc.winW) / float(pc.width);
|
|
float sy = float(pc.winH) / float(pc.height);
|
|
float scale = min(sx, sy);
|
|
float dispW = float(pc.width) * scale;
|
|
float dispH = float(pc.height) * scale;
|
|
float offX = (float(pc.winW) - dispW) * 0.5;
|
|
float offY = (float(pc.winH) - dispH) * 0.5;
|
|
float fbx = gl_FragCoord.x - offX;
|
|
float fby = gl_FragCoord.y - offY;
|
|
if (fbx < 0.0 || fbx >= dispW || fby < 0.0 || fby >= dispH) {
|
|
fragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
|
return;
|
|
}
|
|
// Framebuffer y is bottom-origin; flip to video top-origin.
|
|
uint x = uint(fbx / scale);
|
|
uint y = uint(fby / scale);
|
|
|
|
// V210: 6 pixels per group of 4 words; 3 ten-bit components per word
|
|
// (bits 0-9 / 10-19 / 20-29). Stream order: Cb Y Cr Y Cb Y Cr Y ...
|
|
uint group = x / 6u;
|
|
uint sub = x % 6u;
|
|
uint wordsPerLine = pc.strideBytes / 4u;
|
|
uint base = y * wordsPerLine + group * 4u;
|
|
|
|
uint w0 = words[base + 0u];
|
|
uint w1 = words[base + 1u];
|
|
uint w2 = words[base + 2u];
|
|
uint w3 = words[base + 3u];
|
|
|
|
uint cb0 = (w0 ) & 0x3FFu;
|
|
uint y0 = (w0 >> 10u) & 0x3FFu;
|
|
uint cr0 = (w0 >> 20u) & 0x3FFu;
|
|
uint y1 = (w1 ) & 0x3FFu;
|
|
uint cb1 = (w1 >> 10u) & 0x3FFu;
|
|
uint y2 = (w1 >> 20u) & 0x3FFu;
|
|
uint cr1 = (w2 ) & 0x3FFu;
|
|
uint y3 = (w2 >> 10u) & 0x3FFu;
|
|
uint cb2 = (w2 >> 20u) & 0x3FFu;
|
|
uint y4 = (w3 ) & 0x3FFu;
|
|
uint cr2 = (w3 >> 10u) & 0x3FFu;
|
|
uint y5 = (w3 >> 20u) & 0x3FFu;
|
|
|
|
float Y, Cb, Cr;
|
|
if (sub == 0u) { Y = float(y0); Cb = float(cb0); Cr = float(cr0); }
|
|
else if (sub == 1u) { Y = float(y1); Cb = float(cb0); Cr = float(cr0); }
|
|
else if (sub == 2u) { Y = float(y2); Cb = float(cb1); Cr = float(cr1); }
|
|
else if (sub == 3u) { Y = float(y3); Cb = float(cb1); Cr = float(cr1); }
|
|
else if (sub == 4u) { Y = float(y4); Cb = float(cb2); Cr = float(cr2); }
|
|
else { Y = float(y5); Cb = float(cb2); Cr = float(cr2); }
|
|
|
|
float yf = (Y - 64.0) / 876.0;
|
|
float uf = (Cb - 512.0) / 896.0;
|
|
float vf = (Cr - 512.0) / 896.0;
|
|
float r = yf + 1.5748 * vf;
|
|
float g = yf - 0.1873 * uf - 0.4681 * vf;
|
|
float b = yf + 1.8556 * uf;
|
|
fragColor = vec4(clamp(r, 0.0, 1.0), clamp(g, 0.0, 1.0), clamp(b, 0.0, 1.0), 1.0);
|
|
}
|