diff options
Diffstat (limited to 'components/script/dom/webglvertexarrayobjectoes.rs')
-rw-r--r-- | components/script/dom/webglvertexarrayobjectoes.rs | 251 |
1 files changed, 20 insertions, 231 deletions
diff --git a/components/script/dom/webglvertexarrayobjectoes.rs b/components/script/dom/webglvertexarrayobjectoes.rs index 1d802968ae1..2c03f084031 100644 --- a/components/script/dom/webglvertexarrayobjectoes.rs +++ b/components/script/dom/webglvertexarrayobjectoes.rs @@ -2,41 +2,28 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use crate::dom::bindings::cell::{ref_filter_map, DomRefCell, Ref}; -use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants; +use crate::dom::bindings::cell::Ref; use crate::dom::bindings::codegen::Bindings::WebGLVertexArrayObjectOESBinding; -use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; -use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom}; +use crate::dom::bindings::root::{DomRoot, MutNullableDom}; +use crate::dom::vertexarrayobject::{VertexArrayObject, VertexAttribData}; use crate::dom::webglbuffer::WebGLBuffer; use crate::dom::webglobject::WebGLObject; use crate::dom::webglrenderingcontext::WebGLRenderingContext; -use canvas_traits::webgl::{ - ActiveAttribInfo, WebGLCommand, WebGLError, WebGLResult, WebGLVertexArrayId, -}; +use canvas_traits::webgl::{ActiveAttribInfo, WebGLResult, WebGLVertexArrayId}; use dom_struct::dom_struct; -use std::cell::Cell; #[dom_struct] pub struct WebGLVertexArrayObjectOES { webgl_object_: WebGLObject, - id: Option<WebGLVertexArrayId>, - ever_bound: Cell<bool>, - is_deleted: Cell<bool>, - vertex_attribs: DomRefCell<Box<[VertexAttribData]>>, - element_array_buffer: MutNullableDom<WebGLBuffer>, + array_object: VertexArrayObject, } impl WebGLVertexArrayObjectOES { fn new_inherited(context: &WebGLRenderingContext, id: Option<WebGLVertexArrayId>) -> Self { - let max_vertex_attribs = context.limits().max_vertex_attribs as usize; Self { webgl_object_: WebGLObject::new_inherited(context), - id, - ever_bound: Default::default(), - is_deleted: Default::default(), - vertex_attribs: DomRefCell::new(vec![Default::default(); max_vertex_attribs].into()), - element_array_buffer: Default::default(), + array_object: VertexArrayObject::new(context, id), } } @@ -49,54 +36,31 @@ impl WebGLVertexArrayObjectOES { } pub fn id(&self) -> Option<WebGLVertexArrayId> { - self.id + self.array_object.id() } pub fn is_deleted(&self) -> bool { - self.is_deleted.get() + self.array_object.is_deleted() } pub fn delete(&self, fallible: bool) { - assert!(self.id.is_some()); - if self.is_deleted.get() { - return; - } - self.is_deleted.set(true); - - let context = self.upcast::<WebGLObject>().context(); - let cmd = WebGLCommand::DeleteVertexArray(self.id.unwrap()); - if fallible { - context.send_command_ignored(cmd); - } else { - context.send_command(cmd); - } - - for attrib_data in &**self.vertex_attribs.borrow() { - if let Some(buffer) = attrib_data.buffer() { - buffer.decrement_attached_counter(); - } - } - if let Some(buffer) = self.element_array_buffer.get() { - buffer.decrement_attached_counter(); - } + self.array_object.delete(fallible); } pub fn ever_bound(&self) -> bool { - return self.ever_bound.get(); + self.array_object.ever_bound() } pub fn set_ever_bound(&self) { - self.ever_bound.set(true); + self.array_object.set_ever_bound(); } pub fn element_array_buffer(&self) -> &MutNullableDom<WebGLBuffer> { - &self.element_array_buffer + self.array_object.element_array_buffer() } pub fn get_vertex_attrib(&self, index: u32) -> Option<Ref<VertexAttribData>> { - ref_filter_map(self.vertex_attribs.borrow(), |attribs| { - attribs.get(index as usize) - }) + self.array_object.get_vertex_attrib(index) } pub fn vertex_attrib_pointer( @@ -108,93 +72,20 @@ impl WebGLVertexArrayObjectOES { stride: i32, offset: i64, ) -> WebGLResult<()> { - let mut attribs = self.vertex_attribs.borrow_mut(); - let data = attribs - .get_mut(index as usize) - .ok_or(WebGLError::InvalidValue)?; - - if size < 1 || size > 4 { - return Err(WebGLError::InvalidValue); - } - - // https://www.khronos.org/registry/webgl/specs/latest/1.0/#BUFFER_OFFSET_AND_STRIDE - // https://www.khronos.org/registry/webgl/specs/latest/1.0/#VERTEX_STRIDE - if stride < 0 || stride > 255 || offset < 0 { - return Err(WebGLError::InvalidValue); - } - let bytes_per_component: i32 = match type_ { - constants::BYTE | constants::UNSIGNED_BYTE => 1, - constants::SHORT | constants::UNSIGNED_SHORT => 2, - constants::FLOAT => 4, - _ => return Err(WebGLError::InvalidEnum), - }; - if offset % bytes_per_component as i64 > 0 || stride % bytes_per_component > 0 { - return Err(WebGLError::InvalidOperation); - } - - let context = self.upcast::<WebGLObject>().context(); - let buffer = context.array_buffer(); - match buffer { - Some(ref buffer) => buffer.increment_attached_counter(), - None if offset != 0 => { - // https://github.com/KhronosGroup/WebGL/pull/2228 - return Err(WebGLError::InvalidOperation); - }, - _ => {}, - } - context.send_command(WebGLCommand::VertexAttribPointer( - index, - size, - type_, - normalized, - stride, - offset as u32, - )); - if let Some(old) = data.buffer() { - old.decrement_attached_counter(); - } - - *data = VertexAttribData { - enabled_as_array: data.enabled_as_array, - size: size as u8, - type_, - bytes_per_vertex: size as u8 * bytes_per_component as u8, - normalized, - stride: stride as u8, - offset: offset as u32, - buffer: buffer.map(|b| Dom::from_ref(&*b)), - divisor: data.divisor, - }; - - Ok(()) + self.array_object + .vertex_attrib_pointer(index, size, type_, normalized, stride, offset) } pub fn vertex_attrib_divisor(&self, index: u32, value: u32) { - self.vertex_attribs.borrow_mut()[index as usize].divisor = value; + self.array_object.vertex_attrib_divisor(index, value); } pub fn enabled_vertex_attrib_array(&self, index: u32, value: bool) { - self.vertex_attribs.borrow_mut()[index as usize].enabled_as_array = value; + self.array_object.enabled_vertex_attrib_array(index, value); } pub fn unbind_buffer(&self, buffer: &WebGLBuffer) { - for attrib in &mut **self.vertex_attribs.borrow_mut() { - if let Some(b) = attrib.buffer() { - if b.id() != buffer.id() { - continue; - } - b.decrement_attached_counter(); - } - attrib.buffer = None; - } - if self - .element_array_buffer - .get() - .map_or(false, |b| buffer == &*b) - { - buffer.decrement_attached_counter(); - self.element_array_buffer.set(None); - } + self.array_object.unbind_buffer(buffer); } pub fn validate_for_draw( @@ -203,109 +94,7 @@ impl WebGLVertexArrayObjectOES { instance_count: u32, active_attribs: &[ActiveAttribInfo], ) -> WebGLResult<()> { - // TODO(nox): Cache limits per VAO. - let attribs = self.vertex_attribs.borrow(); - // https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.2 - if attribs - .iter() - .any(|data| data.enabled_as_array && data.buffer.is_none()) - { - return Err(WebGLError::InvalidOperation); - } - let mut has_active_attrib = false; - let mut has_divisor_0 = false; - for active_info in active_attribs { - if active_info.location < 0 { - continue; - } - has_active_attrib = true; - let attrib = &attribs[active_info.location as usize]; - if attrib.divisor == 0 { - has_divisor_0 = true; - } - if !attrib.enabled_as_array { - continue; - } - // https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.6 - if required_len > 0 && instance_count > 0 { - let max_vertices = attrib.max_vertices(); - if attrib.divisor == 0 { - if max_vertices < required_len { - return Err(WebGLError::InvalidOperation); - } - } else if max_vertices - .checked_mul(attrib.divisor) - .map_or(false, |v| v < instance_count) - { - return Err(WebGLError::InvalidOperation); - } - } - } - if has_active_attrib && !has_divisor_0 { - return Err(WebGLError::InvalidOperation); - } - Ok(()) - } -} - -impl Drop for WebGLVertexArrayObjectOES { - fn drop(&mut self) { - if self.id.is_some() { - self.delete(true); - } - } -} - -#[derive(Clone, JSTraceable, MallocSizeOf)] -#[unrooted_must_root_lint::must_root] -pub struct VertexAttribData { - pub enabled_as_array: bool, - pub size: u8, - pub type_: u32, - bytes_per_vertex: u8, - pub normalized: bool, - pub stride: u8, - pub offset: u32, - pub buffer: Option<Dom<WebGLBuffer>>, - pub divisor: u32, -} - -impl Default for VertexAttribData { - #[allow(unrooted_must_root)] - fn default() -> Self { - Self { - enabled_as_array: false, - size: 4, - type_: constants::FLOAT, - bytes_per_vertex: 16, - normalized: false, - stride: 0, - offset: 0, - buffer: None, - divisor: 0, - } - } -} - -impl VertexAttribData { - pub fn buffer(&self) -> Option<&WebGLBuffer> { - self.buffer.as_ref().map(|b| &**b) - } - - fn max_vertices(&self) -> u32 { - let capacity = (self.buffer().unwrap().capacity() as u32).saturating_sub(self.offset); - if capacity < self.bytes_per_vertex as u32 { - 0 - } else if self.stride == 0 { - capacity / self.bytes_per_vertex as u32 - } else if self.stride < self.bytes_per_vertex { - (capacity - (self.bytes_per_vertex - self.stride) as u32) / self.stride as u32 - } else { - let mut max = capacity / self.stride as u32; - if capacity % self.stride as u32 >= self.bytes_per_vertex as u32 { - max += 1; - } - max - } + self.array_object + .validate_for_draw(required_len, instance_count, active_attribs) } } |