Merge inbound to mozilla-central. a=merge

This commit is contained in:
Csoregi Natalia 2019-05-08 06:37:15 +03:00
commit 197210b8c1
4 changed files with 253 additions and 9 deletions

View File

@ -1884,6 +1884,13 @@ static bool CCRunnerFired(TimeStamp aDeadline) {
// or we're doing the initial forget skippables.
FireForgetSkippable(suspected, false, aDeadline);
didDoWork = true;
} else if (!isLateTimerFire && !aDeadline.IsNull()) {
MOZ_ASSERT(!didDoWork);
// If we're called during idle time, try to find some work to do by calling
// the method recursively, effectively bypassing some possible forget
// skippable calls.
sCCRunnerFireCount = numEarlyTimerFires;
return CCRunnerFired(aDeadline);
}
if (isLateTimerFire) {

View File

@ -2549,10 +2549,6 @@ static FeatureState& WebRenderHardwareQualificationStatus(
if (status != nsIGfxInfo::FEATURE_STATUS_OK) {
featureWebRenderQualified.Disable(FeatureStatus::Blocked,
"No qualified hardware", aOutFailureId);
} else if (aHasBattery) {
featureWebRenderQualified.Disable(
FeatureStatus::Blocked, "Has battery",
NS_LITERAL_CSTRING("FEATURE_FAILURE_WR_HAS_BATTERY"));
} else {
nsAutoString adapterVendorID;
gfxInfo->GetAdapterVendorID(adapterVendorID);
@ -2566,7 +2562,27 @@ static FeatureState& WebRenderHardwareQualificationStatus(
FeatureStatus::Blocked, "Bad device id",
NS_LITERAL_CSTRING("FEATURE_FAILURE_BAD_DEVICE_ID"));
} else {
if (adapterVendorID == u"0x10de") {
#ifdef NIGHTLY_BUILD
// For Intel devices, if we have a battery, ignore it if the screen is
// small enough. Note that we always check for a battery with NVIDIA
// because we do not have a limited/curated set of devices to support
// WebRender on.
const int32_t kMaxPixelsBattery = 1920 * 1200; // WUXGA
const int32_t screenPixels = aScreenSize.width * aScreenSize.height;
bool disableForBattery = aHasBattery;
if (adapterVendorID == u"0x8086" && screenPixels > 0 &&
screenPixels <= kMaxPixelsBattery) {
disableForBattery = false;
}
#else
bool disableForBattery = aHasBattery;
#endif
if (disableForBattery) {
featureWebRenderQualified.Disable(
FeatureStatus::Blocked, "Has battery",
NS_LITERAL_CSTRING("FEATURE_FAILURE_WR_HAS_BATTERY"));
} else if (adapterVendorID == u"0x10de") {
if (deviceID < 0x6c0) {
// 0x6c0 is the lowest Fermi device id. Unfortunately some Tesla
// devices that don't support D3D 10.1 have higher deviceIDs. They
@ -2674,13 +2690,12 @@ static FeatureState& WebRenderHardwareQualificationStatus(
else {
// Performance is not great on 4k screens with WebRender + Linux.
// Disable it for now if it is too large.
const int32_t maxPixels = 3440 * 1440; // UWQHD
int32_t pixels = aScreenSize.width * aScreenSize.height;
if (pixels > maxPixels) {
const int32_t kMaxPixelsLinux = 3440 * 1440; // UWQHD
if (screenPixels > kMaxPixelsLinux) {
featureWebRenderQualified.Disable(
FeatureStatus::Blocked, "Screen size too large",
NS_LITERAL_CSTRING("FEATURE_FAILURE_SCREEN_SIZE_TOO_LARGE"));
} else if (pixels <= 0) {
} else if (screenPixels <= 0) {
featureWebRenderQualified.Disable(
FeatureStatus::Blocked, "Screen size unknown",
NS_LITERAL_CSTRING("FEATURE_FAILURE_SCREEN_SIZE_UNKNOWN"));

View File

@ -638,6 +638,8 @@ pub enum RenderTaskKind {
Border(BorderTask),
LineDecoration(LineDecorationTask),
Gradient(GradientTask),
#[cfg(test)]
Test(RenderTargetKind),
}
impl RenderTaskKind {
@ -655,6 +657,8 @@ impl RenderTaskKind {
RenderTaskKind::Border(..) => "Border",
RenderTaskKind::LineDecoration(..) => "LineDecoration",
RenderTaskKind::Gradient(..) => "Gradient",
#[cfg(test)]
RenderTaskKind::Test(..) => "Test",
}
}
}
@ -703,6 +707,21 @@ impl RenderTask {
}
}
#[cfg(test)]
pub fn new_test(
target: RenderTargetKind,
location: RenderTaskLocation,
children: Vec<RenderTaskId>,
) -> Self {
RenderTask {
location,
children,
kind: RenderTaskKind::Test(target),
clear_mode: ClearMode::Transparent,
saved_index: None,
}
}
pub fn new_picture(
location: RenderTaskLocation,
unclipped_size: DeviceSize,
@ -1146,6 +1165,11 @@ impl RenderTask {
RenderTaskKind::Blit(..) => {
UvRectKind::Rect
}
#[cfg(test)]
RenderTaskKind::Test(..) => {
unreachable!("Unexpected render task");
}
}
}
@ -1203,6 +1227,11 @@ impl RenderTask {
RenderTaskKind::Blit(..) => {
[0.0; 3]
}
#[cfg(test)]
RenderTaskKind::Test(..) => {
unreachable!();
}
};
let (mut target_rect, target_index) = self.get_target_rect();
@ -1247,6 +1276,10 @@ impl RenderTask {
RenderTaskKind::Glyph(..) => {
panic!("texture handle not supported for this task kind");
}
#[cfg(test)]
RenderTaskKind::Test(..) => {
panic!("RenderTask tests aren't expected to exercise this code");
}
}
}
@ -1322,6 +1355,9 @@ impl RenderTask {
RenderTaskKind::Blit(..) => {
RenderTargetKind::Color
}
#[cfg(test)]
RenderTaskKind::Test(kind) => kind,
}
}
@ -1350,6 +1386,10 @@ impl RenderTask {
RenderTaskKind::Glyph(..) => {
return;
}
#[cfg(test)]
RenderTaskKind::Test(..) => {
panic!("RenderTask tests aren't expected to exercise this code");
}
};
if let Some(mut request) = gpu_cache.request(cache_handle) {
@ -1412,6 +1452,10 @@ impl RenderTask {
RenderTaskKind::Gradient(..) => {
pt.new_level("Gradient".to_owned());
}
#[cfg(test)]
RenderTaskKind::Test(..) => {
pt.new_level("Test".to_owned());
}
}
pt.add_item(format!("clear to: {:?}", self.clear_mode));
@ -1874,3 +1918,175 @@ fn dump_task_dependency_link(
).unwrap();
}
}
#[cfg(test)]
use euclid::{size2, rect};
#[cfg(test)]
fn dyn_location(w: i32, h: i32) -> RenderTaskLocation {
RenderTaskLocation::Dynamic(None, size2(w, h))
}
#[test]
fn diamond_task_graph() {
// A simple diamon shaped task graph.
//
// [b1]
// / \
// [a] [main_pic]
// \ /
// [b2]
let color = RenderTargetKind::Color;
let counters = RenderTaskTreeCounters::new();
let mut tasks = RenderTaskTree::new(FrameId::first(), &counters);
let a = tasks.add(RenderTask::new_test(color, dyn_location(640, 640), Vec::new()));
let b1 = tasks.add(RenderTask::new_test(color, dyn_location(320, 320), vec![a]));
let b2 = tasks.add(RenderTask::new_test(color, dyn_location(320, 320), vec![a]));
let main_pic = tasks.add(RenderTask::new_test(
color,
RenderTaskLocation::Fixed(rect(0, 0, 3200, 1800)),
vec![b1, b2],
));
let initial_number_of_tasks = tasks.tasks.len();
let passes = tasks.generate_passes(Some(main_pic), size2(3200, 1800), true);
// We should not have added any blits.
assert_eq!(tasks.tasks.len(), initial_number_of_tasks);
assert_eq!(passes.len(), 3);
assert_eq!(passes[0].tasks, vec![a]);
assert_eq!(passes[1].tasks.len(), 2);
assert!(passes[1].tasks.contains(&b1));
assert!(passes[1].tasks.contains(&b2));
assert_eq!(passes[2].tasks, vec![main_pic]);
}
#[test]
fn blur_task_graph() {
// This test simulates a complicated shadow stack effect with target allocation
// conflicts to resolve.
let color = RenderTargetKind::Color;
let counters = RenderTaskTreeCounters::new();
let mut tasks = RenderTaskTree::new(FrameId::first(), &counters);
let pic = tasks.add(RenderTask::new_test(color, dyn_location(640, 640), Vec::new()));
let scale1 = tasks.add(RenderTask::new_test(color, dyn_location(320, 320), vec![pic]));
let scale2 = tasks.add(RenderTask::new_test(color, dyn_location(160, 160), vec![scale1]));
let scale3 = tasks.add(RenderTask::new_test(color, dyn_location(80, 80), vec![scale2]));
let scale4 = tasks.add(RenderTask::new_test(color, dyn_location(40, 40), vec![scale3]));
let vblur1 = tasks.add(RenderTask::new_test(color, dyn_location(40, 40), vec![scale4]));
let hblur1 = tasks.add(RenderTask::new_test(color, dyn_location(40, 40), vec![vblur1]));
let vblur2 = tasks.add(RenderTask::new_test(color, dyn_location(40, 40), vec![scale4]));
let hblur2 = tasks.add(RenderTask::new_test(color, dyn_location(40, 40), vec![vblur2]));
// Insert a task that is an even number of passes away from its dependency.
// This means the source and destination are on the same target and we have to resolve
// this conflict by automatically inserting a blit task.
let vblur3 = tasks.add(RenderTask::new_test(color, dyn_location(80, 80), vec![scale3]));
let hblur3 = tasks.add(RenderTask::new_test(color, dyn_location(80, 80), vec![vblur3]));
// Insert a task that is an odd number > 1 of passes away from its dependency.
// This should force us to mark the dependency "for saving" to keep its content valid
// until the task can access it.
let vblur4 = tasks.add(RenderTask::new_test(color, dyn_location(160, 160), vec![scale2]));
let hblur4 = tasks.add(RenderTask::new_test(color, dyn_location(160, 160), vec![vblur4]));
let main_pic = tasks.add(RenderTask::new_test(
color,
RenderTaskLocation::Fixed(rect(0, 0, 3200, 1800)),
vec![hblur1, hblur2, hblur3, hblur4],
));
let initial_number_of_tasks = tasks.tasks.len();
let passes = tasks.generate_passes(Some(main_pic), size2(3200, 1800), true);
// We should have added a single blit task.
assert_eq!(tasks.tasks.len(), initial_number_of_tasks + 1);
// vblur3's dependency to scale3 should be replaced by a blit.
let blit = tasks[vblur3].children[0];
assert!(blit != scale3);
match tasks[blit].kind {
RenderTaskKind::Blit(..) => {}
_ => { panic!("This should be a blit task."); }
}
assert_eq!(passes.len(), 8);
assert_eq!(passes[0].tasks, vec![pic]);
assert_eq!(passes[1].tasks, vec![scale1]);
assert_eq!(passes[2].tasks, vec![scale2]);
assert_eq!(passes[3].tasks, vec![scale3]);
assert_eq!(passes[4].tasks.len(), 2);
assert!(passes[4].tasks.contains(&scale4));
assert!(passes[4].tasks.contains(&blit));
assert_eq!(passes[5].tasks.len(), 4);
assert!(passes[5].tasks.contains(&vblur1));
assert!(passes[5].tasks.contains(&vblur2));
assert!(passes[5].tasks.contains(&vblur3));
assert!(passes[5].tasks.contains(&vblur4));
assert_eq!(passes[6].tasks.len(), 4);
assert!(passes[6].tasks.contains(&hblur1));
assert!(passes[6].tasks.contains(&hblur2));
assert!(passes[6].tasks.contains(&hblur3));
assert!(passes[6].tasks.contains(&hblur4));
assert_eq!(passes[7].tasks, vec![main_pic]);
// See vblur4's comment above.
assert!(tasks[scale2].saved_index.is_some());
}
#[test]
fn culled_tasks() {
// This test checks that tasks that do not contribute to the frame don't appear in the
// generated passes.
let color = RenderTargetKind::Color;
let counters = RenderTaskTreeCounters::new();
let mut tasks = RenderTaskTree::new(FrameId::first(), &counters);
let a1 = tasks.add(RenderTask::new_test(color, dyn_location(640, 640), Vec::new()));
let _a2 = tasks.add(RenderTask::new_test(color, dyn_location(320, 320), vec![a1]));
let b1 = tasks.add(RenderTask::new_test(color, dyn_location(640, 640), Vec::new()));
let b2 = tasks.add(RenderTask::new_test(color, dyn_location(320, 320), vec![b1]));
let _b3 = tasks.add(RenderTask::new_test(color, dyn_location(320, 320), vec![b2]));
let main_pic = tasks.add(RenderTask::new_test(
color,
RenderTaskLocation::Fixed(rect(0, 0, 3200, 1800)),
vec![b2],
));
let initial_number_of_tasks = tasks.tasks.len();
let passes = tasks.generate_passes(Some(main_pic), size2(3200, 1800), true);
// We should not have added any blits.
assert_eq!(tasks.tasks.len(), initial_number_of_tasks);
assert_eq!(passes.len(), 3);
assert_eq!(passes[0].tasks, vec![b1]);
assert_eq!(passes[1].tasks, vec![b2]);
assert_eq!(passes[2].tasks, vec![main_pic]);
}

View File

@ -573,6 +573,8 @@ impl RenderTarget for ColorRenderTarget {
}
}
}
#[cfg(test)]
RenderTaskKind::Test(..) => {}
}
}
@ -724,6 +726,8 @@ impl RenderTarget for AlphaRenderTarget {
render_tasks.get_task_address(task.children[0]),
);
}
#[cfg(test)]
RenderTaskKind::Test(..) => {}
}
}
@ -872,6 +876,8 @@ impl TextureCacheRenderTarget {
RenderTaskKind::Scaling(..) => {
panic!("BUG: unexpected task kind for texture cache target");
}
#[cfg(test)]
RenderTaskKind::Test(..) => {}
}
}