metal: split video object model
This commit is contained in:
parent
774177390e
commit
7a49da0a48
5 changed files with 424 additions and 354 deletions
|
|
@ -1,6 +1,7 @@
|
|||
mod copy_device;
|
||||
mod hardware_cursor;
|
||||
mod lease;
|
||||
mod model;
|
||||
mod properties;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
|
|
@ -8,6 +9,12 @@ pub use {
|
|||
copy_device::CopyDeviceHolder,
|
||||
hardware_cursor::{MetalHardwareCursor, MetalHardwareCursorChange},
|
||||
lease::{MetalLease, MetalLeaseData},
|
||||
model::{
|
||||
ConnectorDisplayData, ConnectorFutures, FrontState, HandleEvents, MetalConnector,
|
||||
MetalCrtc, MetalDrmDevice, MetalDrmDeviceData, MetalEncoder, MetalLeaseId, MetalLeaseIds,
|
||||
MetalPlane, MetalRenderContext, PendingDrmDevice, PersistentDisplayData, PlaneFormat,
|
||||
PlaneType,
|
||||
},
|
||||
properties::{DefaultProperty, TypedProperty},
|
||||
};
|
||||
|
||||
|
|
@ -17,13 +24,13 @@ use properties::{
|
|||
|
||||
use {
|
||||
crate::{
|
||||
async_engine::{Phase, SpawnedFuture},
|
||||
async_engine::Phase,
|
||||
backend::{
|
||||
BackendColorSpace, BackendConnectorState, BackendDrmDevice, BackendDrmLease,
|
||||
BackendDrmLessee, BackendEotfs, BackendEvent, BackendGammaLut, BackendGammaLutElement,
|
||||
BackendColorSpace, BackendConnectorState, BackendDrmDevice, BackendDrmLessee,
|
||||
BackendEotfs, BackendEvent, BackendGammaLut, BackendGammaLutElement,
|
||||
BackendLuminance, CONCAP_CONNECTOR, CONCAP_MODE_SETTING, CONCAP_PHYSICAL_DISPLAY,
|
||||
Connector, ConnectorCaps, ConnectorEvent, ConnectorId, ConnectorKernelId, DrmDeviceId,
|
||||
HardwareCursor, HardwareCursorUpdate, Mode, MonitorInfo, OutputId,
|
||||
Mode, MonitorInfo, OutputId,
|
||||
transaction::{
|
||||
BackendConnectorTransaction, BackendConnectorTransactionError,
|
||||
BackendConnectorTransactionType, BackendConnectorTransactionTypeDyn,
|
||||
|
|
@ -31,37 +38,32 @@ use {
|
|||
},
|
||||
backends::metal::{
|
||||
MetalBackend, MetalError,
|
||||
allocator::RenderBuffer,
|
||||
present::{
|
||||
DEFAULT_POST_COMMIT_MARGIN, DEFAULT_PRE_COMMIT_MARGIN, DirectScanoutCache,
|
||||
POST_COMMIT_MARGIN_DELTA, PresentFb,
|
||||
DEFAULT_POST_COMMIT_MARGIN, DEFAULT_PRE_COMMIT_MARGIN, POST_COMMIT_MARGIN_DELTA,
|
||||
},
|
||||
transaction::{DrmConnectorState, DrmCrtcState, DrmPlaneState, MetalDeviceTransaction},
|
||||
},
|
||||
cmm::{cmm_description::ColorDescription, cmm_primaries::Primaries},
|
||||
copy_device::{CopyDevice, CopyDeviceRegistry},
|
||||
cmm::cmm_primaries::Primaries,
|
||||
drm_feedback::DrmFeedback,
|
||||
edid::{CtaDataBlock, Descriptor, EdidExtension},
|
||||
format::{Format, XRGB8888},
|
||||
gfx_api::{FdSync, GfxApi, GfxContext, GfxFramebuffer},
|
||||
format::XRGB8888,
|
||||
gfx_api::GfxApi,
|
||||
ifs::wp_presentation_feedback::{KIND_HW_COMPLETION, KIND_VSYNC, KIND_ZERO_COPY},
|
||||
state::State,
|
||||
tree::OutputNode,
|
||||
udev::UdevDevice,
|
||||
utils::{
|
||||
asyncevent::AsyncEvent, binary_search_map::BinarySearchMap, bitflags::BitflagsExt,
|
||||
cell_ext::CellExt, clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt,
|
||||
geometric_decay::GeometricDecay, numcell::NumCell, on_change::OnChange,
|
||||
opaque_cell::OpaqueCell, ordered_float::F64, oserror::OsError,
|
||||
binary_search_map::BinarySearchMap, bitflags::BitflagsExt, cell_ext::CellExt,
|
||||
clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt,
|
||||
geometric_decay::GeometricDecay, numcell::NumCell, ordered_float::F64,
|
||||
oserror::OsError,
|
||||
},
|
||||
video::{
|
||||
INVALID_MODIFIER, Modifier,
|
||||
dmabuf::DmaBufId,
|
||||
INVALID_MODIFIER,
|
||||
drm::{
|
||||
ConnectorStatus, ConnectorType, DRM_CLIENT_CAP_ATOMIC, DrmBlob, DrmCardResources,
|
||||
DrmConnector, DrmCrtc, DrmEncoder, DrmError, DrmEvent, DrmFb, DrmLease, DrmMaster,
|
||||
DrmModeInfo, DrmObject, DrmPlane, DrmProperty, DrmPropertyDefinition,
|
||||
DrmPropertyType, DrmVersion, HDMI_EOTF_TRADITIONAL_GAMMA_SDR, drm_mode_modeinfo,
|
||||
DrmConnector, DrmCrtc, DrmEncoder, DrmError, DrmEvent, DrmFb, DrmMaster,
|
||||
DrmObject, DrmPlane, DrmProperty, DrmPropertyDefinition, DrmPropertyType,
|
||||
DrmVersion, HDMI_EOTF_TRADITIONAL_GAMMA_SDR, drm_mode_modeinfo,
|
||||
hdr_output_metadata,
|
||||
},
|
||||
gbm::GbmDevice,
|
||||
|
|
@ -69,82 +71,18 @@ use {
|
|||
},
|
||||
ahash::{AHashMap, AHashSet},
|
||||
bstr::{BString, ByteSlice},
|
||||
indexmap::{IndexSet, indexset},
|
||||
indexmap::indexset,
|
||||
isnt::std_1::collections::IsntHashMapExt,
|
||||
std::{
|
||||
cell::{Cell, OnceCell, RefCell},
|
||||
cell::{Cell, RefCell},
|
||||
collections::hash_map::Entry,
|
||||
ffi::CString,
|
||||
fmt::{Debug, Formatter},
|
||||
mem,
|
||||
ops::DerefMut,
|
||||
rc::Rc,
|
||||
},
|
||||
uapi::{
|
||||
OwnedFd,
|
||||
c::{self, dev_t},
|
||||
},
|
||||
uapi::c::{self, dev_t},
|
||||
};
|
||||
|
||||
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<dyn GfxContext>,
|
||||
pub gbm: Rc<GbmDevice>,
|
||||
pub devnode: CString,
|
||||
pub copy_device: Rc<CopyDeviceHolder>,
|
||||
}
|
||||
|
||||
|
||||
pub struct MetalDrmDevice {
|
||||
pub backend: Rc<MetalBackend>,
|
||||
pub id: DrmDeviceId,
|
||||
pub devnum: c::dev_t,
|
||||
pub devnode: CString,
|
||||
pub master: Rc<DrmMaster>,
|
||||
pub supports_kms: bool,
|
||||
pub crtcs: AHashMap<DrmCrtc, Rc<MetalCrtc>>,
|
||||
pub encoders: AHashMap<DrmEncoder, Rc<MetalEncoder>>,
|
||||
pub planes: AHashMap<DrmPlane, Rc<MetalPlane>>,
|
||||
pub cursor_width: u64,
|
||||
pub cursor_height: u64,
|
||||
pub supports_async_commit: bool,
|
||||
pub gbm: Rc<GbmDevice>,
|
||||
pub handle_events: HandleEvents,
|
||||
pub ctx: CloneCell<Rc<MetalRenderContext>>,
|
||||
pub copy_device: Rc<CopyDeviceHolder>,
|
||||
pub on_change: OnChange<crate::backend::DrmEvent>,
|
||||
pub direct_scanout_enabled: Cell<Option<bool>>,
|
||||
pub is_nvidia: bool,
|
||||
pub _is_amd: bool,
|
||||
pub lease_ids: MetalLeaseIds,
|
||||
pub leases: CopyHashMap<MetalLeaseId, MetalLeaseData>,
|
||||
pub leases_to_break: CopyHashMap<MetalLeaseId, MetalLeaseData>,
|
||||
pub paused: Cell<bool>,
|
||||
pub min_post_commit_margin: Cell<u64>,
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
impl BackendDrmDevice for MetalDrmDevice {
|
||||
fn id(&self) -> DrmDeviceId {
|
||||
self.id
|
||||
|
|
@ -326,180 +264,6 @@ impl BackendDrmDevice for MetalDrmDevice {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct HandleEvents {
|
||||
pub handle_events: Cell<Option<SpawnedFuture<()>>>,
|
||||
}
|
||||
|
||||
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<MetalDrmDevice>,
|
||||
pub connectors: CopyHashMap<DrmConnector, Rc<MetalConnector>>,
|
||||
pub futures: CopyHashMap<DrmConnector, ConnectorFutures>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PersistentDisplayData {
|
||||
pub state: RefCell<BackendConnectorState>,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ConnectorDisplayData {
|
||||
pub crtc_id: DrmProperty,
|
||||
pub crtcs: BinarySearchMap<DrmCrtc, Rc<MetalCrtc>, 8>,
|
||||
pub first_mode: Mode,
|
||||
pub modes: Vec<DrmModeInfo>,
|
||||
pub persistent: Rc<PersistentDisplayData>,
|
||||
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<DefaultProperty>,
|
||||
pub untyped_properties: AHashMap<DrmProperty, u64>,
|
||||
|
||||
pub connector_id: ConnectorKernelId,
|
||||
pub output_id: Rc<OutputId>,
|
||||
|
||||
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<BackendLuminance>,
|
||||
|
||||
pub colorspace: Option<DrmProperty>,
|
||||
pub hdr_metadata: Option<DrmProperty>,
|
||||
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<ConnectorKernelId>,
|
||||
pub master: Rc<DrmMaster>,
|
||||
pub state: Rc<State>,
|
||||
|
||||
pub dev: Rc<MetalDrmDevice>,
|
||||
pub backend: Rc<MetalBackend>,
|
||||
|
||||
pub connector_id: ConnectorId,
|
||||
|
||||
pub buffers: CloneCell<Option<Rc<[RenderBuffer; 2]>>>,
|
||||
pub color_description: CloneCell<Rc<ColorDescription>>,
|
||||
|
||||
pub lease: Cell<Option<MetalLeaseId>>,
|
||||
|
||||
pub buffers_idle: Cell<bool>,
|
||||
pub crtc_idle: Cell<bool>,
|
||||
pub has_damage: NumCell<u64>,
|
||||
pub cursor_changed: Cell<bool>,
|
||||
pub cursor_damage: Cell<bool>,
|
||||
pub next_vblank_nsec: Cell<u64>,
|
||||
|
||||
pub display: RefCell<ConnectorDisplayData>,
|
||||
|
||||
pub frontend_state: Cell<FrontState>,
|
||||
|
||||
pub primary_plane: CloneCell<Option<Rc<MetalPlane>>>,
|
||||
pub cursor_plane: CloneCell<Option<Rc<MetalPlane>>>,
|
||||
|
||||
pub crtc: CloneCell<Option<Rc<MetalCrtc>>>,
|
||||
|
||||
pub on_change: OnChange<ConnectorEvent>,
|
||||
|
||||
pub present_trigger: AsyncEvent,
|
||||
|
||||
pub cursor_x: Cell<i32>,
|
||||
pub cursor_y: Cell<i32>,
|
||||
pub cursor_enabled: Cell<bool>,
|
||||
pub cursor_buffers: CloneCell<Option<Rc<[RenderBuffer; 2]>>>,
|
||||
pub cursor_swap_buffer: Cell<bool>,
|
||||
pub cursor_sync: CloneCell<Option<FdSync>>,
|
||||
|
||||
pub drm_feedback: CloneCell<Option<Rc<DrmFeedback>>>,
|
||||
pub scanout_buffers: RefCell<AHashMap<DmaBufId, DirectScanoutCache>>,
|
||||
pub active_framebuffer: RefCell<Option<PresentFb>>,
|
||||
pub next_framebuffer: OpaqueCell<Option<PresentFb>>,
|
||||
pub direct_scanout_active: Cell<bool>,
|
||||
|
||||
pub version: NumCell<u64>,
|
||||
pub expected_sequence: Cell<Option<u64>>,
|
||||
pub pre_commit_margin: Cell<u64>,
|
||||
pub pre_commit_margin_decay: GeometricDecay,
|
||||
pub post_commit_margin: Cell<u64>,
|
||||
pub post_commit_margin_decay: GeometricDecay,
|
||||
pub vblank_miss_sec: Cell<u32>,
|
||||
pub vblank_miss_this_sec: NumCell<u32>,
|
||||
pub presentation_is_sync: Cell<bool>,
|
||||
pub presentation_is_zero_copy: Cell<bool>,
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
impl MetalConnector {
|
||||
pub fn send_connected(self: &Rc<Self>) {
|
||||
let dd = &*self.display.borrow();
|
||||
|
|
@ -792,95 +556,6 @@ impl Connector for MetalConnector {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct MetalCrtc {
|
||||
pub id: DrmCrtc,
|
||||
pub idx: usize,
|
||||
pub master: Rc<DrmMaster>,
|
||||
pub default_properties: Vec<DefaultProperty>,
|
||||
pub untyped_properties: RefCell<AHashMap<DrmProperty, u64>>,
|
||||
|
||||
pub lease: Cell<Option<MetalLeaseId>>,
|
||||
|
||||
pub possible_planes: BinarySearchMap<DrmPlane, Rc<MetalPlane>, 8>,
|
||||
|
||||
pub connector: CloneCell<Option<Rc<MetalConnector>>>,
|
||||
pub pending_flip: CloneCell<Option<Rc<MetalConnector>>>,
|
||||
|
||||
pub active: DrmProperty,
|
||||
pub mode_id: DrmProperty,
|
||||
pub vrr_enabled: DrmProperty,
|
||||
pub out_fence_ptr: DrmProperty,
|
||||
pub gamma_lut: Option<DrmProperty>,
|
||||
pub gamma_lut_size: Option<u32>,
|
||||
pub drm_state: RefCell<DrmCrtcState>,
|
||||
|
||||
pub sequence: Cell<u64>,
|
||||
pub have_queued_sequence: Cell<bool>,
|
||||
pub needs_vblank_emulation: Cell<bool>,
|
||||
}
|
||||
|
||||
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<DrmCrtc, Rc<MetalCrtc>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum PlaneType {
|
||||
Overlay,
|
||||
Primary,
|
||||
Cursor,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PlaneFormat {
|
||||
pub format: &'static Format,
|
||||
pub modifiers: IndexSet<Modifier>,
|
||||
}
|
||||
|
||||
pub struct MetalPlane {
|
||||
pub id: DrmPlane,
|
||||
pub master: Rc<DrmMaster>,
|
||||
pub default_properties: Vec<DefaultProperty>,
|
||||
pub untyped_properties: RefCell<AHashMap<DrmProperty, u64>>,
|
||||
|
||||
pub ty: PlaneType,
|
||||
|
||||
pub possible_crtcs: u32,
|
||||
pub formats: AHashMap<u32, PlaneFormat>,
|
||||
|
||||
pub lease: Cell<Option<MetalLeaseId>>,
|
||||
|
||||
pub mode_w: Cell<i32>,
|
||||
pub mode_h: Cell<i32>,
|
||||
|
||||
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<DrmPlaneState>,
|
||||
}
|
||||
|
||||
impl Debug for MetalPlane {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("MetalPlane").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_connectors(
|
||||
backend: &Rc<MetalBackend>,
|
||||
dev: &Rc<MetalDrmDevice>,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,15 @@
|
|||
use super::*;
|
||||
use {
|
||||
crate::{
|
||||
copy_device::{CopyDevice, CopyDeviceRegistry},
|
||||
utils::errorfmt::ErrorFmt,
|
||||
},
|
||||
std::{
|
||||
cell::OnceCell,
|
||||
fmt::{Debug, Formatter},
|
||||
rc::Rc,
|
||||
},
|
||||
uapi::c::dev_t,
|
||||
};
|
||||
|
||||
pub struct CopyDeviceHolder {
|
||||
pub registry: Rc<CopyDeviceRegistry>,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,15 @@
|
|||
use super::*;
|
||||
use {
|
||||
super::MetalConnector,
|
||||
crate::{
|
||||
backend::{HardwareCursor, HardwareCursorUpdate},
|
||||
backends::metal::allocator::RenderBuffer,
|
||||
gfx_api::{FdSync, GfxFramebuffer},
|
||||
},
|
||||
std::{
|
||||
fmt::{Debug, Formatter},
|
||||
rc::Rc,
|
||||
},
|
||||
};
|
||||
|
||||
pub struct MetalHardwareCursor {
|
||||
pub connector: Rc<MetalConnector>,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,13 @@
|
|||
use super::*;
|
||||
use {
|
||||
super::{FrontState, MetalConnector, MetalCrtc, MetalDrmDevice, MetalLeaseId, MetalPlane},
|
||||
crate::{
|
||||
backend::{BackendDrmLease, BackendDrmLessee, ConnectorEvent},
|
||||
utils::errorfmt::ErrorFmt,
|
||||
video::drm::DrmLease,
|
||||
},
|
||||
std::{cell::Cell, rc::Rc},
|
||||
uapi::OwnedFd,
|
||||
};
|
||||
|
||||
pub struct MetalLeaseData {
|
||||
pub lease: DrmLease,
|
||||
|
|
|
|||
364
src/backends/metal/video/model.rs
Normal file
364
src/backends/metal/video/model.rs
Normal file
|
|
@ -0,0 +1,364 @@
|
|||
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<dyn GfxContext>,
|
||||
pub gbm: Rc<GbmDevice>,
|
||||
pub devnode: CString,
|
||||
pub copy_device: Rc<CopyDeviceHolder>,
|
||||
}
|
||||
|
||||
pub struct MetalDrmDevice {
|
||||
pub backend: Rc<MetalBackend>,
|
||||
pub id: DrmDeviceId,
|
||||
pub devnum: c::dev_t,
|
||||
pub devnode: CString,
|
||||
pub master: Rc<DrmMaster>,
|
||||
pub supports_kms: bool,
|
||||
pub crtcs: AHashMap<DrmCrtc, Rc<MetalCrtc>>,
|
||||
pub encoders: AHashMap<DrmEncoder, Rc<MetalEncoder>>,
|
||||
pub planes: AHashMap<DrmPlane, Rc<MetalPlane>>,
|
||||
pub cursor_width: u64,
|
||||
pub cursor_height: u64,
|
||||
pub supports_async_commit: bool,
|
||||
pub gbm: Rc<GbmDevice>,
|
||||
pub handle_events: HandleEvents,
|
||||
pub ctx: CloneCell<Rc<MetalRenderContext>>,
|
||||
pub copy_device: Rc<CopyDeviceHolder>,
|
||||
pub on_change: OnChange<DrmEvent>,
|
||||
pub direct_scanout_enabled: Cell<Option<bool>>,
|
||||
pub is_nvidia: bool,
|
||||
pub _is_amd: bool,
|
||||
pub lease_ids: MetalLeaseIds,
|
||||
pub leases: CopyHashMap<MetalLeaseId, MetalLeaseData>,
|
||||
pub leases_to_break: CopyHashMap<MetalLeaseId, MetalLeaseData>,
|
||||
pub paused: Cell<bool>,
|
||||
pub min_post_commit_margin: Cell<u64>,
|
||||
}
|
||||
|
||||
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<Option<SpawnedFuture<()>>>,
|
||||
}
|
||||
|
||||
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<MetalDrmDevice>,
|
||||
pub connectors: CopyHashMap<DrmConnector, Rc<MetalConnector>>,
|
||||
pub futures: CopyHashMap<DrmConnector, ConnectorFutures>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PersistentDisplayData {
|
||||
pub state: RefCell<BackendConnectorState>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ConnectorDisplayData {
|
||||
pub crtc_id: DrmProperty,
|
||||
pub crtcs: BinarySearchMap<DrmCrtc, Rc<MetalCrtc>, 8>,
|
||||
pub first_mode: Mode,
|
||||
pub modes: Vec<DrmModeInfo>,
|
||||
pub persistent: Rc<PersistentDisplayData>,
|
||||
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<DefaultProperty>,
|
||||
pub untyped_properties: AHashMap<DrmProperty, u64>,
|
||||
|
||||
pub connector_id: ConnectorKernelId,
|
||||
pub output_id: Rc<OutputId>,
|
||||
|
||||
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<BackendLuminance>,
|
||||
|
||||
pub colorspace: Option<DrmProperty>,
|
||||
pub hdr_metadata: Option<DrmProperty>,
|
||||
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<ConnectorKernelId>,
|
||||
pub master: Rc<DrmMaster>,
|
||||
pub state: Rc<State>,
|
||||
|
||||
pub dev: Rc<MetalDrmDevice>,
|
||||
pub backend: Rc<MetalBackend>,
|
||||
|
||||
pub connector_id: ConnectorId,
|
||||
|
||||
pub buffers: CloneCell<Option<Rc<[RenderBuffer; 2]>>>,
|
||||
pub color_description: CloneCell<Rc<ColorDescription>>,
|
||||
|
||||
pub lease: Cell<Option<MetalLeaseId>>,
|
||||
|
||||
pub buffers_idle: Cell<bool>,
|
||||
pub crtc_idle: Cell<bool>,
|
||||
pub has_damage: NumCell<u64>,
|
||||
pub cursor_changed: Cell<bool>,
|
||||
pub cursor_damage: Cell<bool>,
|
||||
pub next_vblank_nsec: Cell<u64>,
|
||||
|
||||
pub display: RefCell<ConnectorDisplayData>,
|
||||
|
||||
pub frontend_state: Cell<FrontState>,
|
||||
|
||||
pub primary_plane: CloneCell<Option<Rc<MetalPlane>>>,
|
||||
pub cursor_plane: CloneCell<Option<Rc<MetalPlane>>>,
|
||||
|
||||
pub crtc: CloneCell<Option<Rc<MetalCrtc>>>,
|
||||
|
||||
pub on_change: OnChange<ConnectorEvent>,
|
||||
|
||||
pub present_trigger: AsyncEvent,
|
||||
|
||||
pub cursor_x: Cell<i32>,
|
||||
pub cursor_y: Cell<i32>,
|
||||
pub cursor_enabled: Cell<bool>,
|
||||
pub cursor_buffers: CloneCell<Option<Rc<[RenderBuffer; 2]>>>,
|
||||
pub cursor_swap_buffer: Cell<bool>,
|
||||
pub cursor_sync: CloneCell<Option<FdSync>>,
|
||||
|
||||
pub drm_feedback: CloneCell<Option<Rc<DrmFeedback>>>,
|
||||
pub scanout_buffers: RefCell<AHashMap<DmaBufId, DirectScanoutCache>>,
|
||||
pub active_framebuffer: RefCell<Option<PresentFb>>,
|
||||
pub next_framebuffer: OpaqueCell<Option<PresentFb>>,
|
||||
pub direct_scanout_active: Cell<bool>,
|
||||
|
||||
pub version: NumCell<u64>,
|
||||
pub expected_sequence: Cell<Option<u64>>,
|
||||
pub pre_commit_margin: Cell<u64>,
|
||||
pub pre_commit_margin_decay: GeometricDecay,
|
||||
pub post_commit_margin: Cell<u64>,
|
||||
pub post_commit_margin_decay: GeometricDecay,
|
||||
pub vblank_miss_sec: Cell<u32>,
|
||||
pub vblank_miss_this_sec: NumCell<u32>,
|
||||
pub presentation_is_sync: Cell<bool>,
|
||||
pub presentation_is_zero_copy: Cell<bool>,
|
||||
}
|
||||
|
||||
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<DrmMaster>,
|
||||
pub default_properties: Vec<DefaultProperty>,
|
||||
pub untyped_properties: RefCell<AHashMap<DrmProperty, u64>>,
|
||||
|
||||
pub lease: Cell<Option<MetalLeaseId>>,
|
||||
|
||||
pub possible_planes: BinarySearchMap<DrmPlane, Rc<MetalPlane>, 8>,
|
||||
|
||||
pub connector: CloneCell<Option<Rc<MetalConnector>>>,
|
||||
pub pending_flip: CloneCell<Option<Rc<MetalConnector>>>,
|
||||
|
||||
pub active: DrmProperty,
|
||||
pub mode_id: DrmProperty,
|
||||
pub vrr_enabled: DrmProperty,
|
||||
pub out_fence_ptr: DrmProperty,
|
||||
pub gamma_lut: Option<DrmProperty>,
|
||||
pub gamma_lut_size: Option<u32>,
|
||||
pub drm_state: RefCell<DrmCrtcState>,
|
||||
|
||||
pub sequence: Cell<u64>,
|
||||
pub have_queued_sequence: Cell<bool>,
|
||||
pub needs_vblank_emulation: Cell<bool>,
|
||||
}
|
||||
|
||||
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<DrmCrtc, Rc<MetalCrtc>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum PlaneType {
|
||||
Overlay,
|
||||
Primary,
|
||||
Cursor,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PlaneFormat {
|
||||
pub format: &'static Format,
|
||||
pub modifiers: IndexSet<Modifier>,
|
||||
}
|
||||
|
||||
pub struct MetalPlane {
|
||||
pub id: DrmPlane,
|
||||
pub master: Rc<DrmMaster>,
|
||||
pub default_properties: Vec<DefaultProperty>,
|
||||
pub untyped_properties: RefCell<AHashMap<DrmProperty, u64>>,
|
||||
|
||||
pub ty: PlaneType,
|
||||
|
||||
pub possible_crtcs: u32,
|
||||
pub formats: AHashMap<u32, PlaneFormat>,
|
||||
|
||||
pub lease: Cell<Option<MetalLeaseId>>,
|
||||
|
||||
pub mode_w: Cell<i32>,
|
||||
pub mode_h: Cell<i32>,
|
||||
|
||||
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<DrmPlaneState>,
|
||||
}
|
||||
|
||||
impl Debug for MetalPlane {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("MetalPlane").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue