mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-20 00:35:44 +00:00
Merge inbound to mozilla-central. a=merge
This commit is contained in:
commit
197210b8c1
@ -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) {
|
||||
|
@ -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"));
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user