From b015e93dc5cff0e637a2d9e2aa9ff62612c45adf Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Thu, 31 Aug 2017 14:58:04 +1000 Subject: [PATCH] Update WR (font instance API). WR now has a concept of font templates and font instances. This makes the WR font interfaces closer to Cairo and Gecko, and also makes some future performance optimizations possible. A font template is the font family, and data backing the font. A font instance is a reference to a font template and per-instance options, such as font size, anti-aliasing settings etc. To update Servo in a minimally invasive way, I added a new font cache call, that creates a font instance. This means that when a font is created, and doesn't exist in the cache there are now two calls to the font cache thread. We could refactor the font cache to make this work in one call, which we should do in the future. However, refactoring the font cache is a large chunk of work by itself. The extra call is only when a font doesn't already exist in the font context cache, so it should have minimal performance impact. --- Cargo.lock | 56 +++++++++---------- components/gfx/font.rs | 4 +- components/gfx/font_cache_thread.rs | 77 ++++++++++++++++++-------- components/gfx/font_context.rs | 9 +-- components/gfx/text/text_run.rs | 2 +- components/layout/webrender_helpers.rs | 1 - components/servo/lib.rs | 2 +- tests/unit/gfx/font_cache_thread.rs | 39 ------------- tests/unit/gfx/lib.rs | 4 -- 9 files changed, 92 insertions(+), 102 deletions(-) delete mode 100644 tests/unit/gfx/font_cache_thread.rs diff --git a/Cargo.lock b/Cargo.lock index 7b84ce75070..5d7a3ee790f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -335,8 +335,8 @@ dependencies = [ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "offscreen_gl_context 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender 0.49.0 (git+https://github.com/servo/webrender)", - "webrender_api 0.49.0 (git+https://github.com/servo/webrender)", + "webrender 0.50.0 (git+https://github.com/servo/webrender)", + "webrender_api 0.50.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -352,7 +352,7 @@ dependencies = [ "offscreen_gl_context 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "servo_config 0.0.1", - "webrender_api 0.49.0 (git+https://github.com/servo/webrender)", + "webrender_api 0.50.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -503,8 +503,8 @@ dependencies = [ "servo_url 0.0.1", "style_traits 0.0.1", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender 0.49.0 (git+https://github.com/servo/webrender)", - "webrender_api 0.49.0 (git+https://github.com/servo/webrender)", + "webrender 0.50.0 (git+https://github.com/servo/webrender)", + "webrender_api 0.50.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -540,7 +540,7 @@ dependencies = [ "servo_remutex 0.0.1", "servo_url 0.0.1", "style_traits 0.0.1", - "webrender_api 0.49.0 (git+https://github.com/servo/webrender)", + "webrender_api 0.50.0 (git+https://github.com/servo/webrender)", "webvr_traits 0.0.1", ] @@ -816,7 +816,7 @@ dependencies = [ "servo_geometry 0.0.1", "servo_url 0.0.1", "style_traits 0.0.1", - "webrender_api 0.49.0 (git+https://github.com/servo/webrender)", + "webrender_api 0.50.0 (git+https://github.com/servo/webrender)", "x11 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1130,7 +1130,7 @@ dependencies = [ "truetype 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.49.0 (git+https://github.com/servo/webrender)", + "webrender_api 0.50.0 (git+https://github.com/servo/webrender)", "xi-unicode 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "xml5ever 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1211,7 +1211,7 @@ dependencies = [ "servo_url 0.0.1", "style_traits 0.0.1", "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.49.0 (git+https://github.com/servo/webrender)", + "webrender_api 0.50.0 (git+https://github.com/servo/webrender)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "x11 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1532,7 +1532,7 @@ dependencies = [ "style_traits 0.0.1", "unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.49.0 (git+https://github.com/servo/webrender)", + "webrender_api 0.50.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -1579,7 +1579,7 @@ dependencies = [ "servo_url 0.0.1", "style 0.0.1", "style_traits 0.0.1", - "webrender_api 0.49.0 (git+https://github.com/servo/webrender)", + "webrender_api 0.50.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -1594,7 +1594,7 @@ dependencies = [ "profile_traits 0.0.1", "script_traits 0.0.1", "servo_url 0.0.1", - "webrender_api 0.49.0 (git+https://github.com/servo/webrender)", + "webrender_api 0.50.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -1678,8 +1678,8 @@ dependencies = [ "style 0.0.1", "style_traits 0.0.1", "webdriver_server 0.0.1", - "webrender 0.49.0 (git+https://github.com/servo/webrender)", - "webrender_api 0.49.0 (git+https://github.com/servo/webrender)", + "webrender 0.50.0 (git+https://github.com/servo/webrender)", + "webrender_api 0.50.0 (git+https://github.com/servo/webrender)", "webvr 0.0.1", "webvr_traits 0.0.1", ] @@ -1872,7 +1872,7 @@ dependencies = [ "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.49.0 (git+https://github.com/servo/webrender)", + "webrender_api 0.50.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -1922,7 +1922,7 @@ dependencies = [ "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.49.0 (git+https://github.com/servo/webrender)", + "webrender_api 0.50.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -1979,7 +1979,7 @@ dependencies = [ "servo_url 0.0.1", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.49.0 (git+https://github.com/servo/webrender)", + "webrender_api 0.50.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -2591,7 +2591,7 @@ dependencies = [ "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "utf-8 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.49.0 (git+https://github.com/servo/webrender)", + "webrender_api 0.50.0 (git+https://github.com/servo/webrender)", "webvr_traits 0.0.1", "xml5ever 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2623,7 +2623,7 @@ dependencies = [ "servo_atoms 0.0.1", "servo_url 0.0.1", "style 0.0.1", - "webrender_api 0.49.0 (git+https://github.com/servo/webrender)", + "webrender_api 0.50.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -2666,7 +2666,7 @@ dependencies = [ "style_traits 0.0.1", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.49.0 (git+https://github.com/servo/webrender)", + "webrender_api 0.50.0 (git+https://github.com/servo/webrender)", "webvr_traits 0.0.1", ] @@ -3159,7 +3159,7 @@ dependencies = [ "selectors 0.19.0", "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "servo_atoms 0.0.1", - "webrender_api 0.49.0 (git+https://github.com/servo/webrender)", + "webrender_api 0.50.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -3539,8 +3539,8 @@ dependencies = [ [[package]] name = "webrender" -version = "0.49.0" -source = "git+https://github.com/servo/webrender#108405dd65004b13c41cd3a032d2750663d3f378" +version = "0.50.0" +source = "git+https://github.com/servo/webrender#eee6067ba4c9e3bb0edfe125919eee8163ba1de5" dependencies = [ "app_units 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3562,13 +3562,13 @@ dependencies = [ "rayon 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "thread_profiler 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.49.0 (git+https://github.com/servo/webrender)", + "webrender_api 0.50.0 (git+https://github.com/servo/webrender)", ] [[package]] name = "webrender_api" -version = "0.49.0" -source = "git+https://github.com/servo/webrender#108405dd65004b13c41cd3a032d2750663d3f378" +version = "0.50.0" +source = "git+https://github.com/servo/webrender#eee6067ba4c9e3bb0edfe125919eee8163ba1de5" dependencies = [ "app_units 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3987,8 +3987,8 @@ dependencies = [ "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff" "checksum webdriver 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d548aabf87411b1b4ba91fd07eacd8b238135c7131a452b8a9f6386209167e18" -"checksum webrender 0.49.0 (git+https://github.com/servo/webrender)" = "" -"checksum webrender_api 0.49.0 (git+https://github.com/servo/webrender)" = "" +"checksum webrender 0.50.0 (git+https://github.com/servo/webrender)" = "" +"checksum webrender_api 0.50.0 (git+https://github.com/servo/webrender)" = "" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum ws 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "04614a58714f3fd4a8b1da4bcae9f031c532d35988c3d39627619248113f8be8" diff --git a/components/gfx/font.rs b/components/gfx/font.rs index a7751e879a4..9c59f71fb0a 100644 --- a/components/gfx/font.rs +++ b/components/gfx/font.rs @@ -112,7 +112,7 @@ pub struct Font { shaper: Option, shape_cache: RefCell>>, glyph_advance_cache: RefCell>, - pub font_key: webrender_api::FontKey, + pub font_key: webrender_api::FontInstanceKey, } impl Font { @@ -121,7 +121,7 @@ impl Font { descriptor: FontTemplateDescriptor, requested_pt_size: Au, actual_pt_size: Au, - font_key: webrender_api::FontKey) -> Font { + font_key: webrender_api::FontInstanceKey) -> Font { let metrics = handle.metrics(); Font { handle: handle, diff --git a/components/gfx/font_cache_thread.rs b/components/gfx/font_cache_thread.rs index c58dfd131ed..bde03e78423 100644 --- a/components/gfx/font_cache_thread.rs +++ b/components/gfx/font_cache_thread.rs @@ -2,6 +2,7 @@ * 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/. */ +use app_units::Au; use font_template::{FontTemplate, FontTemplateDescriptor}; use fontsan; use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; @@ -36,7 +37,7 @@ struct FontTemplates { #[derive(Debug, Deserialize, Serialize)] pub struct FontTemplateInfo { pub font_template: Arc, - pub font_key: Option, + pub font_key: webrender_api::FontKey, } impl FontTemplates { @@ -106,6 +107,7 @@ impl FontTemplates { pub enum Command { GetFontTemplate(FontFamily, FontTemplateDescriptor, IpcSender), GetLastResortFontTemplate(FontTemplateDescriptor, IpcSender), + GetFontInstance(webrender_api::FontKey, Au, IpcSender), AddWebFont(LowercaseString, EffectiveSources, IpcSender<()>), AddDownloadedWebFont(LowercaseString, ServoUrl, Vec, IpcSender<()>), Exit(IpcSender<()>), @@ -127,8 +129,9 @@ struct FontCache { web_families: HashMap, font_context: FontContextHandle, core_resource_thread: CoreResourceThread, - webrender_api: Option, + webrender_api: webrender_api::RenderApi, webrender_fonts: HashMap, + font_instances: HashMap<(webrender_api::FontKey, Au), webrender_api::FontInstanceKey>, } fn populate_generic_fonts() -> HashMap { @@ -172,6 +175,25 @@ impl FontCache { let font_template = self.last_resort_font_template(&descriptor); let _ = result.send(Reply::GetFontTemplateReply(Some(font_template))); } + Command::GetFontInstance(font_key, size, result) => { + let webrender_api = &self.webrender_api; + + let instance_key = *self.font_instances + .entry((font_key, size)) + .or_insert_with(|| { + let key = webrender_api.generate_font_instance_key(); + let mut updates = webrender_api::ResourceUpdates::new(); + updates.add_font_instance(key, + font_key, + size, + None, + None); + webrender_api.update_resources(updates); + key + }); + + let _ = result.send(instance_key); + } Command::AddWebFont(family_name, sources, result) => { self.handle_add_web_font(family_name, sources, result); } @@ -342,22 +364,20 @@ impl FontCache { } fn get_font_template_info(&mut self, template: Arc) -> FontTemplateInfo { - let mut font_key = None; + let webrender_api = &self.webrender_api; + let webrender_fonts = &mut self.webrender_fonts; - if let Some(ref webrender_api) = self.webrender_api { - let webrender_fonts = &mut self.webrender_fonts; - font_key = Some(*webrender_fonts.entry(template.identifier.clone()).or_insert_with(|| { - let font_key = webrender_api.generate_font_key(); - let mut updates = webrender_api::ResourceUpdates::new(); - match (template.bytes_if_in_memory(), template.native_font()) { - (Some(bytes), _) => updates.add_raw_font(font_key, bytes, 0), - (None, Some(native_font)) => updates.add_native_font(font_key, native_font), - (None, None) => updates.add_raw_font(font_key, template.bytes().clone(), 0), - } - webrender_api.update_resources(updates); - font_key - })); - } + let font_key = *webrender_fonts.entry(template.identifier.clone()).or_insert_with(|| { + let font_key = webrender_api.generate_font_key(); + let mut updates = webrender_api::ResourceUpdates::new(); + match (template.bytes_if_in_memory(), template.native_font()) { + (Some(bytes), _) => updates.add_raw_font(font_key, bytes, 0), + (None, Some(native_font)) => updates.add_native_font(font_key, native_font), + (None, None) => updates.add_raw_font(font_key, template.bytes().clone(), 0), + } + webrender_api.update_resources(updates); + font_key + }); FontTemplateInfo { font_template: template, @@ -403,7 +423,7 @@ pub struct FontCacheThread { impl FontCacheThread { pub fn new(core_resource_thread: CoreResourceThread, - webrender_api: Option) -> FontCacheThread { + webrender_api: webrender_api::RenderApi) -> FontCacheThread { let (chan, port) = ipc::channel().unwrap(); let channel_to_self = chan.clone(); @@ -413,14 +433,15 @@ impl FontCacheThread { let mut cache = FontCache { port: port, - channel_to_self: channel_to_self, - generic_fonts: generic_fonts, + channel_to_self, + generic_fonts, local_families: HashMap::new(), web_families: HashMap::new(), font_context: FontContextHandle::new(), - core_resource_thread: core_resource_thread, - webrender_api: webrender_api, + core_resource_thread, + webrender_api, webrender_fonts: HashMap::new(), + font_instances: HashMap::new(), }; cache.refresh_local_families(); @@ -470,6 +491,18 @@ impl FontCacheThread { self.chan.send(Command::AddWebFont(LowercaseString::new(&family.name), sources, sender)).unwrap(); } + pub fn get_font_instance(&self, key: webrender_api::FontKey, size: Au) -> webrender_api::FontInstanceKey { + let (response_chan, response_port) = + ipc::channel().expect("failed to create IPC channel"); + self.chan.send(Command::GetFontInstance(key, size, response_chan)) + .expect("failed to send message to font cache thread"); + + let instance_key = response_port.recv() + .expect("failed to receive response to font request"); + + instance_key + } + pub fn exit(&self) { let (response_chan, response_port) = ipc::channel().unwrap(); self.chan.send(Command::Exit(response_chan)).expect("Couldn't send FontCacheThread exit message"); diff --git a/components/gfx/font_context.rs b/components/gfx/font_context.rs index 67214cf5e40..c21de4b2728 100644 --- a/components/gfx/font_context.rs +++ b/components/gfx/font_context.rs @@ -92,7 +92,9 @@ impl FontContext { template, Some(actual_pt_size))?; - Ok(Font::new(handle, variant, descriptor, pt_size, actual_pt_size, font_key)) + let font_instance_key = self.font_cache_thread + .get_font_instance(font_key, actual_pt_size); + Ok(Font::new(handle, variant, descriptor, pt_size, actual_pt_size, font_instance_key)) } fn expire_font_caches_if_necessary(&mut self) { @@ -166,8 +168,7 @@ impl FontContext { desc.clone(), style.font_size.0, style.font_variant_caps, - template_info.font_key - .expect("No font key present!")); + template_info.font_key); let font = match layout_font { Ok(layout_font) => { let layout_font = Rc::new(RefCell::new(layout_font)); @@ -212,7 +213,7 @@ impl FontContext { desc.clone(), style.font_size.0, style.font_variant_caps, - template_info.font_key.expect("No font key present!")); + template_info.font_key); match layout_font { Ok(layout_font) => { let layout_font = Rc::new(RefCell::new(layout_font)); diff --git a/components/gfx/text/text_run.rs b/components/gfx/text/text_run.rs index 05538a45b26..d34e4788cac 100644 --- a/components/gfx/text/text_run.rs +++ b/components/gfx/text/text_run.rs @@ -30,7 +30,7 @@ pub struct TextRun { pub font_template: Arc, pub actual_pt_size: Au, pub font_metrics: FontMetrics, - pub font_key: webrender_api::FontKey, + pub font_key: webrender_api::FontInstanceKey, /// The glyph runs that make up this text run. pub glyphs: Arc>, pub bidi_level: bidi::Level, diff --git a/components/layout/webrender_helpers.rs b/components/layout/webrender_helpers.rs index 6e5a774e283..32da4981dfc 100644 --- a/components/layout/webrender_helpers.rs +++ b/components/layout/webrender_helpers.rs @@ -288,7 +288,6 @@ impl WebRenderDisplayItemConverter for DisplayItem { &glyphs, item.text_run.font_key, item.text_color, - item.text_run.actual_pt_size, None); } } diff --git a/components/servo/lib.rs b/components/servo/lib.rs index cddc84707d0..ab623cf2c91 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -529,7 +529,7 @@ fn create_constellation(user_agent: Cow<'static, str>, time_profiler_chan.clone(), config_dir); let font_cache_thread = FontCacheThread::new(public_resource_threads.sender(), - Some(webrender_api_sender.create_api())); + webrender_api_sender.create_api()); let resource_sender = public_resource_threads.sender(); diff --git a/tests/unit/gfx/font_cache_thread.rs b/tests/unit/gfx/font_cache_thread.rs deleted file mode 100644 index e60ca8b9ba4..00000000000 --- a/tests/unit/gfx/font_cache_thread.rs +++ /dev/null @@ -1,39 +0,0 @@ -/* 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/. */ - -use cssparser::SourceLocation; -use gfx::font_cache_thread::FontCacheThread; -use ipc_channel::ipc; -use style::computed_values::font_family::{FamilyName, FamilyNameSyntax}; -use style::font_face::{FontFaceRuleData, Source}; - -#[test] -fn test_local_web_font() { - let (inp_chan, _) = ipc::channel().unwrap(); - let (out_chan, out_receiver) = ipc::channel().unwrap(); - let font_cache_thread = FontCacheThread::new(inp_chan, None); - let family_name = FamilyName { - name: From::from("test family"), - syntax: FamilyNameSyntax::Quoted, - }; - let variant_name = FamilyName { - name: From::from("test font face"), - syntax: FamilyNameSyntax::Quoted, - }; - let font_face_rule = FontFaceRuleData { - family: Some(family_name.clone()), - sources: Some(vec![Source::Local(variant_name)]), - source_location: SourceLocation { - line: 0, - column: 0, - }, - }; - - font_cache_thread.add_web_font( - family_name, - font_face_rule.font_face().unwrap().effective_sources(), - out_chan); - - assert_eq!(out_receiver.recv().unwrap(), ()); -} diff --git a/tests/unit/gfx/lib.rs b/tests/unit/gfx/lib.rs index a9b45bd93e8..9a5040b6fe1 100644 --- a/tests/unit/gfx/lib.rs +++ b/tests/unit/gfx/lib.rs @@ -2,10 +2,6 @@ * 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/. */ -extern crate cssparser; extern crate gfx; -extern crate ipc_channel; -extern crate style; -#[cfg(test)] mod font_cache_thread; #[cfg(test)] mod text_util;