use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
use std::mem;
use std::os::fd::FromRawFd;
use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use anyhow::{anyhow, Context};
use smithay::backend::allocator::dmabuf::Dmabuf;
use smithay::backend::allocator::gbm::{GbmAllocator, GbmBufferFlags, GbmDevice};
use smithay::backend::allocator::{Format as DrmFormat, Fourcc};
use smithay::backend::drm::compositor::{DrmCompositor, PrimaryPlaneElement};
use smithay::backend::drm::{DrmDevice, DrmDeviceFd, DrmEvent, DrmEventTime, DrmEventMetadata};
use smithay::backend::egl::context::ContextPriority;
use smithay::backend::egl::{EGLContext, EGLDisplay};
use smithay::backend::libinput::{LibinputInputBackend, LibinputSessionInterface};
use smithay::backend::renderer::gles::{GlesRenderer, GlesTexture, Capability};
use smithay::backend::renderer::{Bind, DebugFlags, ImportDma, ImportEgl};
use smithay::backend::session::libseat::LibSeatSession;
use smithay::backend::session::{Event as SessionEvent, Session};
use smithay::backend::udev::{self, UdevBackend, UdevEvent};
use smithay::desktop::utils::OutputPresentationFeedback;
use smithay::output::{Mode, Output, OutputModeSource, PhysicalProperties, Subpixel, Scale};
use smithay::reexports::calloop::timer::{Timer, TimeoutAction};
use smithay::reexports::calloop::{Dispatcher, LoopHandle, RegistrationToken};
use smithay::reexports::drm::control::{
connector, crtc, Mode as DrmMode, ModeFlags, ModeTypeFlags,
};
use smithay::reexports::input::Libinput;
use smithay::reexports::nix::fcntl::OFlag;
use smithay::reexports::nix::libc::dev_t;
use smithay::reexports::wayland_protocols::wp::linux_dmabuf::zv1::server::zwp_linux_dmabuf_feedback_v1::TrancheFlags;
use smithay::reexports::wayland_protocols::wp::presentation_time::server::wp_presentation_feedback;
use smithay::utils::DeviceFd;
use smithay::wayland::dmabuf::{DmabufFeedbackBuilder, DmabufGlobal, DmabufState, DmabufFeedback};
use smithay_drm_extras::drm_scanner::{DrmScanEvent, DrmScanner};
use smithay_drm_extras::edid::EdidInfo;
use crate::config::Config;
use crate::niri::{OutputRenderElements, State, RedrawState};
use crate::utils::get_monotonic_time;
use crate::Niri;
const BACKGROUND_COLOR: [f32; 4] = [0.1, 0.1, 0.1, 1.];
const SUPPORTED_COLOR_FORMATS: &[Fourcc] = &[Fourcc::Argb8888, Fourcc::Abgr8888];
pub struct Tty {
config: Rc<RefCell<Config>>,
session: LibSeatSession,
udev_dispatcher: Dispatcher<'static, UdevBackend, State>,
libinput: Libinput,
primary_gpu_path: PathBuf,
output_device: Option<OutputDevice>,
connectors: Arc<Mutex<HashMap<String, Output>>>,
}
type GbmDrmCompositor = DrmCompositor<
GbmAllocator<DrmDeviceFd>,
GbmDevice<DrmDeviceFd>,
(OutputPresentationFeedback, Duration),
DrmDeviceFd,
>;
struct OutputDevice {
id: dev_t,
token: RegistrationToken,
drm: DrmDevice,
gbm: GbmDevice<DrmDeviceFd>,
gles: GlesRenderer,
formats: HashSet<DrmFormat>,
drm_scanner: DrmScanner,
surfaces: HashMap<crtc::Handle, Surface>,
dmabuf_state: DmabufState,
dmabuf_global: DmabufGlobal,
}
#[derive(Debug, Clone, Copy)]
struct TtyOutputState {
device_id: dev_t,
crtc: crtc::Handle,
}
struct Surface {
name: String,
compositor: GbmDrmCompositor,
dmabuf_feedback: DmabufFeedback,
/// Tracy frame that goes from vblank to vblank.
vblank_frame: Option<tracy_client::Frame>,