#[cfg(any(windows))]
use crate::windows::OpenGraphicsLibrary;
use core::mem::{
MaybeUninit,
transmute
};
const LINK_STATUS:u32=0x8B82;
const INFO_LOG_LENGTH:u32=0x8B84;
pub const INVALID_INDEX:u32=0xFFFFFFFF;
#[repr(u32)]
#[derive(Clone,Copy,Debug)]
pub enum ProgramParameter{
LinkStatus=LINK_STATUS,
InfoLogLength=INFO_LOG_LENGTH,
}
pub struct Program{
glCreateProgram:usize,
glDeleteProgram:usize,
glAttachShader:usize,
glLinkProgram:usize,
glGetProgramiv:usize,
glGetProgramInfoLog:usize,
glUseProgram:usize,
glGetUniformLocation:usize,
glGetUniformBlockIndex:usize,
glUniformBlockBinding:usize,
}
impl Program{
pub const fn new()->Program{
Self{
glCreateProgram:0,
glDeleteProgram:0,
glAttachShader:0,
glLinkProgram:0,
glGetProgramiv:0,
glGetProgramInfoLog:0,
glUseProgram:0,
glGetUniformLocation:0,
glGetUniformBlockIndex:0,
glUniformBlockBinding:0,
}
}
#[cfg(any(windows))]
pub fn load(&mut self,library:&OpenGraphicsLibrary){
unsafe{
self.glCreateProgram=transmute(library.get_proc_address("glCreateProgram\0"));
self.glDeleteProgram=transmute(library.get_proc_address("glDeleteProgram\0"));
self.glAttachShader=transmute(library.get_proc_address("glAttachShader\0"));
self.glLinkProgram=transmute(library.get_proc_address("glLinkProgram\0"));
self.glGetProgramiv=transmute(library.get_proc_address("glGetProgramiv\0"));
self.glGetProgramInfoLog=transmute(library.get_proc_address("glGetProgramInfoLog\0"));
self.glUseProgram=transmute(library.get_proc_address("glUseProgram\0"));
self.glGetUniformLocation=transmute(library.get_proc_address("glGetUniformLocation\0"));
self.glGetUniformBlockIndex=transmute(library.get_proc_address("glGetUniformBlockIndex\0"));
self.glUniformBlockBinding=transmute(library.get_proc_address("glUniformBlockBinding\0"));
}
}
}
impl Program{
#[inline(always)]
pub fn create(&self)->u32{
unsafe{
transmute::<usize,fn()->u32>(self.glCreateProgram)()
}
}
#[inline(always)]
pub unsafe fn delete(&self,program_id:u32){
transmute::<usize,fn(u32)>(self.glDeleteProgram)(program_id)
}
pub unsafe fn bind(&self,program_id:u32){
transmute::<usize,fn(u32)>(self.glUseProgram)(program_id)
}
#[inline(always)]
pub unsafe fn attach_shader(&self,program_id:u32,shader_id:u32){
transmute::<usize,fn(u32,u32)>(self.glAttachShader)(program_id,shader_id)
}
#[inline(always)]
pub unsafe fn link(&self,program_id:u32){
transmute::<usize,fn(u32)>(self.glLinkProgram)(program_id)
}
#[inline(always)]
pub unsafe fn get_parameter(&self,program_id:u32,parameter:ProgramParameter,value:&mut i32){
transmute::<usize,fn(u32,ProgramParameter,&mut i32)>(self.glGetProgramiv)(program_id,parameter,value)
}
pub unsafe fn get_info_log(&self,shader_id:u32,log:&mut String){
let buffer=log.as_mut_vec();
let mut length:i32=MaybeUninit::uninit().assume_init();
transmute::<usize,fn(u32,i32,&mut i32,*mut u8)>(self.glGetProgramInfoLog)(
shader_id,
buffer.capacity() as i32,
&mut length,
buffer.as_mut_ptr()
);
if length!=0{
length-=1;
}
buffer.set_len(length as usize);
}
#[inline(always)]
pub unsafe fn get_uniform_location(&self,program_id:u32,name:&str)->i32{
transmute::<usize,fn(u32,*const u8)->i32>(self.glGetUniformLocation)(program_id,name.as_ptr())
}
#[inline(always)]
pub unsafe fn get_uniform_block_index(&self,program_id:u32,name:&str)->u32{
transmute::<usize,fn(u32,*const u8)->u32>(self.glGetUniformBlockIndex)(program_id,name.as_ptr())
}
#[inline(always)]
pub unsafe fn set_uniform_block_binding(&self,program_id:u32,uniform_block_index:u32,uniform_block_binding:u32){
transmute::<usize,fn(u32,u32,u32)>(self.glUniformBlockBinding)(program_id,uniform_block_index,uniform_block_binding)
}
}