pub struct ShaderRecordParams {
pub fragment_shader_code_address: u32,
pub fragment_shader_uniforms_address: u32,
pub fragment_shader_num_varyings: u8,
pub vertex_shader_code_address: u32,
pub vertex_shader_uniforms_address: u32,
pub coordinate_shader_code_address: u32,
pub coordinate_shader_uniforms_address: u32,
pub vertex_buffer_address: u32,
}
pub fn build(cl: &mut [u8], params: &ShaderRecordParams) -> usize {
let mut b = Builder { bytes: cl, len: 0 };
b.shader_record(params);
b.attribute_record(
params.vertex_buffer_address,
16,
24,
0, 0, );
b.attribute_record(
params.vertex_buffer_address + 16,
8,
24,
16, 0, );
b.len
}
struct Builder<'a> {
bytes: &'a mut [u8],
len: usize,
}
impl<'a> Builder<'a> {
fn push_u8(&mut self, v: u8) {
self.bytes[self.len] = v;
self.len += 1;
}
fn push_u32(&mut self, v: u32) {
self.bytes[self.len..self.len + 4].copy_from_slice(&v.to_le_bytes());
self.len += 4;
}
fn skip(&mut self, n: usize) {
self.bytes[self.len..self.len + n].fill(0);
self.len += n;
}
fn shader_record(&mut self, params: &ShaderRecordParams) {
self.push_u8(0b0000_0101); self.skip(2); self.push_u8(params.fragment_shader_num_varyings);
self.push_u32(params.fragment_shader_code_address);
self.push_u32(params.fragment_shader_uniforms_address);
self.skip(2); self.push_u8(0b0000_0011); self.push_u8(24); self.push_u32(params.vertex_shader_code_address);
self.push_u32(params.vertex_shader_uniforms_address);
self.skip(2); self.push_u8(0b0000_0001); self.push_u8(16); self.push_u32(params.coordinate_shader_code_address);
self.push_u32(params.coordinate_shader_uniforms_address);
}
fn attribute_record(
&mut self,
address: u32,
bytes: u8,
stride: u8,
vertex_shader_vpm_offset: u8,
coordinate_shader_vpm_offset: u8,
) {
self.push_u32(address);
self.push_u8(bytes - 1);
self.push_u8(stride);
self.push_u8(vertex_shader_vpm_offset);
self.push_u8(coordinate_shader_vpm_offset);
}
}