diff --git a/Cargo.lock b/Cargo.lock index d7151de0d1..f953b3de9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -604,7 +604,7 @@ dependencies = [ "wayland-client 0.20.10 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "winit 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)", - "x11-dl 2.17.5 (registry+https://github.com/rust-lang/crates.io-index)", + "x11-dl 2.18.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1898,7 +1898,7 @@ dependencies = [ "smithay-client-toolkit 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "wayland-client 0.20.10 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "x11-dl 2.17.5 (registry+https://github.com/rust-lang/crates.io-index)", + "x11-dl 2.18.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1971,7 +1971,7 @@ dependencies = [ [[package]] name = "x11-dl" -version = "2.17.5" +version = "2.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2221,7 +2221,7 @@ dependencies = [ "checksum winit 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ec43db5991cc509f5b0c68cb0a0d3614f697c888999990a186a2e895c7f723c0" "checksum ws 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ec91ea61b83ce033c43c06c52ddc7532f465c0153281610d44c58b74083aee1a" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -"checksum x11-dl 2.17.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3235540540fde1ae074c8df49054166c0e070407f1c6e1ee17b8c87c2c7bcc7d" +"checksum x11-dl 2.18.3 (registry+https://github.com/rust-lang/crates.io-index)" = "940586acb859ea05c53971ac231685799a7ec1dee66ac0bccc0e6ad96e06b4e3" "checksum xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c1cb601d29fe2c2ac60a2b2e5e293994d87a1f6fa9687a31a15270f909be9c2" "checksum xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5" "checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" diff --git a/webrender/src/platform/unix/font.rs b/webrender/src/platform/unix/font.rs index 87a6a94103..4e5ade14df 100644 --- a/webrender/src/platform/unix/font.rs +++ b/webrender/src/platform/unix/font.rs @@ -309,7 +309,7 @@ impl FontContext { } pub fn add_raw_font(&mut self, font_key: &FontKey, bytes: Arc>, index: u32) { - if !self.faces.contains_key(&font_key) { + if !self.faces.contains_key(font_key) { let file = FontFile::Data(bytes); if let Some(face) = new_ft_face(font_key, self.lib, &file, index) { self.faces.insert(*font_key, FontFace { file, index, face, mm_var: ptr::null_mut() }); @@ -318,7 +318,7 @@ impl FontContext { } pub fn add_native_font(&mut self, font_key: &FontKey, native_font_handle: NativeFontHandle) { - if !self.faces.contains_key(&font_key) { + if !self.faces.contains_key(font_key) { let cstr = CString::new(native_font_handle.path.as_os_str().to_str().unwrap()).unwrap(); let file = FontFile::Pathname(cstr); let index = native_font_handle.index; @@ -467,41 +467,57 @@ impl FontContext { } }; - if succeeded(result) { - result = unsafe { FT_Load_Glyph(face, glyph.index() as FT_UInt, load_flags as FT_Int32) }; - }; - - if succeeded(result) { - let slot = unsafe { (*face).glyph }; - assert!(slot != ptr::null_mut()); - - if font.flags.contains(FontInstanceFlags::SYNTHETIC_BOLD) { - unsafe { FT_GlyphSlot_Embolden(slot) }; - } + if !succeeded(result) { + error!("Unable to set glyph size and transform: {}", result); + //let raw_error = unsafe { FT_Error_String(result) }; + //if !raw_error.is_ptr() { + // error!("\tcode {:?}", CStr::from_ptr(raw_error)); + //} + debug!( + "\t[{}] for size {:?} and scale {:?} from font {:?}", + glyph.index(), + req_size, + (x_scale, y_scale), + font.font_key, + ); + return None; + } - let format = unsafe { (*slot).format }; - match format { - FT_Glyph_Format::FT_GLYPH_FORMAT_BITMAP => { - let y_size = unsafe { (*(*(*slot).face).size).metrics.y_ppem }; - Some((slot, req_size as f32 / y_size as f32)) - } - FT_Glyph_Format::FT_GLYPH_FORMAT_OUTLINE => Some((slot, scale as f32)), - _ => { - error!("Unsupported format"); - debug!("format={:?}", format); - None - } - } - } else { - error!("Unable to load glyph"); + result = unsafe { FT_Load_Glyph(face, glyph.index() as FT_UInt, load_flags as FT_Int32) }; + if !succeeded(result) { + error!("Unable to load glyph: {}", result); + //let raw_error = unsafe { FT_Error_String(result) }; + //if !raw_error.is_ptr() { + // error!("\tcode {:?}", CStr::from_ptr(raw_error)); + //} debug!( - "{} of size {:?} from font {:?}, {:?}", + "\t[{}] with flags {:?} from font {:?}", glyph.index(), - font.size, + load_flags, font.font_key, - result ); - None + return None; + } + + let slot = unsafe { (*face).glyph }; + assert!(slot != ptr::null_mut()); + + if font.flags.contains(FontInstanceFlags::SYNTHETIC_BOLD) { + unsafe { FT_GlyphSlot_Embolden(slot) }; + } + + let format = unsafe { (*slot).format }; + match format { + FT_Glyph_Format::FT_GLYPH_FORMAT_BITMAP => { + let y_size = unsafe { (*(*(*slot).face).size).metrics.y_ppem }; + Some((slot, req_size as f32 / y_size as f32)) + } + FT_Glyph_Format::FT_GLYPH_FORMAT_OUTLINE => Some((slot, scale as f32)), + _ => { + error!("Unsupported format"); + debug!("format={:?}", format); + None + } } } diff --git a/webrender/src/resource_cache.rs b/webrender/src/resource_cache.rs index 87315bf150..bc002a2c5e 100644 --- a/webrender/src/resource_cache.rs +++ b/webrender/src/resource_cache.rs @@ -1900,12 +1900,9 @@ pub fn get_blob_tiling( #[cfg(any(feature = "capture", feature = "replay"))] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -enum PlainFontTemplate { - Raw { - data: String, - index: u32, - }, - Native, +struct PlainFontTemplate { + data: String, + index: u32, } #[cfg(any(feature = "capture", feature = "replay"))] @@ -2116,13 +2113,24 @@ impl ResourceCache { .map(|(key, template)| { (*key, match *template { FontTemplate::Raw(ref arc, index) => { - PlainFontTemplate::Raw { + PlainFontTemplate { data: font_paths[&arc.as_ptr()].clone(), index, } } - FontTemplate::Native(_) => { - PlainFontTemplate::Native + #[cfg(not(target_os = "macos"))] + FontTemplate::Native(ref native) => { + PlainFontTemplate { + data: native.path.to_string_lossy().to_string(), + index: native.index, + } + } + #[cfg(target_os = "macos")] + FontTemplate::Native(ref native) => { + PlainFontTemplate { + data: native.0.postscript_name().to_string(), + index: 0, + } } }) }) @@ -2165,8 +2173,7 @@ impl ResourceCache { caches: Option, root: &PathBuf, ) -> Vec { - use std::fs::File; - use std::io::Read; + use std::{fs, path::Path}; info!("loading resource cache"); //TODO: instead of filling the local path to Arc map as we process @@ -2206,29 +2213,28 @@ impl ResourceCache { info!("\tfont templates..."); let native_font_replacement = Arc::new(NATIVE_FONT.to_vec()); for (key, plain_template) in resources.font_templates { - let template = match plain_template { - PlainFontTemplate::Raw { data, index } => { - let arc = match raw_map.entry(data) { - Entry::Occupied(e) => { - e.get().clone() - } - Entry::Vacant(e) => { - let mut buffer = Vec::new(); - File::open(root.join(e.key())) - .expect(&format!("Unable to open {}", e.key())) - .read_to_end(&mut buffer) - .unwrap(); - e.insert(Arc::new(buffer)) - .clone() + let arc = match raw_map.entry(plain_template.data) { + Entry::Occupied(e) => { + e.get().clone() + } + Entry::Vacant(e) => { + let file_path = if Path::new(e.key()).is_absolute() { + PathBuf::from(e.key()) + } else { + root.join(e.key()) + }; + let arc = match fs::read(file_path) { + Ok(buffer) => Arc::new(buffer), + Err(err) => { + error!("Unable to open font template {:?}: {:?}", e.key(), err); + Arc::clone(&native_font_replacement) } }; - FontTemplate::Raw(arc, index) - } - PlainFontTemplate::Native => { - FontTemplate::Raw(native_font_replacement.clone(), 0) + e.insert(arc).clone() } }; + let template = FontTemplate::Raw(arc, plain_template.index); self.glyph_rasterizer.add_font(key, template.clone()); res.font_templates.insert(key, template); } @@ -2248,11 +2254,8 @@ impl ResourceCache { e.get().clone() } Entry::Vacant(e) => { - let mut buffer = Vec::new(); - File::open(root.join(e.key())) - .expect(&format!("Unable to open {}", e.key())) - .read_to_end(&mut buffer) - .unwrap(); + let buffer = fs::read(root.join(e.key())) + .expect(&format!("Unable to open {}", e.key())); e.insert(Arc::new(buffer)) .clone() } diff --git a/wrench/script/wrench_with_renderer.py b/wrench/script/wrench_with_renderer.py new file mode 100755 index 0000000000..e2685e8476 --- /dev/null +++ b/wrench/script/wrench_with_renderer.py @@ -0,0 +1,52 @@ +#!/usr/bin/python + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import os +import subprocess +import sys + + +def is_linux(): + return sys.platform.startswith('linux') + + +if is_linux(): + requested_renderer = sys.argv[1] + renderer = "default" + + if requested_renderer == 'hardware': + pass + elif requested_renderer == 'llvmpipe': + os.environ["LIBGL_ALWAYS_SOFTWARE"] = "1" + os.environ["GALLIUM_DRIVER"] = "llvmpipe" + elif requested_renderer == 'softpipe': + os.environ["LIBGL_ALWAYS_SOFTWARE"] = "1" + os.environ["GALLIUM_DRIVER"] = "softpipe" + elif requested_renderer == 'swiftshader': + # TODO: Set up LD_LIBRARY_PATH to SwiftShader libraries automatically. + renderer = 'es3' + else: + print('Unknown renderer ' + requested_renderer) + sys.exit(1) + + cmd = [ + 'cargo', + 'run', + '--release', + '--', + '--no-block', # Run as fast as possible, for benchmarking + '--no-picture-caching', # Disable picture caching, to test rasterization performance + '--no-subpixel-aa', # SwiftShader doesn't support dual source blending + '--renderer', # Select GL3/ES3 renderer API + renderer, + 'load' + ] + + cmd += sys.argv[2:] + print('Running: ' + ' '.join(cmd)) + subprocess.check_call(cmd) +else: + print('This script is only supported on Linux') diff --git a/wrench/src/args.yaml b/wrench/src/args.yaml index da5733ffc9..0024a891c4 100644 --- a/wrench/src/args.yaml +++ b/wrench/src/args.yaml @@ -79,6 +79,14 @@ args: help: Dump the source of the specified shader takes_value: true global: true + - renderer: + long: renderer + help: Select rendering API (gl3, es3) + takes_value: true + global: true + - no_block: + long: no-block + help: Don't block on UI events - run event loop as fast as possible. subcommands: - png: diff --git a/wrench/src/main.rs b/wrench/src/main.rs index ad09f595c6..ba1b1a33cb 100644 --- a/wrench/src/main.rs +++ b/wrench/src/main.rs @@ -246,14 +246,12 @@ fn make_window( vsync: bool, events_loop: &Option, angle: bool, + gl_request: glutin::GlRequest, ) -> WindowWrapper { let wrapper = match *events_loop { Some(ref events_loop) => { let context_builder = glutin::ContextBuilder::new() - .with_gl(glutin::GlRequest::GlThenGles { - opengl_version: (3, 2), - opengles_version: (3, 0), - }) + .with_gl(gl_request) .with_vsync(vsync); let window_builder = winit::WindowBuilder::new() .with_title("WRench") @@ -484,8 +482,31 @@ fn main() { Some(winit::EventsLoop::new()) }; + let gl_request = match args.value_of("renderer") { + Some("es3") => { + glutin::GlRequest::Specific(glutin::Api::OpenGlEs, (3, 0)) + } + Some("gl3") => { + glutin::GlRequest::Specific(glutin::Api::OpenGl, (3, 2)) + } + Some("default") | None => { + glutin::GlRequest::GlThenGles { + opengl_version: (3, 2), + opengles_version: (3, 0), + } + } + Some(api) => { + panic!("Unexpected renderer string {}", api); + } + }; + let mut window = make_window( - size, dp_ratio, args.is_present("vsync"), &events_loop, args.is_present("angle"), + size, + dp_ratio, + args.is_present("vsync"), + &events_loop, + args.is_present("angle"), + gl_request, ); let dp_ratio = dp_ratio.unwrap_or(window.hidpi_factor()); let dim = window.get_inner_size(); @@ -528,7 +549,15 @@ fn main() { } if let Some(subargs) = args.subcommand_matches("show") { - render(&mut wrench, &mut window, size, &mut events_loop, subargs); + let no_block = args.is_present("no_block"); + render( + &mut wrench, + &mut window, + size, + &mut events_loop, + subargs, + no_block, + ); } else if let Some(subargs) = args.subcommand_matches("png") { let surface = match subargs.value_of("surface") { Some("screen") | None => png::ReadSurface::Screen, @@ -571,6 +600,7 @@ fn render<'a>( size: DeviceIntSize, events_loop: &mut Option, subargs: &clap::ArgMatches<'a>, + no_block: bool, ) { let input_path = subargs.value_of("INPUT").map(PathBuf::from).unwrap(); @@ -778,6 +808,11 @@ fn render<'a>( wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags)); do_render = true; } + VirtualKeyCode::Y => { + println!("Clearing all caches..."); + wrench.api.send_debug_cmd(DebugCommand::ClearCaches(ClearCache::all())); + do_frame = true; + } _ => {} } _ => {} @@ -830,7 +865,7 @@ fn render<'a>( // Block the thread until at least one event arrives // On Android, we are generally profiling when running // wrench, and don't want to block on UI events. - if cfg!(not(target_os = "android")) { + if !no_block && cfg!(not(target_os = "android")) { events_loop.run_forever(|event| { pending_events.push(event); winit::ControlFlow::Break diff --git a/wrench/src/wrench.rs b/wrench/src/wrench.rs index 72da49d583..f8164d23b9 100644 --- a/wrench/src/wrench.rs +++ b/wrench/src/wrench.rs @@ -598,6 +598,7 @@ impl Wrench { "T - Save CPU profile to a file", "C - Save a capture to captures/wrench/", "X - Do a hit test at the current cursor position", + "Y - Clear all caches", ]; let color_and_offset = [(ColorF::BLACK, 2.0), (ColorF::WHITE, 0.0)];