1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use super::{AttributeOptions, BufferTarget, Id, WebGlRenderer};
use crate::errors::{Error, NativeError};
use wasm_bindgen::JsCast;
use web_sys::OesVertexArrayObject;
use web_sys::WebGlVertexArrayObject;
use web_sys::{WebGl2RenderingContext, WebGlRenderingContext};
pub struct VertexArray<'a> {
pub attribute_name: &'a str,
pub buffer_id: Id,
pub opts: &'a AttributeOptions,
}
impl<'a> VertexArray<'a> {
pub fn new(attribute_name: &'a str, buffer_id: Id, opts: &'a AttributeOptions) -> Self {
Self {
attribute_name,
buffer_id,
opts,
}
}
}
macro_rules! impl_renderer {
($($type:ty { $($defs:tt)* })+) => {
$(impl WebGlRenderer<$type> {
pub fn release_vertex_array(&self) -> Result<(), Error> {
self._bind_vertex_array(None, None)
}
pub fn activate_vertex_array(&self, vao_id:Id) -> Result<(), Error> {
if Some(vao_id) != self.current_vao_id.get() {
if let Some(vao) = self.vao_lookup.get(vao_id) {
self._bind_vertex_array(Some(vao_id), Some(&vao))
} else {
Err(Error::from(NativeError::VertexArrayMissing))
}
} else {
Ok(())
}
}
pub fn assign_vertex_array(&self, vao_id:Id, element_buffer_id:Option<Id>, configs:&[VertexArray]) -> Result<(), Error> {
let result = if let Some(vao) = self.vao_lookup.get(vao_id) {
self._bind_vertex_array(Some(vao_id), Some(&vao))?;
if let Some(element_buffer_id) = element_buffer_id {
self._bind_buffer_nocheck(element_buffer_id, BufferTarget::ElementArrayBuffer)?;
}
for config in configs {
self._bind_buffer_nocheck(config.buffer_id, BufferTarget::ArrayBuffer)?;
self.activate_attribute(&config.attribute_name, &config.opts)?;
}
Ok(())
} else {
Err(Error::from(NativeError::VertexArrayMissing))
};
self.release_vertex_array()?;
result
}
$($defs)*
})+
};
}
impl_renderer! {
WebGlRenderingContext{
pub fn register_extension_vertex_array(&mut self) -> Result<&OesVertexArrayObject, Error> {
self.register_extension("OES_vertex_array_object")
.map(|ext| ext.unchecked_ref::<OesVertexArrayObject>())
}
fn _get_extension_vertex_array(&self) -> Result<&OesVertexArrayObject, Error> {
self.get_extension("OES_vertex_array_object")
.map(|ext| ext.unchecked_ref::<OesVertexArrayObject>())
}
fn _bind_vertex_array(&self, id:Option<Id>, vao:Option<&WebGlVertexArrayObject>) -> Result<(), Error> {
let ext = self._get_extension_vertex_array()?;
ext.bind_vertex_array_oes(vao);
self.current_vao_id.set(id);
Ok(())
}
pub fn create_vertex_array(&mut self) -> Result<Id, Error> {
let ext = self._get_extension_vertex_array()?;
let vao = ext.create_vertex_array_oes().ok_or(Error::from(NativeError::VertexArrayCreate))?;
let id = self.vao_lookup.insert(vao);
Ok(id)
}
}
WebGl2RenderingContext{
fn _bind_vertex_array(&self, id:Option<Id>, vao:Option<&WebGlVertexArrayObject>) -> Result<(), Error> {
self.gl.bind_vertex_array(vao);
self.current_vao_id.set(id);
Ok(())
}
pub fn create_vertex_array(&mut self) -> Result<Id, Error> {
let vao = self.gl.create_vertex_array().ok_or(Error::from(NativeError::VertexArrayCreate))?;
let id = self.vao_lookup.insert(vao);
Ok(id)
}
}
}