1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use std::ops::{Bound, RangeBounds};
use super::{Buffer, BufferDataUsage, Context, 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 = match items.start_bound() {
Bound::Included(&x) => x as i32,
Bound::Excluded(&x) => x as i32 - 1,
Bound::Unbounded => 0,
};
let end = match items.end_bound() {
Bound::Included(&x) => x as i32 + 1,
Bound::Excluded(&x) => x as i32,
Bound::Unbounded => buffer.count as i32,
};
assert!(
end <= buffer.count as i32,
"items range exceeds buffer size"
);
self.apply_attrs(context, buffer);
context.native.draw_arrays(mode.to_const(), start, end);
}
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;
}