You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否通过dma_buf指针创建可附加到帧缓冲的OpenGL ES纹理?

在OpenGL ES中使用DMA-BUF创建帧缓冲纹理的可行性

常规帧缓冲纹理创建流程

在OpenGL ES中,我们通常按以下方式为帧缓冲创建纹理并附加:

unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);  

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

// 附加到帧缓冲
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);  

你的问题:直接用DMA-BUF虚拟地址传入glTexImage2D可行吗?

你尝试直接将DMA-BUF的虚拟地址vaddr传入glTexImage2D创建纹理,代码如下:

shm_handle_t handle = dma_buf_malloc(size);
void* vaddr = dma_get_address(handle);

unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);

// 用vaddr替代NULL
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, vaddr);

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);  

这种做法不可行,原因如下:

  • OpenGL ES标准APIglTexImage2D不支持直接接收DMA-BUF的虚拟地址作为像素数据指针。DMA-BUF是Linux内核级内存共享机制,用户空间虚拟地址未经过GPU驱动的映射与权限处理,GPU无法直接访问。
  • 直接传入vaddr会导致GPU无法正确读取内存,大概率出现渲染错误、程序崩溃或纹理内容异常。

正确实现方式:通过EGL扩展导入DMA-BUF

要在OpenGL ES中使用DMA-BUF作为帧缓冲纹理,需借助EGL相关扩展(如EGL_EXT_image_dma_buf_import或EGL_KHR_image_base),步骤如下:

  1. 获取DMA-BUF的文件描述符、尺寸、像素格式等核心信息;
  2. 调用EGL扩展函数创建EGLImageKHR对象,关联到目标DMA-BUF;
  3. 创建OpenGL ES纹理,将EGLImageKHR绑定到该纹理;
  4. 将纹理附加到帧缓冲。

示例代码框架:

// 假设已获取DMA-BUF的fd、宽高、格式等参数
int dma_fd = ...; // DMA-BUF的文件描述符
EGLDisplay display = eglGetCurrentDisplay();

// 配置EGLImage属性
EGLint attrs[] = {
    EGL_WIDTH, 800,
    EGL_HEIGHT, 600,
    EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_RGB888, // 匹配DMA-BUF的像素格式
    EGL_DMA_BUF_PLANE0_FD_EXT, dma_fd,
    EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
    EGL_DMA_BUF_PLANE0_PITCH_EXT, 800 * 3, // 根据格式计算行间距
    EGL_NONE
};

// 创建EGLImage
EGLImageKHR egl_image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attrs);

// 创建并绑定纹理
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);

// 将EGLImage关联到纹理
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_image);

// 设置纹理参数
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

// 附加到帧缓冲
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_EXTERNAL_OES, texture, 0);

注意事项:

  • 需确认平台支持目标EGL扩展,可通过eglQueryString查询扩展列表;
  • DRM像素格式需与DMA-BUF实际格式严格匹配;
  • 使用完毕后需销毁EGLImageKHR和纹理,避免内存泄漏。

内容的提问来源于stack exchange,提问作者balamenggan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 00:40:03