如何通过UEFI图形输出协议GOP在屏幕上高效显示高分辨率图像?

摘要:上一节中我们介绍了如何在 UEFI 应用程序中调用特定的 Protocol。本节的任务是利用 UEFI 中的图形输出协议 Gop 在屏幕上输出一个特定图形。下面是我们本次的工程目录。 MyPkg ├── Application │ └──
上一节中我们介绍了如何在 UEFI 应用程序中调用特定的 Protocol。本节的任务是利用 UEFI 中的图形输出协议 Gop 在屏幕上输出一个特定图形。下面是我们本次的工程目录。 MyPkg ├── Application │ └── GopDrawApp │ ├── GopDrawApp.c │ └── GopDrawApp.inf ├── MyPkg.dec └── MyPkg.dsc 什么是图形输出协议(GOP) GOP(Graphics Output Protocol,图形输出协议) 是 UEFI 规范中的一个核心接口,用来在操作系统启动前接管显卡并显示图形界面。接下来我们分两部分来介绍,首先用最简单的语言来说明 GOP 控制显示的原理,然后分析一下 UEFI 中 GOP 的源码定义。 我们在屏幕上看到的一幅完整图片是由有限的特定像素点组成的,比如常见的 1920*1080 分辨率。每个像素点通过红绿蓝三原色的不同强弱组合便能够显示特定的色彩。显存中有一块专门用于存储当前画面像素颜色信息的区域,称为 FrameBuffer(帧缓冲区)。屏幕显示控制器会不断从 FrameBuffer 中读取数据,并将其转换为屏幕上的图像。GOP 的作用就是为操作系统启动前的软件(如 BootLoader、UEFI 应用)提供访问 FrameBuffer 的标准接口。通过 GOP,我们可以获取 FrameBuffer 的地址、分辨率、像素格式,并直接向其中写入数据,从而在屏幕上显示想要的图像。 以下是 GOP 在 UEFI 中的 Protocol 定义。 struct _EFI_GRAPHICS_OUTPUT_PROTOCOL { EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE QueryMode; EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE SetMode; EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT Blt; EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode; }; QueryMode — 查询模式。用于枚举显卡所支持的所有显示模式。在设置分辨率之前,你需要先调用它来查询有哪些模式可用。你需要传入一个 ModeNumber(从 0 开始),它会返回该模式对应的具体信息(分辨率、刷新率等)。 SetMode — 设置模式。将显示设备切换到你指定的某个模式。调用成功后,帧缓冲区的分辨率、像素格式等会随之改变。你需要传入一个 ModeNumber,这个编号必须是通过 QueryMode 查询得到的有效编号。 Blt — 像素块传输。这是一个高效的图形绘制函数。它可以在帧缓冲区内部、或是在帧缓冲区和内存缓冲区之间,复制、填充或转换矩形像素块。 Mode — 当前模式信息。这是一个只读的状态信息。它包含了当前显示模式的具体参数,方便你随时查询。 MaxMode:QueryMode 支持的最大模式数量。 Mode:当前激活的模式编号。 Info:指向 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION 的指针,包含当前模式的详细信息(分辨率、像素格式等)。 SizeOfInfo:上述 Info 结构体的大小。 FrameBufferBase:帧缓冲区的基地址(显存中的物理地址)。你向屏幕写入数据,就是向这个地址开始的内存写入。 FrameBufferSize:帧缓冲区的大小(字节)。 一个典型的 GOP 使用流程如下: 枚举:调用 Gop->QueryMode() 获取所有支持的分辨率。 设置:调用 Gop->SetMode() 切换到你需要的分辨率(比如 1920x1080)。 获取信息:访问 Gop->Mode->FrameBufferBase 和 Gop->Mode->Info->PixelFormat,知道往哪里写数据,以及以什么格式写。 绘制:向 FrameBufferBase 写入像素数据,或调用 Gop->Blt() 来高效绘制图形。 源码示例 此代码大致逻辑如下: 首先需要获取 GOP 的 Protocol 指针。随后即可使用 GOP 的功能。使用Gop->Mode->MaxMode获取显卡支持的显示格式数量,然后调用 Gop->QueryMode()枚举这些格式信息。调用Gop->SetMode()设置其中一个格式。
阅读全文