1extern crate alloc;
2use crate::graphics::color;
3use crate::libs::bmp::{BmpError, BmpImage};
4use alloc::{vec, vec::Vec};
5use core::slice;
6use limine::framebuffer::Framebuffer;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub struct Pixel {
10 pub x: u64,
11 pub y: u64,
12}
13
14impl Pixel {
15 pub fn new(x: u64, y: u64) -> Self {
16 Self { x, y }
17 }
18}
19
20pub trait PixelCoord {
21 fn to_coord(&self) -> (u64, u64);
22}
23
24impl PixelCoord for Pixel {
25 fn to_coord(&self) -> (u64, u64) {
26 (self.x, self.y)
27 }
28}
29
30#[macro_export]
31macro_rules! pixel {
32 ($x:expr, $y:expr) => {{
33 Pixel::new(($x) as u64, ($y) as u64)
34 }};
35}
36
37pub struct Renderer<'a> {
38 framebuffer: Framebuffer<'a>, back_buffer: Vec<u8>, pixel_size: usize, clear_color: color::Color, dirty_min_x: u64,
43 dirty_min_y: u64,
44 dirty_max_x: u64,
45 dirty_max_y: u64,
46 width: usize,
47 height: usize,
48 bpp: usize,
49}
50
51impl<'a> Renderer<'a> {
52 pub fn new(framebuffer: Framebuffer<'a>) -> Self {
53 let width = framebuffer.width() as usize;
54 let height = framebuffer.height() as usize;
55 let bpp = framebuffer.bpp() as usize; let pixel_size = bpp / 8; let buffer_size = width * height * pixel_size; let back_buffer = vec![0; buffer_size];
61 Self {
62 framebuffer: framebuffer,
63 back_buffer,
64 pixel_size,
65 clear_color: color::BLACK,
66 dirty_min_x: u64::MAX,
67 dirty_min_y: u64::MAX,
68 dirty_max_x: 0,
69 dirty_max_y: 0,
70 width,
71 height,
72 bpp,
73 }
74 }
75
76 #[inline(always)]
78 fn get_buffer_offset(&self, x: u64, y: u64) -> usize {
79 y as usize * self.framebuffer.width() as usize * self.pixel_size
81 + x as usize * self.pixel_size
82 }
83
84 #[inline(always)]
86 fn mask_color(&self, color: &color::Color) -> u32 {
87 if self.bpp == 32 {
88 let value: u32 = ((color.r as u32) << self.framebuffer.red_mask_shift())
89 | ((color.g as u32) << self.framebuffer.green_mask_shift())
90 | ((color.b as u32) << self.framebuffer.blue_mask_shift());
91 return value;
92 } else if self.bpp == 24 {
93 color.to_u32(false)
94 } else {
95 panic!("Unsupported bit per pixel: {}", self.framebuffer.bpp())
96 }
97 }
98
99 #[inline(always)]
101 pub unsafe fn set_pixel_raw_unchecked(&mut self, x: u64, y: u64, color: &color::Color) {
102 let offset = self.get_buffer_offset(x, y);
103
104 let color_u32 = if color.a == 255 {
105 self.mask_color(color)
106 } else if color.a == 0 {
107 return;
108 } else {
109 let current_color = self.get_pixel_raw(x, y);
111
112 let alpha = color.a as u32;
114 let inv_alpha = 255 - alpha;
115 let r = (color.r as u32 * alpha + current_color.r as u32 * inv_alpha) / 255;
116 let g = (color.g as u32 * alpha + current_color.g as u32 * inv_alpha) / 255;
117 let b = (color.b as u32 * alpha + current_color.b as u32 * inv_alpha) / 255;
118
119 let mixed_color = color::Color::with_alpha(r as u8, g as u8, b as u8, 255);
120 self.mask_color(&mixed_color)
121 };
122
123 let pixel_bytes = color_u32.to_le_bytes(); unsafe {
125 let dst_ptr = self.back_buffer.as_mut_ptr().add(offset);
126 core::ptr::copy_nonoverlapping(pixel_bytes.as_ptr(), dst_ptr, self.pixel_size);
127 }
128
129 self.dirty_min_x = self.dirty_min_x.min(x);
130 self.dirty_min_y = self.dirty_min_y.min(y);
131 self.dirty_max_x = self.dirty_max_x.max(x);
132 self.dirty_max_y = self.dirty_max_y.max(y);
133 }
134
135 #[inline(always)]
136 pub fn set_pixel_raw(&mut self, x: u64, y: u64, color: &color::Color) {
137 if x >= self.width as u64 || y >= self.height as u64 {
139 return;
140 }
141 unsafe { self.set_pixel_raw_unchecked(x, y, color) };
142 }
143
144 #[inline(always)]
146 pub fn set_pixel(&mut self, pixel: Pixel, color: &color::Color) {
147 let (x, y) = pixel.to_coord();
148 self.set_pixel_raw(x, y, color);
149 }
150
151 pub fn get_pixel(&self, pixel: Pixel) -> color::Color {
153 let (x, y) = pixel.to_coord();
154 self.get_pixel_raw(x, y) }
156
157 fn get_pixel_raw(&self, x: u64, y: u64) -> color::Color {
159 let offset = self.get_buffer_offset(x, y);
160 let mut pixel_data_u32 = 0u32;
161 for i in 0..self.pixel_size {
162 pixel_data_u32 |= (self.back_buffer[offset + i] as u32) << (i * 8);
163 }
164 color::Color::from_u32(pixel_data_u32)
165 }
166
167 pub fn set_clear_color(&mut self, color: color::Color) {
168 self.clear_color = color;
169 }
170
171 pub fn get_clear_color(&self) -> color::Color {
172 self.clear_color
173 }
174
175 pub fn clear(&mut self) {
177 let width = self.framebuffer.width();
178 let height = self.framebuffer.height();
179 let color = self.clear_color.clone();
180 let masked_clear_color = self.mask_color(&color);
182 let pixel_bytes = masked_clear_color.to_le_bytes(); let bytes_to_fill = &pixel_bytes[..self.pixel_size];
184 for y in 0..height {
185 for x in 0..width {
186 let offset = self.get_buffer_offset(x, y);
187 for i in 0..self.pixel_size {
188 self.back_buffer[offset + i] = bytes_to_fill[i];
189 }
190 }
191 }
192
193 self.dirty_min_x = 0;
194 self.dirty_min_y = 0;
195 self.dirty_max_x = width;
196 self.dirty_max_y = height;
197 }
198
199 pub fn draw_line(&mut self, p1: Pixel, p2: Pixel, color: color::Color) {
201 let dx_abs = ((p2.x as i64 - p1.x as i64).abs()) as u64;
202 let dy_abs = ((p2.y as i64 - p1.y as i64).abs()) as u64;
203 let steep = dy_abs > dx_abs;
204 let (mut x1, mut y1) = p1.to_coord();
205 let (mut x2, mut y2) = p2.to_coord();
206 if steep {
207 core::mem::swap(&mut x1, &mut y1);
208 core::mem::swap(&mut x2, &mut y2);
209 }
210 if x1 > x2 {
211 core::mem::swap(&mut x1, &mut x2);
212 core::mem::swap(&mut y1, &mut y2);
213 }
214 let dx = x2 - x1;
215 let dy = (y2 as i64 - y1 as i64).abs() as u64;
216 let mut error = (dx / 2) as i64;
217 let y_step = if y1 < y2 { 1 } else { -1 };
218 let mut y = y1 as i64;
219 for x in x1..=x2 {
220 if steep {
221 if y >= 0 && (y as u64) < self.framebuffer.width() && x < self.framebuffer.height()
223 {
224 self.set_pixel_raw(y as u64, x, &color);
225 }
226 } else {
227 if x < self.framebuffer.width() && y >= 0 && (y as u64) < self.framebuffer.height()
228 {
229 self.set_pixel_raw(x, y as u64, &color);
230 }
231 }
232 error -= dy as i64;
233 if error < 0 {
234 y += y_step;
235 error += dx as i64;
236 }
237 }
238 }
239
240 pub fn draw_triangle(&mut self, p1: Pixel, p2: Pixel, p3: Pixel, color: color::Color) {
242 self.draw_line(p1, p2, color);
243 self.draw_line(p2, p3, color);
244 self.draw_line(p3, p1, color);
245 }
246
247 pub fn fill_triangle(&mut self, p1: Pixel, p2: Pixel, p3: Pixel, color: color::Color) {
249 let (x1, y1) = p1.to_coord();
250 let (x2, y2) = p2.to_coord();
251 let (x3, y3) = p3.to_coord();
252 let mut pts = [pixel!(x1, y1), pixel!(x2, y2), pixel!(x3, y3)];
254 for i in 0..pts.len() {
256 for j in i + 1..pts.len() {
257 if pts[i].y > pts[j].y {
258 pts.swap(i, j);
259 }
260 }
261 }
262 let p1 = pts[0];
263 let p2 = pts[1];
264 let p3 = pts[2];
265 if p1.y == p3.y {
267 return;
268 }
269 let (x1, y1) = (p1.x as i32, p1.y as i32);
271 let (x2, y2) = (p2.x as i32, p2.y as i32);
272 let (x3, y3) = (p3.x as i32, p3.y as i32);
273 let mut fill_h_line = |start_x: i32, end_x: i32, y: i32| {
275 if y < 0 || y >= self.framebuffer.height() as i32 {
276 return;
277 }
278 let mut start_x = start_x.max(0);
279 let mut end_x = end_x.min(self.framebuffer.width() as i32 - 1);
280 if start_x > end_x {
281 core::mem::swap(&mut start_x, &mut end_x);
282 }
283 if start_x < 0 || end_x >= self.framebuffer.width() as i32 {
284 start_x = start_x.max(0);
285 end_x = end_x.min(self.framebuffer.width() as i32 - 1);
286 if start_x > end_x {
287 return;
288 }
289 }
290 for x in start_x..=end_x {
292 if x >= 0 {
293 let pixel = pixel!(x, y);
294 self.set_pixel(pixel, &color);
295 }
296 }
297 };
298 let long_dx = x3 - x1;
299 let long_dy = y3 - y1;
300 if long_dy != 0 {
301 let upper_dx = x2 - x1;
303 let upper_dy = y2 - y1;
304 let y_start = y1;
305 let y_end = y2;
306 for y in y_start..=y_end {
307 let dy = y - y1;
308 let x_long = if long_dy != 0 {
309 x1 + (long_dx * dy + long_dy / 2) / long_dy
310 } else {
311 x1
312 };
313 let x_upper = if upper_dy != 0 {
314 x1 + (upper_dx * dy + upper_dy / 2) / upper_dy
315 } else {
316 x1
317 };
318 fill_h_line(x_long, x_upper, y);
319 }
320 let lower_dx = x3 - x2;
322 let lower_dy = y3 - y2;
323 if lower_dy != 0 {
324 for y in y2..=y3 {
325 let dy_long = y - y1;
326 let dy_lower = y - y2;
327 let x_long = if long_dy != 0 {
328 x1 + (long_dx * dy_long + long_dy / 2) / long_dy
329 } else {
330 x1
331 };
332 let x_lower = if lower_dy != 0 {
333 x2 + (lower_dx * dy_lower + lower_dy / 2) / lower_dy
334 } else {
335 x2
336 };
337 fill_h_line(x_long, x_lower, y);
338 }
339 }
340 }
341 }
342
343 pub fn width(&self) -> u64 {
344 self.framebuffer.width()
345 }
346
347 pub fn height(&self) -> u64 {
348 self.framebuffer.height()
349 }
350
351 pub fn draw_rect(&mut self, pixel: Pixel, width: u64, height: u64, color: color::Color) -> () {
353 let (x, y) = pixel.to_coord();
354 let x2 = x + width;
355 let y2 = y + height;
356 self.draw_line(pixel!(x, y), pixel!(x2, y), color);
358 self.draw_line(pixel!(x2, y), pixel!(x2, y2), color);
359 self.draw_line(pixel!(x2, y2), pixel!(x, y2), color);
360 self.draw_line(pixel!(x, y2), pixel!(x, y), color);
361 }
362
363 pub fn fill_rect(&mut self, pixel: Pixel, width: u64, height: u64, color: color::Color) {
365 let (x_min, y_min) = pixel.to_coord();
366 let x_max = x_min + width;
367 let y_max = y_min + height;
368 let x_start = x_min.max(0);
369 let x_end = x_max.min(self.width() - 1);
370 let y_start = y_min.max(0);
371 let y_end = y_max.min(self.height() - 1);
372 for y in y_start..=y_end {
373 for x in x_start..=x_end {
374 self.set_pixel_raw(x, y, &color); }
376 }
377 }
378
379 pub fn draw_polygon(&mut self, points: &[Pixel], color: color::Color) {
381 if points.len() < 3 {
382 return; }
384 for i in 0..points.len() {
386 let p1 = points[i];
387 let p2 = points[(i + 1) % points.len()]; self.draw_line(p1, p2, color);
389 }
390 }
391 pub fn fill_convex_polygon(&mut self, points: &[Pixel], color: color::Color) {
393 if points.len() < 3 {
394 return; }
396 let mut edges = Vec::new();
398 for i in 0..points.len() {
399 let p1 = points[i];
400 let p2 = points[(i + 1) % points.len()];
401 edges.push((p1, p2));
402 }
403 let min_y = edges.iter().map(|&(p, _)| p.y).min().unwrap_or(0);
405 let max_y = edges.iter().map(|&(p, _)| p.y).max().unwrap_or(0);
406 let mut edge_info: Vec<(f64, f64, f64, f64)> = Vec::new();
408 for &(p1, p2) in &edges {
409 if p1.y != p2.y {
410 let y_start = p1.y.min(p2.y) as f64;
411 let y_end = p1.y.max(p2.y) as f64;
412 let x_start = if p1.y < p2.y {
413 p1.x as f64
414 } else {
415 p2.x as f64
416 };
417 let dx = (p2.x as f64 - p1.x as f64) / (p2.y as f64 - p1.y as f64);
418 edge_info.push((y_start, y_end, x_start, dx));
419 }
420 }
421 for y in min_y..=max_y {
423 let mut intersections = Vec::new();
424
425 for &(y_start, y_end, x_start, dx) in &edge_info {
427 if (y as f64) >= y_start && (y as f64) <= y_end {
428 let x = x_start + (y as f64 - y_start) * dx;
429 intersections.push(x);
430 }
431 }
432 intersections.sort_by(|a, b| a.partial_cmp(b).expect("Float comparison failed"));
434 for i in (0..intersections.len()).step_by(2) {
436 if i + 1 >= intersections.len() {
437 break;
438 }
439
440 let start_x = intersections[i].max(0.0).min(self.width() as f64 - 1.0) as u64;
441 let end_x = intersections[i + 1].max(0.0).min(self.width() as f64 - 1.0) as u64;
442
443 if start_x > end_x {
444 continue;
445 }
446
447 for x in start_x..=end_x {
448 self.set_pixel_raw(x, y, &color);
449 }
450 }
451 }
452 }
453 pub fn fill_polygon(&mut self, points: &[Pixel], color: color::Color) {
455 if points.len() < 3 {
456 return;
457 }
458 let min_y = points.iter().map(|p| p.y).min().unwrap_or(0);
460 let max_y = points.iter().map(|p| p.y).max().unwrap_or(0);
461 let mut edge_table = Vec::new();
463 for i in 0..points.len() {
464 let p1 = points[i];
465 let p2 = points[(i + 1) % points.len()];
466
467 if p1.y != p2.y {
468 let (start, end) = if p1.y < p2.y { (p1, p2) } else { (p2, p1) };
469 let dx = (end.x as f64 - start.x as f64) / (end.y as f64 - start.y as f64);
470 edge_table.push((start.y as f64, end.y as f64, start.x as f64, dx));
471 }
472 }
473 for y in min_y..=max_y {
475 let mut intersections = Vec::new();
476
477 for &(y_min, y_max, mut x, dx) in &edge_table {
479 if (y as f64) >= y_min && (y as f64) < y_max {
480 if y as f64 > y_min {
481 x += (y as f64 - y_min) * dx;
482 }
483 intersections.push(x);
484 }
485 }
486 intersections.sort_by(|a, b| a.partial_cmp(b).expect("Float comparison failed"));
488 let mut inside = false;
490 for i in 0..intersections.len() {
491 if inside && i < intersections.len() {
492 let start_x = intersections[i].max(0.0).min(self.width() as f64 - 1.0) as u64;
493
494 if i + 1 < intersections.len() {
496 let end_x =
497 intersections[i + 1].max(0.0).min(self.width() as f64 - 1.0) as u64;
498
499 if start_x <= end_x {
500 for x in start_x..=end_x {
501 self.set_pixel_raw(x, y, &color);
502 }
503 }
504 } else {
505 let end_x = self.width().min(self.width() - 1);
507 if start_x <= end_x {
508 for x in start_x..=end_x {
509 self.set_pixel_raw(x, y, &color);
510 }
511 }
512 }
513 }
514 inside = !inside;
515 }
516 }
517 }
518
519 pub fn draw_bmp(&mut self, pos: Pixel, bmp: &BmpImage) {
521 let (x_start, y_start) = (pos.x, pos.y);
522
523 for y in 0..bmp.height() {
524 for x in 0..bmp.width() {
525 if let Some(color) = bmp.pixel(x, y) {
526 self.set_pixel_raw(x_start + x as u64, y_start + y as u64, &color);
527 }
528 }
529 }
530 }
531 pub fn draw_bmp_scaled(&mut self, pos: Pixel, bmp: &BmpImage, scale_x: f32, scale_y: f32) {
533 let scaled_width = (bmp.width() as f32 * scale_x) as u64;
534 let scaled_height = (bmp.height() as f32 * scale_y) as u64;
535
536 for y in 0..scaled_height {
537 for x in 0..scaled_width {
538 let src_x = (x as f32 / scale_x) as u32;
540 let src_y = (y as f32 / scale_y) as u32;
541
542 if let Some(color) = bmp.pixel(src_x, src_y) {
543 self.set_pixel_raw(pos.x + x, pos.y + y, &color);
544 }
545 }
546 }
547 }
548 pub fn draw_bmp_distorted(&mut self, corners: [Pixel; 4], bmp: &BmpImage) {
550 let min_x = corners.iter().map(|p| p.x).min().unwrap_or(0);
552 let max_x = corners.iter().map(|p| p.x).max().unwrap_or(0);
553 let min_y = corners.iter().map(|p| p.y).min().unwrap_or(0);
554 let max_y = corners.iter().map(|p| p.y).max().unwrap_or(0);
555
556 for y in min_y..=max_y {
558 for x in min_x..=max_x {
559 let u = (x - min_x) as f32 / (max_x - min_x) as f32;
561 let v = (y - min_y) as f32 / (max_y - min_y) as f32;
562
563 let src_x = (u * bmp.width() as f32) as u32;
564 let src_y = (v * bmp.height() as f32) as u32;
565
566 if let Some(color) = bmp.pixel(src_x, src_y) {
567 self.set_pixel_raw(x, y, &color);
568 }
569 }
570 }
571 }
572 pub fn draw_bmp_from_bytes(&mut self, pos: Pixel, data: &[u8]) -> Result<(), BmpError> {
574 let bmp = BmpImage::from_bytes(data)?;
575 self.draw_bmp(pos, &bmp);
576 Ok(())
577 }
578
579 pub fn draw_circle(&mut self, center: Pixel, radius: u64, color: color::Color) {
581 if radius == 0 {
582 return;
583 }
584
585 let (cx, cy) = center.to_coord();
586 let mut x = 0i64;
587 let mut y = radius as i64;
588 let mut d = 3 - 2 * radius as i64;
589
590 while x <= y {
591 self.set_pixel_raw((cx as i64 + x) as u64, (cy as i64 + y) as u64, &color);
593 self.set_pixel_raw((cx as i64 + x) as u64, (cy as i64 - y) as u64, &color);
594 self.set_pixel_raw((cx as i64 - x) as u64, (cy as i64 + y) as u64, &color);
595 self.set_pixel_raw((cx as i64 - x) as u64, (cy as i64 - y) as u64, &color);
596 self.set_pixel_raw((cx as i64 + y) as u64, (cy as i64 + x) as u64, &color);
597 self.set_pixel_raw((cx as i64 + y) as u64, (cy as i64 - x) as u64, &color);
598 self.set_pixel_raw((cx as i64 - y) as u64, (cy as i64 + x) as u64, &color);
599 self.set_pixel_raw((cx as i64 - y) as u64, (cy as i64 - x) as u64, &color);
600
601 if d < 0 {
602 d = d + 4 * x + 6;
603 } else {
604 d = d + 4 * (x - y) + 10;
605 y -= 1;
606 }
607 x += 1;
608 }
609 }
610
611 pub fn scroll_y(&mut self, offset: i64) {
612 let width = self.framebuffer.width();
613 let height = self.framebuffer.height();
614 let pixel_size = self.pixel_size;
615 let row_bytes = width as usize * pixel_size;
616
617 if offset == 0 {
618 return;
619 }
620
621 let abs_offset = offset.unsigned_abs();
622 if abs_offset >= height {
623 self.clear();
624 return;
625 }
626
627 let move_rows = height - abs_offset;
628 let move_bytes = move_rows as usize * row_bytes;
629
630 if offset > 0 {
631 let src_start = 0;
632 let dest_start = abs_offset as usize * row_bytes;
633 self.back_buffer
634 .copy_within(src_start..move_bytes, dest_start);
635
636 let clear_color = self.clear_color;
637 let masked_color = self.mask_color(&clear_color);
638 let pixel_bytes = masked_color.to_le_bytes();
639 let bytes_to_fill = &pixel_bytes[..pixel_size];
640
641 let mut clear_row = vec![0u8; row_bytes];
642 for x in 0..width as usize {
643 for i in 0..pixel_size {
644 clear_row[x * pixel_size + i] = bytes_to_fill[i];
645 }
646 }
647 for y in 0..abs_offset {
648 let off = y as usize * row_bytes;
649 self.back_buffer[off..off + row_bytes].copy_from_slice(&clear_row);
650 }
651 } else {
652 let src_start = abs_offset as usize * row_bytes;
653 let dest_start = 0;
654 self.back_buffer
655 .copy_within(src_start..(src_start + move_bytes), dest_start);
656
657 let clear_color = self.clear_color;
658 let masked_color = self.mask_color(&clear_color);
659 let pixel_bytes = masked_color.to_le_bytes();
660 let bytes_to_fill = &pixel_bytes[..pixel_size];
661
662 let mut clear_row = vec![0u8; row_bytes];
663 for x in 0..width as usize {
664 for i in 0..pixel_size {
665 clear_row[x * pixel_size + i] = bytes_to_fill[i];
666 }
667 }
668 for y in move_rows..height {
669 let off = y as usize * row_bytes;
670 self.back_buffer[off..off + row_bytes].copy_from_slice(&clear_row);
671 }
672 }
673 self.dirty_min_x = 0;
674 self.dirty_min_y = 0;
675 self.dirty_max_x = width;
676 self.dirty_max_y = height;
677 }
678
679 pub fn present(&mut self) {
681 let fb_width = self.framebuffer.width();
682 let fb_height = self.framebuffer.height();
683
684 let min_x = self.dirty_min_x.min(fb_width);
685 let min_y = self.dirty_min_y.min(fb_height);
686 let max_x = self.dirty_max_x.min(fb_width);
687 let max_y = self.dirty_max_y.min(fb_height);
688
689 if min_x >= max_x || min_y >= max_y {
690 return;
691 }
692
693 let width = (max_x - min_x) as usize;
694 let pitch = self.framebuffer.pitch() as usize; let pixel_size = self.pixel_size; unsafe {
698 let front_buffer_addr = self.framebuffer.addr();
699 for y in min_y..max_y {
700 let back_buffer_offset = (y * fb_width + min_x) as usize * pixel_size;
701 let front_buffer_offset = y as usize * pitch + min_x as usize * pixel_size;
702
703 let source_slice = &self.back_buffer
704 [back_buffer_offset..(back_buffer_offset + width * pixel_size)];
705
706 let dest_ptr = front_buffer_addr.add(front_buffer_offset);
707 let dest_slice = slice::from_raw_parts_mut(dest_ptr, width * pixel_size);
708
709 dest_slice.copy_from_slice(source_slice);
710 }
711 }
712
713 self.dirty_min_x = u64::MAX;
714 self.dirty_min_y = u64::MAX;
715 self.dirty_max_x = 0;
716 self.dirty_max_y = 0;
717 }
718}