diff options
Diffstat (limited to 'components/script/dom/webglprogram.rs')
-rw-r--r-- | components/script/dom/webglprogram.rs | 149 |
1 files changed, 148 insertions, 1 deletions
diff --git a/components/script/dom/webglprogram.rs b/components/script/dom/webglprogram.rs index 3b040a170b1..556573aae2e 100644 --- a/components/script/dom/webglprogram.rs +++ b/components/script/dom/webglprogram.rs @@ -4,6 +4,7 @@ // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl use crate::dom::bindings::cell::{DomRefCell, Ref}; +use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextConstants as constants2; use crate::dom::bindings::codegen::Bindings::WebGLProgramBinding; use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants; use crate::dom::bindings::inheritance::Castable; @@ -16,7 +17,9 @@ use crate::dom::webglrenderingcontext::WebGLRenderingContext; use crate::dom::webglshader::WebGLShader; use crate::dom::webgluniformlocation::WebGLUniformLocation; use canvas_traits::webgl::{webgl_channel, WebGLProgramId, WebGLResult}; -use canvas_traits::webgl::{ActiveAttribInfo, ActiveUniformInfo, WebGLCommand, WebGLError}; +use canvas_traits::webgl::{ + ActiveAttribInfo, ActiveUniformBlockInfo, ActiveUniformInfo, WebGLCommand, WebGLError, +}; use dom_struct::dom_struct; use fnv::FnvHashSet; use std::cell::Cell; @@ -34,6 +37,7 @@ pub struct WebGLProgram { vertex_shader: MutNullableDom<WebGLShader>, active_attribs: DomRefCell<Box<[ActiveAttribInfo]>>, active_uniforms: DomRefCell<Box<[ActiveUniformInfo]>>, + active_uniform_blocks: DomRefCell<Box<[ActiveUniformBlockInfo]>>, transform_feedback_varyings_length: Cell<i32>, transform_feedback_mode: Cell<i32>, } @@ -52,6 +56,7 @@ impl WebGLProgram { vertex_shader: Default::default(), active_attribs: DomRefCell::new(vec![].into()), active_uniforms: DomRefCell::new(vec![].into()), + active_uniform_blocks: DomRefCell::new(vec![].into()), transform_feedback_varyings_length: Default::default(), transform_feedback_mode: Default::default(), } @@ -143,6 +148,7 @@ impl WebGLProgram { .set(self.link_generation.get().checked_add(1).unwrap()); *self.active_attribs.borrow_mut() = Box::new([]); *self.active_uniforms.borrow_mut() = Box::new([]); + *self.active_uniform_blocks.borrow_mut() = Box::new([]); match self.fragment_shader.get() { Some(ref shader) if shader.successfully_compiled() => {}, @@ -197,6 +203,7 @@ impl WebGLProgram { .set(link_info.transform_feedback_mode); *self.active_attribs.borrow_mut() = link_info.active_attribs; *self.active_uniforms.borrow_mut() = link_info.active_uniforms; + *self.active_uniform_blocks.borrow_mut() = link_info.active_uniform_blocks; Ok(()) } @@ -208,6 +215,10 @@ impl WebGLProgram { Ref::map(self.active_uniforms.borrow(), |uniforms| &**uniforms) } + pub fn active_uniform_blocks(&self) -> Ref<[ActiveUniformBlockInfo]> { + Ref::map(self.active_uniform_blocks.borrow(), |blocks| &**blocks) + } + /// glValidateProgram pub fn validate(&self) -> WebGLResult<()> { if self.is_deleted() { @@ -413,6 +424,142 @@ impl WebGLProgram { ))) } + pub fn get_uniform_block_index(&self, name: DOMString) -> WebGLResult<u32> { + if !self.link_called.get() || self.is_deleted() { + return Err(WebGLError::InvalidOperation); + } + + if !validate_glsl_name(&name)? { + return Ok(constants2::INVALID_INDEX); + } + + let (sender, receiver) = webgl_channel().unwrap(); + self.upcast::<WebGLObject>() + .context() + .send_command(WebGLCommand::GetUniformBlockIndex( + self.id, + name.into(), + sender, + )); + Ok(receiver.recv().unwrap()) + } + + pub fn get_uniform_indices(&self, names: Vec<DOMString>) -> WebGLResult<Vec<u32>> { + if !self.link_called.get() || self.is_deleted() { + return Err(WebGLError::InvalidOperation); + } + + let validation_errors = names + .iter() + .map(|name| validate_glsl_name(&name)) + .collect::<Vec<_>>(); + let first_validation_error = validation_errors.iter().find(|result| result.is_err()); + if let Some(error) = first_validation_error { + return Err(error.unwrap_err()); + } + + let names = names + .iter() + .map(|name| name.to_string()) + .collect::<Vec<_>>(); + + let (sender, receiver) = webgl_channel().unwrap(); + self.upcast::<WebGLObject>() + .context() + .send_command(WebGLCommand::GetUniformIndices(self.id, names, sender)); + Ok(receiver.recv().unwrap()) + } + + pub fn get_active_uniforms(&self, indices: Vec<u32>, pname: u32) -> WebGLResult<Vec<i32>> { + if !self.is_linked() || self.is_deleted() { + return Err(WebGLError::InvalidOperation); + } + + match pname { + constants2::UNIFORM_TYPE | + constants2::UNIFORM_SIZE | + constants2::UNIFORM_BLOCK_INDEX | + constants2::UNIFORM_OFFSET | + constants2::UNIFORM_ARRAY_STRIDE | + constants2::UNIFORM_MATRIX_STRIDE | + constants2::UNIFORM_IS_ROW_MAJOR => {}, + _ => return Err(WebGLError::InvalidEnum), + } + + if indices.len() > self.active_uniforms.borrow().len() { + return Err(WebGLError::InvalidValue); + } + + let (sender, receiver) = webgl_channel().unwrap(); + self.upcast::<WebGLObject>() + .context() + .send_command(WebGLCommand::GetActiveUniforms( + self.id, indices, pname, sender, + )); + Ok(receiver.recv().unwrap()) + } + + pub fn get_active_uniform_block_parameter( + &self, + block_index: u32, + pname: u32, + ) -> WebGLResult<Vec<i32>> { + if !self.link_called.get() || self.is_deleted() { + return Err(WebGLError::InvalidOperation); + } + + if block_index as usize >= self.active_uniform_blocks.borrow().len() { + return Err(WebGLError::InvalidValue); + } + + match pname { + constants2::UNIFORM_BLOCK_BINDING | + constants2::UNIFORM_BLOCK_DATA_SIZE | + constants2::UNIFORM_BLOCK_ACTIVE_UNIFORMS | + constants2::UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES | + constants2::UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER | + constants2::UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER => {}, + _ => return Err(WebGLError::InvalidEnum), + } + + let (sender, receiver) = webgl_channel().unwrap(); + self.upcast::<WebGLObject>().context().send_command( + WebGLCommand::GetActiveUniformBlockParameter(self.id, block_index, pname, sender), + ); + Ok(receiver.recv().unwrap()) + } + + pub fn get_active_uniform_block_name(&self, block_index: u32) -> WebGLResult<String> { + if !self.link_called.get() || self.is_deleted() { + return Err(WebGLError::InvalidOperation); + } + + if block_index as usize >= self.active_uniforms.borrow().len() { + return Err(WebGLError::InvalidValue); + } + + let (sender, receiver) = webgl_channel().unwrap(); + self.upcast::<WebGLObject>().context().send_command( + WebGLCommand::GetActiveUniformBlockName(self.id, block_index, sender), + ); + Ok(receiver.recv().unwrap()) + } + + pub fn bind_uniform_block(&self, block_index: u32, block_binding: u32) -> WebGLResult<()> { + if block_index as usize >= self.active_uniform_blocks.borrow().len() { + return Err(WebGLError::InvalidValue); + } + + self.upcast::<WebGLObject>() + .context() + .send_command(WebGLCommand::UniformBlockBinding( + self.id, + block_index, + block_binding, + )); + Ok(()) + } + /// glGetProgramInfoLog pub fn get_info_log(&self) -> WebGLResult<String> { if self.is_deleted() { |