Auto merge of #25765 - szeged:mmatyas__webgl_fns_framebuf_readslot, r=jdm

Add initial support for WebGL2 read framebuffer

Adds support for binding to the read framebuffer slot and querying its status.

<!-- Please describe your changes on the following line: -->

Depends on #25752

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. -->
This commit is contained in:
bors-servo 2020-02-18 17:11:17 -05:00 committed by GitHub
commit b20883ce99
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 203 additions and 90 deletions

View file

@ -503,6 +503,13 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
self.current_transform_feedback.get() self.current_transform_feedback.get()
); );
}, },
// NOTE: DRAW_FRAMEBUFFER_BINDING is the same as FRAMEBUFFER_BINDING, handled on the WebGL1 side
constants::READ_FRAMEBUFFER_BINDING => unsafe {
return optional_root_object_to_js_or_null!(
*cx,
&self.base.get_read_framebuffer_slot().get()
);
},
_ => {}, _ => {},
} }
@ -650,7 +657,32 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
/// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6 /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6
fn BindFramebuffer(&self, target: u32, framebuffer: Option<&WebGLFramebuffer>) { fn BindFramebuffer(&self, target: u32, framebuffer: Option<&WebGLFramebuffer>) {
self.base.BindFramebuffer(target, framebuffer) handle_potential_webgl_error!(
self.base,
self.base.validate_new_framebuffer_binding(framebuffer),
return
);
let (bind_read, bind_draw) = match target {
constants::FRAMEBUFFER => (true, true),
constants::READ_FRAMEBUFFER => (true, false),
constants::DRAW_FRAMEBUFFER => (false, true),
_ => return self.base.webgl_error(InvalidEnum),
};
if bind_read {
self.base.bind_framebuffer_to(
target,
framebuffer,
&self.base.get_read_framebuffer_slot(),
);
}
if bind_draw {
self.base.bind_framebuffer_to(
target,
framebuffer,
&self.base.get_draw_framebuffer_slot(),
);
}
} }
/// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.7 /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.7
@ -2221,7 +2253,20 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
/// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6 /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6
fn CheckFramebufferStatus(&self, target: u32) -> u32 { fn CheckFramebufferStatus(&self, target: u32) -> u32 {
self.base.CheckFramebufferStatus(target) 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 0;
},
};
match fb_slot.get() {
Some(fb) => fb.check_status(),
None => constants::FRAMEBUFFER_COMPLETE,
}
} }
/// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.7 /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.7

View file

