1 use std::{ 2 fs::File, 3 io::{Seek, SeekFrom, Write}, 4 sync::{Arc, RwLock}, 5 }; 6 7 use starry_client::base::renderer::Renderer; 8 9 use crate::base::rect::Rect; 10 11 use super::{starry_server, window_manager::window_manager, SCREEN_WIDTH}; 12 13 static mut COMPOSITOR: Option<Arc<Compositor>> = None; 14 15 /// 获得合成渲染器实例 16 pub fn compositor() -> Option<Arc<Compositor>> { 17 unsafe { COMPOSITOR.clone() } 18 } 19 20 #[allow(dead_code)] 21 /// 合成渲染器 22 pub struct Compositor { 23 /// 数据锁 24 data: RwLock<CompositorData>, 25 } 26 27 pub struct CompositorData { 28 /// 待重绘的窗口 29 redraws: Vec<Rect>, 30 31 fb_file: File, 32 } 33 34 #[allow(dead_code)] 35 impl Compositor { 36 /// 创建合成渲染器 37 pub fn new() { 38 let compositor = Compositor { 39 data: RwLock::new(CompositorData { 40 redraws: Vec::new(), 41 fb_file: File::open("/dev/fb0").expect("[Error] Unable to open framebuffer"), 42 }), 43 }; 44 45 unsafe { 46 COMPOSITOR = Some(Arc::new(compositor)); 47 } 48 49 // println!("[Init] Compositor created successfully!"); 50 } 51 52 /// TODO 53 /// 重绘所有请求的窗口 54 pub fn redraw_all(&self) { 55 // println!("[Info] Compositor begin redraw_all..."); 56 let window_manager = window_manager().unwrap(); 57 let server = starry_server().unwrap(); 58 let cursor_rect = window_manager.cursor_rect(); 59 60 // 对窗口排序 61 window_manager.rezbuffer(); 62 63 let mut window_manager_guard = window_manager.data.write().unwrap(); 64 let mut compositor_guard = self.data.write().unwrap(); 65 let mut server_guard = server.data.write().unwrap(); 66 67 let mut total_redraw_rect_opt: Option<Rect> = None; 68 for original_rect in compositor_guard.redraws.drain(..) { 69 // 更新重绘的总矩形区域 70 if !original_rect.is_empty() { 71 total_redraw_rect_opt = match total_redraw_rect_opt { 72 Some(total_redraw) => Some(total_redraw.container(&original_rect)), 73 None => Some(original_rect), 74 } 75 } 76 77 let mut cursors = server_guard.cursors.clone(); 78 // 遍历所有显示窗口 79 for display in server_guard.displays.iter_mut() { 80 let rect = original_rect.intersection(&display.screen_rect()); 81 if !rect.is_empty() { 82 // TODO: 填充默认颜色 83 84 // 倒序渲染所有窗口 85 let len = window_manager_guard.zbuffer.len(); 86 for index in (0..len).rev() { 87 let entry = window_manager_guard.zbuffer.get(index).unwrap(); 88 let _id = entry.0; 89 let index = entry.2; 90 if let Some(window) = window_manager_guard.windows.get_mut(&index) { 91 // TODO: 渲染窗口标题 92 93 // 渲染窗体 94 window.draw(display, &rect); 95 } 96 } 97 } 98 99 let cursor_intersect = rect.intersection(&cursor_rect); 100 if !cursor_intersect.is_empty() { 101 if let Some(cursor) = cursors.get_mut(&window_manager_guard.cursor_i) { 102 display.roi(&cursor_intersect).blend(&cursor.roi( 103 &cursor_intersect.offset(-cursor_rect.left(), -cursor_rect.top()), 104 )); 105 } 106 } 107 } 108 } 109 110 // println!("[Info] Compositor calculate total redraw rect done!"); 111 112 // TODO 113 let mut fb = &compositor_guard.fb_file; 114 115 if let Some(total_redraw_rect) = total_redraw_rect_opt { 116 for display in server_guard.displays.iter_mut() { 117 let display_redraw = total_redraw_rect.intersection(&display.screen_rect()); 118 if !display_redraw.is_empty() { 119 for y in 0..display_redraw.height() { 120 for x in 0..display_redraw.width() { 121 let pixel = display.image.get_pixel( 122 x + display_redraw.left() - display.x, 123 y + display_redraw.top() - display.y, 124 ); 125 let offset = (((y + display_redraw.top()) * SCREEN_WIDTH as i32) 126 + x 127 + display_redraw.left()) 128 * 4; 129 fb.seek(SeekFrom::Start(offset as u64)) 130 .expect("Unable to seek framebuffer"); 131 fb.write_all(&pixel.to_bgra_bytes()) 132 .expect("Unable to write framebuffer"); 133 } 134 } 135 } 136 } 137 } 138 } 139 140 /// 窗口请求重绘 141 pub fn request_redraw(&self, rect: Rect) { 142 // println!("[Info] Compositor request redraw rect {:?}", rect); 143 let mut guard = self.data.write().unwrap(); 144 let mut push = true; 145 146 for rect in guard.redraws.iter_mut() { 147 let container = rect.container(&rect); 148 if container.area() <= rect.area() + rect.area() { 149 *rect = container; 150 push = false; 151 } 152 } 153 154 if push { 155 guard.redraws.push(rect); 156 } 157 } 158 } 159