mirror of
https://github.com/servo/servo.git
synced 2025-06-16 12:24:29 +00:00
Remove extra webgl message pumping thread.
This commit is contained in:
parent
d7269ad3c6
commit
a2ca3ddbd9
10 changed files with 189 additions and 43 deletions
|
@ -10,7 +10,8 @@ use euclid::default::Size2D;
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use gleam::gl;
|
use gleam::gl;
|
||||||
use half::f16;
|
use half::f16;
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::{self, IpcSender, OpaqueIpcMessage};
|
||||||
|
use ipc_channel::router::ROUTER;
|
||||||
use offscreen_gl_context::{DrawBuffer, GLContext, NativeGLContextMethods};
|
use offscreen_gl_context::{DrawBuffer, GLContext, NativeGLContextMethods};
|
||||||
use pixels::{self, PixelFormat};
|
use pixels::{self, PixelFormat};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
@ -159,27 +160,24 @@ impl WebGLThread {
|
||||||
event_loop_waker: Box<dyn EventLoopWaker>,
|
event_loop_waker: Box<dyn EventLoopWaker>,
|
||||||
textures: TexturesMap,
|
textures: TexturesMap,
|
||||||
) -> WebGLMainThread {
|
) -> WebGLMainThread {
|
||||||
|
if let WebGLReceiver::Ipc(ref mut receiver) = init.receiver {
|
||||||
// Interpose a new channel in between the existing WebGL channel endpoints.
|
// Interpose a new channel in between the existing WebGL channel endpoints.
|
||||||
// This will bounce all WebGL messages through a second thread adding a small
|
// This will bounce all WebGL messages through the router thread adding a small
|
||||||
// delay, but this will also ensure that the main thread will wake up and
|
// delay, but this will also ensure that the main thread will wake up and
|
||||||
// process the WebGL message when it arrives.
|
// process the WebGL message when it arrives.
|
||||||
let (from_router_sender, from_router_receiver) = webgl_channel::<WebGLMsg>().unwrap();
|
let (from_router_sender, from_router_receiver) = ipc::channel::<WebGLMsg>().unwrap();
|
||||||
let receiver = mem::replace(&mut init.receiver, from_router_receiver);
|
let old_receiver = mem::replace(receiver, from_router_receiver);
|
||||||
|
ROUTER.add_route(
|
||||||
let thread_data = WebGLThread::new(init);
|
old_receiver.to_opaque(),
|
||||||
|
Box::new(move |msg: OpaqueIpcMessage| {
|
||||||
thread::Builder::new()
|
let _ = from_router_sender.send(msg.to().unwrap());
|
||||||
.name("WebGL main thread pump".to_owned())
|
|
||||||
.spawn(move || {
|
|
||||||
while let Ok(msg) = receiver.recv() {
|
|
||||||
let _ = from_router_sender.send(msg);
|
|
||||||
event_loop_waker.wake();
|
event_loop_waker.wake();
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.expect("Thread spawning failed");
|
|
||||||
|
|
||||||
WebGLMainThread {
|
WebGLMainThread {
|
||||||
thread_data,
|
thread_data: WebGLThread::new(init),
|
||||||
textures,
|
textures,
|
||||||
shut_down: false,
|
shut_down: false,
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,7 @@ use compositing::compositor_thread::Msg as ToCompositorMsg;
|
||||||
use compositing::SendableFrameTree;
|
use compositing::SendableFrameTree;
|
||||||
use crossbeam_channel::{unbounded, Receiver, Sender};
|
use crossbeam_channel::{unbounded, Receiver, Sender};
|
||||||
use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg};
|
use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg};
|
||||||
use embedder_traits::{Cursor, EmbedderMsg, EmbedderProxy};
|
use embedder_traits::{Cursor, EmbedderMsg, EmbedderProxy, EventLoopWaker};
|
||||||
use euclid::{default::Size2D as UntypedSize2D, Scale, Size2D};
|
use euclid::{default::Size2D as UntypedSize2D, Scale, Size2D};
|
||||||
use gfx::font_cache_thread::FontCacheThread;
|
use gfx::font_cache_thread::FontCacheThread;
|
||||||
use gfx_traits::Epoch;
|
use gfx_traits::Epoch;
|
||||||
|
@ -416,6 +416,9 @@ pub struct Constellation<Message, LTF, STF> {
|
||||||
|
|
||||||
/// Application window's GL Context for Media player
|
/// Application window's GL Context for Media player
|
||||||
player_context: WindowGLContext,
|
player_context: WindowGLContext,
|
||||||
|
|
||||||
|
/// Mechanism to force the compositor to process events.
|
||||||
|
event_loop_waker: Option<Box<dyn EventLoopWaker>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// State needed to construct a constellation.
|
/// State needed to construct a constellation.
|
||||||
|
@ -469,6 +472,9 @@ pub struct InitialConstellationState {
|
||||||
|
|
||||||
/// Application window's GL Context for Media player
|
/// Application window's GL Context for Media player
|
||||||
pub player_context: WindowGLContext,
|
pub player_context: WindowGLContext,
|
||||||
|
|
||||||
|
/// Mechanism to force the compositor to process events.
|
||||||
|
pub event_loop_waker: Option<Box<dyn EventLoopWaker>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Data needed for webdriver
|
/// Data needed for webdriver
|
||||||
|
@ -767,6 +773,7 @@ where
|
||||||
enable_canvas_antialiasing,
|
enable_canvas_antialiasing,
|
||||||
glplayer_threads: state.glplayer_threads,
|
glplayer_threads: state.glplayer_threads,
|
||||||
player_context: state.player_context,
|
player_context: state.player_context,
|
||||||
|
event_loop_waker: state.event_loop_waker,
|
||||||
};
|
};
|
||||||
|
|
||||||
constellation.run();
|
constellation.run();
|
||||||
|
@ -1009,6 +1016,7 @@ where
|
||||||
webvr_chan: self.webvr_chan.clone(),
|
webvr_chan: self.webvr_chan.clone(),
|
||||||
webxr_registry: self.webxr_registry.clone(),
|
webxr_registry: self.webxr_registry.clone(),
|
||||||
player_context: self.player_context.clone(),
|
player_context: self.player_context.clone(),
|
||||||
|
event_loop_waker: self.event_loop_waker.as_ref().map(|w| (*w).clone_box()),
|
||||||
});
|
});
|
||||||
|
|
||||||
let pipeline = match result {
|
let pipeline = match result {
|
||||||
|
|
|
@ -11,6 +11,7 @@ use compositing::CompositionPipeline;
|
||||||
use compositing::CompositorProxy;
|
use compositing::CompositorProxy;
|
||||||
use crossbeam_channel::Sender;
|
use crossbeam_channel::Sender;
|
||||||
use devtools_traits::{DevtoolsControlMsg, ScriptToDevtoolsControlMsg};
|
use devtools_traits::{DevtoolsControlMsg, ScriptToDevtoolsControlMsg};
|
||||||
|
use embedder_traits::EventLoopWaker;
|
||||||
use euclid::{Scale, Size2D};
|
use euclid::{Scale, Size2D};
|
||||||
use gfx::font_cache_thread::FontCacheThread;
|
use gfx::font_cache_thread::FontCacheThread;
|
||||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
||||||
|
@ -195,6 +196,9 @@ pub struct InitialPipelineState {
|
||||||
|
|
||||||
/// Application window's GL Context for Media player
|
/// Application window's GL Context for Media player
|
||||||
pub player_context: WindowGLContext,
|
pub player_context: WindowGLContext,
|
||||||
|
|
||||||
|
/// Mechanism to force the compositor to process events.
|
||||||
|
pub event_loop_waker: Option<Box<dyn EventLoopWaker>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct NewPipeline {
|
pub struct NewPipeline {
|
||||||
|
@ -327,7 +331,11 @@ impl Pipeline {
|
||||||
let register = state
|
let register = state
|
||||||
.background_monitor_register
|
.background_monitor_register
|
||||||
.expect("Couldn't start content, no background monitor has been initiated");
|
.expect("Couldn't start content, no background monitor has been initiated");
|
||||||
unprivileged_pipeline_content.start_all::<Message, LTF, STF>(false, register);
|
unprivileged_pipeline_content.start_all::<Message, LTF, STF>(
|
||||||
|
false,
|
||||||
|
register,
|
||||||
|
state.event_loop_waker,
|
||||||
|
);
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -524,6 +532,7 @@ impl UnprivilegedPipelineContent {
|
||||||
self,
|
self,
|
||||||
wait_for_completion: bool,
|
wait_for_completion: bool,
|
||||||
background_hang_monitor_register: Box<dyn BackgroundHangMonitorRegister>,
|
background_hang_monitor_register: Box<dyn BackgroundHangMonitorRegister>,
|
||||||
|
event_loop_waker: Option<Box<dyn EventLoopWaker>>,
|
||||||
) where
|
) where
|
||||||
LTF: LayoutThreadFactory<Message = Message>,
|
LTF: LayoutThreadFactory<Message = Message>,
|
||||||
STF: ScriptThreadFactory<Message = Message>,
|
STF: ScriptThreadFactory<Message = Message>,
|
||||||
|
@ -566,6 +575,7 @@ impl UnprivilegedPipelineContent {
|
||||||
webrender_api_sender: self.webrender_api_sender.clone(),
|
webrender_api_sender: self.webrender_api_sender.clone(),
|
||||||
layout_is_busy: layout_thread_busy_flag.clone(),
|
layout_is_busy: layout_thread_busy_flag.clone(),
|
||||||
player_context: self.player_context.clone(),
|
player_context: self.player_context.clone(),
|
||||||
|
event_loop_waker,
|
||||||
},
|
},
|
||||||
self.load_data.clone(),
|
self.load_data.clone(),
|
||||||
self.opts.profile_script_events,
|
self.opts.profile_script_events,
|
||||||
|
|
|
@ -54,6 +54,7 @@ use canvas_traits::webgl::{WebGLShaderId, WebGLTextureId, WebGLVersion, WebGLVer
|
||||||
use crossbeam_channel::{Receiver, Sender};
|
use crossbeam_channel::{Receiver, Sender};
|
||||||
use cssparser::RGBA;
|
use cssparser::RGBA;
|
||||||
use devtools_traits::{CSSError, TimelineMarkerType, WorkerId};
|
use devtools_traits::{CSSError, TimelineMarkerType, WorkerId};
|
||||||
|
use embedder_traits::EventLoopWaker;
|
||||||
use encoding_rs::{Decoder, Encoding};
|
use encoding_rs::{Decoder, Encoding};
|
||||||
use euclid::default::{Point2D, Rect, Rotation3D, Transform2D, Transform3D};
|
use euclid::default::{Point2D, Rect, Rotation3D, Transform2D, Transform3D};
|
||||||
use euclid::Length as EuclidLength;
|
use euclid::Length as EuclidLength;
|
||||||
|
@ -146,7 +147,7 @@ pub unsafe trait JSTraceable {
|
||||||
unsafe fn trace(&self, trc: *mut JSTracer);
|
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);
|
unsafe_no_jsmanaged_fields!(CSSError);
|
||||||
|
|
||||||
|
|
|
@ -32,11 +32,11 @@ use crate::dom::vreyeparameters::VREyeParameters;
|
||||||
use crate::dom::vrframedata::VRFrameData;
|
use crate::dom::vrframedata::VRFrameData;
|
||||||
use crate::dom::vrpose::VRPose;
|
use crate::dom::vrpose::VRPose;
|
||||||
use crate::dom::vrstageparameters::VRStageParameters;
|
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::CommonScriptMsg;
|
||||||
use crate::script_runtime::ScriptThreadEventCategory::WebVREvent;
|
use crate::script_runtime::ScriptThreadEventCategory::WebVREvent;
|
||||||
use crate::task_source::{TaskSource, TaskSourceName};
|
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 crossbeam_channel::{unbounded, Sender};
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
|
@ -102,7 +102,7 @@ struct VRRAFUpdate {
|
||||||
depth_near: f64,
|
depth_near: f64,
|
||||||
depth_far: f64,
|
depth_far: f64,
|
||||||
/// WebGL API sender
|
/// WebGL API sender
|
||||||
api_sender: Option<WebGLMsgSender>,
|
api_sender: Option<WebGLMessageSender>,
|
||||||
/// Number uniquely identifying the WebGL context
|
/// Number uniquely identifying the WebGL context
|
||||||
/// so that we may setup/tear down VR compositors as things change
|
/// so that we may setup/tear down VR compositors as things change
|
||||||
context_id: usize,
|
context_id: usize,
|
||||||
|
@ -583,7 +583,7 @@ impl VRDisplay {
|
||||||
.fire(self.global().upcast::<EventTarget>());
|
.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())
|
self.layer_ctx.get().map(|c| c.webgl_sender())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,12 +54,13 @@ use backtrace::Backtrace;
|
||||||
use canvas_traits::webgl::WebGLError::*;
|
use canvas_traits::webgl::WebGLError::*;
|
||||||
use canvas_traits::webgl::{
|
use canvas_traits::webgl::{
|
||||||
webgl_channel, AlphaTreatment, DOMToTextureCommand, GLContextAttributes, GLLimits, GlType,
|
webgl_channel, AlphaTreatment, DOMToTextureCommand, GLContextAttributes, GLLimits, GlType,
|
||||||
Parameter, TexDataType, TexFormat, TexParameter, WebGLCommand, WebGLCommandBacktrace,
|
Parameter, TexDataType, TexFormat, TexParameter, WebGLChan, WebGLCommand,
|
||||||
WebGLContextShareMode, WebGLError, WebGLFramebufferBindingRequest, WebGLMsg, WebGLMsgSender,
|
WebGLCommandBacktrace, WebGLContextId, WebGLContextShareMode, WebGLError,
|
||||||
WebGLProgramId, WebGLResult, WebGLSLVersion, WebGLSender, WebGLVersion, WebVRCommand,
|
WebGLFramebufferBindingRequest, WebGLMsg, WebGLMsgSender, WebGLProgramId, WebGLResult,
|
||||||
YAxisTreatment,
|
WebGLSLVersion, WebGLSendResult, WebGLSender, WebGLVersion, WebVRCommand, YAxisTreatment,
|
||||||
};
|
};
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
|
use embedder_traits::EventLoopWaker;
|
||||||
use euclid::default::{Point2D, Rect, Size2D};
|
use euclid::default::{Point2D, Rect, Size2D};
|
||||||
use ipc_channel::ipc::{self, IpcSharedMemory};
|
use ipc_channel::ipc::{self, IpcSharedMemory};
|
||||||
use js::jsapi::{JSContext, JSObject, Type};
|
use js::jsapi::{JSContext, JSObject, Type};
|
||||||
|
@ -79,6 +80,7 @@ use std::cell::Cell;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::ptr::{self, NonNull};
|
use std::ptr::{self, NonNull};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use webrender_api::ImageKey;
|
||||||
|
|
||||||
// From the GLES 2.0.25 spec, page 85:
|
// From the GLES 2.0.25 spec, page 85:
|
||||||
//
|
//
|
||||||
|
@ -135,7 +137,7 @@ bitflags! {
|
||||||
pub struct WebGLRenderingContext {
|
pub struct WebGLRenderingContext {
|
||||||
reflector_: Reflector,
|
reflector_: Reflector,
|
||||||
#[ignore_malloc_size_of = "Channels are hard"]
|
#[ignore_malloc_size_of = "Channels are hard"]
|
||||||
webgl_sender: WebGLMsgSender,
|
webgl_sender: WebGLMessageSender,
|
||||||
#[ignore_malloc_size_of = "Defined in webrender"]
|
#[ignore_malloc_size_of = "Defined in webrender"]
|
||||||
webrender_image: Cell<Option<webrender_api::ImageKey>>,
|
webrender_image: Cell<Option<webrender_api::ImageKey>>,
|
||||||
share_mode: WebGLContextShareMode,
|
share_mode: WebGLContextShareMode,
|
||||||
|
@ -197,7 +199,10 @@ impl WebGLRenderingContext {
|
||||||
let max_combined_texture_image_units = ctx_data.limits.max_combined_texture_image_units;
|
let max_combined_texture_image_units = ctx_data.limits.max_combined_texture_image_units;
|
||||||
Self {
|
Self {
|
||||||
reflector_: Reflector::new(),
|
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),
|
webrender_image: Cell::new(None),
|
||||||
share_mode: ctx_data.share_mode,
|
share_mode: ctx_data.share_mode,
|
||||||
webgl_version,
|
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()
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -50,6 +50,7 @@ use crate::dom::promise::Promise;
|
||||||
use crate::dom::screen::Screen;
|
use crate::dom::screen::Screen;
|
||||||
use crate::dom::storage::Storage;
|
use crate::dom::storage::Storage;
|
||||||
use crate::dom::testrunner::TestRunner;
|
use crate::dom::testrunner::TestRunner;
|
||||||
|
use crate::dom::webglrenderingcontext::WebGLCommandSender;
|
||||||
use crate::dom::windowproxy::WindowProxy;
|
use crate::dom::windowproxy::WindowProxy;
|
||||||
use crate::dom::worklet::Worklet;
|
use crate::dom::worklet::Worklet;
|
||||||
use crate::dom::workletglobalscope::WorkletGlobalScopeType;
|
use crate::dom::workletglobalscope::WorkletGlobalScopeType;
|
||||||
|
@ -73,7 +74,7 @@ use crossbeam_channel::{unbounded, Sender, TryRecvError};
|
||||||
use cssparser::{Parser, ParserInput, SourceLocation};
|
use cssparser::{Parser, ParserInput, SourceLocation};
|
||||||
use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType};
|
use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType};
|
||||||
use dom_struct::dom_struct;
|
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::default::{Point2D as UntypedPoint2D, Rect as UntypedRect};
|
||||||
use euclid::{Point2D, Rect, Scale, Size2D, Vector2D};
|
use euclid::{Point2D, Rect, Scale, Size2D, Vector2D};
|
||||||
use ipc_channel::ipc::{channel, IpcSender};
|
use ipc_channel::ipc::{channel, IpcSender};
|
||||||
|
@ -326,6 +327,10 @@ pub struct Window {
|
||||||
/// Window's GL context from application
|
/// Window's GL context from application
|
||||||
#[ignore_malloc_size_of = "defined in script_thread"]
|
#[ignore_malloc_size_of = "defined in script_thread"]
|
||||||
player_context: WindowGLContext,
|
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 {
|
impl Window {
|
||||||
|
@ -432,8 +437,10 @@ impl Window {
|
||||||
self.current_viewport.clone().get()
|
self.current_viewport.clone().get()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn webgl_chan(&self) -> Option<WebGLChan> {
|
pub(crate) fn webgl_chan(&self) -> Option<WebGLCommandSender> {
|
||||||
self.webgl_chan.clone()
|
self.webgl_chan
|
||||||
|
.as_ref()
|
||||||
|
.map(|chan| WebGLCommandSender::new(chan.clone(), self.get_event_loop_waker()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn webvr_thread(&self) -> Option<IpcSender<WebVRMsg>> {
|
pub fn webvr_thread(&self) -> Option<IpcSender<WebVRMsg>> {
|
||||||
|
@ -498,6 +505,10 @@ impl Window {
|
||||||
pub fn get_player_context(&self) -> WindowGLContext {
|
pub fn get_player_context(&self) -> WindowGLContext {
|
||||||
self.player_context.clone()
|
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
|
// https://html.spec.whatwg.org/multipage/#atob
|
||||||
|
@ -2087,6 +2098,7 @@ impl Window {
|
||||||
replace_surrogates: bool,
|
replace_surrogates: bool,
|
||||||
user_agent: Cow<'static, str>,
|
user_agent: Cow<'static, str>,
|
||||||
player_context: WindowGLContext,
|
player_context: WindowGLContext,
|
||||||
|
event_loop_waker: Option<Box<dyn EventLoopWaker>>,
|
||||||
) -> DomRoot<Self> {
|
) -> DomRoot<Self> {
|
||||||
let layout_rpc: Box<dyn LayoutRPC + Send> = {
|
let layout_rpc: Box<dyn LayoutRPC + Send> = {
|
||||||
let (rpc_send, rpc_recv) = unbounded();
|
let (rpc_send, rpc_recv) = unbounded();
|
||||||
|
@ -2169,6 +2181,7 @@ impl Window {
|
||||||
userscripts_path,
|
userscripts_path,
|
||||||
replace_surrogates,
|
replace_surrogates,
|
||||||
player_context,
|
player_context,
|
||||||
|
event_loop_waker,
|
||||||
});
|
});
|
||||||
|
|
||||||
unsafe { WindowBinding::Wrap(JSContext::from_ptr(runtime.cx()), win) }
|
unsafe { WindowBinding::Wrap(JSContext::from_ptr(runtime.cx()), win) }
|
||||||
|
|
|
@ -93,7 +93,7 @@ use crossbeam_channel::{unbounded, Receiver, Sender};
|
||||||
use devtools_traits::CSSError;
|
use devtools_traits::CSSError;
|
||||||
use devtools_traits::{DevtoolScriptControlMsg, DevtoolsPageInfo};
|
use devtools_traits::{DevtoolScriptControlMsg, DevtoolsPageInfo};
|
||||||
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
|
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
|
||||||
use embedder_traits::EmbedderMsg;
|
use embedder_traits::{EmbedderMsg, EventLoopWaker};
|
||||||
use euclid::default::{Point2D, Rect};
|
use euclid::default::{Point2D, Rect};
|
||||||
use euclid::Vector2D;
|
use euclid::Vector2D;
|
||||||
use headers::ReferrerPolicy as ReferrerPolicyHeader;
|
use headers::ReferrerPolicy as ReferrerPolicyHeader;
|
||||||
|
@ -684,6 +684,9 @@ pub struct ScriptThread {
|
||||||
|
|
||||||
/// Application window's GL Context for Media player
|
/// Application window's GL Context for Media player
|
||||||
player_context: WindowGLContext,
|
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
|
/// In the event of thread panic, all data on the stack runs its destructor. However, there
|
||||||
|
@ -1314,6 +1317,7 @@ impl ScriptThread {
|
||||||
replace_surrogates,
|
replace_surrogates,
|
||||||
user_agent,
|
user_agent,
|
||||||
player_context: state.player_context,
|
player_context: state.player_context,
|
||||||
|
event_loop_waker: state.event_loop_waker,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3142,6 +3146,7 @@ impl ScriptThread {
|
||||||
self.replace_surrogates,
|
self.replace_surrogates,
|
||||||
self.user_agent.clone(),
|
self.user_agent.clone(),
|
||||||
self.player_context.clone(),
|
self.player_context.clone(),
|
||||||
|
self.event_loop_waker.as_ref().map(|w| (*w).clone_box()),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Initialize the browsing context for the window.
|
// Initialize the browsing context for the window.
|
||||||
|
|
|
@ -24,7 +24,7 @@ use bluetooth_traits::BluetoothRequest;
|
||||||
use canvas_traits::webgl::WebGLPipeline;
|
use canvas_traits::webgl::WebGLPipeline;
|
||||||
use crossbeam_channel::{Receiver, RecvTimeoutError, Sender};
|
use crossbeam_channel::{Receiver, RecvTimeoutError, Sender};
|
||||||
use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId};
|
use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId};
|
||||||
use embedder_traits::Cursor;
|
use embedder_traits::{Cursor, EventLoopWaker};
|
||||||
use euclid::{
|
use euclid::{
|
||||||
default::{Point2D, Rect},
|
default::{Point2D, Rect},
|
||||||
Length, Scale, Size2D, Vector2D,
|
Length, Scale, Size2D, Vector2D,
|
||||||
|
@ -666,6 +666,8 @@ pub struct InitialScriptState {
|
||||||
pub layout_is_busy: Arc<AtomicBool>,
|
pub layout_is_busy: Arc<AtomicBool>,
|
||||||
/// Application window's GL Context for Media player
|
/// Application window's GL Context for Media player
|
||||||
pub player_context: WindowGLContext,
|
pub player_context: WindowGLContext,
|
||||||
|
/// Mechanism to force the compositor to process events.
|
||||||
|
pub event_loop_waker: Option<Box<dyn EventLoopWaker>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This trait allows creating a `ScriptThread` without depending on the `script`
|
/// This trait allows creating a `ScriptThread` without depending on the `script`
|
||||||
|
|
|
@ -413,17 +413,17 @@ where
|
||||||
let (external_image_handlers, external_images) = WebrenderExternalImageHandlers::new();
|
let (external_image_handlers, external_images) = WebrenderExternalImageHandlers::new();
|
||||||
let mut external_image_handlers = Box::new(external_image_handlers);
|
let mut external_image_handlers = Box::new(external_image_handlers);
|
||||||
|
|
||||||
// Initialize WebGL Thread entry point.
|
let run_webgl_on_main_thread =
|
||||||
let webgl_result = gl_factory.map(|factory| {
|
|
||||||
let run_on_main_thread =
|
|
||||||
cfg!(windows) || std::env::var("SERVO_WEBGL_MAIN_THREAD").is_ok();
|
cfg!(windows) || std::env::var("SERVO_WEBGL_MAIN_THREAD").is_ok();
|
||||||
|
|
||||||
|
// Initialize WebGL Thread entry point.
|
||||||
|
let webgl_result = gl_factory.map(|factory| {
|
||||||
let (webgl_threads, thread_data, image_handler, output_handler) = WebGLThreads::new(
|
let (webgl_threads, thread_data, image_handler, output_handler) = WebGLThreads::new(
|
||||||
factory,
|
factory,
|
||||||
webrender_api_sender.clone(),
|
webrender_api_sender.clone(),
|
||||||
webvr_compositor.map(|c| c as Box<_>),
|
webvr_compositor.map(|c| c as Box<_>),
|
||||||
external_images.clone(),
|
external_images.clone(),
|
||||||
if run_on_main_thread {
|
if run_webgl_on_main_thread {
|
||||||
ThreadMode::MainThread(embedder.create_event_loop_waker())
|
ThreadMode::MainThread(embedder.create_event_loop_waker())
|
||||||
} else {
|
} else {
|
||||||
ThreadMode::OffThread(window.gl())
|
ThreadMode::OffThread(window.gl())
|
||||||
|
@ -464,6 +464,17 @@ where
|
||||||
|
|
||||||
webrender.set_external_image_handler(external_image_handlers);
|
webrender.set_external_image_handler(external_image_handlers);
|
||||||
|
|
||||||
|
// When webgl execution occurs on the main thread, and the script thread
|
||||||
|
// lives in the same process, then the script thread needs the ability to
|
||||||
|
// wake up the main thread's event loop when webgl commands need processing.
|
||||||
|
// When there are multiple processes, this is handled automatically by
|
||||||
|
// the IPC receiving handler instead.
|
||||||
|
let event_loop_waker = if run_webgl_on_main_thread && !opts.multiprocess {
|
||||||
|
Some(embedder.create_event_loop_waker())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
// Create the constellation, which maintains the engine
|
// Create the constellation, which maintains the engine
|
||||||
// pipelines, including the script and layout threads, as well
|
// pipelines, including the script and layout threads, as well
|
||||||
// as the navigation context.
|
// as the navigation context.
|
||||||
|
@ -484,6 +495,7 @@ where
|
||||||
webvr_chan,
|
webvr_chan,
|
||||||
webvr_constellation_sender,
|
webvr_constellation_sender,
|
||||||
glplayer_threads,
|
glplayer_threads,
|
||||||
|
event_loop_waker,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Send the constellation's swmanager sender to service worker manager thread
|
// Send the constellation's swmanager sender to service worker manager thread
|
||||||
|
@ -802,6 +814,7 @@ fn create_constellation(
|
||||||
webvr_chan: Option<IpcSender<WebVRMsg>>,
|
webvr_chan: Option<IpcSender<WebVRMsg>>,
|
||||||
webvr_constellation_sender: Option<Sender<Sender<ConstellationMsg>>>,
|
webvr_constellation_sender: Option<Sender<Sender<ConstellationMsg>>>,
|
||||||
glplayer_threads: Option<GLPlayerThreads>,
|
glplayer_threads: Option<GLPlayerThreads>,
|
||||||
|
event_loop_waker: Option<Box<dyn EventLoopWaker>>,
|
||||||
) -> (Sender<ConstellationMsg>, SWManagerSenders) {
|
) -> (Sender<ConstellationMsg>, SWManagerSenders) {
|
||||||
// Global configuration options, parsed from the command line.
|
// Global configuration options, parsed from the command line.
|
||||||
let opts = opts::get();
|
let opts = opts::get();
|
||||||
|
@ -843,6 +856,7 @@ fn create_constellation(
|
||||||
webxr_registry,
|
webxr_registry,
|
||||||
glplayer_threads,
|
glplayer_threads,
|
||||||
player_context,
|
player_context,
|
||||||
|
event_loop_waker,
|
||||||
};
|
};
|
||||||
let (constellation_chan, from_swmanager_sender) = Constellation::<
|
let (constellation_chan, from_swmanager_sender) = Constellation::<
|
||||||
script_layout_interface::message::Msg,
|
script_layout_interface::message::Msg,
|
||||||
|
@ -947,7 +961,8 @@ pub fn run_content_process(token: String) {
|
||||||
layout_thread::LayoutThread,
|
layout_thread::LayoutThread,
|
||||||
script::script_thread::ScriptThread>(
|
script::script_thread::ScriptThread>(
|
||||||
true,
|
true,
|
||||||
background_hang_monitor_register
|
background_hang_monitor_register,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue