Android使用EGL初始化openGL2.0上下文

我想在本机代码上在 Android上进行屏幕外图像处理,因此我需要通过EGL在本机代码中创建openGL上下文.

通过EGL,我们可以创建EGLSurface,我可以看到有三种选择:
* EGL_WINDOW_BIT
* EGL_PIXMAP_BIT
* EGL_BUFFER_BIT

第一个用于屏幕处理,第二个用于屏幕外,因此我使用EGL_PIXMAP_BIT,如下所示:

// Step 1 - Get the default display.
EGLDisplay eglDisplay = eglGetDisplay((EGLNativeDisplayType) 0);
if ((eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY) {
    LOGH("eglGetDisplay() returned error %d",eglGetError());
    exit(-1);
}

// Step 2 - Initialize EGL.
if (!eglInitialize(eglDisplay,0)) {
    LOGH("eglInitialize() returned error %d",eglGetError());
    exit(-1);
}

// Step 3 - Make OpenGL ES the current API.
eglBindAPI(EGL_OPENGL_ES_API);

// Step 4 - Specify the required configuration attributes.
EGLint pi32ConfigAttribs[] = { EGL_SURFACE_TYPE,EGL_PIXMAP_BIT,EGL_BLUE_SIZE,8,EGL_GREEN_SIZE,EGL_RED_SIZE,EGL_NONE,EGL_BIND_TO_TEXTURE_RGBA,EGL_TRUE };

// Step 5 - Find a config that matches all requirements.
int iConfigs;
EGLConfig eglConfig;
eglChooseConfig(eglDisplay,pi32ConfigAttribs,&eglConfig,1,&iConfigs);
if (iConfigs != 1) {
    LOGH(
            "Error: eglChooseConfig(): config not found %d - %d.\n",eglGetError(),iConfigs);
    exit(-1);
}

// Step 6 - Create a surface to draw to.
EGLSurface eglSurface = eglCreatePbufferSurface(eglDisplay,eglConfig,NULL);

// Step 7 - Create a context.
EGLContext eglContext = eglCreateContext(eglDisplay,NULL,ai32ContextAttribs);

// Step 8 - Bind the context to the current thread
eglMakeCurrent(eglDisplay,eglSurface,eglContext);

代码在第5步失败了,似乎Android不支持屏幕外处理?不支持EGL_PIXMAP_BIT类型.

解决方法

您正在尝试使用仅在Android上无法运行的EGL选项,而pbuffers仅适用于某些GPU – 而不是Nvidia Tegra. pi32ConfigAttribs []看起来应该是这样的,无论它是在屏幕上还是在屏幕外:
EGLint pi32ConfigAttribs[] = 
{
    EGL_RENDERABLE_TYPE,EGL_OPENGL_ES2_BIT,EGL_ALPHA_SIZE,EGL_DEPTH_SIZE,EGL_STENCIL_SIZE,EGL_NONE
};

Android在支持屏幕外EGLSurfaces方面非常缺乏灵活性.他们定义了自己的名为EGL_NATIVE_BUFFER_ANDROID的pixmap类型.

要在Android上创建一个离屏的EGL表面,请构造一个SurfaceTexture并将其传递给eglCreateWindowSurface().您还应该查看使用EGL图像扩展和EGL_NATIVE_BUFFER_ANDROID,如下所述:

http://software.intel.com/en-us/articles/using-opengl-es-to-accelerate-apps-with-legacy-2d-guis

http://software.intel.com/en-us/articles/porting-opengl-games-to-android-on-intel-atom-processors-part-1

更新:
以下是一些创建屏幕外表面的示例代码:

private EGL10 mEgl;
private EGLConfig[] maEGLconfigs;
private EGLDisplay mEglDisplay = null;
private EGLContext mEglContext = null;
private EGLSurface mEglSurface = null;
private EGLSurface[] maEglSurfaces = new EGLSurface[MAX_SURFACES];

@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture,int width,int height) 
{
    InitializeEGL();
    CreateSurfaceEGL(surfaceTexture,width,height);
}

private void InitializeEGL()
{
    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,EGL10.EGL_RED_SIZE,EGL10.EGL_GREEN_SIZE,EGL10.EGL_BLUE_SIZE,EGL10.EGL_ALPHA_SIZE,EGL10.EGL_DEPTH_SIZE,EGL10.EGL_STENCIL_SIZE,EGL10.EGL_NONE
    };
    if ((!mEgl.eglChooseConfig(mEglDisplay,configSpec,maEGLconfigs,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);  
}

private void CreateSurfaceEGL(SurfaceTexture surfaceTexture,int height)
{
    surfaceTexture.setDefaultBufferSize(width,height);

    mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay,surfaceTexture,null);

    if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE)
    {
        int error = mEgl.eglGetError();

        if (error == EGL10.EGL_BAD_NATIVE_WINDOW)
        {
            Log.e(LOG_TAG,"Error: createWindowSurface() Returned EGL_BAD_NATIVE_WINDOW.");
            return;
        }
        throw new RuntimeException("Error: createWindowSurface() Failed " + GLUtils.getEGLErrorString(error));
    }
    if (!mEgl.eglMakeCurrent(mEglDisplay,mEglSurface,mEglContext))
        throw new RuntimeException("Error: eglMakeCurrent() Failed " + GLUtils.getEGLErrorString(mEgl.eglGetError()));

    int[] widthResult = new int[1];
    int[] heightResult = new int[1];

    mEgl.eglQuerySurface(mEglDisplay,EGL10.EGL_WIDTH,widthResult);
    mEgl.eglQuerySurface(mEglDisplay,EGL10.EGL_HEIGHT,heightResult);
    Log.i(LOG_TAG,"EGL Surface Dimensions:" + widthResult[0] + " " + heightResult[0]);
}

private void DeleteSurfaceEGL(EGLSurface eglSurface)
{
    if (eglSurface != EGL10.EGL_NO_SURFACE)
        mEgl.eglDestroySurface(mEglDisplay,eglSurface);
}

相关文章

Android 如何解决dialog弹出时无法捕捉Activity的back事件 在...
Android实现自定义带文字和图片的Button 在Android开发中经常...
Android 关于长按back键退出应用程序的实现最近在做一个Andr...
android自带的时间选择器只能精确到分,但是对于某些应用要求...