Android initialise openGL2.0 context with EGL

匿名 (未验证) 提交于 2019-12-03 08:44:33

问题:

I want to do off-screen image processing on Android in native code, so I need create the openGL context in native code by EGL.

By EGL, we can create EGLSurface, I can see there are three choices there: * EGL_WINDOW_BIT * EGL_PIXMAP_BIT * EGL_BUFFER_BIT

The first one is for on-screen processing, the second one is for off-screen, so I use EGL_PIXMAP_BIT like this:

// 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, 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, 8, EGL_RED_SIZE, 8, 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, eglConfig, NULL,         ai32ContextAttribs);  // Step 8 - Bind the context to the current thread eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); 

The code failed at step 5, it seems Android doesn't support off screen processing? EGL_PIXMAP_BIT type is not supported.!

回答1:

You are trying to use EGL options that just don't work on Android and pbuffers only work on some GPUs - not Nvidia Tegra. pi32ConfigAttribs[] should look like this regardless of whether it will be on-screen or off-screen:

EGLint pi32ConfigAttribs[] =  {     EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,     EGL_RED_SIZE, 8,     EGL_GREEN_SIZE, 8,     EGL_BLUE_SIZE, 8,     EGL_ALPHA_SIZE, 8,     EGL_DEPTH_SIZE, 0,     EGL_STENCIL_SIZE, 0,     EGL_NONE }; 

Android is very inflexible in how they support off-screen EGLSurfaces. They defined their own pixmap type named EGL_NATIVE_BUFFER_ANDROID.

To create an EGL surface that is off-screen on Android, construct a SurfaceTexture and pass that to eglCreateWindowSurface(). You should also look at using the EGL Image Extension and EGL_NATIVE_BUFFER_ANDROID, as discussed here:

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

UPDATE: Here is some sample code that creates an off-screen surface:

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, 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);   }  private void CreateSurfaceEGL(SurfaceTexture surfaceTexture, int width, int height) {     surfaceTexture.setDefaultBufferSize(width, height);      mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, maEGLconfigs[0], 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, 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, mEglSurface, EGL10.EGL_WIDTH, widthResult);     mEgl.eglQuerySurface(mEglDisplay, mEglSurface, 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); } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!