use std::marker::PhantomData;
use once_cell::unsync::OnceCell;
use web_sys::{WebGlProgram, WebGlShader, WebGlUniformLocation};
use crate::{AttributeType, Context, UniformType};
pub struct ProgramData {
#[doc(hidden)]
pub program: WebGlProgram,
#[doc(hidden)]
pub vertex_shader: WebGlShader,
#[doc(hidden)]
pub fragment_shader: WebGlShader,
}
pub struct Attribute<T: AttributeType> {
location: OnceCell<u32>,
_ph: PhantomData<&'static T>,
}
impl<T: AttributeType> Attribute<T> {
#[doc(hidden)]
pub fn create_from_macro() -> Self {
Self {
location: OnceCell::new(),
_ph: PhantomData,
}
}
pub fn get_location(&self, context: &Context, program: &ProgramData, name: &str) -> u32 {
*self.location.get_or_init(|| {
let location = context.native.get_attrib_location(&program.program, name);
let location = location as u32;
context.native.enable_vertex_attrib_array(location);
location
})
}
}
pub struct Uniform<T: UniformType> {
location: OnceCell<Option<WebGlUniformLocation>>,
_ph: PhantomData<&'static T>,
}
impl<T: UniformType> Uniform<T> {
#[doc(hidden)]
pub fn create_from_macro() -> Self {
Self {
location: OnceCell::new(),
_ph: PhantomData,
}
}
pub fn get_location<'t>(
&'t self,
context: &Context,
program: &ProgramData,
name: &str,
) -> Option<&'t WebGlUniformLocation> {
self.location
.get_or_init(|| context.native.get_uniform_location(&program.program, name))
.as_ref()
}
}