148d97639Syuyi2439 use std::{ 248d97639Syuyi2439 cell::Cell, 348d97639Syuyi2439 fs::File, 448d97639Syuyi2439 io::{Seek, SeekFrom, Write}, 548d97639Syuyi2439 }; 6bee61dcaSR0ronoa 748d97639Syuyi2439 use crate::base::{ 848d97639Syuyi2439 color::Color, 948d97639Syuyi2439 renderer::{RenderMode, Renderer}, 1048d97639Syuyi2439 }; 11bee61dcaSR0ronoa 12bee61dcaSR0ronoa // TODO: 读帧缓冲设备属性 13bee61dcaSR0ronoa /// 屏幕宽度 14bee61dcaSR0ronoa const SCREEN_WIDTH: usize = 1440; 15bee61dcaSR0ronoa /// 屏幕高度 16bee61dcaSR0ronoa #[allow(dead_code)] 17bee61dcaSR0ronoa const SCREEN_HEIGHT: usize = 900; 18bee61dcaSR0ronoa 19*2b942a51SR0ronoa const FB_FILE_PATH: &str = "/dev/fb0"; 20*2b942a51SR0ronoa 2145e17157SR0ronoa /// 客户端的窗口类,与服务端的窗口对象一一对应 2245e17157SR0ronoa /// 一般来说客户端应用程序不直接使用该类,而通过Toolkit库间接使用 23bee61dcaSR0ronoa #[allow(dead_code)] 24bee61dcaSR0ronoa pub struct Window { 25bee61dcaSR0ronoa /// 窗口左上角的x坐标 26bee61dcaSR0ronoa x: i32, 27bee61dcaSR0ronoa /// 窗口左上角的y坐标 28bee61dcaSR0ronoa y: i32, 29bee61dcaSR0ronoa /// 窗口的宽度 30bee61dcaSR0ronoa w: u32, 31bee61dcaSR0ronoa /// 窗口的高度 32bee61dcaSR0ronoa h: u32, 33bee61dcaSR0ronoa /// 窗口的标题 3445e17157SR0ronoa title: String, 35bee61dcaSR0ronoa /// TODO 36bee61dcaSR0ronoa // window_async: bool, 37bee61dcaSR0ronoa /// 窗口是否大小可变 38bee61dcaSR0ronoa resizable: bool, 39bee61dcaSR0ronoa /// 窗口的渲染模式 40bee61dcaSR0ronoa mode: Cell<RenderMode>, 41bee61dcaSR0ronoa // TODO 42bee61dcaSR0ronoa // file_opt: Option<File>, 43bee61dcaSR0ronoa // TODO: 改定长数组 44bee61dcaSR0ronoa // data_opt: Option<& 'static mut [Color]>, 45bee61dcaSR0ronoa /// 窗口的渲染数据 46bee61dcaSR0ronoa data_opt: Option<Box<[Color]>>, 47*2b942a51SR0ronoa /// 帧缓冲文件 48*2b942a51SR0ronoa fb_file: File, 49bee61dcaSR0ronoa } 50bee61dcaSR0ronoa 51bee61dcaSR0ronoa impl Renderer for Window { 52bee61dcaSR0ronoa fn width(&self) -> u32 { 53bee61dcaSR0ronoa self.w 54bee61dcaSR0ronoa } 55bee61dcaSR0ronoa 56bee61dcaSR0ronoa fn height(&self) -> u32 { 57bee61dcaSR0ronoa self.h 58bee61dcaSR0ronoa } 59bee61dcaSR0ronoa 60bee61dcaSR0ronoa fn data(&self) -> &[Color] { 61bee61dcaSR0ronoa self.data_opt.as_ref().unwrap() 62bee61dcaSR0ronoa } 63bee61dcaSR0ronoa 64bee61dcaSR0ronoa fn data_mut(&mut self) -> &mut [Color] { 65bee61dcaSR0ronoa self.data_opt.as_mut().unwrap() 66bee61dcaSR0ronoa } 67bee61dcaSR0ronoa 68bee61dcaSR0ronoa fn sync(&mut self) -> bool { 6945e17157SR0ronoa for y in 0..self.height() as i32 { 7045e17157SR0ronoa for x in 0..self.width() as i32 { 7145e17157SR0ronoa let pixel = self.get_pixel(x, y); 7245e17157SR0ronoa let offset = (((y + self.y()) * SCREEN_WIDTH as i32) + x + self.x()) * 4; 7345e17157SR0ronoa // 写缓冲区 74*2b942a51SR0ronoa self.fb_file 75*2b942a51SR0ronoa .seek(SeekFrom::Start(offset as u64)) 761c11e7deSyuyi2439 .expect("Unable to seek framebuffer"); 77*2b942a51SR0ronoa self.fb_file 78*2b942a51SR0ronoa .write_all(&pixel.to_bgra_bytes()) 791c11e7deSyuyi2439 .expect("Unable to write framebuffer"); 8045e17157SR0ronoa } 8145e17157SR0ronoa } 82bee61dcaSR0ronoa true 83bee61dcaSR0ronoa } 84bee61dcaSR0ronoa 85bee61dcaSR0ronoa fn mode(&self) -> &Cell<RenderMode> { 86bee61dcaSR0ronoa &self.mode 87bee61dcaSR0ronoa } 88bee61dcaSR0ronoa } 89bee61dcaSR0ronoa 90bee61dcaSR0ronoa #[allow(dead_code)] 91bee61dcaSR0ronoa impl Window { 92bee61dcaSR0ronoa /// TODO: 接收flags 93b0262857SR0ronoa pub fn new(x: i32, y: i32, w: u32, h: u32, title: &str, color: Color) -> Self { 94bee61dcaSR0ronoa Window { 95bee61dcaSR0ronoa x: x, 96bee61dcaSR0ronoa y: y, 97bee61dcaSR0ronoa w: w, 98bee61dcaSR0ronoa h: h, 9945e17157SR0ronoa title: title.to_string(), 100bee61dcaSR0ronoa // window_async: false, 101bee61dcaSR0ronoa resizable: false, 102bee61dcaSR0ronoa mode: Cell::new(RenderMode::Blend), 103bee61dcaSR0ronoa // file_opt: None, 104b0262857SR0ronoa data_opt: Some(vec![color; (w * h) as usize].into_boxed_slice()), 105*2b942a51SR0ronoa fb_file: File::open(FB_FILE_PATH).expect("[Error] Window failed to open fb file"), 106bee61dcaSR0ronoa } 107bee61dcaSR0ronoa 108bee61dcaSR0ronoa // TODO: 与服务器通信 109bee61dcaSR0ronoa } 110bee61dcaSR0ronoa 11145e17157SR0ronoa /// 返回窗口x坐标 112bee61dcaSR0ronoa pub fn x(&self) -> i32 { 113bee61dcaSR0ronoa self.x 114bee61dcaSR0ronoa } 115bee61dcaSR0ronoa 11645e17157SR0ronoa /// 返回窗口y坐标 117bee61dcaSR0ronoa pub fn y(&self) -> i32 { 118bee61dcaSR0ronoa self.y 119bee61dcaSR0ronoa } 120bee61dcaSR0ronoa 12145e17157SR0ronoa /// 返回窗口标题 122bee61dcaSR0ronoa pub fn title(&self) -> String { 12345e17157SR0ronoa self.title.clone() 1241c11e7deSyuyi2439 } 125bee61dcaSR0ronoa 12645e17157SR0ronoa /// 改变窗口的位置 12745e17157SR0ronoa pub fn set_pos(&mut self, x: i32, y: i32) { 12845e17157SR0ronoa self.x = x; 12945e17157SR0ronoa self.y = y; 13045e17157SR0ronoa } 131bee61dcaSR0ronoa 13245e17157SR0ronoa /// 改变窗口的大小 13345e17157SR0ronoa pub fn set_size(&mut self, width: u32, height: u32) { 13445e17157SR0ronoa self.w = width; 13545e17157SR0ronoa self.h = height; 13645e17157SR0ronoa } 13745e17157SR0ronoa 13845e17157SR0ronoa /// 改变窗口标题 13945e17157SR0ronoa pub fn set_title(&mut self, title: &str) { 14045e17157SR0ronoa self.title = title.to_string(); 14145e17157SR0ronoa } 142bee61dcaSR0ronoa } 143