1use std::ops::RangeBounds;
2
3use super::{resolve_range, Buffer, BufferDataUsage, Context, Indices, RenderPrimitiveType};
4
5pub trait Program: Sized {
9 type AttrStruct: AttrStruct;
12
13 fn create(context: &Context) -> Self {
15 let p = Self::create_internally(context);
16 p.compile_shaders(context);
17 p.link_shaders(context);
18 p
19 }
20
21 fn create_internally(gl: &Context) -> Self;
23
24 fn compile_shaders(&self, gl: &Context);
26
27 fn link_shaders(&self, gl: &Context);
29
30 fn prepare_buffer(
32 context: &Context,
33 attrs: &[Self::AttrStruct],
34 usage: BufferDataUsage,
35 ) -> Buffer<Self::AttrStruct> {
36 Buffer::from_slice(context, attrs, usage)
37 }
38
39 fn draw_fully(
41 &self,
42 context: &Context,
43 mode: RenderPrimitiveType,
44 buffer: &Buffer<Self::AttrStruct>,
45 items: impl RangeBounds<usize>,
46 ) {
47 let (start, end) = resolve_range(items, buffer.count);
48
49 self.apply_attrs(context, buffer);
50
51 context.native.draw_arrays(mode.to_const(), start, end);
52 }
53
54 fn draw_indexed(
56 &self,
57 context: &Context,
58 mode: RenderPrimitiveType,
59 buffer: &Buffer<Self::AttrStruct>,
60 indices: &Indices,
61 items: impl RangeBounds<usize>,
62 ) {
63 self.apply_attrs(context, buffer);
64
65 indices.draw(mode, context, items);
66 }
67
68 fn apply_attrs(&self, context: &Context, buffer: &Buffer<Self::AttrStruct>);
70}
71
72pub trait AttrStruct {
76 fn fields_count() -> usize;
78
79 fn field_gl_name(i: usize) -> &'static str;
81
82 fn field_offset(i: usize) -> usize;
84
85 fn field_type(i: usize) -> u32;
87
88 fn field_num_comps(i: usize) -> usize;
90
91 fn field_normalized(i: usize) -> bool;
93}