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/webglrenderingcontext.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/webglrenderingcontext.rs')
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 169 |
1 files changed, 85 insertions, 84 deletions
diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 766c61fa57c..42e748d51d6 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -30,6 +30,20 @@ use std::sync::mpsc::{channel, Sender}; use util::str::DOMString; use offscreen_gl_context::GLContextAttributes; +pub const MAX_UNIFORM_AND_ATTRIBUTE_LEN : usize = 256; + +macro_rules! handle_potential_webgl_error { + ($context:ident, $call:expr, $return_on_error:expr) => { + match $call { + Ok(ret) => ret, + Err(error) => { + $context.handle_webgl_error(error); + $return_on_error + } + } + } +} + #[dom_struct] pub struct WebGLRenderingContext { reflector_: Reflector, @@ -174,48 +188,44 @@ impl<'a> WebGLRenderingContextMethods for &'a WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 fn AttachShader(self, program: Option<&WebGLProgram>, shader: Option<&WebGLShader>) { - let program_id = match program { - Some(program) => program.get_id(), - None => return, - }; - let shader_id = match shader { - Some(shader) => shader.get_id(), - None => return, - }; - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::AttachShader(program_id, shader_id))).unwrap() + if let Some(program) = program { + if let Some(shader) = shader { + handle_potential_webgl_error!(self, program.attach_shader(shader), ()); + } + } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5 fn BindBuffer(self, target: u32, buffer: Option<&WebGLBuffer>) { - let id = buffer.map(|buf| buf.get_id()).unwrap_or(0); - self.renderer.send( - CanvasMsg::WebGL(CanvasWebGLMsg::BindBuffer(target, id))).unwrap() + if let Some(buffer) = buffer { + buffer.bind(target) + } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6 fn BindFramebuffer(self, target: u32, framebuffer: Option<&WebGLFramebuffer>) { - let id = framebuffer.map(|fb| fb.get_id()).unwrap_or(0); - self.renderer.send( - CanvasMsg::WebGL(CanvasWebGLMsg::BindFramebuffer(target, id))).unwrap() + if let Some(framebuffer) = framebuffer { + framebuffer.bind(target) + } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.7 fn BindRenderbuffer(self, target: u32, renderbuffer: Option<&WebGLRenderbuffer>) { - let id = renderbuffer.map(|rb| rb.get_id()).unwrap_or(0); - self.renderer.send( - CanvasMsg::WebGL(CanvasWebGLMsg::BindRenderbuffer(target, id))).unwrap() + if let Some(renderbuffer) = renderbuffer { + renderbuffer.bind(target) + } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 fn BindTexture(self, target: u32, texture: Option<&WebGLTexture>) { - let id = texture.map(|tex| tex.get_id()).unwrap_or(0); - self.renderer.send( - CanvasMsg::WebGL(CanvasWebGLMsg::BindTexture(target, id))).unwrap() + if let Some(texture) = texture { + texture.bind(target) + } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5 #[allow(unsafe_code)] - fn BufferData(self, _cx: *mut JSContext, target: u32, data: Option<*mut JSObject>, usage: u32) { + fn BufferData(self, cx: *mut JSContext, target: u32, data: Option<*mut JSObject>, usage: u32) { let data = match data { Some(data) => data, None => return, @@ -246,104 +256,84 @@ impl<'a> WebGLRenderingContextMethods for &'a WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 fn CompileShader(self, shader: Option<&WebGLShader>) { - let shader_id = match shader { - Some(shader) => shader.get_id(), - None => return, - }; - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::CompileShader(shader_id))).unwrap() + if let Some(shader) = shader { + shader.compile() + } } // TODO(ecoal95): Probably in the future we should keep track of the // generated objects, either here or in the webgl task // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5 fn CreateBuffer(self) -> Option<Root<WebGLBuffer>> { - let (sender, receiver) = channel(); - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::CreateBuffer(sender))).unwrap(); - receiver.recv().unwrap() - .map(|buffer_id| WebGLBuffer::new(self.global.root().r(), *buffer_id)) + WebGLBuffer::maybe_new(self.global.root().r(), self.renderer.clone()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6 fn CreateFramebuffer(self) -> Option<Root<WebGLFramebuffer>> { - let (sender, receiver) = channel(); - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::CreateFramebuffer(sender))).unwrap(); - receiver.recv().unwrap() - .map(|fb_id| WebGLFramebuffer::new(self.global.root().r(), *fb_id)) + WebGLFramebuffer::maybe_new(self.global.root().r(), self.renderer.clone()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.7 fn CreateRenderbuffer(self) -> Option<Root<WebGLRenderbuffer>> { - let (sender, receiver) = channel(); - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::CreateRenderbuffer(sender))).unwrap(); - receiver.recv().unwrap() - .map(|program_id| WebGLRenderbuffer::new(self.global.root().r(), *program_id)) + WebGLRenderbuffer::maybe_new(self.global.root().r(), self.renderer.clone()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 fn CreateTexture(self) -> Option<Root<WebGLTexture>> { - let (sender, receiver) = channel(); - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::CreateTexture(sender))).unwrap(); - receiver.recv().unwrap() - .map(|texture_id| WebGLTexture::new(self.global.root().r(), *texture_id)) + WebGLTexture::maybe_new(self.global.root().r(), self.renderer.clone()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 fn CreateProgram(self) -> Option<Root<WebGLProgram>> { - let (sender, receiver) = channel(); - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::CreateProgram(sender))).unwrap(); - receiver.recv().unwrap() - .map(|program_id| WebGLProgram::new(self.global.root().r(), *program_id)) + WebGLProgram::maybe_new(self.global.root().r(), self.renderer.clone()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 // TODO(ecoal95): Check if constants are cross-platform or if we must make a translation // between WebGL constants and native ones. fn CreateShader(self, shader_type: u32) -> Option<Root<WebGLShader>> { - let (sender, receiver) = channel(); - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::CreateShader(shader_type, sender))).unwrap(); - receiver.recv().unwrap() - .map(|shader_id| WebGLShader::new(self.global.root().r(), *shader_id)) + WebGLShader::maybe_new(self.global.root().r(), self.renderer.clone(), shader_type) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5 fn DeleteBuffer(self, buffer: Option<&WebGLBuffer>) { if let Some(buffer) = buffer { - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteBuffer(buffer.get_id()))).unwrap(); + buffer.delete() } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6 fn DeleteFramebuffer(self, framebuffer: Option<&WebGLFramebuffer>) { if let Some(framebuffer) = framebuffer { - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteFramebuffer(framebuffer.get_id()))).unwrap(); + framebuffer.delete() } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.7 fn DeleteRenderbuffer(self, renderbuffer: Option<&WebGLRenderbuffer>) { if let Some(renderbuffer) = renderbuffer { - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteRenderbuffer(renderbuffer.get_id()))).unwrap(); + renderbuffer.delete() } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 fn DeleteTexture(self, texture: Option<&WebGLTexture>) { if let Some(texture) = texture { - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteTexture(texture.get_id()))).unwrap(); + texture.delete() } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 fn DeleteProgram(self, program: Option<&WebGLProgram>) { if let Some(program) = program { - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteProgram(program.get_id()))).unwrap(); + program.delete() } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 fn DeleteShader(self, shader: Option<&WebGLShader>) { if let Some(shader) = shader { - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteShader(shader.get_id()))).unwrap(); + shader.delete() } } @@ -359,21 +349,17 @@ impl<'a> WebGLRenderingContextMethods for &'a WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn GetAttribLocation(self, program: Option<&WebGLProgram>, name: DOMString) -> i32 { - let program_id = match program { - Some(program) => program.get_id(), - None => return -1, - }; - let (sender, receiver) = channel(); - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::GetAttribLocation(program_id, name, sender))).unwrap(); - receiver.recv().unwrap() + if let Some(program) = program { + handle_potential_webgl_error!(self, program.get_attrib_location(name), None).unwrap_or(-1) + } else { + -1 + } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 fn GetShaderInfoLog(self, shader: Option<&WebGLShader>) -> Option<DOMString> { if let Some(shader) = shader { - let (sender, receiver) = channel(); - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::GetShaderInfoLog(shader.get_id(), sender))).unwrap(); - Some(receiver.recv().unwrap()) + shader.info_log() } else { None } @@ -382,10 +368,11 @@ impl<'a> WebGLRenderingContextMethods for &'a WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 fn GetShaderParameter(self, _: *mut JSContext, shader: Option<&WebGLShader>, param_id: u32) -> JSVal { if let Some(shader) = shader { - let (sender, receiver) = channel(); - self.renderer.send( - CanvasMsg::WebGL(CanvasWebGLMsg::GetShaderParameter(shader.get_id(), param_id, sender))).unwrap(); - Int32Value(receiver.recv().unwrap()) + match handle_potential_webgl_error!(self, shader.parameter(param_id), WebGLShaderParameter::Invalid) { + WebGLShaderParameter::Int(val) => Int32Value(val), + WebGLShaderParameter::Bool(val) => BooleanValue(val), + WebGLShaderParameter::Invalid => NullValue(), + } } else { NullValue() } @@ -396,10 +383,7 @@ impl<'a> WebGLRenderingContextMethods for &'a WebGLRenderingContext { program: Option<&WebGLProgram>, name: DOMString) -> Option<Root<WebGLUniformLocation>> { if let Some(program) = program { - let (sender, receiver) = channel(); - self.renderer.send( - CanvasMsg::WebGL(CanvasWebGLMsg::GetUniformLocation(program.get_id(), name, sender))).unwrap(); - receiver.recv().unwrap() + handle_potential_webgl_error!(self, program.get_uniform_location(name), None) .map(|location| WebGLUniformLocation::new(self.global.root().r(), location)) } else { None @@ -409,15 +393,23 @@ impl<'a> WebGLRenderingContextMethods for &'a WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 fn LinkProgram(self, program: Option<&WebGLProgram>) { if let Some(program) = program { - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::LinkProgram(program.get_id()))).unwrap() + program.link() } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 fn ShaderSource(self, shader: Option<&WebGLShader>, source: DOMString) { if let Some(shader) = shader { - self.renderer.send( - CanvasMsg::WebGL(CanvasWebGLMsg::ShaderSource(shader.get_id(), source))).unwrap(); + shader.set_source(source) + } + } + + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 + fn GetShaderSource(self, shader: Option<&WebGLShader>) -> Option<DOMString> { + if let Some(shader) = shader { + shader.source() + } else { + None } } @@ -428,7 +420,7 @@ impl<'a> WebGLRenderingContextMethods for &'a WebGLRenderingContext { uniform: Option<&WebGLUniformLocation>, data: Option<*mut JSObject>) { let uniform_id = match uniform { - Some(uniform) => uniform.get_id(), + Some(uniform) => uniform.id(), None => return, }; @@ -446,11 +438,9 @@ impl<'a> WebGLRenderingContextMethods for &'a WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 fn UseProgram(self, program: Option<&WebGLProgram>) { - let program_id = match program { - Some(program) => program.get_id(), - None => return, - }; - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::UseProgram(program_id as u32))).unwrap() + if let Some(program) = program { + program.use_program() + } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 @@ -473,6 +463,17 @@ impl<'a> WebGLRenderingContextMethods for &'a WebGLRenderingContext { } } +pub trait WebGLRenderingContextHelpers { + fn handle_webgl_error(&self, err: WebGLError); +} + +impl<'a> WebGLRenderingContextHelpers for &'a WebGLRenderingContext { + fn handle_webgl_error(&self, _: WebGLError) { + debug!("WebGL error received"); + // ignore for now + } +} + pub trait LayoutCanvasWebGLRenderingContextHelpers { #[allow(unsafe_code)] unsafe fn get_renderer(&self) -> Sender<CanvasMsg>; |