mirror of
https://github.com/servo/servo.git
synced 2025-08-02 20:20:14 +01:00
Auto merge of #25855 - jdm:surface-inversion, r=Manishearth,asajeffrey
Remove GL->d3d blit in HoloLens immersive mode Depends on: * https://github.com/servo/surfman/pull/151 * https://github.com/asajeffrey/surfman-chains/pull/7 * https://github.com/servo/webxr/pull/133 These changes add two extra APIs for embedders to use when registering a WebXR device - one to allow running any closure as a task in the webgl thread, and one to register an arbitrary surface provider for a particular webxr session. When an openxr session is started, it can then obtain the webgl thread's d3d device from that thread's surfman device and ensure that openxr uses it. Surface providers are traits that have their methods invoked by the webgl thread as part of the the normal swapchain operations. This allows the openxr surface provider to return surfaces that wrap the underlying openxr textures, which are valid in the webgl thread and can be used as the target of an opaque framebuffer. --- - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix #25735 - [x] These changes do not require tests because there are no windows immersive mode tests
This commit is contained in:
commit
b4d7ec1c99
17 changed files with 223 additions and 117 deletions
52
Cargo.lock
generated
52
Cargo.lock
generated
|
@ -496,8 +496,8 @@ dependencies = [
|
|||
"raqote",
|
||||
"servo_config",
|
||||
"sparkle",
|
||||
"surfman 0.1.3",
|
||||
"surfman-chains 0.2.1",
|
||||
"surfman 0.1.4",
|
||||
"surfman-chains 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"surfman-chains-api",
|
||||
"time",
|
||||
"webrender",
|
||||
|
@ -742,6 +742,7 @@ dependencies = [
|
|||
name = "compositing"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"canvas",
|
||||
"crossbeam-channel",
|
||||
"embedder_traits",
|
||||
"euclid",
|
||||
|
@ -3184,7 +3185,7 @@ dependencies = [
|
|||
"sparkle",
|
||||
"style",
|
||||
"style_traits",
|
||||
"surfman 0.1.3",
|
||||
"surfman 0.1.4",
|
||||
"webdriver_server",
|
||||
"webgpu",
|
||||
"webrender",
|
||||
|
@ -5046,7 +5047,7 @@ dependencies = [
|
|||
"servo-media",
|
||||
"sparkle",
|
||||
"surfman 0.2.0",
|
||||
"surfman-chains 0.3.0",
|
||||
"surfman-chains 0.3.0 (git+https://github.com/asajeffrey/surfman-chains?branch=multi)",
|
||||
"surfman-chains-api",
|
||||
]
|
||||
|
||||
|
@ -5697,9 +5698,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "surfman"
|
||||
version = "0.1.3"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10248da202c1c8d8798783bbc4ba08e81ff225c6e2a394d64748d2a62acb198c"
|
||||
checksum = "43bf043642ad98aaa51956091c4f829a400bad5f023b5f0095ecda61f925c63d"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cgl 0.3.2",
|
||||
|
@ -5726,7 +5727,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "surfman"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/pcwalton/surfman?branch=multi#808e5c5906dbcc6707536c8bac8bcc9389b4e1eb"
|
||||
source = "git+https://github.com/pcwalton/surfman?branch=multi#fb782262617e7ca839a4e487b116a5199afaf963"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cgl 0.3.2",
|
||||
|
@ -5750,20 +5751,6 @@ dependencies = [
|
|||
"x11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "surfman-chains"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2c1b5976b229a807a9e79b3b5248da577948b9882c77f2afce27cf562f80e22"
|
||||
dependencies = [
|
||||
"euclid",
|
||||
"fnv",
|
||||
"log",
|
||||
"sparkle",
|
||||
"surfman 0.1.3",
|
||||
"surfman-chains-api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "surfman-chains"
|
||||
version = "0.3.0"
|
||||
|
@ -5777,6 +5764,20 @@ dependencies = [
|
|||
"surfman-chains-api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "surfman-chains"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2a679f5be9644bbf93662f3b1a704cc6b81c147d4b7d6d5c8d8b6f453176f01"
|
||||
dependencies = [
|
||||
"euclid",
|
||||
"fnv",
|
||||
"log",
|
||||
"sparkle",
|
||||
"surfman 0.1.4",
|
||||
"surfman-chains-api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "surfman-chains-api"
|
||||
version = "0.2.0"
|
||||
|
@ -6649,9 +6650,10 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "webxr"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/servo/webxr#a1afba096c9797c3663727de58f54eae898f3050"
|
||||
source = "git+https://github.com/servo/webxr#3ac3e83f37ff64c74c847a610a8cefba9b907a9c"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"crossbeam-channel",
|
||||
"euclid",
|
||||
"gl_generator 0.13.1",
|
||||
"gleam 0.9.2",
|
||||
|
@ -6659,8 +6661,8 @@ dependencies = [
|
|||
"log",
|
||||
"openxr",
|
||||
"serde",
|
||||
"surfman 0.1.3",
|
||||
"surfman-chains 0.2.1",
|
||||
"surfman 0.1.4",
|
||||
"surfman-chains 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time",
|
||||
"webxr-api",
|
||||
"winapi",
|
||||
|
@ -6670,7 +6672,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "webxr-api"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/servo/webxr#a1afba096c9797c3663727de58f54eae898f3050"
|
||||
source = "git+https://github.com/servo/webxr#3ac3e83f37ff64c74c847a610a8cefba9b907a9c"
|
||||
dependencies = [
|
||||
"euclid",
|
||||
"ipc-channel",
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -14,6 +14,7 @@ use std::num::{NonZeroU32, NonZeroU64};
|
|||
use std::ops::Deref;
|
||||
use webrender_api::{DocumentId, ImageKey, PipelineId};
|
||||
use webvr_traits::WebVRPoseInformation;
|
||||
use webxr_api::SessionId;
|
||||
use webxr_api::SwapChainId as WebXRSwapChainId;
|
||||
|
||||
/// Helper function that creates a WebGL channel (WebGLSender, WebGLReceiver) to be used in WebGLCommands.
|
||||
|
@ -80,6 +81,7 @@ pub enum WebGLMsg {
|
|||
WebGLContextId,
|
||||
Size2D<i32>,
|
||||
WebGLSender<Option<WebXRSwapChainId>>,
|
||||
SessionId,
|
||||
),
|
||||
/// Performs a buffer swap.
|
||||
///
|
||||
|
@ -188,9 +190,14 @@ impl WebGLMsgSender {
|
|||
&self,
|
||||
size: Size2D<i32>,
|
||||
sender: WebGLSender<Option<WebXRSwapChainId>>,
|
||||
id: SessionId,
|
||||
) -> WebGLSendResult {
|
||||
self.sender
|
||||
.send(WebGLMsg::CreateWebXRSwapChain(self.ctx_id, size, sender))
|
||||
self.sender.send(WebGLMsg::CreateWebXRSwapChain(
|
||||
self.ctx_id,
|
||||
size,
|
||||
sender,
|
||||
id,
|
||||
))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -9,6 +9,7 @@ mod mpsc;
|
|||
|
||||
use crate::webgl::WebGLMsg;
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use ipc_channel::router::ROUTER;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use servo_config::opts;
|
||||
use std::fmt;
|
||||
|
@ -78,6 +79,18 @@ where
|
|||
WebGLReceiver::Mpsc(ref receiver) => receiver.try_recv().map_err(|_| ()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_inner(self) -> crossbeam_channel::Receiver<T>
|
||||
where
|
||||
T: Send + 'static,
|
||||
{
|
||||
match self {
|
||||
WebGLReceiver::Ipc(receiver) => {
|
||||
ROUTER.route_ipc_receiver_to_new_crossbeam_receiver(receiver)
|
||||
},
|
||||
WebGLReceiver::Mpsc(receiver) => receiver.into_inner(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn webgl_channel<T>() -> Result<(WebGLSender<T>, WebGLReceiver<T>), ()>
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{Deserializer, Serializer};
|
||||
use std::sync::mpsc;
|
||||
|
||||
#[macro_use]
|
||||
macro_rules! unreachable_serializable {
|
||||
|
@ -26,8 +25,8 @@ macro_rules! unreachable_serializable {
|
|||
};
|
||||
}
|
||||
|
||||
pub struct WebGLSender<T>(mpsc::Sender<T>);
|
||||
pub struct WebGLReceiver<T>(mpsc::Receiver<T>);
|
||||
pub struct WebGLSender<T>(crossbeam_channel::Sender<T>);
|
||||
pub struct WebGLReceiver<T>(crossbeam_channel::Receiver<T>);
|
||||
|
||||
impl<T> Clone for WebGLSender<T> {
|
||||
fn clone(&self) -> Self {
|
||||
|
@ -37,24 +36,27 @@ impl<T> Clone for WebGLSender<T> {
|
|||
|
||||
impl<T> WebGLSender<T> {
|
||||
#[inline]
|
||||
pub fn send(&self, data: T) -> Result<(), mpsc::SendError<T>> {
|
||||
pub fn send(&self, data: T) -> Result<(), crossbeam_channel::SendError<T>> {
|
||||
self.0.send(data)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> WebGLReceiver<T> {
|
||||
#[inline]
|
||||
pub fn recv(&self) -> Result<T, mpsc::RecvError> {
|
||||
pub fn recv(&self) -> Result<T, crossbeam_channel::RecvError> {
|
||||
self.0.recv()
|
||||
}
|
||||
#[inline]
|
||||
pub fn try_recv(&self) -> Result<T, mpsc::TryRecvError> {
|
||||
pub fn try_recv(&self) -> Result<T, crossbeam_channel::TryRecvError> {
|
||||
self.0.try_recv()
|
||||
}
|
||||
pub fn into_inner(self) -> crossbeam_channel::Receiver<T> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn webgl_channel<T>() -> Result<(WebGLSender<T>, WebGLReceiver<T>), ()> {
|
||||
let (sender, receiver) = mpsc::channel();
|
||||
let (sender, receiver) = crossbeam_channel::unbounded();
|
||||
Ok((WebGLSender(sender), WebGLReceiver(receiver)))
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ default = []
|
|||
gl = ["gleam", "pixels"]
|
||||
|
||||
[dependencies]
|
||||
canvas = { path = "../canvas" }
|
||||
crossbeam-channel = "0.4"
|
||||
embedder_traits = {path = "../embedder_traits"}
|
||||
euclid = "0.20"
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
//! Abstract windowing methods. The concrete implementations of these can be found in `platform/`.
|
||||
|
||||
use canvas::{SurfaceProviders, WebGlExecutor};
|
||||
use embedder_traits::EventLoopWaker;
|
||||
use euclid::Scale;
|
||||
#[cfg(feature = "gl")]
|
||||
|
@ -184,7 +185,13 @@ pub trait EmbedderMethods {
|
|||
}
|
||||
|
||||
/// Register services with a WebXR Registry.
|
||||
fn register_webxr(&mut self, _: &mut webxr::MainThreadRegistry) {}
|
||||
fn register_webxr(
|
||||
&mut self,
|
||||
_: &mut webxr::MainThreadRegistry,
|
||||
_: WebGlExecutor,
|
||||
_: SurfaceProviders,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
|
|
@ -142,9 +142,11 @@ impl WebGLFramebuffer {
|
|||
size: Size2D<i32, Viewport>,
|
||||
) -> Option<(WebXRSwapChainId, DomRoot<Self>)> {
|
||||
let (sender, receiver) = webgl_channel().unwrap();
|
||||
let _ = context
|
||||
.webgl_sender()
|
||||
.send_create_webxr_swap_chain(size.to_untyped(), sender);
|
||||
let _ = context.webgl_sender().send_create_webxr_swap_chain(
|
||||
size.to_untyped(),
|
||||
sender,
|
||||
session.session_id(),
|
||||
);
|
||||
let swap_chain_id = receiver.recv().unwrap()?;
|
||||
let framebuffer_id =
|
||||
WebGLFramebufferId::Opaque(WebGLOpaqueFramebufferId::WebXR(swap_chain_id));
|
||||
|
|
|
@ -81,6 +81,7 @@ use std::cell::Cell;
|
|||
use std::cmp;
|
||||
use std::ptr::{self, NonNull};
|
||||
use std::rc::Rc;
|
||||
use webxr_api::SessionId;
|
||||
use webxr_api::SwapChainId as WebXRSwapChainId;
|
||||
|
||||
// From the GLES 2.0.25 spec, page 85:
|
||||
|
@ -4576,8 +4577,9 @@ impl WebGLMessageSender {
|
|||
&self,
|
||||
size: Size2D<i32>,
|
||||
sender: WebGLSender<Option<WebXRSwapChainId>>,
|
||||
id: SessionId,
|
||||
) -> WebGLSendResult {
|
||||
self.wake_after_send(|| self.sender.send_create_webxr_swap_chain(size, sender))
|
||||
self.wake_after_send(|| self.sender.send_create_webxr_swap_chain(size, sender, id))
|
||||
}
|
||||
|
||||
pub fn send_resize(
|
||||
|
|
|
@ -51,7 +51,7 @@ use std::mem;
|
|||
use std::rc::Rc;
|
||||
use webxr_api::{
|
||||
self, util, Display, EnvironmentBlendMode, Event as XREvent, Frame, SelectEvent, SelectKind,
|
||||
Session, View, Viewer, Visibility,
|
||||
Session, SessionId, View, Viewer, Visibility,
|
||||
};
|
||||
|
||||
#[dom_struct]
|
||||
|
@ -462,6 +462,10 @@ impl XRSession {
|
|||
viewport: Rect::from_size(size.to_i32()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn session_id(&self) -> SessionId {
|
||||
self.session.borrow().id()
|
||||
}
|
||||
}
|
||||
|
||||
impl XRSessionMethods for XRSession {
|
||||
|
|
|
@ -65,7 +65,7 @@ fn webdriver(_port: u16, _constellation: Sender<ConstellationMsg>) {}
|
|||
|
||||
use bluetooth::BluetoothThreadFactory;
|
||||
use bluetooth_traits::BluetoothRequest;
|
||||
use canvas::WebGLComm;
|
||||
use canvas::{SurfaceProviders, WebGLComm, WebGlExecutor};
|
||||
use canvas_traits::webgl::WebGLThreads;
|
||||
use compositing::compositor_thread::{
|
||||
CompositorProxy, CompositorReceiver, InitialCompositorState, Msg,
|
||||
|
@ -432,14 +432,6 @@ where
|
|||
panic!("We don't currently support running both WebVR and WebXR");
|
||||
}
|
||||
|
||||
// For the moment, we enable use both the webxr crate and the rust-webvr crate,
|
||||
// but we are migrating over to just using webxr.
|
||||
let mut webxr_main_thread = webxr::MainThreadRegistry::new(event_loop_waker)
|
||||
.expect("Failed to create WebXR device registry");
|
||||
if pref!(dom.webxr.enabled) {
|
||||
embedder.register_webxr(&mut webxr_main_thread);
|
||||
}
|
||||
|
||||
let mut webvr_heartbeats = Vec::new();
|
||||
let webvr_services = if pref!(dom.webvr.enabled) {
|
||||
let mut services = VRServiceManager::new();
|
||||
|
@ -468,7 +460,12 @@ where
|
|||
let (external_image_handlers, external_images) = WebrenderExternalImageHandlers::new();
|
||||
let mut external_image_handlers = Box::new(external_image_handlers);
|
||||
|
||||
let webgl_threads = create_webgl_threads(
|
||||
// For the moment, we enable use both the webxr crate and the rust-webvr crate,
|
||||
// but we are migrating over to just using webxr.
|
||||
let mut webxr_main_thread = webxr::MainThreadRegistry::new(event_loop_waker)
|
||||
.expect("Failed to create WebXR device registry");
|
||||
|
||||
let (webgl_threads, webgl_extras) = create_webgl_threads(
|
||||
&*window,
|
||||
&mut webrender,
|
||||
webrender_api_sender.clone(),
|
||||
|
@ -478,6 +475,16 @@ where
|
|||
external_images.clone(),
|
||||
);
|
||||
|
||||
if pref!(dom.webxr.enabled) {
|
||||
if let Some((webxr_surface_providers, webgl_executor)) = webgl_extras {
|
||||
embedder.register_webxr(
|
||||
&mut webxr_main_thread,
|
||||
webgl_executor,
|
||||
webxr_surface_providers,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let glplayer_threads = match window.get_gl_context() {
|
||||
GlContext::Unknown => None,
|
||||
_ => {
|
||||
|
@ -1060,7 +1067,10 @@ fn create_webgl_threads<W>(
|
|||
webxr_main_thread: &mut webxr::MainThreadRegistry,
|
||||
external_image_handlers: &mut WebrenderExternalImageHandlers,
|
||||
external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
|
||||
) -> Option<WebGLThreads>
|
||||
) -> (
|
||||
Option<WebGLThreads>,
|
||||
Option<(SurfaceProviders, WebGlExecutor)>,
|
||||
)
|
||||
where
|
||||
W: WindowMethods + 'static + ?Sized,
|
||||
{
|
||||
|
@ -1074,7 +1084,7 @@ where
|
|||
Ok(a) => a,
|
||||
Err(e) => {
|
||||
warn!("Failed to create software graphics context: {:?}", e);
|
||||
return None;
|
||||
return (None, None);
|
||||
},
|
||||
};
|
||||
(Device::Software(device), Context::Software(context))
|
||||
|
@ -1083,7 +1093,7 @@ where
|
|||
Ok(a) => a,
|
||||
Err(e) => {
|
||||
warn!("Failed to create hardware graphics context: {:?}", e);
|
||||
return None;
|
||||
return (None, None);
|
||||
},
|
||||
};
|
||||
(Device::Hardware(device), Context::Hardware(context))
|
||||
|
@ -1094,7 +1104,7 @@ where
|
|||
Ok(a) => a,
|
||||
Err(e) => {
|
||||
warn!("Failed to create graphics context: {:?}", e);
|
||||
return None;
|
||||
return (None, None);
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -1106,8 +1116,10 @@ where
|
|||
let WebGLComm {
|
||||
webgl_threads,
|
||||
webxr_swap_chains,
|
||||
webxr_surface_providers,
|
||||
image_handler,
|
||||
output_handler,
|
||||
webgl_executor,
|
||||
} = WebGLComm::new(
|
||||
device,
|
||||
context,
|
||||
|
@ -1129,5 +1141,8 @@ where
|
|||
webrender.set_output_image_handler(output_handler);
|
||||
}
|
||||
|
||||
Some(webgl_threads)
|
||||
(
|
||||
Some(webgl_threads),
|
||||
Some((webxr_surface_providers, webgl_executor)),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ use glutin;
|
|||
use glutin::dpi::LogicalSize;
|
||||
use glutin::EventsLoopClosed;
|
||||
use rust_webvr::GlWindowVRService;
|
||||
use servo::canvas::{SurfaceProviders, WebGlExecutor};
|
||||
use servo::compositing::windowing::EmbedderMethods;
|
||||
use servo::embedder_traits::EventLoopWaker;
|
||||
use servo::servo_config::{opts, pref};
|
||||
|
@ -89,7 +90,12 @@ impl EmbedderMethods for EmbedderCallbacks {
|
|||
}
|
||||
}
|
||||
|
||||
fn register_webxr(&mut self, xr: &mut webxr::MainThreadRegistry) {
|
||||
fn register_webxr(
|
||||
&mut self,
|
||||
xr: &mut webxr::MainThreadRegistry,
|
||||
_executor: WebGlExecutor,
|
||||
_surface_provider_registration: SurfaceProviders
|
||||
) {
|
||||
if pref!(dom.webxr.test) {
|
||||
xr.register_mock(webxr::headless::HeadlessMockDiscovery::new());
|
||||
} else if !opts::get().headless && pref!(dom.webxr.glwindow) {
|
||||
|
|
|
@ -13,6 +13,7 @@ pub use servo::embedder_traits::{
|
|||
pub use servo::script_traits::{MediaSessionActionType, MouseButton};
|
||||
|
||||
use getopts::Options;
|
||||
use servo::canvas::{SurfaceProviders, WebGlExecutor};
|
||||
use servo::compositing::windowing::{
|
||||
AnimationState, EmbedderCoordinates, EmbedderMethods, MouseWindowEvent, WindowEvent,
|
||||
WindowMethods,
|
||||
|
@ -723,19 +724,52 @@ impl EmbedderMethods for ServoEmbedderCallbacks {
|
|||
}
|
||||
|
||||
#[cfg(feature = "uwp")]
|
||||
fn register_webxr(&mut self, registry: &mut webxr::MainThreadRegistry) {
|
||||
fn register_webxr(
|
||||
&mut self,
|
||||
registry: &mut webxr::MainThreadRegistry,
|
||||
executor: WebGlExecutor,
|
||||
surface_providers: SurfaceProviders,
|
||||
) {
|
||||
debug!("EmbedderMethods::register_xr");
|
||||
assert!(
|
||||
self.xr_discovery.is_none(),
|
||||
"UWP builds should not be initialized with a WebXR Discovery object"
|
||||
);
|
||||
let gl = self.gl.clone();
|
||||
let discovery = webxr::openxr::OpenXrDiscovery::new(gl);
|
||||
|
||||
struct ProviderRegistration(SurfaceProviders);
|
||||
impl webxr::openxr::SurfaceProviderRegistration for ProviderRegistration {
|
||||
fn register(&self, id: webxr_api::SessionId, provider: servo::canvas::SurfaceProvider) {
|
||||
self.0.lock().unwrap().insert(id, provider);
|
||||
}
|
||||
fn clone(&self) -> Box<dyn webxr::openxr::SurfaceProviderRegistration> {
|
||||
Box::new(ProviderRegistration(self.0.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
struct GlThread(WebGlExecutor);
|
||||
impl webxr::openxr::GlThread for GlThread {
|
||||
fn execute(&self, runnable: Box<dyn FnOnce() + Send>) {
|
||||
let _ = self.0.send(runnable);
|
||||
}
|
||||
fn clone(&self) -> Box<dyn webxr::openxr::GlThread> {
|
||||
Box::new(GlThread(self.0.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
let discovery = webxr::openxr::OpenXrDiscovery::new(
|
||||
Box::new(GlThread(executor)),
|
||||
Box::new(ProviderRegistration(surface_providers)),
|
||||
);
|
||||
registry.register(discovery);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "uwp"))]
|
||||
fn register_webxr(&mut self, registry: &mut webxr::MainThreadRegistry) {
|
||||
fn register_webxr(
|
||||
&mut self,
|
||||
registry: &mut webxr::MainThreadRegistry,
|
||||
_executor: WebGlExecutor,
|
||||
_surface_provider_registration: SurfaceProviders,
|
||||
) {
|
||||
debug!("EmbedderMethods::register_xr");
|
||||
if let Some(discovery) = self.xr_discovery.take() {
|
||||
registry.register(discovery);
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
[incompatible-texture-type-for-sampler.html]
|
||||
expected: CRASH
|
||||
expected: TIMEOUT
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue