Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Discard the dirty rect of evicted texture cache entries #2774

Merged
merged 2 commits into from May 24, 2018
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -174,7 +174,7 @@ where
K: Clone + Hash + Eq + Debug,
U: Default,
{
pub fn new() -> ResourceClassCache<K, V, U> {
pub fn new() -> Self {
ResourceClassCache {
resources: FastHashMap::default(),
user_data: Default::default(),
@@ -510,16 +510,14 @@ impl ResourceCache {
tiling,
);
}
let dirty_rect = Some(descriptor.full_rect());

let resource = ImageResource {
descriptor,
data,
epoch: Epoch(0),
tiling,
dirty_rect: Some(DeviceUintRect::new(
DeviceUintPoint::zero(),
descriptor.size,
)),
dirty_rect,
};

self.resources.image_templates.insert(image_key, resource);
@@ -636,9 +634,14 @@ impl ResourceCache {
let needs_upload = self.texture_cache
.request(&entry.as_ref().unwrap().texture_cache_handle, gpu_cache);

if !needs_upload && !needs_update {
return;
}
let dirty_rect = if needs_upload {
// the texture cache entry has been evicted, treat it as all dirty
Some(template.descriptor.full_rect())
} else if needs_update {
template.dirty_rect
} else {
return
};

// We can start a worker thread rasterizing right now, if:
// - The image is a blob.
@@ -658,7 +661,7 @@ impl ResourceCache {
tile_offset.y as f32 * tile_size as f32,
);

if let Some(dirty) = template.dirty_rect {
if let Some(dirty) = dirty_rect {
if intersect_for_tile(dirty, actual_size, tile_size, tile_offset).is_none() {
// don't bother requesting unchanged tiles
return
@@ -678,7 +681,7 @@ impl ResourceCache {
offset,
format: template.descriptor.format,
},
template.dirty_rect,
dirty_rect,
);
}
}
@@ -6,7 +6,8 @@ extern crate serde_bytes;

use font::{FontInstanceKey, FontKey, FontTemplate};
use std::sync::Arc;
use {DevicePoint, DeviceUintRect, DeviceUintSize, IdNamespace, TileOffset, TileSize};
use {DevicePoint, DeviceUintPoint, DeviceUintRect, DeviceUintSize};
use {IdNamespace, TileOffset, TileSize};
use euclid::size2;

#[repr(C)]
@@ -106,6 +107,13 @@ impl ImageDescriptor {
pub fn compute_total_size(&self) -> u32 {
self.compute_stride() * self.size.height
}

pub fn full_rect(&self) -> DeviceUintRect {
DeviceUintRect::new(
DeviceUintPoint::zero(),
self.size,
)
}
}

#[derive(Clone, Debug, Serialize, Deserialize)]
@@ -47,6 +47,7 @@ impl<'a> RawtestHarness<'a> {
self.test_blob_update_epoch_test();
self.test_tile_decomposition();
self.test_very_large_blob();
self.test_offscreen_blob();
self.test_save_restore();
self.test_capture();
self.test_zero_height_window();
@@ -226,6 +227,116 @@ impl<'a> RawtestHarness<'a> {
self.wrench.api.update_resources(txn.resource_updates);
}

fn test_offscreen_blob(&mut self) {
println!("\toffscreen blob update.");

assert_eq!(self.wrench.device_pixel_ratio, 1.);

let window_size = self.window.get_inner_size();

let test_size = DeviceUintSize::new(800, 800);

let window_rect = DeviceUintRect::new(
DeviceUintPoint::new(0, window_size.height - test_size.height),
test_size,
);

// This exposes a crash in tile decomposition
let mut txn = Transaction::new();
let layout_size = LayoutSize::new(800., 800.);

let blob_img = self.wrench.api.generate_image_key();
txn.add_image(
blob_img,
ImageDescriptor::new(1510, 1510, ImageFormat::BGRA8, false, false),
ImageData::new_blob_image(blob::serialize_blob(ColorU::new(50, 50, 150, 255))),
None,
);

let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size);

let info = LayoutPrimitiveInfo::new(rect(0., 0.0, 1510., 1510.));

let image_size = size(1510., 1510.);

// setup some malicious image size parameters
builder.push_image(
&info,
image_size,
image_size,
ImageRendering::Auto,
AlphaType::PremultipliedAlpha,
blob_img,
);

let mut epoch = Epoch(0);

self.submit_dl(&mut epoch, layout_size, builder, &txn.resource_updates);

let original_pixels = self.render_and_get_pixels(window_rect);

let mut epoch = Epoch(1);

let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size);

let info = LayoutPrimitiveInfo::new(rect(-10000., 0.0, 1510., 1510.));

let image_size = size(1510., 1510.);

// setup some malicious image size parameters
builder.push_image(
&info,
image_size,
image_size,
ImageRendering::Auto,
AlphaType::PremultipliedAlpha,
blob_img,
);

self.submit_dl(&mut epoch, layout_size, builder, &[]);

let _offscreen_pixels = self.render_and_get_pixels(window_rect);

let mut txn = Transaction::new();

txn.update_image(
blob_img,
ImageDescriptor::new(1510, 1510, ImageFormat::BGRA8, false, false),
ImageData::new_blob_image(blob::serialize_blob(ColorU::new(50, 50, 150, 255))),
Some(rect(10, 10, 100, 100)),
);

let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size);

let info = LayoutPrimitiveInfo::new(rect(0., 0.0, 1510., 1510.));

let image_size = size(1510., 1510.);

// setup some malicious image size parameters
builder.push_image(
&info,
image_size,
image_size,
ImageRendering::Auto,
AlphaType::PremultipliedAlpha,
blob_img,
);

let mut epoch = Epoch(2);

self.submit_dl(&mut epoch, layout_size, builder, &txn.resource_updates);

let pixels = self.render_and_get_pixels(window_rect);

assert!(pixels == original_pixels);

// Leaving a tiled blob image in the resource cache
// confuses the `test_capture`. TODO: remove this
txn = Transaction::new();
txn.delete_image(blob_img);
self.wrench.api.update_resources(txn.resource_updates);
}

fn test_retained_blob_images_test(&mut self) {
println!("\tretained blob images test...");
let blob_img;
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.