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);
}
}
}