glReadPixels при использовании PBuffers не работает на некоторых устройствах Android
Я столкнулся с проблемой с некоторыми драйверами opengl ES, когда при вызове glReadPixels для Pbuffer некоторые устройства просто убивают приложение без каких-либо сообщений. Другие дадут мне следующий след, а затем остановятся примерно на 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);
}
1 ответ
Pbuffers не поддерживаются на устройствах с графическими процессорами Nvidia Tegra. Проблема в их драйвере EGL, а не в вашем коде. Но на самом деле нет веской причины использовать pbuffers. Они устарели. Вместо этого вы должны использовать FBO, особенно на Android. В этой статье подробно объясняется, почему:
http://processors.wiki.ti.com/index.php/Render_to_Texture_with_OpenGL_ES
Лучший способ создать внеэкранную поверхность на Android - это создать новую SurfaceTexture() и передать ее eglCreateWindowSurface().