1use crate::_private::WireMode;
4use crate::Direction;
5use crate::PciId;
6use crate::Workspace;
7use crate::video::connector_type::CON_9PIN_DIN;
8use crate::video::connector_type::CON_COMPONENT;
9use crate::video::connector_type::CON_COMPOSITE;
10use crate::video::connector_type::CON_DISPLAY_PORT;
11use crate::video::connector_type::CON_DPI;
12use crate::video::connector_type::CON_DSI;
13use crate::video::connector_type::CON_DVIA;
14use crate::video::connector_type::CON_DVID;
15use crate::video::connector_type::CON_DVII;
16use crate::video::connector_type::CON_EDP;
17use crate::video::connector_type::CON_EMBEDDED_WINDOW;
18use crate::video::connector_type::CON_HDMIA;
19use crate::video::connector_type::CON_HDMIB;
20use crate::video::connector_type::CON_LVDS;
21use crate::video::connector_type::CON_SPI;
22use crate::video::connector_type::CON_SVIDEO;
23use crate::video::connector_type::CON_TV;
24use crate::video::connector_type::CON_UNKNOWN;
25use crate::video::connector_type::CON_USB;
26use crate::video::connector_type::CON_VGA;
27use crate::video::connector_type::CON_VIRTUAL;
28use crate::video::connector_type::CON_WRITEBACK;
29use crate::video::connector_type::ConnectorType;
30use jay_proc::PrivateEnum;
31use serde::Deserialize;
32use serde::Serialize;
33use std::str::FromStr;
34use std::time::Duration;
35
36#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
44pub struct Mode {
45 pub(crate) width: i32,
46 pub(crate) height: i32,
47 pub(crate) refresh_millihz: u32,
48}
49
50impl Mode {
51 pub fn width(&self) -> i32 {
53 self.width
54 }
55
56 pub fn height(&self) -> i32 {
58 self.height
59 }
60
61 pub fn refresh_rate(&self) -> u32 {
65 self.refresh_millihz
66 }
67
68 pub(crate) fn zeroed() -> Self {
69 Self {
70 width: 0,
71 height: 0,
72 refresh_millihz: 0,
73 }
74 }
75}
76
77#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
82pub struct Connector(pub u64);
83
84impl Connector {
85 pub fn exists(self) -> bool {
90 self.0 != 0
91 }
92
93 pub fn connected(self) -> bool {
95 if !self.exists() {
96 return false;
97 }
98 get!(false).connector_connected(self)
99 }
100
101 pub fn compositor_output(self) -> bool {
103 get!(false).connector_compositor_output(self)
104 }
105
106 pub fn scale(self) -> f64 {
108 if !self.exists() {
109 return 1.0;
110 }
111 get!(1.0).connector_get_scale(self)
112 }
113
114 pub fn set_scale(self, scale: f64) {
116 if !self.exists() {
117 return;
118 }
119 log::info!("setting scale to {}", scale);
120 get!().connector_set_scale(self, scale);
121 }
122
123 pub fn ty(self) -> ConnectorType {
125 if !self.exists() {
126 return CON_UNKNOWN;
127 }
128 get!(CON_UNKNOWN).connector_type(self)
129 }
130
131 pub fn mode(self) -> Mode {
133 if !self.exists() {
134 return Mode::zeroed();
135 }
136 get!(Mode::zeroed()).connector_mode(self)
137 }
138
139 pub fn set_mode(self, width: i32, height: i32, refresh_millihz: Option<u32>) {
147 if !self.exists() {
148 log::warn!("set_mode called on a connector that does not exist");
149 return;
150 }
151 let refresh_millihz = match refresh_millihz {
152 Some(r) => r,
153 _ => match self
154 .modes()
155 .iter()
156 .find(|m| m.width == width && m.height == height)
157 {
158 Some(m) => m.refresh_millihz,
159 _ => {
160 log::warn!("Could not find any mode with width {width} and height {height}");
161 return;
162 }
163 },
164 };
165 get!().connector_set_mode(
166 self,
167 WireMode {
168 width,
169 height,
170 refresh_millihz,
171 },
172 )
173 }
174
175 pub fn modes(self) -> Vec<Mode> {
177 if !self.exists() {
178 return Vec::new();
179 }
180 get!(Vec::new()).connector_modes(self)
181 }
182
183 pub fn supports_arbitrary_modes(self) -> bool {
185 if !self.exists() {
186 return false;
187 }
188 get!(false).connector_supports_arbitrary_modes(self)
189 }
190
191 pub fn width(self) -> i32 {
195 get!().connector_size(self).0
196 }
197
198 pub fn height(self) -> i32 {
202 get!().connector_size(self).1
203 }
204
205 pub fn size(self) -> (i32, i32) {
209 if !self.exists() {
210 return (0, 0);
211 }
212 get!((0, 0)).connector_size(self)
213 }
214
215 pub fn refresh_rate(self) -> u32 {
219 self.mode().refresh_millihz
220 }
221
222 pub fn position(self) -> (i32, i32) {
224 if !self.connected() {
225 return (0, 0);
226 }
227 get!().connector_get_position(self)
228 }
229
230 pub fn set_position(self, x: i32, y: i32) {
238 if !self.exists() {
239 log::warn!("set_position called on a connector that does not exist");
240 return;
241 }
242 get!().connector_set_position(self, x, y);
243 }
244
245 pub fn set_enabled(self, enabled: bool) {
249 if !self.exists() {
250 log::warn!("set_enabled called on a connector that does not exist");
251 return;
252 }
253 get!().connector_set_enabled(self, enabled);
254 }
255
256 pub fn set_transform(self, transform: Transform) {
258 if !self.exists() {
259 log::warn!("set_transform called on a connector that does not exist");
260 return;
261 }
262 get!().connector_set_transform(self, transform);
263 }
264
265 pub fn name(self) -> String {
266 if !self.exists() {
267 return String::new();
268 }
269 get!(String::new()).connector_get_name(self)
270 }
271
272 pub fn model(self) -> String {
273 if !self.exists() {
274 return String::new();
275 }
276 get!(String::new()).connector_get_model(self)
277 }
278
279 pub fn manufacturer(self) -> String {
280 if !self.exists() {
281 return String::new();
282 }
283 get!(String::new()).connector_get_manufacturer(self)
284 }
285
286 pub fn serial_number(self) -> String {
287 if !self.exists() {
288 return String::new();
289 }
290 get!(String::new()).connector_get_serial_number(self)
291 }
292
293 pub fn set_vrr_mode(self, mode: VrrMode) {
295 get!().set_vrr_mode(Some(self), mode)
296 }
297
298 pub fn set_vrr_cursor_hz(self, hz: f64) {
304 get!().set_vrr_cursor_hz(Some(self), hz)
305 }
306
307 pub fn set_tearing_mode(self, mode: TearingMode) {
309 get!().set_tearing_mode(Some(self), mode)
310 }
311
312 pub fn set_format(self, format: Format) {
314 get!().connector_set_format(self, format);
315 }
316
317 pub fn set_colors(self, color_space: ColorSpace, eotf: Eotf) {
327 get!().connector_set_colors(self, color_space, eotf);
328 }
329
330 pub fn set_blend_space(self, blend_space: BlendSpace) {
334 get!().connector_set_blend_space(self, blend_space);
335 }
336
337 pub fn set_brightness(self, brightness: Option<f64>) {
354 get!().connector_set_brightness(self, brightness);
355 }
356
357 pub fn active_workspace(self) -> Workspace {
362 get!(Workspace(0)).get_connector_active_workspace(self)
363 }
364
365 pub fn workspaces(self) -> Vec<Workspace> {
369 get!().get_connector_workspaces(self)
370 }
371
372 pub fn connector_in_direction(self, direction: Direction) -> Connector {
380 get!(Connector(0)).get_connector_in_direction(self, direction)
381 }
382
383 pub fn set_use_native_gamut(self, use_native_gamut: bool) {
400 get!().connector_set_use_native_gamut(self, use_native_gamut);
401 }
402
403 pub fn set_scaling_filter(self, scaling_filter: ScalingFilter) {
407 get!().connector_set_scaling_filter(self, scaling_filter);
408 }
409}
410
411pub fn drm_devices() -> Vec<DrmDevice> {
413 get!().drm_devices()
414}
415
416pub fn on_new_drm_device<F: FnMut(DrmDevice) + 'static>(f: F) {
418 get!().on_new_drm_device(f)
419}
420
421pub fn on_drm_device_removed<F: FnMut(DrmDevice) + 'static>(f: F) {
423 get!().on_del_drm_device(f)
424}
425
426pub fn on_new_connector<F: FnMut(Connector) + 'static>(f: F) {
428 get!().on_new_connector(f)
429}
430
431pub fn on_connector_connected<F: FnMut(Connector) + 'static>(f: F) {
433 get!().on_connector_connected(f)
434}
435
436pub fn on_connector_disconnected<F: FnMut(Connector) + 'static>(f: F) {
438 get!().on_connector_disconnected(f)
439}
440
441pub fn on_graphics_initialized<F: FnOnce() + 'static>(f: F) {
446 get!().on_graphics_initialized(f)
447}
448
449pub fn connectors() -> Vec<Connector> {
450 get!().connectors(None)
451}
452
453pub fn get_connector(id: impl ToConnectorId) -> Connector {
487 let (ty, idx) = match id.to_connector_id() {
488 Ok(id) => id,
489 Err(e) => {
490 log::error!("{}", e);
491 return Connector(0);
492 }
493 };
494 get!(Connector(0)).get_connector(ty, idx)
495}
496
497pub fn get_connector_by_name(name: &str) -> Connector {
502 get!(Connector(0)).get_connector_by_name(name)
503}
504
505pub trait ToConnectorId {
507 fn to_connector_id(&self) -> Result<(ConnectorType, u32), String>;
508}
509
510impl ToConnectorId for (ConnectorType, u32) {
511 fn to_connector_id(&self) -> Result<(ConnectorType, u32), String> {
512 Ok(*self)
513 }
514}
515
516impl ToConnectorId for &'_ str {
517 fn to_connector_id(&self) -> Result<(ConnectorType, u32), String> {
518 let pairs = [
519 ("DP-", CON_DISPLAY_PORT),
520 ("eDP-", CON_EDP),
521 ("HDMI-A-", CON_HDMIA),
522 ("HDMI-B-", CON_HDMIB),
523 ("EmbeddedWindow-", CON_EMBEDDED_WINDOW),
524 ("VGA-", CON_VGA),
525 ("DVI-I-", CON_DVII),
526 ("DVI-D-", CON_DVID),
527 ("DVI-A-", CON_DVIA),
528 ("Composite-", CON_COMPOSITE),
529 ("SVIDEO-", CON_SVIDEO),
530 ("LVDS-", CON_LVDS),
531 ("Component-", CON_COMPONENT),
532 ("DIN-", CON_9PIN_DIN),
533 ("TV-", CON_TV),
534 ("Virtual-", CON_VIRTUAL),
535 ("DSI-", CON_DSI),
536 ("DPI-", CON_DPI),
537 ("Writeback-", CON_WRITEBACK),
538 ("SPI-", CON_SPI),
539 ("USB-", CON_USB),
540 ];
541 for (prefix, ty) in pairs {
542 if let Some(suffix) = self.strip_prefix(prefix)
543 && let Ok(idx) = u32::from_str(suffix)
544 {
545 return Ok((ty, idx));
546 }
547 }
548 Err(format!("`{}` is not a valid connector identifier", self))
549 }
550}
551
552pub mod connector_type {
554 use serde::Deserialize;
555 use serde::Serialize;
556
557 #[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
559 pub struct ConnectorType(pub u32);
560
561 pub const CON_UNKNOWN: ConnectorType = ConnectorType(0);
562 pub const CON_VGA: ConnectorType = ConnectorType(1);
563 pub const CON_DVII: ConnectorType = ConnectorType(2);
564 pub const CON_DVID: ConnectorType = ConnectorType(3);
565 pub const CON_DVIA: ConnectorType = ConnectorType(4);
566 pub const CON_COMPOSITE: ConnectorType = ConnectorType(5);
567 pub const CON_SVIDEO: ConnectorType = ConnectorType(6);
568 pub const CON_LVDS: ConnectorType = ConnectorType(7);
569 pub const CON_COMPONENT: ConnectorType = ConnectorType(8);
570 pub const CON_9PIN_DIN: ConnectorType = ConnectorType(9);
571 pub const CON_DISPLAY_PORT: ConnectorType = ConnectorType(10);
572 pub const CON_HDMIA: ConnectorType = ConnectorType(11);
573 pub const CON_HDMIB: ConnectorType = ConnectorType(12);
574 pub const CON_TV: ConnectorType = ConnectorType(13);
575 pub const CON_EDP: ConnectorType = ConnectorType(14);
576 pub const CON_VIRTUAL: ConnectorType = ConnectorType(15);
577 pub const CON_DSI: ConnectorType = ConnectorType(16);
578 pub const CON_DPI: ConnectorType = ConnectorType(17);
579 pub const CON_WRITEBACK: ConnectorType = ConnectorType(18);
580 pub const CON_SPI: ConnectorType = ConnectorType(19);
581 pub const CON_USB: ConnectorType = ConnectorType(20);
582 pub const CON_EMBEDDED_WINDOW: ConnectorType = ConnectorType(u32::MAX);
583 pub const CON_VIRTUAL_OUTPUT: ConnectorType = ConnectorType(u32::MAX - 1);
584}
585
586#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
592pub struct DrmDevice(pub u64);
593
594impl DrmDevice {
595 pub fn connectors(self) -> Vec<Connector> {
597 get!().connectors(Some(self))
598 }
599
600 pub fn devnode(self) -> String {
604 get!().drm_device_devnode(self)
605 }
606
607 pub fn syspath(self) -> String {
611 get!().drm_device_syspath(self)
612 }
613
614 pub fn vendor(self) -> String {
618 get!().drm_device_vendor(self)
619 }
620
621 pub fn model(self) -> String {
625 get!().drm_device_model(self)
626 }
627
628 pub fn pci_id(self) -> PciId {
632 get!().drm_device_pci_id(self)
633 }
634
635 pub fn make_render_device(self) {
637 get!().make_render_device(self);
638 }
639
640 pub fn set_gfx_api(self, gfx_api: GfxApi) {
644 get!().set_gfx_api(Some(self), gfx_api.to_private());
645 }
646
647 pub fn set_direct_scanout_enabled(self, enabled: bool) {
649 get!().set_direct_scanout_enabled(Some(self), enabled);
650 }
651
652 pub fn set_flip_margin(self, margin: Duration) {
659 get!().set_flip_margin(self, margin);
660 }
661
662 pub fn set_plane_color_pipelines_enabled(self, enabled: bool) {
666 get!().set_plane_color_pipelines_enabled(self, enabled);
667 }
668
669 pub fn plane_color_pipelines_enabled(self) -> bool {
671 get!().get_plane_color_pipelines_enabled(self)
672 }
673
674 pub fn toggle_plane_color_pipelines_enabled(self) {
676 self.set_plane_color_pipelines_enabled(!self.plane_color_pipelines_enabled());
677 }
678}
679
680#[non_exhaustive]
682#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq, PrivateEnum)]
683pub enum GfxApi {
684 OpenGl,
685 Vulkan,
686}
687
688pub fn set_gfx_api(gfx_api: GfxApi) {
696 get!().set_gfx_api(None, gfx_api.to_private());
697}
698
699pub fn set_direct_scanout_enabled(enabled: bool) {
705 get!().set_direct_scanout_enabled(None, enabled);
706}
707
708#[derive(Serialize, Deserialize, Copy, Clone, Debug, Eq, PartialEq, Hash, Default)]
710pub enum Transform {
711 #[default]
713 None,
714 Rotate90,
716 Rotate180,
718 Rotate270,
720 Flip,
722 FlipRotate90,
724 FlipRotate180,
726 FlipRotate270,
728}
729
730#[derive(Serialize, Deserialize, Copy, Clone, Debug, Eq, PartialEq, Hash, Default)]
732pub struct VrrMode(pub u32);
733
734impl VrrMode {
735 pub const NEVER: Self = Self(0);
737 pub const ALWAYS: Self = Self(1);
739 pub const VARIANT_1: Self = Self(2);
741 pub const VARIANT_2: Self = Self(3);
743 pub const VARIANT_3: Self = Self(4);
745}
746
747pub fn set_vrr_mode(mode: VrrMode) {
751 get!().set_vrr_mode(None, mode)
752}
753
754pub fn set_vrr_cursor_hz(hz: f64) {
762 get!().set_vrr_cursor_hz(None, hz)
763}
764
765#[derive(Serialize, Deserialize, Copy, Clone, Debug, Eq, PartialEq, Hash, Default)]
767pub struct TearingMode(pub u32);
768
769impl TearingMode {
770 pub const NEVER: Self = Self(0);
772 pub const ALWAYS: Self = Self(1);
774 pub const VARIANT_1: Self = Self(2);
776 pub const VARIANT_2: Self = Self(3);
778 pub const VARIANT_3: Self = Self(4);
783}
784
785pub fn set_tearing_mode(mode: TearingMode) {
789 get!().set_tearing_mode(None, mode)
790}
791
792pub fn create_virtual_output(name: &str) {
802 get!().create_virtual_output(name);
803}
804
805pub fn remove_virtual_output(name: &str) {
809 get!().remove_virtual_output(name);
810}
811
812#[derive(Serialize, Deserialize, Copy, Clone, Debug, Eq, PartialEq, Hash)]
814pub struct Format(pub u32);
815
816impl Format {
817 pub const ARGB8888: Self = Self(0);
818 pub const XRGB8888: Self = Self(1);
819 pub const ABGR8888: Self = Self(2);
820 pub const XBGR8888: Self = Self(3);
821 pub const R8: Self = Self(4);
822 pub const GR88: Self = Self(5);
823 pub const RGB888: Self = Self(6);
824 pub const BGR888: Self = Self(7);
825 pub const RGBA4444: Self = Self(8);
826 pub const RGBX4444: Self = Self(9);
827 pub const BGRA4444: Self = Self(10);
828 pub const BGRX4444: Self = Self(11);
829 pub const RGB565: Self = Self(12);
830 pub const BGR565: Self = Self(13);
831 pub const RGBA5551: Self = Self(14);
832 pub const RGBX5551: Self = Self(15);
833 pub const BGRA5551: Self = Self(16);
834 pub const BGRX5551: Self = Self(17);
835 pub const ARGB1555: Self = Self(18);
836 pub const XRGB1555: Self = Self(19);
837 pub const ARGB2101010: Self = Self(20);
838 pub const XRGB2101010: Self = Self(21);
839 pub const ABGR2101010: Self = Self(22);
840 pub const XBGR2101010: Self = Self(23);
841 pub const ABGR16161616: Self = Self(24);
842 pub const XBGR16161616: Self = Self(25);
843 pub const ABGR16161616F: Self = Self(26);
844 pub const XBGR16161616F: Self = Self(27);
845 pub const BGR161616: Self = Self(28);
846 pub const R16F: Self = Self(29);
847 pub const GR1616F: Self = Self(30);
848 pub const BGR161616F: Self = Self(31);
849 pub const R32F: Self = Self(32);
850 pub const GR3232F: Self = Self(33);
851 pub const BGR323232F: Self = Self(34);
852 pub const ABGR32323232F: Self = Self(35);
853}
854
855#[derive(Serialize, Deserialize, Copy, Clone, Debug, Eq, PartialEq, Hash)]
857pub struct ColorSpace(pub u32);
858
859impl ColorSpace {
860 pub const DEFAULT: Self = Self(0);
862 pub const BT2020: Self = Self(1);
864}
865
866#[derive(Serialize, Deserialize, Copy, Clone, Debug, Eq, PartialEq, Hash)]
868pub struct Eotf(pub u32);
869
870#[deprecated = "use the Eotf type instead"]
871pub type TransferFunction = Eotf;
872
873impl Eotf {
874 pub const DEFAULT: Self = Self(0);
876 pub const PQ: Self = Self(1);
878}
879
880#[derive(Serialize, Deserialize, Copy, Clone, Debug, Eq, PartialEq, Hash)]
882pub struct BlendSpace(pub u32);
883
884impl BlendSpace {
885 pub const SRGB: Self = Self(0);
888 pub const LINEAR: Self = Self(1);
891}
892
893#[derive(Serialize, Deserialize, Copy, Clone, Debug, Eq, PartialEq, Hash)]
895pub struct ScalingFilter(pub u32);
896
897impl ScalingFilter {
898 pub const LINEAR: Self = Self(0);
900 pub const NEAREST: Self = Self(1);
902}