Как правильно инициализировать и закончить EGL на Android

В то время как существует много примеров вокруг использования OpenGL ES на Android, все они кажутся неправильными (даже те, которые поставляются с Android SDK/NDK) в отношении инициализации/завершения EGL. И источником проблемы является только модель приложения Android, которая делает правильное использование EGL странным.

Реальная проблема, которую EGL инициализировала на OS процесс, в то время как все образцы Android и даже GLSurfaceView (фактически большинство из них просто используют его) включают инициализацию/завершение EGL на Компонент (Activity или WallpaperService). И это совершенно неправильно из-за того, что все компоненты работают в одном процессе! Нет проблем, если приложение состоит из одного компонента, но это проблема, если в приложении есть несколько компонентов, и каждый из них использует OpenGL ES.

Просто рассмотрите ситуацию, когда два компонента приложения, которые используют OpenGL ES, запускаются в одно и то же время, и один из них завершен. При завершении такого компонента вызывается eglTerminate() (смотрите в GLSurfaceView исходный код, чтобы узнать, о чем я говорю), и это прекратит работу EGL для всего процесса! И любые вызовы EGL от другого уже запущенного компонента не сработают с этого момента!

У меня есть проверка на множество примеров, и все они инициализируют и завершают EGL на каждый компонент (фактически никто из тех, кого я видел, не делает что-то другое, чем GLSurfaceView, большинство из них просто копирует GLSurfaceView.

И теперь мне интересно найти "правильный" способ получить работу (относительно инициализации/завершения) с помощью EGL на Android.

"Правильный" способ должен обеспечивать:

  • Инициализация EGL при запуске любого первого компонента с использованием EGL
  • Окончание EGL, когда последний компонент с использованием EGL завершен.
  • Многопоточность. Не должно быть ограничений на манипуляции EGL только из основного потока приложений.

Обратите внимание, что (2) имеет важное значение для минимизации использования системных ресурсов приложением, если нет активных объектов, которые используют EGL/OpenGL ES.

Любые идеи? Или, может быть, я упустил кое-что о EGL на Android?

Update

Есть еще одна интересная проблема:

В связи с тем, что для каждого потока разрешен только один активный контекст рендеринга, только один компонент одновременно может использовать OpenGL ES из основного потока. Наличие нескольких Компонентов, которые используют OpenGL ES в основном потоке, запущенном в одно и то же время, приведет к проблемам, потому что последний вызов компонента eglMakeCurrent() будет неявно "заменять" все контексты других компонентов его собственным ( и это фактически полностью сломает логику компонентов).

Обновление 2 (окончательное)

Было обнаружено (благодаря Romain Guy), что Android действительно имеет внутренний обходной путь для проблемы инициализации/завершения EGL в форме явного (это противоречит спецификации EGL и не упоминается в Android документация) "подсчет ссылок" внутри eglInitialize() и eglTerminate().

Ответы

Ответ 1

eglTerminate() и eglInitialize() относятся к подсчету ссылок, поэтому для каждого "компонента" это необходимо для их вызова. В Android 3.0, в частности, очень часто бывает несколько контекстов OpenGL в одном приложении, и с EGL нет никаких проблем.