Skip to content

Commit

Permalink
Add support for WebGL2 getFramebufferAttachmentParameter
Browse files Browse the repository at this point in the history
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
  • Loading branch information
mmatyas committed Feb 21, 2020
1 parent afb1faf commit d5d0a78
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 99 deletions.
182 changes: 179 additions & 3 deletions components/script/dom/webgl2renderingcontext.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
@@ -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

Expand All @@ -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

Expand Down
Expand Up @@ -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

0 comments on commit d5d0a78

Please sign in to comment.