Skip to main content

v_shield/
platform_sync.rs

1//! 🛡️ V-Shield Platform Sync
2//!
3//! Sincronización de renderizado multiplataforma.
4//!
5//! Maneja las diferencias entre X11, OpenGL, y otros backends
6//! para garantizar que los comandos de renderizado se ejecuten
7//! correctamente en cada frame.
8//!
9//! # Modos
10//!
11//! - `X11`: Termux-X11, Linux desktop → XFlush + XSync
12//! - `OpenGL`: Native GL → glFlush
13//! - `Auto`: Auto-detect por env var `DISPLAY`
14//!
15//! # Ejemplo
16//!
17//! ```rust
18//! use v_shield::platform_sync::PlatformSync;
19//!
20//! let mut sync = PlatformSync::new();
21//! // ... al final de cada frame ...
22//! sync.sync();
23//! ```
24
25/// Modo de sincronización
26#[derive(Debug, Clone, Copy, PartialEq)]
27pub enum PlatformSyncMode {
28    /// X11 (Termux-X11)
29    X11,
30    /// OpenGL nativo
31    OpenGL,
32    /// Auto-detect
33    Auto,
34}
35
36/// Platform Sync - sincronización de frame multiplataforma
37///
38/// **Funciones**:
39/// - `xflush()`: Forzar flush de comandos X11
40/// - `xsync()`: Sincronizar con servidor X11
41/// - `gl_flush()`: OpenGL buffer swap
42pub struct PlatformSync {
43    /// Si está habilitado
44    enabled: bool,
45    /// Modo: x11, gl, auto
46    mode: PlatformSyncMode,
47    /// Frame count
48    frame: u64,
49}
50
51impl PlatformSync {
52    /// Crear Platform Sync (auto-detect)
53    pub fn new() -> Self {
54        let mode = Self::detect_mode();
55        #[cfg(debug_assertions)]
56        println!(
57            "[PLATFORM SYNC] Detectado modo: {:?} (Termux-X11 compatible)",
58            mode
59        );
60        Self {
61            enabled: true,
62            mode,
63            frame: 0,
64        }
65    }
66
67    /// Detectar modo automáticamente
68    fn detect_mode() -> PlatformSyncMode {
69        // Si DISPLAY está seteado, asumir X11
70        if std::env::var("DISPLAY").is_ok() {
71            PlatformSyncMode::X11
72        } else {
73            PlatformSyncMode::OpenGL
74        }
75    }
76
77    /// Platform sync: llamar al final de cada frame
78    pub fn sync(&mut self) {
79        if !self.enabled {
80            return;
81        }
82
83        self.frame += 1;
84
85        match self.mode {
86            PlatformSyncMode::X11 => {
87                self.xflush();
88                self.xsync();
89            }
90            PlatformSyncMode::OpenGL => {
91                self.gl_flush();
92            }
93            PlatformSyncMode::Auto => {
94                // Auto: intentar X11 primero, fallback a GL
95                self.xflush();
96                self.gl_flush();
97            }
98        }
99    }
100
101    /// XFlush: Forzar flush de comandos X11
102    fn xflush(&self) {
103        // NOTA: Esto requiere FFI con libX11
104        // Por ahora, es un no-op. El backend de SDL2/raylib
105        // ya maneja el flush internamente.
106        #[cfg(debug_assertions)]
107        eprintln!("[PLATFORM SYNC] XFlush: stub (SDL2/raylib manejan internamente)");
108    }
109
110    /// XSync: Sincronizar con servidor X11
111    fn xsync(&self) {
112        // NOTA: Requiere libX11
113        #[cfg(debug_assertions)]
114        eprintln!("[PLATFORM SYNC] XSync: stub (SDL2/raylib manejan internamente)");
115    }
116
117    /// glFlush: OpenGL buffer swap
118    fn gl_flush(&self) {
119        // El backend de SDL2/raylib ya hace swap internamente
120        // en su Drop de DrawHandle / end_drawing()
121    }
122
123    /// Habilitar Platform Sync
124    pub fn enable(&mut self) {
125        self.enabled = true;
126    }
127
128    /// Deshabilitar Platform Sync
129    pub fn disable(&mut self) {
130        self.enabled = false;
131    }
132
133    /// Cambiar modo
134    pub fn set_mode(&mut self, mode: PlatformSyncMode) {
135        self.mode = mode;
136    }
137
138    /// Obtener modo actual
139    pub fn mode(&self) -> PlatformSyncMode {
140        self.mode
141    }
142
143    /// Frame count actual
144    pub fn frame_count(&self) -> u64 {
145        self.frame
146    }
147}
148
149impl Default for PlatformSync {
150    fn default() -> Self {
151        Self::new()
152    }
153}
154
155#[cfg(test)]
156mod tests {
157    use super::*;
158
159    #[test]
160    fn test_platform_sync_new() {
161        let sync = PlatformSync::new();
162        assert!(sync.enabled);
163        assert_eq!(sync.frame, 0);
164    }
165
166    #[test]
167    fn test_platform_sync_enable_disable() {
168        let mut sync = PlatformSync::new();
169        sync.disable();
170        assert!(!sync.enabled);
171        sync.enable();
172        assert!(sync.enabled);
173    }
174
175    #[test]
176    fn test_platform_sync_sync_disabled() {
177        let mut sync = PlatformSync::new();
178        sync.disable();
179        sync.sync(); // No debe panic
180        assert_eq!(sync.frame, 0);
181    }
182
183    #[test]
184    fn test_platform_sync_mode() {
185        let mut sync = PlatformSync::new();
186        sync.set_mode(PlatformSyncMode::OpenGL);
187        assert_eq!(sync.mode(), PlatformSyncMode::OpenGL);
188        sync.set_mode(PlatformSyncMode::X11);
189        assert_eq!(sync.mode(), PlatformSyncMode::X11);
190    }
191
192    #[test]
193    fn test_platform_sync_default() {
194        let sync = PlatformSync::default();
195        assert!(sync.enabled);
196    }
197}