use crate::lib::*; pub trait State { fn bound_obj() -> &'static mut u32; fn tracked_obj() -> &'static mut u32; unsafe fn bind(_: u32) {} unsafe fn gen(obj: &mut u32) { GL::unigl::glCreateBuffer(obj); } unsafe fn del(obj: &mut u32) { gl::DeleteBuffers(1, obj); debug_assert!({ Self::crossbindcheck_map().values_mut().for_each(|b| { b.iter_mut().for_each(|o| { if *o == *obj { *o = 0; } }) }); true }); } fn crossbindcheck_map() -> &'static mut HashMap> { LocalStatic!(HashMap>) } fn checkcrossbinds(obj: &u32) { debug_assert!({ if let Ok(_pos) = Self::crossbindcheck_map() .get(obj) .unwrap_or_else(|| ASSERT!(false, "No {} buffer bound to GL object {obj}", type_name::())) .binary_search(&0) { ASSERT!(false, "{} buffer bound to GL object {obj} at position {_pos} was invalidated", type_name::()); } true }); } fn Lock(obj: u32) { debug_assert!({ ASSERT!( *Self::tracked_obj() == 0, "Tried to bind GL {} object {obj} while {} still in use", type_name::(), Self::tracked_obj() ); *Self::tracked_obj() = obj; true }); } fn Unlock() { debug_assert!({ *Self::tracked_obj() = 0; true }); } fn New() -> u32 { let mut obj = 0; GL!(Self::gen(&mut obj)); ASSERT!(obj != 0, "GL {} not initilized", type_name::()); DEBUG!("Created GL {} obj {obj}", type_name::()); obj } fn Bind(obj: u32) { let bound_obj = Self::bound_obj(); if *bound_obj != obj { DEBUG!("Binding GL {} obj {obj}", type_name::()); *bound_obj = obj; GL!(Self::bind(obj)); } } fn Drop(obj: u32) { ASSERT!(obj != 0, "GL {} zero before drop", type_name::()); if *Self::bound_obj() == obj { *Self::bound_obj() = 0; } let mut obj = obj; DEBUG!("Deleting GL {} obj {obj}", type_name::()); GL!(Self::del(&mut obj)); } }