/* DRM fd 只用于缓冲分配/取物理地址,不需要 SET_MASTER(避免抢 fb0 显示) */
int drm_fd = open("dev/dri/card0");
if(drm_fd < 0){
printf("打开drm设备失败\n");
}
//创建drm_mode_create_dumb向内核申请显存
struct drm_mode_create_dumb create;
memset(&create, 0, sizeof(create)); //清空物理内存
//设置要分配的内存大小,长 宽 像素密度 RGB565的bpp是16,NV12是12 alloc_h高度如果是NV12那么高度要*1.5
create.width = w; create.height = h; create.bpp = bpp;
ioctl(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create); //ioctl去分配
struct drm_rockchip_gem_phys gp;
memset(&gp, 0, sizeof(gp));
gp.handle = create.handle; //拿到分配后的句柄
ioctl(drm_fd, DRM_ROCKCHIP_GEM_GET_PHYS, &gp);
// 拿到 32 位物理地址。无 IOMMU 的 RV1106 上,这是 RGA 硬件能直访内存的唯一途径
gp.phy_addr;
struct drm_mode_map_dumb map;
memset(&map, 0, sizeof(map));
map.handle = create.handle;
ioctl(drm_fd, DRM_IOCTL_MODE_MAP_DUMB, &map);
//拿到对应的虚拟内存,用于给应用通过memcpy直接复制使用,应用不能直接拿物理内存数据
int viturlt_addr = mmap(NULL, create.size, PROT_READ | PROT_WRITE, MAP_SHARED,
g_drm_fd, map.offset);
// 3. 构造 RGA 输入/输出 buffer 分配内存
rga_buffer_t src = wrapbuffer_physicaladdr((void*)phy_addr, width, height, RK_FORMAT_YCbCr_420_SP);
rga_buffer_t dst = wrapbuffer_physicaladdr((void*)other_phy_addr, out_width, out_height, RK_FORMAT_RGB_565);
rga_dma_buf_t g_src; /* CMA 源缓冲:BGRA 屏幕帧中转 */
rga_dma_buf_t g_dst; /* CMA 目的缓冲:NV12 转换结果 */
//构造 RGA 输入/输出 buffer
rga_buf_alloc(w, h, RK_FORMAT_BGRA_8888, &g_src);
rga_buf_alloc(w, h, RK_FORMAT_YCbCr_420_SP, &g_dst);
rga_buffer_t sb = rga_wrapbuffer(&g_src, g_w, g_h, RK_FORMAT_BGRA_8888,
src_stride / 4, g_h);
rga_buffer_t db = rga_wrapbuffer(&g_dst, g_w, g_h, RK_FORMAT_YCbCr_420_SP,
NV12_STRIDE, 0);
第一段(物理地址 + memcpy) :“事必躬亲” 。直接调用 DRM 底层接口(drmModeCreateFB 之类)分配物理连续内存。需要手动记录物理地址(phy_addr)和虚拟地址(mmap 返回值),并且手动执行 memcpy 把源数据填进去。
第二段(rga_dma_buf_t) :“封装托管” 。调用了 RGA 库自带的 rga_buf_alloc()。这个函数内部帮您完成了“DRM分配 + mmap”的全套流程,并将物理地址、虚拟地址、文件描述符(fd)打包进结构体 rga_dma_buf_t。
typedef struct {
void* vir_addr; /* virtual address */
void* phy_addr; /* physical address */
int fd; /* shared fd */
int width; /* width */
int height; /* height */
int wstride; /* wstride */
int hstride; /* hstride */
int format; /* format */
int color_space_mode; /* color_space_mode */
int global_alpha; /* global_alpha, the default should be 0xff */
int rd_mode;
/* legacy */
int color; /* color, used by color fill */
im_colorkey_range colorkey_range; /* range value of color key */
im_nn_t nn;
int rop_code;
rga_buffer_handle_t handle; /* buffer handle */
} rga_buffer_t;