aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2020-02-21 15:25:29 -0500
committerGitHub <noreply@github.com>2020-02-21 15:25:29 -0500
commit10e85760cf8b167fb8f01af76377a0c657b2434a (patch)
tree57ae54d513872bb32014730e59ff0a06dbb10bb6 /components/script/dom
parentbe4ecb9233b06c88e1a7a6f64b4f286afb16bfdc (diff)
parentd5d0a788e315530de7e738643652b0adf10e2c80 (diff)
downloadservo-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. -->
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/webgl2renderingcontext.rs182
1 files changed, 179 insertions, 3 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