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 },
134 SurfaceTitle {
135 surface_id: u16,
136 title: String,
137 },
138 SurfaceAppId {
139 surface_id: u16,
140 app_id: String,
141 },
142 SurfaceResized {
143 surface_id: u16,
144 width: u16,
145 height: u16,
146 },
147 ClipboardContent {
148 surface_id: u16,
149 mime_type: String,
150 data: Vec<u8>,
151 },
152 SurfaceCursor {
153 surface_id: u16,
154 cursor: CursorImage,
155 },
156 }
157
158 pub enum CompositorCommand {
159 KeyInput {
160 surface_id: u16,
161 keycode: u32,
162 pressed: bool,
163 },
164 PointerMotion {
165 surface_id: u16,
166 x: f64,
167 y: f64,
168 },
169 PointerButton {
170 surface_id: u16,
171 button: u32,
172 pressed: bool,
173 },
174 PointerAxis {
175 surface_id: u16,
176 axis: u8,
177 value: f64,
178 },
179 SurfaceResize {
180 surface_id: u16,
181 width: u16,
182 height: u16,
183 scale_120: u16,
184 },
185 SurfaceFocus {
186 surface_id: u16,
187 },
188 SurfaceClose {
189 surface_id: u16,
190 },
191 ClipboardOffer {
192 mime_type: String,
193 data: Vec<u8>,
194 },
195 ClipboardListMimes {
197 reply: mpsc::SyncSender<Vec<String>>,
198 },
199 ClipboardGet {
201 mime_type: String,
202 reply: mpsc::SyncSender<Option<Vec<u8>>>,
203 },
204 TextInput {
209 text: String,
210 },
211 ReleaseKeys {
212 keycodes: Vec<u32>,
213 },
214 Capture {
215 surface_id: u16,
216 scale_120: u16,
218 reply: mpsc::SyncSender<Option<(u32, u32, Vec<u8>)>>,
219 },
220 RequestFrame {
224 surface_id: u16,
225 },
226 SetExternalOutputBuffers {
227 surface_id: u32,
228 buffers: Vec<ExternalOutputBuffer>,
229 },
230 SetRefreshRate {
232 mhz: u32,
233 },
234 SetVulkanEncoder {
236 surface_id: u32,
237 codec: u8,
238 qp: u8,
239 width: u32,
240 height: u32,
241 },
242 RequestVulkanKeyframe {
244 surface_id: u32,
245 },
246 DestroyVulkanEncoder {
248 surface_id: u32,
249 },
250 Shutdown,
251 }
252
253 #[derive(Clone, Copy, Default)]
254 pub struct ExternalOutputPlane {
255 pub offset: u32,
256 pub pitch: u32,
257 }
258
259 pub struct ExternalOutputBuffer {
260 pub fd: Arc<OwnedFd>,
261 pub fourcc: u32,
262 pub modifier: u64,
263 pub stride: u32,
264 pub offset: u32,
265 pub width: u32,
266 pub height: u32,
267 pub va_surface_id: u32,
268 pub va_display: usize,
269 pub planes: Vec<ExternalOutputPlane>,
270 }
271
272 pub struct CompositorHandle {
273 pub event_rx: mpsc::Receiver<CompositorEvent>,
274 pub command_tx: mpsc::Sender<CompositorCommand>,
275 pub socket_name: String,
276 pub thread: std::thread::JoinHandle<()>,
277 pub shutdown: Arc<AtomicBool>,
278 pub vulkan_video_encode: bool,
280 pub vulkan_video_encode_av1: bool,
282 }
283
284 impl CompositorHandle {
285 pub fn wake(&self) {}
287 }
288
289 pub fn spawn_compositor(
290 _verbose: bool,
291 _event_notify: Arc<dyn Fn() + Send + Sync>,
292 _gpu_device: &str,
293 ) -> CompositorHandle {
294 let (event_tx, event_rx) = mpsc::channel();
295 let (command_tx, _command_rx) = mpsc::channel();
296 let shutdown = Arc::new(AtomicBool::new(false));
297 drop(event_tx);
299 CompositorHandle {
300 event_rx,
301 command_tx,
302 socket_name: String::new(),
303 thread: std::thread::spawn(|| {}),
304 shutdown,
305 vulkan_video_encode: false,
306 vulkan_video_encode_av1: false,
307 }
308 }
309}
310
311#[cfg(not(target_os = "linux"))]
312pub use stub::*;