Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement WebGLRenderingContextBase.getAttachedShaders #20411

Merged
merged 3 commits into from Mar 24, 2018
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -974,6 +974,14 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
level: i32) {
self.base.FramebufferTexture2D(target, attachment, textarget, texture, level)
}

/// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9
fn GetAttachedShaders(
&self,
program: &WebGLProgram,
) -> Option<Vec<DomRoot<WebGLShader>>> {
self.base.GetAttachedShaders(program)
}
}


@@ -367,6 +367,19 @@ impl WebGLProgram {
self.renderer.send(WebGLCommand::GetProgramParameter(self.id, param_id, sender)).unwrap();
receiver.recv().unwrap()
}

pub fn attached_shaders(&self) -> WebGLResult<Vec<DomRoot<WebGLShader>>> {
if self.is_deleted.get() {
return Err(WebGLError::InvalidValue);
}
Ok(match (self.vertex_shader.get(), self.fragment_shader.get()) {
(Some(vertex_shader), Some(fragment_shader)) => {
vec![vertex_shader, fragment_shader]
}
(Some(shader), None) | (None, Some(shader)) => vec![shader],
(None, None) => vec![]
})
}
}

impl Drop for WebGLProgram {
@@ -1237,21 +1237,41 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {

#[allow(unsafe_code)]
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5
unsafe fn GetBufferParameter(&self, _cx: *mut JSContext, target: u32, parameter: u32) -> JSVal {
let parameter_matches = match parameter {
constants::BUFFER_SIZE |
constants::BUFFER_USAGE => true,
_ => false,
unsafe fn GetBufferParameter(
&self,
_cx: *mut JSContext,
target: u32,
parameter: u32,
) -> JSVal {
let buffer = match target {
constants::ARRAY_BUFFER => self.bound_buffer_array.get(),
constants::ELEMENT_ARRAY_BUFFER => self.bound_buffer_element_array.get(),
_ => {
self.webgl_error(InvalidEnum);
return NullValue();
}
};
match parameter {
constants::BUFFER_SIZE | constants::BUFFER_USAGE => {},
_ => {
self.webgl_error(InvalidEnum);
return NullValue();
}
}
let buffer = match buffer {
Some(buffer) => buffer,
None => {
self.webgl_error(InvalidOperation);
return NullValue();
}
};

if !parameter_matches {
self.webgl_error(InvalidEnum);
return NullValue();
if parameter == constants::BUFFER_SIZE {
return Int32Value(buffer.capacity() as i32);
}

let (sender, receiver) = webgl_channel().unwrap();
self.send_command(WebGLCommand::GetBufferParameter(target, parameter, sender));

Int32Value(receiver.recv().unwrap())
}

@@ -1946,7 +1966,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {

// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9
fn CompileShader(&self, shader: &WebGLShader) {
shader.compile(self.webgl_version, self.glsl_version, &self.extension_manager)
handle_potential_webgl_error!(
self,
shader.compile(self.webgl_version, self.glsl_version, &self.extension_manager)
)
}

// TODO(emilio): Probably in the future we should keep track of the
@@ -3578,6 +3601,14 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
None => self.webgl_error(InvalidOperation),
};
}

/// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9
fn GetAttachedShaders(
&self,
program: &WebGLProgram,
) -> Option<Vec<DomRoot<WebGLShader>>> {
handle_potential_webgl_error!(self, program.attached_shaders().map(Some), None)
}
}

pub trait LayoutCanvasWebGLRenderingContextHelpers {
@@ -3,8 +3,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl
use canvas_traits::webgl::{WebGLSLVersion, WebGLVersion};
use canvas_traits::webgl::{webgl_channel, WebGLCommand, WebGLMsgSender, WebGLParameter, WebGLResult, WebGLShaderId};
use canvas_traits::webgl::{WebGLCommand, WebGLError, WebGLMsgSender};
use canvas_traits::webgl::{WebGLParameter, WebGLResult, WebGLSLVersion};
use canvas_traits::webgl::{WebGLShaderId, WebGLVersion, webgl_channel};
use dom::bindings::cell::DomRefCell;
use dom::bindings::codegen::Bindings::WebGLShaderBinding;
use dom::bindings::reflector::reflect_dom_object;
@@ -98,74 +99,83 @@ impl WebGLShader {
&self,
webgl_version: WebGLVersion,
glsl_version: WebGLSLVersion,
ext: &WebGLExtensions
) {
ext: &WebGLExtensions,
) -> WebGLResult<()> {
if self.is_deleted.get() && !self.is_attached() {
return Err(WebGLError::InvalidValue);
}
if self.compilation_status.get() != ShaderCompilationStatus::NotCompiled {
debug!("Compiling already compiled shader {}", self.id);
}

if let Some(ref source) = *self.source.borrow() {
let mut params = BuiltInResources::default();
params.FragmentPrecisionHigh = 1;
params.OES_standard_derivatives = ext.is_enabled::<OESStandardDerivatives>() as i32;
let validator = match webgl_version {
WebGLVersion::WebGL1 => {
let output_format = if cfg!(any(target_os = "android", target_os = "ios")) {
Output::Essl
} else {
Output::Glsl
};
ShaderValidator::for_webgl(self.gl_type,
output_format,
&params).unwrap()
},
WebGLVersion::WebGL2 => {
let output_format = if cfg!(any(target_os = "android", target_os = "ios")) {
Output::Essl
} else {
match (glsl_version.major, glsl_version.minor) {
(1, 30) => Output::Glsl130,
(1, 40) => Output::Glsl140,
(1, 50) => Output::Glsl150Core,
(3, 30) => Output::Glsl330Core,
(4, 0) => Output::Glsl400Core,
(4, 10) => Output::Glsl410Core,
(4, 20) => Output::Glsl420Core,
(4, 30) => Output::Glsl430Core,
(4, 40) => Output::Glsl440Core,
(4, _) => Output::Glsl450Core,
_ => Output::Glsl140
}
};
ShaderValidator::for_webgl2(self.gl_type,
output_format,
&params).unwrap()
},
};

match validator.compile_and_translate(&[source]) {
Ok(translated_source) => {
debug!("Shader translated: {}", translated_source);
// NOTE: At this point we should be pretty sure that the compilation in the paint thread
// will succeed.
// It could be interesting to retrieve the info log from the paint thread though
let msg = WebGLCommand::CompileShader(self.id, translated_source);
self.renderer.send(msg).unwrap();
self.compilation_status.set(ShaderCompilationStatus::Succeeded);
},
Err(error) => {
self.compilation_status.set(ShaderCompilationStatus::Failed);
debug!("Shader {} compilation failed: {}", self.id, error);
},
}

*self.info_log.borrow_mut() = Some(validator.info_log());
// TODO(emilio): More data (like uniform data) should be collected
// here to properly validate uniforms.
//
// This requires a more complex interface with ANGLE, using C++
// bindings and being extremely cautious about destructing things.
let source = self.source.borrow();
let source = match source.as_ref() {
Some(source) => source,
None => return Ok(()),
};

let mut params = BuiltInResources::default();
params.FragmentPrecisionHigh = 1;
params.OES_standard_derivatives = ext.is_enabled::<OESStandardDerivatives>() as i32;
let validator = match webgl_version {
WebGLVersion::WebGL1 => {
let output_format = if cfg!(any(target_os = "android", target_os = "ios")) {
Output::Essl
} else {
Output::Glsl
};
ShaderValidator::for_webgl(self.gl_type,
output_format,
&params).unwrap()
},
WebGLVersion::WebGL2 => {
let output_format = if cfg!(any(target_os = "android", target_os = "ios")) {
Output::Essl
} else {
match (glsl_version.major, glsl_version.minor) {
(1, 30) => Output::Glsl130,
(1, 40) => Output::Glsl140,
(1, 50) => Output::Glsl150Core,
(3, 30) => Output::Glsl330Core,
(4, 0) => Output::Glsl400Core,
(4, 10) => Output::Glsl410Core,
(4, 20) => Output::Glsl420Core,
(4, 30) => Output::Glsl430Core,
(4, 40) => Output::Glsl440Core,
(4, _) => Output::Glsl450Core,
_ => Output::Glsl140
}
};
ShaderValidator::for_webgl2(self.gl_type,
output_format,
&params).unwrap()
},
};

match validator.compile_and_translate(&[source]) {
Ok(translated_source) => {
debug!("Shader translated: {}", translated_source);
// NOTE: At this point we should be pretty sure that the compilation in the paint thread
// will succeed.
// It could be interesting to retrieve the info log from the paint thread though
let msg = WebGLCommand::CompileShader(self.id, translated_source);
self.renderer.send(msg).unwrap();
self.compilation_status.set(ShaderCompilationStatus::Succeeded);
},
Err(error) => {
self.compilation_status.set(ShaderCompilationStatus::Failed);
debug!("Shader {} compilation failed: {}", self.id, error);
},
}

*self.info_log.borrow_mut() = Some(validator.info_log());

// TODO(emilio): More data (like uniform data) should be collected
// here to properly validate uniforms.
//
// This requires a more complex interface with ANGLE, using C++
// bindings and being extremely cautious about destructing things.
Ok(())
}

/// Mark this shader as deleted (if it wasn't previously)
@@ -202,6 +212,9 @@ impl WebGLShader {

/// glGetParameter
pub fn parameter(&self, param_id: u32) -> WebGLResult<WebGLParameter> {
if self.is_deleted.get() && !self.is_attached() {
return Err(WebGLError::InvalidValue);
}
let (sender, receiver) = webgl_channel().unwrap();
self.renderer.send(WebGLCommand::GetShaderParameter(self.id, param_id, sender)).unwrap();
receiver.recv().unwrap()
@@ -563,7 +563,7 @@ interface WebGLRenderingContextBase

WebGLActiveInfo? getActiveAttrib(WebGLProgram program, GLuint index);
WebGLActiveInfo? getActiveUniform(WebGLProgram program, GLuint index);
//sequence<WebGLShader>? getAttachedShaders(WebGLProgram? program);
sequence<WebGLShader>? getAttachedShaders(WebGLProgram program);

[WebGLHandlesContextLoss] GLint getAttribLocation(WebGLProgram program, DOMString name);

@@ -1,14 +1,10 @@
[methods.html]
type: testharness
[WebGL test #0: Property either does not exist or is not a function: getAttachedShaders]
[WebGL test #0: Property either does not exist or is not a function: getRenderbufferParameter]
expected: FAIL

[WebGL test #1: Property either does not exist or is not a function: getRenderbufferParameter]
[WebGL test #1: Property either does not exist or is not a function: getUniform]
expected: FAIL

[WebGL test #2: Property either does not exist or is not a function: getUniform]
expected: FAIL

[WebGL test #3: Property either does not exist or is not a function: isContextLost]
[WebGL test #2: Property either does not exist or is not a function: isContextLost]
expected: FAIL

@@ -1,3 +1,7 @@
[null-object-behaviour.html]
type: testharness
expected: CRASH
[WebGL test #3: getError expected: INVALID_VALUE. Was NO_ERROR : after evaluating: context.linkProgram(undefined)]
expected: FAIL

[WebGL test #38: getError expected: INVALID_OPERATION. Was INVALID_VALUE : after evaluating: context.bufferData(context.ARRAY_BUFFER, 1, context.STATIC_DRAW)]
expected: FAIL

This file was deleted.

This file was deleted.

@@ -1,9 +1,19 @@
[program-test.html]
type: testharness
expected: ERROR
[WebGL test #17: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
[WebGL test #53: getError expected: INVALID_OPERATION. Was NO_ERROR : drawing with a null program should generate INVALID_OPERATION]
expected: FAIL

[WebGL test #21: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
[WebGL test #58: linking should fail with in-use formerly good program, with new bad shader attached]
expected: FAIL

[WebGL test #64: getError expected: NO_ERROR. Was INVALID_OPERATION : delete the current program shouldn't change the current rendering state]
expected: FAIL

[WebGL test #65: getError expected: NO_ERROR. Was INVALID_OPERATION : The current program shouldn't be deleted]
expected: FAIL

[WebGL test #69: an attached shader shouldn't be deleted]
expected: FAIL

[WebGL test #70: getError expected: INVALID_VALUE. Was INVALID_OPERATION : a delete-marked program should be deleted once it's no longer the current program]
expected: FAIL

@@ -1,9 +1,29 @@
[gl-object-get-calls.html]
type: testharness
expected: ERROR
[WebGL test #0: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
[WebGL test #33: gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH) should be 2. Threw exception TypeError: gl.getRenderbufferParameter is not a function]
expected: FAIL

[Untitled]
[WebGL test #34: gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT) should be 2. Threw exception TypeError: gl.getRenderbufferParameter is not a function]
expected: FAIL

[WebGL test #35: gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_INTERNAL_FORMAT) should be non-zero. Threw exception TypeError: gl.getRenderbufferParameter is not a function]
expected: FAIL

[WebGL test #36: gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_DEPTH_SIZE) should be non-zero. Threw exception TypeError: gl.getRenderbufferParameter is not a function]
expected: FAIL

[WebGL test #39: gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_RED_SIZE) should be non-zero. Threw exception TypeError: gl.getRenderbufferParameter is not a function]
expected: FAIL

[WebGL test #40: gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_GREEN_SIZE) should be non-zero. Threw exception TypeError: gl.getRenderbufferParameter is not a function]
expected: FAIL

[WebGL test #41: gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_BLUE_SIZE) should be non-zero. Threw exception TypeError: gl.getRenderbufferParameter is not a function]
expected: FAIL

[WebGL test #42: gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_ALPHA_SIZE) should be non-zero. Threw exception TypeError: gl.getRenderbufferParameter is not a function]
expected: FAIL

[WebGL test #43: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
expected: FAIL

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.