use crate::VideoMode;
pub fn pixel_clock_khz_cvt_rb_estimate(mode: &VideoMode) -> u32 {
if let Some(clk) = mode.pixel_clock_khz {
return clk;
}
let h_total = mode.width as u64 + 160;
let v_total = mode.height as u64 + 8;
(h_total * v_total * mode.refresh_rate as u64 / 1000) as u32
}
#[cfg(test)]
mod tests {
use super::*;
use crate::VideoMode;
#[test]
fn exact_clock_returned_unchanged() {
let mode = VideoMode::new(1920, 1080, 60, false).with_detailed_timing(
148_500,
88,
44,
4,
5,
0,
0,
Default::default(),
None,
);
assert_eq!(pixel_clock_khz_cvt_rb_estimate(&mode), 148_500);
}
#[test]
fn non_dtd_mode_uses_cvt_rb_formula() {
let mode = VideoMode::new(1920, 1080, 60, false);
assert_eq!(pixel_clock_khz_cvt_rb_estimate(&mode), 135_782);
}
#[test]
fn zero_refresh_rate_returns_zero() {
let mode = VideoMode::new(1920, 1080, 0, false);
assert_eq!(pixel_clock_khz_cvt_rb_estimate(&mode), 0);
}
}
#[non_exhaustive]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TimingFormula {
DefaultGtf,
RangeLimitsOnly,
SecondaryGtf(GtfSecondaryParams),
Cvt(CvtSupportParams),
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GtfSecondaryParams {
pub start_freq_khz: u16,
pub c: u8,
pub m: u16,
pub k: u8,
pub j: u8,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CvtSupportParams {
pub version: u8,
pub pixel_clock_adjust: u8,
pub max_h_active_pixels: Option<u16>,
pub supported_aspect_ratios: CvtAspectRatios,
pub preferred_aspect_ratio: Option<CvtAspectRatio>,
pub standard_blanking: bool,
pub reduced_blanking: bool,
pub scaling: CvtScaling,
pub preferred_v_rate: Option<u8>,
}
bitflags::bitflags! {
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct CvtAspectRatios: u8 {
const R4_3 = 0x80;
const R16_9 = 0x40;
const R16_10 = 0x20;
const R5_4 = 0x10;
const R15_9 = 0x08;
}
}
bitflags::bitflags! {
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct CvtScaling: u8 {
const HORIZONTAL_SHRINK = 0x80;
const HORIZONTAL_STRETCH = 0x40;
const VERTICAL_SHRINK = 0x20;
const VERTICAL_STRETCH = 0x10;
}
}
#[non_exhaustive]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CvtAspectRatio {
R4_3,
R16_9,
R16_10,
R5_4,
R15_9,
}