Bug 1587713 - Don't limit the number of rasterized blob tiles per transaction. r=jrmuizel

If this change lands without making waves, a lot of complicated blob infrastructure will be removed as a followup.

Differential Revision: https://phabricator.services.mozilla.com/D49185

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Nicolas Silva 2019-11-04 14:55:40 +00:00
parent d60ad185ac
commit 4a8849bcc4

View File

@ -436,9 +436,7 @@ pub struct BlobImageRasterizerEpoch(usize);
/// Stores parameters for clearing blob image tiles.
///
/// The clearing is necessary when originally requested tile range exceeds
/// MAX_TILES_PER_REQUEST. In this case, some tiles are not rasterized by
/// AsyncBlobImageRasterizer. They need to be cleared.
/// TODO(nical) this can be removed.
#[derive(Clone, Copy, Debug)]
pub struct BlobImageClearParams {
pub key: BlobImageKey,
@ -730,35 +728,6 @@ impl ResourceCache {
self.blob_image_rasterizer = Some(rasterizer);
self.blob_image_rasterizer_consumed_epoch = supp.epoch;
}
// Discard blob image tiles that are not rendered by AsyncBlobImageRasterizer.
// It happens when originally requested tile range exceeds MAX_TILES_PER_REQUEST.
for req in supp.clear_requests {
let tiles = match self.rasterized_blob_images.get_mut(&req.key) {
Some(RasterizedBlob::Tiled(tiles)) => tiles,
_ => { continue; }
};
tiles.retain(|tile, _| {
!req.original_tile_range.contains(*tile) ||
req.actual_tile_range.contains(*tile)
});
let texture_cache = &mut self.texture_cache;
match self.cached_images.try_get_mut(&req.key.as_image()) {
Some(&mut ImageResult::Multi(ref mut entries)) => {
entries.retain(|key, entry| {
if !req.original_tile_range.contains(key.tile.unwrap()) ||
req.actual_tile_range.contains(key.tile.unwrap()) {
return true;
}
entry.mark_unused(texture_cache);
return false;
});
}
_ => {}
}
}
}
pub fn add_rasterized_blob_images(
@ -1266,7 +1235,6 @@ impl ResourceCache {
return (None, Vec::new());
}
let mut blob_tiles_clear_requests = Vec::new();
let mut blob_request_params = Vec::new();
for key in keys {
let template = self.blob_image_templates.get_mut(key).unwrap();
@ -1274,7 +1242,7 @@ impl ResourceCache {
if let Some(tile_size) = template.tiling {
// If we know that only a portion of the blob image is in the viewport,
// only request these visible tiles since blob images can be huge.
let mut tiles = compute_tile_range(
let tiles = compute_tile_range(
&template.visible_rect,
tile_size,
);
@ -1302,46 +1270,6 @@ impl ResourceCache {
DirtyRect::All => tiles,
};
let original_tile_range = tiles;
// This code tries to keep things sane if Gecko sends
// nonsensical blob image requests.
// Constant here definitely needs to be tweaked.
const MAX_TILES_PER_REQUEST: i32 = 512;
// For truly nonsensical requests, we might run into overflow
// when computing width * height, so we first check each extent
// individually.
while !tiles.size.is_empty_or_negative()
&& (tiles.size.width > MAX_TILES_PER_REQUEST
|| tiles.size.height > MAX_TILES_PER_REQUEST
|| tiles.size.width * tiles.size.height > MAX_TILES_PER_REQUEST) {
let limit = 46340; // sqrt(i32::MAX) rounded down to avoid overflow.
let w = tiles.size.width.min(limit);
let h = tiles.size.height.min(limit);
let diff = w * h - MAX_TILES_PER_REQUEST;
// Remove tiles in the largest dimension.
if tiles.size.width > tiles.size.height {
tiles.size.width -= diff / h + 1;
tiles.origin.x += diff / (2 * h);
} else {
tiles.size.height -= diff / w + 1;
tiles.origin.y += diff / (2 * w);
}
}
// When originally requested tile range exceeds MAX_TILES_PER_REQUEST,
// some tiles are not rasterized by AsyncBlobImageRasterizer.
// They need to be cleared.
if original_tile_range != tiles {
let clear_params = BlobImageClearParams {
key: *key,
original_tile_range,
actual_tile_range: tiles,
};
blob_tiles_clear_requests.push(clear_params);
}
for_each_tile_in_range(&tiles, |tile| {
let still_valid = template.valid_tiles_after_bounds_change
.map(|valid_tiles| valid_tiles.contains(tile))
@ -1431,7 +1359,7 @@ impl ResourceCache {
self.blob_image_rasterizer_produced_epoch.0 += 1;
let info = AsyncBlobImageInfo {
epoch: self.blob_image_rasterizer_produced_epoch,
clear_requests: blob_tiles_clear_requests,
clear_requests: Vec::new(),
};
let handler = self.blob_image_handler.as_mut().unwrap();
handler.prepare_resources(&self.resources, &blob_request_params);