148d97639Syuyi2439 use std::{ 248d97639Syuyi2439 cell::Cell, 3*1bee64b6SR0ronoa cmp::min, 448d97639Syuyi2439 fs::File, 548d97639Syuyi2439 io::{Seek, SeekFrom, Write}, 648d97639Syuyi2439 }; 7bee61dcaSR0ronoa 848d97639Syuyi2439 use crate::base::{ 948d97639Syuyi2439 color::Color, 1048d97639Syuyi2439 renderer::{RenderMode, Renderer}, 1148d97639Syuyi2439 }; 12bee61dcaSR0ronoa 13bee61dcaSR0ronoa // TODO: 读帧缓冲设备属性 14bee61dcaSR0ronoa /// 屏幕宽度 15bee61dcaSR0ronoa const SCREEN_WIDTH: usize = 1440; 16bee61dcaSR0ronoa /// 屏幕高度 17bee61dcaSR0ronoa #[allow(dead_code)] 18bee61dcaSR0ronoa const SCREEN_HEIGHT: usize = 900; 19bee61dcaSR0ronoa 202b942a51SR0ronoa const FB_FILE_PATH: &str = "/dev/fb0"; 212b942a51SR0ronoa 2245e17157SR0ronoa /// 客户端的窗口类,与服务端的窗口对象一一对应 2345e17157SR0ronoa /// 一般来说客户端应用程序不直接使用该类,而通过Toolkit库间接使用 24bee61dcaSR0ronoa #[allow(dead_code)] 25bee61dcaSR0ronoa pub struct Window { 26bee61dcaSR0ronoa /// 窗口左上角的x坐标 27bee61dcaSR0ronoa x: i32, 28bee61dcaSR0ronoa /// 窗口左上角的y坐标 29bee61dcaSR0ronoa y: i32, 30bee61dcaSR0ronoa /// 窗口的宽度 31bee61dcaSR0ronoa w: u32, 32bee61dcaSR0ronoa /// 窗口的高度 33bee61dcaSR0ronoa h: u32, 34bee61dcaSR0ronoa /// 窗口的标题 3545e17157SR0ronoa title: String, 36bee61dcaSR0ronoa /// TODO 37bee61dcaSR0ronoa // window_async: bool, 38bee61dcaSR0ronoa /// 窗口是否大小可变 39bee61dcaSR0ronoa resizable: bool, 40bee61dcaSR0ronoa /// 窗口的渲染模式 41bee61dcaSR0ronoa mode: Cell<RenderMode>, 42bee61dcaSR0ronoa // TODO 43bee61dcaSR0ronoa // file_opt: Option<File>, 44bee61dcaSR0ronoa // TODO: 改定长数组 45bee61dcaSR0ronoa // data_opt: Option<& 'static mut [Color]>, 46bee61dcaSR0ronoa /// 窗口的渲染数据 47bee61dcaSR0ronoa data_opt: Option<Box<[Color]>>, 482b942a51SR0ronoa /// 帧缓冲文件 492b942a51SR0ronoa fb_file: File, 50bee61dcaSR0ronoa } 51bee61dcaSR0ronoa 52bee61dcaSR0ronoa impl Renderer for Window { 53bee61dcaSR0ronoa fn width(&self) -> u32 { 54bee61dcaSR0ronoa self.w 55bee61dcaSR0ronoa } 56bee61dcaSR0ronoa 57bee61dcaSR0ronoa fn height(&self) -> u32 { 58bee61dcaSR0ronoa self.h 59bee61dcaSR0ronoa } 60bee61dcaSR0ronoa 61bee61dcaSR0ronoa fn data(&self) -> &[Color] { 62bee61dcaSR0ronoa self.data_opt.as_ref().unwrap() 63bee61dcaSR0ronoa } 64bee61dcaSR0ronoa 65bee61dcaSR0ronoa fn data_mut(&mut self) -> &mut [Color] { 66bee61dcaSR0ronoa self.data_opt.as_mut().unwrap() 67bee61dcaSR0ronoa } 68bee61dcaSR0ronoa 69bee61dcaSR0ronoa fn sync(&mut self) -> bool { 70*1bee64b6SR0ronoa // 处理窗口大小超限的情况 71*1bee64b6SR0ronoa let width = min(self.width() as i32, SCREEN_WIDTH as i32 - self.x); 72*1bee64b6SR0ronoa let height = min(self.height() as i32, SCREEN_HEIGHT as i32 - self.y); 73*1bee64b6SR0ronoa 74*1bee64b6SR0ronoa for y in 0..height as i32 { 75*1bee64b6SR0ronoa for x in 0..width as i32 { 7645e17157SR0ronoa let pixel = self.get_pixel(x, y); 7745e17157SR0ronoa let offset = (((y + self.y()) * SCREEN_WIDTH as i32) + x + self.x()) * 4; 7845e17157SR0ronoa // 写缓冲区 792b942a51SR0ronoa self.fb_file 802b942a51SR0ronoa .seek(SeekFrom::Start(offset as u64)) 811c11e7deSyuyi2439 .expect("Unable to seek framebuffer"); 822b942a51SR0ronoa self.fb_file 832b942a51SR0ronoa .write_all(&pixel.to_bgra_bytes()) 841c11e7deSyuyi2439 .expect("Unable to write framebuffer"); 8545e17157SR0ronoa } 8645e17157SR0ronoa } 87bee61dcaSR0ronoa true 88bee61dcaSR0ronoa } 89bee61dcaSR0ronoa 90bee61dcaSR0ronoa fn mode(&self) -> &Cell<RenderMode> { 91bee61dcaSR0ronoa &self.mode 92bee61dcaSR0ronoa } 93bee61dcaSR0ronoa } 94bee61dcaSR0ronoa 95bee61dcaSR0ronoa #[allow(dead_code)] 96bee61dcaSR0ronoa impl Window { 97bee61dcaSR0ronoa /// TODO: 接收flags 98b0262857SR0ronoa pub fn new(x: i32, y: i32, w: u32, h: u32, title: &str, color: Color) -> Self { 99bee61dcaSR0ronoa Window { 100bee61dcaSR0ronoa x: x, 101bee61dcaSR0ronoa y: y, 102bee61dcaSR0ronoa w: w, 103bee61dcaSR0ronoa h: h, 10445e17157SR0ronoa title: title.to_string(), 105bee61dcaSR0ronoa // window_async: false, 106bee61dcaSR0ronoa resizable: false, 107bee61dcaSR0ronoa mode: Cell::new(RenderMode::Blend), 108bee61dcaSR0ronoa // file_opt: None, 109b0262857SR0ronoa data_opt: Some(vec![color; (w * h) as usize].into_boxed_slice()), 1102b942a51SR0ronoa fb_file: File::open(FB_FILE_PATH).expect("[Error] Window failed to open fb file"), 111bee61dcaSR0ronoa } 112bee61dcaSR0ronoa 113bee61dcaSR0ronoa // TODO: 与服务器通信 114bee61dcaSR0ronoa } 115bee61dcaSR0ronoa 11645e17157SR0ronoa /// 返回窗口x坐标 117bee61dcaSR0ronoa pub fn x(&self) -> i32 { 118bee61dcaSR0ronoa self.x 119bee61dcaSR0ronoa } 120bee61dcaSR0ronoa 12145e17157SR0ronoa /// 返回窗口y坐标 122bee61dcaSR0ronoa pub fn y(&self) -> i32 { 123bee61dcaSR0ronoa self.y 124bee61dcaSR0ronoa } 125bee61dcaSR0ronoa 12645e17157SR0ronoa /// 返回窗口标题 127bee61dcaSR0ronoa pub fn title(&self) -> String { 12845e17157SR0ronoa self.title.clone() 1291c11e7deSyuyi2439 } 130bee61dcaSR0ronoa 13145e17157SR0ronoa /// 改变窗口的位置 13245e17157SR0ronoa pub fn set_pos(&mut self, x: i32, y: i32) { 13345e17157SR0ronoa self.x = x; 13445e17157SR0ronoa self.y = y; 13545e17157SR0ronoa } 136bee61dcaSR0ronoa 13745e17157SR0ronoa /// 改变窗口的大小 13845e17157SR0ronoa pub fn set_size(&mut self, width: u32, height: u32) { 13945e17157SR0ronoa self.w = width; 14045e17157SR0ronoa self.h = height; 14145e17157SR0ronoa } 14245e17157SR0ronoa 14345e17157SR0ronoa /// 改变窗口标题 14445e17157SR0ronoa pub fn set_title(&mut self, title: &str) { 14545e17157SR0ronoa self.title = title.to_string(); 14645e17157SR0ronoa } 147bee61dcaSR0ronoa } 148