我遇到以下情况:
在iOS和Android的跨平台渲染库中(用c(++)编写),我有两个线程,每个线程都需要自己的EGLContext: 线程A是主线程;它渲染到窗口。 线程B是一个生成器线程,它执行各种计算并将结果呈现为稍后由线程A使用的纹理。
由于我无法在iOS上使用EGL,因此库使用静态Obj.-C函数的函数指针来创建新的上下文并将其设置为当前。 这已经有效了,我使用
为线程A创建了上下文EAGLContext *contextA = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
线程B的上下文是使用
创建的EAGLContext *contextB = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup:[contextA sharegroup]];
然后我可以设置两个电流中的任何一个:
[EAGLContext setCurrentContext:context];
要在Android上使用相同的逻辑(传递给库的函数指针),我想在JNI绑定的C端执行此操作,这次使用真正的EGL而不是Apple的EAGL。 我可以使用WindowSurface和本机Window轻松创建contextA,我可以创建contextB并将contextA传递给eglCreateContext调用的shareContext参数。
但是当我想让contextB变为当前时,我必须将一个表面传递给eglMakeCurrent调用,并且我试图弄清楚要在那里传递什么样的表面。
我不明白Munshi,Ginsurg和Shreiner的意思是什么,帧缓冲对象如何替代pbuffer表面?如果我创建一个非常小的(例如1x1px)pbuffer表面以使上下文变为当前状态,那么我仍可以渲染成任意大的FBO吗?还有其他我不知道的可能性吗?
非常感谢你的帮助!
答案 0 :(得分:3)
传递给eglMakeCurrent()的表面必须是eglCreateWindowSurface()的EGL表面。例如:
EGLSurface EglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, maEGLconfigs[0], surfaceTexture, null);
mEgl.eglMakeCurrent(mEglDisplay, EglSurface, EglSurface, mEglContext);
但是,eglCreateWindowSurface()需要一个SurfaceTexture,它在创建TextureView时提供给onSurfaceTextureAvailable()回调,但你也可以在没有任何View的情况下创建离屏SurfaceTextures。
有一个示例应用程序在Android SDK中使用TextureView,虽然它使用SurfaceTexture进行摄像机视频而不是OpenGL ES渲染:
sources\android-17\com\android\test\hwui\GLTextureViewActivity.java
默认情况下,FBO的EGL表面将与创建它们的SurfaceTexture具有相同的大小。您可以使用以下命令更改SurfaceTexture的大小:
surfaceTexture.setDefaultBufferSize(width, height);
不要在Android上使用pbuffers,因为某些平台(Nvidia Tegra)不支持它们。 本文详细解释了FBO优于pbuffers的优点:
http://processors.wiki.ti.com/index.php/Render_to_Texture_with_OpenGL_ES
答案 1 :(得分:3)
我最终使用了PBuffer表面(大小为1x1) - 然后我创建了一个FBO并渲染到纹理中就好了。为了显示它们(在不同的线程和不同的(共享的)opengl上下文中),我使用带有ANativeWindow的windowsurface(在sdk的某处有一个样本)。
答案 2 :(得分:0)
如果只想绘制到FBO,你可以抓住已经由你或其他人创建的任何EGLContext(例如GLSurfaceView)并使其成为当前的,然后你只需生成你的FBO然后用它绘制。 问题是如何将GLSurfaceView创建的上下文分享到您的跨平台c ++库。我通过调用c ++中的静态函数来实现这一点,以便在上下文由Java层创建当前上下文后立即获取eglcontext和surface。比如下面的代码:
//This is a GLSurfaceView renderer method
@override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
//up to this point, we know the EGLContext
//has already been set current on this thread.
//call JNI function to setup context
graphics_library_setup_context();
}
c ++对应
void setup_context() {
context = eglGetCurrentContext();
display = eglGetCurrentDisplay();
surface = eglGetCurrentSurface(EGL_DRAW);
}