From 1b4a3d8987077ce003ab0755b33663bda7f31935 Mon Sep 17 00:00:00 2001 From: Istvan Miklos Date: Thu, 5 Mar 2020 15:51:18 +0100 Subject: [PATCH] Add VertexArrayObject support for WebGL2 The implementation was already in place for OpenGL ES. My approach with this patch is to add support for WebGL2 by sharing the implementation between the WebGL2 and GLES. --- components/script/dom/mod.rs | 2 + components/script/dom/vertexarrayobject.rs | 296 ++++++++++++++++++ .../script/dom/webgl2renderingcontext.rs | 42 ++- .../script/dom/webglrenderingcontext.rs | 294 ++++++++++++----- .../script/dom/webglvertexarrayobject.rs | 100 ++++++ .../script/dom/webglvertexarrayobjectoes.rs | 251 ++------------- .../dom/webidls/WebGL2RenderingContext.webidl | 8 +- .../dom/webidls/WebGLVertexArrayObject.webidl | 11 + .../attribs/gl-vertex-attrib-render.html.ini | 8 - .../buffer-data-array-buffer-delete.html.ini | 8 - ...ncorrect-context-object-behaviour.html.ini | 2 +- .../conformance2/context/methods-2.html.ini | 12 - .../attrib-location-length-limits.html.ini | 4 +- .../conformance2/misc/expando-loss-2.html.ini | 5 +- .../misc/instanceof-test.html.ini | 4 - .../misc/object-deletion-behaviour-2.html.ini | 5 - .../instanced-rendering-bug.html.ini | 5 - .../state/gl-object-get-calls.html.ini | 10 + .../simultaneous_binding.html.ini | 114 +++++++ .../vertex-array-object.html.ini | 5 - 20 files changed, 815 insertions(+), 371 deletions(-) create mode 100644 components/script/dom/vertexarrayobject.rs create mode 100644 components/script/dom/webglvertexarrayobject.rs create mode 100644 components/script/dom/webidls/WebGLVertexArrayObject.webidl delete mode 100644 tests/wpt/webgl/meta/conformance/attribs/gl-vertex-attrib-render.html.ini delete mode 100644 tests/wpt/webgl/meta/conformance/buffers/buffer-data-array-buffer-delete.html.ini delete mode 100644 tests/wpt/webgl/meta/conformance2/misc/instanceof-test.html.ini delete mode 100644 tests/wpt/webgl/meta/conformance2/misc/object-deletion-behaviour-2.html.ini delete mode 100644 tests/wpt/webgl/meta/conformance2/rendering/instanced-rendering-bug.html.ini delete mode 100644 tests/wpt/webgl/meta/conformance2/vertex_arrays/vertex-array-object.html.ini diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 0e1b4789ad4..3691ba5a299 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -527,6 +527,7 @@ pub mod userscripts; pub mod validation; pub mod validitystate; pub mod values; +pub mod vertexarrayobject; pub mod videotrack; pub mod videotracklist; pub mod virtualmethods; @@ -560,6 +561,7 @@ pub mod webglsync; pub mod webgltexture; pub mod webgltransformfeedback; pub mod webgluniformlocation; +pub mod webglvertexarrayobject; pub mod webglvertexarrayobjectoes; pub mod websocket; pub mod wheelevent; diff --git a/components/script/dom/vertexarrayobject.rs b/components/script/dom/vertexarrayobject.rs new file mode 100644 index 00000000000..025cff9194a --- /dev/null +++ b/components/script/dom/vertexarrayobject.rs @@ -0,0 +1,296 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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::root::{Dom, MutNullableDom}; +use crate::dom::webglbuffer::WebGLBuffer; +use crate::dom::webglrenderingcontext::WebGLRenderingContext; +use canvas_traits::webgl::{ + ActiveAttribInfo, WebGLCommand, WebGLError, WebGLResult, WebGLVertexArrayId, +}; +use std::cell::Cell; + +#[derive(JSTraceable, MallocSizeOf)] +#[unrooted_must_root_lint::must_root] +pub struct VertexArrayObject { + context: Dom, + id: Option, + ever_bound: Cell, + is_deleted: Cell, + vertex_attribs: DomRefCell>, + element_array_buffer: MutNullableDom, +} + +impl VertexArrayObject { + pub fn new(context: &WebGLRenderingContext, id: Option) -> Self { + let max_vertex_attribs = context.limits().max_vertex_attribs as usize; + Self { + context: Dom::from_ref(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(), + } + } + + pub fn id(&self) -> Option { + self.id + } + + pub fn is_deleted(&self) -> bool { + self.is_deleted.get() + } + + pub fn delete(&self, fallible: bool) { + assert!(self.id.is_some()); + if self.is_deleted.get() { + return; + } + self.is_deleted.set(true); + let cmd = WebGLCommand::DeleteVertexArray(self.id.unwrap()); + if fallible { + self.context.send_command_ignored(cmd); + } else { + self.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(); + } + } + + pub fn ever_bound(&self) -> bool { + return self.ever_bound.get(); + } + + pub fn set_ever_bound(&self) { + self.ever_bound.set(true); + } + + pub fn element_array_buffer(&self) -> &MutNullableDom { + &self.element_array_buffer + } + + pub fn get_vertex_attrib(&self, index: u32) -> Option> { + ref_filter_map(self.vertex_attribs.borrow(), |attribs| { + attribs.get(index as usize) + }) + } + + pub fn vertex_attrib_pointer( + &self, + index: u32, + size: i32, + type_: u32, + normalized: bool, + 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 buffer = self.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); + }, + _ => {}, + } + self.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(()) + } + + pub fn vertex_attrib_divisor(&self, index: u32, value: u32) { + self.vertex_attribs.borrow_mut()[index as usize].divisor = value; + } + + pub fn enabled_vertex_attrib_array(&self, index: u32, value: bool) { + self.vertex_attribs.borrow_mut()[index as usize].enabled_as_array = 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); + } + } + + pub fn validate_for_draw( + &self, + required_len: u32, + 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 VertexArrayObject { + 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>, + 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) + } + + pub 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 + } + } +} diff --git a/components/script/dom/webgl2renderingcontext.rs b/components/script/dom/webgl2renderingcontext.rs index 1c458778a1c..699631de5d2 100644 --- a/components/script/dom/webgl2renderingcontext.rs +++ b/components/script/dom/webgl2renderingcontext.rs @@ -36,6 +36,7 @@ use crate::dom::webglsync::WebGLSync; use crate::dom::webgltexture::WebGLTexture; use crate::dom::webgltransformfeedback::WebGLTransformFeedback; use crate::dom::webgluniformlocation::WebGLUniformLocation; +use crate::dom::webglvertexarrayobject::WebGLVertexArrayObject; use crate::dom::window::Window; use crate::js::conversions::ToJSValConvertible; use crate::script_runtime::JSContext; @@ -181,6 +182,10 @@ impl WebGL2RenderingContext { self.base.recreate(size) } + pub fn current_vao(&self) -> DomRoot { + self.base.current_vao_webgl2() + } + pub fn base_context(&self) -> DomRoot { DomRoot::from_ref(&*self.base) } @@ -193,6 +198,7 @@ impl WebGL2RenderingContext { constants::PIXEL_UNPACK_BUFFER => Ok(self.bound_pixel_unpack_buffer.get()), constants::TRANSFORM_FEEDBACK_BUFFER => Ok(self.bound_transform_feedback_buffer.get()), constants::UNIFORM_BUFFER => Ok(self.bound_uniform_buffer.get()), + constants::ELEMENT_ARRAY_BUFFER => Ok(self.current_vao().element_array_buffer().get()), _ => self.base.bound_buffer(target), } } @@ -777,6 +783,15 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { self.current_transform_feedback.get() ); }, + constants::ELEMENT_ARRAY_BUFFER_BINDING => unsafe { + let buffer = self.current_vao().element_array_buffer().get(); + return optional_root_object_to_js_or_null!(*cx, buffer); + }, + constants::VERTEX_ARRAY_BINDING => unsafe { + let vao = self.current_vao(); + let vao = vao.id().map(|_| &*vao); + return optional_root_object_to_js_or_null!(*cx, vao); + }, // NOTE: DRAW_FRAMEBUFFER_BINDING is the same as FRAMEBUFFER_BINDING, handled on the WebGL1 side constants::READ_FRAMEBUFFER_BINDING => unsafe { return optional_root_object_to_js_or_null!( @@ -942,6 +957,7 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.2 fn BindBuffer(&self, target: u32, buffer: Option<&WebGLBuffer>) { + let current_vao; let slot = match target { constants::COPY_READ_BUFFER => &self.bound_copy_read_buffer, constants::COPY_WRITE_BUFFER => &self.bound_copy_write_buffer, @@ -949,6 +965,10 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { constants::PIXEL_UNPACK_BUFFER => &self.bound_pixel_unpack_buffer, constants::TRANSFORM_FEEDBACK_BUFFER => &self.bound_transform_feedback_buffer, constants::UNIFORM_BUFFER => &self.bound_uniform_buffer, + constants::ELEMENT_ARRAY_BUFFER => { + current_vao = self.current_vao(); + current_vao.element_array_buffer() + }, _ => return self.base.BindBuffer(target, buffer), }; self.base.bind_buffer_maybe(&slot, target, buffer); @@ -1409,6 +1429,11 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { self.base.CreateShader(shader_type) } + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.17 + fn CreateVertexArray(&self) -> Option> { + self.base.create_vertex_array_webgl2() + } + /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5 fn DeleteBuffer(&self, buffer: Option<&WebGLBuffer>) { let buffer = match buffer { @@ -1419,7 +1444,7 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { if buffer.is_marked_for_deletion() { return; } - self.base.current_vao().unbind_buffer(buffer); + self.current_vao().unbind_buffer(buffer); self.unbind_from(&self.base.array_buffer_slot(), &buffer); self.unbind_from(&self.bound_copy_read_buffer, &buffer); self.unbind_from(&self.bound_copy_write_buffer, &buffer); @@ -1463,6 +1488,11 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { self.base.DeleteShader(shader) } + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.17 + fn DeleteVertexArray(&self, vertex_array: Option<&WebGLVertexArrayObject>) { + self.base.delete_vertex_array_webgl2(vertex_array); + } + /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11 fn DrawArrays(&self, mode: u32, first: i32, count: i32) { self.base.DrawArrays(mode, first, count) @@ -1662,6 +1692,11 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { self.base.IsTexture(texture) } + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.17 + fn IsVertexArray(&self, vertex_array: Option<&WebGLVertexArrayObject>) -> bool { + self.base.is_vertex_array_webgl2(vertex_array) + } + /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn LineWidth(&self, width: f32) { self.base.LineWidth(width) @@ -3042,6 +3077,11 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { } } + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.17 + fn BindVertexArray(&self, array: Option<&WebGLVertexArrayObject>) { + self.base.bind_vertex_array_webgl2(array); + } + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.13 fn SamplerParameteri(&self, sampler: &WebGLSampler, pname: u32, param: i32) { handle_potential_webgl_error!(self.base, self.base.validate_ownership(sampler), return); diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 65134a631e1..bda7c036d60 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -2,6 +2,7 @@ * 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; use crate::dom::bindings::codegen::Bindings::ANGLEInstancedArraysBinding::ANGLEInstancedArraysConstants; use crate::dom::bindings::codegen::Bindings::EXTBlendMinmaxBinding::EXTBlendMinmaxConstants; use crate::dom::bindings::codegen::Bindings::OESVertexArrayObjectBinding::OESVertexArrayObjectConstants; @@ -26,6 +27,7 @@ use crate::dom::htmlcanvaselement::HTMLCanvasElement; use crate::dom::htmliframeelement::HTMLIFrameElement; use crate::dom::node::{document_from_node, window_from_node, Node, NodeDamage}; use crate::dom::promise::Promise; +use crate::dom::vertexarrayobject::VertexAttribData; use crate::dom::webgl_extensions::WebGLExtensions; use crate::dom::webgl_validations::tex_image_2d::{ CommonCompressedTexImage2DValidatorResult, CommonTexImage2DValidator, @@ -47,6 +49,7 @@ use crate::dom::webglshader::WebGLShader; use crate::dom::webglshaderprecisionformat::WebGLShaderPrecisionFormat; use crate::dom::webgltexture::{TexParameterValue, WebGLTexture}; use crate::dom::webgluniformlocation::WebGLUniformLocation; +use crate::dom::webglvertexarrayobject::WebGLVertexArrayObject; use crate::dom::webglvertexarrayobjectoes::WebGLVertexArrayObjectOES; use crate::dom::window::Window; use crate::script_runtime::JSContext as SafeJSContext; @@ -183,6 +186,8 @@ pub struct WebGLRenderingContext { capabilities: Capabilities, default_vao: DomOnceCell, current_vao: MutNullableDom, + default_vao_webgl2: DomOnceCell, + current_vao_webgl2: MutNullableDom, textures: Textures, api_type: GlType, } @@ -242,6 +247,8 @@ impl WebGLRenderingContext { capabilities: Default::default(), default_vao: Default::default(), current_vao: Default::default(), + default_vao_webgl2: Default::default(), + current_vao_webgl2: Default::default(), textures: Textures::new(max_combined_texture_image_units), api_type: ctx_data.api_type, } @@ -294,6 +301,15 @@ impl WebGLRenderingContext { }) } + pub fn current_vao_webgl2(&self) -> DomRoot { + self.current_vao_webgl2.or_init(|| { + DomRoot::from_ref( + self.default_vao_webgl2 + .init_once(|| WebGLVertexArrayObject::new(self, None)), + ) + }) + } + pub fn recreate(&self, size: Size2D) { let (sender, receiver) = webgl_channel().unwrap(); self.webgl_sender.send_resize(size, sender).unwrap(); @@ -889,11 +905,18 @@ impl WebGLRenderingContext { 0 }; - self.current_vao().validate_for_draw( - required_len, - primcount as u32, - ¤t_program.active_attribs(), - )?; + match self.webgl_version() { + WebGLVersion::WebGL1 => self.current_vao().validate_for_draw( + required_len, + primcount as u32, + ¤t_program.active_attribs(), + )?, + WebGLVersion::WebGL2 => self.current_vao_webgl2().validate_for_draw( + required_len, + primcount as u32, + ¤t_program.active_attribs(), + )?, + }; self.validate_framebuffer()?; @@ -950,11 +973,11 @@ impl WebGLRenderingContext { } let current_program = self.current_program.get().ok_or(InvalidOperation)?; - let array_buffer = self - .current_vao() - .element_array_buffer() - .get() - .ok_or(InvalidOperation)?; + let array_buffer = match self.webgl_version() { + WebGLVersion::WebGL1 => self.current_vao().element_array_buffer().get(), + WebGLVersion::WebGL2 => self.current_vao_webgl2().element_array_buffer().get(), + } + .ok_or(InvalidOperation)?; if count > 0 && primcount > 0 { // This operation cannot overflow in u64 and we know all those values are nonnegative. @@ -965,11 +988,18 @@ impl WebGLRenderingContext { } // TODO(nox): Pass the correct number of vertices required. - self.current_vao().validate_for_draw( - 0, - primcount as u32, - ¤t_program.active_attribs(), - )?; + match self.webgl_version() { + WebGLVersion::WebGL1 => self.current_vao().validate_for_draw( + 0, + primcount as u32, + ¤t_program.active_attribs(), + )?, + WebGLVersion::WebGL2 => self.current_vao_webgl2().validate_for_draw( + 0, + primcount as u32, + ¤t_program.active_attribs(), + )?, + }; self.validate_framebuffer()?; @@ -1003,7 +1033,12 @@ impl WebGLRenderingContext { return self.webgl_error(InvalidValue); } - self.current_vao().vertex_attrib_divisor(index, divisor); + match self.webgl_version() { + WebGLVersion::WebGL1 => self.current_vao().vertex_attrib_divisor(index, divisor), + WebGLVersion::WebGL2 => self + .current_vao_webgl2() + .vertex_attrib_divisor(index, divisor), + }; self.send_command(WebGLCommand::VertexAttribDivisor { index, divisor }); } @@ -1066,6 +1101,15 @@ impl WebGLRenderingContext { .map(|id| WebGLVertexArrayObjectOES::new(self, Some(id))) } + pub fn create_vertex_array_webgl2(&self) -> Option> { + let (sender, receiver) = webgl_channel().unwrap(); + self.send_command(WebGLCommand::CreateVertexArray(sender)); + receiver + .recv() + .unwrap() + .map(|id| WebGLVertexArrayObject::new(self, Some(id))) + } + pub fn delete_vertex_array(&self, vao: Option<&WebGLVertexArrayObjectOES>) { if let Some(vao) = vao { handle_potential_webgl_error!(self, self.validate_ownership(vao), return); @@ -1084,6 +1128,24 @@ impl WebGLRenderingContext { } } + pub fn delete_vertex_array_webgl2(&self, vao: Option<&WebGLVertexArrayObject>) { + if let Some(vao) = vao { + handle_potential_webgl_error!(self, self.validate_ownership(vao), return); + // The default vertex array has no id and should never be passed around. + assert!(vao.id().is_some()); + if vao.is_deleted() { + return; + } + if vao == &*self.current_vao_webgl2() { + // Setting it to None will make self.current_vao() reset it to the default one + // next time it is called. + self.current_vao_webgl2.set(None); + self.send_command(WebGLCommand::BindVertexArray(None)); + } + vao.delete(false); + } + } + pub fn is_vertex_array(&self, vao: Option<&WebGLVertexArrayObjectOES>) -> bool { vao.map_or(false, |vao| { // The default vertex array has no id and should never be passed around. @@ -1092,6 +1154,14 @@ impl WebGLRenderingContext { }) } + pub fn is_vertex_array_webgl2(&self, vao: Option<&WebGLVertexArrayObject>) -> bool { + vao.map_or(false, |vao| { + // The default vertex array has no id and should never be passed around. + assert!(vao.id().is_some()); + self.validate_ownership(vao).is_ok() && vao.ever_bound() && !vao.is_deleted() + }) + } + pub fn bind_vertex_array(&self, vao: Option<&WebGLVertexArrayObjectOES>) { if let Some(vao) = vao { // The default vertex array has no id and should never be passed around. @@ -1108,6 +1178,22 @@ impl WebGLRenderingContext { self.current_vao.set(vao); } + pub fn bind_vertex_array_webgl2(&self, vao: Option<&WebGLVertexArrayObject>) { + if let Some(vao) = vao { + // The default vertex array has no id and should never be passed around. + assert!(vao.id().is_some()); + handle_potential_webgl_error!(self, self.validate_ownership(vao), return); + if vao.is_deleted() { + return self.webgl_error(InvalidOperation); + } + vao.set_ever_bound(); + } + self.send_command(WebGLCommand::BindVertexArray(vao.and_then(|vao| vao.id()))); + // Setting it to None will make self.current_vao() reset it to the default one + // next time it is called. + self.current_vao_webgl2.set(vao); + } + fn validate_blend_mode(&self, mode: u32) -> WebGLResult<()> { match mode { constants::FUNC_ADD | constants::FUNC_SUBTRACT | constants::FUNC_REVERSE_SUBTRACT => { @@ -2552,9 +2638,14 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { if attrib_id >= self.limits.max_vertex_attribs { return self.webgl_error(InvalidValue); } - - self.current_vao() - .enabled_vertex_attrib_array(attrib_id, true); + match self.webgl_version() { + WebGLVersion::WebGL1 => self + .current_vao() + .enabled_vertex_attrib_array(attrib_id, true), + WebGLVersion::WebGL2 => self + .current_vao_webgl2() + .enabled_vertex_attrib_array(attrib_id, true), + }; self.send_command(WebGLCommand::EnableVertexAttribArray(attrib_id)); } @@ -2563,9 +2654,14 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { if attrib_id >= self.limits.max_vertex_attribs { return self.webgl_error(InvalidValue); } - - self.current_vao() - .enabled_vertex_attrib_array(attrib_id, false); + match self.webgl_version() { + WebGLVersion::WebGL1 => self + .current_vao() + .enabled_vertex_attrib_array(attrib_id, false), + WebGLVersion::WebGL2 => self + .current_vao_webgl2() + .enabled_vertex_attrib_array(attrib_id, false), + }; self.send_command(WebGLCommand::DisableVertexAttribArray(attrib_id)); } @@ -2890,56 +2986,73 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { #[allow(unsafe_code)] // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 fn GetVertexAttrib(&self, cx: SafeJSContext, index: u32, param: u32) -> JSVal { - let current_vao = self.current_vao(); - let data = handle_potential_webgl_error!( - self, - current_vao.get_vertex_attrib(index).ok_or(InvalidValue), - return NullValue() - ); - if param == constants::CURRENT_VERTEX_ATTRIB { - let value = if index == 0 { - let (x, y, z, w) = self.current_vertex_attrib_0.get(); - [x, y, z, w] - } else { - let (sender, receiver) = webgl_channel().unwrap(); - self.send_command(WebGLCommand::GetCurrentVertexAttrib(index, sender)); - receiver.recv().unwrap() - }; - unsafe { - rooted!(in(*cx) let mut result = ptr::null_mut::()); - let _ = Float32Array::create(*cx, CreateWith::Slice(&value), result.handle_mut()) - .unwrap(); - return ObjectValue(result.get()); - } - } - - if !self - .extension_manager - .is_get_vertex_attrib_name_enabled(param) - { - self.webgl_error(WebGLError::InvalidEnum); - return NullValue(); - } - - match param { - constants::VERTEX_ATTRIB_ARRAY_ENABLED => BooleanValue(data.enabled_as_array), - constants::VERTEX_ATTRIB_ARRAY_SIZE => Int32Value(data.size as i32), - constants::VERTEX_ATTRIB_ARRAY_TYPE => Int32Value(data.type_ as i32), - constants::VERTEX_ATTRIB_ARRAY_NORMALIZED => BooleanValue(data.normalized), - constants::VERTEX_ATTRIB_ARRAY_STRIDE => Int32Value(data.stride as i32), - constants::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING => unsafe { - rooted!(in(*cx) let mut jsval = NullValue()); - if let Some(buffer) = data.buffer() { - buffer.to_jsval(*cx, jsval.handle_mut()); + let get_attrib = |data: Ref| -> JSVal { + if param == constants::CURRENT_VERTEX_ATTRIB { + let value = if index == 0 { + let (x, y, z, w) = self.current_vertex_attrib_0.get(); + [x, y, z, w] + } else { + let (sender, receiver) = webgl_channel().unwrap(); + self.send_command(WebGLCommand::GetCurrentVertexAttrib(index, sender)); + receiver.recv().unwrap() + }; + unsafe { + rooted!(in(*cx) let mut result = ptr::null_mut::()); + let _ = + Float32Array::create(*cx, CreateWith::Slice(&value), result.handle_mut()) + .unwrap(); + return ObjectValue(result.get()); } - jsval.get() + } + if !self + .extension_manager + .is_get_vertex_attrib_name_enabled(param) + { + self.webgl_error(WebGLError::InvalidEnum); + return NullValue(); + } + + match param { + constants::VERTEX_ATTRIB_ARRAY_ENABLED => BooleanValue(data.enabled_as_array), + constants::VERTEX_ATTRIB_ARRAY_SIZE => Int32Value(data.size as i32), + constants::VERTEX_ATTRIB_ARRAY_TYPE => Int32Value(data.type_ as i32), + constants::VERTEX_ATTRIB_ARRAY_NORMALIZED => BooleanValue(data.normalized), + constants::VERTEX_ATTRIB_ARRAY_STRIDE => Int32Value(data.stride as i32), + constants::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING => unsafe { + rooted!(in(*cx) let mut jsval = NullValue()); + if let Some(buffer) = data.buffer() { + buffer.to_jsval(*cx, jsval.handle_mut()); + } + jsval.get() + }, + ANGLEInstancedArraysConstants::VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE => { + UInt32Value(data.divisor) + }, + _ => { + self.webgl_error(InvalidEnum); + NullValue() + }, + } + }; + + match self.webgl_version() { + WebGLVersion::WebGL1 => { + let current_vao = self.current_vao(); + let data = handle_potential_webgl_error!( + self, + current_vao.get_vertex_attrib(index).ok_or(InvalidValue), + return NullValue() + ); + get_attrib(data) }, - ANGLEInstancedArraysConstants::VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE => { - UInt32Value(data.divisor) - }, - _ => { - self.webgl_error(InvalidEnum); - NullValue() + WebGLVersion::WebGL2 => { + let current_vao = self.current_vao_webgl2(); + let data = handle_potential_webgl_error!( + self, + current_vao.get_vertex_attrib(index).ok_or(InvalidValue), + return NullValue() + ); + get_attrib(data) }, } } @@ -2950,13 +3063,26 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { self.webgl_error(InvalidEnum); return 0; } - let vao = self.current_vao(); - let data = handle_potential_webgl_error!( - self, - vao.get_vertex_attrib(index).ok_or(InvalidValue), - return 0 - ); - data.offset as i64 + match self.webgl_version() { + WebGLVersion::WebGL1 => { + let current_vao = self.current_vao(); + let data = handle_potential_webgl_error!( + self, + current_vao.get_vertex_attrib(index).ok_or(InvalidValue), + return 0 + ); + data.offset as i64 + }, + WebGLVersion::WebGL2 => { + let current_vao = self.current_vao_webgl2(); + let data = handle_potential_webgl_error!( + self, + current_vao.get_vertex_attrib(index).ok_or(InvalidValue), + return 0 + ); + data.offset as i64 + }, + } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 @@ -3819,11 +3945,15 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { stride: i32, offset: i64, ) { - handle_potential_webgl_error!( - self, - self.current_vao() - .vertex_attrib_pointer(index, size, type_, normalized, stride, offset) - ); + let res = match self.webgl_version() { + WebGLVersion::WebGL1 => self + .current_vao() + .vertex_attrib_pointer(index, size, type_, normalized, stride, offset), + WebGLVersion::WebGL2 => self + .current_vao_webgl2() + .vertex_attrib_pointer(index, size, type_, normalized, stride, offset), + }; + handle_potential_webgl_error!(self, res); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.4 diff --git a/components/script/dom/webglvertexarrayobject.rs b/components/script/dom/webglvertexarrayobject.rs new file mode 100644 index 00000000000..48355d05557 --- /dev/null +++ b/components/script/dom/webglvertexarrayobject.rs @@ -0,0 +1,100 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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; +use crate::dom::bindings::codegen::Bindings::WebGLVertexArrayObjectBinding; +use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; +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, WebGLResult, WebGLVertexArrayId}; +use dom_struct::dom_struct; + +#[dom_struct] +pub struct WebGLVertexArrayObject { + webgl_object_: WebGLObject, + array_object: VertexArrayObject, +} + +impl WebGLVertexArrayObject { + fn new_inherited(context: &WebGLRenderingContext, id: Option) -> Self { + Self { + webgl_object_: WebGLObject::new_inherited(context), + array_object: VertexArrayObject::new(context, id), + } + } + + pub fn new(context: &WebGLRenderingContext, id: Option) -> DomRoot { + reflect_dom_object( + Box::new(WebGLVertexArrayObject::new_inherited(context, id)), + &*context.global(), + WebGLVertexArrayObjectBinding::Wrap, + ) + } + + pub fn id(&self) -> Option { + self.array_object.id() + } + + pub fn is_deleted(&self) -> bool { + self.array_object.is_deleted() + } + + pub fn delete(&self, fallible: bool) { + self.array_object.delete(fallible); + } + + pub fn ever_bound(&self) -> bool { + self.array_object.ever_bound() + } + + pub fn set_ever_bound(&self) { + self.array_object.set_ever_bound(); + } + + pub fn element_array_buffer(&self) -> &MutNullableDom { + self.array_object.element_array_buffer() + } + + pub fn get_vertex_attrib(&self, index: u32) -> Option> { + self.array_object.get_vertex_attrib(index) + } + + pub fn vertex_attrib_pointer( + &self, + index: u32, + size: i32, + type_: u32, + normalized: bool, + stride: i32, + offset: i64, + ) -> WebGLResult<()> { + self.array_object + .vertex_attrib_pointer(index, size, type_, normalized, stride, offset) + } + + pub fn vertex_attrib_divisor(&self, index: u32, value: u32) { + self.array_object.vertex_attrib_divisor(index, value); + } + + pub fn enabled_vertex_attrib_array(&self, index: u32, value: bool) { + self.array_object.enabled_vertex_attrib_array(index, value); + } + + pub fn unbind_buffer(&self, buffer: &WebGLBuffer) { + self.array_object.unbind_buffer(buffer); + } + + pub fn validate_for_draw( + &self, + required_len: u32, + instance_count: u32, + active_attribs: &[ActiveAttribInfo], + ) -> WebGLResult<()> { + self.array_object + .validate_for_draw(required_len, instance_count, active_attribs) + } +} 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, - ever_bound: Cell, - is_deleted: Cell, - vertex_attribs: DomRefCell>, - element_array_buffer: MutNullableDom, + array_object: VertexArrayObject, } impl WebGLVertexArrayObjectOES { fn new_inherited(context: &WebGLRenderingContext, id: Option) -> 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 { - 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::().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 { - &self.element_array_buffer + self.array_object.element_array_buffer() } pub fn get_vertex_attrib(&self, index: u32) -> Option> { - 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::().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>, - 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) } } diff --git a/components/script/dom/webidls/WebGL2RenderingContext.webidl b/components/script/dom/webidls/WebGL2RenderingContext.webidl index e25174b858d..72bd68a9f8a 100644 --- a/components/script/dom/webidls/WebGL2RenderingContext.webidl +++ b/components/script/dom/webidls/WebGL2RenderingContext.webidl @@ -11,10 +11,6 @@ typedef long long GLint64; typedef unsigned long long GLuint64; - -// interface WebGLVertexArrayObject : WebGLObject { -// }; - typedef (/*[AllowShared]*/ Uint32Array or sequence) Uint32List; interface mixin WebGL2RenderingContextBase @@ -540,10 +536,10 @@ interface mixin WebGL2RenderingContextBase void uniformBlockBinding(WebGLProgram program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); /* Vertex Array Objects */ - /*WebGLVertexArrayObject? createVertexArray(); + WebGLVertexArrayObject? createVertexArray(); void deleteVertexArray(WebGLVertexArrayObject? vertexArray); [WebGLHandlesContextLoss] GLboolean isVertexArray(WebGLVertexArrayObject? vertexArray); - void bindVertexArray(WebGLVertexArrayObject? array);*/ + void bindVertexArray(WebGLVertexArrayObject? array); }; [Exposed=Window, Pref="dom.webgl2.enabled"] diff --git a/components/script/dom/webidls/WebGLVertexArrayObject.webidl b/components/script/dom/webidls/WebGLVertexArrayObject.webidl new file mode 100644 index 00000000000..a42d8cbe051 --- /dev/null +++ b/components/script/dom/webidls/WebGLVertexArrayObject.webidl @@ -0,0 +1,11 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ +// +// WebGL IDL definitions scraped from the Khronos specification: +// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.17 +// + +[Exposed=(Window), Pref="dom.webgl2.enabled"] +interface WebGLVertexArrayObject : WebGLObject { +}; diff --git a/tests/wpt/webgl/meta/conformance/attribs/gl-vertex-attrib-render.html.ini b/tests/wpt/webgl/meta/conformance/attribs/gl-vertex-attrib-render.html.ini deleted file mode 100644 index e0b8587440f..00000000000 --- a/tests/wpt/webgl/meta/conformance/attribs/gl-vertex-attrib-render.html.ini +++ /dev/null @@ -1,8 +0,0 @@ -[gl-vertex-attrib-render.html] - bug: https://github.com/servo/servo/issues/21132 - [WebGL test #0: Unable to fetch WebGL rendering context for Canvas] - expected: FAIL - - [WebGL test #1: could not create context] - expected: FAIL - diff --git a/tests/wpt/webgl/meta/conformance/buffers/buffer-data-array-buffer-delete.html.ini b/tests/wpt/webgl/meta/conformance/buffers/buffer-data-array-buffer-delete.html.ini deleted file mode 100644 index 4c895897d40..00000000000 --- a/tests/wpt/webgl/meta/conformance/buffers/buffer-data-array-buffer-delete.html.ini +++ /dev/null @@ -1,8 +0,0 @@ -[buffer-data-array-buffer-delete.html] - bug: https://github.com/servo/servo/issues/21132 - [WebGL test #0: Unable to fetch WebGL rendering context for Canvas] - expected: FAIL - - [WebGL test #1: context does not exist] - expected: FAIL - diff --git a/tests/wpt/webgl/meta/conformance2/context/incorrect-context-object-behaviour.html.ini b/tests/wpt/webgl/meta/conformance2/context/incorrect-context-object-behaviour.html.ini index ce40e588ab4..d21792b69e3 100644 --- a/tests/wpt/webgl/meta/conformance2/context/incorrect-context-object-behaviour.html.ini +++ b/tests/wpt/webgl/meta/conformance2/context/incorrect-context-object-behaviour.html.ini @@ -1,5 +1,5 @@ [incorrect-context-object-behaviour.html] expected: ERROR - [WebGL test #0: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).] + [WebGL test #1: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).] expected: FAIL diff --git a/tests/wpt/webgl/meta/conformance2/context/methods-2.html.ini b/tests/wpt/webgl/meta/conformance2/context/methods-2.html.ini index 0aa68bae88a..d313f232cdd 100644 --- a/tests/wpt/webgl/meta/conformance2/context/methods-2.html.ini +++ b/tests/wpt/webgl/meta/conformance2/context/methods-2.html.ini @@ -11,27 +11,15 @@ [WebGL test #18: Property either does not exist or is not a function: drawBuffers] expected: FAIL - [WebGL test #22: Property either does not exist or is not a function: bindVertexArray] - expected: FAIL - [WebGL test #12: Property either does not exist or is not a function: vertexAttribI4i] expected: FAIL - [WebGL test #19: Property either does not exist or is not a function: createVertexArray] - expected: FAIL - [WebGL test #6: Property either does not exist or is not a function: texStorage2D] expected: FAIL [WebGL test #1: Property either does not exist or is not a function: blitFramebuffer] expected: FAIL - [WebGL test #21: Property either does not exist or is not a function: isVertexArray] - expected: FAIL - - [WebGL test #20: Property either does not exist or is not a function: deleteVertexArray] - expected: FAIL - [WebGL test #5: Property either does not exist or is not a function: texImage3D] expected: FAIL diff --git a/tests/wpt/webgl/meta/conformance2/glsl3/attrib-location-length-limits.html.ini b/tests/wpt/webgl/meta/conformance2/glsl3/attrib-location-length-limits.html.ini index 1007a87a5b2..6644c7eaa1f 100644 --- a/tests/wpt/webgl/meta/conformance2/glsl3/attrib-location-length-limits.html.ini +++ b/tests/wpt/webgl/meta/conformance2/glsl3/attrib-location-length-limits.html.ini @@ -1,8 +1,8 @@ [attrib-location-length-limits.html] - [WebGL test #1: getError expected: NO_ERROR. Was INVALID_VALUE : ] + [WebGL test #2: attrib location was -1, should not be] expected: FAIL - [WebGL test #2: attrib location was -1, should not be] + [WebGL test #1: getError expected: NO_ERROR. Was INVALID_VALUE : ] expected: FAIL [WebGL test #3: getError expected: NO_ERROR. Was INVALID_VALUE : ] diff --git a/tests/wpt/webgl/meta/conformance2/misc/expando-loss-2.html.ini b/tests/wpt/webgl/meta/conformance2/misc/expando-loss-2.html.ini index 4a77251d5d8..99c2d835d15 100644 --- a/tests/wpt/webgl/meta/conformance2/misc/expando-loss-2.html.ini +++ b/tests/wpt/webgl/meta/conformance2/misc/expando-loss-2.html.ini @@ -1,5 +1,8 @@ [expando-loss-2.html] expected: ERROR - [WebGL test #10: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).] + [WebGL test #16: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).] + expected: FAIL + + [WebGL test #15: getParameter(TEXTURE_BINDING_3D) returns instance that was bound.] expected: FAIL diff --git a/tests/wpt/webgl/meta/conformance2/misc/instanceof-test.html.ini b/tests/wpt/webgl/meta/conformance2/misc/instanceof-test.html.ini deleted file mode 100644 index 7343c2b36f6..00000000000 --- a/tests/wpt/webgl/meta/conformance2/misc/instanceof-test.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[instanceof-test.html] - [WebGL test #10: gl.createVertexArray() instanceof WebGLVertexArrayObject should be true. Threw exception TypeError: gl.createVertexArray is not a function] - expected: FAIL - diff --git a/tests/wpt/webgl/meta/conformance2/misc/object-deletion-behaviour-2.html.ini b/tests/wpt/webgl/meta/conformance2/misc/object-deletion-behaviour-2.html.ini deleted file mode 100644 index ddbdd34f4d3..00000000000 --- a/tests/wpt/webgl/meta/conformance2/misc/object-deletion-behaviour-2.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[object-deletion-behaviour-2.html] - expected: ERROR - [WebGL test #40: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).] - expected: FAIL - diff --git a/tests/wpt/webgl/meta/conformance2/rendering/instanced-rendering-bug.html.ini b/tests/wpt/webgl/meta/conformance2/rendering/instanced-rendering-bug.html.ini deleted file mode 100644 index 8d6c65c8525..00000000000 --- a/tests/wpt/webgl/meta/conformance2/rendering/instanced-rendering-bug.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[instanced-rendering-bug.html] - expected: ERROR - [WebGL test #1: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).] - expected: FAIL - diff --git a/tests/wpt/webgl/meta/conformance2/state/gl-object-get-calls.html.ini b/tests/wpt/webgl/meta/conformance2/state/gl-object-get-calls.html.ini index 928182c84fc..e716cca6804 100644 --- a/tests/wpt/webgl/meta/conformance2/state/gl-object-get-calls.html.ini +++ b/tests/wpt/webgl/meta/conformance2/state/gl-object-get-calls.html.ini @@ -41,3 +41,13 @@ [WebGL test #182: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).] expected: FAIL + + [WebGL test #3: gl.getBufferParameter(gl.ELEMENT_ARRAY_BUFFER, gl.BUFFER_SIZE) should be 16 (of type number). Was null (of type object).] + expected: FAIL + + [WebGL test #4: gl.getBufferParameter(gl.ELEMENT_ARRAY_BUFFER, gl.BUFFER_USAGE) should be 35048 (of type number). Was null (of type object).] + expected: FAIL + + [WebGL test #5: getBufferParameter did not generate INVALID_ENUM for invalid parameter enum: NO_ERROR] + expected: FAIL + diff --git a/tests/wpt/webgl/meta/conformance2/transform_feedback/simultaneous_binding.html.ini b/tests/wpt/webgl/meta/conformance2/transform_feedback/simultaneous_binding.html.ini index 9d27715d328..9cb14f444b9 100644 --- a/tests/wpt/webgl/meta/conformance2/transform_feedback/simultaneous_binding.html.ini +++ b/tests/wpt/webgl/meta/conformance2/transform_feedback/simultaneous_binding.html.ini @@ -1,2 +1,116 @@ [simultaneous_binding.html] expected: ERROR + [WebGL test #6: buffer should match expected values] + expected: FAIL + + [WebGL test #50: Unexpected error before drawing: 1282] + expected: FAIL + + [WebGL test #4: Unexpected error before drawing: 1282] + expected: FAIL + + [WebGL test #59: Unexpected error before drawing: 1282] + expected: FAIL + + [WebGL test #45: Unexpected error before drawing: 1282] + expected: FAIL + + [WebGL test #13: getError expected: NO_ERROR. Was INVALID_OPERATION : transform feedback should be successful] + expected: FAIL + + [WebGL test #41: Unexpected error before drawing: 1282] + expected: FAIL + + [WebGL test #46: getError expected: NO_ERROR. Was INVALID_OPERATION : transform feedback should be successful] + expected: FAIL + + [WebGL test #8: Unexpected error before drawing: 1282] + expected: FAIL + + [WebGL test #15: getError expected: INVALID_OPERATION. Was NO_ERROR : drawArrays: buffer used as vertex attrib and tf simultaneously] + expected: FAIL + + [WebGL test #37: Unexpected error before drawing: 1282] + expected: FAIL + + [WebGL test #27: getError expected: NO_ERROR. Was INVALID_OPERATION : tf buffer not used as uniform buffer anymore] + expected: FAIL + + [WebGL test #16: getError expected: INVALID_OPERATION. Was NO_ERROR : drawElements: buffer used as vertex attrib and tf simultaneously] + expected: FAIL + + [WebGL test #29: Unexpected error before drawing: 1282] + expected: FAIL + + [WebGL test #55: Unexpected error before drawing: 1282] + expected: FAIL + + [WebGL test #14: buffer should match expected values] + expected: FAIL + + [WebGL test #38: getError expected: NO_ERROR. Was INVALID_OPERATION : transform feedback should be successful] + expected: FAIL + + [WebGL test #54: getError expected: INVALID_OPERATION. Was NO_ERROR : drawElements: buffer used as uniform buffer and tf simultaneously] + expected: FAIL + + [WebGL test #47: buffer should match expected values] + expected: FAIL + + [WebGL test #49: getError expected: INVALID_OPERATION. Was NO_ERROR : drawElements: buffer used as vertex attrib and tf simultaneously] + expected: FAIL + + [WebGL test #10: buffer should match expected values] + expected: FAIL + + [WebGL test #12: Unexpected error before drawing: 1282] + expected: FAIL + + [WebGL test #48: getError expected: INVALID_OPERATION. Was NO_ERROR : drawArrays: buffer used as vertex attrib and tf simultaneously] + expected: FAIL + + [WebGL test #43: buffer should match expected values] + expected: FAIL + + [WebGL test #42: getError expected: NO_ERROR. Was INVALID_OPERATION : transform feedback should be successful] + expected: FAIL + + [WebGL test #17: Unexpected error before drawing: 1282] + expected: FAIL + + [WebGL test #22: Unexpected error before drawing: 1282] + expected: FAIL + + [WebGL test #19: should be the same as before as nothing has executed] + expected: FAIL + + [WebGL test #52: should be the same as before as nothing has executed] + expected: FAIL + + [WebGL test #39: buffer should match expected values] + expected: FAIL + + [WebGL test #5: getError expected: NO_ERROR. Was INVALID_OPERATION : transform feedback should be successful] + expected: FAIL + + [WebGL test #62: Unexpected error before drawing: 1282] + expected: FAIL + + [WebGL test #53: getError expected: INVALID_OPERATION. Was NO_ERROR : drawArrays: buffer used as uniform buffer and tf simultaneously] + expected: FAIL + + [WebGL test #26: Unexpected error before drawing: 1282] + expected: FAIL + + [WebGL test #21: getError expected: INVALID_OPERATION. Was NO_ERROR : drawElements: buffer used as uniform buffer and tf simultaneously] + expected: FAIL + + [WebGL test #20: getError expected: INVALID_OPERATION. Was NO_ERROR : drawArrays: buffer used as uniform buffer and tf simultaneously] + expected: FAIL + + [WebGL test #60: getError expected: NO_ERROR. Was INVALID_OPERATION : tf buffer not used as uniform buffer anymore] + expected: FAIL + + [WebGL test #9: getError expected: NO_ERROR. Was INVALID_OPERATION : transform feedback should be successful] + expected: FAIL + diff --git a/tests/wpt/webgl/meta/conformance2/vertex_arrays/vertex-array-object.html.ini b/tests/wpt/webgl/meta/conformance2/vertex_arrays/vertex-array-object.html.ini deleted file mode 100644 index 03c136e539d..00000000000 --- a/tests/wpt/webgl/meta/conformance2/vertex_arrays/vertex-array-object.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[vertex-array-object.html] - expected: ERROR - [WebGL test #4: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).] - expected: FAIL -