Skip to content

Commit

Permalink
Remove extra webgl message pumping thread.
Browse files Browse the repository at this point in the history
  • Loading branch information
jdm committed Jul 26, 2019
1 parent d7269ad commit a2ca3dd
Show file tree
Hide file tree
Showing 10 changed files with 189 additions and 43 deletions.
36 changes: 17 additions & 19 deletions components/canvas/webgl_thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ use euclid::default::Size2D;
use fnv::FnvHashMap;
use gleam::gl;
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 pixels::{self, PixelFormat};
use std::borrow::Cow;
Expand Down Expand Up @@ -159,27 +160,24 @@ impl WebGLThread {
event_loop_waker: Box<dyn EventLoopWaker>,
textures: TexturesMap,
) -> WebGLMainThread {
// Interpose a new channel in between the existing WebGL channel endpoints.
// This will bounce all WebGL messages through a second thread adding a small
// delay, but this will also ensure that the main thread will wake up and
// process the WebGL message when it arrives.
let (from_router_sender, from_router_receiver) = webgl_channel::<WebGLMsg>().unwrap();
let receiver = mem::replace(&mut init.receiver, from_router_receiver);

let thread_data = WebGLThread::new(init);

thread::Builder::new()
.name("WebGL main thread pump".to_owned())
.spawn(move || {
while let Ok(msg) = receiver.recv() {
let _ = from_router_sender.send(msg);
if let WebGLReceiver::Ipc(ref mut receiver) = init.receiver {
// Interpose a new channel in between the existing WebGL channel endpoints.
// 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
// process the WebGL message when it arrives.
let (from_router_sender, from_router_receiver) = ipc::channel::<WebGLMsg>().unwrap();
let old_receiver = mem::replace(receiver, from_router_receiver);
ROUTER.add_route(
old_receiver.to_opaque(),
Box::new(move |msg: OpaqueIpcMessage| {
let _ = from_router_sender.send(msg.to().unwrap());
event_loop_waker.wake();
}
})
.expect("Thread spawning failed");
}),
);
}

WebGLMainThread {
thread_data,
thread_data: WebGLThread::new(init),
textures,
shut_down: false,
}
Expand Down
10 changes: 9 additions & 1 deletion components/constellation/constellation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ use compositing::compositor_thread::Msg as ToCompositorMsg;
use compositing::SendableFrameTree;
use crossbeam_channel::{unbounded, Receiver, Sender};
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 gfx::font_cache_thread::FontCacheThread;
use gfx_traits::Epoch;
Expand Down Expand Up @@ -416,6 +416,9 @@ pub struct Constellation<Message, LTF, STF> {

/// Application window's GL Context for Media player
player_context: WindowGLContext,

/// Mechanism to force the compositor to process events.
event_loop_waker: Option<Box<dyn EventLoopWaker>>,
}

/// State needed to construct a constellation.
Expand Down Expand Up @@ -469,6 +472,9 @@ pub struct InitialConstellationState {

/// Application window's GL Context for Media player
pub player_context: WindowGLContext,

/// Mechanism to force the compositor to process events.
pub event_loop_waker: Option<Box<dyn EventLoopWaker>>,
}

/// Data needed for webdriver
Expand Down Expand Up @@ -767,6 +773,7 @@ where
enable_canvas_antialiasing,
glplayer_threads: state.glplayer_threads,
player_context: state.player_context,
event_loop_waker: state.event_loop_waker,
};

constellation.run();
Expand Down Expand Up @@ -1009,6 +1016,7 @@ where
webvr_chan: self.webvr_chan.clone(),
webxr_registry: self.webxr_registry.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 {
Expand Down
12 changes: 11 additions & 1 deletion components/constellation/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use compositing::CompositionPipeline;
use compositing::CompositorProxy;
use crossbeam_channel::Sender;
use devtools_traits::{DevtoolsControlMsg, ScriptToDevtoolsControlMsg};
use embedder_traits::EventLoopWaker;
use euclid::{Scale, Size2D};
use gfx::font_cache_thread::FontCacheThread;
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
Expand Down Expand Up @@ -195,6 +196,9 @@ pub struct InitialPipelineState {

/// Application window's GL Context for Media player
pub player_context: WindowGLContext,

/// Mechanism to force the compositor to process events.
pub event_loop_waker: Option<Box<dyn EventLoopWaker>>,
}

pub struct NewPipeline {
Expand Down Expand Up @@ -327,7 +331,11 @@ impl Pipeline {
let register = state
.background_monitor_register
.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
};

Expand Down Expand Up @@ -524,6 +532,7 @@ impl UnprivilegedPipelineContent {
self,
wait_for_completion: bool,
background_hang_monitor_register: Box<dyn BackgroundHangMonitorRegister>,
event_loop_waker: Option<Box<dyn EventLoopWaker>>,
) where
LTF: LayoutThreadFactory<Message = Message>,
STF: ScriptThreadFactory<Message = Message>,
Expand Down Expand Up @@ -566,6 +575,7 @@ impl UnprivilegedPipelineContent {
webrender_api_sender: self.webrender_api_sender.clone(),
layout_is_busy: layout_thread_busy_flag.clone(),
player_context: self.player_context.clone(),
event_loop_waker,
},
self.load_data.clone(),
self.opts.profile_script_events,
Expand Down
3 changes: 2 additions & 1 deletion components/script/dom/bindings/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down
8 changes: 4 additions & 4 deletions components/script/dom/vrdisplay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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())
}

Expand Down
108 changes: 101 additions & 7 deletions components/script/dom/webglrenderingcontext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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:
//
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -319,7 +324,7 @@ impl WebGLRenderingContext {
}
}

pub fn webgl_sender(&self) -> WebGLMsgSender {
pub(crate) fn webgl_sender(&self) -> WebGLMessageSender {
self.webgl_sender.clone()
}

Expand Down Expand Up @@ -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()
}
}
Loading

0 comments on commit a2ca3dd

Please sign in to comment.