1extern crate gl;
2
3use std::ffi::{c_void, CStr};
4
5pub mod buffer;
6pub mod glsl;
7pub mod vec;
8pub mod texture;
9pub mod target;
10pub mod vertex;
11
12pub use vec::{Vec2, Vec3, Vec4};
13
14pub trait GlslType {
15 fn to_glsl() -> String {
16 "".to_owned()
17 }
18}
19
20#[macro_export]
21macro_rules! impl_glsl {
22 ($tp: ty, $name: literal) => {
23 impl GlslType for $tp {
24 fn to_glsl() -> String { $name.to_owned() }
25 }
26 };
27}
28
29impl_glsl!(bool, "bool");
30impl_glsl!(i32, "int");
31impl_glsl!(u32, "uint");
32impl_glsl!(f32, "float");
33impl_glsl!(f64, "double");
34
35pub trait GlTarget {
36 fn target() -> u32;
37 fn binding() -> u32;
38 fn current_bind() -> u32 {
39 let mut gl_id = 0;
40 unsafe { gl::GetIntegerv(Self::binding(), &mut gl_id) };
41 return gl_id as u32;
42 }
43}
44
45pub trait GlBind {
46 fn bind(&self);
47 fn unbind(&self);
48}
49
50pub trait GlUse {
51 fn set_used(&self);
52 fn set_unused(&self);
53}
54
55pub trait GlEnum {
56 fn gl_enum() -> u32 { gl::NONE }
57 fn to_enum(&self) -> u32 { gl::NONE }
58}
59
60pub trait GlObject {
61 fn get_id(&self) -> u32;
62}
63
64pub trait GlAttrib: GlEnum + Sized {
65 fn size() -> u32 { 1 }
66 fn stride() -> usize { std::mem::size_of::<Self>() }
67 fn get_size(&self) -> u32 { Self::size() }
68 fn get_stride(&self) -> usize { Self::stride() }
69
70 fn setup_attrib(index: u32, normalized: bool, stride: i32, start: i32) {
71 unsafe { gl::VertexAttribPointer(index, Self::size() as i32, Self::gl_enum(), normalized as u8, stride, start as *const c_void) };
72 }
73}
74
75pub trait GlUniform {
76 fn uniform(location: i32, val: &Self);
77 fn uniformv(location: i32, count: i32, ptr: *const Self);
78
79 fn send_uniform(&self, location: i32);
80}
81
82#[derive(Default, Debug)]
83pub enum GlType {
84 #[default]
85 Byte,
86 UByte,
87 Short,
88 UShort,
89 Int,
90 UInt,
91 Float,
92 Double
93}
94
95impl GlEnum for GlType {
96 fn to_enum(&self) -> u32 {
97 match self {
98 GlType::Byte => { return gl::BYTE },
99 GlType::UByte => { return gl::UNSIGNED_BYTE },
100 GlType::Short => { return gl::SHORT },
101 GlType::UShort => { return gl::UNSIGNED_SHORT },
102 GlType::Int => { return gl::INT },
103 GlType::UInt => { return gl::UNSIGNED_INT },
104 GlType::Float => { return gl::FLOAT },
105 GlType::Double => { return gl::DOUBLE }
106 }
107 }
108}
109
110macro_rules! impl_type {
111 ($tp: ty, $Enum: expr) => {
112 impl GlEnum for $tp {
113 fn gl_enum() -> u32 { $Enum }
114 fn to_enum(&self) -> u32 { $Enum }
115 }
116
117 impl GlAttrib for $tp {}
118 };
119 ($tp: ty, $Enum: expr, $Uniform: ident, $Uniformv: ident) => {
120 impl GlEnum for $tp {
121 fn gl_enum() -> u32 { $Enum }
122 fn to_enum(&self) -> u32 { $Enum }
123 }
124
125 impl GlAttrib for $tp {}
126
127 impl GlUniform for $tp {
128 fn uniform(location: i32, val: &$tp) {
129 unsafe { gl::$Uniform(location, *val) };
130 }
131
132 fn uniformv(location: i32, count: i32, ptr: *const $tp) {
133 unsafe { gl::$Uniformv(location, count, ptr) };
134 }
135
136 fn send_uniform(&self, location: i32) {
137 unsafe { gl::$Uniform(location, *self) };
138 }
139 }
140
141 };
151 ($tp: ty, $Enum: expr, $Uniform: ident, $Uniformv: ident, $convert: ty) => {
152 impl GlEnum for $tp {
153 fn gl_enum() -> u32 { $Enum }
154 fn to_enum(&self) -> u32 { $Enum }
155 }
156
157 impl GlAttrib for $tp {}
158
159 impl GlUniform for $tp {
160 fn uniform(location: i32, val: &$tp) {
161 unsafe { gl::$Uniform(location, *val as $convert) };
162 }
163 fn uniformv(location: i32, count: i32, ptr: *const Self) {
164 unsafe { gl::$Uniformv(location, count, ptr as *const $convert) };
165 }
166
167 fn send_uniform(&self, location: i32) {
168 unsafe { gl::$Uniform(location, *self as $convert) };
169 }
170 }
171
172 };
187}
188
189impl_type!(bool, gl::BOOL, Uniform1i, Uniform1iv, i32);
198impl_type!(i8, gl::BYTE, Uniform1i, Uniform1iv, i32);
199impl_type!(u8, gl::UNSIGNED_BYTE, Uniform1ui, Uniform1uiv, u32);
200impl_type!(i16, gl::SHORT, Uniform1i, Uniform1iv, i32);
201impl_type!(u16, gl::UNSIGNED_SHORT, Uniform1ui, Uniform1uiv, u32);
202impl_type!(i32, gl::INT, Uniform1i, Uniform1iv);
203impl_type!(u32, gl::UNSIGNED_INT, Uniform1ui, Uniform1uiv);
204impl_type!(f32, gl::FLOAT, Uniform1f, Uniform1fv);
205impl_type!(f64, gl::DOUBLE, Uniform1d, Uniform1dv);
206
207#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
208pub enum ClearFlags {
209 #[default]
210 ColorBufferBit,
211 DepthBufferBit,
212 StencilBufferBit
213}
214
215impl GlEnum for ClearFlags {
216 fn to_enum(&self) -> u32 {
217 match self {
218 Self::ColorBufferBit => { gl::COLOR_BUFFER_BIT },
219 Self::DepthBufferBit => { gl::DEPTH_BUFFER_BIT },
220 Self::StencilBufferBit => { gl::STENCIL_BUFFER_BIT },
221 }
222 }
223}
224
225#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
226pub enum EnableFlags {
227 #[default]
228 Blend,
229 CullFace,
230 DepthTest,
231 Dither,
232 Texture2D,
233 ScissorTest,
234}
235
236impl GlEnum for EnableFlags {
237 fn to_enum(&self) -> u32 {
238 match self {
239 Self::Blend => { gl::BLEND },
240 Self::CullFace => { gl::CULL_FACE },
241 Self::DepthTest => { gl::DEPTH_TEST },
242 Self::Dither => { gl::DITHER },
243 Self::Texture2D => { gl::TEXTURE_2D },
244 Self::ScissorTest => { gl::SCISSOR_TEST }
245 }
246 }
247}
248
249
250#[derive(Default, Debug, PartialEq, Eq, Copy, Clone)]
251pub enum DrawMode {
252 Points,
253 Lines,
254 #[default]
255 Triangles
256}
257
258impl GlEnum for DrawMode {
259 fn to_enum(&self) -> u32 {
260 match self {
261 Self::Points => { gl::POINTS },
262 Self::Lines => { gl::LINES },
263 Self::Triangles => { gl::TRIANGLES }
264 }
265 }
266}
267
268#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
269pub enum BlendFunc {
270 Zero,
271 One,
272 SrcColor,
273 OneMinusSrcColor,
274 DstColor,
275 OneMinusDstColor,
276 SrcAlpha,
277 OneMinusSrcAlpha,
278 DstAlpha,
279 OneMinusDstAlpha,
280 ConstantColor,
281 OneMinusConstantColor,
282 ConstantAlpha,
283 OneMinusConstantAlpha,
284}
285
286impl GlEnum for BlendFunc {
287 fn to_enum(&self) -> u32 {
288 match self {
289 Self::Zero => { gl::ZERO },
290 Self::SrcAlpha => { gl::SRC_ALPHA },
291 Self::OneMinusSrcAlpha => { gl::ONE_MINUS_SRC_ALPHA },
292 _ => { gl::NONE }
293 }
294 }
295}
296
297#[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
298pub enum CullMode {
299 #[default]
300 Front,
301 Back,
302 FrontAndBack,
303}
304
305impl GlEnum for CullMode {
306 fn to_enum(&self) -> u32 {
307 match self {
308 Self::Front => { gl::FRONT },
309 Self::Back => { gl::BACK },
310 Self::FrontAndBack => { gl::FRONT_AND_BACK },
311 }
312 }
313}
314
315#[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
316pub enum FrontFace {
317 #[default]
318 CCW,
319 CW
320}
321
322impl GlEnum for FrontFace {
323 fn to_enum(&self) -> u32 {
324 match self {
325 Self::CCW => { gl::CCW },
326 Self::CW => { gl::CW },
327 }
328 }
329}
330
331#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
332pub enum GlFunc {
333 Never,
334 Less,
335 Equal,
336 LEqual,
337 Greater,
338 NotEqual,
339 GEqual,
340 Always
341}
342
343impl GlEnum for GlFunc {
344 fn to_enum(&self) -> u32 {
345 match self {
346 Self::Never => { gl::NEVER },
347 Self::Less => { gl::LESS },
348 Self::Equal => { gl::EQUAL },
349 Self::LEqual => { gl::LEQUAL },
350 Self::Greater => { gl::GREATER },
351 Self::NotEqual => { gl::NOTEQUAL },
352 Self::GEqual => { gl::GEQUAL },
353 Self::Always => { gl::ALWAYS },
354 }
355 }
356}
357
358pub fn gl_version() -> String {
359 let version = unsafe { gl::GetString(gl::VERSION) };
360 #[cfg(target_arch="aarch64")]
361 let ptr = unsafe { CStr::from_ptr(version as *const u8) };
362 #[cfg(not(target_arch="aarch64"))]
363 let ptr = unsafe { CStr::from_ptr(version as *const i8) };
364 return ptr.to_str().unwrap().to_string()
365}
366
367pub fn glsl_version() -> String {
368 let version = unsafe { gl::GetString(gl::SHADING_LANGUAGE_VERSION) };
369 #[cfg(target_arch="aarch64")]
370 let ptr = unsafe { CStr::from_ptr(version as *const u8) };
371 #[cfg(not(target_arch="aarch64"))]
372 let ptr = unsafe { CStr::from_ptr(version as *const i8) };
373 return ptr.to_str().unwrap().to_string()
374}
375
376pub fn load_with<F: FnMut(&'static str) -> *const c_void>(loadfn: F) { gl::load_with(loadfn) }
377
378pub fn enable(flags: &[EnableFlags]) {
379 for flag in flags {
380 unsafe { gl::Enable(flag.to_enum()) };
381 }
382}
383
384pub fn disable(flags: &[EnableFlags]) {
385 for flag in flags {
386 unsafe { gl::Disable(flag.to_enum()) };
387 }
388}
389
390pub fn blend_color(color: Vec4) {
392 unsafe { gl::BlendColor(color.x, color.y, color.z, color.w) };
393}
394
395pub fn blend_func(sfactor: BlendFunc, dfactor: BlendFunc) {
396 unsafe { gl::BlendFunc(sfactor.to_enum(), dfactor.to_enum()) };
397}
398
399pub fn blend_func_separate(src_rgb: BlendFunc, dst_rgb: BlendFunc, src_alpha: BlendFunc, dst_alpha: BlendFunc) {
400 unsafe { gl::BlendFuncSeparate(src_rgb.to_enum(), dst_rgb.to_enum(), src_alpha.to_enum(), dst_alpha.to_enum()) };
401}
402
403pub fn color_mask(r: bool, g: bool, b: bool, a: bool) {
405 unsafe { gl::ColorMask(r.to_enum() as u8, g.to_enum() as u8, b.to_enum() as u8, a.to_enum() as u8) }
406}
407
408pub fn clear_color(r: f32, g: f32, b: f32, a: f32) {
409 unsafe { gl::ClearColor(r, g, b, a) };
410}
411
412pub fn cull_face(mode: CullMode) {
414 unsafe { gl::CullFace(mode.to_enum()) };
415}
416
417pub fn front_face(mode: FrontFace) {
418 unsafe { gl::FrontFace(mode.to_enum()) };
419}
420
421pub fn depth_func(func: GlFunc) {
423 unsafe { gl::DepthFunc(func.to_enum()) };
424}
425
426pub fn depth_mask(enabled: bool) {
427 unsafe { gl::DepthMask(enabled.to_enum() as u8) };
428}
429
430pub fn clear_depth(d: f64) {
431 unsafe { gl::ClearDepth(d) };
432}
433
434pub fn stencil_func(func: GlFunc, ref_: i32, mask: u32) {
436 unsafe { gl::StencilFunc(func.to_enum(), ref_, mask) };
437}
438
439pub fn stencil_func_separate(face: CullMode, func: GlFunc, ref_: i32, mask: u32) {
440 unsafe { gl::StencilFuncSeparate(face.to_enum(), func.to_enum(), ref_, mask) };
441}
442
443pub fn clear_stencil(s: i32) {
444 unsafe { gl::ClearStencil(s) };
445}
446
447pub fn clear(flags: &[ClearFlags]) {
449 let mut mask = 0;
450 for flag in flags {
451 mask = mask | (flag.to_enum());
452 }
453 unsafe { gl::Clear(mask) };
454}
455
456pub fn scissor(x: i32, y: i32, width: i32, height: i32) {
457 unsafe { gl::Scissor(x, y, width, height) };
458}
459
460pub fn viewport(x: i32, y: i32, width: i32, height: i32) {
461 unsafe { gl::Viewport(x, y, width, height) };
462}
463
464pub fn draw_arrays(mode: DrawMode, start: i32, count: i32) {
465 unsafe { gl::DrawArrays(mode.to_enum(), start, count) };
466}
467
468pub fn draw_elements(mode: DrawMode, start: i32, count: i32) {
469 unsafe { gl::DrawElements(mode.to_enum(), count, gl::UNSIGNED_INT, start as *const c_void) };
470}