use std::ops::RangeBounds;
use super::{resolve_range, Buffer, BufferDataUsage, Context, Indices, RenderPrimitiveType};
pub trait Program: Sized {
type AttrStruct: AttrStruct;
fn create(context: &Context) -> Self {
let p = Self::create_internally(context);
p.compile_shaders(context);
p.link_shaders(context);
p
}
fn create_internally(gl: &Context) -> Self;
fn compile_shaders(&self, gl: &Context);
fn link_shaders(&self, gl: &Context);
fn prepare_buffer(
context: &Context,
attrs: &[Self::AttrStruct],
usage: BufferDataUsage,
) -> Buffer<Self::AttrStruct> {
Buffer::from_slice(context, attrs, usage)
}
fn draw_fully(
&self,
context: &Context,
mode: RenderPrimitiveType,
buffer: &Buffer<Self::AttrStruct>,
items: impl RangeBounds<usize>,
) {
let (start, end) = resolve_range(items, buffer.count);
self.apply_attrs(context, buffer);
context.native.draw_arrays(mode.to_const(), start, end);
}
fn draw_indexed(
&self,
context: &Context,
mode: RenderPrimitiveType,
buffer: &Buffer<Self::AttrStruct>,
indices: &Indices,
items: impl RangeBounds<usize>,
) {
self.apply_attrs(context, buffer);
indices.draw(mode, context, items);
}
fn apply_attrs(&self, context: &Context, buffer: &Buffer<Self::AttrStruct>);
}
pub trait AttrStruct {
fn fields_count() -> usize;
fn field_gl_name(i: usize) -> &'static str;
fn field_offset(i: usize) -> usize;
fn field_type(i: usize) -> u32;
fn field_num_comps(i: usize) -> usize;
fn field_normalized(i: usize) -> bool;
}