Предотвратить уничтожение EGLContext при переходе в фоновый режим

Моя игра для Android (OpenGL ES 2.0) должна быть приостановлена, когда пользователь сворачивает ее, не уничтожая то, что уже нарисовано на экране. Изначально он использовал NativeActivity и чистый C++, но, похоже, там это невозможно. Я переписал его, и теперь Java генерирует собственный GLSurfaceView, а игровая логика + рендеринг — на C++. Я добавил setPreserveEGLContextOnPause(true) при создании поверхности.

Таким образом, ошибка после нажатия пользователем кнопки «Домой»:

  1. onPause отправляет nativeOnPause в код C++ через JNI.
  2. Код C++ устанавливает переменную паузы, которая предотвращает обновление и рендеринг

Это работает нормально. После того, как мы вернемся к приложению:

  1. onResume вызывает nativeOnResume
  2. nativeOnResume вызывает методы EGL для получения текущего контекста, отображения и отображения и передает их менеджеру игры.
  3. Обновление и рендеринг теперь активированы
  4. Мы получаем несколько сообщений EGL_BAD_SURFACE и, наконец, вылетаем на eglMakeCurrent.

Вопрос в том, должны ли мы каким-либо образом воссоздавать EGLSurface и EGLDisplay, используя текущий контекст, или получить текущую поверхность и отображение в порядке?

Я также заметил, что когда мы возвращаемся к приложению, вызывается onResume, но не вызывается onSurfaceChanged или onSurfaceCreated.

Любое предложение, как решить эту проблему на устройствах> 4.0?


person rafalczuj    schedule 14.03.2015    source источник


Ответы (1)


Не используйте GLSurfaceView, если вы хотите контролировать время жизни контекста EGL.

Класс GLSurfaceView обрабатывает контекст EGL за вас и довольно агрессивно отбрасывает его. Вызов setPreserveEGLContextOnPause(), вероятно, не будет делать то, что вы хотите. Если вы переключитесь на SurfaceView, вы получите полный контроль над временем жизни контекста EGL, но это палка о двух концах, поскольку теперь вам необходимо полностью управлять контекстом EGL.

Вы можете найти различные примеры использования GLES с SurfaceView в Grafika. Действие "тренажер аппаратного масштабирования" является разумным примером.

Это действие также демонстрирует один из подходов к управлению жизненным циклом действия. Обсуждение взаимосвязи между Activity и SurfaceView, в том числе почему вы не всегда видите surfaceChanged() и surfaceCreated(), можно найти в приложении к документу по графической архитектуре.

Тем не менее, сохранение контекста EGL и всех связанных с ним ресурсов, пока ваше приложение неактивно, является плохой практикой. Когда пользователь приостанавливает ваше приложение, эти ресурсы должны быть освобождены, чтобы другие приложения имели в своем распоряжении все возможности устройства.

person fadden    schedule 15.03.2015