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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
use super::{state::*, tex_state::*, universion::*};
use crate::lib::*;

macro_rules! m_STATE {
	() => {
		fn bound_obj() -> &'static mut u32 {
			LocalStatic!(u32)
		}
		fn tracked_obj() -> &'static mut u32 {
			LocalStatic!(u32)
		}
	};
}

pub trait Buffer: TrivialBound + State {
	const TYPE: GLenum;
}

derive_common_VAL! { pub struct Attribute; }
impl State for Attribute {
	m_STATE!();
}
impl Buffer for Attribute {
	const TYPE: GLenum = gl::ARRAY_BUFFER;
}

derive_common_VAL! { pub struct Index; }
impl State for Index {
	m_STATE!();
}
impl Buffer for Index {
	const TYPE: GLenum = gl::ELEMENT_ARRAY_BUFFER;
}

pub trait ShdBuffType: Buffer {
	fn max_bindings() -> i32;
	fn max_size() -> usize;
}

derive_common_VAL! { pub struct Uniform; }
impl State for Uniform {
	m_STATE!();
}
impl Buffer for Uniform {
	const TYPE: GLenum = gl::UNIFORM_BUFFER;
}

derive_common_VAL! { pub struct ShdStorage; }
impl State for ShdStorage {
	m_STATE!();
}
impl Buffer for ShdStorage {
	const TYPE: GLenum = gl::SHADER_STORAGE_BUFFER;
}

macro_rules! impl_shd {
	($n: ident, $t: ident) => {
		#[derive(Default, Debug)]
		pub struct $n;
		impl State for $n {
			m_STATE!();
			unsafe fn gen(obj: &mut u32) {
				*obj = gl::CreateShader(gl::$t);
			}
			unsafe fn del(obj: &mut u32) {
				gl::DeleteShader(*obj);
			}
		}
	};
}
impl_shd!(ShaderVert, VERTEX_SHADER);
impl_shd!(ShaderPix, FRAGMENT_SHADER);
impl_shd!(ShaderGeom, GEOMETRY_SHADER);
impl_shd!(ShaderComp, COMPUTE_SHADER);
impl_shd!(ShaderTCtrl, TESS_CONTROL_SHADER);
impl_shd!(ShaderTEval, TESS_EVALUATION_SHADER);

#[derive(Default, Debug)]
pub struct ShaderProg;
impl State for ShaderProg {
	m_STATE!();
	unsafe fn bind(obj: u32) {
		gl::UseProgram(obj);
	}
	unsafe fn gen(obj: &mut u32) {
		*obj = gl::CreateProgram();
	}
	unsafe fn del(obj: &mut u32) {
		gl::DeleteProgram(*obj);
	}
}

#[derive(Default, Debug)]
pub struct VertArrObj;
impl State for VertArrObj {
	m_STATE!();
	unsafe fn bind(obj: u32) {
		gl::BindVertexArray(obj);
	}
	unsafe fn gen(obj: &mut u32) {
		glCreateVao(obj);
	}
	unsafe fn del(obj: &mut u32) {
		gl::DeleteVertexArrays(1, obj);
	}
}

#[derive(Default, Debug)]
pub struct Query;
impl State for Query {
	m_STATE!();
	unsafe fn gen(obj: &mut u32) {
		gl::GenQueries(1, obj);
	}
	unsafe fn del(obj: &mut u32) {
		gl::DeleteQueries(1, obj);
	}
}

#[derive(Default, Debug)]
pub struct Framebuff;
impl State for Framebuff {
	m_STATE!();
	unsafe fn bind(obj: u32) {
		gl::BindFramebuffer(gl::DRAW_FRAMEBUFFER, obj);
	}
	unsafe fn gen(obj: &mut u32) {
		glCreateFramebuff(obj);
	}
	unsafe fn del(obj: &mut u32) {
		gl::DeleteFramebuffers(1, obj);
	}
}

#[derive(Default, Debug)]
pub struct Renderbuff;
impl State for Renderbuff {
	m_STATE!();
	unsafe fn gen(obj: &mut u32) {
		glCreateRenderbuff(obj);
	}
	unsafe fn del(obj: &mut u32) {
		gl::DeleteRenderbuffers(1, obj);
	}
}

#[derive(Default, Debug)]
pub struct SamplObj;
impl State for SamplObj {
	m_STATE!();
	unsafe fn gen(obj: &mut u32) {
		gl::GenSamplers(1, obj);
	}
	unsafe fn del(obj: &mut u32) {
		TexState::drop_samp(*obj);
		gl::DeleteSamplers(1, obj);
	}
}

#[derive(Default, Debug)]
pub struct Texture<T>(Dummy<T>);
impl<T: TexType> State for Texture<T> {
	m_STATE!();
	unsafe fn gen(obj: &mut u32) {
		glCreateTexture(T::TYPE, obj);
	}
	unsafe fn del(obj: &mut u32) {
		TexState::drop_tex(*obj);
		glDeleteTexture(obj);
	}
}
pub trait TexType: TrivialBound {
	const TYPE: GLenum;
}