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 }
67
68 pub struct EncodedFrame {
71 pub surface_id: u16,
72 pub client_id: u64,
73 pub width: u32,
74 pub height: u32,
75 pub data: Arc<Vec<u8>>,
76 pub is_keyframe: bool,
77 pub codec_flag: u8,
78 }
79
80 impl PixelData {
81 pub fn to_rgba(&self, _width: u32, _height: u32) -> Vec<u8> {
82 match self {
83 PixelData::Rgba(data) => data.as_ref().clone(),
84 PixelData::Bgra(data) => {
85 let mut rgba = Vec::with_capacity(data.len());
86 for px in data.chunks_exact(4) {
87 rgba.extend_from_slice(&[px[2], px[1], px[0], px[3]]);
88 }
89 rgba
90 }
91 _ => Vec::new(),
92 }
93 }
94
95 pub fn is_empty(&self) -> bool {
96 match self {
97 PixelData::Bgra(v) | PixelData::Rgba(v) => v.is_empty(),
98 PixelData::Nv12 { data, .. } => data.is_empty(),
99 PixelData::DmaBuf { .. }
100 | PixelData::VaSurface { .. }
101 | PixelData::Nv12DmaBuf { .. } => false,
102 }
103 }
104
105 pub fn is_dmabuf(&self) -> bool {
106 matches!(self, PixelData::DmaBuf { .. })
107 }
108
109 pub fn is_va_surface(&self) -> bool {
110 matches!(self, PixelData::VaSurface { .. })
111 }
112 }
113
114 #[derive(Clone)]
115 pub enum CursorImage {
116 Named(String),
117 Custom {
118 hotspot_x: u16,
119 hotspot_y: u16,
120 width: u16,
121 height: u16,
122 rgba: Vec<u8>,
123 },
124 Hidden,
125 }
126
127 pub enum CompositorEvent {
128 SurfaceCreated {
129 surface_id: u16,
130 title: String,
131 app_id: String,
132 parent_id: u16,
133 width: u16,
134 height: u16,
135 },
136 SurfaceDestroyed {
137 surface_id: u16,
138 },
139 SurfaceCommit {
140 surface_id: u16,
141 width: u32,
142 height: u32,
143 pixels: PixelData,
144 timestamp_ms: u32,
145 },
146 SurfaceEncoded {
147 frame: EncodedFrame,
148 timestamp_ms: u32,
149 },
150 VulkanEncoderUnavailable {
151 surface_id: u16,
152 client_id: u64,
153 },
154 SurfaceTitle {
155 surface_id: u16,
156 title: String,
157 },
158 SurfaceAppId {
159 surface_id: u16,
160 app_id: String,
161 },
162 SurfaceResized {
163 surface_id: u16,
164 width: u16,
165 height: u16,
166 },
167 ClipboardContent {
168 surface_id: u16,
169 mime_type: String,
170 data: Vec<u8>,
171 },
172 SurfaceCursor {
173 surface_id: u16,
174 cursor: CursorImage,
175 },
176 }
177
178 pub enum CompositorCommand {
179 KeyInput {
180 surface_id: u16,
181 keycode: u32,
182 pressed: bool,
183 },
184 PointerMotion {
185 surface_id: u16,
186 x: f64,
187 y: f64,
188 },
189 PointerButton {
190 surface_id: u16,
191 button: u32,
192 pressed: bool,
193 },
194 PointerAxis {
195 surface_id: u16,
196 axis: u8,
197 value: f64,
198 },
199 SurfaceResize {
200 surface_id: u16,
201 width: u16,
202 height: u16,
203 scale_120: u16,
204 },
205 SurfaceFocus {
206 surface_id: u16,
207 },
208 SurfaceClose {
209 surface_id: u16,
210 },
211 ClipboardOffer {
212 mime_type: String,
213 data: Vec<u8>,
214 },
215 ClipboardListMimes {
217 reply: mpsc::SyncSender<Vec<String>>,
218 },
219 ClipboardGet {
221 mime_type: String,
222 reply: mpsc::SyncSender<Option<Vec<u8>>>,
223 },
224 TextInput {
229 text: String,
230 },
231 ReleaseKeys {
232 keycodes: Vec<u32>,
233 },
234 Capture {
235 surface_id: u16,
236 scale_120: u16,
238 reply: mpsc::SyncSender<Option<(u32, u32, Vec<u8>)>>,
239 },
240 RequestFrame {
244 surface_id: u16,
245 },
246 SetExternalOutputBuffers {
247 surface_id: u32,
248 target_w: u32,
249 target_h: u32,
250 buffers: Vec<ExternalOutputBuffer>,
251 },
252 RegisterDownscaleTarget {
253 surface_id: u32,
254 target_w: u32,
255 target_h: u32,
256 },
257 ClearDownscaleTarget {
258 surface_id: u32,
259 target_w: u32,
260 target_h: u32,
261 },
262 SetRefreshRate {
264 mhz: u32,
265 },
266 SetVulkanEncoder {
268 surface_id: u32,
269 client_id: u64,
270 codec: u8,
271 qp: u8,
272 width: u32,
273 height: u32,
274 },
275 SetVulkanEncoderQp {
277 surface_id: u32,
278 client_id: u64,
279 qp: u8,
280 },
281 RequestVulkanKeyframe {
283 surface_id: u32,
284 client_id: u64,
285 },
286 DestroyVulkanEncoder {
289 surface_id: u32,
290 client_id: Option<u64>,
291 },
292 Shutdown,
293 }
294
295 #[derive(Clone, Copy, Default)]
296 pub struct ExternalOutputPlane {
297 pub offset: u32,
298 pub pitch: u32,
299 }
300
301 pub struct ExternalOutputBuffer {
302 pub fd: Arc<OwnedFd>,
303 pub fourcc: u32,
304 pub modifier: u64,
305 pub stride: u32,
306 pub offset: u32,
307 pub width: u32,
308 pub height: u32,
309 pub va_surface_id: u32,
310 pub va_display: usize,
311 pub planes: Vec<ExternalOutputPlane>,
312 }
313
314 pub struct CompositorHandle {
315 pub event_rx: mpsc::Receiver<CompositorEvent>,
316 pub command_tx: mpsc::Sender<CompositorCommand>,
317 pub socket_name: String,
318 pub thread: std::thread::JoinHandle<()>,
319 pub shutdown: Arc<AtomicBool>,
320 pub vulkan_video_encode: bool,
322 pub vulkan_video_encode_av1: bool,
324 }
325
326 impl CompositorHandle {
327 pub fn wake(&self) {}
329 }
330
331 pub fn spawn_compositor(
332 _verbose: bool,
333 _event_notify: Arc<dyn Fn() + Send + Sync>,
334 _gpu_device: &str,
335 ) -> CompositorHandle {
336 let (event_tx, event_rx) = mpsc::channel();
337 let (command_tx, _command_rx) = mpsc::channel();
338 let shutdown = Arc::new(AtomicBool::new(false));
339 drop(event_tx);
341 CompositorHandle {
342 event_rx,
343 command_tx,
344 socket_name: String::new(),
345 thread: std::thread::spawn(|| {}),
346 shutdown,
347 vulkan_video_encode: false,
348 vulkan_video_encode_av1: false,
349 }
350 }
351}
352
353#[cfg(not(target_os = "linux"))]
354pub use stub::*;