Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not panic when swap_buffer (egl) fails #1320

Closed
Kaiser1989 opened this issue Aug 6, 2020 · 1 comment
Closed

Do not panic when swap_buffer (egl) fails #1320

Kaiser1989 opened this issue Aug 6, 2020 · 1 comment

Comments

@Kaiser1989
Copy link

I notices some bug in running on android. When resuming to the app, sometimes the swap_buffer method is throwing an egl error:

... /? E/BufferQueueProducer: [rust.rust_android_example/android.app.NativeActivity#0] queueBuffer: BufferQueue has been abandoned
.../rust.rust_android_example E/Surface: queueBuffer: error queuing buffer to SurfaceTexture, -19
.../? E/BufferQueueProducer: [rust.rust_android_example/android.app.NativeActivity#0] dequeueBuffer: BufferQueue has been abandoned
.../rust.rust_android_example E/EGL_emulation: tid 21300: swapBuffers(552): error 0x300d (EGL_BAD_SURFACE)

The problem is located under glutin/src/api/egl/mod.rs line 663:

    #[inline]
    pub fn swap_buffers(&self) -> Result<(), ContextError> {
        let egl = EGL.as_ref().unwrap();
        let surface = self.surface.as_ref().unwrap().lock();
        if *surface == ffi::egl::NO_SURFACE {
            return Err(ContextError::ContextLost);
        }

        let ret = unsafe { egl.SwapBuffers(self.display, *surface) };

        if ret == 0 {
            match unsafe { egl.GetError() } as u32 {
                ffi::egl::CONTEXT_LOST => {
                    return Err(ContextError::ContextLost)
                }
                err => panic!(
                    "swap_buffers: eglSwapBuffers failed (eglGetError returned 0x{:x})",
                    err
                ),
            }
        } else {
            Ok(())
        }
    }

Calling the panic! kills the app. There is no chance to recover from this state. I noticed, that this problem can easily be fixed by recreating the graphics context. Therefore we need to have a chance to handle that problem:

My simple hack is following:

    #[inline]
    pub fn swap_buffers(&self) -> Result<(), ContextError> {
        let egl = EGL.as_ref().unwrap();
        let surface = self.surface.as_ref().unwrap().lock();
        if *surface == ffi::egl::NO_SURFACE {
            return Err(ContextError::ContextLost);
        }

        let ret = unsafe { egl.SwapBuffers(self.display, *surface) };

        if ret == 0 {
            Err(ContextError::ContextLost)
        } else {
            Ok(())
        }
    }

This gives me a chance to release all openGL resources, recreate the context, and finally recreate all buffers, and the app keeps running. The user doesn't even notice...

Maybe the problem is lies somewhere else, but calling panic! takes away all possibilities.

@kchibisov
Copy link
Member

kchibisov commented Sep 3, 2022

Fixed in #1435.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants