2012-01-06 3 views
2

Я пытаюсь создать игру на базе NDK на Android ICS. Он отлично работал на сотах и ​​пряниках.eglCreateWindowSurface на ICS и переключение с 2D на 3D

В игре используется 2D-рендеринг, некоторый 3D-рендеринг, переключение между двумя на разных этапах исполнения. (Это не подлежит обсуждению из-за стороннего кода.) Мы используем ANativeWindow_lock()/ANativeWindow_unlockAndPost() для 2D-рендеринга и eglCreateWindowSurface()/gl*()/eglSwapBuffers() для 3D-рендеринга.

На сотах и ​​пряниках все это прекрасно работает. В ICS, eglCreateWindowSurface() терпит неудачу со следующими сообщениями в журнале:

E/SurfaceTexture(1765): [com.fnord/com.fnord.MyActivity] connect: already connected (cur=2, req=1) 
E/libEGL (5466): EGLNativeWindowType 0x29e9b8 already connected to another API 
E/libEGL (5466): eglCreateWindowSurface:374 error 300b (EGL_BAD_NATIVE_WINDOW) 
E/libEGL (5466): call to OpenGL ES API with no current context (logged once per thread) 

Глядя на исходный код кажется, довольно очевидно, что eglCreateWindowSurface() терпит неудачу, потому что что-то получил родное окно открытым для 2D-рендеринга и он не позволит мне измените его на 3D, не выпуская сначала поверхность. Однако API ANativeWindow, похоже, не имеет очевидного способа сделать это.

Неужели кто-то еще сталкивается с этим, и какое решение?

Обновлено

Так я переписан мой 2D код рендеринга использовать OpenGL примитивов вместо (загрузки BackBuffer в текстуру, делают текстуру с помощью пары треугольников, SwapBuffers). Это работает до определенной степени. Теперь что происходит, что 2D-рендеринг работает нормально; затем я уничтожаю поверхность, создаю новую в подготовке к 3D-рендерингу, а второй вызов eglCreateWindowSurface() терпит неудачу. На этот раз, с:

E/SurfaceTexture(1869): [com.fnord/com.fnord.MyActivity] connect: already connected (cur=1, req=1) 

... и он выдает ошибку EGL из AEGL_BAD_NATIVE_WINDOW.

Обратите внимание, что новая поверхность создана с точно такими же атрибутами, как и старый. Я даже пытался убедиться, что звоню eglTerminate()/eglInitialize() между двумя вызовами eglCreateWindowSurface().

В этом случае я могу использовать каждый ANativeWindow ровно один раз? Если это так, разве это не может привести к проверке соответствия ХРОНОС? Есть ли способ заставить NativeActivity воссоздать окно?

Обновленный обновленный

Оказывается, что последняя проблема была вызвана я не в состоянии назвать eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) перед уничтожением контекста и поверхности. Это привело к тому, что уничтожение было отложено до тех пор, пока поток не будет связан с контуром и поверхностью, что, конечно же, не было, поэтому вызвало логический отказ eglCreateWindowSurface() (вы не можете иметь две поверхности окна в одном и том же родном окне).

Этобит противоинтуитивный, потому что можно было бы предположить, что вызов eglTerminate() уничтожит все ресурсы EGL, но разрешено спецификацией. Имейте в виду!

ответ

1

Это не поддерживаемый случай использования. Тот факт, что он работал раньше, был удачей для вас, и это может потерпеть неудачу на некоторых устройствах. Вы можете обойти это, визуализируя 2D или 3D-контент в другом окне или отображая 2D-контент в растровом изображении, который затем используете в качестве текстуры GL и т. Д.

+0

У вас есть ссылка для ссылки на это? то есть, какая функциональность гарантирована для поддержки? –

+0

Я переписал свой код для 2D-рендеринга через OpenGL --- но он все равно не работает. Детали в теле. Предложения с благодарностью оценили ... –

+0

Не могли бы вы показать свой код, пожалуйста? Уничтожение/воссоздание поверхности окна - это то, что делает аппаратный рендеринг довольно часто. Почему вы разрушаете свою поверхность? –

0

Вы можете переключиться с OpenGL для рендеринга CPU (ANativeWindow_lock), и наоборот, но вы должны освободить использованную Surface с Surface.release() и создать новую из вашей SurfaceTexture для другого API.

Example app