Подтвердить что ты не робот

Предотвратить onPause из разбиения контекста OpenGL

Я пишу приложение для Android, которое использует OpenGL ES (GLSurfaceView и GLSurfaceView.Renderer). Проблема в том, что когда пользователь переключает приложения и затем переключается обратно в мое приложение, GLSurfaceView уничтожает и воссоздает контекст GL. Это то, что он должен делать в соответствии с документацией, но есть ли способ предотвратить это?

Требуется много времени, чтобы загрузить текстуры в контекст, и я бы хотел, чтобы не перезагружать их.

4b9b3361

Ответ 1

Я думаю, что то, что вы ищете, обсуждается в документации GLSurfaceView:

A GLSurfaceView должен быть уведомлен, когда действие приостанавливается и возобновляется. Клиенты GLSurfaceView обязаны call onPause(), когда активность паузы и onResume(), когда активность возобновляется. Эти вызовы позволяют GLSurfaceView для приостановки и возобновления рендеринг потока, а также разрешить GLSurfaceView для выпуска и воссоздания дисплей OpenGL.

При использовании стандартного Android SDK вы должны освобождать/воссоздавать свой контекст всякий раз, когда действие приостанавливается/возобновляется (включая изменения ориентации экрана). Это не приведет к тому, что контекст GL будет выпущен и не восстановлен, когда активность будет загружена обратно в память. Помните, что мы имеем дело с очень ограниченными ресурсами (особенно на устройствах с низкой степенью сложности). Итак, короткий ответ: вы не можете предотвратить его, не нарушая ваше приложение.

Предполагая, что вы используете стандартную платформу Android/OpenGL, вам нужно сделать следующее...

В вашей деятельности убедитесь, что у вас есть следующие переопределенные методы:

public void onPause() {
    myGlSurfaceView.onPause();
}

public void onResume() {
    myGlSurfaceView.onResume();
}

Все, что вы держите вне среды GL, по-прежнему необходимо сохранить и восстановить вручную (растровые изображения, состояние игры и т.д.), для этого вам понадобятся статические поля или механизм, подобный SharedPreferences.

Update

Android 3.x предоставляет функцию сохранять контекст GL в паузе без необходимости воссоздавать. Однако есть несколько оговорок:

  • Функции Android 3.x недоступны ок. 90% устройств на рынке в настоящее время
  • Устройства также должны поддерживать несколько контекстов EGL, неясно, сколько устройств на рынке в настоящее время поддерживает это.

Используя некоторые функции API для проверки возможностей, можно использовать эту функцию на поддерживающих устройствах. Однако вам все равно придется вернуться к воссозданию контекста для остальных. На мой взгляд, до тех пор, пока больше устройств не будет работать под управлением Android 3, было бы лучше отложить использование setPreserveEGLContextOnPause и сосредоточиться на обеспечении достаточного тестирования подхода к контексту.

Ответ 2

Как уже упоминалось в комментарии выше, также можно избежать разгрома контекста GL ранее выпусков Android (1.x, 2.x), решение состоит в том, чтобы скопировать GLSurfaceView из исходного кода SDK Android-15, изменить его пакет имя, а затем используйте свою собственную копию GlSurfaceView.

Он должен работать на устройствах, поддерживающих несколько контекстов GL (за исключением чипов Adreno на данный момент), независимо от версии Android. Опасность состоит в том, что GLSurfaceView от Android-15 содержит только необходимые материалы для работы с android-15, наша версия должна обрабатывать все ОС-версии.

Мы используем собственную реализацию GlSurfaceView на основе копии ReplicaIsland, где Chriss Pruit также использовал свою собственную реализацию.

В нашей версии мы добавили setPreserveEGLContextOnPause из SDK-15, что позволяет сохранить GL-контекст, например, для одной из них, использующей Android 2.3.

Мы также изменили другие вещи в соответствии с нашими потребностями, что не имеет отношения к этому вопросу (например, 32-разрядная рендеринг на поддерживающих ее телефонах, в противном случае - 16 бит).

Наш GlSurfaceView: http://pastebin.com/U4x5JjAr

Вот оригинальная версия GlSurfaceView SDK-15, отформатированная в том же стиле (Android), что и выше http://pastebin.com/hziRmB3E (так что легко сравнивать и видеть изменения)

Не забудьте включить сохранение контекста, вызвав:

    glSurfaceView.setPreserveEGLContextOnPause(true);

Ответ 3

Начиная с уровня API 11, вы можете указать, должен ли быть сохранен ваш контекст.

Из документа:

public void setPreserveEGLContextOnPause (boolean preserveOnPause) Поскольку: Уровень API 11

Управляет сохранением контекста EGL, когда GLSurfaceView приостановлено и возобновлено.

Если установлено значение true, контекст EGL может быть сохранен, если GLSurfaceView приостановлен. Является ли контекст EGL фактически сохраненным или не зависит от того, является ли устройство Android, что программа running on может поддерживать произвольное количество контекстов EGL или нет. Устройства, которые могут поддерживать только ограниченное количество контекстов EGL, должны освободить контекст EGL, чтобы позволить нескольким приложениям делиться графическим процессором.

Если установлено значение false, контекст EGL будет выпущен, когда GLSurfaceView приостанавливается и воссоздается, когда GLSurfaceView возобновлено.

Значение по умолчанию - false.

Параметры preserveOnPause сохранить EGL контекст при паузе

Ответ 4

Прошло некоторое время с тех пор, как я работал с OpenGL, и это был стандартный сорт на ПК, но я, кажется, помню, что стандартный OpenGL не требует перезагрузки текстур при переключении контекста. Конечно, в этом случае это действительно не помогает.

Предполагая, что текстуры должны быть перезагружены, возникает вопрос: как вы ускоряете это? И тогда возникает вопрос, сколько текстуров вам нужно в любой момент и можете ли вы загрузить их по требованию? Каковы их размеры? Я помню, что полномочия двух обычно быстрее загружались, хотя это также может зависеть от реализации OpenGL и драйверов.

Я также слышал о сохранении контекста где-то там, где он не будет уничтожен, что-то вроде этого потока: опровергает проблему переключения вида просмотра