mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
Auto merge of #24525 - glowe:issue-23009/separate_angle_and_disable_vsync, r=jdm
Issue 23009/separate angle and disable vsync The `--angle` and `--disable-vsync` options were declared as global options, but only used in the Glutin embedding for desktop builds. Moving them to the Glutin embedding code makes them easier to update in the future. I modified `opts::from_cmdline_args` to accept a `getopts::Options` (as prescribed in the issue) and augmented `opts::ArgumentParsingResult` to include an `opts::Matches` and `content-process` String when appropriate. I could use some feedback on this last bit. I could have changed the function to return `opts::Matches` and have the embedding code look for the presence of `content-process`, but I felt that the approach I went with was closer to the original design. The other aspect I'm not sure about is moving `disable-vsync` from a global debug option to a plain embedder option. This changes the command line interface for glutin, which is maybe bad. However I wasn't sure whether it was worth preserving the original behavior given the complexity of injecting debug options into `opts::from_cmdline_args`. - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes partially fix #23009 – there are 2 more options to deal with, but I'm not sure if we should handle them yet. - [x] These changes do not require tests because this is a refactoring and I'm hoping that the existing tests cover these changes. r? @jdm
This commit is contained in:
commit
2ad6e94091
14 changed files with 180 additions and 127 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -4370,6 +4370,7 @@ dependencies = [
|
|||
"cc",
|
||||
"clipboard",
|
||||
"euclid",
|
||||
"getopts",
|
||||
"gleam 0.6.18",
|
||||
"glutin",
|
||||
"image",
|
||||
|
@ -4771,6 +4772,7 @@ name = "simpleservo"
|
|||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"core-foundation",
|
||||
"getopts",
|
||||
"gl_generator 0.11.0",
|
||||
"libc",
|
||||
"libloading",
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
use crate::prefs::{self, PrefValue};
|
||||
use euclid::Size2D;
|
||||
use getopts::Options;
|
||||
use getopts::{Matches, Options};
|
||||
use servo_geometry::DeviceIndependentPixel;
|
||||
use servo_url::ServoUrl;
|
||||
use std::borrow::Cow;
|
||||
|
@ -32,10 +32,6 @@ pub struct Opts {
|
|||
/// The maximum size of each tile in pixels (`-s`).
|
||||
pub tile_size: usize,
|
||||
|
||||
/// The ratio of device pixels per px at the default scale. If unspecified, will use the
|
||||
/// platform default setting.
|
||||
pub device_pixels_per_px: Option<f32>,
|
||||
|
||||
/// `None` to disable the time profiler or `Some` to enable it with:
|
||||
///
|
||||
/// - an interval in seconds to cause it to produce output on that interval.
|
||||
|
@ -78,9 +74,6 @@ pub struct Opts {
|
|||
|
||||
pub headless: bool,
|
||||
|
||||
/// Use ANGLE to create the GL context (Windows-only).
|
||||
pub angle: bool,
|
||||
|
||||
/// True to exit on thread failure instead of displaying about:failure.
|
||||
pub hard_fail: bool,
|
||||
|
||||
|
@ -184,12 +177,6 @@ pub struct Opts {
|
|||
/// True to exit after the page load (`-x`).
|
||||
pub exit_after_load: bool,
|
||||
|
||||
/// Do not use native titlebar
|
||||
pub no_native_titlebar: bool,
|
||||
|
||||
/// Enable vsync in the compositor
|
||||
pub enable_vsync: bool,
|
||||
|
||||
/// True to show webrender profiling stats on screen.
|
||||
pub webrender_stats: bool,
|
||||
|
||||
|
@ -207,9 +194,6 @@ pub struct Opts {
|
|||
/// after each change is made.
|
||||
pub precache_shaders: bool,
|
||||
|
||||
/// True if WebRender should use multisample antialiasing.
|
||||
pub use_msaa: bool,
|
||||
|
||||
/// Directory for a default config directory
|
||||
pub config_dir: Option<PathBuf>,
|
||||
|
||||
|
@ -231,9 +215,6 @@ pub struct Opts {
|
|||
|
||||
/// Print Progressive Web Metrics to console.
|
||||
pub print_pwm: bool,
|
||||
|
||||
/// Only shutdown once all theads are finished.
|
||||
pub clean_shutdown: bool,
|
||||
}
|
||||
|
||||
fn print_usage(app: &str, opts: &Options) {
|
||||
|
@ -314,9 +295,6 @@ pub struct DebugOptions {
|
|||
/// Load web fonts synchronously to avoid non-deterministic network-driven reflows.
|
||||
pub load_webfonts_synchronously: bool,
|
||||
|
||||
/// Disable vsync in the compositor
|
||||
pub disable_vsync: bool,
|
||||
|
||||
/// Show webrender profiling stats on screen.
|
||||
pub webrender_stats: bool,
|
||||
|
||||
|
@ -326,9 +304,6 @@ pub struct DebugOptions {
|
|||
/// Enable webrender instanced draw call batching.
|
||||
pub webrender_disable_batch: bool,
|
||||
|
||||
/// Use multisample antialiasing in WebRender.
|
||||
pub use_msaa: bool,
|
||||
|
||||
// don't skip any backtraces on panic
|
||||
pub full_backtraces: bool,
|
||||
|
||||
|
@ -368,11 +343,9 @@ impl DebugOptions {
|
|||
"replace-surrogates" => self.replace_surrogates = true,
|
||||
"gc-profile" => self.gc_profile = true,
|
||||
"load-webfonts-synchronously" => self.load_webfonts_synchronously = true,
|
||||
"disable-vsync" => self.disable_vsync = true,
|
||||
"wr-stats" => self.webrender_stats = true,
|
||||
"wr-record" => self.webrender_record = true,
|
||||
"wr-no-batch" => self.webrender_disable_batch = true,
|
||||
"msaa" => self.use_msaa = true,
|
||||
"full-backtraces" => self.full_backtraces = true,
|
||||
"precache-shaders" => self.precache_shaders = true,
|
||||
"signpost" => self.signpost = true,
|
||||
|
@ -462,12 +435,7 @@ fn print_debug_usage(app: &str) -> ! {
|
|||
"load-webfonts-synchronously",
|
||||
"Load web fonts synchronously to avoid non-deterministic network-driven reflows",
|
||||
);
|
||||
print_option(
|
||||
"disable-vsync",
|
||||
"Disable vsync mode in the compositor to allow profiling at more than monitor refresh rate",
|
||||
);
|
||||
print_option("wr-stats", "Show WebRender profiler on screen.");
|
||||
print_option("msaa", "Use multisample antialiasing in WebRender.");
|
||||
print_option("full-backtraces", "Print full backtraces for all errors");
|
||||
print_option("wr-debug", "Display webrender tile borders.");
|
||||
print_option("wr-no-batch", "Disable webrender instanced batching.");
|
||||
|
@ -552,7 +520,6 @@ pub fn default_opts() -> Opts {
|
|||
is_running_problem_test: false,
|
||||
url: None,
|
||||
tile_size: 512,
|
||||
device_pixels_per_px: None,
|
||||
time_profiling: None,
|
||||
time_profiler_trace_path: None,
|
||||
mem_profiler_period: None,
|
||||
|
@ -564,7 +531,6 @@ pub fn default_opts() -> Opts {
|
|||
gc_profile: false,
|
||||
load_webfonts_synchronously: false,
|
||||
headless: false,
|
||||
angle: false,
|
||||
hard_fail: true,
|
||||
bubble_inline_sizes_separately: false,
|
||||
show_debug_fragment_borders: false,
|
||||
|
@ -594,10 +560,7 @@ pub fn default_opts() -> Opts {
|
|||
style_sharing_stats: false,
|
||||
convert_mouse_to_touch: false,
|
||||
exit_after_load: false,
|
||||
no_native_titlebar: false,
|
||||
enable_vsync: true,
|
||||
webrender_stats: false,
|
||||
use_msaa: false,
|
||||
config_dir: None,
|
||||
full_backtraces: false,
|
||||
is_printing_version: false,
|
||||
|
@ -609,19 +572,16 @@ pub fn default_opts() -> Opts {
|
|||
certificate_path: None,
|
||||
unminify_js: false,
|
||||
print_pwm: false,
|
||||
clean_shutdown: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
|
||||
pub fn from_cmdline_args(mut opts: Options, args: &[String]) -> ArgumentParsingResult {
|
||||
let (app_name, args) = args.split_first().unwrap();
|
||||
|
||||
let mut opts = Options::new();
|
||||
opts.optflag("c", "cpu", "CPU painting");
|
||||
opts.optflag("g", "gpu", "GPU painting");
|
||||
opts.optopt("o", "output", "Output file", "output.png");
|
||||
opts.optopt("s", "size", "Size of tiles", "512");
|
||||
opts.optopt("", "device-pixel-ratio", "Device pixels per px", "");
|
||||
opts.optflagopt(
|
||||
"p",
|
||||
"profile",
|
||||
|
@ -673,11 +633,6 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
|
|||
"",
|
||||
);
|
||||
opts.optflag("z", "headless", "Headless mode");
|
||||
opts.optflag(
|
||||
"",
|
||||
"angle",
|
||||
"Use ANGLE to create a GL context (Windows-only)",
|
||||
);
|
||||
opts.optflag(
|
||||
"f",
|
||||
"hard-fail",
|
||||
|
@ -767,11 +722,6 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
|
|||
"config directory following xdg spec on linux platform",
|
||||
"",
|
||||
);
|
||||
opts.optflag(
|
||||
"",
|
||||
"clean-shutdown",
|
||||
"Do not shutdown until all threads have finished (macos only)",
|
||||
);
|
||||
opts.optflag("v", "version", "Display servo version information");
|
||||
opts.optflag("", "unminify-js", "Unminify Javascript");
|
||||
opts.optopt("", "profiler-db-user", "Profiler database user", "");
|
||||
|
@ -793,7 +743,7 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
|
|||
// some dummy options for now.
|
||||
if let Some(content_process) = opt_match.opt_str("content-process") {
|
||||
MULTIPROCESS.store(true, Ordering::SeqCst);
|
||||
return ArgumentParsingResult::ContentProcess(content_process);
|
||||
return ArgumentParsingResult::ContentProcess(opt_match, content_process);
|
||||
}
|
||||
|
||||
let mut debug_options = DebugOptions::default();
|
||||
|
@ -836,15 +786,6 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
|
|||
None => 512,
|
||||
};
|
||||
|
||||
let device_pixels_per_px = opt_match.opt_str("device-pixel-ratio").map(|dppx_str| {
|
||||
dppx_str.parse().unwrap_or_else(|err| {
|
||||
args_fail(&format!(
|
||||
"Error parsing option: --device-pixel-ratio ({})",
|
||||
err
|
||||
))
|
||||
})
|
||||
});
|
||||
|
||||
// If only the flag is present, default to a 5 second period for both profilers
|
||||
let time_profiling = if opt_match.opt_present("p") {
|
||||
match opt_match.opt_str("p") {
|
||||
|
@ -986,9 +927,6 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
|
|||
})
|
||||
.collect();
|
||||
|
||||
let do_not_use_native_titlebar =
|
||||
opt_match.opt_present("b") || !(pref!(shell.native_titlebar.enabled));
|
||||
|
||||
let enable_subpixel_text_antialiasing =
|
||||
!debug_options.disable_subpixel_aa && pref!(gfx.subpixel_text_antialiasing.enabled);
|
||||
|
||||
|
@ -998,7 +936,6 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
|
|||
is_running_problem_test: is_running_problem_test,
|
||||
url: url_opt,
|
||||
tile_size: tile_size,
|
||||
device_pixels_per_px: device_pixels_per_px,
|
||||
time_profiling: time_profiling,
|
||||
time_profiler_trace_path: opt_match.opt_str("profiler-trace-path"),
|
||||
mem_profiler_period: mem_profiler_period,
|
||||
|
@ -1010,7 +947,6 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
|
|||
gc_profile: debug_options.gc_profile,
|
||||
load_webfonts_synchronously: debug_options.load_webfonts_synchronously,
|
||||
headless: opt_match.opt_present("z"),
|
||||
angle: opt_match.opt_present("angle"),
|
||||
hard_fail: opt_match.opt_present("f") && !opt_match.opt_present("F"),
|
||||
bubble_inline_sizes_separately: bubble_inline_sizes_separately,
|
||||
profile_script_events: debug_options.profile_script_events,
|
||||
|
@ -1040,10 +976,7 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
|
|||
style_sharing_stats: debug_options.style_sharing_stats,
|
||||
convert_mouse_to_touch: debug_options.convert_mouse_to_touch,
|
||||
exit_after_load: opt_match.opt_present("x"),
|
||||
no_native_titlebar: do_not_use_native_titlebar,
|
||||
enable_vsync: !debug_options.disable_vsync,
|
||||
webrender_stats: debug_options.webrender_stats,
|
||||
use_msaa: debug_options.use_msaa,
|
||||
config_dir: opt_match.opt_str("config-dir").map(Into::into),
|
||||
full_backtraces: debug_options.full_backtraces,
|
||||
is_printing_version: is_printing_version,
|
||||
|
@ -1055,7 +988,6 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
|
|||
certificate_path: opt_match.opt_str("certificate-path"),
|
||||
unminify_js: opt_match.opt_present("unminify-js"),
|
||||
print_pwm: opt_match.opt_present("print-pwm"),
|
||||
clean_shutdown: opt_match.opt_present("clean-shutdown"),
|
||||
};
|
||||
|
||||
set_options(opts);
|
||||
|
@ -1074,12 +1006,12 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
|
|||
set_pref!(layout.threads, layout_threads as i64);
|
||||
}
|
||||
|
||||
ArgumentParsingResult::ChromeProcess
|
||||
return ArgumentParsingResult::ChromeProcess(opt_match);
|
||||
}
|
||||
|
||||
pub enum ArgumentParsingResult {
|
||||
ChromeProcess,
|
||||
ContentProcess(String),
|
||||
ChromeProcess(Matches),
|
||||
ContentProcess(Matches, String),
|
||||
}
|
||||
|
||||
// Make Opts available globally. This saves having to clone and pass
|
||||
|
|
|
@ -464,6 +464,10 @@ pub struct Constellation<Message, LTF, STF> {
|
|||
|
||||
/// Mechanism to force the compositor to process events.
|
||||
event_loop_waker: Option<Box<dyn EventLoopWaker>>,
|
||||
|
||||
/// The ratio of device pixels per px at the default scale. If unspecified, will use the
|
||||
/// platform default setting.
|
||||
device_pixels_per_px: Option<f32>,
|
||||
}
|
||||
|
||||
/// State needed to construct a constellation.
|
||||
|
@ -520,6 +524,10 @@ pub struct InitialConstellationState {
|
|||
|
||||
/// Mechanism to force the compositor to process events.
|
||||
pub event_loop_waker: Option<Box<dyn EventLoopWaker>>,
|
||||
|
||||
/// The ratio of device pixels per px at the default scale. If unspecified, will use the
|
||||
/// platform default setting.
|
||||
pub device_pixels_per_px: Option<f32>,
|
||||
}
|
||||
|
||||
/// Data needed for webdriver
|
||||
|
@ -837,6 +845,7 @@ where
|
|||
glplayer_threads: state.glplayer_threads,
|
||||
player_context: state.player_context,
|
||||
event_loop_waker: state.event_loop_waker,
|
||||
device_pixels_per_px,
|
||||
};
|
||||
|
||||
constellation.run();
|
||||
|
@ -1081,6 +1090,7 @@ where
|
|||
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()),
|
||||
device_pixels_per_px: self.device_pixels_per_px,
|
||||
});
|
||||
|
||||
let pipeline = match result {
|
||||
|
|
|
@ -205,6 +205,10 @@ pub struct InitialPipelineState {
|
|||
|
||||
/// Mechanism to force the compositor to process events.
|
||||
pub event_loop_waker: Option<Box<dyn EventLoopWaker>>,
|
||||
|
||||
/// The ratio of device pixels per px at the default scale. If unspecified, will use the
|
||||
/// platform default setting.
|
||||
pub device_pixels_per_px: Option<f32>,
|
||||
}
|
||||
|
||||
pub struct NewPipeline {
|
||||
|
@ -312,6 +316,7 @@ impl Pipeline {
|
|||
webvr_chan: state.webvr_chan,
|
||||
webxr_registry: state.webxr_registry,
|
||||
player_context: state.player_context,
|
||||
device_pixels_per_px: state.device_pixels_per_px,
|
||||
};
|
||||
|
||||
// Spawn the child process.
|
||||
|
@ -518,6 +523,7 @@ pub struct UnprivilegedPipelineContent {
|
|||
webvr_chan: Option<IpcSender<WebVRMsg>>,
|
||||
webxr_registry: webxr_api::Registry,
|
||||
player_context: WindowGLContext,
|
||||
device_pixels_per_px: Option<f32>,
|
||||
}
|
||||
|
||||
impl UnprivilegedPipelineContent {
|
||||
|
@ -609,7 +615,7 @@ impl UnprivilegedPipelineContent {
|
|||
layout_thread_busy_flag.clone(),
|
||||
self.opts.load_webfonts_synchronously,
|
||||
self.opts.initial_window_size,
|
||||
self.opts.device_pixels_per_px,
|
||||
self.device_pixels_per_px,
|
||||
self.opts.dump_display_list,
|
||||
self.opts.dump_display_list_json,
|
||||
self.opts.dump_style_tree,
|
||||
|
|
|
@ -306,7 +306,11 @@ impl<Window> Servo<Window>
|
|||
where
|
||||
Window: WindowMethods + 'static + ?Sized,
|
||||
{
|
||||
pub fn new(mut embedder: Box<dyn EmbedderMethods>, window: Rc<Window>) -> Servo<Window> {
|
||||
pub fn new(
|
||||
mut embedder: Box<dyn EmbedderMethods>,
|
||||
window: Rc<Window>,
|
||||
device_pixels_per_px: Option<f32>,
|
||||
) -> Servo<Window> {
|
||||
// Global configuration options, parsed from the command line.
|
||||
let opts = opts::get();
|
||||
|
||||
|
@ -551,6 +555,7 @@ where
|
|||
webvr_constellation_sender,
|
||||
glplayer_threads,
|
||||
event_loop_waker,
|
||||
device_pixels_per_px,
|
||||
);
|
||||
|
||||
// Send the constellation's swmanager sender to service worker manager thread
|
||||
|
@ -582,7 +587,7 @@ where
|
|||
opts.is_running_problem_test,
|
||||
opts.exit_after_load,
|
||||
opts.convert_mouse_to_touch,
|
||||
opts.device_pixels_per_px,
|
||||
device_pixels_per_px,
|
||||
);
|
||||
|
||||
Servo {
|
||||
|
@ -870,6 +875,7 @@ fn create_constellation(
|
|||
webvr_constellation_sender: Option<Sender<Sender<ConstellationMsg>>>,
|
||||
glplayer_threads: Option<GLPlayerThreads>,
|
||||
event_loop_waker: Option<Box<dyn EventLoopWaker>>,
|
||||
device_pixels_per_px: Option<f32>,
|
||||
) -> (Sender<ConstellationMsg>, SWManagerSenders) {
|
||||
// Global configuration options, parsed from the command line.
|
||||
let opts = opts::get();
|
||||
|
@ -912,6 +918,7 @@ fn create_constellation(
|
|||
glplayer_threads,
|
||||
player_context,
|
||||
event_loop_waker,
|
||||
device_pixels_per_px,
|
||||
};
|
||||
let (constellation_chan, from_swmanager_sender) = Constellation::<
|
||||
script_layout_interface::message::Msg,
|
||||
|
@ -920,7 +927,7 @@ fn create_constellation(
|
|||
>::start(
|
||||
initial_state,
|
||||
opts.initial_window_size,
|
||||
opts.device_pixels_per_px,
|
||||
device_pixels_per_px,
|
||||
opts.random_pipeline_closure_probability,
|
||||
opts.random_pipeline_closure_seed,
|
||||
opts.is_running_problem_test,
|
||||
|
|
|
@ -49,6 +49,7 @@ vslatestinstalled = ["libservo/vslatestinstalled"]
|
|||
backtrace = "0.3"
|
||||
clipboard = "0.5"
|
||||
euclid = "0.20"
|
||||
getopts = "0.2.11"
|
||||
gleam = "0.6"
|
||||
glutin = "0.21.0"
|
||||
keyboard-types = "0.4.3"
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
use crate::browser::Browser;
|
||||
use crate::embedder::EmbedderCallbacks;
|
||||
use crate::window_trait::WindowPortsMethods;
|
||||
use crate::events_loop::EventsLoop;
|
||||
use crate::window_trait::WindowPortsMethods;
|
||||
use crate::{headed_window, headless_window};
|
||||
use glutin::WindowId;
|
||||
use servo::compositing::windowing::WindowEvent;
|
||||
|
@ -34,14 +34,29 @@ pub struct App {
|
|||
}
|
||||
|
||||
impl App {
|
||||
pub fn run() {
|
||||
pub fn run(
|
||||
angle: bool,
|
||||
enable_vsync: bool,
|
||||
use_msaa: bool,
|
||||
no_native_titlebar: bool,
|
||||
device_pixels_per_px: Option<f32>,
|
||||
) {
|
||||
let events_loop = EventsLoop::new(opts::get().headless);
|
||||
|
||||
// Implements window methods, used by compositor.
|
||||
let window = if opts::get().headless {
|
||||
headless_window::Window::new(opts::get().initial_window_size)
|
||||
headless_window::Window::new(opts::get().initial_window_size, device_pixels_per_px)
|
||||
} else {
|
||||
Rc::new(headed_window::Window::new(opts::get().initial_window_size, None, events_loop.clone()))
|
||||
Rc::new(headed_window::Window::new(
|
||||
opts::get().initial_window_size,
|
||||
None,
|
||||
events_loop.clone(),
|
||||
angle,
|
||||
enable_vsync,
|
||||
use_msaa,
|
||||
no_native_titlebar,
|
||||
device_pixels_per_px,
|
||||
))
|
||||
};
|
||||
|
||||
// Implements embedder methods, used by libservo and constellation.
|
||||
|
@ -49,12 +64,13 @@ impl App {
|
|||
window.clone(),
|
||||
events_loop.clone(),
|
||||
window.gl(),
|
||||
angle,
|
||||
));
|
||||
|
||||
// Handle browser state.
|
||||
let browser = Browser::new(window.clone());
|
||||
|
||||
let mut servo = Servo::new(embedder, window.clone());
|
||||
let mut servo = Servo::new(embedder, window.clone(), device_pixels_per_px);
|
||||
let browser_id = BrowserId::new();
|
||||
servo.handle_events(vec![WindowEvent::NewBrowser(get_default_url(), browser_id)]);
|
||||
servo.setup_logging();
|
||||
|
@ -110,7 +126,7 @@ impl App {
|
|||
};
|
||||
window.winit_event_to_servo_event(event);
|
||||
return cont;
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -121,7 +137,10 @@ impl App {
|
|||
fn run_loop(self) {
|
||||
loop {
|
||||
let animating = WINDOWS.with(|windows| {
|
||||
windows.borrow().iter().any(|(_, window)| window.is_animating())
|
||||
windows
|
||||
.borrow()
|
||||
.iter()
|
||||
.any(|(_, window)| window.is_animating())
|
||||
});
|
||||
if !animating || self.suspended.get() {
|
||||
// If there's no animations running then we block on the window event loop.
|
||||
|
@ -219,8 +238,8 @@ pub fn register_window(window: Rc<dyn WindowPortsMethods>) {
|
|||
});
|
||||
}
|
||||
|
||||
pub fn gl_version() -> glutin::GlRequest {
|
||||
if opts::get().angle {
|
||||
pub fn gl_version(angle: bool) -> glutin::GlRequest {
|
||||
if angle {
|
||||
glutin::GlRequest::Specific(glutin::Api::OpenGlEs, (3, 0))
|
||||
} else {
|
||||
glutin::GlRequest::GlThenGles {
|
||||
|
|
|
@ -9,8 +9,8 @@ use crate::events_loop::EventsLoop;
|
|||
use crate::window_trait::WindowPortsMethods;
|
||||
use gleam::gl;
|
||||
use glutin;
|
||||
use glutin::EventsLoopClosed;
|
||||
use glutin::dpi::LogicalSize;
|
||||
use glutin::EventsLoopClosed;
|
||||
use rust_webvr::GlWindowVRService;
|
||||
use servo::compositing::windowing::EmbedderMethods;
|
||||
use servo::embedder_traits::EventLoopWaker;
|
||||
|
@ -24,15 +24,22 @@ pub struct EmbedderCallbacks {
|
|||
window: Rc<dyn WindowPortsMethods>,
|
||||
events_loop: Rc<RefCell<EventsLoop>>,
|
||||
gl: Rc<dyn gl::Gl>,
|
||||
angle: bool,
|
||||
}
|
||||
|
||||
impl EmbedderCallbacks {
|
||||
pub fn new(
|
||||
window: Rc<dyn WindowPortsMethods>,
|
||||
events_loop: Rc<RefCell<EventsLoop>>,
|
||||
gl: Rc<dyn gl::Gl>
|
||||
gl: Rc<dyn gl::Gl>,
|
||||
angle: bool,
|
||||
) -> EmbedderCallbacks {
|
||||
EmbedderCallbacks { window, events_loop, gl }
|
||||
EmbedderCallbacks {
|
||||
window,
|
||||
events_loop,
|
||||
gl,
|
||||
angle,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,7 +62,10 @@ impl EmbedderMethods for EmbedderCallbacks {
|
|||
let size = LogicalSize::new(size.width, size.height);
|
||||
let events_loop_clone = self.events_loop.clone();
|
||||
let events_loop_factory = Box::new(move || {
|
||||
events_loop_clone.borrow_mut().take().ok_or(EventsLoopClosed)
|
||||
events_loop_clone
|
||||
.borrow_mut()
|
||||
.take()
|
||||
.ok_or(EventsLoopClosed)
|
||||
});
|
||||
let window_builder = glutin::WindowBuilder::new()
|
||||
.with_title(name.clone())
|
||||
|
@ -63,12 +73,13 @@ impl EmbedderMethods for EmbedderCallbacks {
|
|||
.with_visibility(false)
|
||||
.with_multitouch();
|
||||
let context = glutin::ContextBuilder::new()
|
||||
.with_gl(app::gl_version())
|
||||
.with_gl(app::gl_version(self.angle))
|
||||
.with_vsync(false) // Assume the browser vsync is the same as the test VR window vsync
|
||||
.build_windowed(window_builder, &*self.events_loop.borrow().as_winit())
|
||||
.expect("Failed to create window.");
|
||||
let gl = self.gl.clone();
|
||||
let (service, heartbeat) = GlWindowVRService::new(name, context, events_loop_factory, gl);
|
||||
let (service, heartbeat) =
|
||||
GlWindowVRService::new(name, context, events_loop_factory, gl);
|
||||
|
||||
services.register(Box::new(service));
|
||||
heartbeats.push(Box::new(heartbeat));
|
||||
|
|
|
@ -71,6 +71,11 @@ pub struct Window {
|
|||
fullscreen: Cell<bool>,
|
||||
gl: Rc<dyn gl::Gl>,
|
||||
xr_rotation: Cell<Rotation3D<f32, UnknownUnit, UnknownUnit>>,
|
||||
angle: bool,
|
||||
enable_vsync: bool,
|
||||
use_msaa: bool,
|
||||
no_native_titlebar: bool,
|
||||
device_pixels_per_px: Option<f32>,
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
|
@ -90,6 +95,11 @@ impl Window {
|
|||
win_size: Size2D<u32, DeviceIndependentPixel>,
|
||||
sharing: Option<&Window>,
|
||||
events_loop: Rc<RefCell<EventsLoop>>,
|
||||
angle: bool,
|
||||
enable_vsync: bool,
|
||||
use_msaa: bool,
|
||||
no_native_titlebar: bool,
|
||||
device_pixels_per_px: Option<f32>,
|
||||
) -> Window {
|
||||
let opts = opts::get();
|
||||
|
||||
|
@ -97,7 +107,7 @@ impl Window {
|
|||
// `load_end()`. This avoids an ugly flash of unstyled content (especially important since
|
||||
// unstyled content is white and chrome often has a transparent background). See issue
|
||||
// #9996.
|
||||
let visible = opts.output_file.is_none() && !opts.no_native_titlebar;
|
||||
let visible = opts.output_file.is_none() && !no_native_titlebar;
|
||||
|
||||
let win_size: DeviceIntSize = (win_size.to_f32() * window_creation_scale_factor()).to_i32();
|
||||
let width = win_size.to_untyped().width;
|
||||
|
@ -105,8 +115,8 @@ impl Window {
|
|||
|
||||
let mut window_builder = glutin::WindowBuilder::new()
|
||||
.with_title("Servo".to_string())
|
||||
.with_decorations(!opts.no_native_titlebar)
|
||||
.with_transparency(opts.no_native_titlebar)
|
||||
.with_decorations(!no_native_titlebar)
|
||||
.with_transparency(no_native_titlebar)
|
||||
.with_dimensions(LogicalSize::new(width as f64, height as f64))
|
||||
.with_visibility(visible)
|
||||
.with_multitouch();
|
||||
|
@ -114,10 +124,10 @@ impl Window {
|
|||
window_builder = builder_with_platform_options(window_builder);
|
||||
|
||||
let mut context_builder = glutin::ContextBuilder::new()
|
||||
.with_gl(app::gl_version())
|
||||
.with_vsync(opts.enable_vsync);
|
||||
.with_gl(app::gl_version(angle))
|
||||
.with_vsync(enable_vsync);
|
||||
|
||||
if opts.use_msaa {
|
||||
if use_msaa {
|
||||
context_builder = context_builder.with_multisampling(MULTISAMPLES)
|
||||
}
|
||||
|
||||
|
@ -198,6 +208,11 @@ impl Window {
|
|||
primary_monitor,
|
||||
screen_size,
|
||||
xr_rotation: Cell::new(Rotation3D::identity()),
|
||||
angle,
|
||||
enable_vsync,
|
||||
use_msaa,
|
||||
no_native_titlebar,
|
||||
device_pixels_per_px,
|
||||
};
|
||||
|
||||
window.present();
|
||||
|
@ -317,7 +332,7 @@ impl Window {
|
|||
}
|
||||
|
||||
fn servo_hidpi_factor(&self) -> Scale<f32, DeviceIndependentPixel, DevicePixel> {
|
||||
match opts::get().device_pixels_per_px {
|
||||
match self.device_pixels_per_px {
|
||||
Some(device_pixels_per_px) => Scale::new(device_pixels_per_px),
|
||||
_ => match opts::get().output_file {
|
||||
Some(_) => Scale::new(1.0),
|
||||
|
@ -545,6 +560,11 @@ impl webxr::glwindow::GlWindow for Window {
|
|||
self.inner_size.get(),
|
||||
Some(self),
|
||||
self.events_loop.clone(),
|
||||
self.angle,
|
||||
self.enable_vsync,
|
||||
self.use_msaa,
|
||||
self.no_native_titlebar,
|
||||
self.device_pixels_per_px,
|
||||
));
|
||||
app::register_window(window.clone());
|
||||
Ok(window)
|
||||
|
|
|
@ -5,12 +5,11 @@
|
|||
//! A headless window implementation.
|
||||
|
||||
use crate::window_trait::WindowPortsMethods;
|
||||
use glutin;
|
||||
use euclid::{default::Size2D as UntypedSize2D, Point2D, Rotation3D, Scale, Size2D, UnknownUnit};
|
||||
use gleam::gl;
|
||||
use glutin;
|
||||
use servo::compositing::windowing::{AnimationState, WindowEvent};
|
||||
use servo::compositing::windowing::{EmbedderCoordinates, WindowMethods};
|
||||
use servo::servo_config::opts;
|
||||
use servo::servo_geometry::DeviceIndependentPixel;
|
||||
use servo::style_traits::DevicePixel;
|
||||
use servo::webrender_api::units::{DeviceIntRect, DeviceIntSize};
|
||||
|
@ -92,10 +91,14 @@ pub struct Window {
|
|||
animation_state: Cell<AnimationState>,
|
||||
fullscreen: Cell<bool>,
|
||||
gl: Rc<dyn gl::Gl>,
|
||||
device_pixels_per_px: Option<f32>,
|
||||
}
|
||||
|
||||
impl Window {
|
||||
pub fn new(size: Size2D<u32, DeviceIndependentPixel>) -> Rc<dyn WindowPortsMethods> {
|
||||
pub fn new(
|
||||
size: Size2D<u32, DeviceIndependentPixel>,
|
||||
device_pixels_per_px: Option<f32>,
|
||||
) -> Rc<dyn WindowPortsMethods> {
|
||||
let context = HeadlessContext::new(size.width, size.height, None);
|
||||
let gl = unsafe { gl::GlFns::load_with(|s| HeadlessContext::get_proc_address(s)) };
|
||||
|
||||
|
@ -110,13 +113,14 @@ impl Window {
|
|||
gl,
|
||||
animation_state: Cell::new(AnimationState::Idle),
|
||||
fullscreen: Cell::new(false),
|
||||
device_pixels_per_px,
|
||||
};
|
||||
|
||||
Rc::new(window)
|
||||
}
|
||||
|
||||
fn servo_hidpi_factor(&self) -> Scale<f32, DeviceIndependentPixel, DevicePixel> {
|
||||
match opts::get().device_pixels_per_px {
|
||||
match self.device_pixels_per_px {
|
||||
Some(device_pixels_per_px) => Scale::new(device_pixels_per_px),
|
||||
_ => Scale::new(1.0),
|
||||
}
|
||||
|
@ -133,9 +137,7 @@ impl WindowPortsMethods for Window {
|
|||
}
|
||||
|
||||
fn id(&self) -> glutin::WindowId {
|
||||
unsafe {
|
||||
glutin::WindowId::dummy()
|
||||
}
|
||||
unsafe { glutin::WindowId::dummy() }
|
||||
}
|
||||
|
||||
fn page_height(&self) -> f32 {
|
||||
|
@ -167,8 +169,7 @@ impl WindowMethods for Window {
|
|||
|
||||
fn get_coordinates(&self) -> EmbedderCoordinates {
|
||||
let dpr = self.servo_hidpi_factor();
|
||||
let size =
|
||||
(Size2D::new(self.context.width, self.context.height).to_f32() * dpr).to_i32();
|
||||
let size = (Size2D::new(self.context.width, self.context.height).to_f32() * dpr).to_i32();
|
||||
let viewport = DeviceIntRect::new(Point2D::zero(), size);
|
||||
let framebuffer = DeviceIntSize::from_untyped(size.to_untyped());
|
||||
EmbedderCoordinates {
|
||||
|
@ -223,7 +224,10 @@ impl webxr::glwindow::GlWindow for Window {
|
|||
fn swap_buffers(&self) {}
|
||||
fn size(&self) -> UntypedSize2D<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)
|
||||
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<Rc<dyn webxr::glwindow::GlWindow>, ()> {
|
||||
let width = self.context.width;
|
||||
|
@ -236,6 +240,7 @@ impl webxr::glwindow::GlWindow for Window {
|
|||
gl,
|
||||
animation_state: Cell::new(AnimationState::Idle),
|
||||
fullscreen: Cell::new(false),
|
||||
device_pixels_per_px: self.device_pixels_per_px,
|
||||
}))
|
||||
}
|
||||
fn get_rotation(&self) -> Rotation3D<f32, UnknownUnit, UnknownUnit> {
|
||||
|
|
|
@ -24,8 +24,10 @@ mod window_trait;
|
|||
|
||||
use app::App;
|
||||
use backtrace::Backtrace;
|
||||
use getopts::Options;
|
||||
use servo::config::opts::{self, ArgumentParsingResult};
|
||||
use servo::config::servo_version;
|
||||
use servo::servo_config::pref;
|
||||
use std::env;
|
||||
use std::panic;
|
||||
use std::process;
|
||||
|
@ -39,7 +41,7 @@ pub mod platform {
|
|||
pub mod macos;
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
pub fn deinit() {}
|
||||
pub fn deinit(_clean_shutdown: bool) {}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "macos", target_os = "linux")))]
|
||||
|
@ -76,16 +78,40 @@ pub fn main() {
|
|||
|
||||
// Parse the command line options and store them globally
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let opts_result = opts::from_cmdline_args(&args);
|
||||
let mut opts = Options::new();
|
||||
opts.optflag(
|
||||
"",
|
||||
"angle",
|
||||
"Use ANGLE to create a GL context (Windows-only)",
|
||||
);
|
||||
opts.optflag(
|
||||
"",
|
||||
"clean-shutdown",
|
||||
"Do not shutdown until all threads have finished (macos only)",
|
||||
);
|
||||
opts.optflag(
|
||||
"",
|
||||
"disable-vsync",
|
||||
"Disable vsync mode in the compositor to allow profiling at more than monitor refresh rate",
|
||||
);
|
||||
opts.optflag("", "msaa", "Use multisample antialiasing in WebRender.");
|
||||
opts.optflag("b", "no-native-titlebar", "Do not use native titlebar");
|
||||
opts.optopt("", "device-pixel-ratio", "Device pixels per px", "");
|
||||
|
||||
let content_process_token = if let ArgumentParsingResult::ContentProcess(token) = opts_result {
|
||||
Some(token)
|
||||
} else {
|
||||
let opts_matches;
|
||||
let content_process_token;
|
||||
match opts::from_cmdline_args(opts, &args) {
|
||||
ArgumentParsingResult::ContentProcess(matches, token) => {
|
||||
opts_matches = matches;
|
||||
content_process_token = Some(token);
|
||||
if opts::get().is_running_problem_test && env::var("RUST_LOG").is_err() {
|
||||
env::set_var("RUST_LOG", "compositing::constellation");
|
||||
}
|
||||
|
||||
None
|
||||
},
|
||||
ArgumentParsingResult::ChromeProcess(matches) => {
|
||||
opts_matches = matches;
|
||||
content_process_token = None;
|
||||
},
|
||||
};
|
||||
|
||||
// TODO: once log-panics is released, can this be replaced by
|
||||
|
@ -128,7 +154,20 @@ pub fn main() {
|
|||
process::exit(0);
|
||||
}
|
||||
|
||||
App::run();
|
||||
let angle = opts_matches.opt_present("angle");
|
||||
let clean_shutdown = opts_matches.opt_present("clean-shutdown");
|
||||
let do_not_use_native_titlebar =
|
||||
opts_matches.opt_present("no-native-titlebar") || !(pref!(shell.native_titlebar.enabled));
|
||||
let enable_vsync = !opts_matches.opt_present("disable-vsync");
|
||||
let use_msaa = opts_matches.opt_present("msaa");
|
||||
let device_pixels_per_px = opts_matches.opt_str("device-pixel-ratio").map(|dppx_str| {
|
||||
dppx_str.parse().unwrap_or_else(|err| {
|
||||
error!( "Error parsing option: --device-pixel-ratio ({})", err);
|
||||
process::exit(1);
|
||||
})
|
||||
});
|
||||
|
||||
platform::deinit()
|
||||
App::run(angle, enable_vsync, use_msaa, do_not_use_native_titlebar, device_pixels_per_px);
|
||||
|
||||
platform::deinit(clean_shutdown)
|
||||
}
|
||||
|
|
|
@ -2,12 +2,11 @@
|
|||
* 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 servo::config::opts;
|
||||
use std::ptr;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
pub fn deinit() {
|
||||
pub fn deinit(clean_shutdown: bool) {
|
||||
// An unfortunate hack to make sure the linker's dead code stripping doesn't strip our
|
||||
// `Info.plist`.
|
||||
unsafe {
|
||||
|
@ -21,7 +20,7 @@ pub fn deinit() {
|
|||
"{} threads are still running after shutdown (bad).",
|
||||
thread_count
|
||||
);
|
||||
if opts::get().clean_shutdown {
|
||||
if clean_shutdown {
|
||||
println!("Waiting until all threads have shutdown");
|
||||
loop {
|
||||
let thread_count = unsafe { macos_count_running_threads() };
|
||||
|
|
|
@ -7,6 +7,7 @@ edition = "2018"
|
|||
publish = false
|
||||
|
||||
[dependencies]
|
||||
getopts = "0.2.11"
|
||||
libservo = { path = "../../../components/servo" }
|
||||
log = "0.4"
|
||||
servo-media = { git = "https://github.com/servo/media" }
|
||||
|
|
|
@ -9,6 +9,7 @@ pub mod gl_glue;
|
|||
|
||||
pub use servo::script_traits::MouseButton;
|
||||
|
||||
use getopts::Options;
|
||||
use servo::compositing::windowing::{
|
||||
AnimationState, EmbedderCoordinates, EmbedderMethods, MouseWindowEvent, WindowEvent,
|
||||
WindowMethods,
|
||||
|
@ -170,7 +171,7 @@ pub fn init(
|
|||
gfx.subpixel_text_antialiasing.enabled,
|
||||
init_opts.enable_subpixel_text_antialiasing
|
||||
);
|
||||
opts::from_cmdline_args(&args);
|
||||
opts::from_cmdline_args(Options::new(), &args);
|
||||
}
|
||||
|
||||
let embedder_url = init_opts.url.as_ref().and_then(|s| ServoUrl::parse(s).ok());
|
||||
|
@ -204,7 +205,7 @@ pub fn init(
|
|||
gl: gl.clone(),
|
||||
});
|
||||
|
||||
let servo = Servo::new(embedder_callbacks, window_callbacks.clone());
|
||||
let servo = Servo::new(embedder_callbacks, window_callbacks.clone(), None);
|
||||
|
||||
SERVO.with(|s| {
|
||||
let mut servo_glue = ServoGlue {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue