mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Refactored image cache task - details below.
* Simpler image cache API for clients to use. * Significantly fewer threads. * One thread for image cache task (multiplexes commands, decoder threads and async resource requests). * 4 threads for decoder worker tasks. * Removed ReflowEvent hacks in script and layout tasks. * Image elements pass a Trusted<T> to image cache, which is used to dirty nodes via script task. Previous use of Untrusted addresses was unsafe. * Image requests such as background-image on layout / paint threads trigger repaint only rather than full reflow. * Add reflow batching for when multiple images load quickly. * Reduces the number of paints loading wikipedia from ~95 to ~35. * Reasonably simple to add proper prefetch support in a follow up PR. * Async loaded images always construct Image fragments now, instead of generic. * Image fragments support the image not being present. * Simpler implementation of synchronous image loading for reftests. * Removed image holder. * image.onload support. * image NaturalWidth and NaturalHeight support. * Updated WPT expectations.
This commit is contained in:
parent
e278e5b9a2
commit
d8aef7208e
33 changed files with 2785 additions and 1679 deletions
|
@ -38,7 +38,7 @@ use devtools_traits::{DevtoolsControlChan, TimelineMarker, TimelineMarkerType, T
|
|||
use msg::compositor_msg::ScriptListener;
|
||||
use msg::constellation_msg::{LoadData, PipelineId, SubpageId, ConstellationChan, WindowSizeData, WorkerId};
|
||||
use net_traits::ResourceTask;
|
||||
use net_traits::image_cache_task::ImageCacheTask;
|
||||
use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask};
|
||||
use net_traits::storage_task::{StorageTask, StorageType};
|
||||
use util::geometry::{self, Au, MAX_RECT};
|
||||
use util::opts;
|
||||
|
@ -67,18 +67,19 @@ use std::sync::mpsc::TryRecvError::{Empty, Disconnected};
|
|||
use time;
|
||||
|
||||
/// Extra information concerning the reason for reflowing.
|
||||
#[derive(Debug)]
|
||||
pub enum ReflowReason {
|
||||
CachedPageNeededReflow,
|
||||
FirstLoad,
|
||||
KeyEvent,
|
||||
MouseEvent,
|
||||
Query,
|
||||
ReceivedReflowEvent,
|
||||
Timer,
|
||||
Viewport,
|
||||
WindowResize,
|
||||
DOMContentLoaded,
|
||||
DocumentLoaded,
|
||||
ImageLoaded,
|
||||
}
|
||||
|
||||
#[dom_struct]
|
||||
|
@ -89,6 +90,7 @@ pub struct Window {
|
|||
console: MutNullableJS<Console>,
|
||||
navigator: MutNullableJS<Navigator>,
|
||||
image_cache_task: ImageCacheTask,
|
||||
image_cache_chan: ImageCacheChan,
|
||||
compositor: DOMRefCell<Box<ScriptListener+'static>>,
|
||||
browser_context: DOMRefCell<Option<BrowserContext>>,
|
||||
page: Rc<Page>,
|
||||
|
@ -160,6 +162,9 @@ pub struct Window {
|
|||
/// An enlarged rectangle around the page contents visible in the viewport, used
|
||||
/// to prevent creating display list items for content that is far away from the viewport.
|
||||
page_clip_rect: Cell<Rect<Au>>,
|
||||
|
||||
/// A counter of the number of pending reflows for this window.
|
||||
pending_reflow_count: Cell<u32>,
|
||||
}
|
||||
|
||||
impl Window {
|
||||
|
@ -179,6 +184,10 @@ impl Window {
|
|||
self.script_chan.clone()
|
||||
}
|
||||
|
||||
pub fn image_cache_chan(&self) -> ImageCacheChan {
|
||||
self.image_cache_chan.clone()
|
||||
}
|
||||
|
||||
pub fn get_next_worker_id(&self) -> WorkerId {
|
||||
let worker_id = self.next_worker_id.get();
|
||||
let WorkerId(id_num) = worker_id;
|
||||
|
@ -481,6 +490,8 @@ pub trait WindowHelpers {
|
|||
fn windowproxy_handler(self) -> WindowProxyHandler;
|
||||
fn get_next_subpage_id(self) -> SubpageId;
|
||||
fn layout_is_idle(self) -> bool;
|
||||
fn get_pending_reflow_count(self) -> u32;
|
||||
fn add_pending_reflow(self);
|
||||
fn set_resize_event(self, event: WindowSizeData);
|
||||
fn steal_resize_event(self) -> Option<WindowSizeData>;
|
||||
fn set_page_clip_rect_with_new_viewport(self, viewport: Rect<f32>) -> bool;
|
||||
|
@ -549,11 +560,9 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
|
|||
None => return,
|
||||
};
|
||||
|
||||
debug!("script: performing reflow for goal {:?}", goal);
|
||||
|
||||
let root: JSRef<Node> = NodeCast::from_ref(root);
|
||||
if query_type == ReflowQueryType::NoQuery && !root.get_has_dirty_descendants() {
|
||||
debug!("root has no dirty descendants; avoiding reflow");
|
||||
debug!("root has no dirty descendants; avoiding reflow (reason {:?})", reason);
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -562,6 +571,8 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
|
|||
None => return,
|
||||
};
|
||||
|
||||
debug!("script: performing reflow for goal {:?} reason {:?}", goal, reason);
|
||||
|
||||
if self.need_emit_timeline_marker(TimelineMarkerType::Reflow) {
|
||||
let marker = TimelineMarker::new("Reflow".to_owned(), TracingMetadata::IntervalStart);
|
||||
self.emit_timeline_marker(marker);
|
||||
|
@ -604,6 +615,8 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
|
|||
|
||||
self.join_layout();
|
||||
|
||||
self.pending_reflow_count.set(0);
|
||||
|
||||
if self.need_emit_timeline_marker(TimelineMarkerType::Reflow) {
|
||||
let marker = TimelineMarker::new("Reflow".to_owned(), TracingMetadata::IntervalEnd);
|
||||
self.emit_timeline_marker(marker);
|
||||
|
@ -745,6 +758,14 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
|
|||
port.is_none()
|
||||
}
|
||||
|
||||
fn get_pending_reflow_count(self) -> u32 {
|
||||
self.pending_reflow_count.get()
|
||||
}
|
||||
|
||||
fn add_pending_reflow(self) {
|
||||
self.pending_reflow_count.set(self.pending_reflow_count.get() + 1);
|
||||
}
|
||||
|
||||
fn set_resize_event(self, event: WindowSizeData) {
|
||||
self.resize_event.set(Some(event));
|
||||
}
|
||||
|
@ -828,6 +849,7 @@ impl Window {
|
|||
pub fn new(js_context: Rc<Cx>,
|
||||
page: Rc<Page>,
|
||||
script_chan: Box<ScriptChan+Send>,
|
||||
image_cache_chan: ImageCacheChan,
|
||||
control_chan: ScriptControlChan,
|
||||
compositor: Box<ScriptListener+'static>,
|
||||
image_cache_task: ImageCacheTask,
|
||||
|
@ -850,6 +872,7 @@ impl Window {
|
|||
let win = box Window {
|
||||
eventtarget: EventTarget::new_inherited(EventTargetTypeId::Window),
|
||||
script_chan: script_chan,
|
||||
image_cache_chan: image_cache_chan,
|
||||
control_chan: control_chan,
|
||||
console: Default::default(),
|
||||
compositor: DOMRefCell::new(compositor),
|
||||
|
@ -882,6 +905,7 @@ impl Window {
|
|||
layout_rpc: layout_rpc,
|
||||
layout_join_port: DOMRefCell::new(None),
|
||||
window_size: Cell::new(window_size),
|
||||
pending_reflow_count: Cell::new(0),
|
||||
|
||||
devtools_marker_sender: RefCell::new(None),
|
||||
devtools_markers: RefCell::new(HashSet::new()),
|
||||
|
@ -929,12 +953,12 @@ fn debug_reflow_events(goal: &ReflowGoal, query_type: &ReflowQueryType, reason:
|
|||
ReflowReason::KeyEvent => "\tKeyEvent",
|
||||
ReflowReason::MouseEvent => "\tMouseEvent",
|
||||
ReflowReason::Query => "\tQuery",
|
||||
ReflowReason::ReceivedReflowEvent => "\tReceivedReflowEvent",
|
||||
ReflowReason::Timer => "\tTimer",
|
||||
ReflowReason::Viewport => "\tViewport",
|
||||
ReflowReason::WindowResize => "\tWindowResize",
|
||||
ReflowReason::DOMContentLoaded => "\tDOMContentLoaded",
|
||||
ReflowReason::DocumentLoaded => "\tDocumentLoaded",
|
||||
ReflowReason::ImageLoaded => "\tImageLoaded",
|
||||
});
|
||||
|
||||
println!("{}", debug_msg);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue