2017-02-21 30 views
0

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

Целью этого процесса андроида является рендеринг материала на растровое изображение в фоновом потоке без видимого пользователя (таким образом, внеэкранный рендеринг). Библиотека, которую я использую для визуализации этого материала, требует, чтобы я вручную настраивал контекст OpenGL, прежде чем использовать методы рендеринга утилиты. Мне нужно загрузить растровое изображение в текстуру OpenGL (созданную GLES20.glGenTextures (..)) после инициализации контекста OpenGL и привязки его к потоку. Однако я не могу подробно рассказать о библиотеке.

Проблема: я не знаю, как настроить контекст OpenGL в android без использования GLSurfaceView, и каждый поиск для него перенаправляет меня на какое-то решение, основанное именно на этом SurfaceView. Поэтому мне нужна начальная точка, чтобы выяснить, как делать вызовы GLES20, действующие в фоновом потоке.

То, что я знаю, что мне нужно использовать методы, предоставляемые EGL14, чтобы установить его:

eglCreateContext(...); 
eglMakeCurrent(...); 
eglInitialize(...); 

Но поскольку документация рода не существует у меня есть проблемы, выяснить, какие параметры использовать, или даже в какой комбинации/порядке их использования.

Любая помощь очень ценится.

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


EDIT 2:

Таким образом, после рытья еще немного я наткнулся на что-то выглядит довольно прилично:

mEgl = (EGL10) EGLContext.getEGL(); 

mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); 

if (mEglDisplay == EGL10.EGL_NO_DISPLAY) 
    throw new RuntimeException("Error: eglGetDisplay() Failed " 
      + GLUtils.getEGLErrorString(mEgl.eglGetError())); 

int[] version = new int[2]; 

if (!mEgl.eglInitialize(mEglDisplay, version)) 
    throw new RuntimeException("Error: eglInitialize() Failed " 
      + GLUtils.getEGLErrorString(mEgl.eglGetError())); 

maEGLconfigs = new EGLConfig[1]; 

int[] configsCount = new int[1]; 
int[] configSpec = new int[] 
     { 
       EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 
       EGL10.EGL_RED_SIZE, 8, 
       EGL10.EGL_GREEN_SIZE, 8, 
       EGL10.EGL_BLUE_SIZE, 8, 
       EGL10.EGL_ALPHA_SIZE, 8, 
       EGL10.EGL_DEPTH_SIZE, 0, 
       EGL10.EGL_STENCIL_SIZE, 0, 
       EGL10.EGL_NONE 
     }; 
if ((!mEgl.eglChooseConfig(mEglDisplay, configSpec, maEGLconfigs, 1, configsCount)) || (configsCount[0] == 0)) 
    throw new IllegalArgumentException("Error: eglChooseConfig() Failed " 
      + GLUtils.getEGLErrorString(mEgl.eglGetError())); 

if (maEGLconfigs[0] == null) 
    throw new RuntimeException("Error: eglConfig() not Initialized"); 

int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE}; 

mEglContext = mEgl.eglCreateContext(mEglDisplay, maEGLconfigs[0], EGL10.EGL_NO_CONTEXT, attrib_list); 

Следующий вызов тогда будет:

final int[] textureHandle = {0}; 
GLES20.glGenTextures(1, textureHandle, 0); 

Но textureHandle [0] все еще 0. Также он выводит на консоль ошибку:

E/libEGL: call to OpenGL ES API with no current context 

Итак, если мы проигнорируем проблему, что код использует старые методы EGL10, он по-прежнему не работает должным образом. Что мне здесь не хватает?

+0

Я не уверен, что создание контекста должно быть в классе, таком как EGL14. Контекст обычно генерируется с помощью свойства, указывающего, какую версию использовать. После этого вы используете соответствующий API. Не могли бы вы проверить из другого вопроса egl.eglCreateContext. http://stackoverflow.com/questions/5930274/attribute-list-in-eglcreatecontext –

+0

Вам не хватает вызова функций eglCreateSurface и eglMakeCurrent(). Перед созданием контекста рендеринга вы должны создать поверхность, а затем после создания контекста рендеринга вы должны сделать его текущим. – gulati

+0

