1- use bootloader_api:: info:: { FrameBufferInfo , PixelFormat } ;
1+ use crate :: framebuffer:: FrameBufferWriter ;
2+ use bootloader_api:: info:: FrameBufferInfo ;
3+ use core:: fmt:: Write ;
24use conquer_once:: spin:: OnceCell ;
3- use core:: {
4- fmt:: { self , Write } ,
5- ptr,
6- } ;
7- use font_constants:: BACKUP_CHAR ;
8- use noto_sans_mono_bitmap:: {
9- get_raster, get_raster_width, FontWeight , RasterHeight , RasterizedChar ,
10- } ;
115use spinning_top:: Spinlock ;
126
137/// The global logger instance used for the `log` crate.
148pub static LOGGER : OnceCell < LockedLogger > = OnceCell :: uninit ( ) ;
159
16- /// A [`Logger`] instance protected by a spinlock.
17- pub struct LockedLogger ( Spinlock < Logger > ) ;
18-
19- /// Additional vertical space between lines
20- const LINE_SPACING : usize = 2 ;
21- /// Additional horizontal space between characters.
22- const LETTER_SPACING : usize = 0 ;
23-
24- /// Padding from the border. Prevent that font is too close to border.
25- const BORDER_PADDING : usize = 1 ;
26-
27- /// Constants for the usage of the [`noto_sans_mono_bitmap`] crate.
28- mod font_constants {
29- use super :: * ;
30-
31- /// Height of each char raster. The font size is ~0.84% of this. Thus, this is the line height that
32- /// enables multiple characters to be side-by-side and appear optically in one line in a natural way.
33- pub const CHAR_RASTER_HEIGHT : RasterHeight = RasterHeight :: Size16 ;
34-
35- /// The width of each single symbol of the mono space font.
36- pub const CHAR_RASTER_WIDTH : usize = get_raster_width ( FontWeight :: Regular , CHAR_RASTER_HEIGHT ) ;
37-
38- /// Backup character if a desired symbol is not available by the font.
39- /// The '�' character requires the feature "unicode-specials".
40- pub const BACKUP_CHAR : char = '�' ;
41-
42- pub const FONT_WEIGHT : FontWeight = FontWeight :: Regular ;
43- }
44-
45- /// Returns the raster of the given char or the raster of [`font_constants::BACKUP_CHAR`].
46- fn get_char_raster ( c : char ) -> RasterizedChar {
47- fn get ( c : char ) -> Option < RasterizedChar > {
48- get_raster (
49- c,
50- font_constants:: FONT_WEIGHT ,
51- font_constants:: CHAR_RASTER_HEIGHT ,
52- )
53- }
54- get ( c) . unwrap_or_else ( || get ( BACKUP_CHAR ) . expect ( "Should get raster of backup char." ) )
55- }
10+ /// A [`FrameBufferWriter`] instance protected by a spinlock.
11+ pub struct LockedLogger ( Spinlock < FrameBufferWriter > ) ;
5612
5713impl LockedLogger {
5814 /// Create a new instance that logs to the given framebuffer.
5915 pub fn new ( framebuffer : & ' static mut [ u8 ] , info : FrameBufferInfo ) -> Self {
60- LockedLogger ( Spinlock :: new ( Logger :: new ( framebuffer, info) ) )
16+ LockedLogger ( Spinlock :: new ( FrameBufferWriter :: new ( framebuffer, info) ) )
6117 }
6218
6319 /// Force-unlocks the logger to prevent a deadlock.
@@ -82,112 +38,3 @@ impl log::Log for LockedLogger {
8238 fn flush ( & self ) { }
8339}
8440
85- /// Allows logging text to a pixel-based framebuffer.
86- pub struct Logger {
87- framebuffer : & ' static mut [ u8 ] ,
88- info : FrameBufferInfo ,
89- x_pos : usize ,
90- y_pos : usize ,
91- }
92-
93- impl Logger {
94- /// Creates a new logger that uses the given framebuffer.
95- pub fn new ( framebuffer : & ' static mut [ u8 ] , info : FrameBufferInfo ) -> Self {
96- let mut logger = Self {
97- framebuffer,
98- info,
99- x_pos : 0 ,
100- y_pos : 0 ,
101- } ;
102- logger. clear ( ) ;
103- logger
104- }
105-
106- fn newline ( & mut self ) {
107- self . y_pos += font_constants:: CHAR_RASTER_HEIGHT . val ( ) + LINE_SPACING ;
108- self . carriage_return ( )
109- }
110-
111- fn carriage_return ( & mut self ) {
112- self . x_pos = BORDER_PADDING ;
113- }
114-
115- /// Erases all text on the screen. Resets `self.x_pos` and `self.y_pos`.
116- pub fn clear ( & mut self ) {
117- self . x_pos = BORDER_PADDING ;
118- self . y_pos = BORDER_PADDING ;
119- self . framebuffer . fill ( 0 ) ;
120- }
121-
122- fn width ( & self ) -> usize {
123- self . info . width
124- }
125-
126- fn height ( & self ) -> usize {
127- self . info . height
128- }
129-
130- /// Writes a single char to the framebuffer. Takes care of special control characters, such as
131- /// newlines and carriage returns.
132- fn write_char ( & mut self , c : char ) {
133- match c {
134- '\n' => self . newline ( ) ,
135- '\r' => self . carriage_return ( ) ,
136- c => {
137- let new_xpos = self . x_pos + font_constants:: CHAR_RASTER_WIDTH ;
138- if new_xpos >= self . width ( ) {
139- self . newline ( ) ;
140- }
141- let new_ypos =
142- self . y_pos + font_constants:: CHAR_RASTER_HEIGHT . val ( ) + BORDER_PADDING ;
143- if new_ypos >= self . height ( ) {
144- self . clear ( ) ;
145- }
146- self . write_rendered_char ( get_char_raster ( c) ) ;
147- }
148- }
149- }
150-
151- /// Prints a rendered char into the framebuffer.
152- /// Updates `self.x_pos`.
153- fn write_rendered_char ( & mut self , rendered_char : RasterizedChar ) {
154- for ( y, row) in rendered_char. raster ( ) . iter ( ) . enumerate ( ) {
155- for ( x, byte) in row. iter ( ) . enumerate ( ) {
156- self . write_pixel ( self . x_pos + x, self . y_pos + y, * byte) ;
157- }
158- }
159- self . x_pos += rendered_char. width ( ) + LETTER_SPACING ;
160- }
161-
162- fn write_pixel ( & mut self , x : usize , y : usize , intensity : u8 ) {
163- let pixel_offset = y * self . info . stride + x;
164- let color = match self . info . pixel_format {
165- PixelFormat :: Rgb => [ intensity, intensity, intensity / 2 , 0 ] ,
166- PixelFormat :: Bgr => [ intensity / 2 , intensity, intensity, 0 ] ,
167- PixelFormat :: U8 => [ if intensity > 200 { 0xf } else { 0 } , 0 , 0 , 0 ] ,
168- other => {
169- // set a supported (but invalid) pixel format before panicking to avoid a double
170- // panic; it might not be readable though
171- self . info . pixel_format = PixelFormat :: Rgb ;
172- panic ! ( "pixel format {:?} not supported in logger" , other)
173- }
174- } ;
175- let bytes_per_pixel = self . info . bytes_per_pixel ;
176- let byte_offset = pixel_offset * bytes_per_pixel;
177- self . framebuffer [ byte_offset..( byte_offset + bytes_per_pixel) ]
178- . copy_from_slice ( & color[ ..bytes_per_pixel] ) ;
179- let _ = unsafe { ptr:: read_volatile ( & self . framebuffer [ byte_offset] ) } ;
180- }
181- }
182-
183- unsafe impl Send for Logger { }
184- unsafe impl Sync for Logger { }
185-
186- impl fmt:: Write for Logger {
187- fn write_str ( & mut self , s : & str ) -> fmt:: Result {
188- for c in s. chars ( ) {
189- self . write_char ( c) ;
190- }
191- Ok ( ( ) )
192- }
193- }
0 commit comments