use { super::{copy_device::CopyDeviceHolder, lease::MetalLeaseData, properties::DefaultProperty}, crate::{ async_engine::SpawnedFuture, backend::{ BackendConnectorState, BackendLuminance, ConnectorEvent, ConnectorId, ConnectorKernelId, DrmDeviceId, DrmEvent, Mode, OutputId, }, backends::metal::{ MetalBackend, allocator::RenderBuffer, present::{DirectScanoutCache, PresentFb}, transaction::{DrmConnectorState, DrmCrtcState, DrmPlaneState}, }, cmm::{cmm_description::ColorDescription, cmm_primaries::Primaries}, drm_feedback::DrmFeedback, format::Format, gfx_api::{FdSync, GfxContext}, state::State, utils::{ asyncevent::AsyncEvent, binary_search_map::BinarySearchMap, clonecell::CloneCell, copyhashmap::CopyHashMap, geometric_decay::GeometricDecay, numcell::NumCell, on_change::OnChange, opaque_cell::OpaqueCell, }, video::{ Modifier, dmabuf::DmaBufId, drm::{ ConnectorStatus, DrmConnector, DrmCrtc, DrmEncoder, DrmMaster, DrmModeInfo, DrmObject, DrmPlane, DrmProperty, }, gbm::GbmDevice, }, }, ahash::AHashMap, indexmap::IndexSet, std::{ cell::{Cell, RefCell}, ffi::CString, fmt::{Debug, Formatter}, rc::Rc, }, uapi::c, }; pub struct PendingDrmDevice { pub id: DrmDeviceId, pub devnum: c::dev_t, pub devnode: CString, } #[derive(Debug)] pub struct MetalRenderContext { pub dev_id: DrmDeviceId, pub gfx: Rc, pub gbm: Rc, pub devnode: CString, pub copy_device: Rc, } pub struct MetalDrmDevice { pub backend: Rc, pub id: DrmDeviceId, pub devnum: c::dev_t, pub devnode: CString, pub master: Rc, pub supports_kms: bool, pub crtcs: AHashMap>, pub encoders: AHashMap>, pub planes: AHashMap>, pub cursor_width: u64, pub cursor_height: u64, pub supports_async_commit: bool, pub gbm: Rc, pub handle_events: HandleEvents, pub ctx: CloneCell>, pub copy_device: Rc, pub on_change: OnChange, pub direct_scanout_enabled: Cell>, pub is_nvidia: bool, pub _is_amd: bool, pub lease_ids: MetalLeaseIds, pub leases: CopyHashMap, pub leases_to_break: CopyHashMap, pub paused: Cell, pub min_post_commit_margin: Cell, } impl Debug for MetalDrmDevice { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("MetalDrmDevice").finish_non_exhaustive() } } impl MetalDrmDevice { pub fn is_render_device(&self) -> bool { if let Some(ctx) = self.backend.ctx.get() { return ctx.dev_id == self.id; } false } } pub struct HandleEvents { pub handle_events: Cell>>, } impl Debug for HandleEvents { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("HandleEvents").finish_non_exhaustive() } } #[derive(Debug)] pub struct MetalDrmDeviceData { pub dev: Rc, pub connectors: CopyHashMap>, pub futures: CopyHashMap, } #[derive(Debug)] pub struct PersistentDisplayData { pub state: RefCell, } #[derive(Debug)] pub struct ConnectorDisplayData { pub crtc_id: DrmProperty, pub crtcs: BinarySearchMap, 8>, pub first_mode: Mode, pub modes: Vec, pub persistent: Rc, pub refresh: u32, pub non_desktop: bool, pub non_desktop_effective: bool, pub vrr_capable: bool, pub _vrr_refresh_max_nsec: u64, pub default_properties: Vec, pub untyped_properties: AHashMap, pub connector_id: ConnectorKernelId, pub output_id: Rc, pub connection: ConnectorStatus, pub mm_width: u32, pub mm_height: u32, pub _subpixel: u32, pub supports_bt2020: bool, pub supports_pq: bool, pub primaries: Primaries, pub luminance: Option, pub colorspace: Option, pub hdr_metadata: Option, pub drm_state: DrmConnectorState, } impl ConnectorDisplayData { fn update_refresh(&mut self, dev: &MetalDrmDevice) { self.refresh = 0; if self.drm_state.crtc_id.is_none() { return; } let Some(crtc) = dev.crtcs.get(&self.drm_state.crtc_id) else { return; }; let drm_state = &*crtc.drm_state.borrow(); let Some(mode) = &drm_state.mode else { return; }; let refresh_rate_mhz = mode.refresh_rate_millihz(); if refresh_rate_mhz != 0 { self.refresh = (1_000_000_000_000u64 / refresh_rate_mhz as u64) as u32; } } fn update_non_desktop_effective(&mut self) { let state = &*self.persistent.state.borrow(); self.non_desktop_effective = !state.enabled || state.non_desktop_override.unwrap_or(self.non_desktop); } pub fn update_cached_fields(&mut self, dev: &MetalDrmDevice) { self.update_refresh(dev); self.update_non_desktop_effective(); } } linear_ids!(MetalLeaseIds, MetalLeaseId, u64); #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum FrontState { Removed, Disconnected, Connected { non_desktop: bool }, Unavailable, } pub struct MetalConnector { pub id: DrmConnector, pub kernel_id: Cell, pub master: Rc, pub state: Rc, pub dev: Rc, pub backend: Rc, pub connector_id: ConnectorId, pub buffers: CloneCell>>, pub color_description: CloneCell>, pub lease: Cell>, pub buffers_idle: Cell, pub crtc_idle: Cell, pub has_damage: NumCell, pub cursor_changed: Cell, pub cursor_damage: Cell, pub next_vblank_nsec: Cell, pub display: RefCell, pub frontend_state: Cell, pub primary_plane: CloneCell>>, pub cursor_plane: CloneCell>>, pub crtc: CloneCell>>, pub on_change: OnChange, pub present_trigger: AsyncEvent, pub cursor_x: Cell, pub cursor_y: Cell, pub cursor_enabled: Cell, pub cursor_buffers: CloneCell>>, pub cursor_swap_buffer: Cell, pub cursor_sync: CloneCell>, pub drm_feedback: CloneCell>>, pub scanout_buffers: RefCell>, pub active_framebuffer: RefCell>, pub next_framebuffer: OpaqueCell>, pub direct_scanout_active: Cell, pub version: NumCell, pub expected_sequence: Cell>, pub pre_commit_margin: Cell, pub pre_commit_margin_decay: GeometricDecay, pub post_commit_margin: Cell, pub post_commit_margin_decay: GeometricDecay, pub vblank_miss_sec: Cell, pub vblank_miss_this_sec: NumCell, pub presentation_is_sync: Cell, pub presentation_is_zero_copy: Cell, } impl Debug for MetalConnector { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("MetalConnnector").finish_non_exhaustive() } } pub struct ConnectorFutures { pub _present: SpawnedFuture<()>, } impl Debug for ConnectorFutures { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("ConnectorFutures").finish_non_exhaustive() } } pub struct MetalCrtc { pub id: DrmCrtc, pub idx: usize, pub master: Rc, pub default_properties: Vec, pub untyped_properties: RefCell>, pub lease: Cell>, pub possible_planes: BinarySearchMap, 8>, pub connector: CloneCell>>, pub pending_flip: CloneCell>>, pub active: DrmProperty, pub mode_id: DrmProperty, pub vrr_enabled: DrmProperty, pub out_fence_ptr: DrmProperty, pub gamma_lut: Option, pub gamma_lut_size: Option, pub drm_state: RefCell, pub sequence: Cell, pub have_queued_sequence: Cell, pub needs_vblank_emulation: Cell, } impl Debug for MetalCrtc { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("MetalCrtc").finish_non_exhaustive() } } #[derive(Debug)] pub struct MetalEncoder { pub id: DrmEncoder, pub crtcs: AHashMap>, } #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum PlaneType { Overlay, Primary, Cursor, } #[derive(Debug)] pub struct PlaneFormat { pub format: &'static Format, pub modifiers: IndexSet, } pub struct MetalPlane { pub id: DrmPlane, pub master: Rc, pub default_properties: Vec, pub untyped_properties: RefCell>, pub ty: PlaneType, pub possible_crtcs: u32, pub formats: AHashMap, pub lease: Cell>, pub mode_w: Cell, pub mode_h: Cell, pub crtc_id: DrmProperty, pub crtc_x: DrmProperty, pub crtc_y: DrmProperty, pub crtc_w: DrmProperty, pub crtc_h: DrmProperty, pub src_x: DrmProperty, pub src_y: DrmProperty, pub src_w: DrmProperty, pub src_h: DrmProperty, pub in_fence_fd: DrmProperty, pub fb_id: DrmProperty, pub drm_state: RefCell, } impl Debug for MetalPlane { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("MetalPlane").finish_non_exhaustive() } }