Skip to content

Commit

Permalink
Allow more WebGL2 FBO attachment formats
Browse files Browse the repository at this point in the history
Add support for most of the framebuffer attachment formats
introduced in WebGL2 for textures and renderbuffers.

Related format tables:

- https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glTexImage2D.xhtml
- https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glRenderbufferStorage.xhtml
  • Loading branch information
mmatyas committed Mar 3, 2020
1 parent d42835b commit 859a3a4
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 96 deletions.
126 changes: 101 additions & 25 deletions components/script/dom/webglframebuffer.rs
Expand Up @@ -219,10 +219,10 @@ impl WebGLFramebuffer {
self.size.get()
}

fn check_attachment_constraints(
fn check_attachment_constraints<'a>(
&self,
attachment: &Option<WebGLFramebufferAttachment>,
constraints: &[u32],
mut constraints: impl Iterator<Item = &'a u32>,
fb_size: &mut Option<(i32, i32)>,
) -> Result<(), u32> {
// Get the size of this attachment.
Expand Down Expand Up @@ -254,7 +254,7 @@ impl WebGLFramebuffer {
}

if let Some(format) = format {
if constraints.iter().all(|c| *c != format) {
if constraints.all(|c| *c != format) {
return Err(constants::FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
}
}
Expand All @@ -269,22 +269,6 @@ impl WebGLFramebuffer {
let has_z = z.is_some();
let has_s = s.is_some();
let has_zs = zs.is_some();
let attachments = [&*z, &*s, &*zs];
let attachment_constraints = [
&[
constants::DEPTH_COMPONENT16,
constants::DEPTH_COMPONENT24,
constants::DEPTH_COMPONENT32F,
constants::DEPTH24_STENCIL8,
constants::DEPTH32F_STENCIL8,
][..],
&[
constants::STENCIL_INDEX8,
constants::DEPTH24_STENCIL8,
constants::DEPTH32F_STENCIL8,
][..],
&[constants::DEPTH_STENCIL][..],
];

let is_supported = match self.webgl_version {
// From the WebGL 1.0 spec, 6.6 ("Framebuffer Object Attachments"):
Expand Down Expand Up @@ -326,26 +310,118 @@ impl WebGLFramebuffer {

let mut fb_size = None;

for (attachment, constraints) in attachments.iter().zip(&attachment_constraints) {
let attachments = [&*z, &*s, &*zs];
let webgl1_attachment_constraints = &[
&[
constants::DEPTH_COMPONENT16,
constants::DEPTH_COMPONENT24,
constants::DEPTH_COMPONENT32F,
constants::DEPTH24_STENCIL8,
constants::DEPTH32F_STENCIL8,
][..],
&[
constants::STENCIL_INDEX8,
constants::DEPTH24_STENCIL8,
constants::DEPTH32F_STENCIL8,
][..],
&[constants::DEPTH_STENCIL][..],
];
let webgl2_attachment_constraints = &[
&[constants::DEPTH_STENCIL][..],
&[constants::DEPTH_STENCIL][..],
&[][..],
];
let empty_attachment_constrains = &[&[][..], &[][..], &[][..]];
let extra_attachment_constraints = match self.webgl_version {
WebGLVersion::WebGL1 => empty_attachment_constrains,
WebGLVersion::WebGL2 => webgl2_attachment_constraints,
};
let attachment_constraints = webgl1_attachment_constraints
.iter()
.zip(extra_attachment_constraints.iter())
.map(|(a, b)| a.iter().chain(b.iter()));

for (attachment, constraints) in attachments.iter().zip(attachment_constraints) {
if let Err(errnum) =
self.check_attachment_constraints(attachment, constraints, &mut fb_size)
{
return self.status.set(errnum);
}
}

let color_constraints = &[
constants::RGBA4,
constants::RGB5_A1,
let webgl1_color_constraints = &[
constants::RGB,
constants::RGB565,
constants::RGB5_A1,
constants::RGBA,
constants::RGB,
constants::RGBA4,
][..];
let webgl2_color_constraints = &[
constants::ALPHA,
constants::LUMINANCE,
constants::LUMINANCE_ALPHA,
constants::R11F_G11F_B10F,
constants::R16F,
constants::R16I,
constants::R16UI,
constants::R32F,
constants::R32I,
constants::R32UI,
constants::R8,
constants::R8_SNORM,
constants::R8I,
constants::R8UI,
constants::RG16F,
constants::RG16I,
constants::RG16UI,
constants::RG32F,
constants::RG32I,
constants::RG32UI,
constants::RG8,
constants::RG8_SNORM,
constants::RG8I,
constants::RG8UI,
constants::RGB10_A2,
constants::RGB10_A2UI,
constants::RGB16F,
constants::RGB16I,
constants::RGB16UI,
constants::RGB32F,
constants::RGB32I,
constants::RGB32UI,
constants::RGB8,
constants::RGB8_SNORM,
constants::RGB8I,
constants::RGB8UI,
constants::RGB9_E5,
constants::RGBA16F,
constants::RGBA16I,
constants::RGBA16UI,
constants::RGBA32F,
constants::RGBA32I,
constants::RGBA32UI,
constants::RGBA8,
constants::RGBA8_SNORM,
constants::RGBA8I,
constants::RGBA8UI,
constants::SRGB8,
constants::SRGB8_ALPHA8,
][..];
let empty_color_constrains = &[][..];
let extra_color_constraints = match self.webgl_version {
WebGLVersion::WebGL1 => empty_color_constrains,
WebGLVersion::WebGL2 => webgl2_color_constraints,
};
let color_constraints = webgl1_color_constraints
.iter()
.chain(extra_color_constraints.iter());

let has_c = self.colors.iter().any(|att| att.borrow().is_some());
for attachment in self.colors.iter() {
let attachment = attachment.borrow();
let constraints = color_constraints.clone();
if let Err(errnum) =
self.check_attachment_constraints(&*attachment, color_constraints, &mut fb_size)
self.check_attachment_constraints(&*attachment, constraints, &mut fb_size)
{
return self.status.set(errnum);
}
Expand Down
25 changes: 25 additions & 0 deletions components/script/dom/webglrenderbuffer.rs
Expand Up @@ -145,6 +145,31 @@ impl WebGLRenderbuffer {
constants::RGBA4 | constants::DEPTH_COMPONENT16 | constants::STENCIL_INDEX8 => {
internal_format
},
constants::R8 |
constants::R8UI |
constants::R8I |
constants::R16UI |
constants::R16I |
constants::R32UI |
constants::R32I |
constants::RG8 |
constants::RG8UI |
constants::RG8I |
constants::RG16UI |
constants::RG16I |
constants::RG32UI |
constants::RG32I |
constants::RGB8 |
constants::RGBA8 |
constants::SRGB8_ALPHA8 |
constants::RGB10_A2 |
constants::RGBA8UI |
constants::RGBA8I |
constants::RGB10_A2UI |
constants::RGBA16UI |
constants::RGBA16I |
constants::RGBA32I |
constants::RGBA32UI |
constants::DEPTH_COMPONENT24 |
constants::DEPTH_COMPONENT32F |
constants::DEPTH24_STENCIL8 |
Expand Down

This file was deleted.

@@ -1,7 +1,7 @@
[read-pixels-from-rgb8-into-pbo-bug.html]
[WebGL test #1: framebuffer with RGB8 color buffer is incomplete]
[WebGL test #2: getError expected: NO_ERROR. Was INVALID_OPERATION : Tests should complete without gl errors]
expected: FAIL

[WebGL test #2: getError expected: NO_ERROR. Was INVALID_ENUM : Tests should complete without gl errors]
[WebGL test #1: Expected in pixel 0: [255,0,0,255\], got: 0,0,0,0]
expected: FAIL

@@ -1,34 +1,7 @@
[framebuffer-object-attachment.html]
[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.]
[WebGL test #45: getError expected: NO_ERROR. Was INVALID_ENUM : ]
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

[WebGL test #17: checkFramebufferStatus expects [FRAMEBUFFER_COMPLETE\], was FRAMEBUFFER_INCOMPLETE_ATTACHMENT]
expected: FAIL

[WebGL test #9: checkFramebufferStatus expects [FRAMEBUFFER_COMPLETE\], was FRAMEBUFFER_INCOMPLETE_ATTACHMENT]
expected: FAIL

[WebGL test #11: getError expected: NO_ERROR. Was INVALID_ENUM : ]
expected: FAIL

[WebGL test #19: checkFramebufferStatus expects [FRAMEBUFFER_COMPLETE\], was FRAMEBUFFER_INCOMPLETE_ATTACHMENT]
expected: FAIL

[WebGL test #22: checkFramebufferStatus expects [FRAMEBUFFER_COMPLETE\], was FRAMEBUFFER_INCOMPLETE_ATTACHMENT]
expected: FAIL

[WebGL test #18: checkFramebufferStatus expects [FRAMEBUFFER_COMPLETE\], was FRAMEBUFFER_INCOMPLETE_ATTACHMENT]
expected: FAIL

[WebGL test #27: getError expected: NO_ERROR. Was INVALID_ENUM : ]
[WebGL test #28: checkFramebufferStatus expects [FRAMEBUFFER_COMPLETE\], was FRAMEBUFFER_INCOMPLETE_ATTACHMENT]
expected: FAIL

@@ -1,47 +1,35 @@
[clearbuffer-sub-source.html]
[WebGL test #14: getError expected: NO_ERROR. Was INVALID_FRAMEBUFFER_OPERATION : clearBuffer with srcOffset = 2 should succeed]
expected: FAIL

[WebGL test #5: clearBuffer fails to work. Expected: 1,2,3,4, got: 0,0,0,0]
expected: FAIL

[WebGL test #2: getError expected: NO_ERROR. Was INVALID_ENUM : clearBuffer with no srcOffset should succeed]
expected: FAIL

[WebGL test #11: clearBuffer fails to work. Expected: 1,2,3,4, got: 0,0,0,0]
expected: FAIL

[WebGL test #13: clearBuffer fails to work. Expected: 1,2,3,4, got: 0,0,0,0]
expected: FAIL

[WebGL test #9: gl.checkFramebufferStatus(gl.FRAMEBUFFER) should be 36053. Was 36054.]
[WebGL test #12: getError expected: NO_ERROR. Was INVALID_OPERATION : clearBuffer with srcOffset = 0 should succeed]
expected: FAIL

[WebGL test #10: getError expected: NO_ERROR. Was INVALID_ENUM : clearBuffer with no srcOffset should succeed]
[WebGL test #6: getError expected: NO_ERROR. Was INVALID_OPERATION : clearBuffer with srcOffset = 2 should succeed]
expected: FAIL

[WebGL test #16: getError expected: INVALID_VALUE. Was INVALID_FRAMEBUFFER_OPERATION : clearBuffer with srcOffset = 4 should fail: out of bounds]
[WebGL test #4: getError expected: NO_ERROR. Was INVALID_OPERATION : clearBuffer with srcOffset = 0 should succeed]
expected: FAIL

[WebGL test #4: getError expected: NO_ERROR. Was INVALID_FRAMEBUFFER_OPERATION : clearBuffer with srcOffset = 0 should succeed]
[WebGL test #14: getError expected: NO_ERROR. Was INVALID_OPERATION : clearBuffer with srcOffset = 2 should succeed]
expected: FAIL

[WebGL test #15: clearBuffer fails to work. Expected: 3,4,5,6, got: 0,0,0,0]
expected: FAIL

[WebGL test #8: getError expected: INVALID_VALUE. Was INVALID_FRAMEBUFFER_OPERATION : clearBuffer with srcOffset = 4 should fail: out of bounds]
expected: FAIL

[WebGL test #6: getError expected: NO_ERROR. Was INVALID_FRAMEBUFFER_OPERATION : clearBuffer with srcOffset = 2 should succeed]
[WebGL test #8: getError expected: INVALID_VALUE. Was INVALID_OPERATION : clearBuffer with srcOffset = 4 should fail: out of bounds]
expected: FAIL

[WebGL test #7: clearBuffer fails to work. Expected: 3,4,5,6, got: 0,0,0,0]
expected: FAIL

[WebGL test #12: getError expected: NO_ERROR. Was INVALID_FRAMEBUFFER_OPERATION : clearBuffer with srcOffset = 0 should succeed]
expected: FAIL

[WebGL test #1: gl.checkFramebufferStatus(gl.FRAMEBUFFER) should be 36053. Was 36054.]
[WebGL test #16: getError expected: INVALID_VALUE. Was INVALID_OPERATION : clearBuffer with srcOffset = 4 should fail: out of bounds]
expected: FAIL

[WebGL test #3: clearBuffer fails to work. Expected: 1,2,3,4, got: 0,0,0,0]
Expand Down
Expand Up @@ -3,6 +3,3 @@
[WebGL test #2: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
expected: FAIL

[WebGL test #1: gl.checkFramebufferStatus(gl.FRAMEBUFFER) should be 36053. Was 36054.]
expected: FAIL

12 changes: 0 additions & 12 deletions tests/wpt/webgl/meta/conformance2/state/gl-get-calls.html.ini
Expand Up @@ -8,9 +8,6 @@
[WebGL test #80: context.getParameter(context.MIN_PROGRAM_TEXEL_OFFSET) is not an instance of Number]
expected: FAIL

[WebGL test #41: context.getParameter(context.MAX_DRAW_BUFFERS) should be >= 4. Was null (of type object).]
expected: FAIL

[WebGL test #33: context.getParameter(context.MAX_ARRAY_TEXTURE_LAYERS) should be >= 256. Was null (of type object).]
expected: FAIL

Expand Down Expand Up @@ -89,15 +86,9 @@
[WebGL test #48: context.getParameter(context.MAX_FRAGMENT_INPUT_COMPONENTS) is not an instance of Number]
expected: FAIL

[WebGL test #37: context.getParameter(context.MAX_COLOR_ATTACHMENTS) should be >= 4. Was null (of type object).]
expected: FAIL

[WebGL test #9: context.getParameter(context.PACK_SKIP_ROWS) should be 0 (of type number). Was null (of type object).]
expected: FAIL

[WebGL test #42: context.getParameter(context.MAX_DRAW_BUFFERS) is not an instance of Number]
expected: FAIL

[WebGL test #34: context.getParameter(context.MAX_ARRAY_TEXTURE_LAYERS) is not an instance of Number]
expected: FAIL

Expand All @@ -107,9 +98,6 @@
[WebGL test #12: context.getParameter(context.RASTERIZER_DISCARD) should be false (of type boolean). Was null (of type object).]
expected: FAIL

[WebGL test #38: context.getParameter(context.MAX_COLOR_ATTACHMENTS) is not an instance of Number]
expected: FAIL

[WebGL test #44: context.getParameter(context.MAX_ELEMENT_INDEX) is not an instance of Number]
expected: FAIL

Expand Down

0 comments on commit 859a3a4

Please sign in to comment.