mirror of
https://github.com/servo/servo.git
synced 2025-08-15 18:35:33 +01:00
Incremental Style Recalc
This patch puts in the initial framework for incremental reflow. Nodes' styles are no longer recalculated unless the node has changed. I've been hacking on the general problem of incremental reflow for the past couple weeks, and I've yet to get a full implementation that actually passes all the reftests + wikipedia + cnn. Therefore, I'm going to try to land the different parts of it one by one. This patch only does incremental style recalc, without incremental flow construction, inline-size bubbling, reflow, or display lists. Those will be coming in that order as I finish them. At least with this strategy, I can land a working version of incremental reflow, even if not yet complete. r? @pcwalton
This commit is contained in:
parent
510f8a817f
commit
d12c6e7383
31 changed files with 641 additions and 424 deletions
|
@ -18,15 +18,16 @@ use url::Url;
|
|||
/// 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.
|
||||
#[deriving(Clone)]
|
||||
pub struct ImageHolder {
|
||||
pub struct ImageHolder<NodeAddress> {
|
||||
url: Url,
|
||||
image: Option<Arc<Box<Image>>>,
|
||||
cached_size: Size2D<int>,
|
||||
local_image_cache: Arc<Mutex<LocalImageCache>>,
|
||||
local_image_cache: Arc<Mutex<LocalImageCache<NodeAddress>>>,
|
||||
}
|
||||
|
||||
impl ImageHolder {
|
||||
pub fn new(url: Url, local_image_cache: Arc<Mutex<LocalImageCache>>) -> ImageHolder {
|
||||
impl<NodeAddress: Send> 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,
|
||||
|
@ -60,9 +61,9 @@ impl ImageHolder {
|
|||
}
|
||||
|
||||
/// Query and update the current image size.
|
||||
pub fn get_size(&mut self) -> Option<Size2D<int>> {
|
||||
pub fn get_size(&mut self, node_address: NodeAddress) -> Option<Size2D<int>> {
|
||||
debug!("get_size() {}", self.url.serialize());
|
||||
self.get_image().map(|img| {
|
||||
self.get_image(node_address).map(|img| {
|
||||
self.cached_size = Size2D(img.width as int,
|
||||
img.height as int);
|
||||
self.cached_size.clone()
|
||||
|
@ -74,7 +75,7 @@ impl ImageHolder {
|
|||
self.image.clone()
|
||||
}
|
||||
|
||||
pub fn get_image(&mut self) -> Option<Arc<Box<Image>>> {
|
||||
pub fn get_image(&mut self, node_address: NodeAddress) -> Option<Arc<Box<Image>>> {
|
||||
debug!("get_image() {}", self.url.serialize());
|
||||
|
||||
// If this is the first time we've called this function, load
|
||||
|
@ -83,7 +84,7 @@ impl ImageHolder {
|
|||
let port = {
|
||||
let val = self.local_image_cache.lock();
|
||||
let mut local_image_cache = val;
|
||||
local_image_cache.get_image(&self.url)
|
||||
local_image_cache.get_image(node_address, &self.url)
|
||||
};
|
||||
match port.recv() {
|
||||
ImageReady(image) => {
|
||||
|
@ -105,5 +106,8 @@ impl ImageHolder {
|
|||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn url(&self) -> &Url {
|
||||
&self.url
|
||||
}
|
||||
}
|
||||
|
|
|
@ -227,8 +227,8 @@ impl ImageCache {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_state(&self, url: Url) -> ImageState {
|
||||
match self.state_map.find(&url) {
|
||||
fn get_state(&self, url: &Url) -> ImageState {
|
||||
match self.state_map.find(url) {
|
||||
Some(state) => state.clone(),
|
||||
None => Init
|
||||
}
|
||||
|
@ -239,7 +239,7 @@ impl ImageCache {
|
|||
}
|
||||
|
||||
fn prefetch(&mut self, url: Url) {
|
||||
match self.get_state(url.clone()) {
|
||||
match self.get_state(&url) {
|
||||
Init => {
|
||||
let to_cache = self.chan.clone();
|
||||
let resource_task = self.resource_task.clone();
|
||||
|
@ -270,7 +270,7 @@ impl ImageCache {
|
|||
}
|
||||
|
||||
fn store_prefetched_image_data(&mut self, url: Url, data: Result<Vec<u8>, ()>) {
|
||||
match self.get_state(url.clone()) {
|
||||
match self.get_state(&url) {
|
||||
Prefetching(next_step) => {
|
||||
match data {
|
||||
Ok(data) => {
|
||||
|
@ -298,7 +298,7 @@ impl ImageCache {
|
|||
}
|
||||
|
||||
fn decode(&mut self, url: Url) {
|
||||
match self.get_state(url.clone()) {
|
||||
match self.get_state(&url) {
|
||||
Init => fail!("decoding image before prefetch"),
|
||||
|
||||
Prefetching(DoNotDecode) => {
|
||||
|
@ -338,7 +338,7 @@ impl ImageCache {
|
|||
|
||||
fn store_image(&mut self, url: Url, image: Option<Arc<Box<Image>>>) {
|
||||
|
||||
match self.get_state(url.clone()) {
|
||||
match self.get_state(&url) {
|
||||
Decoding => {
|
||||
match image {
|
||||
Some(image) => {
|
||||
|
@ -376,7 +376,7 @@ impl ImageCache {
|
|||
}
|
||||
|
||||
fn get_image(&self, url: Url, response: Sender<ImageResponseMsg>) {
|
||||
match self.get_state(url.clone()) {
|
||||
match self.get_state(&url) {
|
||||
Init => fail!("request for image before prefetch"),
|
||||
Prefetching(DoDecode) => response.send(ImageNotReady),
|
||||
Prefetching(DoNotDecode) | Prefetched(..) => fail!("request for image before decode"),
|
||||
|
@ -387,7 +387,7 @@ impl ImageCache {
|
|||
}
|
||||
|
||||
fn wait_for_image(&mut self, url: Url, response: Sender<ImageResponseMsg>) {
|
||||
match self.get_state(url.clone()) {
|
||||
match self.get_state(&url) {
|
||||
Init => fail!("request for image before prefetch"),
|
||||
|
||||
Prefetching(DoNotDecode) | Prefetched(..) => fail!("request for image before decode"),
|
||||
|
|
|
@ -16,19 +16,19 @@ use std::collections::hashmap::HashMap;
|
|||
use servo_util::task::spawn_named;
|
||||
use url::Url;
|
||||
|
||||
pub trait ImageResponder {
|
||||
fn respond(&self) -> proc(ImageResponseMsg):Send;
|
||||
pub trait ImageResponder<NodeAddress: Send> {
|
||||
fn respond(&self) -> proc(ImageResponseMsg, NodeAddress):Send;
|
||||
}
|
||||
|
||||
pub struct LocalImageCache {
|
||||
pub struct LocalImageCache<NodeAddress> {
|
||||
image_cache_task: ImageCacheTask,
|
||||
round_number: uint,
|
||||
on_image_available: Option<Box<ImageResponder+Send>>,
|
||||
on_image_available: Option<Box<ImageResponder<NodeAddress>+Send>>,
|
||||
state_map: HashMap<Url, ImageState>
|
||||
}
|
||||
|
||||
impl LocalImageCache {
|
||||
pub fn new(image_cache_task: ImageCacheTask) -> LocalImageCache {
|
||||
impl<NodeAddress: Send> LocalImageCache<NodeAddress> {
|
||||
pub fn new(image_cache_task: ImageCacheTask) -> LocalImageCache<NodeAddress> {
|
||||
LocalImageCache {
|
||||
image_cache_task: image_cache_task,
|
||||
round_number: 1,
|
||||
|
@ -46,10 +46,10 @@ struct ImageState {
|
|||
last_response: ImageResponseMsg
|
||||
}
|
||||
|
||||
impl LocalImageCache {
|
||||
impl<NodeAddress: Send> LocalImageCache<NodeAddress> {
|
||||
/// The local cache will only do a single remote request for a given
|
||||
/// URL in each 'round'. Layout should call this each time it begins
|
||||
pub fn next_round(&mut self, on_image_available: Box<ImageResponder+Send>) {
|
||||
pub fn next_round(&mut self, on_image_available: Box<ImageResponder<NodeAddress> + Send>) {
|
||||
self.round_number += 1;
|
||||
self.on_image_available = Some(on_image_available);
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ impl LocalImageCache {
|
|||
}
|
||||
|
||||
// FIXME: Should return a Future
|
||||
pub fn get_image(&mut self, url: &Url) -> Receiver<ImageResponseMsg> {
|
||||
pub fn get_image(&mut self, node_address: NodeAddress, url: &Url) -> Receiver<ImageResponseMsg> {
|
||||
{
|
||||
let round_number = self.round_number;
|
||||
let state = self.get_state(url);
|
||||
|
@ -127,12 +127,13 @@ impl LocalImageCache {
|
|||
// on the image to load and triggering layout
|
||||
let image_cache_task = self.image_cache_task.clone();
|
||||
assert!(self.on_image_available.is_some());
|
||||
let on_image_available: proc(ImageResponseMsg):Send = self.on_image_available.as_ref().unwrap().respond();
|
||||
let on_image_available: proc(ImageResponseMsg, NodeAddress):Send =
|
||||
self.on_image_available.as_ref().unwrap().respond();
|
||||
let url = (*url).clone();
|
||||
spawn_named("LocalImageCache", proc() {
|
||||
let (response_chan, response_port) = channel();
|
||||
image_cache_task.send(WaitForImage(url.clone(), response_chan));
|
||||
on_image_available(response_port.recv());
|
||||
image_cache_task.send(WaitForImage(url, response_chan));
|
||||
on_image_available(response_port.recv(), node_address);
|
||||
});
|
||||
}
|
||||
_ => ()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue