OpenGL ES 2.0 - 如何有效地将纹理复制到帧缓冲区
OpenGL ES 2.0 - How to efficiently copy a Texture into Frame Buffer
简而言之 - 我有一个 OpenGL 纹理,我需要在 OpenGL ES 2.0 下以最有效的方式将其复制到 FBO 或其他纹理中。
目前我只是将第一个纹理绘制到 FBO 中。
有没有更高效的方法?例如。某种像素复制,不涉及将像素数据拉回 RAM,然后缓冲到另一个纹理 - 在 ES 2.0 配置文件中。
为您提供上下文 - 这是与视频渲染相关的:
我有一个 OpenGL 纹理被来自 LibVLC 的视频帧数据缓冲,但由于我的应用程序重绘率和解码器刷新率之间的时间问题,OpenGL 纹理可能没有新帧要更新而且非常奇怪如果我要在没有要更新的帧的情况下将纹理绘制到屏幕上 - 而不是它包含前一帧的数据,它会绘制一些自己的奇怪图像(它看起来像一个 space 入侵者??) - 因此为什么我需要 'cache' 上一帧的内容。
具体来说,这是一个 OpenGL 纹理,用于创建一个 Android SurfaceTexture,我必须手动调用 updateTexImage 和 releaseTexImage 来更新纹理的内容,然后标记我已经完成了绘制 SurfaceTexture 后的内容。如果我不发布它,那么就没有新的框架可以更新到它。如果我释放它,我不能多次重绘同一帧。这导致我在纹理更新后对其进行缓存,以便解码器可以自由写入它并且如果我再次绘制并且还没有更新,我仍然有前一帧。
谢谢。
此解决方案基于已弄清楚如何与 Android SurfaceTexture 正确交互以避免必须完全缓存其内容。
如果有人想分享有关 OpenGL ES 2.0 中高效纹理复制的答案,请随意 - 这适合我原来的问题。
对于任何感兴趣的人,这就是我所做的:
用于在 Android 上渲染视频的我的 GLPaint class 包含 SurfaceTexture 实例,它是从 JOGL OpenGL 纹理创建的(使用它的 ID)- 这使我能够绘制纹理作为我的一部分GLPaint.paint 函数。
这个GLPaint实现了SurfaceTexture.OnFrameAvailableListener接口的onFrameAvailable方法。我有一个私有布尔值来标记第一帧 'written' - 这是避免过早释放 SurfaceTexture 所必需的。
classGUIThreadLock 是我对 ReentrantLock 的扩展——我扩展它以获得额外的调试信息并制作静态单例。这个锁在我的 'one in - one out' 控制器中用于我的 UI 中的线程,确保我的 UI 中一次只有一个线程处于活动状态(通常只是主渲染器循环器)但也处理获取每当分别获取和放弃锁时,OpenGL 上下文绑定或解除绑定到锁所有者线程。
@Override
public void onFrameAvailable( SurfaceTexture pSurfaceTexture )
{
try
{
GUIThreadLock.acquire();
if( written )
{
pSurfaceTexture.releaseTexImage();
}
pSurfaceTexture.updateTexImage();
written = true;
}
finally
{
GUIThreadLock.relinquish();
}
}
这意味着当新帧准备就绪时,SurfaceTexture 会释放旧帧并更新到新帧 - 然后它会与当前帧一起缓冲我希望绘制视频的任何点,直到下一帧准备好。 GUIThreadLock 保护 SurfaceTexture 在我绘制内容时不更新内容,但也获取我的 GL 上下文,以便回调线程可以在此处实际执行更新。
我的重绘线程在绘制我的应用程序之前也需要 GUIThreadLock - 因此 GL 上下文受到保护,帧更新和帧绘制之间的关系得到巩固。
简而言之 - 我有一个 OpenGL 纹理,我需要在 OpenGL ES 2.0 下以最有效的方式将其复制到 FBO 或其他纹理中。
目前我只是将第一个纹理绘制到 FBO 中。
有没有更高效的方法?例如。某种像素复制,不涉及将像素数据拉回 RAM,然后缓冲到另一个纹理 - 在 ES 2.0 配置文件中。
为您提供上下文 - 这是与视频渲染相关的:
我有一个 OpenGL 纹理被来自 LibVLC 的视频帧数据缓冲,但由于我的应用程序重绘率和解码器刷新率之间的时间问题,OpenGL 纹理可能没有新帧要更新而且非常奇怪如果我要在没有要更新的帧的情况下将纹理绘制到屏幕上 - 而不是它包含前一帧的数据,它会绘制一些自己的奇怪图像(它看起来像一个 space 入侵者??) - 因此为什么我需要 'cache' 上一帧的内容。
具体来说,这是一个 OpenGL 纹理,用于创建一个 Android SurfaceTexture,我必须手动调用 updateTexImage 和 releaseTexImage 来更新纹理的内容,然后标记我已经完成了绘制 SurfaceTexture 后的内容。如果我不发布它,那么就没有新的框架可以更新到它。如果我释放它,我不能多次重绘同一帧。这导致我在纹理更新后对其进行缓存,以便解码器可以自由写入它并且如果我再次绘制并且还没有更新,我仍然有前一帧。
谢谢。
此解决方案基于已弄清楚如何与 Android SurfaceTexture 正确交互以避免必须完全缓存其内容。
如果有人想分享有关 OpenGL ES 2.0 中高效纹理复制的答案,请随意 - 这适合我原来的问题。
对于任何感兴趣的人,这就是我所做的:
用于在 Android 上渲染视频的我的 GLPaint class 包含 SurfaceTexture 实例,它是从 JOGL OpenGL 纹理创建的(使用它的 ID)- 这使我能够绘制纹理作为我的一部分GLPaint.paint 函数。
这个GLPaint实现了SurfaceTexture.OnFrameAvailableListener接口的onFrameAvailable方法。我有一个私有布尔值来标记第一帧 'written' - 这是避免过早释放 SurfaceTexture 所必需的。
classGUIThreadLock 是我对 ReentrantLock 的扩展——我扩展它以获得额外的调试信息并制作静态单例。这个锁在我的 'one in - one out' 控制器中用于我的 UI 中的线程,确保我的 UI 中一次只有一个线程处于活动状态(通常只是主渲染器循环器)但也处理获取每当分别获取和放弃锁时,OpenGL 上下文绑定或解除绑定到锁所有者线程。
@Override
public void onFrameAvailable( SurfaceTexture pSurfaceTexture )
{
try
{
GUIThreadLock.acquire();
if( written )
{
pSurfaceTexture.releaseTexImage();
}
pSurfaceTexture.updateTexImage();
written = true;
}
finally
{
GUIThreadLock.relinquish();
}
}
这意味着当新帧准备就绪时,SurfaceTexture 会释放旧帧并更新到新帧 - 然后它会与当前帧一起缓冲我希望绘制视频的任何点,直到下一帧准备好。 GUIThreadLock 保护 SurfaceTexture 在我绘制内容时不更新内容,但也获取我的 GL 上下文,以便回调线程可以在此处实际执行更新。
我的重绘线程在绘制我的应用程序之前也需要 GUIThreadLock - 因此 GL 上下文受到保护,帧更新和帧绘制之间的关系得到巩固。