diff options
Diffstat (limited to 'components/script/dom/webgl2renderingcontext.rs')
-rw-r--r-- | components/script/dom/webgl2renderingcontext.rs | 134 |
1 files changed, 133 insertions, 1 deletions
diff --git a/components/script/dom/webgl2renderingcontext.rs b/components/script/dom/webgl2renderingcontext.rs index fea8b54e849..ae6b66187cd 100644 --- a/components/script/dom/webgl2renderingcontext.rs +++ b/components/script/dom/webgl2renderingcontext.rs @@ -25,7 +25,7 @@ use crate::dom::webglprogram::WebGLProgram; use crate::dom::webglquery::WebGLQuery; use crate::dom::webglrenderbuffer::WebGLRenderbuffer; use crate::dom::webglrenderingcontext::{ - uniform_get, uniform_typed, LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext, + uniform_get, uniform_typed, LayoutCanvasWebGLRenderingContextHelpers, VertexAttrib, WebGLRenderingContext, }; use crate::dom::webglsampler::{WebGLSampler, WebGLSamplerValue}; use crate::dom::webglshader::WebGLShader; @@ -230,6 +230,62 @@ impl WebGL2RenderingContext { } } + fn validate_vertex_attribs_for_draw(&self) { + let program = match self.base.current_program() { + Some(program) => program, + None => return, + }; + let groups = [ + [ + constants::INT, + constants::INT_VEC2, + constants::INT_VEC3, + constants::INT_VEC4, + ], + [ + constants::UNSIGNED_INT, + constants::UNSIGNED_INT_VEC2, + constants::UNSIGNED_INT_VEC3, + constants::UNSIGNED_INT_VEC4, + ], + [ + constants::FLOAT, + constants::FLOAT_VEC2, + constants::FLOAT_VEC3, + constants::FLOAT_VEC4, + ], + ]; + let vao = self.current_vao(); + for prog_attrib in program.active_attribs().iter() { + let attrib = handle_potential_webgl_error!( + self.base, + vao.get_vertex_attrib(prog_attrib.location as u32) + .ok_or(InvalidOperation), + return + ); + + let current_vertex_attrib = + self.base.current_vertex_attribs()[prog_attrib.location as usize]; + let attrib_data_base_type = if !attrib.enabled_as_array { + match current_vertex_attrib { + VertexAttrib::Int(_, _, _, _) => constants::INT, + VertexAttrib::Uint(_, _, _, _) => constants::UNSIGNED_INT, + VertexAttrib::Float(_, _, _, _) => constants::FLOAT, + } + } else { + attrib.type_ + }; + + let contains = groups + .iter() + .find(|g| g.contains(&attrib_data_base_type) && g.contains(&prog_attrib.type_)); + if contains.is_none() { + self.base.webgl_error(InvalidOperation); + return; + } + } + } + pub fn base_context(&self) -> DomRoot<WebGLRenderingContext> { DomRoot::from_ref(&*self.base) } @@ -739,6 +795,28 @@ impl WebGL2RenderingContext { true } + + fn vertex_attrib_i(&self, index: u32, x: i32, y: i32, z: i32, w: i32) { + if index >= self.base.limits().max_vertex_attribs { + return self.base.webgl_error(InvalidValue); + } + self.base.current_vertex_attribs()[index as usize] = VertexAttrib::Int(x, y, z, w); + self.current_vao() + .set_vertex_attrib_type(index, constants::INT); + self.base + .send_command(WebGLCommand::VertexAttribI(index, x, y, z, w)); + } + + fn vertex_attrib_u(&self, index: u32, x: u32, y: u32, z: u32, w: u32) { + if index >= self.base.limits().max_vertex_attribs { + return self.base.webgl_error(InvalidValue); + } + self.base.current_vertex_attribs()[index as usize] = VertexAttrib::Uint(x, y, z, w); + self.current_vao() + .set_vertex_attrib_type(index, constants::UNSIGNED_INT); + self.base + .send_command(WebGLCommand::VertexAttribU(index, x, y, z, w)); + } } impl WebGL2RenderingContextMethods for WebGL2RenderingContext { @@ -1569,12 +1647,14 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11 fn DrawArrays(&self, mode: u32, first: i32, count: i32) { self.validate_uniform_block_for_draw(); + self.validate_vertex_attribs_for_draw(); self.base.DrawArrays(mode, first, count) } /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11 fn DrawElements(&self, mode: u32, count: i32, type_: u32, offset: i64) { self.validate_uniform_block_for_draw(); + self.validate_vertex_attribs_for_draw(); self.base.DrawElements(mode, count, type_, offset) } @@ -2591,6 +2671,40 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { self.base.VertexAttrib4fv(indx, v) } + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.8 + fn VertexAttribI4i(&self, index: u32, x: i32, y: i32, z: i32, w: i32) { + self.vertex_attrib_i(index, x, y, z, w) + } + + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.8 + fn VertexAttribI4iv(&self, index: u32, v: Int32ArrayOrLongSequence) { + let values = match v { + Int32ArrayOrLongSequence::Int32Array(v) => v.to_vec(), + Int32ArrayOrLongSequence::LongSequence(v) => v, + }; + if values.len() < 4 { + return self.base.webgl_error(InvalidValue); + } + self.vertex_attrib_i(index, values[0], values[1], values[2], values[3]); + } + + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.8 + fn VertexAttribI4ui(&self, index: u32, x: u32, y: u32, z: u32, w: u32) { + self.vertex_attrib_u(index, x, y, z, w) + } + + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.8 + fn VertexAttribI4uiv(&self, index: u32, v: Uint32ArrayOrUnsignedLongSequence) { + let values = match v { + Uint32ArrayOrUnsignedLongSequence::Uint32Array(v) => v.to_vec(), + Uint32ArrayOrUnsignedLongSequence::UnsignedLongSequence(v) => v, + }; + if values.len() < 4 { + return self.base.webgl_error(InvalidValue); + } + self.vertex_attrib_u(index, values[0], values[1], values[2], values[3]); + } + /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn VertexAttribPointer( &self, @@ -2605,6 +2719,21 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { .VertexAttribPointer(attrib_id, size, data_type, normalized, stride, offset) } + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.8 + fn VertexAttribIPointer(&self, index: u32, size: i32, type_: u32, stride: i32, offset: i64) { + match type_ { + constants::BYTE | + constants::UNSIGNED_BYTE | + constants::SHORT | + constants::UNSIGNED_SHORT | + constants::INT | + constants::UNSIGNED_INT => {}, + _ => return self.base.webgl_error(InvalidEnum), + }; + self.base + .VertexAttribPointer(index, size, type_, false, stride, offset) + } + /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.4 fn Viewport(&self, x: i32, y: i32, width: i32, height: i32) { self.base.Viewport(x, y, width, height) @@ -2820,6 +2949,7 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.9 fn DrawArraysInstanced(&self, mode: u32, first: i32, count: i32, primcount: i32) { self.validate_uniform_block_for_draw(); + self.validate_vertex_attribs_for_draw(); handle_potential_webgl_error!( self.base, self.base @@ -2837,6 +2967,7 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { primcount: i32, ) { self.validate_uniform_block_for_draw(); + self.validate_vertex_attribs_for_draw(); handle_potential_webgl_error!( self.base, self.base @@ -2859,6 +2990,7 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { return; } self.validate_uniform_block_for_draw(); + self.validate_vertex_attribs_for_draw(); handle_potential_webgl_error!( self.base, self.base |