1#[cfg(target_os = "linux")]
2mod imp;
3#[cfg(target_os = "linux")]
4mod input_region;
5#[cfg_attr(not(target_os = "linux"), allow(dead_code))]
7mod pointer_focus;
8#[cfg(target_os = "linux")]
9mod positioner;
10#[cfg(target_os = "linux")]
11mod render;
12#[cfg(target_os = "linux")]
13mod vulkan_encode;
14#[cfg(target_os = "linux")]
15mod vulkan_render;
16#[cfg(target_os = "linux")]
17pub use imp::*;
18
19#[cfg(not(target_os = "linux"))]
20mod stub {
21 use std::sync::Arc;
22 use std::sync::atomic::AtomicBool;
23 use std::sync::mpsc;
24
25 pub mod drm_fourcc {
26 pub const ARGB8888: u32 = u32::from_le_bytes(*b"AR24");
27 pub const XRGB8888: u32 = u32::from_le_bytes(*b"XR24");
28 pub const ABGR8888: u32 = u32::from_le_bytes(*b"AB24");
29 pub const XBGR8888: u32 = u32::from_le_bytes(*b"XB24");
30 pub const NV12: u32 = u32::from_le_bytes(*b"NV12");
31 }
32
33 #[derive(Debug)]
35 pub struct OwnedFd(());
36
37 #[derive(Clone)]
38 pub enum PixelData {
39 Bgra(Arc<Vec<u8>>),
40 Rgba(Arc<Vec<u8>>),
41 Nv12 {
42 data: Arc<Vec<u8>>,
43 y_stride: usize,
44 uv_stride: usize,
45 },
46 DmaBuf {
47 fd: Arc<OwnedFd>,
48 fourcc: u32,
49 modifier: u64,
50 stride: u32,
51 offset: u32,
52 },
53 Nv12DmaBuf {
54 fd: Arc<OwnedFd>,
55 stride: u32,
56 uv_offset: u32,
57 width: u32,
58 height: u32,
59 sync_fd: Option<Arc<OwnedFd>>,
60 },
61 VaSurface {
62 surface_id: u32,
63 va_display: usize,
64 _fd: Arc<OwnedFd>,
65 },
66 Encoded {
67 data: Arc<Vec<u8>>,
68 is_keyframe: bool,
69 codec_flag: u8,
70 },
71 }
72
73 impl PixelData {
74 pub fn to_rgba(&self, _width: u32, _height: u32) -> Vec<u8> {
75 match self {
76 PixelData::Rgba(data) => data.as_ref().clone(),
77 PixelData::Bgra(data) => {
78 let mut rgba = Vec::with_capacity(data.len());
79 for px in data.chunks_exact(4) {
80 rgba.extend_from_slice(&[px[2], px[1], px[0], px[3]]);
81 }
82 rgba
83 }
84 _ => Vec::new(),
85 }
86 }
87
88 pub fn is_empty(&self) -> bool {
89 match self {
90 PixelData::Bgra(v) | PixelData::Rgba(v) => v.is_empty(),
91 PixelData::Nv12 { data, .. } => data.is_empty(),
92 PixelData::DmaBuf { .. }
93 | PixelData::VaSurface { .. }
94 | PixelData::Nv12DmaBuf { .. } => false,
95 PixelData::Encoded { data, .. } => data.is_empty(),
96 }
97 }
98
99 pub fn is_dmabuf(&self) -> bool {
100 matches!(self, PixelData::DmaBuf { .. })
101 }
102
103 pub fn is_va_surface(&self) -> bool {
104 matches!(self, PixelData::VaSurface { .. })
105 }
106 }
107
108 #[derive(Clone)]
109 pub enum CursorImage {
110 Named(String),
111 Custom {
112 hotspot_x: u16,
113 hotspot_y: u16,
114 width: u16,
115 height: u16,
116 rgba: Vec<u8>,
117 },
118 Hidden,
119 }
120
121 pub enum CompositorEvent {
122 SurfaceCreated {
123 surface_id: u16,
124 title: String,
125 app_id: String,
126 parent_id: u16,
127 width: u16,
128 height: u16,
129 },
130 SurfaceDestroyed {
131 surface_id: u16,
132 },
133 SurfaceCommit {
134 surface_id: u16,
135 width: u32,
136 height: u32,
137 pixels: PixelData,
138 timestamp_ms: u32,
139 },
140 SurfaceTitle {
141 surface_id: u16,
142 title: String,
143 },
144 SurfaceAppId {
145 surface_id: u16,
146 app_id: String,
147 },
148 SurfaceResized {
149 surface_id: u16,
150 width: u16,
151 height: u16,
152 },
153 ClipboardContent {
154 surface_id: u16,
155 mime_type: String,
156 data: Vec<u8>,
157 },
158 SurfaceCursor {
159 surface_id: u16,
160 cursor: CursorImage,
161 },
162 }
163
164 pub enum CompositorCommand {
165 KeyInput {
166 surface_id: u16,
167 keycode: u32,
168 pressed: bool,
169 },
170 PointerMotion {
171 surface_id: u16,
172 x: f64,
173 y: f64,
174 },
175 PointerButton {
176 surface_id: u16,
177 button: u32,
178 pressed: bool,
179 },
180 PointerAxis {
181 surface_id: u16,
182 axis: u8,
183 value: f64,
184 },
185 SurfaceResize {
186 surface_id: u16,
187 width: u16,
188 height: u16,
189 scale_120: u16,
190 },
191 SurfaceFocus {
192 surface_id: u16,
193 },
194 SurfaceClose {
195 surface_id: u16,
196 },
197 ClipboardOffer {
198 mime_type: String,
199 data: Vec<u8>,
200 },
201 ClipboardListMimes {
203 reply: mpsc::SyncSender<Vec<String>>,
204 },
205 ClipboardGet {
207 mime_type: String,
208 reply: mpsc::SyncSender<Option<Vec<u8>>>,
209 },
210 TextInput {
215 text: String,
216 },
217 ReleaseKeys {
218 keycodes: Vec<u32>,
219 },
220 Capture {
221 surface_id: u16,
222 scale_120: u16,
224 reply: mpsc::SyncSender<Option<(u32, u32, Vec<u8>)>>,
225 },
226 RequestFrame {
230 surface_id: u16,
231 },
232 SetExternalOutputBuffers {
233 surface_id: u32,
234 target_w: u32,
235 target_h: u32,
236 buffers: Vec<ExternalOutputBuffer>,
237 },
238 RegisterDownscaleTarget {
239 surface_id: u32,
240 target_w: u32,
241 target_h: u32,
242 },
243 ClearDownscaleTarget {
244 surface_id: u32,
245 target_w: u32,
246 target_h: u32,
247 },
248 SetRefreshRate {
250 mhz: u32,
251 },
252 SetVulkanEncoder {
254 surface_id: u32,
255 codec: u8,
256 qp: u8,
257 width: u32,
258 height: u32,
259 },
260 RequestVulkanKeyframe {
262 surface_id: u32,
263 },
264 DestroyVulkanEncoder {
266 surface_id: u32,
267 },
268 Shutdown,
269 }
270
271 #[derive(Clone, Copy, Default)]
272 pub struct ExternalOutputPlane {
273 pub offset: u32,
274 pub pitch: u32,
275 }
276
277 pub struct ExternalOutputBuffer {
278 pub fd: Arc<OwnedFd>,
279 pub fourcc: u32,
280 pub modifier: u64,
281 pub stride: u32,
282 pub offset: u32,
283 pub width: u32,
284 pub height: u32,
285 pub va_surface_id: u32,
286 pub va_display: usize,
287 pub planes: Vec<ExternalOutputPlane>,
288 }
289
290 pub struct CompositorHandle {
291 pub event_rx: mpsc::Receiver<CompositorEvent>,
292 pub command_tx: mpsc::Sender<CompositorCommand>,
293 pub socket_name: String,
294 pub thread: std::thread::JoinHandle<()>,
295 pub shutdown: Arc<AtomicBool>,
296 pub vulkan_video_encode: bool,
298 pub vulkan_video_encode_av1: bool,
300 }
301
302 impl CompositorHandle {
303 pub fn wake(&self) {}
305 }
306
307 pub fn spawn_compositor(
308 _verbose: bool,
309 _event_notify: Arc<dyn Fn() + Send + Sync>,
310 _gpu_device: &str,
311 ) -> CompositorHandle {
312 let (event_tx, event_rx) = mpsc::channel();
313 let (command_tx, _command_rx) = mpsc::channel();
314 let shutdown = Arc::new(AtomicBool::new(false));
315 drop(event_tx);
317 CompositorHandle {
318 event_rx,
319 command_tx,
320 socket_name: String::new(),
321 thread: std::thread::spawn(|| {}),
322 shutdown,
323 vulkan_video_encode: false,
324 vulkan_video_encode_av1: false,
325 }
326 }
327}
328
329#[cfg(not(target_os = "linux"))]
330pub use stub::*;