Какую поверхность использовать для eglMakeCurrent для контекста, который распространяется только в FBOs

У меня сложилась следующая ситуация:

В библиотеке рендеринга кросс-платформы для iOS и Android (написанной на c (++)) у меня есть два потока, каждый из которых нуждается в собственном EGLContext: Thread A является основным потоком; Он отображает Окно. Thread B – поток генератора, который выполняет различные вычисления и отображает результаты в текстуры, которые позже используются потоком A.

Поскольку я не могу использовать EGL в iOS, библиотека использует указатели функций для статических функций Obj.-C для создания нового контекста и установки его текущей. Это уже работает, я создаю контекст для потока A, используя

EAGLContext *contextA = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; 

Контекст для потока B создается с использованием

 EAGLContext *contextB = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup:[contextA sharegroup]]; 

Затем я могу установить любой из двух токов:

 [EAGLContext setCurrentContext:context]; 

Чтобы использовать ту же логику (указатели функций, переданные в библиотеку) на Android, я хочу сделать это на стороне C привязок JNI, на этот раз используя реальный EGL вместо Apple EAGL. Я могу легко создать contextA с помощью WindowSurface и собственного окна, я могу создать contextB и передать contextA в параметр shareContext вызова eglCreateContext.

Но когда я хочу создать currentB current, я должен передать поверхность вызову eglMakeCurrent, и я пытаюсь выяснить, какая поверхность должна пройти там.

  • Я не могу использовать WindowSurface, который я использую для contextA, поскольку спецификация говорит в разделе 3.7, что «не более одного контекста для каждого поддерживаемого клиентского API может быть текущим для конкретного потока в данный момент времени, и максимум один контекст может быть привязан к определенному Поверхности в данный момент времени ».
  • Я не могу указать EGL_NO_SURFACE, потому что это приведет к ошибке EGL_BAD_MATCH в вызове eglMakeCurrent.
  • Кажется, я мог бы использовать поверхность PBuffer, но я колеблюсь, потому что мне нужно будет указать ширину и высоту, когда я создам такую ​​поверхность, и поток B может захотеть создать текстуры разных размеров. В дополнение к этому, в «Руководстве по программированию OpenGL ES 2.0» Мунши, Гинзбурга и Шрейнера говорится в разделе 3.8, что «Pbuffers чаще всего используются для создания текстурных карт. Если все, что вы хотите сделать, отображает текстуру, мы рекомендуем Используя объекты framebuffer […] вместо pbuffers, потому что они более эффективны », что именно то, что я хочу сделать в потоке B.

Я не понимаю, что Мунши, Гинсург и Шрейнер подразумевают под этим предложением, каким образом объект фреймбуфера будет заменять поверхность pbuffer? Что делать, если я создаю очень маленькую (скажем, 1x1px) поверхность pbuffer, чтобы сделать контекст текущим – могу ли я затем отобразить в произвольно большие FBOs? Есть ли другие возможности, о которых я еще не знаю?

Большое спасибо за вашу помощь!

Поверхность, которую вы передаете eglMakeCurrent (), должна быть поверхностью EGL из eglCreateWindowSurface (). Например:

  EGLSurface EglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, maEGLconfigs[0], surfaceTexture, null); mEgl.eglMakeCurrent(mEglDisplay, EglSurface, EglSurface, mEglContext); 

Но для eglCreateWindowSurface () требуется SurfaceTexture, которая предоставляется для обратного вызова onSurfaceTextureAvailable () при создании TextureView, но вы также можете создавать SurfaceTextures вне экрана без какого-либо представления.

Существует пример приложения, которое использует TextureView в Android SDK здесь, хотя оно использует SurfaceTexture для видео камеры, а не для рендеринга OpenGL ES:

 sources\android-17\com\android\test\hwui\GLTextureViewActivity.java 

По умолчанию поверхность EGL для FBO будет иметь тот же размер, что и SurfaceTexture, из которой они были созданы. Вы можете изменить размер SurfaceTexture с помощью:

  surfaceTexture.setDefaultBufferSize(width, height); 

Не используйте pbuffers на Android, потому что некоторые платформы (Nvidia Tegra) не поддерживают их. В этой статье подробно описаны преимущества FBOs над pbuffers:

http://processors.wiki.ti.com/index.php/Render_to_Texture_with_OpenGL_ES

Я закончил тем, что использовал поверхность PBuffer (размер 1×1) – тогда я создаю FBO и визуализую в текстуры просто отлично. Для отображения их (в другом потоке и в другом (общем) контексте opengl), я использую windowsurface с ANativeWindow (есть образец этого где-то в sdk).