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:
Glenn Watson 2015-04-20 13:34:26 +10:00
parent e278e5b9a2
commit d8aef7208e
33 changed files with 2785 additions and 1679 deletions

View file

@ -28,8 +28,7 @@ use gfx::display_list::{BLUR_INFLATION_FACTOR, OpaqueNode};
use gfx::text::glyph::CharIndex;
use gfx::text::text_run::{TextRun, TextRunSlice};
use msg::constellation_msg::{ConstellationChan, Msg, PipelineId, SubpageId};
use net_traits::image::holder::ImageHolder;
use net_traits::local_image_cache::LocalImageCache;
use net_traits::image::base::Image;
use rustc_serialize::{Encodable, Encoder};
use script_traits::UntrustedNodeAddress;
use std::borrow::ToOwned;
@ -297,7 +296,7 @@ impl CanvasFragmentInfo {
pub struct ImageFragmentInfo {
/// The image held within this fragment.
pub replaced_image_fragment_info: ReplacedImageFragmentInfo,
pub image: ImageHolder<UntrustedNodeAddress>,
pub image: Option<Arc<Image>>,
}
impl ImageFragmentInfo {
@ -306,8 +305,8 @@ impl ImageFragmentInfo {
/// FIXME(pcwalton): The fact that image fragments store the cache in the fragment makes little
/// sense to me.
pub fn new(node: &ThreadSafeLayoutNode,
image_url: Url,
local_image_cache: Arc<Mutex<LocalImageCache<UntrustedNodeAddress>>>)
url: Option<Url>,
layout_context: &LayoutContext)
-> ImageFragmentInfo {
fn convert_length(node: &ThreadSafeLayoutNode, name: &Atom) -> Option<Au> {
let element = node.as_element();
@ -316,32 +315,42 @@ impl ImageFragmentInfo {
.map(|pixels| Au::from_px(pixels))
}
let image = url.and_then(|url| layout_context.get_or_request_image(url));
ImageFragmentInfo {
replaced_image_fragment_info: ReplacedImageFragmentInfo::new(node,
convert_length(node, &atom!("width")),
convert_length(node, &atom!("height"))),
image: ImageHolder::new(image_url, local_image_cache)
image: image,
}
}
/// Returns the original inline-size of the image.
pub fn image_inline_size(&mut self) -> Au {
let size = self.image.get_size(self.replaced_image_fragment_info.for_node).unwrap_or(Size2D::zero());
Au::from_px(if self.replaced_image_fragment_info.writing_mode_is_vertical {
size.height
} else {
size.width
} as isize)
match self.image {
Some(ref image) => {
Au::from_px(if self.replaced_image_fragment_info.writing_mode_is_vertical {
image.height
} else {
image.width
} as isize)
}
None => Au(0)
}
}
/// Returns the original block-size of the image.
pub fn image_block_size(&mut self) -> Au {
let size = self.image.get_size(self.replaced_image_fragment_info.for_node).unwrap_or(Size2D::zero());
Au::from_px(if self.replaced_image_fragment_info.writing_mode_is_vertical {
size.width
} else {
size.height
} as isize)
match self.image {
Some(ref image) => {
Au::from_px(if self.replaced_image_fragment_info.writing_mode_is_vertical {
image.width
} else {
image.height
} as isize)
}
None => Au(0)
}
}
/// Tile an image