在后台线程中初始化OpenGL上下文

时间:2017-02-21 09:20:13

标签: java android opengl-es rendering

所以我遇到了解决android中屏幕外渲染问题的困难,无法找到解决方案。请记住,我是所有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方法,它仍然无法正常工作。我在这里缺少什么?

1 个答案:

答案 0 :(得分: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");
    }
}