diff options
Diffstat (limited to 'components/script/dom/webglrenderingcontext.rs')
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 98 |
1 files changed, 61 insertions, 37 deletions
diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index f19664ad0ad..b5faecc7371 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -54,11 +54,11 @@ use crate::script_runtime::JSContext as SafeJSContext; use backtrace::Backtrace; use canvas_traits::webgl::WebGLError::*; use canvas_traits::webgl::{ - webgl_channel, AlphaTreatment, DOMToTextureCommand, GLContextAttributes, GLFormats, GLLimits, - GlType, Parameter, TexDataType, TexFormat, TexParameter, WebGLChan, WebGLCommand, - WebGLCommandBacktrace, WebGLContextId, WebGLContextShareMode, WebGLError, - WebGLFramebufferBindingRequest, WebGLMsg, WebGLMsgSender, WebGLProgramId, WebGLResult, - WebGLSLVersion, WebGLSendResult, WebGLSender, WebGLVersion, WebVRCommand, YAxisTreatment, + webgl_channel, AlphaTreatment, DOMToTextureCommand, GLContextAttributes, GLLimits, GlType, + Parameter, TexDataType, TexFormat, TexParameter, WebGLChan, WebGLCommand, + WebGLCommandBacktrace, WebGLContextId, WebGLError, WebGLFramebufferBindingRequest, WebGLMsg, + WebGLMsgSender, WebGLOpaqueFramebufferId, WebGLProgramId, WebGLResult, WebGLSLVersion, + WebGLSendResult, WebGLSender, WebGLVersion, WebVRCommand, YAxisTreatment, }; use dom_struct::dom_struct; use embedder_traits::EventLoopWaker; @@ -81,6 +81,7 @@ use std::cell::Cell; use std::cmp; use std::ptr::{self, NonNull}; use std::rc::Rc; +use webxr_api::SwapChainId as WebXRSwapChainId; // From the GLES 2.0.25 spec, page 85: // @@ -130,10 +131,9 @@ pub struct WebGLRenderingContext { webgl_sender: WebGLMessageSender, #[ignore_malloc_size_of = "Defined in webrender"] webrender_image: webrender_api::ImageKey, - share_mode: WebGLContextShareMode, webgl_version: WebGLVersion, glsl_version: WebGLSLVersion, - #[ignore_malloc_size_of = "Defined in offscreen_gl_context"] + #[ignore_malloc_size_of = "Defined in surfman"] limits: GLLimits, canvas: Dom<HTMLCanvasElement>, #[ignore_malloc_size_of = "Defined in canvas_traits"] @@ -160,7 +160,6 @@ pub struct WebGLRenderingContext { current_vao: MutNullableDom<WebGLVertexArrayObjectOES>, textures: Textures, api_type: GlType, - framebuffer_format: GLFormats, } impl WebGLRenderingContext { @@ -195,7 +194,6 @@ impl WebGLRenderingContext { window.get_event_loop_waker(), ), webrender_image: ctx_data.image_key, - share_mode: ctx_data.share_mode, webgl_version, glsl_version: ctx_data.glsl_version, limits: ctx_data.limits, @@ -220,7 +218,6 @@ impl WebGLRenderingContext { current_vao: Default::default(), textures: Textures::new(max_combined_texture_image_units), api_type: ctx_data.api_type, - framebuffer_format: ctx_data.framebuffer_format, } }) } @@ -292,7 +289,7 @@ impl WebGLRenderingContext { self.send_command(WebGLCommand::Scissor(rect.0, rect.1, rect.2, rect.3)); // Bound texture must not change when the canvas is resized. - // Right now offscreen_gl_context generates a new FBO and the bound texture is changed + // Right now surfman generates a new FBO and the bound texture is changed // in order to create a new render to texture attachment. // Send a command to re-bind the TEXTURE_2D, if any. if let Some(texture) = self @@ -308,7 +305,7 @@ impl WebGLRenderingContext { } // Bound framebuffer must not change when the canvas is resized. - // Right now offscreen_gl_context 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. if let Some(fbo) = self.bound_framebuffer.get() { let id = WebGLFramebufferBindingRequest::Explicit(fbo.id()); @@ -324,6 +321,10 @@ impl WebGLRenderingContext { self.webgl_sender.context_id() } + pub fn onscreen(&self) -> bool { + self.canvas.upcast::<Node>().is_connected() + } + #[inline] pub fn send_command(&self, command: WebGLCommand) { self.webgl_sender @@ -337,6 +338,10 @@ impl WebGLRenderingContext { .send(command, capture_webgl_backtrace(self)); } + pub fn swap_buffers(&self, id: Option<WebGLOpaqueFramebufferId>) { + let _ = self.webgl_sender.send_swap_buffers(id); + } + #[inline] pub fn send_vr_command(&self, command: WebVRCommand) { self.webgl_sender.send_vr(command).unwrap(); @@ -438,13 +443,12 @@ impl WebGLRenderingContext { } let target = TexImageTarget::Texture2D; - let info = texture.image_info_for_target(&target, 0); - if info.is_initialized() { + if let Some(info) = texture.image_info_for_target(&target, 0) { self.validate_filterable_texture( &texture, target, 0, - info.internal_format().unwrap_or(TexFormat::RGBA), + info.internal_format(), Size2D::new(info.width(), info.height()), info.data_type().unwrap_or(TexDataType::UnsignedByte), ); @@ -462,7 +466,7 @@ impl WebGLRenderingContext { .dirty(NodeDamage::OtherNodeDamage); let document = document_from_node(&*self.canvas); - document.add_dirty_canvas(self.context_id()); + document.add_dirty_canvas(self); } fn vertex_attrib(&self, indx: u32, x: f32, y: f32, z: f32, w: f32) { @@ -746,7 +750,10 @@ impl WebGLRenderingContext { pixels: TexPixels, ) { // We have already validated level - let image_info = texture.image_info_for_target(&target, level); + let image_info = match texture.image_info_for_target(&target, level) { + Some(info) => info, + None => return self.webgl_error(InvalidOperation), + }; // GL_INVALID_VALUE is generated if: // - xoffset or yoffset is less than 0 @@ -761,9 +768,7 @@ impl WebGLRenderingContext { } // NB: format and internal_format must match. - if format != image_info.internal_format().unwrap() || - data_type != image_info.data_type().unwrap() - { + if format != image_info.internal_format() || data_type != image_info.data_type().unwrap() { return self.webgl_error(InvalidOperation); } @@ -810,8 +815,9 @@ impl WebGLRenderingContext { receiver.recv().unwrap() } - pub fn layout_handle(&self) -> webrender_api::ImageKey { - self.webrender_image + pub(crate) fn layout_handle(&self) -> HTMLCanvasDataSource { + let image_key = self.webrender_image; + HTMLCanvasDataSource::WebGL(image_key) } // https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/ @@ -1086,17 +1092,9 @@ impl WebGLRenderingContext { self.bound_framebuffer.get() } - pub fn bound_renderbuffer(&self) -> Option<DomRoot<WebGLRenderbuffer>> { - self.bound_renderbuffer.get() - } - pub fn extension_manager(&self) -> &WebGLExtensions { &self.extension_manager } - - pub fn formats(&self) -> &GLFormats { - &self.framebuffer_format - } } #[cfg(not(feature = "webgl_backtrace"))] @@ -1921,9 +1919,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { Some(WebGLFramebufferAttachmentRoot::Renderbuffer(rb)) => { TexFormat::from_gl_constant(rb.internal_format()) }, - Some(WebGLFramebufferAttachmentRoot::Texture(texture)) => { - texture.image_info_for_target(&target, 0).internal_format() - }, + Some(WebGLFramebufferAttachmentRoot::Texture(texture)) => texture + .image_info_for_target(&target, 0) + .map(|info| info.internal_format()), None => None, }, None => { @@ -2022,7 +2020,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { Err(_) => return, }; - let image_info = texture.image_info_for_target(&target, level); + let image_info = match texture.image_info_for_target(&target, level) { + Some(info) => info, + None => return self.webgl_error(InvalidOperation), + }; // GL_INVALID_VALUE is generated if: // - xoffset or yoffset is less than 0 @@ -2225,6 +2226,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6 fn DeleteFramebuffer(&self, framebuffer: Option<&WebGLFramebuffer>) { if let Some(framebuffer) = framebuffer { + // https://immersive-web.github.io/webxr/#opaque-framebuffer + // Can opaque framebuffers be deleted? + // https://github.com/immersive-web/webxr/issues/855 + handle_potential_webgl_error!(self, framebuffer.validate_transparent(), return); handle_potential_webgl_error!(self, self.validate_ownership(framebuffer), return); handle_object_deletion!( self, @@ -2384,7 +2389,11 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { pname: u32, ) -> JSVal { // Check if currently bound framebuffer is non-zero as per spec. - if self.bound_framebuffer.get().is_none() { + if let Some(fb) = self.bound_framebuffer.get() { + // Opaque framebuffers cannot have their attachments inspected + // https://immersive-web.github.io/webxr/#opaque-framebuffer + handle_potential_webgl_error!(self, fb.validate_transparent(), return NullValue()); + } else { self.webgl_error(InvalidOperation); return NullValue(); } @@ -2487,6 +2496,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.7 fn GetRenderbufferParameter(&self, _cx: SafeJSContext, target: u32, pname: u32) -> JSVal { + // We do not check to see if the renderbuffer came from an opaque framebuffer + // https://github.com/immersive-web/webxr/issues/862 let target_matches = target == constants::RENDERBUFFER; let pname_matches = match pname { @@ -3477,6 +3488,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { if program.is_deleted() || !program.is_linked() || + self.context_id() != location.context_id() || program.id() != location.program_id() || program.link_generation() != location.link_generation() { @@ -4153,7 +4165,7 @@ pub trait LayoutCanvasWebGLRenderingContextHelpers { impl LayoutCanvasWebGLRenderingContextHelpers for LayoutDom<WebGLRenderingContext> { #[allow(unsafe_code)] unsafe fn canvas_data_source(&self) -> HTMLCanvasDataSource { - HTMLCanvasDataSource::WebGL((*self.unsafe_get()).layout_handle()) + (*self.unsafe_get()).layout_handle() } } @@ -4347,7 +4359,7 @@ impl TexPixels { } #[derive(JSTraceable)] -pub(crate) struct WebGLCommandSender { +pub struct WebGLCommandSender { sender: WebGLChan, waker: Option<Box<dyn EventLoopWaker>>, } @@ -4410,6 +4422,18 @@ impl WebGLMessageSender { self.wake_after_send(|| self.sender.send_vr(command)) } + pub fn send_swap_buffers(&self, id: Option<WebGLOpaqueFramebufferId>) -> WebGLSendResult { + self.wake_after_send(|| self.sender.send_swap_buffers(id)) + } + + pub fn send_create_webxr_swap_chain( + &self, + size: Size2D<i32>, + sender: WebGLSender<Option<WebXRSwapChainId>>, + ) -> WebGLSendResult { + self.wake_after_send(|| self.sender.send_create_webxr_swap_chain(size, sender)) + } + pub fn send_resize( &self, size: Size2D<u32>, |