Android - 在背景上下文中创建共享FBO纹理到主线程

时间:2018-01-24 00:13:21

标签: android multithreading opengl-es textures fbo

我需要在后台线程中使用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。 请帮忙!

1 个答案:

答案 0 :(得分:0)

您只能在上下文共享组中共享内容。创建第二个上下文时,需要将其设置为使用第一个上下文作为父项。首先创建主渲染上下文,并在创建加载线程上下文时将主上下文作为share_context的{​​{1}}参数传递。参见:

https://www.khronos.org/registry/EGL/sdk/docs/man/html/eglCreateContext.xhtml

目前您正在传递eglCreateContext(),这解释了为什么它们之间没有共享。

但请注意,并非所有资源都可以共享。数据资源 - 例如纹理,缓冲区和着色器等都很好,可以共享。纯粹管理FBO和VAO等状态的对象不可共享。如果您遇到的性能问题是FBO创建 - 而不是纹理数据管理 - 那么使用第二个上下文不会有帮助......