能否通过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标准API
glTexImage2D不支持直接接收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),步骤如下:
- 获取DMA-BUF的文件描述符、尺寸、像素格式等核心信息;
- 调用EGL扩展函数创建
EGLImageKHR对象,关联到目标DMA-BUF; - 创建OpenGL ES纹理,将
EGLImageKHR绑定到该纹理; - 将纹理附加到帧缓冲。
示例代码框架:
// 假设已获取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
相关产品推荐
相关产品推荐

