diff options
Diffstat (limited to 'components/script')
-rw-r--r-- | components/script/dom/bindings/trace.rs | 3 | ||||
-rw-r--r-- | components/script/dom/vrdisplay.rs | 8 | ||||
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 108 | ||||
-rw-r--r-- | components/script/dom/window.rs | 19 | ||||
-rw-r--r-- | components/script/script_thread.rs | 7 |
5 files changed, 129 insertions, 16 deletions
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index bad7ebaa4bb..9fcc61dc8b6 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -54,6 +54,7 @@ use canvas_traits::webgl::{WebGLShaderId, WebGLTextureId, WebGLVersion, WebGLVer use crossbeam_channel::{Receiver, Sender}; use cssparser::RGBA; use devtools_traits::{CSSError, TimelineMarkerType, WorkerId}; +use embedder_traits::EventLoopWaker; use encoding_rs::{Decoder, Encoding}; use euclid::default::{Point2D, Rect, Rotation3D, Transform2D, Transform3D}; use euclid::Length as EuclidLength; @@ -146,7 +147,7 @@ pub unsafe trait JSTraceable { unsafe fn trace(&self, trc: *mut JSTracer); } -unsafe_no_jsmanaged_fields!(Box<dyn TaskBox>); +unsafe_no_jsmanaged_fields!(Box<dyn TaskBox>, Box<dyn EventLoopWaker>); unsafe_no_jsmanaged_fields!(CSSError); diff --git a/components/script/dom/vrdisplay.rs b/components/script/dom/vrdisplay.rs index 462b1651eb3..81a263d3394 100644 --- a/components/script/dom/vrdisplay.rs +++ b/components/script/dom/vrdisplay.rs @@ -32,11 +32,11 @@ use crate::dom::vreyeparameters::VREyeParameters; use crate::dom::vrframedata::VRFrameData; use crate::dom::vrpose::VRPose; use crate::dom::vrstageparameters::VRStageParameters; -use crate::dom::webglrenderingcontext::WebGLRenderingContext; +use crate::dom::webglrenderingcontext::{WebGLMessageSender, WebGLRenderingContext}; use crate::script_runtime::CommonScriptMsg; use crate::script_runtime::ScriptThreadEventCategory::WebVREvent; use crate::task_source::{TaskSource, TaskSourceName}; -use canvas_traits::webgl::{webgl_channel, WebGLMsgSender, WebGLReceiver, WebVRCommand}; +use canvas_traits::webgl::{webgl_channel, WebGLReceiver, WebVRCommand}; use crossbeam_channel::{unbounded, Sender}; use dom_struct::dom_struct; use ipc_channel::ipc::IpcSender; @@ -102,7 +102,7 @@ struct VRRAFUpdate { depth_near: f64, depth_far: f64, /// WebGL API sender - api_sender: Option<WebGLMsgSender>, + api_sender: Option<WebGLMessageSender>, /// Number uniquely identifying the WebGL context /// so that we may setup/tear down VR compositors as things change context_id: usize, @@ -583,7 +583,7 @@ impl VRDisplay { .fire(self.global().upcast::<EventTarget>()); } - fn api_sender(&self) -> Option<WebGLMsgSender> { + fn api_sender(&self) -> Option<WebGLMessageSender> { self.layer_ctx.get().map(|c| c.webgl_sender()) } diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 1240caccf7c..743a2adec84 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -54,12 +54,13 @@ use backtrace::Backtrace; use canvas_traits::webgl::WebGLError::*; use canvas_traits::webgl::{ webgl_channel, AlphaTreatment, DOMToTextureCommand, GLContextAttributes, GLLimits, GlType, - Parameter, TexDataType, TexFormat, TexParameter, WebGLCommand, WebGLCommandBacktrace, - WebGLContextShareMode, WebGLError, WebGLFramebufferBindingRequest, WebGLMsg, WebGLMsgSender, - WebGLProgramId, WebGLResult, WebGLSLVersion, WebGLSender, WebGLVersion, WebVRCommand, - YAxisTreatment, + Parameter, TexDataType, TexFormat, TexParameter, WebGLChan, WebGLCommand, + WebGLCommandBacktrace, WebGLContextId, WebGLContextShareMode, WebGLError, + WebGLFramebufferBindingRequest, WebGLMsg, WebGLMsgSender, WebGLProgramId, WebGLResult, + WebGLSLVersion, WebGLSendResult, WebGLSender, WebGLVersion, WebVRCommand, YAxisTreatment, }; use dom_struct::dom_struct; +use embedder_traits::EventLoopWaker; use euclid::default::{Point2D, Rect, Size2D}; use ipc_channel::ipc::{self, IpcSharedMemory}; use js::jsapi::{JSContext, JSObject, Type}; @@ -79,6 +80,7 @@ use std::cell::Cell; use std::cmp; use std::ptr::{self, NonNull}; use std::rc::Rc; +use webrender_api::ImageKey; // From the GLES 2.0.25 spec, page 85: // @@ -135,7 +137,7 @@ bitflags! { pub struct WebGLRenderingContext { reflector_: Reflector, #[ignore_malloc_size_of = "Channels are hard"] - webgl_sender: WebGLMsgSender, + webgl_sender: WebGLMessageSender, #[ignore_malloc_size_of = "Defined in webrender"] webrender_image: Cell<Option<webrender_api::ImageKey>>, share_mode: WebGLContextShareMode, @@ -197,7 +199,10 @@ impl WebGLRenderingContext { let max_combined_texture_image_units = ctx_data.limits.max_combined_texture_image_units; Self { reflector_: Reflector::new(), - webgl_sender: ctx_data.sender, + webgl_sender: WebGLMessageSender::new( + ctx_data.sender, + window.get_event_loop_waker(), + ), webrender_image: Cell::new(None), share_mode: ctx_data.share_mode, webgl_version, @@ -319,7 +324,7 @@ impl WebGLRenderingContext { } } - pub fn webgl_sender(&self) -> WebGLMsgSender { + pub(crate) fn webgl_sender(&self) -> WebGLMessageSender { self.webgl_sender.clone() } @@ -4288,3 +4293,92 @@ impl TexPixels { } } } + +#[derive(JSTraceable)] +pub(crate) struct WebGLCommandSender { + sender: WebGLChan, + waker: Option<Box<dyn EventLoopWaker>>, +} + +impl WebGLCommandSender { + pub fn new(sender: WebGLChan, waker: Option<Box<dyn EventLoopWaker>>) -> WebGLCommandSender { + WebGLCommandSender { sender, waker } + } + + pub fn send(&self, msg: WebGLMsg) -> WebGLSendResult { + let result = self.sender.send(msg); + if let Some(ref waker) = self.waker { + waker.wake(); + } + result + } +} + +#[derive(JSTraceable, MallocSizeOf)] +pub(crate) struct WebGLMessageSender { + sender: WebGLMsgSender, + #[ignore_malloc_size_of = "traits are cumbersome"] + waker: Option<Box<dyn EventLoopWaker>>, +} + +impl Clone for WebGLMessageSender { + fn clone(&self) -> WebGLMessageSender { + WebGLMessageSender { + sender: self.sender.clone(), + waker: self.waker.as_ref().map(|w| (*w).clone_box()), + } + } +} + +impl WebGLMessageSender { + fn wake_after_send<F: FnOnce() -> WebGLSendResult>(&self, f: F) -> WebGLSendResult { + let result = f(); + if let Some(ref waker) = self.waker { + waker.wake(); + } + result + } + + pub fn new( + sender: WebGLMsgSender, + waker: Option<Box<dyn EventLoopWaker>>, + ) -> WebGLMessageSender { + WebGLMessageSender { sender, waker } + } + + pub fn context_id(&self) -> WebGLContextId { + self.sender.context_id() + } + + pub fn send(&self, msg: WebGLCommand, backtrace: WebGLCommandBacktrace) -> WebGLSendResult { + self.wake_after_send(|| self.sender.send(msg, backtrace)) + } + + pub fn send_vr(&self, command: WebVRCommand) -> WebGLSendResult { + self.wake_after_send(|| self.sender.send_vr(command)) + } + + pub fn send_resize( + &self, + size: Size2D<u32>, + sender: WebGLSender<Result<(), String>>, + ) -> WebGLSendResult { + self.wake_after_send(|| self.sender.send_resize(size, sender)) + } + + pub fn send_remove(&self) -> WebGLSendResult { + self.wake_after_send(|| self.sender.send_remove()) + } + + pub fn send_update_wr_image(&self, sender: WebGLSender<ImageKey>) -> WebGLSendResult { + self.wake_after_send(|| self.sender.send_update_wr_image(sender)) + } + + pub fn send_dom_to_texture(&self, command: DOMToTextureCommand) -> WebGLSendResult { + self.wake_after_send(|| self.sender.send_dom_to_texture(command)) + } + + pub fn webxr_external_image_api(&self) -> impl webxr_api::WebGLExternalImageApi { + self.sender.webxr_external_image_api() + } +} diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index ccbd08e1ef7..b33a5c5a126 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -50,6 +50,7 @@ use crate::dom::promise::Promise; use crate::dom::screen::Screen; use crate::dom::storage::Storage; use crate::dom::testrunner::TestRunner; +use crate::dom::webglrenderingcontext::WebGLCommandSender; use crate::dom::windowproxy::WindowProxy; use crate::dom::worklet::Worklet; use crate::dom::workletglobalscope::WorkletGlobalScopeType; @@ -73,7 +74,7 @@ use crossbeam_channel::{unbounded, Sender, TryRecvError}; use cssparser::{Parser, ParserInput, SourceLocation}; use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType}; use dom_struct::dom_struct; -use embedder_traits::EmbedderMsg; +use embedder_traits::{EmbedderMsg, EventLoopWaker}; use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect}; use euclid::{Point2D, Rect, Scale, Size2D, Vector2D}; use ipc_channel::ipc::{channel, IpcSender}; @@ -326,6 +327,10 @@ pub struct Window { /// Window's GL context from application #[ignore_malloc_size_of = "defined in script_thread"] player_context: WindowGLContext, + + /// A mechanism to force the compositor to process events. + #[ignore_malloc_size_of = "traits are cumbersome"] + event_loop_waker: Option<Box<dyn EventLoopWaker>>, } impl Window { @@ -432,8 +437,10 @@ impl Window { self.current_viewport.clone().get() } - pub fn webgl_chan(&self) -> Option<WebGLChan> { - self.webgl_chan.clone() + pub(crate) fn webgl_chan(&self) -> Option<WebGLCommandSender> { + self.webgl_chan + .as_ref() + .map(|chan| WebGLCommandSender::new(chan.clone(), self.get_event_loop_waker())) } pub fn webvr_thread(&self) -> Option<IpcSender<WebVRMsg>> { @@ -498,6 +505,10 @@ impl Window { pub fn get_player_context(&self) -> WindowGLContext { self.player_context.clone() } + + pub fn get_event_loop_waker(&self) -> Option<Box<dyn EventLoopWaker>> { + self.event_loop_waker.as_ref().map(|w| (*w).clone_box()) + } } // https://html.spec.whatwg.org/multipage/#atob @@ -2087,6 +2098,7 @@ impl Window { replace_surrogates: bool, user_agent: Cow<'static, str>, player_context: WindowGLContext, + event_loop_waker: Option<Box<dyn EventLoopWaker>>, ) -> DomRoot<Self> { let layout_rpc: Box<dyn LayoutRPC + Send> = { let (rpc_send, rpc_recv) = unbounded(); @@ -2169,6 +2181,7 @@ impl Window { userscripts_path, replace_surrogates, player_context, + event_loop_waker, }); unsafe { WindowBinding::Wrap(JSContext::from_ptr(runtime.cx()), win) } diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 81ef7d9493c..77e037406f7 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -93,7 +93,7 @@ use crossbeam_channel::{unbounded, Receiver, Sender}; use devtools_traits::CSSError; use devtools_traits::{DevtoolScriptControlMsg, DevtoolsPageInfo}; use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId}; -use embedder_traits::EmbedderMsg; +use embedder_traits::{EmbedderMsg, EventLoopWaker}; use euclid::default::{Point2D, Rect}; use euclid::Vector2D; use headers::ReferrerPolicy as ReferrerPolicyHeader; @@ -684,6 +684,9 @@ pub struct ScriptThread { /// Application window's GL Context for Media player player_context: WindowGLContext, + + /// A mechanism to force the compositor's event loop to process events. + event_loop_waker: Option<Box<dyn EventLoopWaker>>, } /// In the event of thread panic, all data on the stack runs its destructor. However, there @@ -1314,6 +1317,7 @@ impl ScriptThread { replace_surrogates, user_agent, player_context: state.player_context, + event_loop_waker: state.event_loop_waker, } } @@ -3142,6 +3146,7 @@ impl ScriptThread { self.replace_surrogates, self.user_agent.clone(), self.player_context.clone(), + self.event_loop_waker.as_ref().map(|w| (*w).clone_box()), ); // Initialize the browsing context for the window. |