mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
webxr: create glwindow with Rc window and without rendering context (#34813)
* Create webxr glwindow with Rc window Signed-off-by: Wu Yu Wei <yuweiwu@pm.me> * Remove obselte gurad type Signed-off-by: Wu Yu Wei <yuweiwu@pm.me> * Update GlWindow trait method Signed-off-by: Wu Yuwei <yuweiwu@pm.me> * Update how webxr discorvery is created Now glwindow will create a hidden window. It's better to not use it unless we really want to use this port. Signed-off-by: Wu Yu Wei <yuweiwu@pm.me> * Link back to upstream webxr repo Signed-off-by: Wu Yu Wei <yuweiwu@pm.me> --------- Signed-off-by: Wu Yu Wei <yuweiwu@pm.me> Signed-off-by: Wu Yuwei <yuweiwu@pm.me>
This commit is contained in:
parent
b252f238d1
commit
da2074e5d6
7 changed files with 26 additions and 97 deletions
5
Cargo.lock
generated
5
Cargo.lock
generated
|
@ -8312,13 +8312,14 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webxr"
|
name = "webxr"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
source = "git+https://github.com/servo/webxr#db11d8d3c72b88ae5e3eb59679a0b2f7dd0bce7f"
|
source = "git+https://github.com/servo/webxr#4fd38cf6dd29ac58bafd0be2ef5337827853dcdd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
"euclid",
|
"euclid",
|
||||||
"glow",
|
"glow",
|
||||||
"log",
|
"log",
|
||||||
"openxr",
|
"openxr",
|
||||||
|
"raw-window-handle",
|
||||||
"serde",
|
"serde",
|
||||||
"surfman",
|
"surfman",
|
||||||
"webxr-api",
|
"webxr-api",
|
||||||
|
@ -8329,7 +8330,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webxr-api"
|
name = "webxr-api"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
source = "git+https://github.com/servo/webxr#db11d8d3c72b88ae5e3eb59679a0b2f7dd0bce7f"
|
source = "git+https://github.com/servo/webxr#4fd38cf6dd29ac58bafd0be2ef5337827853dcdd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"euclid",
|
"euclid",
|
||||||
"ipc-channel",
|
"ipc-channel",
|
||||||
|
|
|
@ -404,6 +404,8 @@ mod gen {
|
||||||
test: bool,
|
test: bool,
|
||||||
first_person_observer_view: bool,
|
first_person_observer_view: bool,
|
||||||
glwindow: {
|
glwindow: {
|
||||||
|
/// Enable servo/webxr's glwindow port. This is enabled only if openxr is
|
||||||
|
/// disabled.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
#[serde(rename = "dom.webxr.glwindow.left-right")]
|
#[serde(rename = "dom.webxr.glwindow.left-right")]
|
||||||
|
@ -421,6 +423,7 @@ mod gen {
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
},
|
},
|
||||||
openxr: {
|
openxr: {
|
||||||
|
/// Enable servo/webxr's openxr port
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
},
|
},
|
||||||
sessionavailable: bool,
|
sessionavailable: bool,
|
||||||
|
|
|
@ -30,12 +30,11 @@ use winit::event::WindowEvent;
|
||||||
use winit::event_loop::{ActiveEventLoop, ControlFlow};
|
use winit::event_loop::{ActiveEventLoop, ControlFlow};
|
||||||
use winit::window::WindowId;
|
use winit::window::WindowId;
|
||||||
|
|
||||||
use super::events_loop::{EventLoopGuard, EventsLoop, WakerEvent};
|
use super::events_loop::{EventsLoop, WakerEvent};
|
||||||
use super::minibrowser::Minibrowser;
|
use super::minibrowser::Minibrowser;
|
||||||
use super::webview::WebViewManager;
|
use super::webview::WebViewManager;
|
||||||
use super::{headed_window, headless_window};
|
use super::{headed_window, headless_window};
|
||||||
use crate::desktop::embedder::{EmbedderCallbacks, XrDiscovery};
|
use crate::desktop::embedder::{EmbedderCallbacks, XrDiscovery};
|
||||||
use crate::desktop::events_loop::with_current_event_loop;
|
|
||||||
use crate::desktop::tracing::trace_winit_event;
|
use crate::desktop::tracing::trace_winit_event;
|
||||||
use crate::desktop::window_trait::WindowPortsMethods;
|
use crate::desktop::window_trait::WindowPortsMethods;
|
||||||
use crate::parser::get_default_url;
|
use crate::parser::get_default_url;
|
||||||
|
@ -172,7 +171,7 @@ impl App {
|
||||||
self.event_queue.push(EmbedderEvent::Idle);
|
self.event_queue.push(EmbedderEvent::Idle);
|
||||||
let (_, window) = self.windows.iter().next().unwrap();
|
let (_, window) = self.windows.iter().next().unwrap();
|
||||||
|
|
||||||
let openxr_discovery = if pref!(dom.webxr.openxr.enabled) && !opts::get().headless {
|
let xr_discovery = if pref!(dom.webxr.openxr.enabled) && !opts::get().headless {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let openxr = {
|
let openxr = {
|
||||||
let app_info = AppInfo::new("Servoshell", 0, "Servo", 0);
|
let app_info = AppInfo::new("Servoshell", 0, "Servo", 0);
|
||||||
|
@ -182,28 +181,13 @@ impl App {
|
||||||
let openxr = None;
|
let openxr = None;
|
||||||
|
|
||||||
openxr
|
openxr
|
||||||
|
} else if pref!(dom.webxr.glwindow.enabled) && !opts::get().headless {
|
||||||
|
let window = window.new_glwindow(event_loop.unwrap());
|
||||||
|
Some(XrDiscovery::GlWindow(GlWindowDiscovery::new(window)))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let glwindow_discovery = if pref!(dom.webxr.glwindow.enabled) && !opts::get().headless {
|
|
||||||
let window = window.clone();
|
|
||||||
let factory = Box::new(move || {
|
|
||||||
with_current_event_loop(|w| Ok(window.new_glwindow(w)))
|
|
||||||
.expect("An event loop should always be active in headed mode")
|
|
||||||
});
|
|
||||||
Some(XrDiscovery::GlWindow(GlWindowDiscovery::new(
|
|
||||||
rendering_context.connection(),
|
|
||||||
rendering_context.adapter(),
|
|
||||||
rendering_context.context_attributes(),
|
|
||||||
factory,
|
|
||||||
)))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let xr_discovery = openxr_discovery.or(glwindow_discovery);
|
|
||||||
|
|
||||||
let window = window.clone();
|
let window = window.clone();
|
||||||
// Implements embedder methods, used by libservo and constellation.
|
// Implements embedder methods, used by libservo and constellation.
|
||||||
let embedder = Box::new(EmbedderCallbacks::new(self.waker.clone(), xr_discovery));
|
let embedder = Box::new(EmbedderCallbacks::new(self.waker.clone(), xr_discovery));
|
||||||
|
@ -423,7 +407,6 @@ impl App {
|
||||||
|
|
||||||
impl ApplicationHandler<WakerEvent> for App {
|
impl ApplicationHandler<WakerEvent> for App {
|
||||||
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
||||||
let _guard = EventLoopGuard::new(event_loop);
|
|
||||||
self.init(Some(event_loop));
|
self.init(Some(event_loop));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
//! An event loop implementation that works in headless mode.
|
//! An event loop implementation that works in headless mode.
|
||||||
|
|
||||||
use std::cell::Cell;
|
|
||||||
use std::sync::{Arc, Condvar, Mutex};
|
use std::sync::{Arc, Condvar, Mutex};
|
||||||
use std::time;
|
use std::time;
|
||||||
|
|
||||||
|
@ -12,7 +11,7 @@ use log::warn;
|
||||||
use servo::config::{pref, set_pref};
|
use servo::config::{pref, set_pref};
|
||||||
use servo::embedder_traits::EventLoopWaker;
|
use servo::embedder_traits::EventLoopWaker;
|
||||||
use winit::error::EventLoopError;
|
use winit::error::EventLoopError;
|
||||||
use winit::event_loop::{ActiveEventLoop, EventLoop as WinitEventLoop};
|
use winit::event_loop::EventLoop as WinitEventLoop;
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
use winit::platform::macos::{ActivationPolicy, EventLoopBuilderExtMacOS};
|
use winit::platform::macos::{ActivationPolicy, EventLoopBuilderExtMacOS};
|
||||||
|
|
||||||
|
@ -164,48 +163,3 @@ impl EventLoopWaker for HeadlessEventLoopWaker {
|
||||||
Box::new(HeadlessEventLoopWaker(self.0.clone()))
|
Box::new(HeadlessEventLoopWaker(self.0.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_local! {
|
|
||||||
static CURRENT_EVENT_LOOP: Cell<Option<*const ActiveEventLoop>> = const { Cell::new(None) };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct EventLoopGuard;
|
|
||||||
|
|
||||||
impl EventLoopGuard {
|
|
||||||
pub fn new(event_loop: &ActiveEventLoop) -> Self {
|
|
||||||
CURRENT_EVENT_LOOP.with(|cell| {
|
|
||||||
assert!(
|
|
||||||
cell.get().is_none(),
|
|
||||||
"Attempted to set a new event loop while one is already set"
|
|
||||||
);
|
|
||||||
cell.set(Some(event_loop as *const ActiveEventLoop));
|
|
||||||
});
|
|
||||||
Self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for EventLoopGuard {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
CURRENT_EVENT_LOOP.with(|cell| cell.set(None));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper function to safely use the current event loop
|
|
||||||
#[allow(unsafe_code)]
|
|
||||||
pub fn with_current_event_loop<F, R>(f: F) -> Option<R>
|
|
||||||
where
|
|
||||||
F: FnOnce(&ActiveEventLoop) -> R,
|
|
||||||
{
|
|
||||||
CURRENT_EVENT_LOOP.with(|cell| {
|
|
||||||
cell.get().map(|ptr| {
|
|
||||||
// SAFETY:
|
|
||||||
// 1. The pointer is guaranteed to be valid when it's Some, as the EventLoopGuard that created it
|
|
||||||
// lives at least as long as the reference, and clears it when it's dropped. Only run_forever creates
|
|
||||||
// a new EventLoopGuard, and does not leak it.
|
|
||||||
// 2. Since the pointer was created from a borrow which lives at least as long as this pointer there are
|
|
||||||
// no mutable references to the ActiveEventLoop.
|
|
||||||
let event_loop = unsafe { &*ptr };
|
|
||||||
f(event_loop)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ use std::rc::Rc;
|
||||||
|
|
||||||
use euclid::{Angle, Length, Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vector2D, Vector3D};
|
use euclid::{Angle, Length, Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vector2D, Vector3D};
|
||||||
use log::{debug, info, trace};
|
use log::{debug, info, trace};
|
||||||
use raw_window_handle::HasWindowHandle;
|
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
|
||||||
use servo::compositing::windowing::{
|
use servo::compositing::windowing::{
|
||||||
AnimationState, EmbedderCoordinates, EmbedderEvent, MouseWindowEvent, WindowMethods,
|
AnimationState, EmbedderCoordinates, EmbedderEvent, MouseWindowEvent, WindowMethods,
|
||||||
};
|
};
|
||||||
|
@ -498,13 +498,13 @@ impl WindowPortsMethods for Window {
|
||||||
fn new_glwindow(
|
fn new_glwindow(
|
||||||
&self,
|
&self,
|
||||||
event_loop: &winit::event_loop::ActiveEventLoop,
|
event_loop: &winit::event_loop::ActiveEventLoop,
|
||||||
) -> Box<dyn webxr::glwindow::GlWindow> {
|
) -> Rc<dyn webxr::glwindow::GlWindow> {
|
||||||
let size = self.winit_window.outer_size();
|
let size = self.winit_window.outer_size();
|
||||||
|
|
||||||
let window_attr = winit::window::Window::default_attributes()
|
let window_attr = winit::window::Window::default_attributes()
|
||||||
.with_title("Servo XR".to_string())
|
.with_title("Servo XR".to_string())
|
||||||
.with_inner_size(size)
|
.with_inner_size(size)
|
||||||
.with_visible(true);
|
.with_visible(false);
|
||||||
|
|
||||||
let winit_window = event_loop
|
let winit_window = event_loop
|
||||||
.create_window(window_attr)
|
.create_window(window_attr)
|
||||||
|
@ -515,7 +515,7 @@ impl WindowPortsMethods for Window {
|
||||||
xr_translation: Cell::new(Vector3D::zero()),
|
xr_translation: Cell::new(Vector3D::zero()),
|
||||||
});
|
});
|
||||||
self.xr_window_poses.borrow_mut().push(pose.clone());
|
self.xr_window_poses.borrow_mut().push(pose.clone());
|
||||||
Box::new(XRWindow { winit_window, pose })
|
Rc::new(XRWindow { winit_window, pose })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn winit_window(&self) -> Option<&winit::window::Window> {
|
fn winit_window(&self) -> Option<&winit::window::Window> {
|
||||||
|
@ -602,6 +602,7 @@ impl webxr::glwindow::GlWindow for XRWindow {
|
||||||
device: &mut Device,
|
device: &mut Device,
|
||||||
_context: &mut Context,
|
_context: &mut Context,
|
||||||
) -> webxr::glwindow::GlWindowRenderTarget {
|
) -> webxr::glwindow::GlWindowRenderTarget {
|
||||||
|
self.winit_window.set_visible(true);
|
||||||
let window_handle = self
|
let window_handle = self
|
||||||
.winit_window
|
.winit_window
|
||||||
.window_handle()
|
.window_handle()
|
||||||
|
@ -636,6 +637,10 @@ impl webxr::glwindow::GlWindow for XRWindow {
|
||||||
webxr::glwindow::GlWindowMode::Blit
|
webxr::glwindow::GlWindowMode::Blit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn display_handle(&self) -> raw_window_handle::DisplayHandle {
|
||||||
|
self.winit_window.display_handle().unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl XRWindowPose {
|
impl XRWindowPose {
|
||||||
|
|
|
@ -9,14 +9,13 @@ use std::rc::Rc;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
|
||||||
use euclid::num::Zero;
|
use euclid::num::Zero;
|
||||||
use euclid::{Box2D, Length, Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vector3D};
|
use euclid::{Box2D, Length, Point2D, Scale, Size2D};
|
||||||
use servo::compositing::windowing::{
|
use servo::compositing::windowing::{
|
||||||
AnimationState, EmbedderCoordinates, EmbedderEvent, WindowMethods,
|
AnimationState, EmbedderCoordinates, EmbedderEvent, WindowMethods,
|
||||||
};
|
};
|
||||||
use servo::config::opts;
|
use servo::config::opts;
|
||||||
use servo::servo_geometry::DeviceIndependentPixel;
|
use servo::servo_geometry::DeviceIndependentPixel;
|
||||||
use servo::webrender_api::units::{DeviceIntSize, DevicePixel};
|
use servo::webrender_api::units::{DeviceIntSize, DevicePixel};
|
||||||
use surfman::{Context, Device};
|
|
||||||
|
|
||||||
use crate::desktop::window_trait::WindowPortsMethods;
|
use crate::desktop::window_trait::WindowPortsMethods;
|
||||||
|
|
||||||
|
@ -124,7 +123,7 @@ impl WindowPortsMethods for Window {
|
||||||
fn new_glwindow(
|
fn new_glwindow(
|
||||||
&self,
|
&self,
|
||||||
_events_loop: &winit::event_loop::ActiveEventLoop,
|
_events_loop: &winit::event_loop::ActiveEventLoop,
|
||||||
) -> Box<dyn webxr::glwindow::GlWindow> {
|
) -> Rc<dyn webxr::glwindow::GlWindow> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,21 +157,3 @@ impl WindowMethods for Window {
|
||||||
self.animation_state.set(state);
|
self.animation_state.set(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl webxr::glwindow::GlWindow for Window {
|
|
||||||
fn get_render_target(
|
|
||||||
&self,
|
|
||||||
_device: &mut Device,
|
|
||||||
_context: &mut Context,
|
|
||||||
) -> webxr::glwindow::GlWindowRenderTarget {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_rotation(&self) -> Rotation3D<f32, UnknownUnit, UnknownUnit> {
|
|
||||||
Rotation3D::identity()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_translation(&self) -> Vector3D<f32, UnknownUnit> {
|
|
||||||
Vector3D::zero()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
//! Definition of Window.
|
//! Definition of Window.
|
||||||
//! Implemented by headless and headed windows.
|
//! Implemented by headless and headed windows.
|
||||||
|
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use euclid::{Length, Scale};
|
use euclid::{Length, Scale};
|
||||||
use servo::compositing::windowing::{EmbedderEvent, WindowMethods};
|
use servo::compositing::windowing::{EmbedderEvent, WindowMethods};
|
||||||
use servo::config::opts;
|
use servo::config::opts;
|
||||||
|
@ -41,7 +43,7 @@ pub trait WindowPortsMethods: WindowMethods {
|
||||||
fn new_glwindow(
|
fn new_glwindow(
|
||||||
&self,
|
&self,
|
||||||
event_loop: &winit::event_loop::ActiveEventLoop,
|
event_loop: &winit::event_loop::ActiveEventLoop,
|
||||||
) -> Box<dyn webxr::glwindow::GlWindow>;
|
) -> Rc<dyn webxr::glwindow::GlWindow>;
|
||||||
fn winit_window(&self) -> Option<&winit::window::Window>;
|
fn winit_window(&self) -> Option<&winit::window::Window>;
|
||||||
fn toolbar_height(&self) -> Length<f32, DeviceIndependentPixel>;
|
fn toolbar_height(&self) -> Length<f32, DeviceIndependentPixel>;
|
||||||
fn set_toolbar_height(&self, height: Length<f32, DeviceIndependentPixel>);
|
fn set_toolbar_height(&self, height: Length<f32, DeviceIndependentPixel>);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue