eglCreateWindowSurface на ICS и переключение с 2D на 3D - PullRequest
3 голосов
/ 06 января 2012

Я пытаюсь заставить игру на основе NDK работать на Android ICS.Он отлично работал на Honeycomb и Gingerbread.

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

На Honeycomb и Gingerbread все это работало нормально.На 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 точно один раз?Если это так, разве это не провалит тесты на соответствие EGL от Khronos?Есть ли способ заставить NativeActivity воссоздать окно?прежде чем уничтожить контекст и поверхность.Это приводило к тому, что уничтожение задерживалось до тех пор, пока поток не освободил контекст и поверхность, что, конечно, не было, поэтому законный вызов eglCreateWindowSurface() не состоялся (у вас не может быть двух оконных поверхностей в одном собственном окне).).

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

Ответы [ 2 ]

1 голос
/ 06 января 2012

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

0 голосов
/ 23 февраля 2018

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

Пример приложения

...