pel 0.1.0

OpenGL backed framebuffer
Documentation
use std::{
    ffi::{CStr, CString},
    ptr,
};

use ogl33::{
    consts::{GL_COMPILE_STATUS, GL_FALSE, GL_INFO_LOG_LENGTH},
    functions::{glCompileShader, glCreateShader, glDeleteShader, glGetShaderInfoLog, glGetShaderiv, glShaderSource},
    types::{GLchar, GLenum, GLint, GLuint},
};

use crate::Error;

use super::util;

pub struct Shader {
    id: GLuint,
}

impl Shader {
    pub(crate) fn compile(src: &CStr, shader_type: GLenum) -> crate::Result<Self> {
        let id: GLuint = unsafe { glCreateShader(shader_type) };
        unsafe {
            glShaderSource(id, 1, &src.as_ptr(), ptr::null());
            glCompileShader(id);
        }

        let mut status: GLint = GL_FALSE as GLint;
        unsafe {
            glGetShaderiv(id, GL_COMPILE_STATUS, &mut status);
        }

        if status == GL_FALSE as GLint {
            let mut len: GLint = 0;
            unsafe {
                glGetShaderiv(id, GL_INFO_LOG_LENGTH, &mut len);
            }

            let info = unsafe {
                let info: *mut GLchar = util::make_gl_str(len);
                glGetShaderInfoLog(id, len, ptr::null_mut(), info);

                CString::from_raw(info)
            };

            unsafe {
                glDeleteShader(id);
            }

            Err(Error::CompileShader(info.to_string_lossy().into_owned()))
        } else {
            Ok(Self { id })
        }
    }

    pub(crate) fn id(&self) -> GLuint {
        self.id
    }
}

impl Drop for Shader {
    fn drop(&mut self) {
        unsafe {
            glDeleteShader(self.id);
        }
    }
}