@MaticOblak Я не уверен, что понимаю, что вы говорите. В самом конце моего примера я делаю именно то, что вы сказали (по крайней мере, я думаю, что смотрю на ссылку, которую вы указали). А теперь я вижу, что вы написали об исходном посте без редактирования. Да, вы правы. Я просто использовал примеры EGL14.egl ....(), чтобы показать, к какому классу принадлежит класс. Я не хотел подразумевать, что они являются статическими методами. Я отредактирую свой вопрос, чтобы избежать недоразумений. –

ответ

0

Функция ниже устанавливает контекст рендеринга OpenGL ES 1.x. Вы можете изменить список атрибутов для создания контекстной функции для создания контекста рендеринга OpenGL ES 2.x

void initializeEGL() { 
    //get access to the EGL object, so that we can 
    //initialize EGL 
    mEGL = (EGL10) EGLContext.getEGL(); 

    //initialize display 
    mDisplay = mEGL.eglGetDisplay(EGL11.EGL_DEFAULT_DISPLAY); 
    if(mDisplay == EGL11.EGL_NO_DISPLAY) 
    { 
     Log.e("SimpleGLView", "Unable to get access to Native Display"); 
    } 

    int[] version = new int[2]; 
    boolean success = mEGL.eglInitialize(mDisplay, version); 
    if(!success) { 
     int error = mEGL.eglGetError(); 
     switch(error) { 
     case EGL11.EGL_NOT_INITIALIZED: 
      Log.e("SimpleGLView", "Unable to initialize the EGL sub-system"); 
      break; 
     case EGL11.EGL_BAD_DISPLAY: 
      Log.e("SimpleGLView", "Display not valid"); 
      break; 
     } 
     return; 
     } 

    int[] mConfigSpec = { EGL11.EGL_RED_SIZE, 8, 
           EGL11.EGL_GREEN_SIZE, 8, 
           EGL11.EGL_BLUE_SIZE, 8, 
           EGL11.EGL_DEPTH_SIZE, 16, 
           EGL11.EGL_STENCIL_SIZE, 8, 
           EGL11.EGL_NONE }; 
    EGLConfig[] configs = new EGLConfig[1]; 
    int[] num_config = new int[1]; 

    success = mEGL.eglChooseConfig(mDisplay, mConfigSpec, configs, 1, num_config); 
    if(success) { 
     Log.i("SimpleGLView", "Successfully acquired a surface configuration"); 
     return; 
    } 

    mConfig = configs[0]; 

    mSurface = mEGL.eglCreateWindowSurface(mDisplay,mConfig, holder, null); 
    if(mSurface == EGL11.EGL_NO_SURFACE) { 
     Log.e("SimpleGLView", "Unable to create surface"); 
     int error = mEGL.eglGetError(); 
     switch(error) { 
     case EGL11.EGL_BAD_CONFIG: 
      Log.e("SimpleGLView", "Invalid configuration selected"); 
      break; 
     case EGL11.EGL_BAD_NATIVE_WINDOW: 
      Log.e("SimpleGLView", "Bad native window used"); 
      break; 
     case EGL11.EGL_BAD_ALLOC: 
      Log.e("SimpleGLView", "Not enough resources to create a surface"); 
      break; 
     } 
     return; 
    } 

    mContext = mEGL.eglCreateContext(mDisplay, mConfig, EGL11.EGL_NO_CONTEXT, null); 
    if(mContext == null) { 
     Log.i("SimpleGLView", "Create Context failed"); 
     return; 
    } 

    success = mEGL.eglMakeCurrent(mDisplay, mSurface, mSurface, mContext); 
    if(success) { 
     Log.i("SimpleGLView", "Made current"); 
    } 
} 
+0

Фрагмент, начинающийся в строке 35 кода, кажется мне странным. Почему я хочу вызвать return, если я успешно выбрал конфигурацию? Выполнение этого не создало бы допустимый контекст для потока, так как mEGL.eglMakeCurrent (...) не будет вызван или мне что-то не хватает? –

+1

В любом случае я нашел способ заставить его работать для моих целей, ваш код мне очень помог, спасибо! Я приму ваш ответ и опубликую отредактированную его версию как ответ, как только я закончу и довожу его –

+0

Вы правы, что возврат не требуется. Не знаю, как это получилось :). Спасибо за исправление ошибки. – gulati