From 532b53ddc94cd99d737411b635f2fb6a6d50af51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 23 Dec 2015 09:22:01 +0100 Subject: [PATCH 1/8] webgl: Implement Uniform1f, Uniform1fv, and Uniform4f I was going to implement Uniform4fv with sequences, (since it practically implemented), but we can't until we support Float32Array args because codegen doesn't know how tu differenciate between both. --- components/canvas/webgl_paint_thread.rs | 6 ++- components/canvas_traits/lib.rs | 3 +- .../script/dom/webglrenderingcontext.rs | 53 +++++++++++++++---- .../dom/webidls/WebGLRenderingContext.webidl | 8 +-- 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/components/canvas/webgl_paint_thread.rs b/components/canvas/webgl_paint_thread.rs index 084ce49d491..84d4906aa85 100644 --- a/components/canvas/webgl_paint_thread.rs +++ b/components/canvas/webgl_paint_thread.rs @@ -157,8 +157,10 @@ impl WebGLPaintThread { gl::bind_texture(target, id), CanvasWebGLMsg::LinkProgram(program_id) => gl::link_program(program_id), - CanvasWebGLMsg::Uniform4fv(uniform_id, data) => - gl::uniform_4f(uniform_id, data[0], data[1], data[2], data[3]), + CanvasWebGLMsg::Uniform1f(uniform_id, x) => + gl::uniform_1f(uniform_id, x), + CanvasWebGLMsg::Uniform4f(uniform_id, x, y, z, w) => + gl::uniform_4f(uniform_id, x, y, z, w), CanvasWebGLMsg::UseProgram(program_id) => gl::use_program(program_id), CanvasWebGLMsg::VertexAttrib(attrib_id, x, y, z, w) => diff --git a/components/canvas_traits/lib.rs b/components/canvas_traits/lib.rs index 90ff7d0daac..bba0db60234 100644 --- a/components/canvas_traits/lib.rs +++ b/components/canvas_traits/lib.rs @@ -180,7 +180,8 @@ pub enum CanvasWebGLMsg { LineWidth(f32), PixelStorei(u32, i32), LinkProgram(u32), - Uniform4fv(i32, Vec), + Uniform1f(i32, f32), + Uniform4f(i32, f32, f32, f32, f32), UseProgram(u32), VertexAttrib(u32, f32, f32, f32, f32), VertexAttribPointer2f(u32, i32, bool, i32, u32), diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 7481b161a77..701ae737ba8 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -930,30 +930,61 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } } - #[allow(unsafe_code)] // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 - fn Uniform4fv(&self, - _cx: *mut JSContext, + fn Uniform1f(&self, uniform: Option<&WebGLUniformLocation>, - data: Option<*mut JSObject>) { + val: f32) { let uniform_id = match uniform { Some(uniform) => uniform.id(), None => return, }; - let data = match data { - Some(data) => data, + self.ipc_renderer + .send(CanvasMsg::WebGL(CanvasWebGLMsg::Uniform1f(uniform_id, val))) + .unwrap() + } + + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 + fn Uniform1fv(&self, + uniform: Option<&WebGLUniformLocation>, + data: Vec) { + if data.is_empty() { + return self.webgl_error(InvalidValue); + } + + self.Uniform1f(uniform, data[0]); + } + + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 + fn Uniform4f(&self, + uniform: Option<&WebGLUniformLocation>, + x: f32, y: f32, z: f32, w: f32) { + let uniform_id = match uniform { + Some(uniform) => uniform.id(), None => return, }; - if let Some(data_vec) = array_buffer_view_to_vec_checked::(data) { - if data_vec.len() < 4 { + self.ipc_renderer + .send(CanvasMsg::WebGL(CanvasWebGLMsg::Uniform4f(uniform_id, x, y, z, w))) + .unwrap() + } + + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 + fn Uniform4fv(&self, + _cx: *mut JSContext, + uniform: Option<&WebGLUniformLocation>, + data: Option<*mut JSObject>) { + let data = match data { + Some(data) => data, + None => return self.webgl_error(InvalidValue), + }; + + if let Some(data) = array_buffer_view_to_vec_checked::(data) { + if data.len() < 4 { return self.webgl_error(InvalidOperation); } - self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::Uniform4fv(uniform_id, data_vec))) - .unwrap() + self.Uniform4f(uniform, data[0], data[1], data[2], data[3]); } else { self.webgl_error(InvalidValue); } diff --git a/components/script/dom/webidls/WebGLRenderingContext.webidl b/components/script/dom/webidls/WebGLRenderingContext.webidl index c2c82b5ff17..37e1e5fe81d 100644 --- a/components/script/dom/webidls/WebGLRenderingContext.webidl +++ b/components/script/dom/webidls/WebGLRenderingContext.webidl @@ -644,9 +644,9 @@ interface WebGLRenderingContextBase //void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, // GLenum format, GLenum type, TexImageSource? source); // May throw DOMException - //void uniform1f(WebGLUniformLocation? location, GLfloat x); + void uniform1f(WebGLUniformLocation? location, GLfloat x); //void uniform1fv(WebGLUniformLocation? location, Float32Array v); - //void uniform1fv(WebGLUniformLocation? location, sequence v); + void uniform1fv(WebGLUniformLocation? location, sequence v); //void uniform1i(WebGLUniformLocation? location, GLint x); //void uniform1iv(WebGLUniformLocation? location, Int32Array v); //void uniform1iv(WebGLUniformLocation? location, sequence v); @@ -662,9 +662,9 @@ interface WebGLRenderingContextBase //void uniform3i(WebGLUniformLocation? location, GLint x, GLint y, GLint z); //void uniform3iv(WebGLUniformLocation? location, Int32Array v); //void uniform3iv(WebGLUniformLocation? location, sequence v); - //void uniform4f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void uniform4f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); // FIXME(dmarcos) The function below is the original function in the webIdl: - // void uniform4fv(WebGLUniformLocation? location, Float32Array v); + //void uniform4fv(WebGLUniformLocation? location, Float32Array v); // The Code genearator doesn't handle BufferDataSource so we're using 'optional object' // in the meantime void uniform4fv(WebGLUniformLocation? location, optional object v); From 221a58378450d26ff9e3bb645df8fcf5fb43994f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Tue, 29 Dec 2015 13:51:10 +0100 Subject: [PATCH 2/8] webgl: Track uniformlocation's program --- components/script/dom/webglprogram.rs | 4 +++ .../script/dom/webglrenderingcontext.rs | 29 ++++++++++++++----- components/script/dom/webgluniformlocation.rs | 13 +++++++-- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/components/script/dom/webglprogram.rs b/components/script/dom/webglprogram.rs index 350fc31929c..272eeae72aa 100644 --- a/components/script/dom/webglprogram.rs +++ b/components/script/dom/webglprogram.rs @@ -55,6 +55,10 @@ impl WebGLProgram { impl WebGLProgram { + pub fn id(&self) -> u32 { + self.id + } + /// glDeleteProgram pub fn delete(&self) { if !self.is_deleted.get() { diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 701ae737ba8..33735d83633 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -79,6 +79,7 @@ pub struct WebGLRenderingContext { bound_texture_cube_map: MutNullableHeap>, bound_buffer_array: MutNullableHeap>, bound_buffer_element_array: MutNullableHeap>, + current_program: MutNullableHeap>, } impl WebGLRenderingContext { @@ -106,6 +107,7 @@ impl WebGLRenderingContext { bound_texture_cube_map: MutNullableHeap::new(None), bound_buffer_array: MutNullableHeap::new(None), bound_buffer_element_array: MutNullableHeap::new(None), + current_program: MutNullableHeap::new(None), } }) } @@ -804,7 +806,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { name: DOMString) -> Option> { if let Some(program) = program { handle_potential_webgl_error!(self, program.get_uniform_location(name), None) - .map(|location| WebGLUniformLocation::new(self.global().r(), location)) + .map(|location| WebGLUniformLocation::new(self.global().r(), location, program.id())) } else { None } @@ -934,13 +936,18 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { fn Uniform1f(&self, uniform: Option<&WebGLUniformLocation>, val: f32) { - let uniform_id = match uniform { - Some(uniform) => uniform.id(), + let uniform = match uniform { + Some(uniform) => uniform, None => return, }; + match self.current_program.get() { + Some(ref program) if program.id() == uniform.program_id() => {}, + _ => return self.webgl_error(InvalidOperation), + }; + self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::Uniform1f(uniform_id, val))) + .send(CanvasMsg::WebGL(CanvasWebGLMsg::Uniform1f(uniform.id(), val))) .unwrap() } @@ -959,13 +966,18 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { fn Uniform4f(&self, uniform: Option<&WebGLUniformLocation>, x: f32, y: f32, z: f32, w: f32) { - let uniform_id = match uniform { - Some(uniform) => uniform.id(), + let uniform = match uniform { + Some(uniform) => uniform, None => return, }; + match self.current_program.get() { + Some(ref program) if program.id() == uniform.program_id() => {}, + _ => return self.webgl_error(InvalidOperation), + }; + self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::Uniform4f(uniform_id, x, y, z, w))) + .send(CanvasMsg::WebGL(CanvasWebGLMsg::Uniform4f(uniform.id(), x, y, z, w))) .unwrap() } @@ -993,7 +1005,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 fn UseProgram(&self, program: Option<&WebGLProgram>) { if let Some(program) = program { - program.use_program() + program.use_program(); + self.current_program.set(Some(program)); } } diff --git a/components/script/dom/webgluniformlocation.rs b/components/script/dom/webgluniformlocation.rs index 7367f9f1d7d..43244ec4a33 100644 --- a/components/script/dom/webgluniformlocation.rs +++ b/components/script/dom/webgluniformlocation.rs @@ -12,18 +12,21 @@ use dom::bindings::reflector::{Reflector, reflect_dom_object}; pub struct WebGLUniformLocation { reflector_: Reflector, id: i32, + program_id: u32, } impl WebGLUniformLocation { - fn new_inherited(id: i32) -> WebGLUniformLocation { + fn new_inherited(id: i32, program_id: u32) -> WebGLUniformLocation { WebGLUniformLocation { reflector_: Reflector::new(), id: id, + program_id: program_id, } } - pub fn new(global: GlobalRef, id: i32) -> Root { - reflect_dom_object(box WebGLUniformLocation::new_inherited(id), global, WebGLUniformLocationBinding::Wrap) + pub fn new(global: GlobalRef, id: i32, program_id: u32) -> Root { + reflect_dom_object( + box WebGLUniformLocation::new_inherited(id, program_id), global, WebGLUniformLocationBinding::Wrap) } } @@ -32,4 +35,8 @@ impl WebGLUniformLocation { pub fn id(&self) -> i32 { self.id } + + pub fn program_id(&self) -> u32 { + self.program_id + } } From 910b2260abcf68f52da674ab30a1577289625629 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Tue, 29 Dec 2015 13:55:34 +0100 Subject: [PATCH 3/8] webgl: Check for pending current_program errors --- components/script/dom/webglrenderingcontext.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 33735d83633..216d6779550 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -696,8 +696,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { constants::LINE_LOOP | constants::LINES | constants::TRIANGLE_STRIP | constants::TRIANGLE_FAN | constants::TRIANGLES => { - // TODO(ecoal95): Check the CURRENT_PROGRAM when we keep track of it, and if it's - // null generate an InvalidOperation error + if self.current_program.get().is_none() { + return self.webgl_error(InvalidOperation); + } + if first < 0 || count < 0 { self.webgl_error(InvalidValue); } else { @@ -733,8 +735,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } // TODO ensure a non-null WebGLBuffer must be bound to the ELEMENT_ARRAY_BUFFER - // TODO(ecoal95): Check the CURRENT_PROGRAM when we keep track of it, and if it's - // null generate an InvalidOperation error + if self.current_program.get().is_none() { + return self.webgl_error(InvalidOperation); + } + match mode { constants::POINTS | constants::LINE_STRIP | constants::LINE_LOOP | constants::LINES | From e3532dda249fbe206b5301bf4ac6592de687e47a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Tue, 29 Dec 2015 14:09:31 +0100 Subject: [PATCH 4/8] webgl: Check for bound element array buffer on DrawElements And remove outdated TODOs --- components/script/dom/webglrenderingcontext.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 216d6779550..b8feeb9b93c 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -286,8 +286,6 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.14 fn GetExtension(&self, _cx: *mut JSContext, _name: DOMString) -> *mut JSObject { - // TODO(ecoal95) we actually do not support extensions. - // `getSupportedExtensions` cannot be implemented as of right now (see #544) 0 as *mut JSObject } @@ -640,8 +638,6 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { WebGLProgram::maybe_new(self.global().r(), self.ipc_renderer.clone()) } - // TODO(ecoal95): Check if constants are cross-platform or if we must make a translation - // between WebGL constants and native ones. // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 fn CreateShader(&self, shader_type: u32) -> Option> { WebGLShader::maybe_new(self.global().r(), self.ipc_renderer.clone(), shader_type) @@ -734,8 +730,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { return self.webgl_error(InvalidValue); } - // TODO ensure a non-null WebGLBuffer must be bound to the ELEMENT_ARRAY_BUFFER - if self.current_program.get().is_none() { + if self.current_program.get().is_none() || self.bound_buffer_element_array.get().is_none() { return self.webgl_error(InvalidOperation); } From 5c23c3851a487f4f77462a699af9bc0cea9bb536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Tue, 29 Dec 2015 23:24:58 +0100 Subject: [PATCH 5/8] webgl: Remove old WebGLContextEvent idl It's already defined in its own idl file. --- .../script/dom/webidls/WebGLRenderingContext.webidl | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/components/script/dom/webidls/WebGLRenderingContext.webidl b/components/script/dom/webidls/WebGLRenderingContext.webidl index 37e1e5fe81d..ea49e38d4bd 100644 --- a/components/script/dom/webidls/WebGLRenderingContext.webidl +++ b/components/script/dom/webidls/WebGLRenderingContext.webidl @@ -718,13 +718,3 @@ interface WebGLRenderingContext }; WebGLRenderingContext implements WebGLRenderingContextBase; - -//[Constructor(DOMString type, optional WebGLContextEventInit eventInit)] -//interface WebGLContextEvent : Event { -// readonly attribute DOMString statusMessage; -//}; - -// EventInit is defined in the DOM4 specification. -//dictionary WebGLContextEventInit : EventInit { -// DOMString statusMessage; -//}; From 48962bd6b682504c677f63f8e945790205113a20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 4 Jan 2016 14:04:40 +0100 Subject: [PATCH 6/8] webgl: Improve debugging Now we can keep track of errors more easily. --- components/canvas/webgl_paint_thread.rs | 8 ++- components/canvas_traits/lib.rs | 77 +++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/components/canvas/webgl_paint_thread.rs b/components/canvas/webgl_paint_thread.rs index 84d4906aa85..e328e182680 100644 --- a/components/canvas/webgl_paint_thread.rs +++ b/components/canvas/webgl_paint_thread.rs @@ -46,6 +46,8 @@ impl WebGLPaintThread { /// NB: Not gl-related validations (names, lengths, accepted parameters...) are /// done in the corresponding DOM interfaces pub fn handle_webgl_message(&self, message: CanvasWebGLMsg) { + debug!("WebGL message: {:?}", message); + match message { CanvasWebGLMsg::GetContextAttributes(sender) => self.context_attributes(sender), @@ -181,8 +183,9 @@ impl WebGLPaintThread { self.send_drawing_buffer_height(sender), } - // FIXME: Convert to `debug_assert!` once tests are run with debug assertions - assert!(gl::get_error() == gl::NO_ERROR); + // FIXME: Use debug_assertions once tests are run with them + let error = gl::get_error(); + assert!(error == gl::NO_ERROR, "Unexpected WebGL error: 0x{:x} ({})", error, error); } /// Creates a new `WebGLPaintThread` and returns the out-of-process sender and the in-process @@ -299,6 +302,7 @@ impl WebGLPaintThread { } else { Some(unsafe { NonZero::new(program) }) }; + chan.send(program).unwrap(); } diff --git a/components/canvas_traits/lib.rs b/components/canvas_traits/lib.rs index bba0db60234..d54530b94fd 100644 --- a/components/canvas_traits/lib.rs +++ b/components/canvas_traits/lib.rs @@ -37,6 +37,7 @@ use layers::platform::surface::NativeSurface; use offscreen_gl_context::GLContextAttributes; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::default::Default; +use std::fmt; use std::str::FromStr; use std::sync::mpsc::Sender; use util::mem::HeapSizeOf; @@ -193,6 +194,82 @@ pub enum CanvasWebGLMsg { DrawingBufferHeight(IpcSender), } +impl fmt::Debug for CanvasWebGLMsg { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use CanvasWebGLMsg::*; + let name = match *self { + GetContextAttributes(..) => "GetContextAttributes", + ActiveTexture(..) => "ActiveTexture", + BlendColor(..) => "BlendColor", + BlendEquation(..) => "BlendEquation", + BlendEquationSeparate(..) => "BlendEquationSeparate", + BlendFunc(..) => "BlendFunc", + BlendFuncSeparate(..) => "BlendFuncSeparate", + AttachShader(..) => "AttachShader", + BindAttribLocation(..) => "BindAttribLocation", + BufferData(..) => "BufferData", + BufferSubData(..) => "BufferSubData", + Clear(..) => "Clear", + ClearColor(..) => "ClearColor", + ClearDepth(..) => "ClearDepth", + ClearStencil(..) => "ClearStencil", + ColorMask(..) => "ColorMask", + CullFace(..) => "CullFace", + FrontFace(..) => "FrontFace", + DepthFunc(..) => "DepthFunc", + DepthMask(..) => "DepthMask", + DepthRange(..) => "DepthRange", + Enable(..) => "Enable", + Disable(..) => "Disable", + CompileShader(..) => "CompileShader", + CreateBuffer(..) => "CreateBuffer", + CreateFramebuffer(..) => "CreateFramebuffer", + CreateRenderbuffer(..) => "CreateRenderbuffer", + CreateTexture(..) => "CreateTexture", + CreateProgram(..) => "CreateProgram", + CreateShader(..) => "CreateShader", + DeleteBuffer(..) => "DeleteBuffer", + DeleteFramebuffer(..) => "DeleteFramebuffer", + DeleteRenderbuffer(..) => "DeleteRenderBuffer", + DeleteTexture(..) => "DeleteTexture", + DeleteProgram(..) => "DeleteProgram", + DeleteShader(..) => "DeleteShader", + BindBuffer(..) => "BindBuffer", + BindFramebuffer(..) => "BindFramebuffer", + BindRenderbuffer(..) => "BindRenderbuffer", + BindTexture(..) => "BindTexture", + DrawArrays(..) => "DrawArrays", + DrawElements(..) => "DrawElements", + EnableVertexAttribArray(..) => "EnableVertexAttribArray", + GetBufferParameter(..) => "GetBufferParameter", + GetParameter(..) => "GetParameter", + GetProgramParameter(..) => "GetProgramParameter", + GetShaderParameter(..) => "GetShaderParameter", + GetAttribLocation(..) => "GetAttribLocation", + GetUniformLocation(..) => "GetUniformLocation", + PolygonOffset(..) => "PolygonOffset", + Scissor(..) => "Scissor", + Hint(..) => "Hint", + LineWidth(..) => "LineWidth", + PixelStorei(..) => "PixelStorei", + LinkProgram(..) => "LinkProgram", + Uniform4f(..) => "Uniform4f", + Uniform1f(..) => "Uniform1f", + UseProgram(..) => "UseProgram", + VertexAttrib(..) => "VertexAttrib", + VertexAttribPointer2f(..) => "VertexAttribPointer2f", + Viewport(..) => "Viewport", + TexImage2D(..) => "TexImage2D", + TexParameteri(..) => "TexParameteri", + TexParameterf(..) => "TexParameterf", + DrawingBufferWidth(..) => "DrawingBufferWidth", + DrawingBufferHeight(..) => "DrawingBufferHeight", + }; + + write!(f, "CanvasWebGLMsg::{}(..)", name) + } +} + #[derive(Clone, Copy, PartialEq, Deserialize, Serialize, HeapSizeOf)] pub enum WebGLError { InvalidEnum, From cf479a2b4fd07abf73237fbd365e229787bf6630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 4 Jan 2016 14:06:12 +0100 Subject: [PATCH 7/8] webgl: Fix draw_arrays_simple reftests It used pre-shader translation syntax --- .../wpt/mozilla/tests/mozilla/webgl/draw_arrays_simple.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/wpt/mozilla/tests/mozilla/webgl/draw_arrays_simple.html b/tests/wpt/mozilla/tests/mozilla/webgl/draw_arrays_simple.html index 13835c92930..545f4d3575b 100644 --- a/tests/wpt/mozilla/tests/mozilla/webgl/draw_arrays_simple.html +++ b/tests/wpt/mozilla/tests/mozilla/webgl/draw_arrays_simple.html @@ -11,6 +11,8 @@ From 4092ffd245c51704faec97e6da70577fd92d1f94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 4 Jan 2016 14:17:10 +0100 Subject: [PATCH 8/8] webgl: Check shader compilation status on use_program. --- components/script/dom/webglprogram.rs | 13 ++++++++++++- components/script/dom/webglrenderingcontext.rs | 6 ++++-- components/script/dom/webglshader.rs | 4 ++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/components/script/dom/webglprogram.rs b/components/script/dom/webglprogram.rs index 272eeae72aa..42eb0a23581 100644 --- a/components/script/dom/webglprogram.rs +++ b/components/script/dom/webglprogram.rs @@ -73,8 +73,19 @@ impl WebGLProgram { } /// glUseProgram - pub fn use_program(&self) { + pub fn use_program(&self) -> WebGLResult<()> { + match self.fragment_shader.get() { + Some(ref shader) if shader.successfully_compiled() => {}, + _ => return Err(WebGLError::InvalidOperation), + } + + match self.vertex_shader.get() { + Some(ref shader) if shader.successfully_compiled() => {}, + _ => return Err(WebGLError::InvalidOperation), + } + self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::UseProgram(self.id))).unwrap(); + Ok(()) } /// glAttachShader diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index b8feeb9b93c..2d51fc5c64d 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -1004,8 +1004,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 fn UseProgram(&self, program: Option<&WebGLProgram>) { if let Some(program) = program { - program.use_program(); - self.current_program.set(Some(program)); + match program.use_program() { + Ok(()) => self.current_program.set(Some(program)), + Err(e) => self.webgl_error(e), + } } } diff --git a/components/script/dom/webglshader.rs b/components/script/dom/webglshader.rs index 9fd35610a37..9c4548f1675 100644 --- a/components/script/dom/webglshader.rs +++ b/components/script/dom/webglshader.rs @@ -147,6 +147,10 @@ impl WebGLShader { pub fn set_source(&self, source: DOMString) { *self.source.borrow_mut() = Some(source); } + + pub fn successfully_compiled(&self) -> bool { + self.compilation_status.get() == ShaderCompilationStatus::Succeeded + } } impl Drop for WebGLShader {