我需要在后台线程中使用FBO,因为它会在某些Android设备上导致强大的UI冻结(大约0.5秒)(需要每3-5秒重新创建大约25个FBO对象),我已经使用成功创建了背景上下文EGL14,也渲染到FBO按预期工作,但....我完全无法理解如何与主线程共享FBO纹理!
我尝试使用在后台线程中创建的纹理ID,但是这个id已经存在于主线程中并且与另一个纹理相关或者它们根本没有纹理。 我搜索了很多,但我找不到任何示例代码如何正确地分享纹理到Android上的主线程。请提供解释如何使用GLSurfaceView创建的主线程中的纹理(在后台线程中创建)的任何解决方案或链接。
代码的某些部分
初始化背景背景:
private boolean createEglContext() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
if (mEglDisplay == null) {
mEglDisplay = eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
if (mEglDisplay == EGL14.EGL_NO_DISPLAY) {
return false;
}
int[] version = new int[2];
if (!EGL14.eglInitialize(mEglDisplay, version, 0, version, 1)) {
mEglDisplay = null;
return false;
}
}
if (mEglConfig == null) {
int[] eglConfigAttribList = new int[]{
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, // very important!
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, // we will create a pixelbuffer surface
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8, // if you need the alpha channel
EGL_DEPTH_SIZE, 16, // if you need the depth buffer
EGL_NONE
};
int[] numEglConfigs = new int[1];
android.opengl.EGLConfig[] eglConfigs = new android.opengl.EGLConfig[1];
if (!EGL14.eglChooseConfig(mEglDisplay, eglConfigAttribList, 0,
eglConfigs, 0, eglConfigs.length, numEglConfigs, 0)) {
return false;
}
mEglConfig = eglConfigs[0];
}
int[] ctxAttrib = {
EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
EGL14.EGL_NONE
};
if (mEglContext == null) {
mEglContext = EGL14.eglCreateContext(mEglDisplay, mEglConfig,
EGL14.EGL_NO_CONTEXT, ctxAttrib, 0);
if (mEglContext == null) {
return false;
}
}
int[] surfAttr = {
EGL14.EGL_WIDTH, viewPortWidth,
EGL14.EGL_HEIGHT, viewPortHeight,
EGL14.EGL_NONE
};
mEglSurface = EGL14.eglCreatePbufferSurface(mEglDisplay, mEglConfig, surfAttr, 0);
if (mEglSurface == null) {
return false;
}
EGL14.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
return true;
}
return false;
}
在后台线程上初始化FBO:
...
GLES20.glGenFramebuffers(1, frameObject, 0);
textureObject = new int[1];
GLES20.glGenTextures(1, textureObject, 0);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, textureObject[0]);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureObject[0]);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, textureObject[0], 0);
int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
if (status != GLES20.GL_FRAMEBUFFER_COMPLETE) {
}
....
初始化FBO /渲染到FBO完成后,我试图将生成的纹理id传递给主线程 - 但没有成功。显示的纹理始终不正确或根本没有纹理。
初始化后台线程,渲染到FBO - 一切正常,并且没有任何glError。我正在使用OpenGL ES 2.0。 请帮忙!
答案 0 :(得分:0)
您只能在上下文共享组中共享内容。创建第二个上下文时,需要将其设置为使用第一个上下文作为父项。首先创建主渲染上下文,并在创建加载线程上下文时将主上下文作为share_context
的{{1}}参数传递。参见:
https://www.khronos.org/registry/EGL/sdk/docs/man/html/eglCreateContext.xhtml
目前您正在传递eglCreateContext()
,这解释了为什么它们之间没有共享。
但请注意,并非所有资源都可以共享。数据资源 - 例如纹理,缓冲区和着色器等都很好,可以共享。纯粹管理FBO和VAO等状态的对象不可共享。如果您遇到的性能问题是FBO创建 - 而不是纹理数据管理 - 那么使用第二个上下文不会有帮助......