我想在本机代码上在
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);
解决方法
您正在尝试使用仅在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
更新:
以下是一些创建屏幕外表面的示例代码:
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); }