系统之家提供 Windows 系统、Ghost 系统、驱动与常用软件的安全下载及安装教程。 后台管理
📢 欢迎访问系统之家!所有资源均经过安全检测。

谈一谈Android上的SurfaceTextureSurfaceTexture 是Android上做渲染的核心组件,它

发布时间:2026-09-28 | 浏览:1
📥 下载地址(文章开头)
装机神器,可安装一切系统,纯净版,英文版,繁体版 ,精简版,原版等等等
导言:这篇文章介绍了SurfaceTexture的用法以及原理,对于常见用法不做过多描述,而重点介绍了内部实现以及EGLImage,包括实现共享纹理的两种方式。 1 什么是SurfaceTexture 2 SurfaceTexture的常见应用 - 相机与视频解码 3 SurfaceTexture的内部实现 - EGLImageKHR 3.1 SurfaceTexture是如何创建的 3.2 updateTexImage是如何将数据更新到纹理的 3.1 SurfaceTexture是如何创建的 3.2 updateTexImage是如何将数据更新到纹理的 4 EGLImageKHR 4.1 使用权限问题 4.2 EGLImageKHR的重要性质 4.2 EGLImageKHR的重要性质 5 共享纹理的两种实现 5.1 ShareContext 5.2 EGLImageKHR 5.1 ShareContext 5.2 EGLImageKHR 1 什么是SurfaceTexture SurfaceTexture 是Android上做渲染的核心组件,它是 Surface 和 OpenGL ES纹理的组合,用于提供输出到 GLES 纹理的 Surface。从安卓渲染系统上来说, SurfaceTexture 是一个BufferQueue的消费者,当生产方将新的缓冲区排入队列时, onFrameAvailable() 回调会通知应用。然后,应用调用 updateTexImage() ,这会释放先前占有的缓冲区,从队列中获取新缓冲区并执行 EGL 调用,从而使 GLES 可将此缓冲区作为外部纹理使用。 通过Camera、Video Decoder、OpenGL生成图像流。 图像流通过Surface入队到BufferQueue,并通知到GLConsumer。 GLConsumer从BufferQueue获取图像流GraphicBuffer,并转换为EXTERNAL OES纹理。 得到OES纹理后,用户方就可以将其转换成普通的纹理,然后应用特效或者上屏。 2 SurfaceTexture的常见应用 - 相机与视频解码 SurfaceTexture的最常见应用场景是作为相机或者视频解码器的输出,这种应用场景非常常见,这里就不做详细描述了,以相机为例: 3 SurfaceTexture的内部实现 - EGLImageKHR SurfaceTexture使用时,最主要的两个方法: SurfaceTexture (int texName) // 创建SurfaceTexture void updateTexImage () // 将当前图片流更新到纹理 3.1 SurfaceTexture是如何创建的 首先需要自己创建一个纹理ID,传递给SurfaceTexture,比如 Framework层的SurfaceTexture创建代码如下 framework层会调用到 nativeInit 方法,最终调用到 SurfaceTexture_init 方法。 SurfaceTexture初始化后,向 GLConsumer 设置了 JNISurfaceTextureContext 监听器,该监听器会回调到Java层 SurfaceTexture.postEventFromNative 方法,进一步回调到注册到SurfaceTexture中的OnFrameAvailableListener监听器,用于通知业务层有新的 GraphicBuffer 入队了。这时候业务层就可以调用 updateTexImage 将GraphicBuffer更新到纹理。 3.2 updateTexImage是如何将数据更新到纹理的 按文档所说, OnFrameAvailableListener.onFrameAvailable 回调可以发生在任意线程,所以不能在回调中直接调用 updateTexImage ,而是必须切换到OpenGL线程调用 updateTexImage ,那么内部是怎么实现的呢? 应用层的 updateTexImage 会最终调用到native层的 GLConsumer::updateTexImage() 方法。 可以看到获取帧数据是 acquireBufferLocked 方法。
📥 下载地址(文章中间)
装机神器,可安装一切系统,纯净版,英文版,繁体版 ,精简版,原版等等等
可以看到,SurfaceTexture最终会把GraphicBuffer创建一个EglImage对象,这个对象就保存了帧数据。 那么接下来的 bindTextureImageLocked 是如何将帧数据绑定到纹理上的呢? 再看下 createIfNeeded 方法,它会最终调用到 GLConsumer::EglImage::createImage 关键语句是 eglCreateImageKHR ,可以看到,这里创建了EGLImageKHR 对象。 现在已经生成了EGLImageKHR图像,接下来分析下 EGLImageKHR 图像是如何绑定的 GL_TEXTURE_EXTERNAL_OES 纹理的。 小结一下,整个 updateTexImage 方法大致分为这几步: 生成纹理内容EGLImageKHR 对象,通过 ConsumerBase::acquireBufferLocked 获取当前的显示内容 GraphicBuffer (比如相机帧数据),然后由此 GraphicBuffer 生成一个 EGLImageKHR 图像。 生成纹理内容EGLImageKHR 对象,通过 ConsumerBase::acquireBufferLocked 获取当前的显示内容 GraphicBuffer (比如相机帧数据),然后由此 GraphicBuffer 生成一个 EGLImageKHR 图像。 将 EGLImageKHR 图像通过 glEGLImageTargetTexture2DOES 绑定到 GL_TEXTURE_EXTERNAL_OES 型纹理上。 将 EGLImageKHR 图像通过 glEGLImageTargetTexture2DOES 绑定到 GL_TEXTURE_EXTERNAL_OES 型纹理上。 通过上面分析可以看到,SurfaceTexture的内部,主要是通过EGLImageKHR实现的,那么EGLImageKHR有什么作用呢? EGLImageKHR 是EGL定义的一种专门用于共享2D图像数据的扩展格式,它可以在EGL的各种client api之间共享数据(如OpenGL,OpenVG),它的本意是共享2D图像数据,但是并没有明确限定共享数据的格式以及共享的目的。 EGLImageKHR的创建函数原型是: 在Android系统中专门定义了一个称为 EGL_NATIVE_BUFFER_ANDROID 的Target,支持通 ANativeWindowBuffer 创建EGLImage对象,而Buffer则对应创建EGLImage对象时使用数据。 而在Android上定义的 EGLClientBuffer 是在native中定义的 GraphicBuffer 类,综上, EGLImageKHR 的基本使用流程如下: 如果EGLClientBuffer的数据是YUV格式的,还可以使用纹理Target为:GL_TEXTURE_EXTERNAL_OES, 该Target也是主要用于从EGLImage中产生纹理的情景。 Android NDK没有暴露 GraphicBuffer 相关接口,因此如果直接使用需要自行下载Android源码,编译并打包成动态库,需要注意的是,在API26之后,android已经禁止了私有native api的调用。 不过在API 26以后,Android NDK提供了 Hardware Buffer APIs 类,来实现这样的功能,这个后续文章会详细说明,欢迎订阅😁。 虽然大部分情况下我们直接使用SurfaceTexture即可。 4.2 EGLImageKHR的重要性质 EGLImageKHR其设计目的就是为了共享2D纹理数据的,因此驱动程序在底层实现的时候,往往实现了CPU与GPU对同一资源的访问,这样就可以做到无需拷贝的数据共享,降低功耗与提高性能。 在Android平台上,了解这点是非常重要的。而iOS平台由于使用了EAGL而不是EGL,因此并不会使用EGLImage,但也有自己的数据映射的方式。 从上面可以知道,实现共享纹理,就可以有两种实现方式: 一种是EGL的ShareContext机制 一种是共享内存,这里就是EGLImageKHR 5.1 ShareContext EGL的ShareContext是常见的共享上下文的方式(iOS平台的EAGL叫ShareGroup)。 当 share_context 参数传入另一个EGL的context时,这两个EGLContext就可以共享纹理以及VBO等。 需要注意的是 container objects 不能被共享,比如: Framebuffer objects Vertex array objects Transform feedback objects Program pipeline objects 5.2 EGLImageKHR 这实际上是一种共享内存的方式,以实现共享纹理,最简单就是直接使用SurfaceTexture,这里不再详细说明。当然也可以使用HardwareBuffer与EGLImageKHR来实现。 这篇文章主要介绍了SurfaceTexture的原理,下篇文章将主要介绍 SurfaceTexture与共享内存的应用 ,敬请期待。
📥 下载地址(文章结尾)
装机神器,可安装一切系统,纯净版,英文版,繁体版 ,精简版,原版等等等