mirror of
https://github.com/servo/servo.git
synced 2025-08-01 19:50:30 +01:00
Get the glwindow test XR device to share a GL context with WebGL
This commit is contained in:
parent
bd730e7c16
commit
b19e7d1cbf
7 changed files with 113 additions and 27 deletions
5
Cargo.lock
generated
5
Cargo.lock
generated
|
@ -5504,18 +5504,19 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "webxr"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/servo/webxr#3951634a06e2f9417f04e8ada969589f5b8a01d2"
|
||||
source = "git+https://github.com/servo/webxr#abc779798259d287539347a5d2048ae745f1f2ac"
|
||||
dependencies = [
|
||||
"euclid 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glutin 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webxr-api 0.0.1 (git+https://github.com/servo/webxr)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webxr-api"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/servo/webxr#3951634a06e2f9417f04e8ada969589f5b8a01d2"
|
||||
source = "git+https://github.com/servo/webxr#abc779798259d287539347a5d2048ae745f1f2ac"
|
||||
dependencies = [
|
||||
"euclid 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
@ -36,11 +36,12 @@ impl App {
|
|||
let window = if opts::get().headless {
|
||||
headless_window::Window::new(opts::get().initial_window_size)
|
||||
} else {
|
||||
headed_window::Window::new(opts::get().initial_window_size, events_loop.borrow().as_winit())
|
||||
Rc::new(headed_window::Window::new(opts::get().initial_window_size, None, events_loop.clone()))
|
||||
};
|
||||
|
||||
// Implements embedder methods, used by libservo and constellation.
|
||||
let embedder = Box::new(EmbedderCallbacks::new(
|
||||
window.clone(),
|
||||
events_loop.clone(),
|
||||
window.gl(),
|
||||
));
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use glutin::os::ContextTraitExt;
|
||||
use glutin::{NotCurrent, PossiblyCurrent, WindowedContext};
|
||||
use glutin::{ContextBuilder, CreationError, EventsLoop, NotCurrent, PossiblyCurrent, WindowedContext, WindowBuilder};
|
||||
use servo_media::player::context::GlContext as RawContext;
|
||||
use std::os::raw;
|
||||
|
||||
|
@ -136,6 +136,28 @@ impl GlContext {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn new_window<T>(
|
||||
&self,
|
||||
cb: ContextBuilder<T>,
|
||||
wb: WindowBuilder,
|
||||
el: &EventsLoop
|
||||
) -> Result<WindowedContext<NotCurrent>, CreationError>
|
||||
where
|
||||
T: glutin::ContextCurrentState,
|
||||
{
|
||||
match self {
|
||||
GlContext::Current(ref c) => {
|
||||
cb.with_shared_lists(c).build_windowed(wb, el)
|
||||
},
|
||||
GlContext::NotCurrent(ref c) => {
|
||||
cb.with_shared_lists(c).build_windowed(wb, el)
|
||||
},
|
||||
GlContext::None => {
|
||||
cb.build_windowed(wb, el)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn egl_display(&self) -> Option<*const raw::c_void> {
|
||||
match self {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
use crate::app;
|
||||
use crate::events_loop::EventsLoop;
|
||||
use crate::window_trait::WindowPortsMethods;
|
||||
use gleam::gl;
|
||||
use glutin;
|
||||
use glutin::EventsLoopClosed;
|
||||
|
@ -20,13 +21,18 @@ use std::cell::RefCell;
|
|||
use std::rc::Rc;
|
||||
|
||||
pub struct EmbedderCallbacks {
|
||||
window: Rc<dyn WindowPortsMethods>,
|
||||
events_loop: Rc<RefCell<EventsLoop>>,
|
||||
gl: Rc<dyn gl::Gl>,
|
||||
}
|
||||
|
||||
impl EmbedderCallbacks {
|
||||
pub fn new(events_loop: Rc<RefCell<EventsLoop>>, gl: Rc<dyn gl::Gl>) -> EmbedderCallbacks {
|
||||
EmbedderCallbacks { events_loop, gl }
|
||||
pub fn new(
|
||||
window: Rc<dyn WindowPortsMethods>,
|
||||
events_loop: Rc<RefCell<EventsLoop>>,
|
||||
gl: Rc<dyn gl::Gl>
|
||||
) -> EmbedderCallbacks {
|
||||
EmbedderCallbacks { window, events_loop, gl }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,12 +85,9 @@ impl EmbedderMethods for EmbedderCallbacks {
|
|||
} else if !opts::get().headless && pref!(dom.webxr.glwindow) {
|
||||
warn!("Creating test XR device");
|
||||
let gl = self.gl.clone();
|
||||
let events_loop_clone = self.events_loop.clone();
|
||||
let events_loop_factory = Box::new(move || {
|
||||
events_loop_clone.borrow_mut().take().ok_or(EventsLoopClosed)
|
||||
});
|
||||
let gl_version = app::gl_version();
|
||||
let discovery = webxr::glwindow::GlWindowDiscovery::new(gl, events_loop_factory, gl_version);
|
||||
let window = self.window.clone();
|
||||
let factory = Box::new(move || window.new_window());
|
||||
let discovery = webxr::glwindow::GlWindowDiscovery::new(gl, factory);
|
||||
xr.register(discovery);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,9 +6,10 @@
|
|||
|
||||
use crate::app;
|
||||
use crate::context::GlContext;
|
||||
use crate::events_loop::EventsLoop;
|
||||
use crate::keyutils::keyboard_event_from_winit;
|
||||
use crate::window_trait::{WindowPortsMethods, LINE_HEIGHT};
|
||||
use euclid::{TypedPoint2D, TypedScale, TypedSize2D, TypedVector2D};
|
||||
use euclid::{Size2D, TypedPoint2D, TypedScale, TypedSize2D, TypedVector2D};
|
||||
use gleam::gl;
|
||||
use glutin::dpi::{LogicalPosition, LogicalSize, PhysicalSize};
|
||||
#[cfg(target_os = "macos")]
|
||||
|
@ -55,6 +56,7 @@ fn builder_with_platform_options(builder: glutin::WindowBuilder) -> glutin::Wind
|
|||
|
||||
pub struct Window {
|
||||
gl_context: RefCell<GlContext>,
|
||||
events_loop: Rc<RefCell<EventsLoop>>,
|
||||
screen_size: TypedSize2D<u32, DeviceIndependentPixel>,
|
||||
inner_size: Cell<TypedSize2D<u32, DeviceIndependentPixel>>,
|
||||
mouse_down_button: Cell<Option<glutin::MouseButton>>,
|
||||
|
@ -83,8 +85,9 @@ fn window_creation_scale_factor() -> TypedScale<f32, DeviceIndependentPixel, Dev
|
|||
impl Window {
|
||||
pub fn new(
|
||||
win_size: TypedSize2D<u32, DeviceIndependentPixel>,
|
||||
events_loop: &glutin::EventsLoop,
|
||||
) -> Rc<dyn WindowPortsMethods> {
|
||||
sharing: Option<&GlContext>,
|
||||
events_loop: Rc<RefCell<EventsLoop>>,
|
||||
) -> Window {
|
||||
let opts = opts::get();
|
||||
|
||||
// If there's no chrome, start off with the window invisible. It will be set to visible in
|
||||
|
@ -115,9 +118,10 @@ impl Window {
|
|||
context_builder = context_builder.with_multisampling(MULTISAMPLES)
|
||||
}
|
||||
|
||||
let context = context_builder
|
||||
.build_windowed(window_builder, &events_loop)
|
||||
.expect("Failed to create window.");
|
||||
let context = match sharing {
|
||||
Some(sharing) => sharing.new_window(context_builder, window_builder, events_loop.borrow().as_winit()),
|
||||
None => context_builder.build_windowed(window_builder, events_loop.borrow().as_winit()),
|
||||
}.expect("Failed to create window.");
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
{
|
||||
|
@ -129,7 +133,7 @@ impl Window {
|
|||
context.make_current().expect("Couldn't make window current")
|
||||
};
|
||||
|
||||
let primary_monitor = events_loop.get_primary_monitor();
|
||||
let primary_monitor = events_loop.borrow().as_winit().get_primary_monitor();
|
||||
|
||||
let PhysicalSize {
|
||||
width: screen_width,
|
||||
|
@ -165,6 +169,7 @@ impl Window {
|
|||
|
||||
let window = Window {
|
||||
gl_context: RefCell::new(context),
|
||||
events_loop,
|
||||
event_queue: RefCell::new(vec![]),
|
||||
mouse_down_button: Cell::new(None),
|
||||
mouse_down_point: Cell::new(TypedPoint2D::new(0, 0)),
|
||||
|
@ -180,7 +185,7 @@ impl Window {
|
|||
|
||||
window.present();
|
||||
|
||||
Rc::new(window)
|
||||
window
|
||||
}
|
||||
|
||||
fn handle_received_character(&self, mut ch: char) {
|
||||
|
@ -467,6 +472,37 @@ impl WindowPortsMethods for Window {
|
|||
}
|
||||
}
|
||||
|
||||
impl webxr::glwindow::GlWindow for Window {
|
||||
fn make_current(&mut self) {
|
||||
self.gl_context.get_mut().make_current();
|
||||
}
|
||||
|
||||
fn swap_buffers(&mut self) {
|
||||
self.gl_context.get_mut().swap_buffers();
|
||||
self.gl_context.get_mut().make_not_current();
|
||||
}
|
||||
|
||||
fn size(&self) -> Size2D<gl::GLsizei> {
|
||||
let dpr = self.device_hidpi_factor().get() as f64;
|
||||
let LogicalSize { width, height } = self
|
||||
.gl_context
|
||||
.borrow()
|
||||
.window()
|
||||
.get_inner_size()
|
||||
.expect("Failed to get window inner size.");
|
||||
Size2D::new(width * dpr, height *dpr).to_i32()
|
||||
}
|
||||
|
||||
fn new_window(&self) -> Result<Box<dyn webxr::glwindow::GlWindow>, ()> {
|
||||
let gl_context = self.gl_context.borrow();
|
||||
Ok(Box::new(Window::new(
|
||||
self.inner_size.get(),
|
||||
Some(&*gl_context),
|
||||
self.events_loop.clone(),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
impl WindowMethods for Window {
|
||||
fn gl(&self) -> Rc<dyn gl::Gl> {
|
||||
self.gl.clone()
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
use crate::window_trait::WindowPortsMethods;
|
||||
use glutin;
|
||||
use euclid::{TypedPoint2D, TypedScale, TypedSize2D};
|
||||
use euclid::{Size2D, TypedPoint2D, TypedScale, TypedSize2D};
|
||||
use gleam::gl;
|
||||
use servo::compositing::windowing::{AnimationState, WindowEvent};
|
||||
use servo::compositing::windowing::{EmbedderCoordinates, WindowMethods};
|
||||
|
@ -40,7 +40,7 @@ struct HeadlessContext {
|
|||
|
||||
impl HeadlessContext {
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
fn new(width: u32, height: u32) -> HeadlessContext {
|
||||
fn new(width: u32, height: u32, share: Option<&HeadlessContext>) -> HeadlessContext {
|
||||
let mut attribs = Vec::new();
|
||||
|
||||
attribs.push(osmesa_sys::OSMESA_PROFILE);
|
||||
|
@ -51,8 +51,9 @@ impl HeadlessContext {
|
|||
attribs.push(3);
|
||||
attribs.push(0);
|
||||
|
||||
let context =
|
||||
unsafe { osmesa_sys::OSMesaCreateContextAttribs(attribs.as_ptr(), ptr::null_mut()) };
|
||||
let share = share.map_or(ptr::null_mut(), |share| share._context as *mut _);
|
||||
|
||||
let context = unsafe { osmesa_sys::OSMesaCreateContextAttribs(attribs.as_ptr(), share) };
|
||||
|
||||
assert!(!context.is_null());
|
||||
|
||||
|
@ -78,7 +79,7 @@ impl HeadlessContext {
|
|||
}
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
|
||||
fn new(width: u32, height: u32) -> HeadlessContext {
|
||||
fn new(width: u32, height: u32, _share: Option<&HeadlessContext>) -> HeadlessContext {
|
||||
HeadlessContext {
|
||||
width: width,
|
||||
height: height,
|
||||
|
@ -106,7 +107,7 @@ pub struct Window {
|
|||
|
||||
impl Window {
|
||||
pub fn new(size: TypedSize2D<u32, DeviceIndependentPixel>) -> Rc<dyn WindowPortsMethods> {
|
||||
let context = HeadlessContext::new(size.width, size.height);
|
||||
let context = HeadlessContext::new(size.width, size.height, None);
|
||||
let gl = unsafe { gl::GlFns::load_with(|s| HeadlessContext::get_proc_address(s)) };
|
||||
|
||||
// Print some information about the headless renderer that
|
||||
|
@ -209,3 +210,25 @@ impl WindowMethods for Window {
|
|||
MediaPlayerCtxt::GlApi::None
|
||||
}
|
||||
}
|
||||
|
||||
impl webxr::glwindow::GlWindow for Window {
|
||||
fn make_current(&mut self) {}
|
||||
fn swap_buffers(&mut self) {}
|
||||
fn size(&self) -> Size2D<gl::GLsizei> {
|
||||
let dpr = self.servo_hidpi_factor().get();
|
||||
Size2D::new((self.context.width as f32 * dpr) as gl::GLsizei, (self.context.height as f32 * dpr) as gl::GLsizei)
|
||||
}
|
||||
fn new_window(&self) -> Result<Box<dyn webxr::glwindow::GlWindow>, ()> {
|
||||
let width = self.context.width;
|
||||
let height = self.context.height;
|
||||
let share = Some(&self.context);
|
||||
let context = HeadlessContext::new(width, height, share);
|
||||
let gl = self.gl.clone();
|
||||
Ok(Box::new(Window {
|
||||
context,
|
||||
gl,
|
||||
animation_state: Cell::new(AnimationState::Idle),
|
||||
fullscreen: Cell::new(false),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ use servo::webrender_api::units::{DeviceIntPoint, DeviceIntSize};
|
|||
// This should vary by zoom level and maybe actual text size (focused or under cursor)
|
||||
pub const LINE_HEIGHT: f32 = 38.0;
|
||||
|
||||
pub trait WindowPortsMethods: WindowMethods {
|
||||
pub trait WindowPortsMethods: WindowMethods + webxr::glwindow::GlWindow {
|
||||
fn get_events(&self) -> Vec<WindowEvent>;
|
||||
fn id(&self) -> Option<glutin::WindowId>;
|
||||
fn has_events(&self) -> bool;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue