Для отрисовки графики в Android используется API OpenGL ES (GLES). Чтобы создавать контексты GLES и предоставлять оконную систему для отрисовки GLES, Android использует библиотеку EGL. Вызовы GLES используются для отрисовки многоугольников с текстурами, а вызовы EGL – для вывода изображений на экран.
Прежде чем рисовать с помощью GLES, необходимо создать контекст GL. В EGL это означает создание EGLContext и EGLSurface. Операции GLES применяются к текущему контексту, доступ к которому осуществляется через локальное хранилище потока, а не передается в качестве аргумента. Код отрисовки должен выполняться в потоке GLES, а не в потоке UI.
EGLSurfaces
EGLSurface может быть внеэкранным буфером, выделенным EGL (pbuffer), или окном, выделенным операционной системой. Вызов функции eglCreateWindowSurface() создает поверхности окон EGL.
eglCreateWindowSurface() принимает в качестве аргумента объект окна, который на Android является поверхностью. Поверхность – это сторона производителя BufferQueue. Потребители, такие как SurfaceView, SurfaceTexture, TextureView или ImageReader, создают поверхности.
Когда вы вызываете eglCreateWindowSurface(), EGL создает новый объект EGLSurface и подключает его к интерфейсу производителя объекта BufferQueue окна. С этого момента отрисовка на EGLSurface
извлекает буфер из очереди, отрисовывает его и ставит в очередь для использования потребителем.
EGL не предоставляет вызовы блокировки/разблокировки. Отправьте команды рисования, а затем вызовите функцию eglSwapBuffers(), чтобы отправить текущий кадр. Название метода происходит от традиционного обмена переднего и заднего буферов, но фактическая реализация может быть другой.
С поверхностью может быть связан только один объект EGLSurface (к BufferQueue может быть подключен только один производитель), но если вы уничтожите EGLSurface, он отключится от BufferQueue и позволит подключиться другому объекту.
Один поток может переключаться между несколькими объектами EGLSurface, изменяя текущий. EGLSurface может быть текущим только в одном потоке одновременно.
EGL не является аспектом поверхности, например SurfaceHolder. EGLSurface – связанное, но независимое понятие. Вы можете рисовать на EGLSurface, которая не поддерживается поверхностью, и использовать поверхность без EGL. EGLSurface предоставляет GLES место для рисования.
Требования к OpenGL ES и EGL приведены в документе с определением совместимости для Android.
ANativeWindow
Публичный класс поверхности реализован на языке программирования Java. В C/C++ аналогом является класс ANativeWindow, частично представленный в Android NDK. Получить ANativeWindow из поверхности можно с помощью вызова ANativeWindow_fromSurface(). Как и в случае с Java, вы можете заблокировать, отрендерить в программном обеспечении, а затем разблокировать и опубликовать изображение. Базовый тип нативного окна – это сторона производителя в BufferQueue.
Чтобы создать поверхность окна EGL из нативного кода, передайте экземпляр EGLNativeWindowType в eglCreateWindowSurface(). EGLNativeWindowType – это синоним ANativeWindow, поэтому вы можете привести один тип к другому.