diff --git a/components/canvas/webgl_thread.rs b/components/canvas/webgl_thread.rs index 8ab129680de..abdda3c812a 100644 --- a/components/canvas/webgl_thread.rs +++ b/components/canvas/webgl_thread.rs @@ -740,14 +740,10 @@ impl WebGLImpl { Self::active_attrib(ctx.gl(), program_id, index, chan), WebGLCommand::GetActiveUniform(program_id, index, ref chan) => Self::active_uniform(ctx.gl(), program_id, index, chan), - WebGLCommand::GetAttribLocation(program_id, ref name, ref chan) => - Self::attrib_location(ctx.gl(), program_id, name, chan), WebGLCommand::GetRenderbufferParameter(target, pname, ref chan) => Self::get_renderbuffer_parameter(ctx.gl(), target, pname, chan), WebGLCommand::GetFramebufferAttachmentParameter(target, attachment, pname, ref chan) => Self::get_framebuffer_attachment_parameter(ctx.gl(), target, attachment, pname, chan), - WebGLCommand::GetVertexAttribOffset(index, pname, ref chan) => - Self::vertex_attrib_offset(ctx.gl(), index, pname, chan), WebGLCommand::GetShaderPrecisionFormat(shader_type, precision_type, ref chan) => Self::shader_precision_format(ctx.gl(), shader_type, precision_type, chan), WebGLCommand::GetExtensions(ref chan) => @@ -792,8 +788,6 @@ impl WebGLImpl { ctx.gl().bind_renderbuffer(target, id.map_or(0, WebGLRenderbufferId::get)), WebGLCommand::BindTexture(target, id) => ctx.gl().bind_texture(target, id.map_or(0, WebGLTextureId::get)), - WebGLCommand::LinkProgram(program_id) => - ctx.gl().link_program(program_id.get()), WebGLCommand::Uniform1f(uniform_id, v) => ctx.gl().uniform_1f(uniform_id, v), WebGLCommand::Uniform1fv(uniform_id, ref v) => @@ -832,8 +826,6 @@ impl WebGLImpl { ctx.gl().uniform_matrix_3fv(uniform_id, transpose, v), WebGLCommand::UniformMatrix4fv(uniform_id, transpose, ref v) => ctx.gl().uniform_matrix_4fv(uniform_id, transpose, v), - WebGLCommand::UseProgram(program_id) => - ctx.gl().use_program(program_id.get()), WebGLCommand::ValidateProgram(program_id) => ctx.gl().validate_program(program_id.get()), WebGLCommand::VertexAttrib(attrib_id, x, y, z, w) => @@ -921,17 +913,17 @@ impl WebGLImpl { } sender.send(value).unwrap() } - WebGLCommand::GetProgramParameterBool(program, param, ref sender) => { + WebGLCommand::GetProgramValidateStatus(program, ref sender) => { let mut value = [0]; unsafe { - ctx.gl().get_program_iv(program.get(), param as u32, &mut value); + ctx.gl().get_program_iv(program.get(), gl::VALIDATE_STATUS, &mut value); } sender.send(value[0] != 0).unwrap() } - WebGLCommand::GetProgramParameterInt(program, param, ref sender) => { + WebGLCommand::GetProgramActiveUniforms(program, ref sender) => { let mut value = [0]; unsafe { - ctx.gl().get_program_iv(program.get(), param as u32, &mut value); + ctx.gl().get_program_iv(program.get(), gl::ACTIVE_UNIFORMS, &mut value); } sender.send(value[0]).unwrap() } @@ -949,56 +941,12 @@ impl WebGLImpl { } sender.send(value[0]).unwrap() } - WebGLCommand::GetVertexAttribBool(index, param, ref sender) => { - // FIXME(nox): https://github.com/servo/servo/issues/20608 - let mut max = [0]; + WebGLCommand::GetCurrentVertexAttrib(index, ref sender) => { + let mut value = [0.; 4]; unsafe { - ctx.gl().get_integer_v(gl::MAX_VERTEX_ATTRIBS, &mut max); + ctx.gl().get_vertex_attrib_fv(index, gl::CURRENT_VERTEX_ATTRIB, &mut value); } - let result = if index >= max[0] as u32 { - Err(WebGLError::InvalidValue) - } else { - let mut value = [0]; - unsafe { - ctx.gl().get_vertex_attrib_iv(index, param as u32, &mut value); - } - Ok(value[0] != 0) - }; - sender.send(result).unwrap(); - } - WebGLCommand::GetVertexAttribInt(index, param, ref sender) => { - // FIXME(nox): https://github.com/servo/servo/issues/20608 - let mut max = [0]; - unsafe { - ctx.gl().get_integer_v(gl::MAX_VERTEX_ATTRIBS, &mut max); - } - let result = if index >= max[0] as u32 { - Err(WebGLError::InvalidValue) - } else { - let mut value = [0]; - unsafe { - ctx.gl().get_vertex_attrib_iv(index, param as u32, &mut value); - } - Ok(value[0]) - }; - sender.send(result).unwrap(); - } - WebGLCommand::GetVertexAttribFloat4(index, param, ref sender) => { - // FIXME(nox): https://github.com/servo/servo/issues/20608 - let mut max = [0]; - unsafe { - ctx.gl().get_integer_v(gl::MAX_VERTEX_ATTRIBS, &mut max); - } - let result = if index >= max[0] as u32 { - Err(WebGLError::InvalidValue) - } else { - let mut value = [0.; 4]; - unsafe { - ctx.gl().get_vertex_attrib_fv(index, param as u32, &mut value); - } - Ok(value) - }; - sender.send(result).unwrap(); + sender.send(value).unwrap(); } WebGLCommand::GetTexParameterFloat(target, param, ref sender) => { sender.send(ctx.gl().get_tex_parameter_fv(target, param as u32)).unwrap(); @@ -1012,6 +960,12 @@ impl WebGLImpl { WebGLCommand::TexParameterf(target, param, value) => { ctx.gl().tex_parameter_f(target, param as u32, value) } + WebGLCommand::LinkProgram(program_id, ref sender) => { + return sender.send(Self::link_program(ctx.gl(), program_id)).unwrap(); + } + WebGLCommand::UseProgram(program_id) => { + ctx.gl().use_program(program_id.map_or(0, |p| p.get())) + } } // TODO: update test expectations in order to enable debug assertions @@ -1022,6 +976,45 @@ impl WebGLImpl { assert_eq!(error, gl::NO_ERROR, "Unexpected WebGL error: 0x{:x} ({})", error, error); } + #[allow(unsafe_code)] + fn link_program(gl: &gl::Gl, program: WebGLProgramId) -> ProgramLinkInfo { + gl.link_program(program.get()); + let mut linked = [0]; + unsafe { + gl.get_program_iv(program.get(), gl::LINK_STATUS, &mut linked); + } + if linked[0] == 0 { + return ProgramLinkInfo { + linked: false, + active_attribs: vec![].into(), + } + } + + let mut num_active_attribs = [0]; + unsafe { + gl.get_program_iv(program.get(), gl::ACTIVE_ATTRIBUTES, &mut num_active_attribs); + } + let active_attribs = (0..num_active_attribs[0] as u32).map(|i| { + let (size, type_, name) = gl.get_active_attrib(program.get(), i); + let location = if name.starts_with("gl_") { + -1 + } else { + gl.get_attrib_location(program.get(), &name) + }; + ActiveAttribInfo { + name: from_name_in_compiled_shader(&name), + size, + type_, + location, + } + }).collect::>().into(); + + ProgramLinkInfo { + linked: true, + active_attribs, + } + } + fn read_pixels( gl: &gl::Gl, x: i32, @@ -1072,34 +1065,11 @@ impl WebGLImpl { chan.send(result).unwrap(); } - fn attrib_location(gl: &gl::Gl, - program_id: WebGLProgramId, - name: &str, - chan: &WebGLSender> ) { - let attrib_location = gl.get_attrib_location(program_id.get(), name); - - let attrib_location = if attrib_location == -1 { - None - } else { - Some(attrib_location) - }; - - chan.send(attrib_location).unwrap(); - } - fn finish(gl: &gl::Gl, chan: &WebGLSender<()>) { gl.finish(); chan.send(()).unwrap(); } - fn vertex_attrib_offset(gl: &gl::Gl, - index: u32, - pname: u32, - chan: &WebGLSender) { - let result = gl.get_vertex_attrib_pointer_v(index, pname); - chan.send(result).unwrap(); - } - fn shader_precision_format(gl: &gl::Gl, shader_type: u32, precision_type: u32, diff --git a/components/canvas_traits/webgl.rs b/components/canvas_traits/webgl.rs index 2f39cbada27..6446c0c18d8 100644 --- a/components/canvas_traits/webgl.rs +++ b/components/canvas_traits/webgl.rs @@ -209,9 +209,7 @@ pub enum WebGLCommand { GetShaderPrecisionFormat(u32, u32, WebGLSender<(i32, i32, i32)>), GetActiveAttrib(WebGLProgramId, u32, WebGLSender>), GetActiveUniform(WebGLProgramId, u32, WebGLSender>), - GetAttribLocation(WebGLProgramId, String, WebGLSender>), GetUniformLocation(WebGLProgramId, String, WebGLSender>), - GetVertexAttribOffset(u32, u32, WebGLSender), GetShaderInfoLog(WebGLShaderId, WebGLSender), GetProgramInfoLog(WebGLProgramId, WebGLSender), GetFramebufferAttachmentParameter(u32, u32, u32, WebGLSender), @@ -231,7 +229,7 @@ pub enum WebGLCommand { IsEnabled(u32, WebGLSender), LineWidth(f32), PixelStorei(u32, i32), - LinkProgram(WebGLProgramId), + LinkProgram(WebGLProgramId, WebGLSender), Uniform1f(i32, f32), Uniform1fv(i32, Vec), Uniform1i(i32, i32), @@ -251,7 +249,7 @@ pub enum WebGLCommand { UniformMatrix2fv(i32, bool, Vec), UniformMatrix3fv(i32, bool, Vec), UniformMatrix4fv(i32, bool, Vec), - UseProgram(WebGLProgramId), + UseProgram(Option), ValidateProgram(WebGLProgramId), VertexAttrib(u32, f32, f32, f32, f32), VertexAttribPointer(u32, i32, u32, bool, i32, u32), @@ -274,13 +272,11 @@ pub enum WebGLCommand { GetParameterFloat(ParameterFloat, WebGLSender), GetParameterFloat2(ParameterFloat2, WebGLSender<[f32; 2]>), GetParameterFloat4(ParameterFloat4, WebGLSender<[f32; 4]>), - GetProgramParameterBool(WebGLProgramId, ProgramParameterBool, WebGLSender), - GetProgramParameterInt(WebGLProgramId, ProgramParameterInt, WebGLSender), + GetProgramValidateStatus(WebGLProgramId, WebGLSender), + GetProgramActiveUniforms(WebGLProgramId, WebGLSender), GetShaderParameterBool(WebGLShaderId, ShaderParameterBool, WebGLSender), GetShaderParameterInt(WebGLShaderId, ShaderParameterInt, WebGLSender), - GetVertexAttribBool(u32, VertexAttribBool, WebGLSender>), - GetVertexAttribInt(u32, VertexAttribInt, WebGLSender>), - GetVertexAttribFloat4(u32, VertexAttribFloat4, WebGLSender>), + GetCurrentVertexAttrib(u32, WebGLSender<[f32; 4]>), GetTexParameterFloat(u32, TexParameterFloat, WebGLSender), GetTexParameterInt(u32, TexParameterInt, WebGLSender), TexParameteri(u32, TexParameterInt, i32), @@ -418,6 +414,28 @@ pub enum DOMToTextureCommand { Lock(PipelineId, usize, WebGLSender)>>), } +/// Information about a WebGL program linking operation. +#[derive(Clone, Deserialize, Serialize)] +pub struct ProgramLinkInfo { + /// Whether the program was linked successfully. + pub linked: bool, + /// The list of active attributes. + pub active_attribs: Box<[ActiveAttribInfo]>, +} + +/// Description of a single active attribute. +#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] +pub struct ActiveAttribInfo { + /// The name of the attribute. + pub name: String, + /// The size of the attribute. + pub size: i32, + /// The type of the attribute. + pub type_: u32, + /// The location of the attribute. + pub location: i32, +} + macro_rules! parameters { ($name:ident { $( $variant:ident($kind:ident { $( @@ -528,21 +546,6 @@ parameters! { } } -parameters! { - ProgramParameter { - Bool(ProgramParameterBool { - DeleteStatus = gl::DELETE_STATUS, - LinkStatus = gl::LINK_STATUS, - ValidateStatus = gl::VALIDATE_STATUS, - }), - Int(ProgramParameterInt { - AttachedShaders = gl::ATTACHED_SHADERS, - ActiveAttributes = gl::ACTIVE_ATTRIBUTES, - ActiveUniforms = gl::ACTIVE_UNIFORMS, - }), - } -} - parameters! { ShaderParameter { Bool(ShaderParameterBool { @@ -569,19 +572,38 @@ parameters! { } } -parameters! { - VertexAttrib { - Bool(VertexAttribBool { - VertexAttribArrayEnabled = gl::VERTEX_ATTRIB_ARRAY_ENABLED, - VertexAttribArrayNormalized = gl::VERTEX_ATTRIB_ARRAY_NORMALIZED, - }), - Int(VertexAttribInt { - VertexAttribArraySize = gl::VERTEX_ATTRIB_ARRAY_SIZE, - VertexAttribArrayStride = gl::VERTEX_ATTRIB_ARRAY_STRIDE, - VertexAttribArrayType = gl::VERTEX_ATTRIB_ARRAY_TYPE, - }), - Float4(VertexAttribFloat4 { - CurrentVertexAttrib = gl::CURRENT_VERTEX_ATTRIB, - }), - } +/// ANGLE adds a `_u` prefix to variable names: +/// +/// https://chromium.googlesource.com/angle/angle/+/855d964bd0d05f6b2cb303f625506cf53d37e94f +/// +/// To avoid hard-coding this we would need to use the `sh::GetAttributes` and `sh::GetUniforms` +/// API to look up the `x.name` and `x.mappedName` members. +const ANGLE_NAME_PREFIX: &'static str = "_u"; + +pub fn to_name_in_compiled_shader(s: &str) -> String { + map_dot_separated(s, |s, mapped| { + mapped.push_str(ANGLE_NAME_PREFIX); + mapped.push_str(s); + }) +} + +pub fn from_name_in_compiled_shader(s: &str) -> String { + map_dot_separated(s, |s, mapped| { + mapped.push_str(if s.starts_with(ANGLE_NAME_PREFIX) { + &s[ANGLE_NAME_PREFIX.len()..] + } else { + s + }) + }) +} + +fn map_dot_separated(s: &str, f: F) -> String { + let mut iter = s.split('.'); + let mut mapped = String::new(); + f(iter.next().unwrap(), &mut mapped); + for s in iter { + mapped.push('.'); + f(s, &mut mapped); + } + mapped } diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 794a3618820..06892ec8478 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -32,7 +32,7 @@ use app_units::Au; use canvas_traits::canvas::{CanvasGradientStop, CanvasId, LinearGradientStyle, RadialGradientStyle}; use canvas_traits::canvas::{CompositionOrBlending, LineCapStyle, LineJoinStyle, RepetitionStyle}; -use canvas_traits::webgl::{WebGLBufferId, WebGLFramebufferId, WebGLProgramId, WebGLRenderbufferId}; +use canvas_traits::webgl::{ActiveAttribInfo, WebGLBufferId, WebGLFramebufferId, WebGLProgramId, WebGLRenderbufferId}; use canvas_traits::webgl::{WebGLChan, WebGLContextShareMode, WebGLError, WebGLPipeline, WebGLMsgSender}; use canvas_traits::webgl::{WebGLReceiver, WebGLSender, WebGLShaderId, WebGLTextureId, WebGLVertexArrayId}; use canvas_traits::webgl::{WebGLSLVersion, WebGLVersion}; @@ -342,6 +342,7 @@ unsafe impl JSTraceable for (A, } } +unsafe_no_jsmanaged_fields!(ActiveAttribInfo); unsafe_no_jsmanaged_fields!(bool, f32, f64, String, AtomicBool, AtomicUsize, Uuid, char); unsafe_no_jsmanaged_fields!(usize, u8, u16, u32, u64); unsafe_no_jsmanaged_fields!(isize, i8, i16, i32, i64); diff --git a/components/script/dom/webgl2renderingcontext.rs b/components/script/dom/webgl2renderingcontext.rs index cb5e17dfe26..c06a07a9e3e 100644 --- a/components/script/dom/webgl2renderingcontext.rs +++ b/components/script/dom/webgl2renderingcontext.rs @@ -594,7 +594,7 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { } /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 - fn LinkProgram(&self, program: Option<&WebGLProgram>) { + fn LinkProgram(&self, program: &WebGLProgram) { self.base.LinkProgram(program) } diff --git a/components/script/dom/webgl_extensions/ext/oesvertexarrayobject.rs b/components/script/dom/webgl_extensions/ext/oesvertexarrayobject.rs index a6e8739862e..9ec3065af49 100644 --- a/components/script/dom/webgl_extensions/ext/oesvertexarrayobject.rs +++ b/components/script/dom/webgl_extensions/ext/oesvertexarrayobject.rs @@ -50,7 +50,13 @@ impl OESVertexArrayObjectMethods for OESVertexArrayObject { self.ctx.send_command(WebGLCommand::CreateVertexArray(sender)); let result = receiver.recv().unwrap(); - result.map(|vao_id| WebGLVertexArrayObjectOES::new(&self.global(), vao_id)) + result.map(|vao_id| { + WebGLVertexArrayObjectOES::new( + &self.global(), + vao_id, + self.ctx.limits().max_vertex_attribs, + ) + }) } // https://www.khronos.org/registry/webgl/extensions/OES_vertex_array_object/ @@ -69,8 +75,8 @@ impl OESVertexArrayObjectMethods for OESVertexArrayObject { } // Remove VAO references from buffers - for (_, &(_, ref buffer)) in vao.bound_attrib_buffers().borrow().iter() { - if let Some(ref buffer) = *buffer { + for attrib_data in &*vao.vertex_attribs().borrow() { + if let Some(buffer) = attrib_data.buffer() { buffer.remove_vao_reference(vao.id()); } } @@ -94,9 +100,9 @@ impl OESVertexArrayObjectMethods for OESVertexArrayObject { fn BindVertexArrayOES(&self, vao: Option<&WebGLVertexArrayObjectOES>) { if let Some(bound_vao) = self.bound_vao.get() { // Store buffers attached to attrib pointers - bound_vao.bound_attrib_buffers().set_from(&self.ctx.bound_attrib_buffers()); - for (_, (_, ref buffer)) in bound_vao.bound_attrib_buffers().borrow().iter() { - if let Some(ref buffer) = *buffer { + bound_vao.vertex_attribs().clone_from(&self.ctx.vertex_attribs()); + for attrib_data in &*bound_vao.vertex_attribs().borrow() { + if let Some(buffer) = attrib_data.buffer() { buffer.add_vao_reference(bound_vao.id()); } } @@ -119,13 +125,13 @@ impl OESVertexArrayObjectMethods for OESVertexArrayObject { self.bound_vao.set(Some(&vao)); // Restore WebGLRenderingContext current bindings - self.ctx.bound_attrib_buffers().set_from(&vao.bound_attrib_buffers()); + self.ctx.vertex_attribs().clone_from(&vao.vertex_attribs()); let element_array = vao.bound_buffer_element_array(); self.ctx.set_bound_buffer_element_array(element_array.as_ref().map(|buffer| &**buffer)); } else { self.ctx.send_command(WebGLCommand::BindVertexArray(None)); self.bound_vao.set(None); - self.ctx.bound_attrib_buffers().clear(); + self.ctx.vertex_attribs().clear(); } } } diff --git a/components/script/dom/webglprogram.rs b/components/script/dom/webglprogram.rs index d710568d1ca..4c52ed75928 100644 --- a/components/script/dom/webglprogram.rs +++ b/components/script/dom/webglprogram.rs @@ -3,8 +3,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl -use canvas_traits::webgl::{WebGLCommand, WebGLError, WebGLMsgSender, WebGLProgramId, WebGLResult}; -use canvas_traits::webgl::webgl_channel; +use canvas_traits::webgl::{ActiveAttribInfo, WebGLCommand, WebGLError, WebGLMsgSender}; +use canvas_traits::webgl::{WebGLProgramId, WebGLResult, from_name_in_compiled_shader}; +use canvas_traits::webgl::{to_name_in_compiled_shader, webgl_channel}; +use dom::bindings::cell::DomRefCell; use dom::bindings::codegen::Bindings::WebGLProgramBinding; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants; use dom::bindings::reflector::{DomObject, reflect_dom_object}; @@ -16,7 +18,7 @@ use dom::webglrenderingcontext::MAX_UNIFORM_AND_ATTRIBUTE_LEN; use dom::webglshader::WebGLShader; use dom::window::Window; use dom_struct::dom_struct; -use std::cell::Cell; +use std::cell::{Cell, Ref}; #[dom_struct] pub struct WebGLProgram { @@ -29,46 +31,7 @@ pub struct WebGLProgram { vertex_shader: MutNullableDom, #[ignore_malloc_size_of = "Defined in ipc-channel"] renderer: WebGLMsgSender, -} - -/// ANGLE adds a `_u` prefix to variable names: -/// -/// https://chromium.googlesource.com/angle/angle/+/855d964bd0d05f6b2cb303f625506cf53d37e94f -/// -/// To avoid hard-coding this we would need to use the `sh::GetAttributes` and `sh::GetUniforms` -/// API to look up the `x.name` and `x.mappedName` members, -/// then build a data structure for bi-directional lookup (so either linear scan or two hashmaps). -/// Even then, this would probably only support plain variable names like "foo". -/// Strings passed to e.g. `GetUniformLocation` can be expressions like "foo[0].bar", -/// with the mapping for that "bar" name in yet another part of ANGLE’s API. -const ANGLE_NAME_PREFIX: &'static str = "_u"; - -fn to_name_in_compiled_shader(s: &str) -> String { - map_dot_separated(s, |s, mapped| { - mapped.push_str(ANGLE_NAME_PREFIX); - mapped.push_str(s); - }) -} - -fn from_name_in_compiled_shader(s: &str) -> String { - map_dot_separated(s, |s, mapped| { - mapped.push_str(if s.starts_with(ANGLE_NAME_PREFIX) { - &s[ANGLE_NAME_PREFIX.len()..] - } else { - s - }) - }) -} - -fn map_dot_separated(s: &str, f: F) -> String { - let mut iter = s.split('.'); - let mut mapped = String::new(); - f(iter.next().unwrap(), &mut mapped); - for s in iter { - mapped.push('.'); - f(s, &mut mapped); - } - mapped + active_attribs: DomRefCell>, } impl WebGLProgram { @@ -84,6 +47,7 @@ impl WebGLProgram { fragment_shader: Default::default(), vertex_shader: Default::default(), renderer: renderer, + active_attribs: DomRefCell::new(vec![].into()), } } @@ -142,7 +106,7 @@ impl WebGLProgram { return Err(WebGLError::InvalidOperation); } self.linked.set(false); - self.link_called.set(true); + *self.active_attribs.borrow_mut() = vec![].into(); match self.fragment_shader.get() { Some(ref shader) if shader.successfully_compiled() => {}, @@ -154,22 +118,16 @@ impl WebGLProgram { _ => return Ok(()), // callers use gl.LINK_STATUS to check link errors } - self.linked.set(true); - self.renderer.send(WebGLCommand::LinkProgram(self.id)).unwrap(); + let (sender, receiver) = webgl_channel().unwrap(); + self.renderer.send(WebGLCommand::LinkProgram(self.id, sender)).unwrap(); + let link_info = receiver.recv().unwrap(); + self.linked.set(link_info.linked); + *self.active_attribs.borrow_mut() = link_info.active_attribs; Ok(()) } - /// glUseProgram - pub fn use_program(&self) -> WebGLResult<()> { - if self.is_deleted() { - return Err(WebGLError::InvalidOperation); - } - if !self.linked.get() { - return Err(WebGLError::InvalidOperation); - } - - self.renderer.send(WebGLCommand::UseProgram(self.id)).unwrap(); - Ok(()) + pub fn active_attribs(&self) -> Ref<[ActiveAttribInfo]> { + Ref::map(self.active_attribs.borrow(), |attribs| &**attribs) } /// glValidateProgram @@ -281,19 +239,18 @@ impl WebGLProgram { if self.is_deleted() { return Err(WebGLError::InvalidValue); } - let (sender, receiver) = webgl_channel().unwrap(); - self.renderer - .send(WebGLCommand::GetActiveAttrib(self.id, index, sender)) - .unwrap(); - - receiver.recv().unwrap().map(|(size, ty, name)| { - let name = DOMString::from(from_name_in_compiled_shader(&name)); - WebGLActiveInfo::new(self.global().as_window(), size, ty, name) - }) + let attribs = self.active_attribs.borrow(); + let data = attribs.get(index as usize).ok_or(WebGLError::InvalidValue)?; + Ok(WebGLActiveInfo::new( + self.global().as_window(), + data.size, + data.type_, + data.name.clone().into(), + )) } /// glGetAttribLocation - pub fn get_attrib_location(&self, name: DOMString) -> WebGLResult> { + pub fn get_attrib_location(&self, name: DOMString) -> WebGLResult { if !self.is_linked() || self.is_deleted() { return Err(WebGLError::InvalidOperation); } @@ -303,21 +260,20 @@ impl WebGLProgram { // Check if the name is reserved if name.starts_with("gl_") { - return Ok(None); + return Ok(-1); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#GLSL_CONSTRUCTS if name.starts_with("webgl_") || name.starts_with("_webgl_") { - return Ok(None); + return Ok(-1); } - let name = to_name_in_compiled_shader(&name); - - let (sender, receiver) = webgl_channel().unwrap(); - self.renderer - .send(WebGLCommand::GetAttribLocation(self.id, name, sender)) - .unwrap(); - Ok(receiver.recv().unwrap()) + let location = self.active_attribs + .borrow() + .iter() + .find(|attrib| attrib.name == &*name) + .map_or(-1, |attrib| attrib.location); + Ok(location) } /// glGetUniformLocation diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 7079bbcc76b..cb4c5dbcfb0 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -4,8 +4,8 @@ use byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt}; use canvas_traits::canvas::{byte_swap, multiply_u8_pixel}; -use canvas_traits::webgl::{DOMToTextureCommand, Parameter, ProgramParameter}; -use canvas_traits::webgl::{ShaderParameter, TexParameter, VertexAttrib, WebGLCommand}; +use canvas_traits::webgl::{DOMToTextureCommand, Parameter}; +use canvas_traits::webgl::{ShaderParameter, TexParameter, WebGLCommand}; use canvas_traits::webgl::{WebGLContextShareMode, WebGLError}; use canvas_traits::webgl::{WebGLFramebufferBindingRequest, WebGLMsg, WebGLMsgSender}; use canvas_traits::webgl::{WebGLResult, WebGLSLVersion, WebGLVersion}; @@ -193,7 +193,7 @@ pub struct WebGLRenderingContext { bound_texture_unit: Cell, bound_buffer_array: MutNullableDom, bound_buffer_element_array: MutNullableDom, - bound_attrib_buffers: BoundAttribBuffers, + vertex_attribs: VertexAttribs, current_program: MutNullableDom, #[ignore_malloc_size_of = "Because it's small"] current_vertex_attrib_0: Cell<(f32, f32, f32, f32)>, @@ -234,6 +234,7 @@ impl WebGLRenderingContext { share_mode: ctx_data.share_mode, webgl_version, glsl_version: ctx_data.glsl_version, + vertex_attribs: VertexAttribs::new(ctx_data.limits.max_vertex_attribs), limits: ctx_data.limits, canvas: Dom::from_ref(canvas), last_error: Cell::new(None), @@ -244,7 +245,6 @@ impl WebGLRenderingContext { bound_texture_unit: Cell::new(constants::TEXTURE0), bound_buffer_array: MutNullableDom::new(None), bound_buffer_element_array: MutNullableDom::new(None), - bound_attrib_buffers: Default::default(), bound_renderbuffer: MutNullableDom::new(None), current_program: MutNullableDom::new(None), current_vertex_attrib_0: Cell::new((0f32, 0f32, 0f32, 1f32)), @@ -312,8 +312,8 @@ impl WebGLRenderingContext { }) } - pub fn bound_attrib_buffers(&self) -> &BoundAttribBuffers { - &self.bound_attrib_buffers + pub fn vertex_attribs(&self) -> &VertexAttribs { + &self.vertex_attribs } pub fn bound_buffer_element_array(&self) -> Option> { @@ -2075,7 +2075,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } // Remove deleted buffer from bound attrib buffers. - self.bound_attrib_buffers.remove_buffer(buffer); + self.vertex_attribs.delete_buffer(buffer); // Delete buffer. handle_object_deletion!(self, self.bound_buffer_array, buffer, @@ -2202,13 +2202,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } } - { - // https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.2 - let buffers = self.bound_attrib_buffers.borrow(); - if buffers.iter().any(|(_, &(enabled, ref buffer))| enabled && buffer.is_none()) { - return self.webgl_error(InvalidOperation); - } - } + handle_potential_webgl_error!(self, self.vertex_attribs.validate_for_draw(), return); if !self.validate_framebuffer_complete() { return; @@ -2277,13 +2271,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } } - { - // https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.2 - let buffers = self.bound_attrib_buffers.borrow(); - if buffers.iter().any(|(_, &(enabled, ref buffer))| enabled && buffer.is_none()) { - return self.webgl_error(InvalidOperation); - } - } + handle_potential_webgl_error!(self, self.vertex_attribs.validate_for_draw(), return); if !self.validate_framebuffer_complete() { return; @@ -2299,7 +2287,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { return self.webgl_error(InvalidValue); } - self.bound_attrib_buffers.enabled(attrib_id, true); + self.vertex_attribs.enabled_as_array(attrib_id, true); self.send_command(WebGLCommand::EnableVertexAttribArray(attrib_id)); } @@ -2309,7 +2297,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { return self.webgl_error(InvalidValue); } - self.bound_attrib_buffers.enabled(attrib_id, false); + self.vertex_attribs.enabled_as_array(attrib_id, false); self.send_command(WebGLCommand::DisableVertexAttribArray(attrib_id)); } @@ -2326,18 +2314,12 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn GetActiveAttrib(&self, program: &WebGLProgram, index: u32) -> Option> { - match program.get_active_attrib(index) { - Ok(ret) => Some(ret), - Err(e) => { - self.webgl_error(e); - return None; - } - } + handle_potential_webgl_error!(self, program.get_active_attrib(index).map(Some), None) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn GetAttribLocation(&self, program: &WebGLProgram, name: DOMString) -> i32 { - handle_potential_webgl_error!(self, program.get_attrib_location(name), None).unwrap_or(-1) + handle_potential_webgl_error!(self, program.get_attrib_location(name), -1) } #[allow(unsafe_code)] @@ -2509,17 +2491,32 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { #[allow(unsafe_code)] // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 unsafe fn GetProgramParameter(&self, _: *mut JSContext, program: &WebGLProgram, param: u32) -> JSVal { - match handle_potential_webgl_error!(self, ProgramParameter::from_u32(param), return NullValue()) { - ProgramParameter::Bool(param) => { + // FIXME(nox): INVALID_OPERATION if program comes from a different context. + match param { + constants::DELETE_STATUS => BooleanValue(program.is_deleted()), + constants::LINK_STATUS => BooleanValue(program.is_linked()), + constants::VALIDATE_STATUS => { + // FIXME(nox): This could be cached on the DOM side when we call validateProgram + // but I'm not sure when the value should be reset. let (sender, receiver) = webgl_channel().unwrap(); - self.send_command(WebGLCommand::GetProgramParameterBool(program.id(), param, sender)); + self.send_command(WebGLCommand::GetProgramValidateStatus(program.id(), sender)); BooleanValue(receiver.recv().unwrap()) } - ProgramParameter::Int(param) => { + constants::ATTACHED_SHADERS => { + // FIXME(nox): This allocates a vector and roots a couple of shaders for nothing. + Int32Value(program.attached_shaders().map(|shaders| shaders.len() as i32).unwrap_or(0)) + } + constants::ACTIVE_ATTRIBUTES => Int32Value(program.active_attribs().len() as i32), + constants::ACTIVE_UNIFORMS => { + // FIXME(nox): We'll need to cache that on the DOM side at some point. let (sender, receiver) = webgl_channel().unwrap(); - self.send_command(WebGLCommand::GetProgramParameterInt(program.id(), param, sender)); + self.send_command(WebGLCommand::GetProgramActiveUniforms(program.id(), sender)); Int32Value(receiver.recv().unwrap()) } + _ => { + self.webgl_error(InvalidEnum); + NullValue() + } } } @@ -2591,43 +2588,44 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { #[allow(unsafe_code)] // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 unsafe fn GetVertexAttrib(&self, cx: *mut JSContext, index: u32, param: u32) -> JSVal { - if index == 0 && param == constants::CURRENT_VERTEX_ATTRIB { + let data = handle_potential_webgl_error!( + self, + self.vertex_attribs.get(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() + }; + // FIXME(nox): https://github.com/servo/servo/issues/20655 rooted!(in(cx) let mut result = UndefinedValue()); - let (x, y, z, w) = self.current_vertex_attrib_0.get(); - let attrib = vec![x, y, z, w]; - attrib.to_jsval(cx, result.handle_mut()); - return result.get() + value.to_jsval(cx, result.handle_mut()); + return result.get(); } - if param == constants::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING { - rooted!(in(cx) let mut jsval = NullValue()); - if let Some(buffer) = self.bound_attrib_buffers.get(index) { - buffer.to_jsval(cx, jsval.handle_mut()); + 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 => { + rooted!(in(cx) let mut jsval = NullValue()); + if let Some(data) = self.vertex_attribs.get(index) { + if let Some(buffer) = data.buffer() { + buffer.to_jsval(cx, jsval.handle_mut()); + } + } + jsval.get() } - return jsval.get(); - } - - match handle_potential_webgl_error!(self, VertexAttrib::from_u32(param), return NullValue()) { - VertexAttrib::Bool(param) => { - let (sender, receiver) = webgl_channel().unwrap(); - self.send_command(WebGLCommand::GetVertexAttribBool(index, param, sender)); - let value = handle_potential_webgl_error!(self, receiver.recv().unwrap(), return NullValue()); - BooleanValue(value) - } - VertexAttrib::Int(param) => { - let (sender, receiver) = webgl_channel().unwrap(); - self.send_command(WebGLCommand::GetVertexAttribInt(index, param, sender)); - let value = handle_potential_webgl_error!(self, receiver.recv().unwrap(), return NullValue()); - Int32Value(value) - } - VertexAttrib::Float4(param) => { - let (sender, receiver) = webgl_channel().unwrap(); - self.send_command(WebGLCommand::GetVertexAttribFloat4(index, param, sender)); - let value = handle_potential_webgl_error!(self, receiver.recv().unwrap(), return NullValue()); - // FIXME(nox): https://github.com/servo/servo/issues/20655 - rooted!(in(cx) let mut result = UndefinedValue()); - value.to_jsval(cx, result.handle_mut()); - result.get() + _ => { + self.webgl_error(InvalidEnum); + NullValue() } } } @@ -2638,10 +2636,12 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { self.webgl_error(InvalidEnum); return 0; } - let (sender, receiver) = webgl_channel().unwrap(); - self.send_command(WebGLCommand::GetVertexAttribOffset(index, pname, sender)); - - receiver.recv().unwrap() as i64 + let data = handle_potential_webgl_error!( + self, + self.vertex_attribs.get(index).ok_or(InvalidValue), + return 0 + ); + data.offset as i64 } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 @@ -2956,12 +2956,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 - fn LinkProgram(&self, program: Option<&WebGLProgram>) { - if let Some(program) = program { - if let Err(e) = program.link() { - self.webgl_error(e); - } - } + fn LinkProgram(&self, program: &WebGLProgram) { + // FIXME(nox): INVALID_OPERATION if program comes from a different context. + handle_potential_webgl_error!(self, program.link()); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 @@ -3245,11 +3242,12 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 fn UseProgram(&self, program: Option<&WebGLProgram>) { if let Some(program) = program { - match program.use_program() { - Ok(()) => self.current_program.set(Some(program)), - Err(e) => self.webgl_error(e), + if program.is_deleted() || !program.is_linked() { + return self.webgl_error(InvalidOperation); } } + self.send_command(WebGLCommand::UseProgram(program.map(|p| p.id()))); + self.current_program.set(program); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 @@ -3328,49 +3326,30 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 - fn VertexAttribPointer(&self, attrib_id: u32, size: i32, data_type: u32, - normalized: bool, stride: i32, offset: i64) { - if attrib_id >= self.limits.max_vertex_attribs { - return self.webgl_error(InvalidValue); - } + fn VertexAttribPointer( + &self, + index: u32, + size: i32, + type_: u32, + normalized: bool, + stride: i32, + offset: i64, + ) { + handle_potential_webgl_error!( + self, + self.vertex_attribs.set_pointer( + index, + size, + type_, + normalized, + stride, + offset, + self.bound_buffer_array.get().as_ref().map(|buffer| &**buffer), + ), + return + ); - // GLES spec: If offset or stride is negative, an INVALID_VALUE error will be generated - // WebGL spec: the maximum supported stride is 255 - if stride < 0 || stride > 255 || offset < 0 { - return self.webgl_error(InvalidValue); - } - if size < 1 || size > 4 { - return self.webgl_error(InvalidValue); - } - - let buffer_array = match self.bound_buffer_array.get() { - Some(buffer) => buffer, - None => { - return self.webgl_error(InvalidOperation); - } - }; - - // stride and offset must be multiple of data_type - match data_type { - constants::BYTE | constants::UNSIGNED_BYTE => {}, - constants::SHORT | constants::UNSIGNED_SHORT => { - if offset % 2 > 0 || stride % 2 > 0 { - return self.webgl_error(InvalidOperation); - } - }, - constants::FLOAT => { - if offset % 4 > 0 || stride % 4 > 0 { - return self.webgl_error(InvalidOperation); - } - }, - _ => return self.webgl_error(InvalidEnum), - - } - - self.bound_attrib_buffers.bind_buffer(attrib_id, &buffer_array); - - let msg = WebGLCommand::VertexAttribPointer(attrib_id, size, data_type, normalized, stride, offset as u32); - self.send_command(msg); + self.send_command(WebGLCommand::VertexAttribPointer(index, size, type_, normalized, stride, offset as u32)); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.4 @@ -3805,48 +3784,137 @@ impl UniformSetterType { } } -#[derive(Default, JSTraceable, MallocSizeOf)] +#[derive(JSTraceable, MallocSizeOf)] #[must_root] -pub struct BoundAttribBuffers { - elements: DomRefCell>)>>, +pub struct VertexAttribs { + attribs: DomRefCell>, } -impl BoundAttribBuffers { +impl VertexAttribs { + pub fn new(max: u32) -> Self { + // High-end GPUs have 16 of those, let's just use a boxed slice. + Self { attribs: DomRefCell::new(vec![Default::default(); max as usize].into()) } + } + pub fn clear(&self) { - self.elements.borrow_mut().clear() + for attrib in &mut **self.attribs.borrow_mut() { + *attrib = Default::default(); + } } - pub fn set_from(&self, other: &BoundAttribBuffers) { - *self.elements.borrow_mut() = other.elements.borrow().clone(); + pub fn clone_from(&self, other: &Self) { + self.attribs.borrow_mut().clone_from_slice(&other.attribs.borrow()); } - pub fn borrow(&self) -> Ref>)>> { - self.elements.borrow() + pub fn set_pointer( + &self, + index: u32, + size: i32, + type_: u32, + normalized: bool, + stride: i32, + offset: i64, + buffer: Option<&WebGLBuffer>, + ) -> WebGLResult<()> { + let mut attribs = self.attribs.borrow_mut(); + let data = attribs.get_mut(index as usize).ok_or(InvalidValue)?; + + if size < 1 || size > 4 { + return Err(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(InvalidValue); + } + match type_ { + constants::BYTE | constants::UNSIGNED_BYTE => {}, + constants::SHORT | constants::UNSIGNED_SHORT => { + if offset % 2 > 0 || stride % 2 > 0 { + return Err(InvalidOperation); + } + }, + constants::FLOAT => { + if offset % 4 > 0 || stride % 4 > 0 { + return Err(InvalidOperation); + } + }, + _ => return Err(InvalidEnum), + } + + let buffer = buffer.ok_or(InvalidOperation)?; + + *data = VertexAttribData { + enabled_as_array: data.enabled_as_array, + size: size as u8, + type_, + normalized, + stride: stride as u8, + offset: offset as u32, + buffer: Some(Dom::from_ref(buffer)), + }; + Ok(()) } - fn remove_buffer(&self, buffer: &WebGLBuffer) { - self.elements.borrow_mut().retain(|_, v| { - v.1.as_ref().map_or(true, |b| b.id() != buffer.id()) - }) + pub fn borrow(&self) -> Ref<[VertexAttribData]> { + Ref::map(self.attribs.borrow(), |attribs| &**attribs) } - fn get(&self, index: u32) -> Option> { - ref_filter_map(self.elements.borrow(), |elements| { - elements.get(&index).and_then(|&(_, ref buffer)| { - buffer.as_ref().map(|b| &**b) - }) - }) + fn delete_buffer(&self, buffer: &WebGLBuffer) { + for attrib in &mut **self.attribs.borrow_mut() { + if attrib.buffer().map_or(false, |b| b.id() == buffer.id()) { + attrib.buffer = None; + } + } } - fn enabled(&self, index: u32, value: bool) { - let mut elements = self.elements.borrow_mut(); - let pair = elements.entry(index).or_insert((false, None)); - pair.0 = value; + fn get(&self, index: u32) -> Option> { + ref_filter_map(self.attribs.borrow(), |attribs| attribs.get(index as usize)) } - fn bind_buffer(&self, index: u32, buffer: &WebGLBuffer) { - let mut elements = self.elements.borrow_mut(); - let pair = elements.entry(index).or_insert((false, None)); - pair.1 = Some(Dom::from_ref(buffer)); + fn enabled_as_array(&self, index: u32, value: bool) { + self.attribs.borrow_mut()[index as usize].enabled_as_array = value; + } + + fn validate_for_draw(&self) -> WebGLResult<()> { + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.2 + if self.borrow().iter().any(|data| data.enabled_as_array && data.buffer.is_none()) { + return Err(InvalidOperation); + } + Ok(()) + } +} + +#[derive(Clone, JSTraceable, MallocSizeOf)] +#[must_root] +pub struct VertexAttribData { + enabled_as_array: bool, + size: u8, + type_: u32, + normalized: bool, + stride: u8, + offset: u32, + buffer: Option>, +} + +impl Default for VertexAttribData { + #[allow(unrooted_must_root)] + fn default() -> Self { + Self { + enabled_as_array: false, + size: 4, + type_: constants::FLOAT, + normalized: false, + stride: 0, + offset: 0, + buffer: None, + } + } +} + +impl VertexAttribData { + pub fn buffer(&self) -> Option<&WebGLBuffer> { + self.buffer.as_ref().map(|b| &**b) } } diff --git a/components/script/dom/webglvertexarrayobjectoes.rs b/components/script/dom/webglvertexarrayobjectoes.rs index 49babf3095d..883559f8ac2 100644 --- a/components/script/dom/webglvertexarrayobjectoes.rs +++ b/components/script/dom/webglvertexarrayobjectoes.rs @@ -9,7 +9,7 @@ use dom::bindings::root::{DomRoot, MutNullableDom}; use dom::globalscope::GlobalScope; use dom::webglbuffer::WebGLBuffer; use dom::webglobject::WebGLObject; -use dom::webglrenderingcontext::BoundAttribBuffers; +use dom::webglrenderingcontext::VertexAttribs; use dom_struct::dom_struct; use std::cell::Cell; @@ -19,30 +19,36 @@ pub struct WebGLVertexArrayObjectOES { id: WebGLVertexArrayId, ever_bound: Cell, is_deleted: Cell, - bound_attrib_buffers: BoundAttribBuffers, + vertex_attribs: VertexAttribs, bound_buffer_element_array: MutNullableDom, } impl WebGLVertexArrayObjectOES { - fn new_inherited(id: WebGLVertexArrayId) -> WebGLVertexArrayObjectOES { + fn new_inherited(id: WebGLVertexArrayId, max_vertex_attribs: u32) -> Self { Self { webgl_object_: WebGLObject::new_inherited(), id: id, ever_bound: Cell::new(false), is_deleted: Cell::new(false), - bound_attrib_buffers: Default::default(), + vertex_attribs: VertexAttribs::new(max_vertex_attribs), bound_buffer_element_array: MutNullableDom::new(None), } } - pub fn new(global: &GlobalScope, id: WebGLVertexArrayId) -> DomRoot { - reflect_dom_object(Box::new(WebGLVertexArrayObjectOES::new_inherited(id)), - global, - WebGLVertexArrayObjectOESBinding::Wrap) + pub fn new( + global: &GlobalScope, + id: WebGLVertexArrayId, + max_vertex_attribs: u32, + ) -> DomRoot { + reflect_dom_object( + Box::new(WebGLVertexArrayObjectOES::new_inherited(id, max_vertex_attribs)), + global, + WebGLVertexArrayObjectOESBinding::Wrap, + ) } - pub fn bound_attrib_buffers(&self) -> &BoundAttribBuffers { - &self.bound_attrib_buffers + pub fn vertex_attribs(&self) -> &VertexAttribs { + &self.vertex_attribs } pub fn id(&self) -> WebGLVertexArrayId { diff --git a/components/script/dom/webidls/WebGLRenderingContext.webidl b/components/script/dom/webidls/WebGLRenderingContext.webidl index 8ec02ce95ea..82769410062 100644 --- a/components/script/dom/webidls/WebGLRenderingContext.webidl +++ b/components/script/dom/webidls/WebGLRenderingContext.webidl @@ -597,7 +597,7 @@ interface WebGLRenderingContextBase [WebGLHandlesContextLoss] GLboolean isShader(WebGLShader? shader); [WebGLHandlesContextLoss] GLboolean isTexture(WebGLTexture? texture); void lineWidth(GLfloat width); - void linkProgram(WebGLProgram? program); + void linkProgram(WebGLProgram program); void pixelStorei(GLenum pname, GLint param); void polygonOffset(GLfloat factor, GLfloat units); diff --git a/components/script_plugins/unrooted_must_root.rs b/components/script_plugins/unrooted_must_root.rs index 6277b309c0c..1c347897b91 100644 --- a/components/script_plugins/unrooted_must_root.rs +++ b/components/script_plugins/unrooted_must_root.rs @@ -52,6 +52,7 @@ fn is_unrooted_ty(cx: &LateContext, ty: &ty::TyS, in_new_function: bool) -> bool } else if match_def_path(cx, did.did, &["core", "cell", "Ref"]) || match_def_path(cx, did.did, &["core", "cell", "RefMut"]) || match_def_path(cx, did.did, &["core", "slice", "Iter"]) + || match_def_path(cx, did.did, &["core", "slice", "IterMut"]) || match_def_path(cx, did.did, &["std", "collections", "hash", "map", "Entry"]) || match_def_path(cx, did.did, &["std", "collections", "hash", "map", "OccupiedEntry"]) || match_def_path(cx, did.did, &["std", "collections", "hash", "map", "VacantEntry"]) diff --git a/tests/wpt/mozilla/meta/webgl/conformance-1.0.3/conformance/programs/program-test.html.ini b/tests/wpt/mozilla/meta/webgl/conformance-1.0.3/conformance/programs/program-test.html.ini index a5f39d42b57..164f0e3c2a2 100644 --- a/tests/wpt/mozilla/meta/webgl/conformance-1.0.3/conformance/programs/program-test.html.ini +++ b/tests/wpt/mozilla/meta/webgl/conformance-1.0.3/conformance/programs/program-test.html.ini @@ -1,10 +1,4 @@ [program-test.html] - [WebGL test #53: getError expected: INVALID_OPERATION. Was NO_ERROR : drawing with a null program should generate INVALID_OPERATION] - expected: FAIL - - [WebGL test #58: linking should fail with in-use formerly good program, with new bad shader attached] - expected: FAIL - [WebGL test #64: getError expected: NO_ERROR. Was INVALID_OPERATION : delete the current program shouldn't change the current rendering state] expected: FAIL