7.4 GUI 图形界面
7.4 GUI 图形界面
📚 本节导读
学习时长: 约 45 分钟
难度级别: ⭐⭐⭐⭐☆
前置知识: C 语言结构体、LCD 显示原理、第 5 章设备驱动框架
🎯 学习目标
- 理解 OneOS GUI 图形设备抽象层的架构设计
- 掌握
os_graphic_t、os_graphic_info_t核心数据结构 - 掌握
os_graphic_ops硬件操作接口和os_graphic_draw_ops绘图操作接口 - 了解 RGB565 / RGB888 / ARGB8888 颜色格式及其转换
- 掌握帧缓冲(FrameBuffer)机制和双缓冲技术
- 掌握基本绘图操作(点、线、矩形、圆、文本、图像)
- 掌握字体管理系统(注册字体、切换字体、链表管理)
- 了解 GPU 硬件加速接口
一、概述
OneOS GUI 图形界面基于图形设备抽象层设计,通过 os_graphic_t 结构体将 LCD 显示控制器抽象为统一的图形设备,提供帧缓冲管理、绘制操作和 GPU 加速接口。源码位于 drivers/graphic/ 目录,核心头文件 graphic.h,核心实现文件 graphic.c。
目录结构
drivers/graphic/
├── graphic.h # 图形设备抽象层头文件(数据结构、IOCTL、API声明)
├── graphic.c # 图形设备抽象层实现(帧缓冲管理、绘图算法、IOCTL处理)
├── graphic_conf.h # 图形设备配置头文件
├── Kconfig # 菜单配置项
├── ili9341.c / ili9341.h # ILI9341 LCD 控制器驱动
├── st7789vw.c / st7789vw.h# ST7789VW LCD 控制器驱动
├── otm8009a.c / otm8009a.h# OTM8009A LCD 控制器驱动
├── ht240s030.c / ht240s030.h # HT240S030 LCD 控制器驱动
├── atk_tflcd9341.c / atk_tflcd9341.h # ATK TFLCD9341 驱动
├── dsi.c / dsi.h # DSI 接口驱动
└── font/ # 字体资源目录
├── font_asc2_1608.c # 8x16 ASCII 字体
├── font_asc2_2412.c # 12x24 ASCII 字体
└── font_asc2_3216.c # 16x32 ASCII 字体核心设计特点
- 设备抽象:将 LCD 控制器抽象为
os_graphic_t设备,继承os_device_t,统一接口 - 帧缓冲管理:支持单缓冲和双缓冲(
framebuffer[2]),通过帧切换减少画面撕裂 - 颜色格式灵活:支持 RGB565(16位)、RGB888(24位)、ARGB8888(32位)格式,编译时配置
- 丰富的绘图操作:支持点、线、矩形、圆、实心填充、图像、字符、字符串绘制
- 字体管理:支持字体注册和动态切换,字体通过链表全局管理
- GPU 加速:支持 GPU Blend、AlphaMap Blend、Blit 硬件加速操作
- LCD 控制器兼容:支持 ILI9341、ST7789VW、OTM8009A、HT240S030、ATK TFLCD9341 等常见 LCD 控制器
二、核心数据结构
2.1 os_graphic_info_t —— 图形设备信息
描述 LCD 显示器的硬件参数,包含分辨率、像素格式、帧缓冲等信息(源码 graphic.h 第128-142行):
typedef struct os_graphic_info
{
uint8_t pixel_format; /* 像素格式 */
uint8_t bits_per_pixel; /* 每像素位数 */
uint8_t bytes_per_pixel; /* 每像素字节数 */
uint16_t bytes_per_line; /* 每行字节数 */
uint16_t width; /* 屏幕宽度(像素) */
uint16_t height; /* 屏幕高度(像素) */
uint8_t *framebuffer[2]; /* 帧缓冲指针数组(支持双缓冲) */
uint8_t framebuffer_num; /* 帧缓冲数量(0/1/2) */
uint32_t framebuffer_size; /* 每个帧缓冲的大小 */
uint8_t *framebuffer_curr; /* 当前活跃帧缓冲指针 */
} os_graphic_info_t;字段说明:
| 字段 | 类型 | 说明 |
|---|---|---|
pixel_format | uint8_t | 像素格式,由编译宏 OS_GRAPHIC_LCD_PIXEL_FORMAT 决定 |
bits_per_pixel | uint8_t | 每像素位数,如 RGB565=16, RGB888=24, ARGB8888=32 |
bytes_per_pixel | uint8_t | 每像素字节数,等于 bits_per_pixel / 8 |
bytes_per_line | uint16_t | 每行字节数,等于 width * bytes_per_pixel |
width | uint16_t | 屏幕宽度(像素) |
height | uint16_t | 屏幕高度(像素) |
framebuffer[2] | uint8_t* | 帧缓冲数组,支持最多两个帧缓冲以实现双缓冲 |
framebuffer_num | uint8_t | 当前已注册的帧缓冲数量(0/1/2) |
framebuffer_size | uint32_t | 每个帧缓冲的字节大小,等于 bytes_per_line * height |
framebuffer_curr | uint8_t* | 指向当前活跃帧缓冲的指针,所有绘图操作均写入此缓冲 |
2.2 os_graphic_t —— 图形设备结构体
图形设备的核心结构体,继承 os_device_t,注册时设备类型被设为 OS_DEVICE_TYPE_GRAPHIC(源码 graphic.h 第144-151行):
typedef struct os_graphic_device
{
os_device_t parent; /* 继承自 os_device_t */
struct os_graphic_info info; /* 设备信息 */
const struct os_graphic_ops *ops; /* 硬件操作接口 */
const struct os_graphic_draw_ops *draw_ops; /* 绘图操作接口 */
} os_graphic_t;| 字段 | 类型 | 说明 |
|---|---|---|
parent | os_device_t | 继承的设备基类,设备类型 OS_DEVICE_TYPE_GRAPHIC |
info | os_graphic_info_t | 设备信息,包含分辨率、像素格式、帧缓冲等 |
ops | os_graphic_ops* | 硬件操作接口,由 LCD 驱动实现 |
draw_ops | os_graphic_draw_ops* | 绘图操作接口,由 graphic.c 框架自动填充 |
2.3 os_graphic_ops —— 硬件操作接口
由各 LCD 控制器驱动实现,向框架层提供硬件相关操作(源码 graphic.h 第176-187行):
struct os_graphic_ops
{
void (*display_on)(struct os_device *dev, os_bool_t on_off); /* 显示开关 */
void (*frame_flush)(struct os_device *dev); /* 帧缓冲刷新到屏幕 */
void (*display_area)(struct os_device *dev, os_graphic_area_t *area); /* 指定区域显示 */
#ifdef OS_GRAPHIC_GPU_ENABLE
void (*gpu_blend)(struct os_device *dev, struct os_device_gpu_info *gpu_info);
void (*gpu_alphamap_blend)(struct os_device *dev, struct os_device_gpu_info *gpu_info);
void (*gpu_blit)(struct os_device *dev, struct os_device_gpu_info *gpu_info);
void (*gpu_wait_finish)(struct os_device *dev);
#endif
};| 函数指针 | 说明 |
|---|---|
display_on | 打开/关闭显示。on_off 为 OS_TRUE 时打开,为 OS_FALSE 时关闭 |
frame_flush | 将当前帧缓冲刷新到 LCD 屏幕。刷新后自动切换帧缓冲 ID |
display_area | 将指定区域的数据直接发送到 LCD 控制器(无帧缓冲模式) |
gpu_blend | GPU 硬件混合(需 OS_GRAPHIC_GPU_ENABLE) |
gpu_alphamap_blend | GPU Alpha 贴图混合(需 OS_GRAPHIC_GPU_ENABLE) |
gpu_blit | GPU 块传输,将源数据复制到目标(需 OS_GRAPHIC_GPU_ENABLE) |
gpu_wait_finish | 等待 GPU 硬件操作完成(需 OS_GRAPHIC_GPU_ENABLE) |
2.4 os_graphic_draw_ops —— 绘图操作接口
由 graphic.c 框架层提供默认实现,在 os_graphic_register 注册设备时自动填充。各项操作均支持帧缓冲和无帧缓冲两种模式(源码 graphic.h 第240-259行):
struct os_graphic_draw_ops
{
void (*draw_point)(os_graphic_t *graphic, os_graphic_point_t *point);
void (*draw_line)(os_graphic_t *graphic, os_graphic_line_t *line);
void (*draw_rect)(os_graphic_t *graphic, os_graphic_rect_t *rect);
void (*draw_circle)(os_graphic_t *graphic, os_graphic_circle_t *circle);
void (*draw_solid_rect)(os_graphic_t *graphic, os_graphic_rect_t *rect);
void (*draw_solid_circle)(os_graphic_t *graphic, os_graphic_circle_t *circle);
void (*draw_image)(os_graphic_t *graphic, os_graphic_area_t *area);
void (*draw_char)(os_graphic_t *graphic, int32_t index);
void (*draw_string)(os_graphic_t *graphic, uint8_t *str);
void (*set_txt_cursor)(os_graphic_t *graphic, os_graphic_point_t *pos);
void (*set_txt_color)(os_graphic_t *graphic, os_color_t *color);
os_err_t (*set_font)(os_graphic_t *graphic, char *name);
os_err_t (*add_font)(os_graphic_t *graphic, os_graphic_font_t *font);
void (*clear)(os_graphic_t *graphic, os_color_t *color);
};2.5 绘图参数结构体
/* 点 */
typedef struct os_graphic_point {
int16_t x, y; /* 坐标 */
os_color_t color; /* 颜色 */
} os_graphic_point_t;
/* 线 */
typedef struct os_graphic_line {
int16_t x1, y1, x2, y2; /* 起点和终点坐标 */
os_color_t color; /* 颜色 */
} os_graphic_line_t;
/* 矩形 */
typedef struct os_graphic_rect {
int16_t x, y, w, h; /* 左上角坐标,宽度,高度 */
os_color_t color; /* 颜色 */
} os_graphic_rect_t;
/* 圆 */
typedef struct os_graphic_circle {
int16_t x, y, r; /* 圆心坐标,半径 */
os_color_t color; /* 颜色 */
} os_graphic_circle_t;
/* 区域(用于图像绘制和区域填充) */
typedef struct os_graphic_area {
uint16_t x, y, w, h; /* 左上角坐标,宽度,高度 */
os_color_t color; /* 颜色(填充模式使用) */
uint8_t *buffer; /* 图像数据缓冲区(NULL 表示纯色填充) */
} os_graphic_area_t;2.6 GPU 加速信息结构体
typedef struct os_device_gpu_info
{
char *dest; /* 目标缓冲区地址 */
void *src; /* 源数据地址 */
int32_t src_format; /* 源数据格式 */
int32_t sbpl; /* 源每行字节数 */
int32_t width; /* 宽度 */
int32_t height; /* 高度 */
int32_t alpha; /* Alpha 透明度值 */
uint32_t color; /* 颜色值 */
uint8_t yuv_sampling_mode; /* YUV 采样模式 */
} os_graphic_gpu_t;三、颜色格式
3.1 颜色类型定义
OneOS 支持三种颜色格式,通过编译时 OS_GRAPHIC_LCD_PIXEL_FORMAT 宏配置:
(1)RGB565(16位)—— 对应 OS_GRAPHIC_LCDAT_RGB565
struct os_color16
{
uint16_t b : 5; /* 蓝色:5位(低5位) */
uint16_t g : 6; /* 绿色:6位(中间6位) */
uint16_t r : 5; /* 红色:5位(高5位) */
};16位模式下,提供了便捷的颜色转换宏:
| 宏 | 说明 |
|---|---|
OS_COLOR(r, g, b) | 从 8 位 RGB 创建 16 位颜色 |
OS_COLOR_FROM16(v) | 从 16 位颜色值还原 |
OS_COLOR_FROM32(v) | 从 32 位颜色值转换为 16 位 |
OS_COLOR_TO16(c) | 将 os_color_t 转换为 16 位整数值 |
OS_COLOR_TO32(c) | 将 os_color_t 转换为 32 位整数值(含 Alpha) |
(2)RGB888(24位)—— 对应 OS_GRAPHIC_LCDAT_RGB888
struct os_color24
{
uint8_t b;
uint8_t g;
uint8_t r;
};(3)ARGB8888(32位)—— 对应 OS_GRAPHIC_LCDAT_ARGB8888
struct os_color32
{
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a; /* Alpha 透明度,0xFF 表示完全不透明 */
};3.2 统一颜色类型
通过条件编译,os_color_t 被定义为当前所选像素格式对应的颜色结构体:
#if defined(OS_GRAPHIC_LCDAT_RGB565)
typedef struct os_color16 os_color_t;
#elif defined(OS_GRAPHIC_LCDAT_RGB888)
typedef struct os_color24 os_color_t;
#elif defined(OS_GRAPHIC_LCDAT_ARGB8888)
typedef struct os_color32 os_color_t;
#endif3.3 预定义颜色宏
#define OS_COLOR_WHITE OS_COLOR(0xFF, 0xFF, 0xFF) /* 白色 */
#define OS_COLOR_SILVER OS_COLOR(0xC0, 0xC0, 0xC0) /* 银色 */
#define OS_COLOR_GRAY OS_COLOR(0x80, 0x80, 0x80) /* 灰色 */
#define OS_COLOR_BLACK OS_COLOR(0x00, 0x00, 0x00) /* 黑色 */
#define OS_COLOR_RED OS_COLOR(0xFF, 0x00, 0x00) /* 红色 */
#define OS_COLOR_YELLOW OS_COLOR(0xFF, 0xFF, 0x00) /* 黄色 */
#define OS_COLOR_GREEN OS_COLOR(0x00, 0x80, 0x00) /* 绿色 */
#define OS_COLOR_BLUE OS_COLOR(0x00, 0x00, 0xFF) /* 蓝色 */
#define OS_COLOR_PURPLE OS_COLOR(0x80, 0x00, 0x80) /* 紫色 */
#define OS_COLOR_ORANGE OS_COLOR(0xFF, 0xA5, 0x00) /* 橙色 */四、帧缓冲机制
4.1 帧缓冲初始化
注册图形设备时,os_graphic_register 函数自动初始化帧缓冲相关字段:
graphic->info.framebuffer[0] = OS_NULL;
graphic->info.framebuffer[1] = OS_NULL;
graphic->info.framebuffer_curr = OS_NULL;
graphic->info.framebuffer_num = 0;
graphic->info.framebuffer_size = graphic->info.bytes_per_line * graphic->info.height;4.2 添加帧缓冲
通过 os_graphic_add_framebuffer API 动态添加帧缓冲:
os_err_t os_graphic_add_framebuffer(struct os_device *dev, uint8_t *fb, uint32_t size);调用规则:
- 最多可添加 2 个帧缓冲(用于双缓冲)
- 每个帧缓冲大小必须等于
(width * bytes_per_pixel) * height - 添加第一个帧缓冲时,自动设为当前活跃帧缓冲
- 帧缓冲会被自动清零(
memset(fb, 0, size))
4.3 双缓冲渲染流程
- 获取下一帧缓冲:通过
OS_GRAPHIC_CTRL_FRAME_NEXT获取当前未使用的帧缓冲 - 离屏渲染:在获取到的帧缓冲上执行所有绘图操作
- 切换帧缓冲:通过
OS_GRAPHIC_CTRL_FRAME设置当前活跃帧缓冲 - 刷新显示:通过
OS_GRAPHIC_CTRL_FRAME_FLUSH将帧缓冲刷到 LCD
内部使用全局变量 g_frame_id 跟踪缓冲 ID,每次 frame_flush 后自动切换(g_frame_id = 1 - g_frame_id)。
4.4 无帧缓冲模式
当 framebuffer_num 为 0 时,框架自动降级为无帧缓冲模式,所有绘图操作直接调用 display_area 接口将像素数据发送到 LCD 控制器,适合内存受限的场景。
五、绘图操作
5.1 绘图算法实现
所有绘图操作均由 graphic.c 中的默认实现提供,注册设备时自动挂载到 draw_ops 成员:
const static struct os_graphic_draw_ops draw_ops = {
.draw_point = os_graphic_draw_point,
.draw_line = os_graphic_draw_line,
.draw_rect = os_graphic_draw_rect,
.draw_circle = os_graphic_draw_circle,
.draw_solid_rect = os_graphic_draw_solid_rect,
.draw_solid_circle = os_graphic_draw_solid_circle,
.draw_image = os_graphic_draw_image,
.draw_char = os_graphic_draw_char,
.draw_string = os_graphic_draw_string,
.set_txt_cursor = os_graphic_set_txt_cursor,
.set_txt_color = os_graphic_set_txt_color,
.set_font = os_graphic_set_font,
.add_font = os_graphic_add_font,
.clear = os_graphic_clear,
};关键算法说明:
| 绘图操作 | 算法 | 模式支持 |
|---|---|---|
draw_point | 直接写像素到帧缓冲(有帧缓冲)或通过 display_area 发送(无帧缓冲) | 双模式 |
draw_line | Bresenham 直线算法,水平线优化直接填充 | 双模式 |
draw_rect | 绘制四条边线(调用 draw_line 四次) | 双模式 |
draw_circle | 中点圆算法(Bresenham 圆),8 路对称绘制 | 双模式 |
draw_solid_rect | 逐行像素填充 | 双模式 |
draw_solid_circle | 逐水平线填充,利用圆的对称性优化 | 双模式 |
draw_image | 复制图像数据到帧缓冲 | 双模式 |
draw_char | 调用字体 get_char 获取位图,逐像素绘制 | 双模式 |
draw_string | 逐字符调用 draw_char,自动推进光标位置 | 双模式 |
clear | 调用 draw_solid_rect 填充整个屏幕 | 双模式 |
5.2 字体管理
字体结构体
typedef struct os_graphic_font
{
const char *name; /* 字体名称 */
uint8_t width; /* 字符宽度(像素) */
uint8_t height; /* 字符高度(像素) */
uint8_t bytes; /* 每字符编码字节数(1=ASCII, 2=GB2312等) */
os_list_node_t list; /* 字体链表节点 */
void (*get_char)(int32_t index, uint8_t *buf, int32_t buf_size); /* 获取字符位图回调 */
} os_graphic_font_t;字体管理机制
字体系统采用全局链表管理:
- 全局变量:
g_font_list(字体链表头)、g_font_set(当前活跃字体)、g_txt_color(文本颜色)、g_txt_cursor(光标位置) - 添加字体(
add_font):从堆中分配结构体,加入链表,若当前无活跃字体则自动设为默认 - 切换字体(
set_font):遍历链表,按名称匹配字体后设为当前活跃字体 - 字符绘制(
draw_char):调用活跃字体get_char获取字符位图,逐像素绘制
内置字体
| 字体名称 | 尺寸 | 源文件 |
|---|---|---|
| ASC2_1608 | 8x16 | font_asc2_1608.c |
| ASC2_2412 | 12x24 | font_asc2_2412.c |
| ASC2_3216 | 16x32 | font_asc2_3216.c |
六、IOCTL 控制命令
图形设备支持丰富的 IOCTL 控制命令(源码 graphic.h 第31-63行),所有命令通过 os_device_control 函数调用:
6.1 显示控制
| 命令 | 参数 | 功能 |
|---|---|---|
OS_GRAPHIC_CTRL_POWERON | 无 | 打开显示 |
OS_GRAPHIC_CTRL_POWEROFF | 无 | 关闭显示 |
OS_GRAPHIC_CTRL_GET_INFO | os_graphic_info_t* | 获取设备信息 |
OS_GRAPHIC_CTRL_DISP_AREA | os_graphic_area_t* | 显示指定区域 |
6.2 帧缓冲控制
| 命令 | 参数 | 功能 |
|---|---|---|
OS_GRAPHIC_CTRL_FRAME_NEXT | uint8_t** | 获取下一帧缓冲指针 |
OS_GRAPHIC_CTRL_FRAME | uint8_t* | 设置当前帧缓冲指针 |
OS_GRAPHIC_CTRL_FRAME_FILL | os_graphic_area_t* | 填充帧缓冲指定区域 |
OS_GRAPHIC_CTRL_FRAME_FLUSH | 无 | 刷新帧缓冲到屏幕并自动切换缓冲 ID |
6.3 绘图控制
| 命令 | 参数 | 功能 |
|---|---|---|
OS_GRAPHIC_CTRL_DRAW_POINT | os_graphic_point_t* | 绘制点 |
OS_GRAPHIC_CTRL_DRAW_LINE | os_graphic_line_t* | 绘制线 |
OS_GRAPHIC_CTRL_DRAW_RECT | os_graphic_rect_t* | 绘制矩形边框 |
OS_GRAPHIC_CTRL_DRAW_CIRCLE | os_graphic_circle_t* | 绘制圆边框 |
OS_GRAPHIC_CTRL_DRAW_SOLID_RECT | os_graphic_rect_t* | 绘制实心矩形 |
OS_GRAPHIC_CTRL_DRAW_SOLID_CIRCLE | os_graphic_circle_t* | 绘制实心圆 |
OS_GRAPHIC_CTRL_DRAW_IMAGE | os_graphic_area_t* | 绘制图像(buffer 指向图像数据) |
OS_GRAPHIC_CTRL_DRAW_CHAR | (uint32_t)index | 绘制单个字符 |
OS_GRAPHIC_CTRL_DRAW_STRING | uint8_t* | 绘制字符串 |
OS_GRAPHIC_CTRL_DRAW_TXT_CURSOR | os_graphic_point_t* | 设置文本光标位置 |
OS_GRAPHIC_CTRL_DRAW_TXT_COLOR | os_color_t* | 设置文本颜色 |
OS_GRAPHIC_CTRL_DRAW_ADD_FONT | os_graphic_font_t* | 添加字体 |
OS_GRAPHIC_CTRL_DRAW_FONT | char* | 按名称设置当前字体 |
OS_GRAPHIC_CTRL_DRAW_CLEAR | os_color_t* | 清屏(填充指定颜色) |
6.4 GPU 加速控制
| 命令 | 参数 | 功能 |
|---|---|---|
OS_GRAPHIC_CTRL_GPU_BLEND | os_device_gpu_info* | GPU 混合 |
OS_GRAPHIC_CTRL_GPU_ALPHAMAP_BLEND | os_device_gpu_info* | GPU Alpha 贴图混合 |
OS_GRAPHIC_CTRL_GPU_BLIT | os_device_gpu_info* | GPU 块传输 |
OS_GRAPHIC_CTRL_GPU_WAIT | 无 | 等待 GPU 操作完成 |
七、核心 API
/* 注册图形设备。name 为设备名称(如 "lcd0"),graphic 为已填充 ops 的设备结构体 */
os_err_t os_graphic_register(const char *name, os_graphic_t *graphic);
/* 添加帧缓冲到图形设备。fb 为帧缓冲基地址,size 为缓冲大小 */
os_err_t os_graphic_add_framebuffer(struct os_device *dev, uint8_t *fb, uint32_t size);os_graphic_register 执行的关键操作:
- 设置设备类型
OS_DEVICE_TYPE_GRAPHIC - 挂载设备操作接口
graphic_ops(包含os_graphic_control方法) - 挂载绘图操作接口
draw_ops(受OS_GRAPHIC_DRAW_ENABLE控制) - 从配置宏初始化
info字段(width、height、pixel_format、bits_per_pixel、bytes_per_pixel、bytes_per_line、framebuffer_size) - 重置帧缓冲状态(
framebuffer[0/1]置NULL,framebuffer_num置 0) - 调用
os_device_register注册设备 - 自动调用
display_on打开显示
八、支持的 LCD 控制器
| 控制器 | 源文件 | 接口类型 | 说明 |
|---|---|---|---|
| ILI9341 | ili9341.c | SPI/8080 | 320x240 TFT LCD 控制器 |
| ST7789VW | st7789vw.c | SPI | 240x240/320x240 TFT LCD 控制器 |
| OTM8009A | otm8009a.c | DSI | MIPI DSI 接口 LCD 控制器 |
| HT240S030 | ht240s030.c | SPI | 240x320 TFT LCD 控制器 |
| ATK TFLCD9341 | atk_tflcd9341.c | 8080并口 | 正点原子 TFLCD 模块 |
每个 LCD 驱动需要实现 os_graphic_ops 结构体中的 display_on、frame_flush、display_area 三个核心接口,以及可选的 GPU 加速接口。
九、完整使用示例
9.1 基本绘图操作
#include <graphic.h>
#include <device.h>
void draw_demo(void)
{
os_device_t *graphic_dev;
/* 打开图形设备 */
graphic_dev = os_device_open("lcd0");
if (graphic_dev == OS_NULL)
{
os_kprintf("Failed to open graphic device\r\n");
return;
}
/* 关闭显示(可选,用于初始化时隐藏画面) */
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_POWEROFF, OS_NULL);
/* 清屏为白色 */
os_color_t color = OS_COLOR_WHITE;
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_CLEAR, &color);
/* 绘制红色矩形边框 */
os_graphic_rect_t rect = {
.x = 10, .y = 10, .w = 100, .h = 50,
.color = OS_COLOR_RED,
};
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_RECT, &rect);
/* 绘制蓝色实心圆 */
os_graphic_circle_t circle = {
.x = 120, .y = 100, .r = 30,
.color = OS_COLOR_BLUE,
};
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_SOLID_CIRCLE, &circle);
/* 绘制绿色直线 */
os_graphic_line_t line = {
.x1 = 10, .y1 = 200, .x2 = 200, .y2 = 200,
.color = OS_COLOR_GREEN,
};
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_LINE, &line);
/* 绘制黄色实心矩形 */
os_graphic_rect_t solid_rect = {
.x = 50, .y = 220, .w = 80, .h = 40,
.color = OS_COLOR_YELLOW,
};
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_SOLID_RECT, &solid_rect);
/* 打开显示并刷新到屏幕 */
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_POWERON, OS_NULL);
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_FRAME_FLUSH, OS_NULL);
}9.2 文本显示
void draw_text(void)
{
os_device_t *graphic_dev = os_device_open("lcd0");
if (graphic_dev == OS_NULL) return;
/* 清屏白色 */
os_color_t bg_color = OS_COLOR_WHITE;
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_CLEAR, &bg_color);
/* 设置文本颜色黑色 */
os_color_t text_color = OS_COLOR_BLACK;
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_TXT_COLOR, &text_color);
/* 设置光标位置到 (10, 10) */
os_graphic_point_t cursor = { .x = 10, .y = 10 };
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_TXT_CURSOR, &cursor);
/* 绘制字符串 */
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_STRING, "Hello OneOS!");
/* 第二行文本(红色) */
os_color_t red_color = OS_COLOR_RED;
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_TXT_COLOR, &red_color);
os_graphic_point_t cursor2 = { .x = 10, .y = 40 };
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_TXT_CURSOR, &cursor2);
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_STRING, "GUI Demo v1.0");
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_FRAME_FLUSH, OS_NULL);
}9.3 双缓冲渲染
void double_buffer_demo(void)
{
os_device_t *graphic_dev = os_device_open("lcd0");
os_graphic_info_t info;
uint8_t *next_fb = OS_NULL;
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_GET_INFO, &info);
if (info.framebuffer_num >= 2)
{
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_FRAME_NEXT, &next_fb);
if (next_fb != OS_NULL)
{
/* 切换到离屏缓冲进行渲染 */
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_FRAME, next_fb);
/* 在离屏缓冲中绘制 */
os_graphic_rect_t rect = {
.x = 50, .y = 50, .w = 200, .h = 100,
.color = OS_COLOR_GREEN,
};
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_SOLID_RECT, &rect);
os_graphic_circle_t circle = {
.x = 150, .y = 150, .r = 40,
.color = OS_COLOR_BLUE,
};
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_SOLID_CIRCLE, &circle);
/* 刷新到屏幕(自动切换缓冲区) */
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_FRAME_FLUSH, OS_NULL);
}
}
else
{
os_kprintf("Double buffer not supported\r\n");
}
}9.4 图像显示
extern const uint8_t g_image_data[]; /* 外部图像数据(如 100x60 RGB565) */
void draw_image(void)
{
os_device_t *graphic_dev = os_device_open("lcd0");
if (graphic_dev == OS_NULL) return;
os_graphic_area_t area = {
.x = 50, .y = 50, .w = 100, .h = 60,
.buffer = (uint8_t *)g_image_data, /* 图像数据缓冲区 */
};
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_IMAGE, &area);
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_FRAME_FLUSH, OS_NULL);
}9.5 字体管理
void font_management_demo(void)
{
os_device_t *graphic_dev = os_device_open("lcd0");
/* 注册字体 */
extern os_graphic_font_t font_asc2_1608;
extern os_graphic_font_t font_asc2_2412;
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_ADD_FONT, &font_asc2_1608);
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_ADD_FONT, &font_asc2_2412);
/* 使用 8x16 字体 */
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_FONT, "ASC2_1608");
os_graphic_point_t cursor1 = { .x = 10, .y = 10 };
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_TXT_CURSOR, &cursor1);
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_STRING, "Small Font");
/* 切换到 12x24 字体 */
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_FONT, "ASC2_2412");
os_graphic_point_t cursor2 = { .x = 10, .y = 50 };
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_TXT_CURSOR, &cursor2);
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_DRAW_STRING, "Large Font");
os_device_control(graphic_dev, OS_GRAPHIC_CTRL_FRAME_FLUSH, OS_NULL);
}十、配置选项
| 编译宏 | 说明 |
|---|---|
OS_GRAPHIC_LCD_WIDTH | LCD 屏幕宽度(像素) |
OS_GRAPHIC_LCD_HEIGHT | LCD 屏幕高度(像素) |
OS_GRAPHIC_LCD_DEPTH | LCD 颜色深度(16/24/32) |
OS_GRAPHIC_LCD_PIXEL_FORMAT | 像素格式,决定 OS_GRAPHIC_LCDAT_xxx 宏 |
OS_GRAPHIC_DRAW_ENABLE | 启用绘图操作接口 |
OS_GRAPHIC_GPU_ENABLE | 启用 GPU 硬件加速 |
📝 本节小结
本节详细介绍了 OneOS GUI 图形设备抽象层的完整架构。主要内容包括:
- 设备抽象层:
os_graphic_t继承os_device_t,将 LCD 控制器抽象为统一的图形设备,通过os_graphic_ops(硬件操作)和os_graphic_draw_ops(绘图操作)两层接口分离硬件相关和硬件无关的职责 - 颜色格式:支持 RGB565(16位)、RGB888(24位)、ARGB8888(32位)三种格式,通过编译时宏配置选取,
os_color_t自动适配 - 帧缓冲机制:支持 0/1/2 个帧缓冲,双缓冲模式下通过
frame_flush自动切换渲染缓冲,减少画面撕裂;无帧缓冲模式下直接调用display_area驱动 LCD - 绘图操作:提供 14 种绘图操作,涵盖点/线/矩形/圆/实心填充/图像/字符/字符串/清屏,所有绘图操作均支持帧缓冲与无帧缓冲双模式
- 字体管理:全局链表管理字体,支持多字体注册和动态切换,内置 3 种尺寸 ASCII 字体(8x16/12x24/16x32)
- GPU 加速:提供 Blend、AlphaMap Blend、Blit 硬件加速接口,支持 YUV 采样模式
- IOCTL 控制:25+ 种 IOCTL 命令,覆盖显示控制、帧缓冲管理、绘图操作、GPU 加速,通过
os_device_control统一调用