aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/webglprogram.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/webglprogram.rs')
-rw-r--r--components/script/dom/webglprogram.rs70
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();