diff --git a/Cargo.lock b/Cargo.lock index 2376357643b..ab1a150e4f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/components/config/opts.rs b/components/config/opts.rs index ffc557c0a46..64856866a86 100644 --- a/components/config/opts.rs +++ b/components/config/opts.rs @@ -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, - /// `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, @@ -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 diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index 356f530d9ed..a819bd65a1b 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -464,6 +464,10 @@ pub struct Constellation { /// Mechanism to force the compositor to process events. event_loop_waker: Option>, + + /// The ratio of device pixels per px at the default scale. If unspecified, will use the + /// platform default setting. + device_pixels_per_px: Option, } /// 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>, + + /// 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, } /// 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 { diff --git a/components/constellation/pipeline.rs b/components/constellation/pipeline.rs index 373d4820529..2579343f3fe 100644 --- a/components/constellation/pipeline.rs +++ b/components/constellation/pipeline.rs @@ -205,6 +205,10 @@ pub struct InitialPipelineState { /// Mechanism to force the compositor to process events. pub event_loop_waker: Option>, + + /// 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, } 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>, webxr_registry: webxr_api::Registry, player_context: WindowGLContext, + device_pixels_per_px: Option, } 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, diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 7e8a6c1a438..86920bbe361 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -306,7 +306,11 @@ impl Servo where Window: WindowMethods + 'static + ?Sized, { - pub fn new(mut embedder: Box, window: Rc) -> Servo { + pub fn new( + mut embedder: Box, + window: Rc, + device_pixels_per_px: Option, + ) -> Servo { // 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>>, glplayer_threads: Option, event_loop_waker: Option>, + device_pixels_per_px: Option, ) -> (Sender, 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, diff --git a/ports/glutin/Cargo.toml b/ports/glutin/Cargo.toml index a9f786e7f54..3b490d73e30 100644 --- a/ports/glutin/Cargo.toml +++ b/ports/glutin/Cargo.toml @@ -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" diff --git a/ports/glutin/app.rs b/ports/glutin/app.rs index 77bd3eb41dc..a43245d79a5 100644 --- a/ports/glutin/app.rs +++ b/ports/glutin/app.rs @@ -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, + ) { 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) { }); } -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 { diff --git a/ports/glutin/embedder.rs b/ports/glutin/embedder.rs index fcebdd4d859..678ecdd8064 100644 --- a/ports/glutin/embedder.rs +++ b/ports/glutin/embedder.rs @@ -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, events_loop: Rc>, gl: Rc, + angle: bool, } impl EmbedderCallbacks { pub fn new( window: Rc, events_loop: Rc>, - gl: Rc + gl: Rc, + 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)); diff --git a/ports/glutin/headed_window.rs b/ports/glutin/headed_window.rs index f8e54149863..dfaf980b6fb 100644 --- a/ports/glutin/headed_window.rs +++ b/ports/glutin/headed_window.rs @@ -71,6 +71,11 @@ pub struct Window { fullscreen: Cell, gl: Rc, xr_rotation: Cell>, + angle: bool, + enable_vsync: bool, + use_msaa: bool, + no_native_titlebar: bool, + device_pixels_per_px: Option, } #[cfg(not(target_os = "windows"))] @@ -90,6 +95,11 @@ impl Window { win_size: Size2D, sharing: Option<&Window>, events_loop: Rc>, + angle: bool, + enable_vsync: bool, + use_msaa: bool, + no_native_titlebar: bool, + device_pixels_per_px: Option, ) -> 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 { - 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) diff --git a/ports/glutin/headless_window.rs b/ports/glutin/headless_window.rs index 4b87915bb17..c0c5c1fabb0 100644 --- a/ports/glutin/headless_window.rs +++ b/ports/glutin/headless_window.rs @@ -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, fullscreen: Cell, gl: Rc, + device_pixels_per_px: Option, } impl Window { - pub fn new(size: Size2D) -> Rc { + pub fn new( + size: Size2D, + device_pixels_per_px: Option, + ) -> Rc { 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 { - 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 { 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, ()> { 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 { diff --git a/ports/glutin/main2.rs b/ports/glutin/main2.rs index 579c97d3a23..b8d784db762 100644 --- a/ports/glutin/main2.rs +++ b/ports/glutin/main2.rs @@ -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 = 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 { - if opts::get().is_running_problem_test && env::var("RUST_LOG").is_err() { - env::set_var("RUST_LOG", "compositing::constellation"); - } - - None + 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"); + } + }, + 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) } diff --git a/ports/glutin/platform/macos/mod.rs b/ports/glutin/platform/macos/mod.rs index 730f4072576..d9d14bb9ee8 100644 --- a/ports/glutin/platform/macos/mod.rs +++ b/ports/glutin/platform/macos/mod.rs @@ -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() }; diff --git a/ports/libsimpleservo/api/Cargo.toml b/ports/libsimpleservo/api/Cargo.toml index e0204f3ebb6..afbd3f4c800 100644 --- a/ports/libsimpleservo/api/Cargo.toml +++ b/ports/libsimpleservo/api/Cargo.toml @@ -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" } diff --git a/ports/libsimpleservo/api/src/lib.rs b/ports/libsimpleservo/api/src/lib.rs index a68cea55dbc..57844593a95 100644 --- a/ports/libsimpleservo/api/src/lib.rs +++ b/ports/libsimpleservo/api/src/lib.rs @@ -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 {