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