mallumo-gls 0.43.0

Small low level library for modern (4.5 Core) OpenGL
Documentation
use super::*;
use super::errors::*;

use std::ptr;
use std::ffi::CString;
use std::mem::uninitialized;

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct ShaderId(u32);

impl From<ShaderId> for u32 {
    fn from(shader_id: ShaderId) -> Self {
        shader_id.0
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ShaderParameter {
    ShaderType,
    DeleteStatus,
    CompileStatus,
    InfoLogLength,
    ShaderSourceLength,
}

impl From<ShaderParameter> for u32 {
    fn from(shader_parameter: ShaderParameter) -> Self {
        use self::ShaderParameter::*;
        match shader_parameter {
            ShaderType => gl::SHADER_TYPE,
            DeleteStatus => gl::DELETE_STATUS,
            CompileStatus => gl::COMPILE_STATUS,
            InfoLogLength => gl::INFO_LOG_LENGTH,
            ShaderSourceLength => gl::SHADER_SOURCE_LENGTH,
        }
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ShaderType {
    Vertex,
    Fragment,
    Geometry,
    TessellationEvaluation,
    TessellationControl,
    Compute,
}

impl From<ShaderType> for u32 {
    fn from(shader_type: ShaderType) -> Self {
        match shader_type {
            ShaderType::Vertex => gl::VERTEX_SHADER,
            ShaderType::Fragment => gl::FRAGMENT_SHADER,
            ShaderType::Geometry => gl::GEOMETRY_SHADER,
            ShaderType::TessellationEvaluation => gl::TESS_EVALUATION_SHADER,
            ShaderType::TessellationControl => gl::TESS_CONTROL_SHADER,
            ShaderType::Compute => gl::COMPUTE_SHADER,
        }
    }
}

pub unsafe fn create_shader(shader_type: ShaderType) -> ShaderId {
    ShaderId(gl::CreateShader(shader_type.into()))
}

pub unsafe fn shader_source<T: AsRef<str>>(id: ShaderId, sources: &[T]) {
    let mut source: String = String::new();
    for s in sources {
        source.push_str(s.as_ref());
    }
    let source_cstr = CString::new(source.as_bytes()).unwrap();

    gl::ShaderSource(id.into(), 1, [source_cstr.as_ptr()].as_ptr(), ptr::null());
}

pub unsafe fn compile_shader(id: ShaderId) {
    gl::CompileShader(id.into());
}

pub unsafe fn get_shader(id: ShaderId, parameter: ShaderParameter) -> i32 {
    let mut value: gl::types::GLint = uninitialized();

    gl::GetShaderiv(id.into(), parameter.into(), &mut value);

    value
}

pub unsafe fn get_shader_info_log(id: ShaderId) -> Result<String> {
    let mut error_log_size: gl::types::GLint = get_shader(id.into(), ShaderParameter::InfoLogLength);

    let mut error_log: Vec<u8> = Vec::with_capacity(error_log_size as usize);
    gl::GetShaderInfoLog(
        id.into(),
        error_log_size,
        &mut error_log_size,
        error_log.as_mut_ptr() as *mut gl::types::GLchar,
    );

    error_log.set_len(error_log_size as usize);
    let string = match String::from_utf8(error_log) {
        Ok(s) => s,
        Err(_) => bail!("Could not convert log"),
    };

    Ok(string)
}

pub unsafe fn delete_shader(id: ShaderId) {
    gl::DeleteShader(id.into())
}

pub unsafe fn get_shader_compiled(id: ShaderId) -> bool {
    get_shader(id.into(), ShaderParameter::CompileStatus) == 1
}

pub unsafe fn shader_binary(id: ShaderId, data: &[u8]) -> Result<()> {
    gl::ShaderBinary(
        1,
        &(id.0) as &u32 as *const u32,
        gl::SHADER_BINARY_FORMAT_SPIR_V_ARB,
        data.as_ptr() as *const ::std::os::raw::c_void,
        data.len() as i32,
    );

    get_error(())
}

pub unsafe fn specialize_shader(id: ShaderId) -> Result<()> {
    let entry_point = ::std::ffi::CString::new("main").unwrap();
    gl::SpecializeShaderARB(
        id.into(),
        entry_point.as_ptr(),
        0,
        ::std::ptr::null(),
        ::std::ptr::null(),
    );

    get_error(())
}