diff options
Diffstat (limited to 'components/script/dom/webglprogram.rs')
-rw-r--r-- | components/script/dom/webglprogram.rs | 70 |
1 files changed, 66 insertions, 4 deletions
diff --git a/components/script/dom/webglprogram.rs b/components/script/dom/webglprogram.rs index 9ac3f4e1ad4..6382897efb3 100644 --- a/components/script/dom/webglprogram.rs +++ b/components/script/dom/webglprogram.rs @@ -24,6 +24,7 @@ pub struct WebGLProgram { webgl_object: WebGLObject, id: WebGLProgramId, is_deleted: Cell<bool>, + link_called: Cell<bool>, linked: Cell<bool>, fragment_shader: MutNullableHeap<JS<WebGLShader>>, vertex_shader: MutNullableHeap<JS<WebGLShader>>, @@ -39,6 +40,7 @@ impl WebGLProgram { webgl_object: WebGLObject::new_inherited(), id: id, is_deleted: Cell::new(false), + link_called: Cell::new(false), linked: Cell::new(false), fragment_shader: Default::default(), vertex_shader: Default::default(), @@ -91,27 +93,38 @@ impl WebGLProgram { self.is_deleted.get() } + pub fn is_linked(&self) -> bool { + self.linked.get() + } + /// glLinkProgram - pub fn link(&self) { + pub fn link(&self) -> WebGLResult<()> { + if self.is_deleted() { + return Err(WebGLError::InvalidOperation); + } self.linked.set(false); + self.link_called.set(true); match self.fragment_shader.get() { Some(ref shader) if shader.successfully_compiled() => {}, - _ => return, + _ => return Ok(()), // callers use gl.LINK_STATUS to check link errors } match self.vertex_shader.get() { Some(ref shader) if shader.successfully_compiled() => {}, - _ => return, + _ => return Ok(()), // callers use gl.LINK_STATUS to check link errors } self.linked.set(true); - self.renderer.send(CanvasMsg::WebGL(WebGLCommand::LinkProgram(self.id))).unwrap(); + Ok(()) } /// glUseProgram pub fn use_program(&self) -> WebGLResult<()> { + if self.is_deleted() { + return Err(WebGLError::InvalidOperation); + } if !self.linked.get() { return Err(WebGLError::InvalidOperation); } @@ -120,8 +133,20 @@ impl WebGLProgram { Ok(()) } + /// glValidateProgram + pub fn validate(&self) -> WebGLResult<()> { + if self.is_deleted() { + return Err(WebGLError::InvalidOperation); + } + self.renderer.send(CanvasMsg::WebGL(WebGLCommand::ValidateProgram(self.id))).unwrap(); + Ok(()) + } + /// glAttachShader pub fn attach_shader(&self, shader: &WebGLShader) -> WebGLResult<()> { + if self.is_deleted() || shader.is_deleted() { + return Err(WebGLError::InvalidOperation); + } let shader_slot = match shader.gl_type() { constants::FRAGMENT_SHADER => &self.fragment_shader, constants::VERTEX_SHADER => &self.vertex_shader, @@ -147,6 +172,9 @@ impl WebGLProgram { /// glDetachShader pub fn detach_shader(&self, shader: &WebGLShader) -> WebGLResult<()> { + if self.is_deleted() { + return Err(WebGLError::InvalidOperation); + } let shader_slot = match shader.gl_type() { constants::FRAGMENT_SHADER => &self.fragment_shader, constants::VERTEX_SHADER => &self.vertex_shader, @@ -174,6 +202,9 @@ impl WebGLProgram { /// glBindAttribLocation pub fn bind_attrib_location(&self, index: u32, name: DOMString) -> WebGLResult<()> { + if self.is_deleted() { + return Err(WebGLError::InvalidOperation); + } if name.len() > MAX_UNIFORM_AND_ATTRIBUTE_LEN { return Err(WebGLError::InvalidValue); } @@ -190,6 +221,9 @@ impl WebGLProgram { } pub fn get_active_uniform(&self, index: u32) -> WebGLResult<Root<WebGLActiveInfo>> { + if self.is_deleted() { + return Err(WebGLError::InvalidValue); + } let (sender, receiver) = ipc::channel().unwrap(); self.renderer .send(CanvasMsg::WebGL(WebGLCommand::GetActiveUniform(self.id, index, sender))) @@ -201,6 +235,9 @@ impl WebGLProgram { /// glGetActiveAttrib pub fn get_active_attrib(&self, index: u32) -> WebGLResult<Root<WebGLActiveInfo>> { + if self.is_deleted() { + return Err(WebGLError::InvalidValue); + } let (sender, receiver) = ipc::channel().unwrap(); self.renderer .send(CanvasMsg::WebGL(WebGLCommand::GetActiveAttrib(self.id, index, sender))) @@ -212,6 +249,9 @@ impl WebGLProgram { /// glGetAttribLocation pub fn get_attrib_location(&self, name: DOMString) -> WebGLResult<Option<i32>> { + if !self.is_linked() || self.is_deleted() { + return Err(WebGLError::InvalidOperation); + } if name.len() > MAX_UNIFORM_AND_ATTRIBUTE_LEN { return Err(WebGLError::InvalidValue); } @@ -234,6 +274,9 @@ impl WebGLProgram { /// glGetUniformLocation pub fn get_uniform_location(&self, name: DOMString) -> WebGLResult<Option<i32>> { + if !self.is_linked() || self.is_deleted() { + return Err(WebGLError::InvalidOperation); + } if name.len() > MAX_UNIFORM_AND_ATTRIBUTE_LEN { return Err(WebGLError::InvalidValue); } @@ -250,6 +293,25 @@ impl WebGLProgram { Ok(receiver.recv().unwrap()) } + /// glGetProgramInfoLog + pub fn get_info_log(&self) -> WebGLResult<String> { + if self.is_deleted() { + return Err(WebGLError::InvalidOperation); + } + if self.link_called.get() { + let shaders_compiled = match (self.fragment_shader.get(), self.vertex_shader.get()) { + (Some(fs), Some(vs)) => fs.successfully_compiled() && vs.successfully_compiled(), + _ => false + }; + if !shaders_compiled { + return Ok("One or more shaders failed to compile".to_string()); + } + } + let (sender, receiver) = ipc::channel().unwrap(); + self.renderer.send(CanvasMsg::WebGL(WebGLCommand::GetProgramInfoLog(self.id, sender))).unwrap(); + Ok(receiver.recv().unwrap()) + } + /// glGetProgramParameter pub fn parameter(&self, param_id: u32) -> WebGLResult<WebGLParameter> { let (sender, receiver) = ipc::channel().unwrap(); |