2017-02-21 70 views
0

所以我遇到了一些难题,解决了Android中的离屏渲染问题,并找不到解决方案。请记住,在所有与OpenGL相关的东西中,我都是全新的,所以如果我做出任何虚假陈述,我都会提前道歉。在后台线程中初始化OpenGL上下文

这个android过程的目标是将东西呈现到后台线程中的位图上,而用户不会看到它(因此不在屏幕上呈现)。我用来渲染这些东西的库需要我手动设置OpenGL上下文,然后才能使用实用程序渲染方法。在初始化OpenGL上下文并将其绑定到线程后,我需要将位图加载到OpenGL纹理中(由GLES20.glGenTextures(..)创建)。尽管我无法详细了解图书馆。

问题:我不知道如何在不使用GLSurfaceView的情况下在android中设置OpenGL上下文,并且每次搜索都会将我重定向到某种基于此SurfaceView的解决方案。所以我需要一个起点来弄清楚如何在后台线程中调用GLES20有效。

我知道的是,我需要通过EGL14使用所提供的方法进行设置:

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

但由于文档是一种不存在的我有麻烦搞清楚什么参数来使用,甚至在哪个组合/订单中使用它们。

任何帮助,非常感谢。

编辑:只是为了澄清,我不反对基于GLSurfaceView的解决方案,但据我所知,他们都需要在屏幕上,我绝对不能这样做。


编辑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兼容的渲染上下文。您可以修改ATTRIB列表中创建上下文功能来创建一个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

相关问题