diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2020-02-21 15:25:29 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-21 15:25:29 -0500 |
commit | 10e85760cf8b167fb8f01af76377a0c657b2434a (patch) | |
tree | 57ae54d513872bb32014730e59ff0a06dbb10bb6 | |
parent | be4ecb9233b06c88e1a7a6f64b4f286afb16bfdc (diff) | |
parent | d5d0a788e315530de7e738643652b0adf10e2c80 (diff) | |
download | servo-10e85760cf8b167fb8f01af76377a0c657b2434a.tar.gz servo-10e85760cf8b167fb8f01af76377a0c657b2434a.zip |
Auto merge of #25785 - szeged:mmatyas__webgl_fns_framebuf_getattrparam, r=jdm
Add support for WebGL2 getFramebufferAttachmentParameter
Implements the WebGL2 variant of `getFramebufferAttachmentParameter` and the related parameter checks.
See: https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.4
<!-- Please describe your changes on the following line: -->
Depends on #25784
cc @jdm @zakorgy
---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] There are tests for these changes
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
3 files changed, 182 insertions, 99 deletions
diff --git a/components/script/dom/webgl2renderingcontext.rs b/components/script/dom/webgl2renderingcontext.rs index 4c69efdcb55..dfce0f043ab 100644 --- a/components/script/dom/webgl2renderingcontext.rs +++ b/components/script/dom/webgl2renderingcontext.rs @@ -21,7 +21,7 @@ use crate::dom::htmlcanvaselement::HTMLCanvasElement; use crate::dom::htmliframeelement::HTMLIFrameElement; use crate::dom::webglactiveinfo::WebGLActiveInfo; use crate::dom::webglbuffer::WebGLBuffer; -use crate::dom::webglframebuffer::WebGLFramebuffer; +use crate::dom::webglframebuffer::{WebGLFramebuffer, WebGLFramebufferAttachmentRoot}; use crate::dom::webglprogram::WebGLProgram; use crate::dom::webglquery::WebGLQuery; use crate::dom::webglrenderbuffer::WebGLRenderbuffer; @@ -406,6 +406,157 @@ impl WebGL2RenderingContext { self.base .uniform_vec_section::<u32>(vec, offset, length, uniform_size, uniform_location) } + + #[allow(unsafe_code)] + fn get_default_fb_attachment_param(&self, attachment: u32, pname: u32) -> WebGLResult<JSVal> { + match attachment { + constants::BACK | constants::DEPTH | constants::STENCIL => {}, + _ => return Err(InvalidEnum), + } + + if pname == constants::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME { + return Ok(NullValue()); + } + + let attrs = self + .GetContextAttributes() + .unwrap_or_else(WebGLContextAttributes::empty); + + let intval = match pname { + constants::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE => match attachment { + constants::DEPTH if !attrs.depth => constants::NONE as _, + constants::STENCIL if !attrs.stencil => constants::NONE as _, + _ => constants::FRAMEBUFFER_DEFAULT as _, + }, + constants::FRAMEBUFFER_ATTACHMENT_RED_SIZE | + constants::FRAMEBUFFER_ATTACHMENT_GREEN_SIZE | + constants::FRAMEBUFFER_ATTACHMENT_BLUE_SIZE => match attachment { + constants::BACK => 8, + _ => 0, + }, + constants::FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE => match attachment { + constants::BACK if attrs.alpha => 8, + constants::BACK => return Err(InvalidOperation), + _ => 0, + }, + constants::FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE => match attachment { + constants::DEPTH if attrs.depth => 24, + constants::DEPTH => return Err(InvalidOperation), + _ => 0, + }, + constants::FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE => match attachment { + constants::STENCIL if attrs.stencil => 8, + constants::STENCIL => return Err(InvalidOperation), + _ => 0, + }, + constants::FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE => match attachment { + constants::DEPTH if attrs.depth => constants::UNSIGNED_NORMALIZED as _, + constants::STENCIL if attrs.stencil => constants::UNSIGNED_INT as _, + constants::DEPTH => return Err(InvalidOperation), + constants::STENCIL => return Err(InvalidOperation), + _ => constants::UNSIGNED_NORMALIZED as _, + }, + constants::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING => match attachment { + constants::DEPTH if !attrs.depth => return Err(InvalidOperation), + constants::STENCIL if !attrs.stencil => return Err(InvalidOperation), + _ => constants::LINEAR as _, + }, + _ => return Err(InvalidEnum), + }; + Ok(Int32Value(intval)) + } + + #[allow(unsafe_code)] + fn get_specific_fb_attachment_param( + &self, + cx: JSContext, + fb: &WebGLFramebuffer, + target: u32, + attachment: u32, + pname: u32, + ) -> WebGLResult<JSVal> { + use crate::dom::webglframebuffer::WebGLFramebufferAttachmentRoot::{Renderbuffer, Texture}; + + match attachment { + constants::DEPTH_ATTACHMENT | constants::STENCIL_ATTACHMENT => {}, + constants::DEPTH_STENCIL_ATTACHMENT => { + if pname == constants::FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE { + return Err(InvalidOperation); + } + + let a = fb.attachment(constants::DEPTH_ATTACHMENT); + let b = fb.attachment(constants::STENCIL_ATTACHMENT); + match (a, b) { + (Some(Renderbuffer(ref a)), Some(Renderbuffer(ref b))) if a.id() == b.id() => { + }, + (Some(Texture(ref a)), Some(Texture(ref b))) if a.id() == b.id() => {}, + _ => return Err(InvalidOperation), + } + }, + constants::COLOR_ATTACHMENT0..=constants::COLOR_ATTACHMENT15 => { + let last_slot = + constants::COLOR_ATTACHMENT0 + self.base.limits().max_color_attachments - 1; + if last_slot < attachment { + return Err(InvalidEnum); + } + }, + _ => return Err(InvalidEnum), + } + + let attachment = match attachment { + constants::DEPTH_STENCIL_ATTACHMENT => constants::DEPTH_ATTACHMENT, + _ => attachment, + }; + + if pname == constants::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME { + rooted!(in(*cx) let mut rval = NullValue()); + match fb.attachment(attachment) { + Some(Renderbuffer(rb)) => unsafe { + rb.to_jsval(*cx, rval.handle_mut()); + }, + Some(Texture(texture)) => unsafe { + texture.to_jsval(*cx, rval.handle_mut()); + }, + _ => {}, + } + return Ok(rval.get()); + } + + match pname { + constants::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE => {}, + _ => match fb.attachment(attachment) { + Some(webgl_attachment) => match pname { + constants::FRAMEBUFFER_ATTACHMENT_RED_SIZE | + constants::FRAMEBUFFER_ATTACHMENT_GREEN_SIZE | + constants::FRAMEBUFFER_ATTACHMENT_BLUE_SIZE | + constants::FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE | + constants::FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE | + constants::FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE | + constants::FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE | + constants::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING => {}, + _ => match webgl_attachment { + WebGLFramebufferAttachmentRoot::Renderbuffer(_) => return Err(InvalidEnum), + WebGLFramebufferAttachmentRoot::Texture(_) => match pname { + constants::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL | + constants::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE | + constants::FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER => {}, + _ => return Err(InvalidEnum), + }, + }, + }, + None => return Err(InvalidOperation), + }, + } + + let (sender, receiver) = webgl_channel().unwrap(); + self.base + .send_command(WebGLCommand::GetFramebufferAttachmentParameter( + target, attachment, pname, sender, + )); + + let retval = receiver.recv().unwrap(); + Ok(Int32Value(retval)) + } } impl WebGL2RenderingContextMethods for WebGL2RenderingContext { @@ -586,8 +737,33 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { attachment: u32, pname: u32, ) -> JSVal { - self.base - .GetFramebufferAttachmentParameter(cx, target, attachment, pname) + let fb_slot = match target { + constants::FRAMEBUFFER | constants::DRAW_FRAMEBUFFER => { + self.base.get_draw_framebuffer_slot() + }, + constants::READ_FRAMEBUFFER => &self.base.get_read_framebuffer_slot(), + _ => { + self.base.webgl_error(InvalidEnum); + return NullValue(); + }, + }; + + if let Some(fb) = fb_slot.get() { + // A selected framebuffer is bound to the target + handle_potential_webgl_error!(self.base, fb.validate_transparent(), return NullValue()); + handle_potential_webgl_error!( + self.base, + self.get_specific_fb_attachment_param(cx, &fb, target, attachment, pname), + return NullValue() + ) + } else { + // The default framebuffer is bound to the target + handle_potential_webgl_error!( + self.base, + self.get_default_fb_attachment_param(attachment, pname), + return NullValue() + ) + } } /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.7 diff --git a/tests/wpt/webgl/meta/conformance2/renderbuffers/framebuffer-object-attachment.html.ini b/tests/wpt/webgl/meta/conformance2/renderbuffers/framebuffer-object-attachment.html.ini index 3b4f43532af..29e24af8116 100644 --- a/tests/wpt/webgl/meta/conformance2/renderbuffers/framebuffer-object-attachment.html.ini +++ b/tests/wpt/webgl/meta/conformance2/renderbuffers/framebuffer-object-attachment.html.ini @@ -1,43 +1,13 @@ [framebuffer-object-attachment.html] - [WebGL test #13: checkFramebufferStatus expects [FRAMEBUFFER_COMPLETE\], was FRAMEBUFFER_INCOMPLETE_ATTACHMENT] - expected: FAIL - - [WebGL test #20: checkFramebufferStatus expects [FRAMEBUFFER_COMPLETE\], was FRAMEBUFFER_INCOMPLETE_ATTACHMENT] - expected: FAIL - - [WebGL test #30: getError expected: NO_ERROR. Was INVALID_ENUM : ] - expected: FAIL - - [WebGL test #21: checkFramebufferStatus expects [FRAMEBUFFER_COMPLETE\], was FRAMEBUFFER_UNSUPPORTED] - expected: FAIL - - [WebGL test #25: checkFramebufferStatus expects [FRAMEBUFFER_COMPLETE\], was FRAMEBUFFER_UNSUPPORTED] - expected: FAIL - - [WebGL test #23: checkFramebufferStatus expects [FRAMEBUFFER_COMPLETE\], was FRAMEBUFFER_UNSUPPORTED] - expected: FAIL - - [WebGL test #24: checkFramebufferStatus expects [FRAMEBUFFER_COMPLETE\], was FRAMEBUFFER_UNSUPPORTED] - expected: FAIL - - [WebGL test #22: checkFramebufferStatus expects [FRAMEBUFFER_COMPLETE\], was FRAMEBUFFER_UNSUPPORTED] - expected: FAIL - - [WebGL test #14: getError expected: NO_ERROR. Was INVALID_ENUM : ] - expected: FAIL - - [WebGL test #16: gl.getParameter(gl.RED_BITS) + gl.getParameter(gl.GREEN_BITS) + gl.getParameter(gl.BLUE_BITS) + gl.getParameter(gl.ALPHA_BITS) >= 16 should be true. Was false.] - expected: FAIL - - [WebGL test #59: getError expected: NO_ERROR. Was INVALID_ENUM : Query should not generate error] - expected: FAIL - [WebGL test #13: gl.getParameter(gl.RED_BITS) + gl.getParameter(gl.GREEN_BITS) + gl.getParameter(gl.BLUE_BITS) + gl.getParameter(gl.ALPHA_BITS) >= 16 should be true. Was false.] expected: FAIL [WebGL test #10: checkFramebufferStatus expects [FRAMEBUFFER_COMPLETE\], was FRAMEBUFFER_INCOMPLETE_ATTACHMENT] expected: FAIL + [WebGL test #20: checkFramebufferStatus expects [FRAMEBUFFER_COMPLETE\], was FRAMEBUFFER_INCOMPLETE_ATTACHMENT] + expected: FAIL + [WebGL test #21: checkFramebufferStatus expects [FRAMEBUFFER_COMPLETE\], was FRAMEBUFFER_INCOMPLETE_ATTACHMENT] expected: FAIL @@ -53,9 +23,6 @@ [WebGL test #19: checkFramebufferStatus expects [FRAMEBUFFER_COMPLETE\], was FRAMEBUFFER_INCOMPLETE_ATTACHMENT] expected: FAIL - [WebGL test #56: getError expected: NO_ERROR. Was INVALID_ENUM : Query should not generate error] - expected: FAIL - [WebGL test #22: checkFramebufferStatus expects [FRAMEBUFFER_COMPLETE\], was FRAMEBUFFER_INCOMPLETE_ATTACHMENT] expected: FAIL diff --git a/tests/wpt/webgl/meta/conformance2/renderbuffers/framebuffer-test.html.ini b/tests/wpt/webgl/meta/conformance2/renderbuffers/framebuffer-test.html.ini index 1b898b12be0..9361819dbfb 100644 --- a/tests/wpt/webgl/meta/conformance2/renderbuffers/framebuffer-test.html.ini +++ b/tests/wpt/webgl/meta/conformance2/renderbuffers/framebuffer-test.html.ini @@ -2,63 +2,3 @@ [WebGL test #38: getError expected: INVALID_OPERATION. Was INVALID_ENUM : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read framebuffer with no attachment.] expected: FAIL - [WebGL test #1: getError expected: INVALID_ENUM. Was INVALID_OPERATION : getFramebufferAttachmentParameter(COLOR_ATTACHMENT0) on the default framebuffer.] - expected: FAIL - - [WebGL test #33: getError expected: NO_ERROR. Was INVALID_ENUM : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read/draw framebuffer.] - expected: FAIL - - [WebGL test #42: getError expected: NO_ERROR. Was INVALID_ENUM : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read/draw framebuffer.] - expected: FAIL - - [WebGL test #51: getError expected: INVALID_OPERATION. Was INVALID_ENUM : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE) on read framebuffer without depth attachment.] - expected: FAIL - - [WebGL test #40: getError expected: INVALID_OPERATION. Was INVALID_ENUM : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on draw framebuffer with no attachment.] - expected: FAIL - - [WebGL test #46: getError expected: NO_ERROR. Was INVALID_ENUM : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read/draw framebuffer.] - expected: FAIL - - [WebGL test #54: getError expected: INVALID_OPERATION. Was INVALID_ENUM : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_RED_SIZE) on read framebuffer with no attachment.] - expected: FAIL - - [WebGL test #20: getError expected: INVALID_OPERATION. Was INVALID_ENUM : getFramebufferAttachmentParameter(GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) with no attachment.] - expected: FAIL - - [WebGL test #53: getError expected: INVALID_OPERATION. Was INVALID_ENUM : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_RED_SIZE) on draw framebuffer without color attachment.] - expected: FAIL - - [WebGL test #37: gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_BLUE_SIZE) should be 0 (of type number). Was null (of type object).] - expected: FAIL - - [WebGL test #2: getError expected: NO_ERROR. Was INVALID_OPERATION : getFramebufferAttachmentParameter(BACK) on the default framebuffer.] - expected: FAIL - - [WebGL test #56: getError expected: INVALID_OPERATION. Was INVALID_ENUM : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE) on draw framebuffer with no attachment.] - expected: FAIL - - [WebGL test #15: getError expected: NO_ERROR. Was INVALID_ENUM : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) with no attachment.] - expected: FAIL - - [WebGL test #29: getError expected: NO_ERROR. Was INVALID_ENUM : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read/draw framebuffer.] - expected: FAIL - - [WebGL test #43: getError expected: INVALID_OPERATION. Was INVALID_ENUM : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read/draw framebuffer with no attachment.] - expected: FAIL - - [WebGL test #34: getError expected: INVALID_OPERATION. Was INVALID_ENUM : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read/draw framebuffer with no attachment.] - expected: FAIL - - [WebGL test #47: getError expected: INVALID_OPERATION. Was INVALID_ENUM : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read/draw framebuffer with no attachment.] - expected: FAIL - - [WebGL test #39: getError expected: NO_ERROR. Was INVALID_ENUM : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on draw framebuffer.] - expected: FAIL - - [WebGL test #9: getError expected: NO_ERROR. Was INVALID_ENUM : getFramebufferAttachmentParameter(READ_FRAMEBUFFER).] - expected: FAIL - - [WebGL test #30: getError expected: INVALID_OPERATION. Was INVALID_ENUM : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read/draw framebuffer with no attachment.] - expected: FAIL - |