use super::GL;
use std::rc::Rc;
pub struct Target<C, const N: u32>(pub Rc<C>);
use core::ops::Deref;
impl<C, const N: u32> Deref for Target<C, N> {
type Target = C;
fn deref(&self) -> &Self::Target {
&self.0
}
}
pub struct TextureTarget<C, const N: u32>(Rc<C>);
impl<C, const N: u32> Deref for TextureTarget<C, N> {
type Target = C;
fn deref(&self) -> &Self::Target {
&self.0
}
}
pub struct Context {
pub gl: Rc<GL>,
pub array_buffer: Target<GL, { GL::ARRAY_BUFFER }>,
pub copy_read_buffer: Target<GL, { GL::COPY_READ_BUFFER }>,
pub copy_write_buffer: Target<GL, { GL::COPY_WRITE_BUFFER }>,
pub element_array_buffer: Target<GL, { GL::ELEMENT_ARRAY_BUFFER }>,
pub pixel_pack_buffer: Target<GL, { GL::PIXEL_PACK_BUFFER }>,
pub pixel_unpack_buffer: Target<GL, { GL::PIXEL_UNPACK_BUFFER }>,
pub transform_feedback_buffer: Target<GL, { GL::TRANSFORM_FEEDBACK_BUFFER }>,
pub uniform_buffer: Target<GL, { GL::UNIFORM_BUFFER }>,
pub texture_2d: TextureTarget<GL, { GL::TEXTURE_2D }>,
pub texture_cube_map: TextureTarget<GL, { GL::TEXTURE_CUBE_MAP }>,
pub texture_3d: TextureTarget<GL, { GL::TEXTURE_3D }>,
pub texture_2d_array: TextureTarget<GL, { GL::TEXTURE_3D }>,
}
impl Deref for Context {
type Target = GL;
fn deref(&self) -> &Self::Target {
&self.gl
}
}
impl From<GL> for Context {
fn from(gl: GL) -> Context {
let rc = Rc::new(gl);
Self {
gl: rc.clone(),
array_buffer: Target(rc.clone()),
copy_read_buffer: Target(rc.clone()),
copy_write_buffer: Target(rc.clone()),
element_array_buffer: Target(rc.clone()),
pixel_pack_buffer: Target(rc.clone()),
pixel_unpack_buffer: Target(rc.clone()),
transform_feedback_buffer: Target(rc.clone()),
uniform_buffer: Target(rc.clone()),
texture_2d: TextureTarget(rc.clone()),
texture_cube_map: TextureTarget(rc.clone()),
texture_3d: TextureTarget(rc.clone()),
texture_2d_array: TextureTarget(rc.clone()),
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum Error {
InvalidEnum,
InvalidValue,
InvalidOperation,
InvalidFramebufferOperation,
OutOfMemory,
ContextLost,
}
use core::fmt;
impl fmt::Display for Error {
fn fmt(&self, format: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write! {format, "{:?}", self}
}
}
impl std::error::Error for Error {}
pub trait GLError {
type Error;
fn error(&self) -> Result<(), Self::Error>;
}
impl GLError for GL {
type Error = Error;
fn error(&self) -> Result<(), Error> {
match self.get_error() {
GL::INVALID_ENUM => Err(Error::InvalidEnum),
GL::INVALID_VALUE => Err(Error::InvalidValue),
GL::INVALID_OPERATION => Err(Error::InvalidOperation),
GL::INVALID_FRAMEBUFFER_OPERATION => Err(Error::InvalidFramebufferOperation),
GL::OUT_OF_MEMORY => Err(Error::OutOfMemory),
GL::CONTEXT_LOST_WEBGL => Err(Error::ContextLost),
_ => Ok(()),
}
}
}
use super::attribute::GLType;
use core::ops::Range;
impl Context {
pub fn draw_arrays(&mut self, mode: u32, range: Range<i32>) {
self.gl
.draw_arrays(mode, range.start, range.end - range.start);
}
pub fn draw_elements<T>(&mut self, mode: u32, range: Range<i32>)
where
T: GLType,
{
use std::mem::size_of;
self.gl.draw_elements_with_i32(
mode,
range.end - range.start,
T::TYPE,
range.start * size_of::<T>() as i32,
);
}
}