cat_engine_basement 0.0.0-alpha7

The CatEnigne's basement
Documentation
#[cfg(any(windows))]
use crate::windows::OpenGraphicsLibrary;

use core::mem::{
    MaybeUninit,
    transmute
};

// Program parameters
const LINK_STATUS:u32=0x8B82;
const INFO_LOG_LENGTH:u32=0x8B84;

// Errors
pub const INVALID_INDEX:u32=0xFFFFFFFF;

#[repr(u32)]
#[derive(Clone,Copy,Debug)]
pub enum ProgramParameter{
    // GL_DELETE_STATUS,
    LinkStatus=LINK_STATUS,
    // GL_VALIDATE_STATUS,
    InfoLogLength=INFO_LOG_LENGTH,
    // GL_ATTACHED_SHADERS,
    // GL_ACTIVE_ATTRIBUTES,
    // GL_ACTIVE_ATTRIBUTE_MAX_LENGTH,
    // GL_ACTIVE_UNIFORMS,
    // GL_ACTIVE_UNIFORM_BLOCKS,
    // GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH,
    // GL_ACTIVE_UNIFORM_MAX_LENGTH,
    // GL_TRANSFORM_FEEDBACK_BUFFER_MODE,
    // GL_TRANSFORM_FEEDBACK_VARYINGS,
    // GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH,
    // GL_GEOMETRY_VERTICES_OUT,
    // GL_GEOMETRY_INPUT_TYPE,
    // GL_GEOMETRY_OUTPUT_TYPE
}

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{
    /// Creates a program object.
    /// 
    /// Returns 0 if an error occurs creating the program object
    /// otherwise returns a non-zero value by which it can be referenced.
    #[inline(always)]
    pub fn create(&self)->u32{
        unsafe{
            transmute::<usize,fn()->u32>(self.glCreateProgram)()
        }
    }

    /// Deletes a program object.
    /// 
    /// `GLError::InvalidValue` is generated if program is not a value generated by OpenGL.
    #[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)
    }

    /// Links a program object.
    #[inline(always)]
    pub unsafe fn link(&self,program_id:u32){
        transmute::<usize,fn(u32)>(self.glLinkProgram)(program_id)
    }

    /// Returns a parameter from a program object.
    #[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)
    }

    /// Returns the information log for a program object.
    /// 
    /// Fill `log` without allocation.
    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);
    }

    /// Returns the location of a uniform variable.
    /// 
    /// `name` is a null terminated string.
    #[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())
    }

    /// Retrieves the index of a named uniform block.
    /// 
    /// `name` is a null terminated string.
    #[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())
    }

    /// Assigns a binding point to an active uniform block.
    #[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)
    }
}