aboutsummaryrefslogtreecommitdiffstats
path: root/components/canvas
diff options
context:
space:
mode:
Diffstat (limited to 'components/canvas')
-rw-r--r--components/canvas/Cargo.toml2
-rw-r--r--components/canvas/lib.rs3
-rw-r--r--components/canvas/webgl_mode/inprocess.rs11
-rw-r--r--components/canvas/webgl_thread.rs107
4 files changed, 67 insertions, 56 deletions
diff --git a/components/canvas/Cargo.toml b/components/canvas/Cargo.toml
index ffb12a7a4ce..86cd3c4e440 100644
--- a/components/canvas/Cargo.toml
+++ b/components/canvas/Cargo.toml
@@ -42,5 +42,5 @@ webrender_traits = {path = "../webrender_traits"}
webxr-api = {git = "https://github.com/servo/webxr", features = ["ipc"]}
# NOTE: the sm-angle feature only enables angle on windows, not other platforms!
surfman = { version = "0.1", features = ["sm-angle", "sm-osmesa"] }
-surfman-chains = "0.2"
+surfman-chains = "0.3"
surfman-chains-api = "0.2"
diff --git a/components/canvas/lib.rs b/components/canvas/lib.rs
index 1e5872420bc..074a4a00bcb 100644
--- a/components/canvas/lib.rs
+++ b/components/canvas/lib.rs
@@ -12,6 +12,9 @@ extern crate log;
mod raqote_backend;
pub use webgl_mode::WebGLComm;
+pub use webgl_thread::SurfaceProvider;
+pub use webgl_thread::SurfaceProviders;
+pub use webgl_thread::WebGlExecutor;
pub mod canvas_data;
pub mod canvas_paint_thread;
diff --git a/components/canvas/webgl_mode/inprocess.rs b/components/canvas/webgl_mode/inprocess.rs
index d84b27684d5..b46b1608101 100644
--- a/components/canvas/webgl_mode/inprocess.rs
+++ b/components/canvas/webgl_mode/inprocess.rs
@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
-use crate::webgl_thread::{WebGLThread, WebGLThreadInit};
+use crate::webgl_thread::{SurfaceProviders, WebGLThread, WebGLThreadInit, WebGlExecutor};
use canvas_traits::webgl::{webgl_channel, WebVRRenderHandler};
use canvas_traits::webgl::{WebGLContextId, WebGLMsg, WebGLThreads};
use euclid::default::Size2D;
@@ -11,6 +11,7 @@ use gleam;
use servo_config::pref;
use sparkle::gl;
use sparkle::gl::GlType;
+use std::collections::HashMap;
use std::default::Default;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
@@ -27,8 +28,10 @@ use webxr_api::SwapChainId as WebXRSwapChainId;
pub struct WebGLComm {
pub webgl_threads: WebGLThreads,
pub webxr_swap_chains: SwapChains<WebXRSwapChainId>,
+ pub webxr_surface_providers: SurfaceProviders,
pub image_handler: Box<dyn WebrenderExternalImageApi>,
pub output_handler: Option<Box<dyn webrender_api::OutputImageHandler>>,
+ pub webgl_executor: WebGlExecutor,
}
impl WebGLComm {
@@ -46,6 +49,8 @@ impl WebGLComm {
let (sender, receiver) = webgl_channel::<WebGLMsg>().unwrap();
let webrender_swap_chains = SwapChains::new();
let webxr_swap_chains = SwapChains::new();
+ let webxr_surface_providers = Arc::new(Mutex::new(HashMap::new()));
+ let (runnable_sender, runnable_receiver) = crossbeam_channel::unbounded();
// This implementation creates a single `WebGLThread` for all the pipelines.
let init = WebGLThreadInit {
@@ -56,9 +61,11 @@ impl WebGLComm {
receiver,
webrender_swap_chains: webrender_swap_chains.clone(),
webxr_swap_chains: webxr_swap_chains.clone(),
+ webxr_surface_providers: webxr_surface_providers.clone(),
connection: device.connection(),
adapter: device.adapter(),
api_type,
+ runnable_receiver,
};
let output_handler = if pref!(dom.webgl.dom_to_texture.enabled) {
@@ -74,8 +81,10 @@ impl WebGLComm {
WebGLComm {
webgl_threads: WebGLThreads(sender),
webxr_swap_chains,
+ webxr_surface_providers,
image_handler: Box::new(external),
output_handler: output_handler.map(|b| b as Box<_>),
+ webgl_executor: runnable_sender,
}
}
}
diff --git a/components/canvas/webgl_thread.rs b/components/canvas/webgl_thread.rs
index 1658ebf94a5..f72e2c79bc1 100644
--- a/components/canvas/webgl_thread.rs
+++ b/components/canvas/webgl_thread.rs
@@ -54,7 +54,7 @@ use sparkle::gl::GLint;
use sparkle::gl::GLuint;
use sparkle::gl::Gl;
use std::borrow::Cow;
-use std::cell::{Cell, RefCell};
+use std::collections::HashMap;
use std::rc::Rc;
use std::slice;
use std::sync::{Arc, Mutex};
@@ -70,9 +70,10 @@ use surfman::GLVersion;
use surfman::SurfaceAccess;
use surfman::SurfaceInfo;
use surfman::SurfaceType;
-use surfman_chains::SwapChains;
+use surfman_chains::{SurfmanProvider, SwapChains};
use surfman_chains_api::SwapChainsAPI;
use webrender_traits::{WebrenderExternalImageRegistry, WebrenderImageHandlerType};
+use webxr_api::SessionId;
use webxr_api::SwapChainId as WebXRSwapChainId;
#[cfg(feature = "xr-profile")]
@@ -138,25 +139,29 @@ pub(crate) struct WebGLThread {
/// We use it to get an unique ID for new WebGLContexts.
external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
/// The receiver that will be used for processing WebGL messages.
- receiver: WebGLReceiver<WebGLMsg>,
+ receiver: crossbeam_channel::Receiver<WebGLMsg>,
/// The receiver that should be used to send WebGL messages for processing.
sender: WebGLSender<WebGLMsg>,
/// The swap chains used by webrender
webrender_swap_chains: SwapChains<WebGLContextId>,
/// The swap chains used by webxr
webxr_swap_chains: SwapChains<WebXRSwapChainId>,
+ /// The set of all surface providers corresponding to WebXR sessions.
+ webxr_surface_providers: SurfaceProviders,
+ /// A channel to allow arbitrary threads to execute tasks that run in the WebGL thread.
+ runnable_receiver: crossbeam_channel::Receiver<WebGlRunnable>,
/// Whether this context is a GL or GLES context.
api_type: gl::GlType,
}
-#[derive(PartialEq)]
-enum EventLoop {
- Blocking,
- Nonblocking,
-}
+pub type WebGlExecutor = crossbeam_channel::Sender<WebGlRunnable>;
+pub type WebGlRunnable = Box<dyn FnOnce() + Send>;
+pub type SurfaceProviders = Arc<Mutex<HashMap<SessionId, SurfaceProvider>>>;
+pub type SurfaceProvider = Box<dyn surfman_chains::SurfaceProvider + Send>;
/// The data required to initialize an instance of the WebGLThread type.
pub(crate) struct WebGLThreadInit {
+ pub webxr_surface_providers: SurfaceProviders,
pub webrender_api_sender: webrender_api::RenderApiSender,
pub webvr_compositor: Option<Box<dyn WebVRRenderHandler>>,
pub external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
@@ -167,37 +172,7 @@ pub(crate) struct WebGLThreadInit {
pub connection: Connection,
pub adapter: Adapter,
pub api_type: gl::GlType,
-}
-
-/// The extra data required to run an instance of WebGLThread when it is
-/// not running in its own thread.
-pub struct WebGLMainThread {
- pub(crate) thread_data: RefCell<WebGLThread>,
- shut_down: Cell<bool>,
-}
-
-impl WebGLMainThread {
- /// Synchronously process all outstanding WebGL messages.
- pub fn process(&self) {
- if self.shut_down.get() {
- return;
- }
-
- // Any context could be current when we start.
- self.thread_data.borrow_mut().bound_context_id = None;
- let result = self
- .thread_data
- .borrow_mut()
- .process(EventLoop::Nonblocking);
- if !result {
- self.shut_down.set(true);
- WEBGL_MAIN_THREAD.with(|thread_data| thread_data.borrow_mut().take());
- }
- }
-}
-
-thread_local! {
- static WEBGL_MAIN_THREAD: RefCell<Option<Rc<WebGLMainThread>>> = RefCell::new(None);
+ pub runnable_receiver: crossbeam_channel::Receiver<WebGlRunnable>,
}
// A size at which it should be safe to create GL contexts
@@ -214,9 +189,11 @@ impl WebGLThread {
receiver,
webrender_swap_chains,
webxr_swap_chains,
+ webxr_surface_providers,
connection,
adapter,
api_type,
+ runnable_receiver,
}: WebGLThreadInit,
) -> Self {
WebGLThread {
@@ -229,9 +206,11 @@ impl WebGLThread {
dom_outputs: Default::default(),
external_images,
sender,
- receiver,
+ receiver: receiver.into_inner(),
webrender_swap_chains,
webxr_swap_chains,
+ webxr_surface_providers,
+ runnable_receiver,
api_type,
}
}
@@ -243,23 +222,35 @@ impl WebGLThread {
.name("WebGL thread".to_owned())
.spawn(move || {
let mut data = WebGLThread::new(init);
- data.process(EventLoop::Blocking);
+ data.process();
})
.expect("Thread spawning failed");
}
- fn process(&mut self, loop_type: EventLoop) -> bool {
+ fn process(&mut self) {
let webgl_chan = WebGLChan(self.sender.clone());
- while let Ok(msg) = match loop_type {
- EventLoop::Blocking => self.receiver.recv(),
- EventLoop::Nonblocking => self.receiver.try_recv(),
- } {
- let exit = self.handle_msg(msg, &webgl_chan);
- if exit {
- return false;
+ loop {
+ crossbeam_channel::select! {
+ recv(self.receiver) -> msg => {
+ match msg {
+ Ok(msg) => {
+ let exit = self.handle_msg(msg, &webgl_chan);
+ if exit {
+ return;
+ }
+ }
+ _ => break,
+ }
+ }
+ recv(self.runnable_receiver) -> msg => {
+ if let Ok(msg) = msg {
+ msg();
+ } else {
+ self.runnable_receiver = crossbeam_channel::never();
+ }
+ }
}
}
- true
}
/// Handles a generic WebGLMsg message
@@ -331,8 +322,8 @@ impl WebGLThread {
WebGLMsg::WebVRCommand(ctx_id, command) => {
self.handle_webvr_command(ctx_id, command);
},
- WebGLMsg::CreateWebXRSwapChain(ctx_id, size, sender) => {
- let _ = sender.send(self.create_webxr_swap_chain(ctx_id, size));
+ WebGLMsg::CreateWebXRSwapChain(ctx_id, size, sender, id) => {
+ let _ = sender.send(self.create_webxr_swap_chain(ctx_id, size, id));
},
WebGLMsg::SwapBuffers(swap_ids, sender, sent_time) => {
self.handle_swap_buffers(swap_ids, sender, sent_time);
@@ -443,6 +434,7 @@ impl WebGLThread {
size: safe_size.to_i32(),
};
let surface_access = self.surface_access();
+ let surface_provider = Box::new(SurfmanProvider::new(surface_access));
let mut ctx = self
.device
@@ -469,7 +461,7 @@ impl WebGLThread {
);
self.webrender_swap_chains
- .create_attached_swap_chain(id, &mut self.device, &mut ctx, surface_access)
+ .create_attached_swap_chain(id, &mut self.device, &mut ctx, surface_provider)
.expect("Failed to create the swap chain");
let swap_chain = self
@@ -765,6 +757,7 @@ impl WebGLThread {
&mut self,
context_id: WebGLContextId,
size: Size2D<i32>,
+ session_id: SessionId,
) -> Option<WebXRSwapChainId> {
debug!("WebGLThread::create_webxr_swap_chain()");
let id = WebXRSwapChainId::new();
@@ -775,8 +768,14 @@ impl WebGLThread {
&mut self.contexts,
&mut self.bound_context_id,
)?;
+ let surface_provider = self
+ .webxr_surface_providers
+ .lock()
+ .unwrap()
+ .remove(&session_id)
+ .unwrap_or_else(|| Box::new(SurfmanProvider::new(surface_access)));
self.webxr_swap_chains
- .create_detached_swap_chain(id, size, &mut self.device, &mut data.ctx, surface_access)
+ .create_detached_swap_chain(id, size, &mut self.device, &mut data.ctx, surface_provider)
.ok()?;
debug!("Created swap chain {:?}", id);
Some(id)