pub mod policy;
use alloc::vec::Vec;
use core::cmp::Ordering;
use display_types::{ColorFormat, VideoMode};
use crate::diagnostic::Diagnostic;
use crate::output::config::NegotiatedConfig;
use crate::output::trace::DecisionStep;
use crate::ranker::policy::NegotiationPolicy;
pub use policy::NegotiationPolicy as Policy;
pub trait ConfigRanker {
type Warning: Diagnostic;
fn rank(
&self,
configs: Vec<NegotiatedConfig<Self::Warning>>,
policy: &NegotiationPolicy,
) -> Vec<NegotiatedConfig<Self::Warning>>;
}
#[derive(Debug, Default)]
pub struct DefaultRanker;
fn pixel_area(mode: &VideoMode) -> u32 {
mode.width as u32 * mode.height as u32
}
fn color_format_quality(fmt: ColorFormat) -> u8 {
match fmt {
ColorFormat::Rgb444 => 3,
ColorFormat::YCbCr444 => 2,
ColorFormat::YCbCr422 => 1,
ColorFormat::YCbCr420 => 0,
_ => 0,
}
}
fn compare_configs<W>(
a: &NegotiatedConfig<W>,
b: &NegotiatedConfig<W>,
policy: &NegotiationPolicy,
native_pixels: u32,
) -> Ordering {
if policy.penalize_dsc {
let ord = a.resolved.dsc_required.cmp(&b.resolved.dsc_required);
if ord != Ordering::Equal {
return ord;
}
}
if policy.prefer_native_resolution {
let a_native = pixel_area(&a.resolved.mode) == native_pixels;
let b_native = pixel_area(&b.resolved.mode) == native_pixels;
let ord = b_native.cmp(&a_native);
if ord != Ordering::Equal {
return ord;
}
}
if policy.prefer_color_fidelity {
let ord = b
.resolved
.bit_depth
.bits_per_primary()
.cmp(&a.resolved.bit_depth.bits_per_primary());
if ord != Ordering::Equal {
return ord;
}
let ord = color_format_quality(b.resolved.color_encoding)
.cmp(&color_format_quality(a.resolved.color_encoding));
if ord != Ordering::Equal {
return ord;
}
let ord = b
.resolved
.mode
.refresh_rate
.cmp(&a.resolved.mode.refresh_rate);
if ord != Ordering::Equal {
return ord;
}
} else if policy.prefer_high_refresh {
let ord = b
.resolved
.mode
.refresh_rate
.cmp(&a.resolved.mode.refresh_rate);
if ord != Ordering::Equal {
return ord;
}
let ord = b
.resolved
.bit_depth
.bits_per_primary()
.cmp(&a.resolved.bit_depth.bits_per_primary());
if ord != Ordering::Equal {
return ord;
}
let ord = color_format_quality(b.resolved.color_encoding)
.cmp(&color_format_quality(a.resolved.color_encoding));
if ord != Ordering::Equal {
return ord;
}
} else {
let ord = a
.resolved
.mode
.refresh_rate
.cmp(&b.resolved.mode.refresh_rate);
if ord != Ordering::Equal {
return ord;
}
let ord = a
.resolved
.bit_depth
.bits_per_primary()
.cmp(&b.resolved.bit_depth.bits_per_primary());
if ord != Ordering::Equal {
return ord;
}
let ord = color_format_quality(a.resolved.color_encoding)
.cmp(&color_format_quality(b.resolved.color_encoding));
if ord != Ordering::Equal {
return ord;
}
}
let ord = a.resolved.mode.interlaced.cmp(&b.resolved.mode.interlaced);
if ord != Ordering::Equal {
return ord;
}
let ord = a.resolved.frl_rate.cmp(&b.resolved.frl_rate);
if ord != Ordering::Equal {
return ord;
}
pixel_area(&b.resolved.mode).cmp(&pixel_area(&a.resolved.mode))
}
fn record_preferences<W>(
config: &mut NegotiatedConfig<W>,
policy: &NegotiationPolicy,
native_pixels: u32,
) {
if policy.penalize_dsc && config.resolved.dsc_required {
config.trace.steps.push(DecisionStep::PreferenceApplied {
rule: "DSC penalized".into(),
});
}
if policy.prefer_native_resolution && pixel_area(&config.resolved.mode) == native_pixels {
config.trace.steps.push(DecisionStep::PreferenceApplied {
rule: "native resolution preferred".into(),
});
}
let quality_rule = if policy.prefer_color_fidelity {
"color fidelity preferred"
} else if policy.prefer_high_refresh {
"high refresh rate preferred"
} else {
"power saving ordering applied"
};
config.trace.steps.push(DecisionStep::PreferenceApplied {
rule: quality_rule.into(),
});
if !config.resolved.mode.interlaced {
config.trace.steps.push(DecisionStep::PreferenceApplied {
rule: "progressive mode preferred".into(),
});
}
}
impl ConfigRanker for DefaultRanker {
type Warning = crate::output::warning::Warning;
fn rank(
&self,
mut configs: Vec<NegotiatedConfig<Self::Warning>>,
policy: &NegotiationPolicy,
) -> Vec<NegotiatedConfig<Self::Warning>> {
let native_pixels = configs
.iter()
.map(|c| pixel_area(&c.resolved.mode))
.max()
.unwrap_or(0);
configs.sort_by(|a, b| compare_configs(a, b, policy, native_pixels));
for config in &mut configs {
record_preferences(config, policy, native_pixels);
}
configs
}
}
#[cfg(test)]
mod tests {
use alloc::vec::Vec;
use core::cmp::Ordering;
use display_types::cea861::HdmiForumFrl;
use display_types::{ColorBitDepth, ColorFormat, ResolvedDisplayConfig, VideoMode};
use crate::output::{config::NegotiatedConfig, trace::ReasoningTrace, warning::Warning};
use crate::ranker::policy::NegotiationPolicy;
use crate::output::trace::DecisionStep;
use crate::ranker::DefaultRanker;
use super::ConfigRanker;
use super::{color_format_quality, compare_configs, pixel_area, record_preferences};
fn mode(width: u16, height: u16) -> VideoMode {
VideoMode::new(width, height, 60, false)
}
fn config(
width: u16,
height: u16,
refresh_rate: u16,
interlaced: bool,
color_encoding: ColorFormat,
bit_depth: ColorBitDepth,
frl_rate: HdmiForumFrl,
dsc_required: bool,
) -> NegotiatedConfig<Warning> {
NegotiatedConfig {
resolved: ResolvedDisplayConfig::new(
VideoMode::new(width, height, refresh_rate, interlaced),
color_encoding,
bit_depth,
frl_rate,
dsc_required,
false,
),
warnings: Vec::new(),
trace: ReasoningTrace::new(),
}
}
fn base() -> NegotiatedConfig<Warning> {
config(
1920,
1080,
60,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth8,
HdmiForumFrl::NotSupported,
false,
)
}
#[test]
fn color_format_quality_ordering() {
assert!(
color_format_quality(ColorFormat::Rgb444) > color_format_quality(ColorFormat::YCbCr444)
);
assert!(
color_format_quality(ColorFormat::YCbCr444)
> color_format_quality(ColorFormat::YCbCr422)
);
assert!(
color_format_quality(ColorFormat::YCbCr422)
> color_format_quality(ColorFormat::YCbCr420)
);
}
#[test]
fn color_format_quality_exact_values() {
assert_eq!(color_format_quality(ColorFormat::Rgb444), 3);
assert_eq!(color_format_quality(ColorFormat::YCbCr444), 2);
assert_eq!(color_format_quality(ColorFormat::YCbCr422), 1);
assert_eq!(color_format_quality(ColorFormat::YCbCr420), 0);
}
#[test]
fn pixel_area_multiplies_width_and_height() {
assert_eq!(pixel_area(&mode(1920, 1080)), 1920 * 1080);
assert_eq!(pixel_area(&mode(3840, 2160)), 3840 * 2160);
}
#[test]
fn pixel_area_zero_dimension() {
assert_eq!(pixel_area(&mode(0, 1080)), 0);
assert_eq!(pixel_area(&mode(1920, 0)), 0);
}
#[test]
fn pixel_area_does_not_overflow_u32() {
let area = pixel_area(&mode(u16::MAX, u16::MAX));
assert_eq!(area, u16::MAX as u32 * u16::MAX as u32);
}
const NATIVE: u32 = 1920 * 1080;
#[test]
fn dsc_penalized_ranks_lower() {
let no_dsc = base();
let with_dsc = config(
1920,
1080,
60,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth8,
HdmiForumFrl::NotSupported,
true,
);
let policy = NegotiationPolicy::BEST_QUALITY;
assert_eq!(
compare_configs(&no_dsc, &with_dsc, &policy, NATIVE),
Ordering::Less
);
assert_eq!(
compare_configs(&with_dsc, &no_dsc, &policy, NATIVE),
Ordering::Greater
);
}
#[test]
fn dsc_not_penalized_under_performance() {
let no_dsc = base(); let with_dsc = config(
1920,
1080,
120,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth8,
HdmiForumFrl::NotSupported,
true,
);
let policy = NegotiationPolicy::BEST_PERFORMANCE;
assert_eq!(
compare_configs(&with_dsc, &no_dsc, &policy, NATIVE),
Ordering::Less
);
}
#[test]
fn native_resolution_ranked_first() {
let uhd = config(
3840,
2160,
60,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth8,
HdmiForumFrl::NotSupported,
false,
);
let fhd = base();
let native_pixels = pixel_area(&uhd.resolved.mode); let policy = NegotiationPolicy::BEST_QUALITY;
assert_eq!(
compare_configs(&uhd, &fhd, &policy, native_pixels),
Ordering::Less
);
assert_eq!(
compare_configs(&fhd, &uhd, &policy, native_pixels),
Ordering::Greater
);
}
#[test]
fn native_resolution_equal_area_falls_through_to_next_criterion() {
let depth10 = config(
1920,
1080,
60,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth10,
HdmiForumFrl::NotSupported,
false,
);
let depth8 = base();
let policy = NegotiationPolicy::BEST_QUALITY; let native_pixels = NATIVE;
assert_eq!(
compare_configs(&depth10, &depth8, &policy, native_pixels),
Ordering::Less
);
assert_eq!(
compare_configs(&depth8, &depth10, &policy, native_pixels),
Ordering::Greater
);
}
#[test]
fn color_fidelity_prefers_higher_depth() {
let depth10 = config(
1920,
1080,
60,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth10,
HdmiForumFrl::NotSupported,
false,
);
let depth8 = base();
let policy = NegotiationPolicy::BEST_QUALITY;
assert_eq!(
compare_configs(&depth10, &depth8, &policy, NATIVE),
Ordering::Less
);
assert_eq!(
compare_configs(&depth8, &depth10, &policy, NATIVE),
Ordering::Greater
);
}
#[test]
fn color_fidelity_prefers_rgb_over_ycbcr444() {
let rgb = base(); let ycbcr = config(
1920,
1080,
60,
false,
ColorFormat::YCbCr444,
ColorBitDepth::Depth8,
HdmiForumFrl::NotSupported,
false,
);
let policy = NegotiationPolicy::BEST_QUALITY;
assert_eq!(
compare_configs(&rgb, &ycbcr, &policy, NATIVE),
Ordering::Less
);
assert_eq!(
compare_configs(&ycbcr, &rgb, &policy, NATIVE),
Ordering::Greater
);
}
#[test]
fn color_fidelity_equal_depth_falls_through_to_format() {
let rgb = base(); let ycbcr = config(
1920,
1080,
60,
false,
ColorFormat::YCbCr444,
ColorBitDepth::Depth8,
HdmiForumFrl::NotSupported,
false,
);
let policy = NegotiationPolicy::BEST_QUALITY;
assert_eq!(
compare_configs(&rgb, &ycbcr, &policy, NATIVE),
Ordering::Less
);
assert_eq!(
compare_configs(&ycbcr, &rgb, &policy, NATIVE),
Ordering::Greater
);
}
#[test]
fn color_fidelity_equal_depth_equal_format_falls_through_to_refresh() {
let hz120 = config(
1920,
1080,
120,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth8,
HdmiForumFrl::NotSupported,
false,
);
let hz60 = base();
let policy = NegotiationPolicy::BEST_QUALITY;
assert_eq!(
compare_configs(&hz120, &hz60, &policy, NATIVE),
Ordering::Less
);
assert_eq!(
compare_configs(&hz60, &hz120, &policy, NATIVE),
Ordering::Greater
);
}
#[test]
fn color_fidelity_prefers_higher_refresh_as_tiebreak() {
let hz120 = config(
1920,
1080,
120,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth8,
HdmiForumFrl::NotSupported,
false,
);
let hz60 = base();
let policy = NegotiationPolicy::BEST_QUALITY;
assert_eq!(
compare_configs(&hz120, &hz60, &policy, NATIVE),
Ordering::Less
);
}
#[test]
fn performance_prefers_high_refresh_over_depth() {
let hz120_8bit = base(); let hz120 = config(
1920,
1080,
120,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth8,
HdmiForumFrl::NotSupported,
false,
);
let hz60_10bit = config(
1920,
1080,
60,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth10,
HdmiForumFrl::NotSupported,
false,
);
let policy = NegotiationPolicy::BEST_PERFORMANCE;
let _ = hz120_8bit;
assert_eq!(
compare_configs(&hz120, &hz60_10bit, &policy, NATIVE),
Ordering::Less
);
assert_eq!(
compare_configs(&hz60_10bit, &hz120, &policy, NATIVE),
Ordering::Greater
);
}
#[test]
fn performance_equal_refresh_falls_through_to_depth() {
let depth10 = config(
1920,
1080,
60,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth10,
HdmiForumFrl::NotSupported,
false,
);
let depth8 = base();
let policy = NegotiationPolicy::BEST_PERFORMANCE;
assert_eq!(
compare_configs(&depth10, &depth8, &policy, NATIVE),
Ordering::Less
);
assert_eq!(
compare_configs(&depth8, &depth10, &policy, NATIVE),
Ordering::Greater
);
}
#[test]
fn performance_equal_refresh_equal_depth_falls_through_to_format() {
let rgb = base(); let ycbcr = config(
1920,
1080,
60,
false,
ColorFormat::YCbCr444,
ColorBitDepth::Depth8,
HdmiForumFrl::NotSupported,
false,
);
let policy = NegotiationPolicy::BEST_PERFORMANCE;
assert_eq!(
compare_configs(&rgb, &ycbcr, &policy, NATIVE),
Ordering::Less
);
assert_eq!(
compare_configs(&ycbcr, &rgb, &policy, NATIVE),
Ordering::Greater
);
}
#[test]
fn power_saving_prefers_low_refresh() {
let hz60 = base();
let hz120 = config(
1920,
1080,
120,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth8,
HdmiForumFrl::NotSupported,
false,
);
let policy = NegotiationPolicy::POWER_SAVING;
assert_eq!(
compare_configs(&hz60, &hz120, &policy, NATIVE),
Ordering::Less
);
assert_eq!(
compare_configs(&hz120, &hz60, &policy, NATIVE),
Ordering::Greater
);
}
#[test]
fn power_saving_prefers_low_depth() {
let depth8 = base();
let depth10 = config(
1920,
1080,
60,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth10,
HdmiForumFrl::NotSupported,
false,
);
let policy = NegotiationPolicy::POWER_SAVING;
assert_eq!(
compare_configs(&depth8, &depth10, &policy, NATIVE),
Ordering::Less
);
assert_eq!(
compare_configs(&depth10, &depth8, &policy, NATIVE),
Ordering::Greater
);
}
#[test]
fn power_saving_equal_refresh_falls_through_to_depth() {
let depth8 = base();
let depth10 = config(
1920,
1080,
60,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth10,
HdmiForumFrl::NotSupported,
false,
);
let policy = NegotiationPolicy::POWER_SAVING;
assert_eq!(
compare_configs(&depth8, &depth10, &policy, NATIVE),
Ordering::Less
);
assert_eq!(
compare_configs(&depth10, &depth8, &policy, NATIVE),
Ordering::Greater
);
}
#[test]
fn power_saving_equal_refresh_equal_depth_falls_through_to_format() {
let y420 = config(
1920,
1080,
60,
false,
ColorFormat::YCbCr420,
ColorBitDepth::Depth8,
HdmiForumFrl::NotSupported,
false,
);
let rgb = base();
let policy = NegotiationPolicy::POWER_SAVING;
assert_eq!(
compare_configs(&y420, &rgb, &policy, NATIVE),
Ordering::Less
);
assert_eq!(
compare_configs(&rgb, &y420, &policy, NATIVE),
Ordering::Greater
);
}
#[test]
fn power_saving_prefers_simpler_format() {
let y420 = config(
1920,
1080,
60,
false,
ColorFormat::YCbCr420,
ColorBitDepth::Depth8,
HdmiForumFrl::NotSupported,
false,
);
let rgb = base();
let policy = NegotiationPolicy::POWER_SAVING;
assert_eq!(
compare_configs(&y420, &rgb, &policy, NATIVE),
Ordering::Less
);
assert_eq!(
compare_configs(&rgb, &y420, &policy, NATIVE),
Ordering::Greater
);
}
#[test]
fn progressive_before_interlaced() {
let progressive = base();
let interlaced = config(
1920,
1080,
60,
true,
ColorFormat::Rgb444,
ColorBitDepth::Depth8,
HdmiForumFrl::NotSupported,
false,
);
let policy = NegotiationPolicy::BEST_QUALITY;
assert_eq!(
compare_configs(&progressive, &interlaced, &policy, NATIVE),
Ordering::Less
);
assert_eq!(
compare_configs(&interlaced, &progressive, &policy, NATIVE),
Ordering::Greater
);
}
#[test]
fn lower_frl_rate_tiebreak() {
let low_frl = config(
1920,
1080,
60,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth8,
HdmiForumFrl::Rate3Gbps3Lanes,
false,
);
let high_frl = config(
1920,
1080,
60,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth8,
HdmiForumFrl::Rate6Gbps3Lanes,
false,
);
let policy = NegotiationPolicy::BEST_QUALITY;
assert_eq!(
compare_configs(&low_frl, &high_frl, &policy, NATIVE),
Ordering::Less
);
assert_eq!(
compare_configs(&high_frl, &low_frl, &policy, NATIVE),
Ordering::Greater
);
}
#[test]
fn resolution_area_tiebreak() {
let wider = config(
1920,
1200,
60,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth8,
HdmiForumFrl::NotSupported,
false,
);
let narrower = base();
let native_pixels = pixel_area(&VideoMode::new(3840, 2160, 60, false)); let policy = NegotiationPolicy::BEST_QUALITY;
assert_eq!(
compare_configs(&wider, &narrower, &policy, native_pixels),
Ordering::Less
);
assert_eq!(
compare_configs(&narrower, &wider, &policy, native_pixels),
Ordering::Greater
);
}
fn has_preference(config: &NegotiatedConfig<Warning>, rule: &str) -> bool {
config
.trace
.steps
.iter()
.any(|step| matches!(step, DecisionStep::PreferenceApplied { rule: r } if r == rule))
}
#[test]
fn trace_records_dsc_penalty() {
let mut c = config(
1920,
1080,
60,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth8,
HdmiForumFrl::NotSupported,
true,
);
record_preferences(&mut c, &NegotiationPolicy::BEST_QUALITY, NATIVE);
assert!(has_preference(&c, "DSC penalized"));
}
#[test]
fn trace_no_dsc_penalty_when_not_penalized() {
let mut c = config(
1920,
1080,
60,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth8,
HdmiForumFrl::NotSupported,
true,
);
record_preferences(&mut c, &NegotiationPolicy::BEST_PERFORMANCE, NATIVE); assert!(!has_preference(&c, "DSC penalized"));
}
#[test]
fn trace_no_dsc_penalty_when_not_required() {
let mut c = base(); record_preferences(&mut c, &NegotiationPolicy::BEST_QUALITY, NATIVE);
assert!(!has_preference(&c, "DSC penalized"));
}
#[test]
fn trace_records_native_resolution() {
let mut c = base();
record_preferences(&mut c, &NegotiationPolicy::BEST_QUALITY, NATIVE); assert!(has_preference(&c, "native resolution preferred"));
}
#[test]
fn trace_no_native_resolution_when_not_native() {
let mut c = base();
let other_native = pixel_area(&VideoMode::new(3840, 2160, 60, false));
record_preferences(&mut c, &NegotiationPolicy::BEST_QUALITY, other_native);
assert!(!has_preference(&c, "native resolution preferred"));
}
#[test]
fn trace_no_native_resolution_when_not_preferred() {
let mut c = base();
let policy = NegotiationPolicy {
prefer_native_resolution: false,
..NegotiationPolicy::BEST_QUALITY
};
record_preferences(&mut c, &policy, NATIVE);
assert!(!has_preference(&c, "native resolution preferred"));
}
#[test]
fn trace_records_color_fidelity_preferred() {
let mut c = base();
record_preferences(&mut c, &NegotiationPolicy::BEST_QUALITY, NATIVE);
assert!(has_preference(&c, "color fidelity preferred"));
}
#[test]
fn trace_records_high_refresh_preferred() {
let mut c = base();
record_preferences(&mut c, &NegotiationPolicy::BEST_PERFORMANCE, NATIVE);
assert!(has_preference(&c, "high refresh rate preferred"));
}
#[test]
fn trace_records_power_saving_ordering() {
let mut c = base();
record_preferences(&mut c, &NegotiationPolicy::POWER_SAVING, NATIVE);
assert!(has_preference(&c, "power saving ordering applied"));
}
#[test]
fn trace_records_progressive_mode() {
let mut c = base(); record_preferences(&mut c, &NegotiationPolicy::BEST_QUALITY, NATIVE);
assert!(has_preference(&c, "progressive mode preferred"));
}
#[test]
fn trace_no_progressive_step_for_interlaced() {
let mut c = config(
1920,
1080,
60,
true,
ColorFormat::Rgb444,
ColorBitDepth::Depth8,
HdmiForumFrl::NotSupported,
false,
);
record_preferences(&mut c, &NegotiationPolicy::BEST_QUALITY, NATIVE);
assert!(!has_preference(&c, "progressive mode preferred"));
}
#[test]
fn equal_configs_returns_equal() {
let a = base();
let b = base();
let policy = NegotiationPolicy::BEST_QUALITY;
assert_eq!(compare_configs(&a, &b, &policy, NATIVE), Ordering::Equal);
}
#[test]
fn rank_empty_returns_empty() {
let result = DefaultRanker.rank(Vec::new(), &NegotiationPolicy::BEST_QUALITY);
assert!(result.is_empty());
}
#[test]
fn rank_single_config_appends_trace() {
let configs = alloc::vec![base()];
let result = DefaultRanker.rank(configs, &NegotiationPolicy::BEST_QUALITY);
assert_eq!(result.len(), 1);
assert!(!result[0].trace.steps.is_empty());
}
#[test]
fn rank_orders_multiple_configs() {
let configs = alloc::vec![
config(
1920,
1080,
60,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth8,
HdmiForumFrl::NotSupported,
true
),
base(),
config(
1920,
1080,
60,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth10,
HdmiForumFrl::NotSupported,
false
),
];
let result = DefaultRanker.rank(configs, &NegotiationPolicy::BEST_QUALITY);
assert_eq!(result[0].resolved.bit_depth, ColorBitDepth::Depth10);
assert!(!result[0].resolved.dsc_required);
assert_eq!(result[1].resolved.bit_depth, ColorBitDepth::Depth8);
assert!(!result[1].resolved.dsc_required);
assert!(result[2].resolved.dsc_required);
}
#[test]
fn rank_derives_native_pixels_from_accepted_set() {
let uhd = config(
3840,
2160,
60,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth8,
HdmiForumFrl::NotSupported,
false,
);
let fhd = base();
let result = DefaultRanker.rank(alloc::vec![fhd, uhd], &NegotiationPolicy::BEST_QUALITY);
assert_eq!(result[0].resolved.mode.width, 3840);
assert!(has_preference(&result[0], "native resolution preferred"));
assert!(!has_preference(&result[1], "native resolution preferred"));
}
#[test]
fn rank_records_preferences_on_all_configs() {
let configs = alloc::vec![
config(
1920,
1080,
60,
false,
ColorFormat::Rgb444,
ColorBitDepth::Depth10,
HdmiForumFrl::NotSupported,
false
),
base(),
config(
1920,
1080,
60,
false,
ColorFormat::YCbCr420,
ColorBitDepth::Depth8,
HdmiForumFrl::NotSupported,
false
),
];
let result = DefaultRanker.rank(configs, &NegotiationPolicy::BEST_QUALITY);
for c in &result {
assert!(has_preference(c, "color fidelity preferred"));
}
}
}