diff options
Diffstat (limited to 'components/script/dom/webglprogram.rs')
-rw-r--r-- | components/script/dom/webglprogram.rs | 81 |
1 files changed, 51 insertions, 30 deletions
diff --git a/components/script/dom/webglprogram.rs b/components/script/dom/webglprogram.rs index 075672c8107..4fb1147e042 100644 --- a/components/script/dom/webglprogram.rs +++ b/components/script/dom/webglprogram.rs @@ -25,7 +25,8 @@ use std::cell::{Cell, Ref}; pub struct WebGLProgram { webgl_object: WebGLObject, id: WebGLProgramId, - is_deleted: Cell<bool>, + is_in_use: Cell<bool>, + marked_for_deletion: Cell<bool>, link_called: Cell<bool>, linked: Cell<bool>, link_generation: Cell<u64>, @@ -40,9 +41,10 @@ impl WebGLProgram { Self { webgl_object: WebGLObject::new_inherited(context), id: id, - is_deleted: Cell::new(false), - link_called: Cell::new(false), - linked: Cell::new(false), + is_in_use: Default::default(), + marked_for_deletion: Default::default(), + link_called: Default::default(), + linked: Default::default(), link_generation: Default::default(), fragment_shader: Default::default(), vertex_shader: Default::default(), @@ -73,25 +75,51 @@ impl WebGLProgram { } /// glDeleteProgram - pub fn delete(&self) { - if !self.is_deleted.get() { - self.is_deleted.set(true); - self.upcast::<WebGLObject>() - .context() - .send_command(WebGLCommand::DeleteProgram(self.id)); - - if let Some(shader) = self.fragment_shader.get() { - shader.decrement_attached_counter(); - } + pub fn mark_for_deletion(&self) { + if self.marked_for_deletion.get() { + return; + } + self.marked_for_deletion.set(true); + self.upcast::<WebGLObject>() + .context() + .send_command(WebGLCommand::DeleteProgram(self.id)); + if self.is_deleted() { + self.detach_shaders(); + } + } - if let Some(shader) = self.vertex_shader.get() { - shader.decrement_attached_counter(); - } + pub fn in_use(&self, value: bool) { + if self.is_in_use.get() == value { + return; + } + self.is_in_use.set(value); + if self.is_deleted() { + self.detach_shaders(); } } + fn detach_shaders(&self) { + assert!(self.is_deleted()); + if let Some(shader) = self.fragment_shader.get() { + shader.decrement_attached_counter(); + self.fragment_shader.set(None); + } + if let Some(shader) = self.vertex_shader.get() { + shader.decrement_attached_counter(); + self.vertex_shader.set(None); + } + } + + pub fn is_in_use(&self) -> bool { + self.is_in_use.get() + } + + pub fn is_marked_for_deletion(&self) -> bool { + self.marked_for_deletion.get() + } + pub fn is_deleted(&self) -> bool { - self.is_deleted.get() + self.marked_for_deletion.get() && !self.is_in_use.get() } pub fn is_linked(&self) -> bool { @@ -99,10 +127,7 @@ impl WebGLProgram { } /// glLinkProgram - pub fn link(&self) -> WebGLResult<()> { - if self.is_deleted() { - return Err(WebGLError::InvalidOperation); - } + pub fn link(&self) -> WebGLResult<()> { self.linked.set(false); self.link_generation.set(self.link_generation.get().checked_add(1).unwrap()); *self.active_attribs.borrow_mut() = Box::new([]); @@ -192,8 +217,6 @@ impl WebGLProgram { } }; - // TODO(emilio): Differentiate between same shader already assigned and other previous - // shader. if shader_slot.get().is_some() { return Err(WebGLError::InvalidOperation); } @@ -216,10 +239,7 @@ impl WebGLProgram { let shader_slot = match shader.gl_type() { constants::FRAGMENT_SHADER => &self.fragment_shader, constants::VERTEX_SHADER => &self.vertex_shader, - _ => { - error!("detachShader: Unexpected shader type"); - return Err(WebGLError::InvalidValue); - } + _ => return Err(WebGLError::InvalidValue), }; match shader_slot.get() { @@ -391,7 +411,7 @@ impl WebGLProgram { } pub fn attached_shaders(&self) -> WebGLResult<Vec<DomRoot<WebGLShader>>> { - if self.is_deleted.get() { + if self.marked_for_deletion.get() { return Err(WebGLError::InvalidValue); } Ok(match (self.vertex_shader.get(), self.fragment_shader.get()) { @@ -410,7 +430,8 @@ impl WebGLProgram { impl Drop for WebGLProgram { fn drop(&mut self) { - self.delete(); + self.in_use(false); + self.mark_for_deletion(); } } |