@ -96,20 +96,24 @@ impl WebGLRenderbuffer {
if !self.is_deleted.get() { if !self.is_deleted.get() {
self.is_deleted.set(true); self.is_deleted.set(true);
let context = self.upcast::<WebGLObject>().context();
/* /*
If a renderbuffer object is deleted while its image is attached to the currently If a renderbuffer object is deleted while its image is attached to one or more
bound framebuffer, then it is as if FramebufferRenderbuffer had been called, with attachment points in a currently bound framebuffer object, then it is as if
a renderbuffer of 0, for each attachment point to which this image was attached FramebufferRenderbuffer had been called, with a renderbuffer of zero, for each
in the currently bound framebuffer. attachment point to which this image was attached in that framebuffer object.
- GLES 2.0, 4.4.3, "Attaching Renderbuffer Images to a Framebuffer" In other words,the renderbuffer image is first detached from all attachment points
*/ in that frame-buffer object.
let currently_bound_framebuffer = - GLES 3.0, 4.4.2.3, "Attaching Renderbuffer Images to a Framebuffer"
self.upcast::<WebGLObject>().context().bound_framebuffer(); */
if let Some(fb) = currently_bound_framebuffer { if let Some(fb) = context.get_draw_framebuffer_slot().get() {
let _ = fb.detach_renderbuffer(self);
}
if let Some(fb) = context.get_read_framebuffer_slot().get() {
let _ = fb.detach_renderbuffer(self); let _ = fb.detach_renderbuffer(self);
} }
let context = self.upcast::<WebGLObject>().context();
let cmd = WebGLCommand::DeleteRenderbuffer(self.id); let cmd = WebGLCommand::DeleteRenderbuffer(self.id);
if fallible { if fallible {
context.send_command_ignored(cmd); context.send_command_ignored(cmd);

View file

@ -163,7 +163,10 @@ pub struct WebGLRenderingContext {
texture_unpacking_settings: Cell<TextureUnpacking>, texture_unpacking_settings: Cell<TextureUnpacking>,
// TODO(nox): Should be Cell<u8>. // TODO(nox): Should be Cell<u8>.
texture_unpacking_alignment: Cell<u32>, texture_unpacking_alignment: Cell<u32>,
bound_framebuffer: MutNullableDom<WebGLFramebuffer>, bound_draw_framebuffer: MutNullableDom<WebGLFramebuffer>,
// TODO(mmatyas): This was introduced in WebGL2, but listed here because it's used by
// Textures and Renderbuffers, but such WebGLObjects have access only to the GL1 context.
bound_read_framebuffer: MutNullableDom<WebGLFramebuffer>,
bound_renderbuffer: MutNullableDom<WebGLRenderbuffer>, bound_renderbuffer: MutNullableDom<WebGLRenderbuffer>,
bound_buffer_array: MutNullableDom<WebGLBuffer>, bound_buffer_array: MutNullableDom<WebGLBuffer>,
current_program: MutNullableDom<WebGLProgram>, current_program: MutNullableDom<WebGLProgram>,
@ -223,7 +226,8 @@ impl WebGLRenderingContext {
texture_packing_alignment: Cell::new(4), texture_packing_alignment: Cell::new(4),
texture_unpacking_settings: Cell::new(TextureUnpacking::CONVERT_COLORSPACE), texture_unpacking_settings: Cell::new(TextureUnpacking::CONVERT_COLORSPACE),
texture_unpacking_alignment: Cell::new(4), texture_unpacking_alignment: Cell::new(4),
bound_framebuffer: MutNullableDom::new(None), bound_draw_framebuffer: MutNullableDom::new(None),
bound_read_framebuffer: MutNullableDom::new(None),
bound_buffer_array: MutNullableDom::new(None), bound_buffer_array: MutNullableDom::new(None),
bound_renderbuffer: MutNullableDom::new(None), bound_renderbuffer: MutNullableDom::new(None),
current_program: MutNullableDom::new(None), current_program: MutNullableDom::new(None),
@ -328,7 +332,7 @@ impl WebGLRenderingContext {
// Bound framebuffer must not change when the canvas is resized. // Bound framebuffer must not change when the canvas is resized.
// Right now surfman generates a new FBO on resize. // Right now surfman generates a new FBO on resize.
// Send a command to re-bind the framebuffer, if any. // Send a command to re-bind the framebuffer, if any.
if let Some(fbo) = self.bound_framebuffer.get() { if let Some(fbo) = self.bound_draw_framebuffer.get() {
let id = WebGLFramebufferBindingRequest::Explicit(fbo.id()); let id = WebGLFramebufferBindingRequest::Explicit(fbo.id());
self.send_command(WebGLCommand::BindFramebuffer(constants::FRAMEBUFFER, id)); self.send_command(WebGLCommand::BindFramebuffer(constants::FRAMEBUFFER, id));
} }
@ -402,7 +406,7 @@ impl WebGLRenderingContext {
// The WebGL spec mentions a couple more operations that trigger // The WebGL spec mentions a couple more operations that trigger
// this: clear() and getParameter(IMPLEMENTATION_COLOR_READ_*). // this: clear() and getParameter(IMPLEMENTATION_COLOR_READ_*).
pub fn validate_framebuffer(&self) -> WebGLResult<()> { pub fn validate_framebuffer(&self) -> WebGLResult<()> {
match self.bound_framebuffer.get() { match self.bound_draw_framebuffer.get() {
Some(fb) => match fb.check_status_for_rendering() { Some(fb) => match fb.check_status_for_rendering() {
CompleteForRendering::Complete => Ok(()), CompleteForRendering::Complete => Ok(()),
CompleteForRendering::Incomplete => Err(InvalidFramebufferOperation), CompleteForRendering::Incomplete => Err(InvalidFramebufferOperation),
@ -478,7 +482,7 @@ impl WebGLRenderingContext {
fn mark_as_dirty(&self) { fn mark_as_dirty(&self) {
// If we have a bound framebuffer, then don't mark the canvas as dirty. // If we have a bound framebuffer, then don't mark the canvas as dirty.
if self.bound_framebuffer.get().is_some() { if self.bound_draw_framebuffer.get().is_some() {
return; return;
} }
@ -503,7 +507,7 @@ impl WebGLRenderingContext {
} }
pub fn get_current_framebuffer_size(&self) -> Option<(i32, i32)> { pub fn get_current_framebuffer_size(&self) -> Option<(i32, i32)> {
match self.bound_framebuffer.get() { match self.bound_draw_framebuffer.get() {
Some(fb) => return fb.size(), Some(fb) => return fb.size(),
// The window system framebuffer is bound // The window system framebuffer is bound
@ -757,7 +761,7 @@ impl WebGLRenderingContext {
data: pixels.data.into(), data: pixels.data.into(),
}); });
if let Some(fb) = self.bound_framebuffer.get() { if let Some(fb) = self.bound_draw_framebuffer.get() {
fb.invalidate_texture(&*texture); fb.invalidate_texture(&*texture);
} }
} }
@ -1124,10 +1128,6 @@ impl WebGLRenderingContext {
}); });
} }
pub fn bound_framebuffer(&self) -> Option<DomRoot<WebGLFramebuffer>> {
self.bound_framebuffer.get()
}
pub fn extension_manager(&self) -> &WebGLExtensions { pub fn extension_manager(&self) -> &WebGLExtensions {
&self.extension_manager &self.extension_manager
} }
@ -1341,6 +1341,50 @@ impl WebGLRenderingContext {
} }
self.uniform_vec_section::<f32>(vec, offset, length, uniform_size, uniform_location) self.uniform_vec_section::<f32>(vec, offset, length, uniform_size, uniform_location)
} }
pub fn get_draw_framebuffer_slot(&self) -> &MutNullableDom<WebGLFramebuffer> {
&self.bound_draw_framebuffer
}
pub fn get_read_framebuffer_slot(&self) -> &MutNullableDom<WebGLFramebuffer> {
&self.bound_read_framebuffer
}
pub fn validate_new_framebuffer_binding(
&self,
framebuffer: Option<&WebGLFramebuffer>,
) -> WebGLResult<()> {
if let Some(fb) = framebuffer {
self.validate_ownership(fb)?;
if fb.is_deleted() {
// From the WebGL spec:
//
// "An attempt to bind a deleted framebuffer will
// generate an INVALID_OPERATION error, and the
// current binding will remain untouched."
return Err(InvalidOperation);
}
}
Ok(())
}
pub fn bind_framebuffer_to(
&self,
target: u32,
framebuffer: Option<&WebGLFramebuffer>,
slot: &MutNullableDom<WebGLFramebuffer>,
) {
match framebuffer {
Some(framebuffer) => framebuffer.bind(target),
None => {
// Bind the default framebuffer
let cmd =
WebGLCommand::BindFramebuffer(target, WebGLFramebufferBindingRequest::Default);
self.send_command(cmd);
},
}
slot.set(framebuffer);
}
} }
#[cfg(not(feature = "webgl_backtrace"))] #[cfg(not(feature = "webgl_backtrace"))]
@ -1442,7 +1486,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return optional_root_object_to_js_or_null!(*cx, buffer); return optional_root_object_to_js_or_null!(*cx, buffer);
}, },
constants::FRAMEBUFFER_BINDING => unsafe { constants::FRAMEBUFFER_BINDING => unsafe {
return optional_root_object_to_js_or_null!(*cx, &self.bound_framebuffer.get()); return optional_root_object_to_js_or_null!(
*cx,
&self.bound_draw_framebuffer.get()
);
}, },
constants::RENDERBUFFER_BINDING => unsafe { constants::RENDERBUFFER_BINDING => unsafe {
return optional_root_object_to_js_or_null!(*cx, &self.bound_renderbuffer.get()); return optional_root_object_to_js_or_null!(*cx, &self.bound_renderbuffer.get());
@ -1845,33 +1892,17 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6
fn BindFramebuffer(&self, target: u32, framebuffer: Option<&WebGLFramebuffer>) { fn BindFramebuffer(&self, target: u32, framebuffer: Option<&WebGLFramebuffer>) {
if let Some(fb) = framebuffer { handle_potential_webgl_error!(
handle_potential_webgl_error!(self, self.validate_ownership(fb), return); self,
} self.validate_new_framebuffer_binding(framebuffer),
return
);
if target != constants::FRAMEBUFFER { if target != constants::FRAMEBUFFER {
return self.webgl_error(InvalidEnum); return self.webgl_error(InvalidEnum);
} }
if let Some(framebuffer) = framebuffer { self.bind_framebuffer_to(target, framebuffer, &self.bound_draw_framebuffer)
if framebuffer.is_deleted() {
// From the WebGL spec:
//
// "An attempt to bind a deleted framebuffer will
// generate an INVALID_OPERATION error, and the
// current binding will remain untouched."
return self.webgl_error(InvalidOperation);
} else {
framebuffer.bind(target);
self.bound_framebuffer.set(Some(framebuffer));
}
} else {
// Bind the default framebuffer
let cmd =
WebGLCommand::BindFramebuffer(target, WebGLFramebufferBindingRequest::Default);
self.send_command(cmd);
self.bound_framebuffer.set(framebuffer);
}
} }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.7 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.7
@ -2009,7 +2040,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
data: pixels.data.into(), data: pixels.data.into(),
}); });
if let Some(fb) = self.bound_framebuffer.get() { if let Some(fb) = self.bound_draw_framebuffer.get() {
fb.invalidate_texture(&*texture); fb.invalidate_texture(&*texture);
} }
} }
@ -2100,7 +2131,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
Err(_) => return, Err(_) => return,
}; };
let framebuffer_format = match self.bound_framebuffer.get() { let framebuffer_format = match self.bound_draw_framebuffer.get() {
Some(fb) => match fb.attachment(constants::COLOR_ATTACHMENT0) { Some(fb) => match fb.attachment(constants::COLOR_ATTACHMENT0) {
Some(WebGLFramebufferAttachmentRoot::Renderbuffer(rb)) => { Some(WebGLFramebufferAttachmentRoot::Renderbuffer(rb)) => {
TexFormat::from_gl_constant(rb.internal_format()) TexFormat::from_gl_constant(rb.internal_format())
@ -2419,10 +2450,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
handle_potential_webgl_error!(self, self.validate_ownership(framebuffer), return); handle_potential_webgl_error!(self, self.validate_ownership(framebuffer), return);
handle_object_deletion!( handle_object_deletion!(
self, self,
self.bound_framebuffer, self.bound_draw_framebuffer,
framebuffer, framebuffer,
Some(WebGLCommand::BindFramebuffer( Some(WebGLCommand::BindFramebuffer(
constants::FRAMEBUFFER, framebuffer.target().unwrap(),
WebGLFramebufferBindingRequest::Default WebGLFramebufferBindingRequest::Default
)) ))
); );
@ -2575,7 +2606,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
pname: u32, pname: u32,
) -> JSVal { ) -> JSVal {
// Check if currently bound framebuffer is non-zero as per spec. // Check if currently bound framebuffer is non-zero as per spec.
if let Some(fb) = self.bound_framebuffer.get() { if let Some(fb) = self.bound_draw_framebuffer.get() {
// Opaque framebuffers cannot have their attachments inspected // Opaque framebuffers cannot have their attachments inspected
// https://immersive-web.github.io/webxr/#opaque-framebuffer // https://immersive-web.github.io/webxr/#opaque-framebuffer
handle_potential_webgl_error!(self, fb.validate_transparent(), return NullValue()); handle_potential_webgl_error!(self, fb.validate_transparent(), return NullValue());
@ -2617,27 +2648,31 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
_ => false, _ => false,
}; };
let bound_attachment_matches = let bound_attachment_matches = match self
match self.bound_framebuffer.get().unwrap().attachment(attachment) { .bound_draw_framebuffer
Some(attachment_root) => match attachment_root { .get()
WebGLFramebufferAttachmentRoot::Renderbuffer(_) => match pname { .unwrap()
constants::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE | .attachment(attachment)
constants::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME => true, {
_ => false, Some(attachment_root) => match attachment_root {
}, WebGLFramebufferAttachmentRoot::Renderbuffer(_) => match pname {
WebGLFramebufferAttachmentRoot::Texture(_) => match pname { constants::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE |
constants::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE | constants::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME => true,
constants::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME |
constants::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL |
constants::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE => true,
_ => false,
},
},
_ => match pname {
constants::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE => true,
_ => false, _ => false,
}, },
}; WebGLFramebufferAttachmentRoot::Texture(_) => match pname {
constants::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE |
constants::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME |
constants::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL |
constants::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE => true,
_ => false,
},
},
_ => match pname {
constants::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE => true,
_ => false,
},
};
if !target_matches || !attachment_matches || !pname_matches || !bound_attachment_matches { if !target_matches || !attachment_matches || !pname_matches || !bound_attachment_matches {
self.webgl_error(InvalidEnum); self.webgl_error(InvalidEnum);
@ -2653,7 +2688,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
if pname == constants::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME { if pname == constants::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME {
// if fb is None, an INVALID_OPERATION is returned // if fb is None, an INVALID_OPERATION is returned
// at the beggining of the function, so `.unwrap()` will never panic // at the beggining of the function, so `.unwrap()` will never panic
let fb = self.bound_framebuffer.get().unwrap(); let fb = self.bound_draw_framebuffer.get().unwrap();
if let Some(webgl_attachment) = fb.attachment(attachment) { if let Some(webgl_attachment) = fb.attachment(attachment) {
match webgl_attachment { match webgl_attachment {
WebGLFramebufferAttachmentRoot::Renderbuffer(rb) => unsafe { WebGLFramebufferAttachmentRoot::Renderbuffer(rb) => unsafe {
@ -4158,7 +4193,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return 0; return 0;
} }
match self.bound_framebuffer.get() { match self.bound_draw_framebuffer.get() {
Some(fb) => return fb.check_status(), Some(fb) => return fb.check_status(),
None => return constants::FRAMEBUFFER_COMPLETE, None => return constants::FRAMEBUFFER_COMPLETE,
} }
@ -4185,7 +4220,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
self, self,
rb.storage(self.api_type, internal_format, width, height) rb.storage(self.api_type, internal_format, width, height)
); );
if let Some(fb) = self.bound_framebuffer.get() { if let Some(fb) = self.bound_draw_framebuffer.get() {
fb.invalidate_renderbuffer(&*rb); fb.invalidate_renderbuffer(&*rb);
} }
@ -4208,7 +4243,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return self.webgl_error(InvalidEnum); return self.webgl_error(InvalidEnum);
} }
match self.bound_framebuffer.get() { match self.bound_draw_framebuffer.get() {
Some(fb) => handle_potential_webgl_error!(self, fb.renderbuffer(attachment, rb)), Some(fb) => handle_potential_webgl_error!(self, fb.renderbuffer(attachment, rb)),
None => self.webgl_error(InvalidOperation), None => self.webgl_error(InvalidOperation),
}; };
@ -4231,7 +4266,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return self.webgl_error(InvalidEnum); return self.webgl_error(InvalidEnum);
} }
match self.bound_framebuffer.get() { match self.bound_draw_framebuffer.get() {
Some(fb) => handle_potential_webgl_error!( Some(fb) => handle_potential_webgl_error!(
self, self,
fb.texture2d(attachment, textarget, texture, level) fb.texture2d(attachment, textarget, texture, level)

View file

@ -197,15 +197,17 @@ impl WebGLTexture {
} }
/* /*
If a texture object is deleted while its image is attached to the currently If a texture object is deleted while its image is attached to one or more attachment
bound framebuffer, then it is as if FramebufferTexture2D had been called, with points in a currently bound framebuffer, then it is as if FramebufferTexture had been
a texture of 0, for each attachment point to which this image was attached called, with a texture of zero, for each attachment point to which this im-age was
in the currently bound framebuffer. attached in that framebuffer. In other words, this texture image is firstdetached from
- GLES 2.0, 4.4.3, "Attaching Texture Images to a Framebuffer" all attachment points in a currently bound framebuffer.
*/ - GLES 3.0, 4.4.2.3, "Attaching Texture Images to a Framebuffer"
let currently_bound_framebuffer = */
self.upcast::<WebGLObject>().context().bound_framebuffer(); if let Some(fb) = context.get_draw_framebuffer_slot().get() {
if let Some(fb) = currently_bound_framebuffer { let _ = fb.detach_texture(self);
}
if let Some(fb) = context.get_read_framebuffer_slot().get() {
let _ = fb.detach_texture(self); let _ = fb.detach_texture(self);
} }

View file

@ -50,9 +50,6 @@
[WebGL test #11: getError expected: NO_ERROR. Was INVALID_ENUM : checkFramebufferStatus(READ_FRAMEBUFFER).] [WebGL test #11: getError expected: NO_ERROR. Was INVALID_ENUM : checkFramebufferStatus(READ_FRAMEBUFFER).]
expected: FAIL expected: FAIL
[WebGL test #10: checkFramebufferStatus(READ_FRAMEBUFFER) should succeed.]
expected: FAIL
[WebGL test #27: getError expected: NO_ERROR. Was INVALID_OPERATION : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read/draw framebuffer.] [WebGL test #27: getError expected: NO_ERROR. Was INVALID_OPERATION : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read/draw framebuffer.]
expected: FAIL expected: FAIL
@ -80,9 +77,6 @@
[WebGL test #56: getError expected: NO_ERROR. Was INVALID_ENUM : bind draw framebuffer to default (null) framebuffer.] [WebGL test #56: getError expected: NO_ERROR. Was INVALID_ENUM : bind draw framebuffer to default (null) framebuffer.]
expected: FAIL expected: FAIL
[WebGL test #13: bindFramebuffer(READ_FRAMEBUFFER) should change READ_FRAMEBUFFER_BINDING.]
expected: FAIL
[WebGL test #12: getError expected: NO_ERROR. Was INVALID_ENUM : bindFramebuffer(READ_FRAMEBUFFER).] [WebGL test #12: getError expected: NO_ERROR. Was INVALID_ENUM : bindFramebuffer(READ_FRAMEBUFFER).]
expected: FAIL expected: FAIL
@ -167,3 +161,36 @@
[WebGL test #28: getError expected: NO_ERROR. Was INVALID_ENUM : attach a texture to read/draw framebuffer binding point.] [WebGL test #28: getError expected: NO_ERROR. Was INVALID_ENUM : attach a texture to read/draw framebuffer binding point.]
expected: FAIL 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 #46: getError expected: NO_ERROR. Was INVALID_ENUM : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) on read/draw framebuffer.]
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 #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 #56: getError expected: INVALID_OPERATION. Was INVALID_ENUM : getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE) on draw framebuffer with no attachment.]
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