@@ -147,9 +147,34 @@ void VBEFillScreen(uint32_t color) {
147147void VBEDrawRect (uint32_t x , uint32_t y , uint32_t width , uint32_t height , uint32_t color ) {
148148 if (!vbe_initialized ) return ;
149149
150- for (uint32_t row = y ; row < y + height && row < vbe_info .height ; row ++ ) {
151- for (uint32_t col = x ; col < x + width && col < vbe_info .width ; col ++ ) {
152- VBEPutPixel (col , row , color );
150+ if (x >= vbe_info .width || y >= vbe_info .height ) return ;
151+
152+ // Clip
153+ if (width > vbe_info .width - x ) width = vbe_info .width - x ;
154+ if (height > vbe_info .height - y ) height = vbe_info .height - y ;
155+ if (width == 0 || height == 0 ) return ;
156+
157+ uint32_t mapped = VBEMapColor (color );
158+
159+ uint8_t * fb = (uint8_t * )vbe_info .framebuffer ;
160+ uint32_t pitch = vbe_info .pitch ;
161+
162+ // Pattern buffer: 1 KiB = 256 pixels
163+ uint32_t pattern [256 ];
164+ for (uint32_t i = 0 ; i < 256 ; i ++ ) pattern [i ] = mapped ;
165+
166+ uint64_t row_bytes = (uint64_t )width * 4u ;
167+
168+ for (uint32_t r = 0 ; r < height ; r ++ ) {
169+ uint8_t * dst = fb + (uint64_t )(y + r ) * pitch + (uint64_t )x * 4u ;
170+ uint64_t remaining = row_bytes ;
171+ while (remaining >= sizeof (pattern )) {
172+ FastMemcpy (dst , pattern , sizeof (pattern ));
173+ dst += sizeof (pattern );
174+ remaining -= sizeof (pattern );
175+ }
176+ if (remaining ) {
177+ FastMemcpy (dst , pattern , remaining );
153178 }
154179 }
155180}
@@ -187,21 +212,40 @@ void VBEDrawChar(uint32_t x, uint32_t y, char c, uint32_t fg_color, uint32_t bg_
187212 return ; // Character out of bounds
188213 }
189214
215+ // Clip early if entirely outside
216+ if (x >= vbe_info .width || y >= vbe_info .height ) return ;
217+
190218 const unsigned char * glyph = console_font [(unsigned char )c ];
191219
220+ // Pre-map colors
221+ uint32_t fg = VBEMapColor (fg_color );
222+ uint32_t bg = VBEMapColor (bg_color );
223+
224+ uint32_t max_w = vbe_info .width ;
225+ uint32_t max_h = vbe_info .height ;
226+
192227 // Use the font dimensions from font.h
193228 for (int row = 0 ; row < FONT_HEIGHT ; row ++ ) {
229+ uint32_t py = y + (uint32_t )row ;
230+ if (py >= max_h ) break ; // Outside vertical bounds
231+
194232 // Calculate which byte contains this row's data
195233 int byte_index = row * ((FONT_WIDTH + 7 ) / 8 ); // Number of bytes per row
196234
235+ // Start of the destination row in framebuffer
236+ uint32_t * dst_row = (uint32_t * )((uint8_t * )vbe_info .framebuffer + (uint64_t )py * vbe_info .pitch ) + x ;
237+
197238 for (int col = 0 ; col < FONT_WIDTH ; col ++ ) {
198- int bit_position = 7 - (col % 8 ); // MSB first
239+ uint32_t px = x + (uint32_t )col ;
240+ if (px >= max_w ) break ; // Outside horizontal bounds
199241
200- if ((glyph [byte_index + (col / 8 )] >> bit_position ) & 1 ) {
201- VBEPutPixel (x + col , y + row , fg_color );
242+ int bit_position = 7 - (col % 8 ); // MSB first
243+ uint8_t glyph_byte = glyph [byte_index + (col / 8 )];
244+ if ((glyph_byte >> bit_position ) & 1 ) {
245+ dst_row [col ] = fg ;
202246 } else {
203247 // Always draw background to ensure proper clearing
204- VBEPutPixel ( x + col , y + row , bg_color ) ;
248+ dst_row [ col ] = bg ;
205249 }
206250 }
207251 }
@@ -288,32 +332,62 @@ void VBEShowSplash(void) {
288332 if (!vbe_initialized ) return ;
289333
290334 for (unsigned int i = 0 ; i < num_splash_images ; i ++ ) { // Loop
291- const uint32_t * image_data = (const uint32_t * )splash_images [i % num_splash_images ];
292-
335+ const uint32_t * image_data = (const uint32_t * )splash_images [i ];
336+ uint8_t * fb = (uint8_t * )vbe_info .framebuffer ;
337+ // Copy entire scanlines at once instead of pixel-by-pixel
293338 for (uint32_t y = 0 ; y < vbe_info .height ; y ++ ) {
294- for (uint32_t x = 0 ; x < vbe_info .width ; x ++ ) {
295- VBEPutPixel (x , y , image_data [y * vbe_info .width + x ]);
339+ // Calculate source and destination for this scanline
340+ const uint32_t * src = & image_data [y * vbe_info .width ];
341+ uint8_t * dst = fb + (y * vbe_info .pitch );
342+ // Fast path: only when framebuffer uses 8:8:8 at 16/8/0 (0x00RRGGBB)
343+ int direct_compatible =
344+ (vbe_info .red_mask_size == 8 && vbe_info .red_field_position == 16 ) &&
345+ (vbe_info .green_mask_size == 8 && vbe_info .green_field_position == 8 ) &&
346+ (vbe_info .blue_mask_size == 8 && vbe_info .blue_field_position == 0 );
347+ if (direct_compatible ) {
348+ FastMemcpy (dst , src , vbe_info .width * 4 );
349+ } else {
350+ // Fallback: map each pixel
351+ uint32_t * d32 = (uint32_t * )dst ;
352+ const uint32_t * s32 = src ;
353+ for (uint32_t x = 0 ; x < vbe_info .width ; x ++ ) {
354+ // Assume source is 0x00RRGGBB
355+ d32 [x ] = VBEMapColor (s32 [x ]);
356+ }
296357 }
297358 }
298359 }
299- delay (700000000 );
300360}
301361#endif
302362
303363#ifndef VF_CONFIG_EXCLUDE_EXTRA_OBJECTS
304364void VBEShowPanic (void ) {
305365 if (!vbe_initialized ) return ;
306- const uint32_t * image_data = (const uint32_t * )panic_images [0 ];
307- uint8_t * fb = (uint8_t * )vbe_info .framebuffer ;
308-
309- // Copy entire scanlines at once instead of pixel-by-pixel
310- for (uint32_t y = 0 ; y < vbe_info .height ; y ++ ) {
311- // Calculate source and destination for this scanline
312- const uint32_t * src = & image_data [y * vbe_info .width ];
313- uint8_t * dst = fb + (y * vbe_info .pitch );
314-
315- // Copy entire scanline (width * 4 bytes) using optimized memcpy
316- FastMemcpy (dst , src , vbe_info .width * 4 );
366+ for (unsigned int i = 0 ; i < num_panic_images ; i ++ ) { // Loop
367+ const uint32_t * image_data = (const uint32_t * )panic_images [i ];
368+ uint8_t * fb = (uint8_t * )vbe_info .framebuffer ;
369+ // Copy entire scanlines at once instead of pixel-by-pixel
370+ for (uint32_t y = 0 ; y < vbe_info .height ; y ++ ) {
371+ // Calculate source and destination for this scanline
372+ const uint32_t * src = & image_data [y * vbe_info .width ];
373+ uint8_t * dst = fb + (y * vbe_info .pitch );
374+ // Fast path: only when framebuffer uses 8:8:8 at 16/8/0 (0x00RRGGBB)
375+ int direct_compatible =
376+ (vbe_info .red_mask_size == 8 && vbe_info .red_field_position == 16 ) &&
377+ (vbe_info .green_mask_size == 8 && vbe_info .green_field_position == 8 ) &&
378+ (vbe_info .blue_mask_size == 8 && vbe_info .blue_field_position == 0 );
379+ if (direct_compatible ) {
380+ FastMemcpy (dst , src , vbe_info .width * 4 );
381+ } else {
382+ // Fallback: map each pixel
383+ uint32_t * d32 = (uint32_t * )dst ;
384+ const uint32_t * s32 = src ;
385+ for (uint32_t x = 0 ; x < vbe_info .width ; x ++ ) {
386+ // Assume source is 0x00RRGGBB
387+ d32 [x ] = VBEMapColor (s32 [x ]);
388+ }
389+ }
390+ }
317391 }
318392}
319393#endif
0 commit comments