eglCreateWindowSurface:native_window_api_connect失败解决方法 - 失去了opengl-context-when-android-pauses

问题描述 投票:3回答:2

当android:hardwareAccelerated设置为false进入清单文件时,我的问题只出现在最新的三星Galaxy系列中

据我所知(我自己试过),它发生在Galaxy S9,J6和Note 8上,但不是在Galaxy S8上。其他手机似乎根本没有受到影响。

问题是我得到了一个没有显示任何内容的GLSurfaceView(黑屏),但如果我在活动之间切换,它会再次开始工作,我猜是因为它更新了View而没有错误。

这是我发现的可疑对数线

01-13 14:39:47.813 25013 25080 E libEGL  : eglCreateWindowSurface: native_window_api_connect (win=0xc166b808) failed (0xffffffed) (already connected to another API?)
01-13 14:39:47.813 25013 25080 E libEGL  : eglCreateWindowSurface:679 error 3003 (EGL_BAD_ALLOC)

这些是我的代码的关键部分:

GLSurf glsurf;

public void onPause() {
    super.onPause();

    // stop
    if (glsurf != null) {
        glsurf.onPause();
    }
}

@Override
public void onResume() {
    super.onResume();

    if (glsurf != null)
        glsurf.onResume();
}

public class GLSurf extends GLSurfaceView {

    public GLSurf(Context context) {
        super(context);

        /* Create an OpenGL ES 2.0 context. */
        setEGLContextClientVersion(2);
        setEGLConfigChooser(8, 8, 8, 8, 16, 0);

        // Set the Renderer for drawing on the GLSurfaceView
        mRenderer = new GLRenderer(context);
        setRenderer(mRenderer);

        setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
    }
}

public class GLRenderer implements Renderer {

    GLRenderer(Context c){
        // does nothing
    }

    @Override
    public void onDrawFrame(GL10 unused) {

        // i've copied it but it's not even reached

        // call jni function updating the single texture filling the screen
        nativeGLRender();

        // Draw the triangles
        GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length,
                GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {

        // We need to know the current width and height.
        mScreenWidth = width;
        mScreenHeight = height;

        // Redo the Viewport.
        GLES20.glViewport(0, 0, (int)mScreenWidth, (int)mScreenHeight);

    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {

        // Set the clear color to black
        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1);
    }

}

一些信息更多:

EGL_BAD_ALLOC始终在具有有意义(至少我认为)的日志的事件序列之后出现

onCreate
onResume
onPause

GLSurfaceView: Warning, !readyToDraw() but waiting for draw finished! Early reporting draw finished.

onResume 

libEGL  : eglCreateWindowSurface: native_window_api_connect (win=0xc166b808) failed (0xffffffed) (already connected to another API?)
libEGL  : eglCreateWindowSurface:679 error 3003 (EGL_BAD_ALLOC)

onPause
onStop
onDestroy
onCreate 
onResume
onSurfaceCreated

        : NULL == surf->write_back_color_buffer
        : NULL == surf->write_back_color_buffer
GLThread: eglSwapBuffers failed: EGL_BAD_SURFACE

... black screen ...

请注意,上述事件在没有用户交互的情况下发生,并且持续1-2秒。关于发生了什么的任何想法?

为了完成信息,以下是工作电话的顺序(例如我的nexus 6)

onCreate
onResume
onSurfaceCreated
... working screen

编辑1月16日:

关于这个问题的新信息:

  • 当应用程序第一次启动时,它可以正常工作
  • 永远不要在下一次尝试
  • 如果放在后台并恢复它的工作原理
  • 如果我把android:hardwareAccelerated设置为true(但由于其他原因我不能打开它),这个错误永远不会发生

编辑1月18日

