docs/zh-cn/device_dev_guide/graphics/Framebuffer_Driver.md

345 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Framebuffer 驱动
\[ [English](../../../en/device_dev_guide/graphics/Framebuffer_Driver.md) | 简体中文 \]
## 一、什么是 Framebuffer
Framebuffer帧缓存/显存)是一个用于存储一帧 LCD 图像数据的内存区域。在嵌入式系统中Framebuffer 通常通过内存模拟实现,其大小由 LCD 的分辨率和每个像素的字节大小决定。
### 1、Framebuffer 的大小计算
以 480x320 的屏幕为例在不同像素模式下Framebuffer 的大小如下:
1. ARGB888 (32bpp)
- 计算公式:`480 x 320 x 4 (bytes)`
- 大小614,400 字节
2. RGB565 (16bpp)
- 计算公式:`480 x 320 x 2 (bytes)`
- 大小307,200 字节
## 二、Framebuffer的显示原理
Framebuffer 的显示原理可以概括为LCD 控制器LCDC从 Framebuffer 中读取像素数据,并通过并行数据接口将数据传输到 LCD 面板进行显示。
### 1、显示流程图
以下是 Framebuffer 的显示流程:
![img](./figures/012.svg)
- Framebuffer存储像素数据。
- LCDC从 Framebuffer 中读取像素数据,并将其传输到 LCD 面板。
- LCD Panel接收数据并显示图像。
### 2、数据传输接口
LCDC 通过以下信号将数据传输到 LCD 面板:
- Clock时钟信号用于同步数据传输。
- Data像素数据包括 R、G绿、B三种颜色通道。
- Control控制信号用于管理数据传输的时序和状态。
## 三、openvela Framebuffer 接口
openvela 的 Framebuffer 接口分为上层用户接口和下层驱动接口,分别为用户和设备驱动程序提供了灵活的操作能力。以下是接口的详细说明。
### 1、上层用户接口
openvela 的 Framebuffer 用户接口类似于 Linux 系统,通过 VFS虚拟文件系统提供标准操作接口包括 `open`、`close`、`read`、`write` 和 `ioctl` 等。用户可以通过操作 `/dev/fbx` 设备文件,完成以下功能:
1. 映射 Framebuffer 到用户态:
使用 `mmap` 将 Framebuffer 映射到用户空间,便于直接对 Framebuffer 进行读写操作。
2. 切换 Framebuffer
用户可以通过 `ioctl` 接口切换不同的 Framebuffer 配置或模式。
### 2、下层驱动接口
openvela 的 Framebuffer 驱动接口用于管理 LCD 设备,设计相对简单。开发者可以参考 [video/fb.h](../../../../../../nuttx/blob/dev/include/nuttx/video/fb.h) 和 [/drivers/video/fb.c](../../../../../../nuttx/blob/dev/drivers/video/fb.c) 文件中的实现。以下是 `fb_register()` 函数的源码,展示了与 Framebuffer 设备驱动相关的重要部分:
```C
int fb_register(int display, int plane)
{
FAR struct fb_chardev_s *fb;
...
/* Initialize the frame buffer device. */
ret = up_fbinitialize(display);
if (ret < 0)
{
gerr("ERROR: up_fbinitialize() failed for display %d: %d\n",
display, ret);
goto errout_with_fb;
}
DEBUGASSERT((unsigned)plane <= UINT8_MAX);
fb->plane = plane;
fb->vtable = up_fbgetvplane(display, plane);
if (fb->vtable == NULL)
{
gerr("ERROR: up_fbgetvplane() failed, vplane=%d\n", plane);
goto errout_with_fb;
}
/* Initialize the frame buffer instance. */
...
ret = register_driver(devname, &fb_fops, 0666, (FAR void *)fb);
if (ret < 0)
{
gerr("ERROR: register_driver() failed: %d\n", ret);
goto errout_with_fb;
}
return OK;
errout_with_fb:
kmm_free(fb);
return ret;
}
```
从代码中可以看出Framebuffer 针对 LCD 设备驱动程序提供了以下 3 个接口,驱动程序需要自行实现:
1. `void up_fbinitialize(int display)`
- 用于初始化硬件 LCD 控制器。
- 例如,在 STM32 平台上,`up_fbinitialize` 函数需要初始化 LTDCLCD-TFT 控制器)或 MIPI 接口,并完成 DSI 外设和 LCD IC 的初始化。
2. `FAR struct fb_vtable_s *up_fbgetvplane(int display, int vplane)`
- 获取 LCD 的 `fb_vtable_s` 结构体信息。
- `fb_vtable_s` 是 Framebuffer 的核心结构,包含了 Framebuffer 的所有接口。通过实现该函数LCD 控制器可以将自身信息注册到 Framebuffer 框架中。
- 驱动程序可以参考以下示例实现:
- `drivers/video/vnc/vnc_fbdev.c`
- `boards/arm/stm32f7/stm32f746g-disco/stm32_lcd.c`
3. `void up_fbuninitialize(int display)`
- 执行与 `up_fbinitialize` 相反的操作,用于释放资源。通常可以实现为空,不执行任何操作。
### 3、`struct fb_vtable_s` 结构
`fb_vtable_s` 是 Framebuffer 的核心结构,定义了与视频硬件交互的接口。以下是其主要功能模块:
1. 核心功能。
- `getvideoinfo`:获取视频控制器配置和颜色平面信息。
- `getplaneinfo`:获取指定颜色平面的信息。
2. 可选功能(根据配置启用)。
- 颜色映射(`CONFIG_FB_CMAP`
- `getcmap`:获取当前颜色映射表。
- `putcmap`:更新颜色映射表。
- 硬件光标(`CONFIG_FB_HWCURSOR`
- `getcursor`:获取光标属性。
- `setcursor`:设置光标配置。
- 显示更新(`CONFIG_FB_UPDATE`
- `updatearea`:通知硬件更新指定显示区域。
- 垂直同步(`CONFIG_FB_SYNC`
- `waitforvsync`:等待垂直同步信号,避免屏幕撕裂。
- 叠加管理(`CONFIG_FB_OVERLAY`
- `getoverlayinfo`:获取叠加层的配置信息。
- `settransp`:设置叠加层的透明度。
- `setchromakey`:设置叠加层的色键。
- `setcolor`:用指定颜色填充叠加层。
- `setblank`:启用或禁用叠加层。
- `setarea`:设置叠加操作的活动区域。
- 叠加层的 Blit 和 Blend 操作(`CONFIG_FB_OVERLAY_BLIT`
- `blit`:在叠加层之间执行 Blit 操作。
- `blend`:在叠加层之间执行 Blend 操作。
3. 其他控制功能。
- 显示平移:
- `pandisplay`:为多缓冲区显示执行平移操作。
- 帧率控制:
- `setframerate`:设置 Framebuffer 的刷新率。
- `getframerate`:获取当前刷新率。
- 电源管理:
- `getpower`:获取面板的电源状态。
- `setpower`:启用或禁用面板电源。
#### 示例代码
以下是 `struct fb_vtable_s` 的部分定义示例:
```C
struct fb_vtable_s
{
/* Get information about the video controller configuration and the
* configuration of each color plane.
*/
int (*getvideoinfo)(FAR struct fb_vtable_s *vtable,
FAR struct fb_videoinfo_s *vinfo);
int (*getplaneinfo)(FAR struct fb_vtable_s *vtable, int planeno,
FAR struct fb_planeinfo_s *pinfo);
#ifdef CONFIG_FB_CMAP
/* The following are provided only if the video hardware supports RGB
* color mapping
*/
int (*getcmap)(FAR struct fb_vtable_s *vtable,
FAR struct fb_cmap_s *cmap);
int (*putcmap)(FAR struct fb_vtable_s *vtable,
FAR const struct fb_cmap_s *cmap);
#endif
#ifdef CONFIG_FB_HWCURSOR
/* The following are provided only if the video hardware supports a
* hardware cursor.
*/
int (*getcursor)(FAR struct fb_vtable_s *vtable,
FAR struct fb_cursorattrib_s *attrib);
int (*setcursor)(FAR struct fb_vtable_s *vtable,
FAR struct fb_setcursor_s *settings);
#endif
#ifdef CONFIG_FB_UPDATE
/* The following are provided only if the video hardware need extera
* notification to update display content.
*/
int (*updatearea)(FAR struct fb_vtable_s *vtable,
FAR const struct fb_area_s *area);
#endif
#ifdef CONFIG_FB_SYNC
/* The following are provided only if the video hardware signals
* vertical sync.
*/
int (*waitforvsync)(FAR struct fb_vtable_s *vtable);
#endif
#ifdef CONFIG_FB_OVERLAY
/* Get information about the video controller configuration and the
* configuration of each overlay.
*/
int (*getoverlayinfo)(FAR struct fb_vtable_s *vtable, int overlayno,
FAR struct fb_overlayinfo_s *oinfo);
/* The following are provided only if the video hardware supports
* transparency
*/
int (*settransp)(FAR struct fb_vtable_s *vtable,
FAR const struct fb_overlayinfo_s *oinfo);
/* The following are provided only if the video hardware supports
* chromakey
*/
int (*setchromakey)(FAR struct fb_vtable_s *vtable,
FAR const struct fb_overlayinfo_s *oinfo);
/* The following are provided only if the video hardware supports
* filling the overlay with a color.
*/
int (*setcolor)(FAR struct fb_vtable_s *vtable,
FAR const struct fb_overlayinfo_s *oinfo);
/* The following allows to switch the overlay on or off */
int (*setblank)(FAR struct fb_vtable_s *vtable,
FAR const struct fb_overlayinfo_s *oinfo);
/* The following allows to set the active area for subsequently overlay
* operations.
*/
int (*setarea)(FAR struct fb_vtable_s *vtable,
FAR const struct fb_overlayinfo_s *oinfo);
#ifdef CONFIG_FB_OVERLAY_BLIT
/* The following are provided only if the video hardware supports
* blit operation between overlays.
*/
int (*blit)(FAR struct fb_vtable_s *vtable,
FAR const struct fb_overlayblit_s *blit);
/* The following are provided only if the video hardware supports
* blend operation between overlays.
*/
int (*blend)(FAR struct fb_vtable_s *vtable,
FAR const struct fb_overlayblend_s *blend);
#endif
/* Pan display for multiple buffers. */
int (*pandisplay)(FAR struct fb_vtable_s *vtable,
FAR struct fb_planeinfo_s *pinfo);
/* Specific Controls ******************************************************/
/* Set the frequency of the Framebuffer update panel (0: disable refresh) */
int (*setframerate)(FAR struct fb_vtable_s *vtable, int rate);
/* Get the frequency of the Framebuffer update panel (0: disable refresh) */
int (*getframerate)(FAR struct fb_vtable_s *vtable);
/* Get the panel power status (0: full off). */
int (*getpower)(FAR struct fb_vtable_s *vtable);
/* Enable/disable panel power (0: full off). */
int (*setpower)(FAR struct fb_vtable_s *vtable, int power);
};
```
开发者可以根据具体硬件需求实现这些接口,以满足 Framebuffer 的功能需求。
## 四、启用 Framebuffer
启用 Framebuffer 需要完成以下步骤:
### 1、开启 Framebuffer 编译选项
在配置文件中启用以下选项:
```makefile
CONFIG_VIDEO_FB
```
### 2、注册 Framebuffer
在系统启动的初始化阶段,调用 `fb_register` 函数注册 Framebuffer。以下是示例代码
```C
#include <nuttx/video/fb.h>
#ifdef CONFIG_VIDEO_FB
ret = fb_register(0, 0);
if (ret < 0)
{
syslog(LOG_ERR, "ERROR fb_register() failed: %d\n", ret);
}
#endif
```
### 3、处理 VSync
为了避免屏幕撕裂并提高渲染性能,建议在实现中处理 VSync垂直同步。VSync 的具体实现和优化方法,请参考 [VSync](./VSync.md)。
## 五、相关仓
以下是与 Framebuffer 驱动相关的代码仓库链接:
- [fb.c](../../../../../../nuttx/blob/dev/drivers/video/fb.c)Framebuffer 驱动的实现文件。
- [fb.h](../../../../../../nuttx/blob/dev/include/nuttx/video/fb.h)Framebuffer 驱动的接口定义。