Bug 1450162. Use an Entry type instead of tuples. r=mstange

This will make things a bit cleaner when interacting with the upcoming cache.
This commit is contained in:
Jeff Muizelaar 2018-04-04 16:05:11 -04:00
Родитель 055220511d
Коммит eb32c7230c
1 изменённых файлов: 38 добавлений и 30 удалений

Просмотреть файл

@ -2,7 +2,8 @@ use webrender::api::*;
use bindings::{ByteSlice, MutByteSlice, wr_moz2d_render_cb, ArcVecU8};
use rayon::ThreadPool;
use std::collections::hash_map::{HashMap, Entry};
use std::collections::hash_map::HashMap;
use std::collections::hash_map;
use std::mem;
use std::os::raw::c_void;
use std::ptr;
@ -131,6 +132,13 @@ struct BlobReader<'a> {
begin: usize,
}
struct Entry {
bounds: Box2d,
begin: usize,
end: usize,
extra_end: usize,
}
impl<'a> BlobReader<'a> {
fn new(buf: &'a[u8]) -> BlobReader<'a> {
// The offset of the index is at the end of the buffer.
@ -140,11 +148,11 @@ impl<'a> BlobReader<'a> {
BlobReader { reader: BufReader::new(&buf[index_offset..index_offset_pos]), begin: 0 }
}
fn read_entry(&mut self) -> (usize, usize, usize, Box2d) {
fn read_entry(&mut self) -> Entry {
let end = self.reader.read();
let extra_end = self.reader.read();
let bounds = self.reader.read();
let ret = (self.begin, end, extra_end, bounds);
let ret = Entry { begin: self.begin, end, extra_end, bounds };
self.begin = extra_end;
ret
}
@ -214,9 +222,9 @@ impl From<DeviceUintRect> for Box2d {
fn dump_blob_index(blob: &[u8], dirty_rect: Box2d) {
let mut index = BlobReader::new(blob);
while index.reader.has_more() {
let (_, _, _, bounds) = index.read_entry();
dlog!(" {:?} {}", bounds,
if bounds.contained_by(&dirty_rect) {
let e = index.read_entry();
dlog!(" {:?} {}", e.bounds,
if e.bounds.contained_by(&dirty_rect) {
"*"
} else {
""
@ -229,8 +237,8 @@ fn check_result(result: &[u8]) -> () {
let mut index = BlobReader::new(result);
assert!(index.reader.has_more(), "Unexpectedly empty result. This blob should just have been deleted");
while index.reader.has_more() {
let (_, end, extra, bounds) = index.read_entry();
dlog!("result bounds: {} {} {:?}", end, extra, bounds);
let e = index.read_entry();
dlog!("result bounds: {} {} {:?}", e.end, e.extra_end, e.bounds);
}
}
@ -241,38 +249,38 @@ fn check_result(result: &[u8]) -> () {
Old items contained in the dirty_rect are dropped and new items
are retained.
*/
fn merge_blob_images(old: &[u8], new: &[u8], dirty_rect: Box2d) -> Vec<u8> {
fn merge_blob_images(old_buf: &[u8], new_buf: &[u8], dirty_rect: Box2d) -> Vec<u8> {
let mut result = BlobWriter::new();
dlog!("dirty rect: {:?}", dirty_rect);
dlog!("old:");
dump_blob_index(old, dirty_rect);
dump_blob_index(old_buf, dirty_rect);
dlog!("new:");
dump_blob_index(new, dirty_rect);
dump_blob_index(new_buf, dirty_rect);
let mut old_reader = BlobReader::new(old);
let mut new_reader = BlobReader::new(new);
let mut old_reader = BlobReader::new(old_buf);
let mut new_reader = BlobReader::new(new_buf);
// Loop over both new and old entries merging them.
// Both new and old must have the same number of entries that
// overlap but are not contained by the dirty rect, and they
// must be in the same order.
while new_reader.reader.has_more() {
let (new_begin, new_end, new_extra, new_bounds) = new_reader.read_entry();
dlog!("bounds: {} {} {:?}", new_end, new_extra, new_bounds);
if new_bounds.contained_by(&dirty_rect) {
result.new_entry(new_extra - new_end, new_bounds, &new[new_begin..new_extra]);
let new = new_reader.read_entry();
dlog!("bounds: {} {} {:?}", new.end, new.extra_end, new.bounds);
if new.bounds.contained_by(&dirty_rect) {
result.new_entry(new.extra_end - new.end, new.bounds, &new_buf[new.begin..new.extra_end]);
} else {
loop {
assert!(old_reader.reader.has_more());
let (old_begin, old_end, old_extra, old_bounds) = old_reader.read_entry();
dlog!("new bounds: {} {} {:?}", old_end, old_extra, old_bounds);
if old_bounds.contained_by(&dirty_rect) {
let old = old_reader.read_entry();
dlog!("new bounds: {} {} {:?}", old.end, old.extra_end, old.bounds);
if old.bounds.contained_by(&dirty_rect) {
// fully contained items will be discarded or replaced
} else {
assert_eq!(old_bounds, new_bounds);
assert_eq!(old.bounds, new.bounds);
// we found a matching item use the old data
result.new_entry(old_extra - old_end, old_bounds, &old[old_begin..old_extra]);
result.new_entry(old.extra_end - old.end, old.bounds, &old_buf[old.begin..old.extra_end]);
break;
}
}
@ -281,9 +289,9 @@ fn merge_blob_images(old: &[u8], new: &[u8], dirty_rect: Box2d) -> Vec<u8> {
// Include any remaining old items.
while old_reader.reader.has_more() {
let (_, old_end, old_extra, old_bounds) = old_reader.read_entry();
dlog!("new bounds: {} {} {:?}", old_end, old_extra, old_bounds);
assert!(old_bounds.contained_by(&dirty_rect));
let old = old_reader.read_entry();
dlog!("new bounds: {} {} {:?}", old.end, old.extra_end, old.bounds);
assert!(old.bounds.contained_by(&dirty_rect));
}
let result = result.finish();
@ -302,7 +310,7 @@ impl BlobImageRenderer for Moz2dImageRenderer {
fn update(&mut self, key: ImageKey, data: BlobImageData, dirty_rect: Option<DeviceUintRect>) {
match self.blob_commands.entry(key) {
Entry::Occupied(mut e) => {
hash_map::Entry::Occupied(mut e) => {
let old_data = &mut e.get_mut().0;
*old_data = Arc::new(merge_blob_images(&old_data, &data,
dirty_rect.unwrap().into()));
@ -374,8 +382,8 @@ impl BlobImageRenderer for Moz2dImageRenderer {
let mut index = BlobReader::new(&commands);
assert!(index.reader.pos < index.reader.buf.len());
while index.reader.pos < index.reader.buf.len() {
let (_, end, extra_end, _) = index.read_entry();
process_fonts(BufReader::new(&commands[end..extra_end]), resources);
let e = index.read_entry();
process_fonts(BufReader::new(&commands[e.end..e.extra_end]), resources);
}
}
@ -413,10 +421,10 @@ impl BlobImageRenderer for Moz2dImageRenderer {
fn resolve(&mut self, request: BlobImageRequest) -> BlobImageResult {
match self.rendered_images.entry(request) {
Entry::Vacant(_) => {
hash_map::Entry::Vacant(_) => {
return Err(BlobImageError::InvalidKey);
}
Entry::Occupied(entry) => {
hash_map::Entry::Occupied(entry) => {
// None means we haven't yet received the result.
if entry.get().is_some() {
let result = entry.remove();