  • 我忘了提到仅当android:hardwareAccelerated设置为false时才会出现问题

我也发现了BUG的原因

不知道为什么,但我只是改变了这部分代码

@Override
public void onAttachedToWindow() {
    super.onAttachedToWindow();

    getWindow().setFormat(PixelFormat.RGB_565);
}

有了这个

@Override
public void onAttachedToWindow() {
    super.onAttachedToWindow();
}

一切都很好。三星驱动程序中的错误?也许...

我希望这对某些人有用

android opengl-es egl
2个回答
1
投票

eglCreateWindowSurface:native_window_api_connect失败任何关于发生了什么的想法?

The problem viewed from logcat perspective

来自eglApi.cpp的被调用函数是:

/*
 * native_window_api_connect(..., int api)
 * connects an API to this window. only one API can be connected at a time.
 * Returns -EINVAL if for some reason the window cannot be connected, which
 * can happen if it's connected to some other API.
 */
static inline int native_window_api_connect(
        struct ANativeWindow* window, int api)
{
    return window->perform(window, NATIVE_WINDOW_API_CONNECT, api);
}

以下是来自WindowSurface.recreate()方法的WindowSurface.java的注释块,其中说:

/*
 * If the previous EGLSurface isn't fully destroyed, e.g. it's still current on a
 * context somewhere, the create call will fail with complaints from the Surface
 * about already being connected.
*/

Related problem

来自Opengls eglCreateWindowSurface GL Error EGL_BAD_ALLOC Jitesh Dalsaniya

我解决了错误GL错误EGL_BAD_ALLOC。由于我没有正确处理活动生命周期的渲染器,因此发生此错误。

活动生命周期

必须通知GLSurfaceView何时暂停和恢复渲染。 GLSurfaceView客户必须在活动停止时调用onPause(),并在活动开始时调用onResume()。这些调用允许GLSurfaceView暂停和恢复渲染线程,并允许GLSurfaceView释放并重新创建OpenGL显示。

EGL背景丢失

在某些情况下,EGL渲染上下文将丢失。这通常发生在设备进入睡眠状态后唤醒时。当EGL上下文丢失时,将自动删除与该OpenGL相关联的所有context资源(例如纹理)。为了保持正确渲染,渲染器必须重新创建它仍然需要的任何丢失的资源。 onSurfaceCreated(GL10,EGLConfig)方法是一个方便的地方。

Workaround-to-losing-the-opengl-context-when-android-pauses

所以你的Activity's onPause()应该是这样的:

@Override
public void onPause() {
    glsurf.setVisibility(View.GONE);
    super.onPause();
    ...
}

并且你将GLSurfaceView恢复到层次结构而不是来自onResume()但是来自onWindowFocusChanged()

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if (hasFocus && glsurf.getVisibility() == View.GONE) {
         glsurf.setVisibility(View.VISIBLE);
    }
    ...
}

Other things to try

  1. 你需要调试才能弄清楚它为什么不开心。
  2. 尝试使用OpenglView可见总是和startPreview获得权限。一个看不见的持有者对opengl无效,这可能会导致你的崩溃。
  3. Opengl发布不好?
  4. onSurfaceTextureSizeChanged处理TextureViewGLActivity
  5. EGL_BAD_ALLOCeglSwapBuffers failed: EGL_BAD_SURFACE是一个很大的线索......
  6. !readyToDraw()删除并重新创建Surface?

Further

观察:

如果我把android:hardwareAccelerated设置为true,那么错误永远不会发生

如果您的Target API级别为is >=14,则默认启用硬件加速,但也可以显式启用(在应用程序或活动级别)。

Document Links

GLSurfaceViewGLSurfaceView.Rendererhardware-acceleration


0
投票

glsurf.setVisibility(View.GONE)中调用onPause()可以为我的应用程序工作,但是当我在glsurf.setVisibility(View.VISIBLE)中调用onWindowFocusChanged()时它将无效。

当我在glsurf.setVisibility(View.VISIBLE)打电话给onResume()时,它对我有用。

© www.soinside.com 2019 - 2024. All rights reserved.