1

我遇到了一些 opengl ES 驱动程序的问题,当为 Pbuffer 调用 glReadPixels 时,某些设备只会杀死应用程序而没有任何消息。其他人会给我下一个跟踪,然后冻结大约 10 秒钟,然后终止应用程序。

Unable to Find Phys Addr for 0

到目前为止,问题可重现的受影响设备是:

Galaxy Y, Galaxy Ace, Galaxy Mini, Galaxy Young

我还在下一个设备中测试了代码,它可以按预期正常工作,完全没有问题:

Nexy 4, Nexus 7, Nexus Galaxy, SGI, SGII, SGIII, Motorola Mini-Defy, and some others more.

我已经组合了一个快速测试功能来重现问题。也许有人可以发现问题。请这只是一种测试方法,没有必要对其进行评论,因为我只是将它放在一起以测试错误,如果我遗漏了什么,请告诉我。

private static void bugTest()
{
    EGL10 egl = (EGL10)EGLContext.getEGL();
    EGLDisplay eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);

    // Initialize
    int[] version = new int[2];
    egl.eglInitialize(eglDisplay, version);

    // Query total number of configurations
    int[] totalConfigurations = new int[1];
    egl.eglGetConfigs(eglDisplay, null, 0, totalConfigurations);

    EGLConfig[] configurationsList = new EGLConfig[totalConfigurations[0]];
    int attribs[] = { EGL10.EGL_RENDERABLE_TYPE, 4 /* EGL_OPENGL_ES2_BIT */, EGL10.EGL_RED_SIZE, 1, EGL10.EGL_GREEN_SIZE, 1, EGL10.EGL_BLUE_SIZE, 1, EGL10.EGL_NONE };

    if (egl.eglChooseConfig(eglDisplay, attribs, configurationsList, 1, totalConfigurations) == false)
    {
        Log.e(TAG, "Could not find config for GLES2");          
        egl.eglTerminate(eglDisplay);
        return;
    }

    // Create the PBuffer

    EGLSurface eglSurface = null;
    final int surfaceWidth = 512;
    final int surfaceHeight = 512;

    try
    {
        int[] attribList = new int[] { EGL10.EGL_WIDTH, surfaceWidth, EGL10.EGL_HEIGHT, surfaceHeight, EGL10.EGL_NONE };
        eglSurface = egl.eglCreatePbufferSurface(eglDisplay, configurationsList[0], attribList);
    }
    catch (Exception ex)
    {
        Log.e(TAG, "Failed to create surface");             
        egl.eglTerminate(eglDisplay);
        return;
    }

    // BUG Test for glReadPixels

    if (eglSurface != null)
    {
        // Create context

        final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
        final int GLES_VERSION = 2;
        int[] attribList = { EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION, EGL10.EGL_NONE };
        EGLContext eglContext = egl.eglCreateContext(eglDisplay, configurationsList[0], EGL10.EGL_NO_CONTEXT, attribList);

        if (eglContext != null)
        {
            // Attach context to surface

            if (egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext) == true)
            {
                // Perform the actual bug test

                GL10 gl = (GL10)eglContext.getGL();
                int buffer[] = new int[surfaceWidth * surfaceHeight];
                IntBuffer wrappedBuffer = IntBuffer.wrap(buffer);
                wrappedBuffer.position(0);

                // BUG: Line of failure
                gl.glReadPixels(0, 0, surfaceWidth, surfaceHeight, GL10.GL_RGB, GL10.GL_UNSIGNED_BYTE, wrappedBuffer);

                // Also fails when using RGBA 
                //gl.glReadPixels(0, 0, surfaceWidth, surfaceHeight, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, wrappedBuffer);
            }

            egl.eglDestroyContext(eglDisplay, eglContext);
        }

        egl.eglDestroySurface(display, eglSurface);
    }

    egl.eglTerminate(eglDisplay);
}
4

1 回答 1

0

Pbuffers are not supported on devices with Nvidia Tegra GPUs. The problem is their EGL driver, not your code. But there is really no good reason to use pbuffers anyway. They are obsolete. You should use FBOs instead, especially on Android. This article explains in detail why:

http://processors.wiki.ti.com/index.php/Render_to_Texture_with_OpenGL_ES

The best way to create an off-screen surface on Android is to construct a new SurfaceTexture() and pass that to eglCreateWindowSurface().

于 2013-09-06T17:37:47.527 回答