1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#![no_std]

extern crate alloc;

use alloc::string::String;
use alloc::{vec, vec::Vec};

use embedded_graphics_core::{
    draw_target::DrawTarget,
    geometry::{OriginDimensions, Size},
    pixelcolor::Rgb888,
    pixelcolor::RgbColor,
    Pixel,
};
use uefi::proto::console::gop::{BltOp, BltPixel, BltRegion, GraphicsOutput};

#[derive(Debug)]
pub enum UefiDisplayError {
    PixelRangeError(String),
    DisplayError(String),
}

pub struct UefiDisplay {
    /// 宽
    width: usize,
    // 长
    height: usize,
    // pixels
    pixels: Vec<BltPixel>,
}

impl UefiDisplay {
    pub fn new((width, height): (usize, usize)) -> Self {
        Self {
            width,
            height,
            pixels: vec![BltPixel::new(0, 0, 0); width * height],
        }
    }

    fn pixel(&mut self, x: usize, y: usize) -> Option<&mut BltPixel> {
        self.pixels.get_mut(y * self.width + x)
    }

    pub fn flush(&self, gop: &mut GraphicsOutput) -> Result<(), UefiDisplayError> {
        match gop.blt(BltOp::BufferToVideo {
            buffer: &self.pixels,
            src: BltRegion::Full,
            dest: (0, 0),
            dims: (self.width, self.height),
        }) {
            Ok(_) => Ok(()),
            Err(_) => Err(UefiDisplayError::DisplayError("draw pixel error".into())),
        }
    }
}

impl OriginDimensions for UefiDisplay {
    fn size(&self) -> Size {
        Size {
            width: self.width as u32,
            height: self.height as u32,
        }
    }
}

impl DrawTarget for UefiDisplay {
    type Color = Rgb888;
    type Error = UefiDisplayError;

    fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
    where
        I: IntoIterator<Item = Pixel<Self::Color>>,
    {
        for Pixel(point, color) in pixels {
            // 像素坐标
            let (x, y) = (point.x, point.y);
            // 坐标转换为pixels的索引
            if let Some(pixel) = self.pixel(x as usize, y as usize) {
                // 写入颜色
                pixel.red = color.r();
                pixel.green = color.g();
                pixel.blue = color.b();
            }
        }

        Ok(())
    }
}