mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 02:46:47 +00:00
支持绘制24位深和16位深显示缓冲区 (#640)
* 修复了初始化时显示,边界条件的一个bug * 解决了内存未初始前字体显示的兼容性问题 * 支持绘制24位深和16位深显示缓冲区
This commit is contained in:
parent
4256da7fb6
commit
2755467c79
@ -8,7 +8,10 @@ use crate::{
|
|||||||
mm::{ucontext::LockedVMA, PhysAddr, VirtAddr},
|
mm::{ucontext::LockedVMA, PhysAddr, VirtAddr},
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::fbmem::{FbDevice, FrameBufferManager};
|
use self::{
|
||||||
|
fbmem::{FbDevice, FrameBufferManager},
|
||||||
|
render_helper::{BitIter, EndianPattern},
|
||||||
|
};
|
||||||
|
|
||||||
const COLOR_TABLE_8: &[u32] = &[
|
const COLOR_TABLE_8: &[u32] = &[
|
||||||
0x00000000, 0xff000000, 0x00ff0000, 0xffff0000, 0x0000ff00, 0xff00ff00, 0x00ffff00, 0xffffff00,
|
0x00000000, 0xff000000, 0x00ff0000, 0xffff0000, 0x0000ff00, 0xff00ff00, 0x00ffff00, 0xffffff00,
|
||||||
@ -23,7 +26,7 @@ pub mod fbcon;
|
|||||||
pub mod fbmem;
|
pub mod fbmem;
|
||||||
pub mod fbsysfs;
|
pub mod fbsysfs;
|
||||||
pub mod modedb;
|
pub mod modedb;
|
||||||
|
pub mod render_helper;
|
||||||
// 帧缓冲区id
|
// 帧缓冲区id
|
||||||
int_like!(FbId, u32);
|
int_like!(FbId, u32);
|
||||||
|
|
||||||
@ -106,7 +109,14 @@ pub trait FrameBuffer: FrameBufferInfo + FrameBufferOps + Device {
|
|||||||
{
|
{
|
||||||
unsafe { self.fast_imageblit(image, dst1, fg, bg) }
|
unsafe { self.fast_imageblit(image, dst1, fg, bg) }
|
||||||
} else {
|
} else {
|
||||||
self.slow_imageblit(image, dst1, fg, bg, start_index, pitch_index)
|
self.slow_imageblit(
|
||||||
|
image,
|
||||||
|
dst1,
|
||||||
|
fg,
|
||||||
|
bg,
|
||||||
|
bitstart / 4,
|
||||||
|
self.current_fb_fix().line_length,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
todo!("color image blit todo");
|
todo!("color image blit todo");
|
||||||
@ -246,25 +256,31 @@ pub trait FrameBuffer: FrameBufferInfo + FrameBufferOps + Device {
|
|||||||
_start_index: u32,
|
_start_index: u32,
|
||||||
_pitch_index: u32,
|
_pitch_index: u32,
|
||||||
) {
|
) {
|
||||||
todo!();
|
let mut dst = _dst1.as_ptr::<u32>();
|
||||||
// let bpp = self.current_fb_var().bits_per_pixel;
|
let mut count = 0;
|
||||||
// let pitch = self.current_fb_fix().line_length;
|
let iter = BitIter::new(
|
||||||
// let null_bits = 32 - bpp;
|
_fg,
|
||||||
// let spitch = (image.width + 7) / 8;
|
_bg,
|
||||||
|
EndianPattern::Big,
|
||||||
|
EndianPattern::Little,
|
||||||
|
self.current_fb_var().bits_per_pixel / 8,
|
||||||
|
_image.data.iter(),
|
||||||
|
_image.width,
|
||||||
|
);
|
||||||
|
for (content, full) in iter {
|
||||||
|
unsafe {
|
||||||
|
*dst = content;
|
||||||
|
|
||||||
// // TODO:这里是需要计算的,但是目前用不到,先直接写
|
dst = dst.add(1);
|
||||||
// let bswapmask = 0;
|
}
|
||||||
|
|
||||||
// let dst2 = dst1;
|
if full {
|
||||||
|
count += 1;
|
||||||
// // 一行一行画
|
dst = unsafe {
|
||||||
// for i in image.height..0 {
|
_dst1.as_ptr::<u8>().add((_pitch_index * count) as usize) as *mut u32
|
||||||
// let dst = dst1;
|
};
|
||||||
|
}
|
||||||
// if start_index > 0 {
|
}
|
||||||
// let start_mask = !(!(0 as u32) << start_index);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
172
kernel/src/driver/video/fbdev/base/render_helper.rs
Normal file
172
kernel/src/driver/video/fbdev/base/render_helper.rs
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
use core::slice::Iter;
|
||||||
|
|
||||||
|
pub struct BitIter<'a> {
|
||||||
|
fgcolor: u32,
|
||||||
|
bkcolor: u32,
|
||||||
|
_color_pattern: EndianPattern,
|
||||||
|
_dst_pattern: EndianPattern,
|
||||||
|
src: Iter<'a, u8>,
|
||||||
|
read_mask: u8,
|
||||||
|
byte_per_pixel: u32,
|
||||||
|
buffer: u32,
|
||||||
|
current: u8,
|
||||||
|
left_byte: u32,
|
||||||
|
done: bool,
|
||||||
|
consumed_bit: u32,
|
||||||
|
image_width: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> BitIter<'a> {
|
||||||
|
pub fn new(
|
||||||
|
fgcolor: u32,
|
||||||
|
bkcolor: u32,
|
||||||
|
dst_pattern: EndianPattern,
|
||||||
|
color_pattern: EndianPattern,
|
||||||
|
byte_per_pixel: u32,
|
||||||
|
src: Iter<'a, u8>,
|
||||||
|
image_width: u32,
|
||||||
|
) -> Self {
|
||||||
|
let mut fgcolor = fgcolor;
|
||||||
|
let mut bkcolor = bkcolor;
|
||||||
|
if dst_pattern != color_pattern {
|
||||||
|
fgcolor = Self::reverse(fgcolor, byte_per_pixel);
|
||||||
|
bkcolor = Self::reverse(bkcolor, byte_per_pixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut ans = Self {
|
||||||
|
fgcolor,
|
||||||
|
bkcolor,
|
||||||
|
_color_pattern: color_pattern,
|
||||||
|
_dst_pattern: dst_pattern,
|
||||||
|
src,
|
||||||
|
read_mask: 0b10000000,
|
||||||
|
byte_per_pixel,
|
||||||
|
buffer: 0,
|
||||||
|
current: 0,
|
||||||
|
left_byte: 0,
|
||||||
|
done: false,
|
||||||
|
consumed_bit: 0,
|
||||||
|
image_width,
|
||||||
|
};
|
||||||
|
ans.current = *ans.src.next().unwrap();
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reverse(num: u32, byte_per_pixel: u32) -> u32 {
|
||||||
|
let mask = 0x000000ff;
|
||||||
|
let mut ans = 0;
|
||||||
|
let mut num = num;
|
||||||
|
for _ in 0..3 {
|
||||||
|
ans |= mask & num;
|
||||||
|
ans <<= 8;
|
||||||
|
num >>= 8;
|
||||||
|
}
|
||||||
|
ans |= mask & num;
|
||||||
|
ans >>= (4 - byte_per_pixel) * 8;
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn move_mask(&mut self) -> bool {
|
||||||
|
self.consumed_bit += 1;
|
||||||
|
self.read_mask >>= 1;
|
||||||
|
if self.read_mask == 0b000000000 {
|
||||||
|
self.read_mask = 0b10000000;
|
||||||
|
self.current = match self.src.next() {
|
||||||
|
Some(x) => *x,
|
||||||
|
None => {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn full_buffer(&mut self) -> Result<PixelLineStatus, PixelLineStatus> {
|
||||||
|
let same_endian = if self._dst_pattern == self._color_pattern {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
-1
|
||||||
|
};
|
||||||
|
let mut color = self.read_bit() << (self.left_byte << 3);
|
||||||
|
let mut buffer_pointer = if self._dst_pattern == self._color_pattern {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
3
|
||||||
|
};
|
||||||
|
let mask = 0x000000ff << ((self.byte_per_pixel - 1) << 3);
|
||||||
|
let mut temp;
|
||||||
|
// while buffer_pointer >= 0 && buffer_pointer <= 3 {
|
||||||
|
while (0..=3).contains(&buffer_pointer) {
|
||||||
|
if self.consumed_bit >= self.image_width {
|
||||||
|
self.consumed_bit = 0;
|
||||||
|
return Ok(PixelLineStatus::Full(self.buffer));
|
||||||
|
}
|
||||||
|
temp = color & mask;
|
||||||
|
color <<= 8;
|
||||||
|
temp <<= (4 - self.byte_per_pixel) * 8;
|
||||||
|
temp >>= buffer_pointer * 8;
|
||||||
|
self.buffer |= temp;
|
||||||
|
buffer_pointer += same_endian;
|
||||||
|
self.left_byte += 1;
|
||||||
|
if self.left_byte >= self.byte_per_pixel {
|
||||||
|
self.left_byte = 0;
|
||||||
|
if !self.move_mask() {
|
||||||
|
return Err(PixelLineStatus::Full(self.buffer));
|
||||||
|
}
|
||||||
|
color = self.read_bit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.consumed_bit >= self.image_width {
|
||||||
|
self.consumed_bit = 0;
|
||||||
|
return Ok(PixelLineStatus::Full(self.buffer));
|
||||||
|
}
|
||||||
|
return Ok(PixelLineStatus::NotFull(self.buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_bit(&self) -> u32 {
|
||||||
|
match self.read_mask & self.current {
|
||||||
|
0 => self.bkcolor,
|
||||||
|
_ => self.fgcolor,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for BitIter<'_> {
|
||||||
|
type Item = (u32, bool);
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.done {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
match self.full_buffer() {
|
||||||
|
Ok(x) => {
|
||||||
|
self.buffer = 0;
|
||||||
|
return Some(x.unwarp());
|
||||||
|
}
|
||||||
|
Err(x) => {
|
||||||
|
self.done = true;
|
||||||
|
return Some(x.unwarp());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(PartialEq, PartialOrd)]
|
||||||
|
pub enum EndianPattern {
|
||||||
|
Big,
|
||||||
|
Little,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum PixelLineStatus {
|
||||||
|
Full(u32),
|
||||||
|
NotFull(u32),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PixelLineStatus {
|
||||||
|
pub fn unwarp(self) -> (u32, bool) {
|
||||||
|
match self {
|
||||||
|
PixelLineStatus::Full(x) => (x, true),
|
||||||
|
PixelLineStatus::NotFull(x) => (x, false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -424,7 +424,30 @@ impl FrameBufferOps for VesaFb {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
16 => {
|
||||||
|
let base = screen_base.as_ptr::<u16>();
|
||||||
|
|
||||||
|
for y in rect.dy..(rect.dy + rect.height) {
|
||||||
|
for x in rect.dx..(rect.dx + rect.width) {
|
||||||
|
unsafe { *base.add((y * line_offset + x) as usize) = 0x0000 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
24 => {
|
||||||
|
let base = screen_base.as_ptr::<[u8; 3]>();
|
||||||
|
|
||||||
|
for y in rect.dy..(rect.dy + rect.height) {
|
||||||
|
for x in rect.dx..(rect.dx + rect.width) {
|
||||||
|
unsafe { *base.add((y * line_offset + x) as usize) = [0, 0, 0] };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
send_to_default_serial8250_port(
|
||||||
|
format!("unsupported bit depth:{}!\n\0", bpp).as_bytes(),
|
||||||
|
);
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -565,7 +588,81 @@ impl FrameBufferOps for VesaFb {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2 => {
|
||||||
|
let mut dst = dst.as_ptr::<u16>();
|
||||||
|
let mut src = src.as_ptr::<u16>();
|
||||||
|
let line_offset = var.xres as usize;
|
||||||
|
|
||||||
|
if s_real_x > d_real_x {
|
||||||
|
// 如果src在dst下方,则可以直接拷贝不会出现指针覆盖
|
||||||
|
unsafe {
|
||||||
|
for _ in 0..visiable_h {
|
||||||
|
core::ptr::copy(src, dst, visiable_w as usize);
|
||||||
|
src = src.add(line_offset);
|
||||||
|
dst = dst.add(visiable_w as usize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let mut tmp: Vec<u16> = vec![0; size];
|
||||||
|
let mut tmp_ptr = tmp.as_mut_ptr();
|
||||||
|
|
||||||
|
// 这里是一个可以优化的点,现在为了避免指针拷贝时覆盖,统一先拷贝进入buf再拷贝到dst
|
||||||
|
unsafe {
|
||||||
|
for _ in 0..visiable_h {
|
||||||
|
core::ptr::copy(src, tmp_ptr, visiable_w as usize);
|
||||||
|
src = src.add(line_offset);
|
||||||
|
tmp_ptr = tmp_ptr.add(visiable_w as usize);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_ptr = tmp_ptr.sub(size);
|
||||||
|
for _ in 0..visiable_h {
|
||||||
|
core::ptr::copy(tmp_ptr, dst, visiable_w as usize);
|
||||||
|
dst = dst.add(line_offset);
|
||||||
|
tmp_ptr = tmp_ptr.add(visiable_w as usize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3 => {
|
||||||
|
let mut dst = dst.as_ptr::<[u8; 3]>();
|
||||||
|
let mut src = src.as_ptr::<[u8; 3]>();
|
||||||
|
let line_offset = var.xres as usize;
|
||||||
|
|
||||||
|
if s_real_x > d_real_x {
|
||||||
|
// 如果src在dst下方,则可以直接拷贝不会出现指针覆盖
|
||||||
|
unsafe {
|
||||||
|
for _ in 0..visiable_h {
|
||||||
|
core::ptr::copy(src, dst, visiable_w as usize);
|
||||||
|
src = src.add(line_offset);
|
||||||
|
dst = dst.add(visiable_w as usize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let mut tmp: Vec<u32> = vec![0; size];
|
||||||
|
let mut tmp_ptr = tmp.as_mut_ptr() as *mut [u8; 3];
|
||||||
|
|
||||||
|
// 这里是一个可以优化的点,现在为了避免指针拷贝时覆盖,统一先拷贝进入buf再拷贝到dst
|
||||||
|
unsafe {
|
||||||
|
for _ in 0..visiable_h {
|
||||||
|
core::ptr::copy(src, tmp_ptr, visiable_w as usize);
|
||||||
|
src = src.add(line_offset);
|
||||||
|
tmp_ptr = tmp_ptr.add(visiable_w as usize);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_ptr = tmp_ptr.sub(size);
|
||||||
|
for _ in 0..visiable_h {
|
||||||
|
core::ptr::copy(tmp_ptr, dst, visiable_w as usize);
|
||||||
|
dst = dst.add(line_offset);
|
||||||
|
tmp_ptr = tmp_ptr.add(visiable_w as usize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
|
send_to_default_serial8250_port(
|
||||||
|
format!("bytes_per_pixel:{}\n\0", bytes_per_pixel).as_bytes(),
|
||||||
|
);
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ pub fn video_refresh_manager() -> &'static VideoRefreshManager {
|
|||||||
///管理显示刷新变量的结构体
|
///管理显示刷新变量的结构体
|
||||||
pub struct VideoRefreshManager {
|
pub struct VideoRefreshManager {
|
||||||
device_buffer: RwLock<ScmBufferInfo>,
|
device_buffer: RwLock<ScmBufferInfo>,
|
||||||
refresh_target: RwLock<Option<Arc<SpinLock<Box<[u32]>>>>>,
|
refresh_target: RwLock<Option<Arc<SpinLock<Box<[u8]>>>>>,
|
||||||
running: AtomicBool,
|
running: AtomicBool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +150,7 @@ impl VideoRefreshManager {
|
|||||||
}
|
}
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn refresh_target(&self) -> RwLockReadGuard<'_, Option<Arc<SpinLock<Box<[u32]>>>>> {
|
pub fn refresh_target(&self) -> RwLockReadGuard<'_, Option<Arc<SpinLock<Box<[u8]>>>>> {
|
||||||
let x = self.refresh_target.read();
|
let x = self.refresh_target.read();
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
@ -254,7 +254,7 @@ impl TimerFunction for VideoRefreshExecutor {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut refresh_target: Option<RwLockReadGuard<'_, Option<Arc<SpinLock<Box<[u32]>>>>>> =
|
let mut refresh_target: Option<RwLockReadGuard<'_, Option<Arc<SpinLock<Box<[u8]>>>>>> =
|
||||||
None;
|
None;
|
||||||
const TRY_TIMES: i32 = 2;
|
const TRY_TIMES: i32 = 2;
|
||||||
for i in 0..TRY_TIMES {
|
for i in 0..TRY_TIMES {
|
||||||
@ -288,7 +288,7 @@ impl TimerFunction for VideoRefreshExecutor {
|
|||||||
let mut target_guard = target_guard.unwrap();
|
let mut target_guard = target_guard.unwrap();
|
||||||
unsafe {
|
unsafe {
|
||||||
p.copy_from_nonoverlapping(
|
p.copy_from_nonoverlapping(
|
||||||
target_guard.as_mut_ptr() as *mut u8,
|
target_guard.as_mut_ptr(),
|
||||||
manager.device_buffer().buf_size() as usize,
|
manager.device_buffer().buf_size() as usize,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -144,6 +144,6 @@ pub fn panic(info: &PanicInfo) -> ! {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Current PCB:\n\t{:?}", *(ProcessManager::current_pcb()));
|
println!("Current PCB:\n\t{:?}", (ProcessManager::current_pcb()));
|
||||||
ProcessManager::exit(usize::MAX);
|
ProcessManager::exit(usize::MAX);
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ impl<'a> BitmapFont<'a> {
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn char_map(&self, character: char) -> &'a [u8] {
|
pub fn char_map(&self, character: char) -> &'a [u8] {
|
||||||
|
//获得ASCII的index
|
||||||
let index = self.glyph_mapping.index(character);
|
let index = self.glyph_mapping.index(character);
|
||||||
let pos = index * self.bytes_per_char;
|
let pos = index * self.bytes_per_char;
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ pub enum ScmFramworkType {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ScmBuffer {
|
pub enum ScmBuffer {
|
||||||
DeviceBuffer(VirtAddr),
|
DeviceBuffer(VirtAddr),
|
||||||
DoubleBuffer(Arc<SpinLock<Box<[u32]>>>),
|
DoubleBuffer(Arc<SpinLock<Box<[u8]>>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -81,15 +81,15 @@ impl ScmBufferInfo {
|
|||||||
} else {
|
} else {
|
||||||
let device_buffer_guard = video_refresh_manager().device_buffer();
|
let device_buffer_guard = video_refresh_manager().device_buffer();
|
||||||
|
|
||||||
let buf_space: Arc<SpinLock<Box<[u32]>>> = Arc::new(SpinLock::new(
|
let buf_space: Arc<SpinLock<Box<[u8]>>> = Arc::new(SpinLock::new(
|
||||||
vec![0u32; (device_buffer_guard.size / 4) as usize].into_boxed_slice(),
|
vec![0u8; (device_buffer_guard.size / 4) as usize].into_boxed_slice(),
|
||||||
));
|
));
|
||||||
|
|
||||||
assert!(buf_type.contains(ScmBufferFlag::SCM_BF_DB));
|
assert!(buf_type.contains(ScmBufferFlag::SCM_BF_DB));
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
device_buffer_guard.size as usize,
|
device_buffer_guard.size as usize,
|
||||||
buf_space.lock().len() * core::mem::size_of::<u32>()
|
buf_space.lock().len() * core::mem::size_of::<u8>()
|
||||||
);
|
);
|
||||||
|
|
||||||
// 创建双缓冲区
|
// 创建双缓冲区
|
||||||
@ -155,11 +155,11 @@ impl ScmBufferInfo {
|
|||||||
ScmBuffer::DeviceBuffer(vaddr) => {
|
ScmBuffer::DeviceBuffer(vaddr) => {
|
||||||
let len = self.buf_size() / core::mem::size_of::<u32>();
|
let len = self.buf_size() / core::mem::size_of::<u32>();
|
||||||
let self_buf_guard =
|
let self_buf_guard =
|
||||||
unsafe { core::slice::from_raw_parts_mut(vaddr.data() as *mut u32, len) };
|
unsafe { core::slice::from_raw_parts_mut(vaddr.data() as *mut u8, len) };
|
||||||
match &src.buf {
|
match &src.buf {
|
||||||
ScmBuffer::DeviceBuffer(vaddr) => {
|
ScmBuffer::DeviceBuffer(vaddr) => {
|
||||||
let src_buf_guard =
|
let src_buf_guard =
|
||||||
unsafe { core::slice::from_raw_parts(vaddr.data() as *const u32, len) };
|
unsafe { core::slice::from_raw_parts(vaddr.data() as *const u8, len) };
|
||||||
self_buf_guard.copy_from_slice(src_buf_guard);
|
self_buf_guard.copy_from_slice(src_buf_guard);
|
||||||
}
|
}
|
||||||
ScmBuffer::DoubleBuffer(double_buffer) => {
|
ScmBuffer::DoubleBuffer(double_buffer) => {
|
||||||
@ -173,9 +173,9 @@ impl ScmBufferInfo {
|
|||||||
let mut double_buffer_guard = double_buffer.lock();
|
let mut double_buffer_guard = double_buffer.lock();
|
||||||
match &src.buf {
|
match &src.buf {
|
||||||
ScmBuffer::DeviceBuffer(vaddr) => {
|
ScmBuffer::DeviceBuffer(vaddr) => {
|
||||||
let len = src.buf_size() / core::mem::size_of::<u32>();
|
let len = src.buf_size() / core::mem::size_of::<u8>();
|
||||||
double_buffer_guard.as_mut().copy_from_slice(unsafe {
|
double_buffer_guard.as_mut().copy_from_slice(unsafe {
|
||||||
core::slice::from_raw_parts(vaddr.data() as *const u32, len)
|
core::slice::from_raw_parts(vaddr.data() as *const u8, len)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ScmBuffer::DoubleBuffer(double_buffer) => {
|
ScmBuffer::DoubleBuffer(double_buffer) => {
|
||||||
|
@ -17,6 +17,7 @@ use core::{
|
|||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
intrinsics::unlikely,
|
intrinsics::unlikely,
|
||||||
ops::{Add, AddAssign, Sub},
|
ops::{Add, AddAssign, Sub},
|
||||||
|
ptr::copy_nonoverlapping,
|
||||||
sync::atomic::{AtomicBool, AtomicI32, AtomicU32, Ordering},
|
sync::atomic::{AtomicBool, AtomicI32, AtomicU32, Ordering},
|
||||||
};
|
};
|
||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
@ -295,36 +296,41 @@ pub struct TextuiCharChromatic {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TextuiBuf<'a> {
|
pub struct TextuiBuf<'a> {
|
||||||
buf: Option<&'a mut [u32]>,
|
buf: Option<&'a mut [u8]>,
|
||||||
guard: Option<SpinLockGuard<'a, Box<[u32]>>>,
|
|
||||||
|
guard: Option<SpinLockGuard<'a, Box<[u8]>>>,
|
||||||
|
|
||||||
|
bit_depth: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextuiBuf<'_> {
|
impl TextuiBuf<'_> {
|
||||||
pub fn new(buf: &mut ScmBufferInfo) -> TextuiBuf {
|
pub fn new(buf: &mut ScmBufferInfo) -> TextuiBuf {
|
||||||
let len = buf.buf_size() / 4;
|
let len = buf.buf_size() / 4;
|
||||||
|
let depth = video_refresh_manager().device_buffer().bit_depth();
|
||||||
match &buf.buf {
|
match &buf.buf {
|
||||||
ScmBuffer::DeviceBuffer(vaddr) => {
|
ScmBuffer::DeviceBuffer(vaddr) => {
|
||||||
return TextuiBuf {
|
return TextuiBuf {
|
||||||
buf: Some(unsafe {
|
buf: Some(unsafe {
|
||||||
core::slice::from_raw_parts_mut(vaddr.data() as *mut u32, len)
|
core::slice::from_raw_parts_mut(vaddr.data() as *mut u8, len)
|
||||||
}),
|
}),
|
||||||
guard: None,
|
guard: None,
|
||||||
|
bit_depth: depth,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ScmBuffer::DoubleBuffer(double_buffer) => {
|
ScmBuffer::DoubleBuffer(double_buffer) => {
|
||||||
let guard: SpinLockGuard<'_, Box<[u32]>> = double_buffer.lock();
|
let guard: SpinLockGuard<'_, Box<[u8]>> = double_buffer.lock();
|
||||||
|
|
||||||
return TextuiBuf {
|
return TextuiBuf {
|
||||||
buf: None,
|
buf: None,
|
||||||
guard: Some(guard),
|
guard: Some(guard),
|
||||||
|
bit_depth: depth,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn buf_mut(&mut self) -> &mut [u32] {
|
pub fn buf_mut(&mut self) -> &mut [u8] {
|
||||||
if let Some(buf) = &mut self.buf {
|
if let Some(buf) = &mut self.buf {
|
||||||
return buf;
|
return buf;
|
||||||
} else {
|
} else {
|
||||||
@ -332,8 +338,34 @@ impl TextuiBuf<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn put_color_in_pixel(&mut self, color: u32, index: usize) {
|
pub fn put_color_in_pixel(&mut self, color: u32, index: usize) {
|
||||||
let buf: &mut [u32] = self.buf_mut();
|
let index = index as isize;
|
||||||
buf[index] = color;
|
match self.bit_depth {
|
||||||
|
32 => {
|
||||||
|
let buf = self.buf_mut().as_mut_ptr() as *mut u32;
|
||||||
|
unsafe {
|
||||||
|
*buf.offset(index) = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
24 => {
|
||||||
|
let buf = self.buf_mut().as_mut_ptr();
|
||||||
|
unsafe {
|
||||||
|
copy_nonoverlapping(&color as *const u32 as *const u8, buf.offset(index * 3), 3)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
16 => {
|
||||||
|
let buf = self.buf_mut().as_mut_ptr();
|
||||||
|
unsafe {
|
||||||
|
copy_nonoverlapping(
|
||||||
|
&color as *const u32 as *const u8,
|
||||||
|
buf.offset(index * 2),
|
||||||
|
2,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
panic!("不支持的位深度!")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub fn get_index_of_next_line(now_index: usize) -> usize {
|
pub fn get_index_of_next_line(now_index: usize) -> usize {
|
||||||
textui_framework().metadata.read().buf_info().width() as usize + now_index
|
textui_framework().metadata.read().buf_info().width() as usize + now_index
|
||||||
@ -430,8 +462,10 @@ impl TextuiCharChromatic {
|
|||||||
|
|
||||||
let id_y: u32 = lineid.into();
|
let id_y: u32 = lineid.into();
|
||||||
let y: u32 = id_y * TEXTUI_CHAR_HEIGHT;
|
let y: u32 = id_y * TEXTUI_CHAR_HEIGHT;
|
||||||
|
let buf_depth = video_refresh_manager().device_buffer().bit_depth();
|
||||||
let buf_width = video_refresh_manager().device_buffer().width();
|
let buf_width = video_refresh_manager().device_buffer().width();
|
||||||
|
let byte_num_of_depth = (buf_depth / 8) as usize;
|
||||||
|
|
||||||
// 找到输入缓冲区的起始地址位置
|
// 找到输入缓冲区的起始地址位置
|
||||||
let buf_start =
|
let buf_start =
|
||||||
if let ScmBuffer::DeviceBuffer(vaddr) = video_refresh_manager().device_buffer().buf {
|
if let ScmBuffer::DeviceBuffer(vaddr) = video_refresh_manager().device_buffer().buf {
|
||||||
@ -446,19 +480,35 @@ impl TextuiCharChromatic {
|
|||||||
for i in 0..TEXTUI_CHAR_HEIGHT {
|
for i in 0..TEXTUI_CHAR_HEIGHT {
|
||||||
// 计算出帧缓冲区每一行打印的起始位置的地址(起始位置+(y+i)*缓冲区的宽度+x)
|
// 计算出帧缓冲区每一行打印的起始位置的地址(起始位置+(y+i)*缓冲区的宽度+x)
|
||||||
|
|
||||||
let mut addr: *mut u32 =
|
let mut addr: *mut u8 = (buf_start
|
||||||
(buf_start + buf_width as usize * 4 * (y as usize + i as usize) + 4 * x as usize)
|
+ buf_width as usize * byte_num_of_depth * (y as usize + i as usize)
|
||||||
.data() as *mut u32;
|
+ byte_num_of_depth * x as usize)
|
||||||
|
.data() as *mut u8;
|
||||||
|
|
||||||
testbit = 1 << (TEXTUI_CHAR_WIDTH + 1);
|
testbit = 1 << (TEXTUI_CHAR_WIDTH + 1);
|
||||||
|
|
||||||
for _j in 0..TEXTUI_CHAR_WIDTH {
|
for _j in 0..TEXTUI_CHAR_WIDTH {
|
||||||
|
//该循环是渲染一行像素
|
||||||
//从左往右逐个测试相应位
|
//从左往右逐个测试相应位
|
||||||
testbit >>= 1;
|
testbit >>= 1;
|
||||||
if (font.0[i as usize] & testbit as u8) != 0 {
|
if (font.0[i as usize] & testbit as u8) != 0 {
|
||||||
unsafe { *addr = self.frcolor.into() }; // 字,显示前景色
|
let color: u32 = self.frcolor.into();
|
||||||
|
unsafe {
|
||||||
|
copy_nonoverlapping(
|
||||||
|
&color as *const u32 as *const u8,
|
||||||
|
addr,
|
||||||
|
byte_num_of_depth,
|
||||||
|
)
|
||||||
|
}; // 字,显示前景色
|
||||||
} else {
|
} else {
|
||||||
unsafe { *addr = self.bkcolor.into() }; // 背景色
|
let color: u32 = self.bkcolor.into();
|
||||||
|
unsafe {
|
||||||
|
copy_nonoverlapping(
|
||||||
|
&color as *const u32 as *const u8,
|
||||||
|
addr,
|
||||||
|
byte_num_of_depth,
|
||||||
|
)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -36,7 +36,7 @@ pub fn no_init_textui_putchar_window(
|
|||||||
bkcolor: FontColor,
|
bkcolor: FontColor,
|
||||||
is_put_to_window: bool,
|
is_put_to_window: bool,
|
||||||
) -> Result<(), SystemError> {
|
) -> Result<(), SystemError> {
|
||||||
if NO_ALLOC_OPERATIONS_LINE.load(Ordering::SeqCst) > TRUE_LINE_NUM.load(Ordering::SeqCst) {
|
if NO_ALLOC_OPERATIONS_LINE.load(Ordering::SeqCst) >= TRUE_LINE_NUM.load(Ordering::SeqCst) {
|
||||||
NO_ALLOC_OPERATIONS_LINE.store(0, Ordering::SeqCst);
|
NO_ALLOC_OPERATIONS_LINE.store(0, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
//字符'\0'代表ASCII码表中的空字符,表示字符串的结尾
|
//字符'\0'代表ASCII码表中的空字符,表示字符串的结尾
|
||||||
|
Loading…
x
Reference in New Issue
Block a user