#version 430
// vi: ft=glsl

layout(location = 0) in vec2 texture_coords;
layout(location = 0) out uvec4 out_color;

layout(set = 1, binding = 0) uniform InfoBlock {
	uint format;
	uint width;
	uint height;
	uint stride_x;
	uint stride_y;
};

layout(set = 1, binding = 1) buffer Data {
	uint data[];
};

uint extract_u8(uint i) {
	uint word = data[i / 4];
	uint offset = (i % 4) * 8;
	return word >> offset & 0xFF;
}

uvec4 get_pixel(uint x, uint y) {
	uint i = x * stride_x + y * stride_y;

	// Mono8
	if (format == 0) {
		float mono = extract_u8(i);
		return uvec4(mono, mono, mono, 255);

	// MonoAlpha8(Unpremultiplied)
	} else if (format == 1) {
		uint mono = extract_u8(i);
		uint a    = extract_u8(i + 1);
		return uvec4(mono, mono, mono, a);

	// MonoAlpha8(Premultiplied)
	} else if (format == 2) {
		uint a    = extract_u8(i + 1);
		uint mono = extract_u8(i) * 255 / a;
		return uvec4(mono, mono, mono, a);

	// Bgr8
	} else if (format == 3) {
		uint b = extract_u8(i + 0);
		uint g = extract_u8(i + 1);
		uint r = extract_u8(i + 2);
		return uvec4(r, g, b, 255);

	// Bgra8(Unpremultiplied)
	} else if (format == 4) {
		uint b = extract_u8(i + 0);
		uint g = extract_u8(i + 1);
		uint r = extract_u8(i + 2);
		uint a = extract_u8(i + 3);
		return uvec4(r, g, b, a);

	// Bgra8(Premultiplied)
	} else if (format == 5) {
		uint a = extract_u8(i + 3);
		uint b = extract_u8(i + 0) * 255 / a;
		uint g = extract_u8(i + 1) * 255 / a;
		uint r = extract_u8(i + 2) * 255 / a;
		return uvec4(r, g, b, a);

	// Rgb8
	} else if (format == 6) {
		uint r = extract_u8(i + 0);
		uint g = extract_u8(i + 1);
		uint b = extract_u8(i + 2);
		return uvec4(r, g, b, 255);

	// Rgba8(Unpremultiplied)
	} else if (format == 7) {
		uint r = extract_u8(i + 0);
		uint g = extract_u8(i + 1);
		uint b = extract_u8(i + 2);
		uint a = extract_u8(i + 3);
		return uvec4(r, g, b, a);

	// Rgba8(Premultiplied)
	} else if (format == 8) {
		uint a = extract_u8(i + 3);
		uint r = extract_u8(i + 0) * 255 / a;
		uint g = extract_u8(i + 1) * 255 / a;
		uint b = extract_u8(i + 2) * 255 / a;
		return uvec4(r, g, b, a);

	} else {
		return uvec4(255, 0, 255, 255);
	}
}

void main() {
	uint x = uint(round(texture_coords.x));
	uint y = uint(round(texture_coords.y));
	if (x >= width || y >= height) {
		out_color = uvec4(0, 0, 0, 0);
	} else {
		out_color = get_pixel(x, y);
	}
}
