Skip to content

Commit d4b6872

Browse files
authored
Merge pull request #1713 from Ronin-1124/main
docs: add rga and g2d usage guide docs
2 parents c9e270e + ae7b10b commit d4b6872

14 files changed

Lines changed: 1448 additions & 0 deletions

File tree

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
## 概述
2+
3+
G2D 是 Allwinner SoC 集成的 2D 图形硬件加速器,负责图像旋转、缩放、格式转换、颜色填充等操作。
4+
5+
典型应用场景:
6+
7+
- 视频编解码前后的图像预处理(缩放、色彩空间转换)
8+
- 相机实时预览的图像处理
9+
- 显示输出前的格式转换(RGB ↔ YUV)
10+
- 批量图像处理流水线
11+
12+
**本项目环境:**
13+
14+
| 项目 ||
15+
| ------------ | ---------------------------------- |
16+
| SoC | Allwinner A733 |
17+
| Linux | 5.15.147-100-a733 |
18+
| G2D 驱动版本 | 1.0.0 |
19+
| 驱动模块 | `g2d_sunxi` |
20+
| 设备节点 | `/dev/g2d``/dev/dma_heap/system` |
21+
22+
## 环境准备
23+
24+
### 验证驱动状态
25+
26+
<NewCodeBlock tip="Device" type="device">
27+
28+
```bash
29+
# 检查驱动模块是否已加载
30+
lsmod | grep g2d
31+
# 输出类似: g2d_sunxi 90112 0
32+
33+
# 查看驱动版本
34+
cat /sys/module/g2d_sunxi/version
35+
# 输出: 1.0.0
36+
```
37+
38+
</NewCodeBlock>
39+
40+
若未加载,手动加载:
41+
42+
<NewCodeBlock tip="Device" type="device">
43+
44+
```bash
45+
sudo modprobe g2d_sunxi
46+
```
47+
48+
</NewCodeBlock>
49+
50+
### 设备节点权限
51+
52+
当前系统已配置为无需 root 运行:
53+
54+
```text
55+
/dev/g2d (0666)
56+
/dev/dma_heap/system (0666)
57+
```
58+
59+
如需重新配置 udev 规则:
60+
61+
<NewCodeBlock tip="Device" type="device">
62+
63+
```bash
64+
sudo sh -c 'echo "KERNEL==\"system\", SUBSYSTEM==\"dma_heap\", MODE=\"0666\"" > /etc/udev/rules.d/99-dma-heap.rules'
65+
sudo udevadm control --reload-rules
66+
sudo udevadm trigger
67+
```
68+
69+
</NewCodeBlock>
70+
71+
### 头文件
72+
73+
G2D API 头文件位于:
74+
75+
```text
76+
/usr/include/bsp/linux/sunxi-g2d.h
77+
```
78+
79+
## 快速启动
80+
81+
### 核心概念
82+
83+
使用 G2D 的标准流程:
84+
85+
```text
86+
1. 分配 DMA buffer(图像数据缓冲区)
87+
2. 填充源图像数据
88+
3. 配置 g2d_blit_h 结构体
89+
4. 调用 ioctl(G2D_CMD_BITBLT_H, ...)
90+
5. 从目标 DMA buffer 读取结果
91+
6. 释放资源
92+
```
93+
94+
**关键:G2D 操作的是 DMA buffer,不是普通内存。**
95+
96+
DMA buffer 由 `/dev/dma_heap/system` 分配,物理地址连续,硬件可直接访问。
97+
98+
### 示例(旋转 90°)
99+
100+
<NewCodeBlock tip="Device" type="device">
101+
102+
```c
103+
#include <stdio.h>
104+
#include <stdlib.h>
105+
#include <fcntl.h>
106+
#include <unistd.h>
107+
#include <sys/ioctl.h>
108+
#include <bsp/linux/sunxi-g2d.h>
109+
#include <linux/dma-heap.h>
110+
#include <sys/mman.h>
111+
112+
#define W 1920
113+
#define H 1080
114+
115+
// 分配 DMA buffer,返回 fd 和虚拟地址
116+
static int alloc_dmabuf(int *fd, void **vaddr, size_t size)
117+
{
118+
struct dma_heap_allocation_data alloc_data = {
119+
.len = size, .fd_flags = O_RDWR | O_CLOEXEC, .heap_flags = 0,
120+
};
121+
int heap_fd = open("/dev/dma_heap/system", O_RDONLY);
122+
if (heap_fd < 0) return -1;
123+
if (ioctl(heap_fd, DMA_HEAP_IOCTL_ALLOC, &alloc_data) < 0) {
124+
close(heap_fd); return -1;
125+
}
126+
close(heap_fd);
127+
*fd = alloc_data.fd;
128+
*vaddr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0);
129+
if (*vaddr == MAP_FAILED) { close(*fd); return -1; }
130+
return 0;
131+
}
132+
133+
int main(void)
134+
{
135+
int g2d_fd, src_fd, dst_fd;
136+
void *src_v, *dst_v;
137+
g2d_blt_h blit;
138+
139+
// 1. 分配两个 DMA buffer(源和目标)
140+
alloc_dmabuf(&src_fd, &src_v, W * H * 4);
141+
alloc_dmabuf(&dst_fd, &dst_v, W * H * 4);
142+
143+
// 2. 填充源图像数据(渐变示例)
144+
fill_pattern(src_v, W, H);
145+
146+
// 3. 打开 G2D 设备
147+
g2d_fd = open("/dev/g2d", O_RDWR);
148+
149+
// 4. 配置操作参数
150+
memset(&blit, 0, sizeof(blit));
151+
blit.flag_h = G2D_ROT_90; // 旋转 90°
152+
153+
blit.src_image_h.fd = src_fd;
154+
blit.src_image_h.format = G2D_FORMAT_ARGB8888;
155+
blit.src_image_h.width = W;
156+
blit.src_image_h.height = H;
157+
158+
blit.dst_image_h.fd = dst_fd;
159+
blit.dst_image_h.format = G2D_FORMAT_ARGB8888;
160+
blit.dst_image_h.width = H; // 旋转后宽高互换
161+
blit.dst_image_h.height = W;
162+
163+
// 5. 执行硬件加速操作
164+
ioctl(g2d_fd, G2D_CMD_BITBLT_H, (unsigned long)(&blit));
165+
166+
// 6. 结果已在 dst_v 中,验证或提交给后续流程
167+
168+
// 7. 释放资源
169+
close(g2d_fd);
170+
munmap(src_v, W * H * 4); close(src_fd);
171+
munmap(dst_v, W * H * 4); close(dst_fd);
172+
return 0;
173+
}
174+
```
175+
176+
</NewCodeBlock>
177+
178+
编译
179+
180+
<NewCodeBlock tip="Device" type="device">
181+
182+
```bash
183+
sudo apt install gcc g++ cmake
184+
gcc -o g2d_rotation g2d_rotation.c
185+
```
186+
187+
</NewCodeBlock>
188+
189+
## 示例运行结果
190+
191+
| 示例 | 操作 | 结果 |
192+
| ----------------- | --------------------------- | -------------------------- |
193+
| `g2d_rotation` | ARGB8888 1920×1080 旋转 90° | **8.24 ms**,251.8 MP/sec |
194+
| `g2d_format_conv` | ARGB8888 → YUV420 1920×1080 | **9.56 ms**,216.8 MP/sec |
195+
| `g2d_scaler` | 4096×4096 → 1920×1080 缩放 | **68.60 ms**,244.6 MP/sec |
196+
| `g2d_color_fill` | 1920×1080 纯色填充 | **8.53 ms**,243.2 MP/sec |
197+
198+
注:`g2d_scaler` 源图分辨率上限为 4096×4096(8192×8192 会触发 `EPERM`)。
199+
200+
## API 参考
201+
202+
完整 API 定义和所有支持格式见头文件:
203+
204+
```text
205+
/usr/include/bsp/linux/sunxi-g2d.h
206+
```
207+
208+
常用 ioctl 命令:
209+
210+
| 命令 | 用途 |
211+
| -------------------- | ------------------------------------ |
212+
| `G2D_CMD_BITBLT_H` | 单图像位块传输(旋转/缩放/格式转换) |
213+
| `G2D_CMD_FILLRECT_H` | 颜色填充矩形 |
214+
| `G2D_CMD_STRETCHBLT` | 伸缩位块传输 |
215+
| `G2D_CMD_BLD_H` | Porter-Duff 混合操作 |
216+
| `G2D_CMD_MIXER_TASK` | 批量任务(一次提交多个操作) |
217+
218+
支持格式(部分):
219+
220+
| 格式 | 说明 |
221+
| ------------------------------- | --------------- |
222+
| `G2D_FORMAT_ARGB8888` | 32bpp Alpha-RGB |
223+
| `G2D_FORMAT_RGB888` | 24bpp RGB |
224+
| `G2D_FORMAT_RGB565` | 16bpp |
225+
| `G2D_FORMAT_YUV420UVC_U1V1U0V0` | NV12 标准格式 |
226+
227+
旋转标志:`G2D_ROT_0` / `G2D_ROT_90` / `G2D_ROT_180` / `G2D_ROT_270` / `G2D_ROT_H`(水平翻转)/ `G2D_ROT_V`(垂直翻转)
228+
229+
## 注意事项
230+
231+
- **DMA buffer 必须物理连续**,普通 `malloc` 不能用于 G2D
232+
- **IOMMU 负责地址翻译**,G2D 访问的是 IOMMU 映射后的物理地址,无需关心具体地址值
233+
- **DMA buffer 通过 fd 传递**,用户空间用 `mmap` 后的虚拟地址读写
234+
- **目标分辨率应与源配合**,旋转 90° 时宽高互换
235+
- **格式转换**(如 RGB → YUV)由 G2D 硬件完成,源和目标 format 字段分别设置即可
236+
- **调试时**,失败返回 `-1``errno` 记录具体原因,用 `perror()` 打印

0 commit comments

Comments
 (0)