mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
Update remove_tile, add automatic tile removal, fix tests for quadtree
This commit is contained in:
parent
3bb47133d9
commit
5468885545
3 changed files with 201 additions and 124 deletions
|
@ -305,12 +305,9 @@ impl CompositorTask {
|
|||
let ask_for_tiles: @fn() = || {
|
||||
match *quadtree {
|
||||
Some(ref mut quad) => {
|
||||
let valid = |tile: &~LayerBuffer| -> bool {
|
||||
tile.resolution == *world_zoom
|
||||
};
|
||||
let (tile_request, redisplay) = quad.get_tile_rects(Rect(Point2D(world_offset.x as int,
|
||||
world_offset.y as int),
|
||||
*window_size), valid, *world_zoom);
|
||||
*window_size), *world_zoom);
|
||||
|
||||
if !tile_request.is_empty() {
|
||||
match *render_chan {
|
||||
|
@ -415,10 +412,9 @@ impl CompositorTask {
|
|||
|
||||
NewLayer(new_size, tile_size) => {
|
||||
*page_size = Size2D(new_size.width as f32, new_size.height as f32);
|
||||
*quadtree = Some(Quadtree::new(0, 0,
|
||||
new_size.width.max(&(window_size.width as uint)),
|
||||
*quadtree = Some(Quadtree::new(new_size.width.max(&(window_size.width as uint)),
|
||||
new_size.height.max(&(window_size.height as uint)),
|
||||
tile_size));
|
||||
tile_size, Some(10000000u)));
|
||||
ask_for_tiles();
|
||||
|
||||
}
|
||||
|
@ -569,7 +565,7 @@ impl CompositorTask {
|
|||
composite();
|
||||
}
|
||||
|
||||
timer::sleep(&uv_global_loop::get(), 100);
|
||||
timer::sleep(&uv_global_loop::get(), 10);
|
||||
|
||||
// If a pinch-zoom happened recently, ask for tiles at the new resolution
|
||||
if *zoom_action && precise_time_s() - *zoom_time > 0.3 {
|
||||
|
|
|
@ -10,13 +10,16 @@ use geom::size::Size2D;
|
|||
use geom::rect::Rect;
|
||||
use std::uint::{div_ceil, next_power_of_two};
|
||||
use std::vec::build_sized;
|
||||
use std::util::replace;
|
||||
use gfx::render_task::BufferRequest;
|
||||
use servo_msg::compositor_msg::Tile;
|
||||
|
||||
/// Parent to all quadtree nodes. Stores variables needed at all levels. All method calls
|
||||
/// at this level are in pixel coordinates.
|
||||
pub struct Quadtree<T> {
|
||||
root: QuadtreeNode<T>,
|
||||
max_tile_size: uint,
|
||||
max_mem: Option<uint>,
|
||||
}
|
||||
|
||||
/// A node in the tree. All method calls at this level are in page coordinates.
|
||||
|
@ -31,6 +34,8 @@ struct QuadtreeNode<T> {
|
|||
quadrants: [Option<~QuadtreeNode<T>>, ..4],
|
||||
/// If this node is marked for rendering
|
||||
render_flag: bool,
|
||||
/// Combined size of self.tile and tiles of all descendants
|
||||
tile_mem: uint,
|
||||
}
|
||||
|
||||
priv enum Quadrant {
|
||||
|
@ -40,9 +45,12 @@ priv enum Quadrant {
|
|||
BR = 3,
|
||||
}
|
||||
|
||||
impl<T> Quadtree<T> {
|
||||
impl<T: Tile> Quadtree<T> {
|
||||
/// Public method to create a new Quadtree
|
||||
pub fn new(x: uint, y: uint, width: uint, height: uint, tile_size: uint) -> Quadtree<T> {
|
||||
/// Takes in the initial width and height of the space, a maximum tile size, and
|
||||
/// a maximum amount of memory. Tiles will be deleted if this memory is exceeded.
|
||||
/// Set max_mem to None to turn off automatic tile removal.
|
||||
pub fn new(width: uint, height: uint, tile_size: uint, max_mem: Option<uint>) -> Quadtree<T> {
|
||||
// Spaces must be squares and powers of 2, so expand the space until it is
|
||||
let longer = width.max(&height);
|
||||
let num_tiles = div_ceil(longer, tile_size);
|
||||
|
@ -52,12 +60,14 @@ impl<T> Quadtree<T> {
|
|||
Quadtree {
|
||||
root: QuadtreeNode {
|
||||
tile: None,
|
||||
origin: Point2D(x as f32, y as f32),
|
||||
origin: Point2D(0f32, 0f32),
|
||||
size: size as f32,
|
||||
quadrants: [None, None, None, None],
|
||||
render_flag: false,
|
||||
tile_mem: 0,
|
||||
},
|
||||
max_tile_size: tile_size,
|
||||
max_mem: max_mem,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,8 +80,22 @@ impl<T> Quadtree<T> {
|
|||
self.root.get_tile(x as f32 / scale, y as f32 / scale)
|
||||
}
|
||||
/// Add a tile associtated with a given pixel position and scale.
|
||||
/// If the tile pushes the total memory over its maximum, tiles will be removed
|
||||
/// until total memory is below the maximum again.
|
||||
pub fn add_tile(&mut self, x: uint, y: uint, scale: f32, tile: T) {
|
||||
self.root.add_tile(x as f32 / scale, y as f32 / scale, tile, self.max_tile_size as f32 / scale);
|
||||
match self.max_mem {
|
||||
Some(max) => {
|
||||
while self.root.tile_mem > max {
|
||||
let r = self.root.remove_tile(x as f32 / scale, y as f32 / scale);
|
||||
match r {
|
||||
(Some(_), _, _) => {}
|
||||
_ => fail!("Quadtree: No valid tiles to remove"),
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
/// Get the tile rect in screen and page coordinates for a given pixel position
|
||||
pub fn get_tile_rect(&mut self, x: uint, y: uint, scale: f32) -> BufferRequest {
|
||||
|
@ -83,21 +107,24 @@ impl<T> Quadtree<T> {
|
|||
}
|
||||
/// Ask a tile to be deleted from the quadtree. This tries to delete a tile that is far from the
|
||||
/// given point in pixel coordinates.
|
||||
pub fn remove_tile(&mut self, x: uint, y: uint, scale: f32) {
|
||||
self.root.remove_tile(x as f32 / scale, y as f32 / scale);
|
||||
pub fn remove_tile(&mut self, x: uint, y: uint, scale: f32) -> T {
|
||||
let r = self.root.remove_tile(x as f32 / scale, y as f32 / scale);
|
||||
match r {
|
||||
(Some(tile), _, _) => tile,
|
||||
_ => fail!("Quadtree: No valid tiles to remove"),
|
||||
}
|
||||
/// Given a window rect in pixel coordinates and a function to check if an existing tile is "valid"
|
||||
/// (i.e. is the correct resolution), this function returns a list of BufferRequests for tiles that
|
||||
}
|
||||
/// Given a window rect in pixel coordinates, this function returns a list of BufferRequests for tiles that
|
||||
/// need to be rendered. It also returns a boolean if the window needs to be redisplayed, i.e. if
|
||||
/// no tiles need to be rendered, but the display tree needs to be rebuilt. This can occur when the
|
||||
/// user zooms out and cached tiles need to be displayed on top of higher resolution tiles.
|
||||
pub fn get_tile_rects(&mut self, window: Rect<int>, valid: &fn(&T) -> bool, scale: f32) ->
|
||||
(~[BufferRequest], bool) {
|
||||
|
||||
self.root.get_tile_rects(Rect(Point2D(window.origin.x as f32 / scale, window.origin.y as f32 / scale),
|
||||
/// When this happens, higher resolution tiles will be removed from the quadtree.
|
||||
pub fn get_tile_rects(&mut self, window: Rect<int>, scale: f32) -> (~[BufferRequest], bool) {
|
||||
let (ret, redisplay, _) = self.root.get_tile_rects(
|
||||
Rect(Point2D(window.origin.x as f32 / scale, window.origin.y as f32 / scale),
|
||||
Size2D(window.size.width as f32 / scale, window.size.height as f32 / scale)),
|
||||
valid, scale, self.max_tile_size as f32 / scale)
|
||||
|
||||
scale, self.max_tile_size as f32 / scale);
|
||||
(ret, redisplay)
|
||||
}
|
||||
|
||||
/// Generate html to visualize the tree. For debugging purposes only.
|
||||
|
@ -108,7 +135,7 @@ impl<T> Quadtree<T> {
|
|||
|
||||
}
|
||||
|
||||
impl<T> QuadtreeNode<T> {
|
||||
impl<T: Tile> QuadtreeNode<T> {
|
||||
/// Private method to create new children
|
||||
fn new_child(x: f32, y: f32, size: f32) -> QuadtreeNode<T> {
|
||||
QuadtreeNode {
|
||||
|
@ -117,6 +144,7 @@ impl<T> QuadtreeNode<T> {
|
|||
size: size,
|
||||
quadrants: [None, None, None, None],
|
||||
render_flag: false,
|
||||
tile_mem: 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,7 +199,8 @@ impl<T> QuadtreeNode<T> {
|
|||
|
||||
/// Add a tile associated with a given position in page coords. If the tile size exceeds the maximum,
|
||||
/// the node will be split and the method will recurse until the tile size is within limits.
|
||||
fn add_tile(&mut self, x: f32, y: f32, tile: T, tile_size: f32) {
|
||||
/// Returns an the difference in tile memory between the new quadtree node and the old quadtree node.
|
||||
fn add_tile(&mut self, x: f32, y: f32, tile: T, tile_size: f32) -> int {
|
||||
debug!("Quadtree: Adding: (%?, %?) size:%?px", self.origin.x, self.origin.y, self.size);
|
||||
|
||||
if x >= self.origin.x + self.size || x < self.origin.x
|
||||
|
@ -180,6 +209,8 @@ impl<T> QuadtreeNode<T> {
|
|||
}
|
||||
|
||||
if self.size <= tile_size { // We are the child
|
||||
let old_size = self.tile_mem;
|
||||
self.tile_mem = tile.get_mem();
|
||||
self.tile = Some(tile);
|
||||
// FIXME: This should be inline, but currently won't compile
|
||||
let quads = [TL, TR, BL, BR];
|
||||
|
@ -187,10 +218,15 @@ impl<T> QuadtreeNode<T> {
|
|||
self.quadrants[*quad as int] = None;
|
||||
}
|
||||
self.render_flag = false;
|
||||
self.tile_mem as int - old_size as int
|
||||
} else { // Send tile to children
|
||||
let quad = self.get_quadrant(x, y);
|
||||
match self.quadrants[quad as int] {
|
||||
Some(ref mut child) => child.add_tile(x, y, tile, tile_size),
|
||||
Some(ref mut child) => {
|
||||
let delta = child.add_tile(x, y, tile, tile_size);
|
||||
self.tile_mem = (self.tile_mem as int + delta) as uint;
|
||||
delta
|
||||
}
|
||||
None => { // Make new child
|
||||
let new_size = self.size / 2.0;
|
||||
let new_x = match quad {
|
||||
|
@ -202,21 +238,10 @@ impl<T> QuadtreeNode<T> {
|
|||
BL | BR => self.origin.y + new_size,
|
||||
};
|
||||
let mut c = ~QuadtreeNode::new_child(new_x, new_y, new_size);
|
||||
c.add_tile(x, y, tile, tile_size);
|
||||
let delta = c.add_tile(x, y, tile, tile_size);
|
||||
self.tile_mem = (self.tile_mem as int + delta) as uint;
|
||||
self.quadrants[quad as int] = Some(c);
|
||||
|
||||
// If my tile is completely occluded, get rid of it.
|
||||
// FIXME: figure out a better way to determine if a tile is completely occluded
|
||||
// e.g. this alg doesn't work if a tile is covered by its grandchildren
|
||||
match self.quadrants {
|
||||
[Some(ref tl_child), Some(ref tr_child), Some(ref bl_child), Some(ref br_child)] => {
|
||||
match (&tl_child.tile, &tr_child.tile, &bl_child.tile, &br_child.tile) {
|
||||
(&Some(_), &Some(_), &Some(_), &Some(_)) => self.tile = None,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
delta
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -259,78 +284,81 @@ impl<T> QuadtreeNode<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Removes a tile that is far from the given input point in page coords. Returns true if the child
|
||||
/// has no tiles and needs to be deleted.
|
||||
fn remove_tile(&mut self, x: f32, y: f32) -> bool {
|
||||
match (&self.tile, &self.quadrants) {
|
||||
(&Some(_), &[None, None, None, None]) => {
|
||||
self.tile = None;
|
||||
return true;
|
||||
/// Removes a tile that is far from the given input point in page coords. Returns the tile removed,
|
||||
/// a bool that is true if the child has no tiles and needs to be deleted, and an integer showing the
|
||||
/// amount of memory changed by the operation. Unfortunately, the tile has to be an option, because
|
||||
/// there are occasionally leaves without tiles. However, the option will always be Some as long as
|
||||
/// this quadtree node or at least one of its descendants is not empty.
|
||||
fn remove_tile(&mut self, x: f32, y: f32) -> (Option<T>, bool, int) {
|
||||
if self.tile.is_some() {
|
||||
let ret = replace(&mut(self.tile), None);
|
||||
return match (ret, &self.quadrants) {
|
||||
(Some(tile), &[None, None, None, None]) => {
|
||||
let size = -(tile.get_mem() as int);
|
||||
(Some(tile), true, size)
|
||||
}
|
||||
(&Some(_), _) => {
|
||||
self.tile = None;
|
||||
return false;
|
||||
(Some(tile), _) => {
|
||||
let size = -(tile.get_mem() as int);
|
||||
(Some(tile), false, size)
|
||||
}
|
||||
_ => fail!("Quadtree: tile query failure in remove_tile"),
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// This is a hacky heuristic to find a tile that is "far away". There are better methods.
|
||||
let quad = self.get_quadrant(x, y);
|
||||
let my_child = match quad {
|
||||
TL => {
|
||||
match (&self.quadrants[BR as int], &self.quadrants[BL as int], &self.quadrants[TR as int]) {
|
||||
(&Some(_), _, _) => BR,
|
||||
(&None, &Some(_), _) => BL,
|
||||
(&None, &None, &Some(_)) => TR,
|
||||
_ => TL,
|
||||
}
|
||||
}
|
||||
TR => {
|
||||
match (&self.quadrants[BL as int], &self.quadrants[BR as int], &self.quadrants[TL as int]) {
|
||||
(&Some(_), _, _) => BL,
|
||||
(&None, &Some(_), _) => BR,
|
||||
(&None, &None, &Some(_)) => TL,
|
||||
_ => TR,
|
||||
}
|
||||
}
|
||||
BL => {
|
||||
match (&self.quadrants[TR as int], &self.quadrants[TL as int], &self.quadrants[BR as int]) {
|
||||
(&Some(_), _, _) => TR,
|
||||
(&None, &Some(_), _) => TL,
|
||||
(&None, &None, &Some(_)) => BR,
|
||||
_ => BL,
|
||||
}
|
||||
}
|
||||
BR => {
|
||||
match (&self.quadrants[TL as int], &self.quadrants[TR as int], &self.quadrants[BL as int]) {
|
||||
(&Some(_), _, _) => TL,
|
||||
(&None, &Some(_), _) => TR,
|
||||
(&None, &None, &Some(_)) => BL,
|
||||
_ => BR,
|
||||
}
|
||||
}
|
||||
let queue = match quad {
|
||||
TL => [BR, BL, TR, TL],
|
||||
TR => [BL, BR, TL, TR],
|
||||
BL => [TR, TL, BR, BL],
|
||||
BR => [TL, TR, BL, BR],
|
||||
};
|
||||
|
||||
match self.quadrants[my_child as int] {
|
||||
Some(ref mut child) if !child.remove_tile(x, y) => {
|
||||
return false;
|
||||
}
|
||||
Some(_) => {} // fall through
|
||||
None => fail!("Quadtree: child query failure"),
|
||||
let mut del_quad: Option<Quadrant> = None;
|
||||
let mut ret = (None, false, 0);
|
||||
|
||||
for queue.iter().advance |quad| {
|
||||
match self.quadrants[*quad as int] {
|
||||
Some(ref mut child) => {
|
||||
let (tile, flag, delta) = child.remove_tile(x, y);
|
||||
match tile {
|
||||
Some(_) => {
|
||||
self.tile_mem = (self.tile_mem as int + delta) as uint;
|
||||
if flag {
|
||||
del_quad = Some(*quad);
|
||||
} else {
|
||||
return (tile, flag, delta);
|
||||
}
|
||||
|
||||
// child.remove_tile() returned true
|
||||
self.quadrants[my_child as int] = None;
|
||||
match self.quadrants {
|
||||
[None, None, None, None] => true,
|
||||
_ => false,
|
||||
ret = (tile, flag, delta);
|
||||
break;
|
||||
}
|
||||
None => {},
|
||||
}
|
||||
}
|
||||
None => {},
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a window rect in page coordinates and a tile validation function, returns a BufferRequest array
|
||||
/// and a redisplay boolean. See QuadTree function description for more details.
|
||||
fn get_tile_rects(&mut self, window: Rect<f32>, valid: &fn(&T) -> bool, scale: f32, tile_size: f32) ->
|
||||
(~[BufferRequest], bool) {
|
||||
match del_quad {
|
||||
Some(quad) => {
|
||||
self.quadrants[quad as int] = None;
|
||||
let (tile, _, delta) = ret;
|
||||
match (&self.tile, &self.quadrants) {
|
||||
(&None, &[None, None, None, None]) => (tile, true, delta),
|
||||
_ => (tile, false, delta)
|
||||
}
|
||||
}
|
||||
None => ret,
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a window rect in page coordinates, returns a BufferRequest array,
|
||||
/// a redisplay boolean, and the difference in tile memory between the new and old quadtree nodes.
|
||||
/// NOTE: this method will sometimes modify the tree by deleting tiles.
|
||||
/// See the QuadTree function description for more details.
|
||||
fn get_tile_rects(&mut self, window: Rect<f32>, scale: f32, tile_size: f32) ->
|
||||
(~[BufferRequest], bool, int) {
|
||||
|
||||
let w_x = window.origin.x;
|
||||
let w_y = window.origin.y;
|
||||
|
@ -349,22 +377,27 @@ impl<T> QuadtreeNode<T> {
|
|||
|
||||
if s_size <= tile_size { // We are the child
|
||||
return match self.tile {
|
||||
_ if self.render_flag => (~[], false),
|
||||
Some(ref tile) if valid(tile) => {
|
||||
_ if self.render_flag => (~[], false, 0),
|
||||
Some(ref tile) if tile.is_valid(scale) => {
|
||||
let redisplay = match self.quadrants {
|
||||
[None, None, None, None] => false,
|
||||
_ => true,
|
||||
};
|
||||
let mut delta = 0;
|
||||
if redisplay {
|
||||
let old_mem = self.tile_mem;
|
||||
// FIXME: This should be inline, but currently won't compile
|
||||
let quads = [TL, TR, BL, BR];
|
||||
for quads.iter().advance |quad| {
|
||||
self.quadrants[*quad as int] = None;
|
||||
}
|
||||
self.tile_mem = tile.get_mem();
|
||||
delta = self.tile_mem as int - old_mem as int;
|
||||
|
||||
}
|
||||
(~[], redisplay)
|
||||
(~[], redisplay, delta)
|
||||
}
|
||||
_ => (~[self.get_tile_rect(s_x, s_y, scale, tile_size)], false),
|
||||
_ => (~[self.get_tile_rect(s_x, s_y, scale, tile_size)], false, 0),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -400,6 +433,7 @@ impl<T> QuadtreeNode<T> {
|
|||
|
||||
let mut ret = ~[];
|
||||
let mut redisplay = false;
|
||||
let mut delta = 0;
|
||||
|
||||
for quads_to_check.iter().advance |quad| {
|
||||
// Recurse into child
|
||||
|
@ -422,8 +456,8 @@ impl<T> QuadtreeNode<T> {
|
|||
|
||||
};
|
||||
|
||||
let (c_ret, c_redisplay) = match self.quadrants[*quad as int] {
|
||||
Some(ref mut child) => child.get_tile_rects(new_window, |x| valid(x), scale, tile_size),
|
||||
let (c_ret, c_redisplay, c_delta) = match self.quadrants[*quad as int] {
|
||||
Some(ref mut child) => child.get_tile_rects(new_window, scale, tile_size),
|
||||
None => {
|
||||
// Create new child
|
||||
let new_size = self.size / 2.0;
|
||||
|
@ -436,17 +470,18 @@ impl<T> QuadtreeNode<T> {
|
|||
BL | BR => self.origin.y + new_size,
|
||||
};
|
||||
let mut child = ~QuadtreeNode::new_child(new_x, new_y, new_size);
|
||||
let (a, b) = child.get_tile_rects(new_window, |x| valid(x), scale, tile_size);
|
||||
let (a, b, c) = child.get_tile_rects(new_window, scale, tile_size);
|
||||
self.quadrants[*quad as int] = Some(child);
|
||||
(a, b)
|
||||
(a, b, c)
|
||||
}
|
||||
};
|
||||
|
||||
delta = delta + c_delta;
|
||||
ret = ret + c_ret;
|
||||
redisplay = redisplay || c_redisplay;
|
||||
}
|
||||
|
||||
(ret, redisplay)
|
||||
self.tile_mem = (self.tile_mem as int + delta) as uint;
|
||||
(ret, redisplay, delta)
|
||||
}
|
||||
|
||||
|
||||
|
@ -492,15 +527,42 @@ impl<T> QuadtreeNode<T> {
|
|||
|
||||
|
||||
#[test]
|
||||
fn test_add_tile() {
|
||||
let mut t = Quadtree::new(50, 30, 20, 20, 10);
|
||||
assert!(t.get_tile(50, 30, 1.0).is_none());
|
||||
t.add_tile(50, 30, 1.0, 1);
|
||||
assert!(t.get_tile(50, 30, 1.0).get() == 1);
|
||||
assert!(t.get_tile(59, 39, 1.0).get() == 1);
|
||||
assert!(t.get_tile(60, 40, 1.0).is_none());
|
||||
assert!(t.get_tile(110, 70, 2.0).get() == 1);
|
||||
t.add_tile(100, 60, 2.0, 2);
|
||||
assert!(t.get_tile(109, 69, 2.0).get() == 2);
|
||||
assert!(t.get_tile(110, 70, 2.0).get() == 1);
|
||||
pub fn test() {
|
||||
struct T {
|
||||
a: int,
|
||||
}
|
||||
|
||||
impl Tile for T {
|
||||
fn get_mem(&self) -> uint {
|
||||
1
|
||||
}
|
||||
|
||||
fn is_valid(&self, _: f32) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
let mut q = Quadtree::new(8, 8, 2, Some(4));
|
||||
q.add_tile(0, 0, 1f32, T{a: 0});
|
||||
q.add_tile(0, 0, 2f32, T{a: 1});
|
||||
q.add_tile(0, 0, 2f32, T{a: 2});
|
||||
q.add_tile(2, 0, 2f32, T{a: 3});
|
||||
assert!(q.root.tile_mem == 3);
|
||||
assert!(q.get_all_tiles().len() == 3);
|
||||
q.add_tile(0, 2, 2f32, T{a: 4});
|
||||
q.add_tile(2, 2, 2f32, T{a: 5});
|
||||
assert!(q.root.tile_mem == 4);
|
||||
|
||||
let (request, _) = q.get_tile_rects(Rect(Point2D(0, 0), Size2D(2, 2)), 2f32);
|
||||
assert!(request.is_empty());
|
||||
let (request, _) = q.get_tile_rects(Rect(Point2D(0, 0), Size2D(2, 2)), 1.9);
|
||||
assert!(request.is_empty());
|
||||
let (request, _) = q.get_tile_rects(Rect(Point2D(0, 0), Size2D(2, 2)), 1f32);
|
||||
assert!(request.len() == 4);
|
||||
|
||||
q.add_tile(0, 0, 0.5, T{a: 6});
|
||||
q.add_tile(0, 0, 1f32, T{a: 7});
|
||||
let (_, redisplay) = q.get_tile_rects(Rect(Point2D(0, 0), Size2D(2, 2)), 0.5);
|
||||
assert!(redisplay);
|
||||
assert!(q.root.tile_mem == 1);
|
||||
}
|
|
@ -9,6 +9,7 @@ use geom::size::Size2D;
|
|||
|
||||
use extra::arc;
|
||||
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub struct LayerBuffer {
|
||||
draw_target: DrawTarget,
|
||||
|
@ -68,3 +69,21 @@ pub trait RenderListener {
|
|||
pub trait ScriptListener : Clone {
|
||||
fn set_ready_state(&self, ReadyState);
|
||||
}
|
||||
|
||||
/// The interface used by the quadtree to get info about LayerBuffers
|
||||
pub trait Tile {
|
||||
/// Returns the amount of memory used by the tile
|
||||
fn get_mem(&self) -> uint;
|
||||
/// Returns true if the tile is displayable at the given scale
|
||||
fn is_valid(&self, f32) -> bool;
|
||||
}
|
||||
|
||||
impl Tile for ~LayerBuffer {
|
||||
fn get_mem(&self) -> uint {
|
||||
// This works for now, but in the future we may want a better heuristic
|
||||
self.screen_pos.size.width * self.screen_pos.size.height
|
||||
}
|
||||
fn is_valid(&self, scale: f32) -> bool {
|
||||
self.resolution.approx_eq(&scale)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue