#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); }