mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +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
|
@ -1,100 +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 image::base::Image;
|
||||
use image_cache_task::ImageResponseMsg;
|
||||
use local_image_cache::LocalImageCache;
|
||||
|
||||
use geom::size::Size2D;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use url::Url;
|
||||
|
||||
// FIXME: Nasty coupling here This will be a problem if we want to factor out image handling from
|
||||
// the network stack. This should probably be factored out into an interface and use dependency
|
||||
// injection.
|
||||
|
||||
/// A struct to store image data. The image will be loaded once the first time it is requested,
|
||||
/// and an Arc will be stored. Clones of this Arc are given out on demand.
|
||||
#[derive(Clone)]
|
||||
pub struct ImageHolder<NodeAddress> {
|
||||
url: Url,
|
||||
image: Option<Arc<Image>>,
|
||||
cached_size: Size2D<u32>,
|
||||
local_image_cache: Arc<Mutex<LocalImageCache<NodeAddress>>>,
|
||||
}
|
||||
|
||||
impl<NodeAddress: Send + 'static> ImageHolder<NodeAddress> {
|
||||
pub fn new(url: Url, local_image_cache: Arc<Mutex<LocalImageCache<NodeAddress>>>)
|
||||
-> ImageHolder<NodeAddress> {
|
||||
debug!("ImageHolder::new() {}", url.serialize());
|
||||
let holder = ImageHolder {
|
||||
url: url,
|
||||
image: None,
|
||||
cached_size: Size2D(0,0),
|
||||
local_image_cache: local_image_cache.clone(),
|
||||
};
|
||||
|
||||
// Tell the image cache we're going to be interested in this url
|
||||
// FIXME: These two messages must be sent to prep an image for use
|
||||
// but they are intended to be spread out in time. Ideally prefetch
|
||||
// should be done as early as possible and decode only once we
|
||||
// are sure that the image will be used.
|
||||
{
|
||||
let val = holder.local_image_cache.lock().unwrap();
|
||||
let mut local_image_cache = val;
|
||||
local_image_cache.prefetch(&holder.url);
|
||||
local_image_cache.decode(&holder.url);
|
||||
}
|
||||
|
||||
holder
|
||||
}
|
||||
|
||||
/// This version doesn't perform any computation, but may be stale w.r.t. newly-available image
|
||||
/// data that determines size.
|
||||
///
|
||||
/// The intent is that the impure version is used during layout when dimensions are used for
|
||||
/// computing layout.
|
||||
pub fn size(&self) -> Size2D<u32> {
|
||||
self.cached_size
|
||||
}
|
||||
|
||||
/// Query and update the current image size.
|
||||
pub fn get_size(&mut self, node_address: NodeAddress) -> Option<Size2D<u32>> {
|
||||
debug!("get_size() {}", self.url.serialize());
|
||||
self.get_image(node_address).map(|img| {
|
||||
self.cached_size = Size2D(img.width, img.height);
|
||||
self.cached_size.clone()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_image_if_present(&self) -> Option<Arc<Image>> {
|
||||
debug!("get_image_if_present() {}", self.url.serialize());
|
||||
self.image.clone()
|
||||
}
|
||||
|
||||
pub fn get_image(&mut self, node_address: NodeAddress) -> Option<Arc<Image>> {
|
||||
debug!("get_image() {}", self.url.serialize());
|
||||
|
||||
// If this is the first time we've called this function, load
|
||||
// the image and store it for the future
|
||||
if self.image.is_none() {
|
||||
let port = {
|
||||
let val = self.local_image_cache.lock().unwrap();
|
||||
let mut local_image_cache = val;
|
||||
local_image_cache.get_image(node_address, &self.url)
|
||||
};
|
||||
match port.recv().unwrap() {
|
||||
ImageResponseMsg::ImageReady(image) => self.image = Some(image),
|
||||
ImageResponseMsg::ImageNotReady => debug!("image not ready for {}", self.url.serialize()),
|
||||
ImageResponseMsg::ImageFailed => debug!("image decoding failed for {}", self.url.serialize()),
|
||||
}
|
||||
}
|
||||
|
||||
return self.image.clone();
|
||||
}
|
||||
|
||||
pub fn url(&self) -> &Url {
|
||||
&self.url
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue