diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2016-02-19 00:54:06 +0530 |
---|---|---|
committer | bors-servo <lbergstrom+bors@mozilla.com> | 2016-02-19 00:54:06 +0530 |
commit | ab07b06823ea9748a6091aee2281495f86f00bce (patch) | |
tree | 2dd06ac4834d5bc4bcba6e4ada3aab12bb2c12d9 /components/gfx | |
parent | fe70efe07f6d72665f10c752884e5705d5bdc600 (diff) | |
parent | c0531c312fdb0783e4d121b4c2d7f15d4f5cdc1f (diff) | |
download | servo-ab07b06823ea9748a6091aee2281495f86f00bce.tar.gz servo-ab07b06823ea9748a6091aee2281495f86f00bce.zip |
Auto merge of #9589 - glennw:webrender, r=pcwalton
Add WebRender integration to Servo.
WebRender is an experimental GPU accelerated rendering backend for Servo.
The WebRender backend can be specified by running Servo with the -w option (otherwise the default rendering backend will be used).
WebRender has many bugs, and missing features - but it is usable to browse most websites - please report any WebRender specific rendering bugs you encounter!
<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.svg" height="40" alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/9589)
<!-- Reviewable:end -->
Diffstat (limited to 'components/gfx')
-rw-r--r-- | components/gfx/Cargo.toml | 3 | ||||
-rw-r--r-- | components/gfx/display_list/mod.rs | 37 | ||||
-rw-r--r-- | components/gfx/font.rs | 2 | ||||
-rw-r--r-- | components/gfx/font_cache_thread.rs | 55 | ||||
-rw-r--r-- | components/gfx/font_context.rs | 31 | ||||
-rw-r--r-- | components/gfx/lib.rs | 1 | ||||
-rw-r--r-- | components/gfx/platform/freetype/font_template.rs | 19 | ||||
-rw-r--r-- | components/gfx/platform/macos/font_template.rs | 36 | ||||
-rw-r--r-- | components/gfx/text/text_run.rs | 3 |
9 files changed, 163 insertions, 24 deletions
diff --git a/components/gfx/Cargo.toml b/components/gfx/Cargo.toml index b9e577d3e90..58863a275c1 100644 --- a/components/gfx/Cargo.toml +++ b/components/gfx/Cargo.toml @@ -69,6 +69,9 @@ features = ["plugins"] [dependencies.ipc-channel] git = "https://github.com/servo/ipc-channel" +[dependencies.webrender_traits] +git = "https://github.com/glennw/webrender_traits" + [target.x86_64-apple-darwin.dependencies] core-foundation = "0.2" core-graphics = "0.2" diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index f3aad7848c7..5b0e3935904 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -45,6 +45,7 @@ use util::linked_list::prepend_from; use util::opts; use util::print_tree::PrintTree; use util::range::Range; +use webrender_traits::WebGLContextId; pub use style::dom::OpaqueNode; @@ -641,7 +642,10 @@ impl StackingContext { layer_info: layer_info, last_child_layer_info: None, }; - StackingContextLayerCreator::add_layers_to_preserve_drawing_order(&mut stacking_context); + // webrender doesn't care about layers in the display list - it's handled internally. + if !opts::get().use_webrender { + StackingContextLayerCreator::add_layers_to_preserve_drawing_order(&mut stacking_context); + } stacking_context } @@ -681,7 +685,8 @@ impl StackingContext { // TODO(gw): This is a hack to avoid running the DL optimizer // on 3d transformed tiles. We should have a better solution // than just disabling the opts here. - if paint_context.layer_kind == LayerKind::HasTransform { + if paint_context.layer_kind == LayerKind::HasTransform || + opts::get().use_webrender { // webrender takes care of all culling via aabb tree! self.draw_into_context(&self.display_list, paint_context, &transform, @@ -775,6 +780,9 @@ struct StackingContextLayerCreator { impl StackingContextLayerCreator { fn new() -> StackingContextLayerCreator { + // webrender doesn't care about layers in the display list - it's handled internally. + debug_assert!(!opts::get().use_webrender); + StackingContextLayerCreator { display_list_for_next_layer: None, next_layer_info: None, @@ -969,6 +977,7 @@ pub enum DisplayItem { SolidColorClass(Box<SolidColorDisplayItem>), TextClass(Box<TextDisplayItem>), ImageClass(Box<ImageDisplayItem>), + WebGLClass(Box<WebGLDisplayItem>), BorderClass(Box<BorderDisplayItem>), GradientClass(Box<GradientDisplayItem>), LineClass(Box<LineDisplayItem>), @@ -976,6 +985,7 @@ pub enum DisplayItem { StackingContextClass(Arc<StackingContext>), LayeredItemClass(Box<LayeredItem>), NoopClass(Box<BaseDisplayItem>), + IframeClass(Box<IframeDisplayItem>), } /// Information common to all display items. @@ -1236,6 +1246,20 @@ pub struct ImageDisplayItem { pub image_rendering: image_rendering::T, } +#[derive(Clone, HeapSizeOf, Deserialize, Serialize)] +pub struct WebGLDisplayItem { + pub base: BaseDisplayItem, + #[ignore_heap_size_of = "Defined in webrender_traits"] + pub context_id: WebGLContextId, +} + + +/// Paints an iframe. +#[derive(Clone, HeapSizeOf, Deserialize, Serialize)] +pub struct IframeDisplayItem { + pub base: BaseDisplayItem, + pub iframe: PipelineId, +} /// Paints a gradient. #[derive(Clone, Deserialize, HeapSizeOf, Serialize)] @@ -1450,6 +1474,10 @@ impl DisplayItem { image_item.image_rendering.clone()); } + DisplayItem::WebGLClass(_) => { + panic!("Shouldn't be here, WebGL display items are created just with webrender"); + } + DisplayItem::BorderClass(ref border) => { paint_context.draw_border(&border.base.bounds, &border.border_widths, @@ -1499,6 +1527,7 @@ impl DisplayItem { DisplayItem::LayeredItemClass(_) => panic!("Found layered item during drawing."), DisplayItem::NoopClass(_) => { } + DisplayItem::IframeClass(..) => {} } } @@ -1507,6 +1536,7 @@ impl DisplayItem { DisplayItem::SolidColorClass(ref solid_color) => Some(&solid_color.base), DisplayItem::TextClass(ref text) => Some(&text.base), DisplayItem::ImageClass(ref image_item) => Some(&image_item.base), + DisplayItem::WebGLClass(ref webgl_item) => Some(&webgl_item.base), DisplayItem::BorderClass(ref border) => Some(&border.base), DisplayItem::GradientClass(ref gradient) => Some(&gradient.base), DisplayItem::LineClass(ref line) => Some(&line.base), @@ -1514,6 +1544,7 @@ impl DisplayItem { DisplayItem::LayeredItemClass(ref layered_item) => layered_item.item.base(), DisplayItem::NoopClass(ref base_item) => Some(base_item), DisplayItem::StackingContextClass(_) => None, + DisplayItem::IframeClass(ref iframe) => Some(&iframe.base), } } @@ -1563,6 +1594,7 @@ impl fmt::Debug for DisplayItem { solid_color.color.a), DisplayItem::TextClass(_) => "Text".to_owned(), DisplayItem::ImageClass(_) => "Image".to_owned(), + DisplayItem::WebGLClass(_) => "WebGL".to_owned(), DisplayItem::BorderClass(_) => "Border".to_owned(), DisplayItem::GradientClass(_) => "Gradient".to_owned(), DisplayItem::LineClass(_) => "Line".to_owned(), @@ -1571,6 +1603,7 @@ impl fmt::Debug for DisplayItem { DisplayItem::LayeredItemClass(ref layered_item) => format!("LayeredItem({:?})", layered_item.item), DisplayItem::NoopClass(_) => "Noop".to_owned(), + DisplayItem::IframeClass(_) => "Iframe".to_owned(), }, self.bounds(), ) diff --git a/components/gfx/font.rs b/components/gfx/font.rs index bb9ff7b3d45..8e5a80939ab 100644 --- a/components/gfx/font.rs +++ b/components/gfx/font.rs @@ -23,6 +23,7 @@ use text::shaping::ShaperMethods; use time; use unicode_script::Script; use util::cache::HashCache; +use webrender_traits; static TEXT_SHAPING_PERFORMANCE_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; @@ -100,6 +101,7 @@ pub struct Font { pub shaper: Option<Shaper>, pub shape_cache: HashCache<ShapeCacheEntry, Arc<GlyphStore>>, pub glyph_advance_cache: HashCache<u32, FractionalPixel>, + pub font_key: Option<webrender_traits::FontKey>, } bitflags! { diff --git a/components/gfx/font_cache_thread.rs b/components/gfx/font_cache_thread.rs index 6a2b5b4a033..89eefe9205b 100644 --- a/components/gfx/font_cache_thread.rs +++ b/components/gfx/font_cache_thread.rs @@ -24,12 +24,19 @@ use url::Url; use util::prefs; use util::str::LowercaseString; use util::thread::spawn_named; +use webrender_traits; /// A list of font templates that make up a given font family. struct FontTemplates { templates: Vec<FontTemplate>, } +#[derive(Serialize, Deserialize, Debug)] +pub struct FontTemplateInfo { + pub font_template: Arc<FontTemplateData>, + pub font_key: Option<webrender_traits::FontKey>, +} + impl FontTemplates { fn new() -> FontTemplates { FontTemplates { @@ -73,7 +80,8 @@ impl FontTemplates { } } - let template = FontTemplate::new(identifier, maybe_data); + let template = FontTemplate::new(identifier, + maybe_data); self.templates.push(template); } } @@ -91,7 +99,7 @@ pub enum Command { /// Reply messages sent from the font cache thread to the FontContext caller. #[derive(Deserialize, Serialize, Debug)] pub enum Reply { - GetFontTemplateReply(Option<Arc<FontTemplateData>>), + GetFontTemplateReply(Option<FontTemplateInfo>), } /// The font cache thread itself. It maintains a list of reference counted @@ -104,6 +112,8 @@ struct FontCache { web_families: HashMap<LowercaseString, FontTemplates>, font_context: FontContextHandle, resource_thread: ResourceThread, + webrender_api: Option<webrender_traits::RenderApi>, + webrender_fonts: HashMap<Atom, webrender_traits::FontKey>, } fn populate_generic_fonts() -> HashMap<FontFamily, LowercaseString> { @@ -285,24 +295,46 @@ impl FontCache { } } + fn get_font_template_info(&mut self, template: Arc<FontTemplateData>) -> FontTemplateInfo { + let webrender_fonts = &mut self.webrender_fonts; + let font_key = self.webrender_api.as_ref().map(|webrender_api| { + *webrender_fonts.entry(template.identifier.clone()).or_insert_with(|| { + match (template.bytes_if_in_memory(), template.native_font()) { + (Some(bytes), _) => webrender_api.add_raw_font(bytes), + (None, Some(native_font)) => webrender_api.add_native_font(native_font), + (None, None) => webrender_api.add_raw_font(template.bytes().clone()), + } + }) + }); + + FontTemplateInfo { + font_template: template, + font_key: font_key, + } + } + fn find_font_template(&mut self, family: &FontFamily, desc: &FontTemplateDescriptor) - -> Option<Arc<FontTemplateData>> { - self.find_font_in_web_family(family, desc) + -> Option<FontTemplateInfo> { + let template = self.find_font_in_web_family(family, desc) .or_else(|| { let transformed_family = self.transform_family(family); self.find_font_in_local_family(&transformed_family, desc) - }) + }); + + template.map(|template| { + self.get_font_template_info(template) + }) } fn last_resort_font_template(&mut self, desc: &FontTemplateDescriptor) - -> Arc<FontTemplateData> { + -> FontTemplateInfo { let last_resort = last_resort_font_families(); for family in &last_resort { let family = LowercaseString::new(family); let maybe_font_in_family = self.find_font_in_local_family(&family, desc); if let Some(family) = maybe_font_in_family { - return family; + return self.get_font_template_info(family) } } @@ -318,7 +350,8 @@ pub struct FontCacheThread { } impl FontCacheThread { - pub fn new(resource_thread: ResourceThread) -> FontCacheThread { + pub fn new(resource_thread: ResourceThread, + webrender_api: Option<webrender_traits::RenderApi>) -> FontCacheThread { let (chan, port) = ipc::channel().unwrap(); let channel_to_self = chan.clone(); @@ -334,6 +367,8 @@ impl FontCacheThread { web_families: HashMap::new(), font_context: FontContextHandle::new(), resource_thread: resource_thread, + webrender_api: webrender_api, + webrender_fonts: HashMap::new(), }; cache.refresh_local_families(); @@ -346,7 +381,7 @@ impl FontCacheThread { } pub fn find_font_template(&self, family: FontFamily, desc: FontTemplateDescriptor) - -> Option<Arc<FontTemplateData>> { + -> Option<FontTemplateInfo> { let (response_chan, response_port) = ipc::channel().unwrap(); self.chan.send(Command::GetFontTemplate(family, desc, response_chan)).unwrap(); @@ -361,7 +396,7 @@ impl FontCacheThread { } pub fn last_resort_font_template(&self, desc: FontTemplateDescriptor) - -> Arc<FontTemplateData> { + -> FontTemplateInfo { let (response_chan, response_port) = ipc::channel().unwrap(); self.chan.send(Command::GetLastResortFontTemplate(desc, response_chan)).unwrap(); diff --git a/components/gfx/font_context.rs b/components/gfx/font_context.rs index 8262b0d15fb..7cb95e6fc54 100644 --- a/components/gfx/font_context.rs +++ b/components/gfx/font_context.rs @@ -28,6 +28,7 @@ use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; use string_cache::Atom; use style::computed_values::{font_style, font_variant}; use util::cache::HashCache; +use webrender_traits; #[cfg(any(target_os = "linux", target_os = "android", target_os = "windows"))] fn create_scaled_font(template: &Arc<FontTemplateData>, pt_size: Au) -> ScaledFont { @@ -105,9 +106,12 @@ impl FontContext { } /// Create a font for use in layout calculations. - fn create_layout_font(&self, template: Arc<FontTemplateData>, - descriptor: FontTemplateDescriptor, pt_size: Au, - variant: font_variant::T) -> Result<Font, ()> { + fn create_layout_font(&self, + template: Arc<FontTemplateData>, + descriptor: FontTemplateDescriptor, + pt_size: Au, + variant: font_variant::T, + font_key: Option<webrender_traits::FontKey>) -> Result<Font, ()> { // TODO: (Bug #3463): Currently we only support fake small-caps // painting. We should also support true small-caps (where the // font supports it) in the future. @@ -133,6 +137,7 @@ impl FontContext { metrics: metrics, shape_cache: HashCache::new(), glyph_advance_cache: HashCache::new(), + font_key: font_key, } }) } @@ -201,14 +206,15 @@ impl FontContext { } if !cache_hit { - let font_template = self.font_cache_thread.find_font_template(family.clone(), - desc.clone()); - match font_template { - Some(font_template) => { - let layout_font = self.create_layout_font(font_template, + let template_info = self.font_cache_thread.find_font_template(family.clone(), + desc.clone()); + match template_info { + Some(template_info) => { + let layout_font = self.create_layout_font(template_info.font_template, desc.clone(), style.font_size, - style.font_variant); + style.font_variant, + template_info.font_key); let font = match layout_font { Ok(layout_font) => { let layout_font = Rc::new(RefCell::new(layout_font)); @@ -250,11 +256,12 @@ impl FontContext { } if !cache_hit { - let font_template = self.font_cache_thread.last_resort_font_template(desc.clone()); - let layout_font = self.create_layout_font(font_template, + let template_info = self.font_cache_thread.last_resort_font_template(desc.clone()); + let layout_font = self.create_layout_font(template_info.font_template, desc.clone(), style.font_size, - style.font_variant); + style.font_variant, + template_info.font_key); match layout_font { Ok(layout_font) => { let layout_font = Rc::new(RefCell::new(layout_font)); diff --git a/components/gfx/lib.rs b/components/gfx/lib.rs index 4d17ad41cb1..cb2576dba5c 100644 --- a/components/gfx/lib.rs +++ b/components/gfx/lib.rs @@ -75,6 +75,7 @@ extern crate unicode_script; extern crate url; #[macro_use] extern crate util; +extern crate webrender_traits; pub use paint_context::PaintContext; diff --git a/components/gfx/platform/freetype/font_template.rs b/components/gfx/platform/freetype/font_template.rs index 30f4ffd5437..55a530a7050 100644 --- a/components/gfx/platform/freetype/font_template.rs +++ b/components/gfx/platform/freetype/font_template.rs @@ -5,6 +5,7 @@ use std::fs::File; use std::io::Read; use string_cache::Atom; +use webrender_traits::NativeFontHandle; /// Platform specific font representation for Linux. /// The identifier is an absolute path, and the bytes @@ -36,4 +37,22 @@ impl FontTemplateData { identifier: identifier, } } + + /// Returns a clone of the data in this font. This may be a hugely expensive + /// operation (depending on the platform) which performs synchronous disk I/O + /// and should never be done lightly. + pub fn bytes(&self) -> Vec<u8> { + self.bytes.clone() + } + + /// Returns a clone of the bytes in this font if they are in memory. This function never + /// performs disk I/O. + pub fn bytes_if_in_memory(&self) -> Option<Vec<u8>> { + Some(self.bytes()) + } + + /// Returns the native font that underlies this font template, if applicable. + pub fn native_font(&self) -> Option<NativeFontHandle> { + None + } } diff --git a/components/gfx/platform/macos/font_template.rs b/components/gfx/platform/macos/font_template.rs index d6ee6b9f3f0..f15527e6a9f 100644 --- a/components/gfx/platform/macos/font_template.rs +++ b/components/gfx/platform/macos/font_template.rs @@ -9,9 +9,12 @@ use core_text::font::CTFont; use serde::de::{Error, Visitor}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::borrow::ToOwned; +use std::fs::File; +use std::io::Read; use std::ops::Deref; use std::sync::Mutex; use string_cache::Atom; +use url::Url; /// Platform specific font representation for mac. /// The identifier is a PostScript font name. The @@ -62,6 +65,39 @@ impl FontTemplateData { } ctfont.as_ref().map(|ctfont| (*ctfont).clone()) } + + /// Returns a clone of the data in this font. This may be a hugely expensive + /// operation (depending on the platform) which performs synchronous disk I/O + /// and should never be done lightly. + pub fn bytes(&self) -> Vec<u8> { + match self.bytes_if_in_memory() { + Some(font_data) => return font_data, + None => {} + } + + let path = Url::parse(&*self.ctfont() + .expect("No Core Text font available!") + .url() + .expect("No URL for Core Text font!") + .get_string() + .to_string()).expect("Couldn't parse Core Text font URL!") + .to_file_path() + .expect("Core Text font didn't name a path!"); + let mut bytes = Vec::new(); + File::open(path).expect("Couldn't open font file!").read_to_end(&mut bytes).unwrap(); + bytes + } + + /// Returns a clone of the bytes in this font if they are in memory. This function never + /// performs disk I/O. + pub fn bytes_if_in_memory(&self) -> Option<Vec<u8>> { + self.font_data.clone() + } + + /// Returns the native font that underlies this font template, if applicable. + pub fn native_font(&self) -> Option<CGFont> { + self.ctfont().map(|ctfont| ctfont.copy_to_CGFont()) + } } #[derive(Debug)] diff --git a/components/gfx/text/text_run.rs b/components/gfx/text/text_run.rs index 5b8acb5e1c5..5a3d086de7e 100644 --- a/components/gfx/text/text_run.rs +++ b/components/gfx/text/text_run.rs @@ -13,6 +13,7 @@ use std::sync::Arc; use text::glyph::{CharIndex, GlyphStore}; use util::range::Range; use util::vec::{Comparator, FullBinarySearchMethods}; +use webrender_traits; thread_local! { static INDEX_OF_FIRST_GLYPH_RUN_CACHE: Cell<Option<(*const TextRun, CharIndex, usize)>> = @@ -27,6 +28,7 @@ pub struct TextRun { pub font_template: Arc<FontTemplateData>, pub actual_pt_size: Au, pub font_metrics: FontMetrics, + pub font_key: Option<webrender_traits::FontKey>, /// The glyph runs that make up this text run. pub glyphs: Arc<Vec<GlyphRun>>, pub bidi_level: u8, @@ -177,6 +179,7 @@ impl<'a> TextRun { text: Arc::new(text), font_metrics: font.metrics.clone(), font_template: font.handle.template(), + font_key: font.font_key, actual_pt_size: font.actual_pt_size, glyphs: Arc::new(glyphs), bidi_level: bidi_level, |