diff options
author | ecoal95 <ecoal95@gmail.com> | 2015-06-14 22:55:50 +0200 |
---|---|---|
committer | ecoal95 <ecoal95@gmail.com> | 2015-07-06 19:54:05 +0200 |
commit | b1765c68821d12a21cd304f7dffaa3bdc8f101e4 (patch) | |
tree | d98d8aa769e2894c5ffee3e8597ed93945d4bbed /components/script/dom/webglprogram.rs | |
parent | c0222628264423a67bf98775be83dcf2f85211ab (diff) | |
download | servo-b1765c68821d12a21cd304f7dffaa3bdc8f101e4.tar.gz servo-b1765c68821d12a21cd304f7dffaa3bdc8f101e4.zip |
webgl: Refactor implementation to move logic inside the DOM interfaces
This improves the encapsulation and consistency in our WebGL
implementation.
Also allows to implement new methods such as `getShaderSource()`.
It will also allow us to use `delete()` in the destructors of them (note
that we will want to keep track of them from the context).
Diffstat (limited to 'components/script/dom/webglprogram.rs')
-rw-r--r-- | components/script/dom/webglprogram.rs | 99 |
1 files changed, 93 insertions, 6 deletions
diff --git a/components/script/dom/webglprogram.rs b/components/script/dom/webglprogram.rs index 3e6191d764c..63496f9bff6 100644 --- a/components/script/dom/webglprogram.rs +++ b/components/script/dom/webglprogram.rs @@ -13,27 +13,114 @@ use dom::webglobject::WebGLObject; pub struct WebGLProgram { webgl_object: WebGLObject, id: u32, + is_deleted: Cell<bool>, + fragment_shader: MutNullableHeap<JS<WebGLShader>>, + vertex_shader: MutNullableHeap<JS<WebGLShader>>, + renderer: Sender<CanvasMsg>, } impl WebGLProgram { - fn new_inherited(id: u32) -> WebGLProgram { + fn new_inherited(renderer: Sender<CanvasMsg>, id: u32) -> WebGLProgram { WebGLProgram { webgl_object: WebGLObject::new_inherited(), id: id, + is_deleted: Cell::new(false), + fragment_shader: Default::default(), + vertex_shader: Default::default(), + renderer: renderer, } } - pub fn new(global: GlobalRef, id: u32) -> Root<WebGLProgram> { - reflect_dom_object(box WebGLProgram::new_inherited(id), global, WebGLProgramBinding::Wrap) + pub fn maybe_new(global: GlobalRef, renderer: Sender<CanvasMsg>) -> Option<Root<WebGLProgram>> { + let (sender, receiver) = channel(); + renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::CreateProgram(sender))).unwrap(); + receiver.recv().unwrap() + .map(|program_id| WebGLProgram::new(global, renderer, *program_id)) + } + + pub fn new(global: GlobalRef, renderer: Sender<CanvasMsg>, id: u32) -> Root<WebGLProgram> { + reflect_dom_object(box WebGLProgram::new_inherited(renderer, id), global, WebGLProgramBinding::Wrap) } } pub trait WebGLProgramHelpers { - fn get_id(self) -> u32; + fn delete(self); + fn link(self); + fn use_program(self); + fn attach_shader(self, shader: JSRef<WebGLShader>) -> WebGLResult<()>; + fn get_attrib_location(self, name: String) -> WebGLResult<Option<i32>>; + fn get_uniform_location(self, name: String) -> WebGLResult<Option<i32>>; } impl<'a> WebGLProgramHelpers for &'a WebGLProgram { - fn get_id(self) -> u32 { - self.id + /// glDeleteProgram + fn delete(self) { + if !self.is_deleted.get() { + self.is_deleted.set(true); + self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteProgram(self.id))).unwrap(); + } + } + + /// glLinkProgram + fn link(self) { + self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::LinkProgram(self.id))).unwrap(); + } + + /// glUseProgram + fn use_program(self) { + self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::UseProgram(self.id))).unwrap(); + } + + /// glAttachShader + fn attach_shader(self, shader: &'a WebGLShader) -> WebGLResult<()> { + let shader_slot = match shader.gl_type() { + constants::FRAGMENT_SHADER => &self.fragment_shader, + constants::VERTEX_SHADER => &self.vertex_shader, + _ => return Err(WebGLError::InvalidOperation), + }; + + // TODO(ecoal95): Differenciate between same shader already assigned and other previous + // shader. + if shader_slot.get().is_some() { + return Err(WebGLError::InvalidOperation); + } + + shader_slot.set(Some(JS::from_rooted(shader))); + + self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::AttachShader(self.id, shader.id()))).unwrap(); + + Ok(()) + } + + /// glGetAttribLocation + fn get_attrib_location(self, name: String) -> WebGLResult<Option<i32>> { + if name.len() > MAX_UNIFORM_AND_ATTRIBUTE_LEN { + return Err(WebGLError::InvalidValue); + } + + // Check if the name is reserved + if name.starts_with("webgl") || name.starts_with("_webgl_") { + return Ok(None); + } + + let (sender, receiver) = channel(); + self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::GetAttribLocation(self.id, name, sender))).unwrap(); + Ok(receiver.recv().unwrap()) + } + + /// glGetUniformLocation + fn get_uniform_location(self, name: String) -> WebGLResult<Option<i32>> { + if name.len() > MAX_UNIFORM_AND_ATTRIBUTE_LEN { + return Err(WebGLError::InvalidValue); + } + + // Check if the name is reserved + if name.starts_with("webgl") || name.starts_with("_webgl_") { + return Ok(None); + } + + let (sender, receiver) = channel(); + self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::GetUniformLocation(self.id, name, sender))).unwrap(); + Ok(receiver.recv().unwrap()) } } |