use crate::model::diagnostics::EdidWarning;
use crate::model::manufacture::{ManufacturerId, MonitorString};
pub use display_types::{
CvtAlgorithm, ModeSource, RefreshRate, StereoMode, SyncDefinition, TypeIxStereoMode, VideoMode,
};
pub use display_types::{DisplayCapabilities, ExtensionData};
pub trait ModeSink {
fn push_mode(&mut self, mode: VideoMode);
fn push_warning(&mut self, w: EdidWarning);
}
pub struct StaticContext<'a> {
modes: &'a mut dyn ModeSink,
}
impl<'a> StaticContext<'a> {
pub fn new(modes: &'a mut dyn ModeSink) -> Self {
Self { modes }
}
pub fn push_mode(&mut self, mode: VideoMode) {
self.modes.push_mode(mode);
}
pub fn push_warning(&mut self, w: EdidWarning) {
self.modes.push_warning(w);
}
}
impl ModeSink for StaticContext<'_> {
fn push_mode(&mut self, mode: VideoMode) {
self.modes.push_mode(mode);
}
fn push_warning(&mut self, w: EdidWarning) {
self.modes.push_warning(w);
}
}
#[cfg(any(feature = "alloc", feature = "std"))]
impl ModeSink for DisplayCapabilities {
fn push_mode(&mut self, mode: VideoMode) {
if !self.supported_modes.contains(&mode) {
self.supported_modes.push(mode);
}
}
fn push_warning(&mut self, w: EdidWarning) {
self.push_warning(w);
}
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct StaticDisplayCapabilities<const MAX_MODES: usize> {
pub manufacturer: Option<ManufacturerId>,
pub manufacture_date: Option<crate::model::manufacture::ManufactureDate>,
pub edid_version: Option<crate::model::edid::EdidVersion>,
pub product_code: Option<u16>,
pub serial_number: Option<u32>,
pub serial_number_string: Option<MonitorString>,
pub display_name: Option<MonitorString>,
pub unspecified_text: [Option<MonitorString>; 4],
pub white_points: [Option<crate::model::color::WhitePoint>; 2],
pub digital: bool,
pub color_bit_depth: Option<crate::model::color::ColorBitDepth>,
pub display_technology: Option<crate::model::panel::DisplayTechnology>,
pub display_subtype: Option<u8>,
pub operating_mode: Option<crate::model::panel::OperatingMode>,
pub backlight_type: Option<crate::model::panel::BacklightType>,
pub data_enable_used: Option<bool>,
pub data_enable_positive: Option<bool>,
pub native_pixels: Option<(u16, u16)>,
pub panel_aspect_ratio_100: Option<u8>,
pub physical_orientation: Option<crate::model::panel::PhysicalOrientation>,
pub rotation_capability: Option<crate::model::panel::RotationCapability>,
pub zero_pixel_location: Option<crate::model::panel::ZeroPixelLocation>,
pub scan_direction: Option<crate::model::panel::ScanDirection>,
pub subpixel_layout: Option<crate::model::panel::SubpixelLayout>,
pub pixel_pitch_hundredths_mm: Option<(u8, u8)>,
pub pixel_response_time_ms: Option<u8>,
pub power_sequencing: Option<crate::model::panel::PowerSequencing>,
pub display_id_interface: Option<crate::model::panel::DisplayIdInterface>,
pub stereo_interface: Option<crate::model::panel::DisplayIdStereoInterface>,
pub tiled_topology: Option<crate::model::panel::DisplayIdTiledTopology>,
pub chromaticity: crate::model::color::Chromaticity,
pub gamma: Option<crate::model::color::DisplayGamma>,
pub display_features: Option<crate::model::features::DisplayFeatureFlags>,
pub digital_color_encoding: Option<crate::model::color::DigitalColorEncoding>,
pub analog_color_type: Option<crate::model::color::AnalogColorType>,
pub video_interface: Option<crate::model::input::VideoInterface>,
pub analog_sync_level: Option<crate::model::input::AnalogSyncLevel>,
pub screen_size: Option<crate::model::screen::ScreenSize>,
pub min_v_rate: Option<u16>,
pub max_v_rate: Option<u16>,
pub min_h_rate_khz: Option<u16>,
pub max_h_rate_khz: Option<u16>,
pub max_pixel_clock_mhz: Option<u16>,
pub preferred_image_size_mm: Option<(u16, u16)>,
pub timing_formula: Option<crate::model::timing::TimingFormula>,
pub color_management: Option<crate::model::color::ColorManagementData>,
pub supported_modes: [Option<VideoMode>; MAX_MODES],
pub num_modes: usize,
pub warnings: [Option<EdidWarning>; 8],
pub num_warnings: usize,
}
impl<const MAX_MODES: usize> Default for StaticDisplayCapabilities<MAX_MODES> {
fn default() -> Self {
Self {
manufacturer: None,
manufacture_date: None,
edid_version: None,
product_code: None,
serial_number: None,
serial_number_string: None,
display_name: None,
unspecified_text: Default::default(),
white_points: Default::default(),
digital: false,
color_bit_depth: None,
display_technology: None,
display_subtype: None,
operating_mode: None,
backlight_type: None,
data_enable_used: None,
data_enable_positive: None,
native_pixels: None,
panel_aspect_ratio_100: None,
physical_orientation: None,
rotation_capability: None,
zero_pixel_location: None,
scan_direction: None,
subpixel_layout: None,
pixel_pitch_hundredths_mm: None,
pixel_response_time_ms: None,
power_sequencing: None,
display_id_interface: None,
stereo_interface: None,
tiled_topology: None,
chromaticity: Default::default(),
gamma: None,
display_features: None,
digital_color_encoding: None,
analog_color_type: None,
video_interface: None,
analog_sync_level: None,
screen_size: None,
min_v_rate: None,
max_v_rate: None,
min_h_rate_khz: None,
max_h_rate_khz: None,
max_pixel_clock_mhz: None,
preferred_image_size_mm: None,
timing_formula: None,
color_management: None,
supported_modes: core::array::from_fn(|_| None),
num_modes: 0,
warnings: Default::default(),
num_warnings: 0,
}
}
}
impl<const MAX_MODES: usize> StaticDisplayCapabilities<MAX_MODES> {
pub fn iter_modes(&self) -> impl Iterator<Item = &VideoMode> {
self.supported_modes[..self.num_modes].iter().flatten()
}
pub fn iter_warnings(&self) -> impl Iterator<Item = &EdidWarning> {
self.warnings[..self.num_warnings].iter().flatten()
}
}
impl<const MAX_MODES: usize> ModeSink for StaticDisplayCapabilities<MAX_MODES> {
fn push_mode(&mut self, mode: VideoMode) {
if self.num_modes < MAX_MODES {
for i in 0..self.num_modes {
if let Some(existing) = &self.supported_modes[i] {
if existing.width == mode.width
&& existing.height == mode.height
&& existing.refresh_rate == mode.refresh_rate
&& existing.interlaced == mode.interlaced
{
return;
}
}
}
self.supported_modes[self.num_modes] = Some(mode);
self.num_modes += 1;
}
}
fn push_warning(&mut self, w: EdidWarning) {
if self.num_warnings < 8 {
self.warnings[self.num_warnings] = Some(w);
self.num_warnings += 1;
}
}
}