Android initializes openGL2.0 context with EGL

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

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

The first is for on-screen processing, the second is for off-screen, so I use EGL_PIXMAP_BIT as follows:

// 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); 

Failed to execute the code in step 5, it seems Android does not support screen processing? Type EGL_PIXMAP_BIT is not supported.!

+6
source share
1 answer

You are trying to use EGL options that just don't work on Android, and pbuffers only work on some GPUs, not on Nvidia Tegra. pi32ConfigAttribs[] should look like this, regardless of whether it is 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 the way they support external EGLSurfaces. They defined their own pixmap type named EGL_NATIVE_BUFFER_ANDROID .

To create an EGL surface that is off-screen on Android, create a SurfaceTexture and pass it to eglCreateWindowSurface() . You should also look at the EGL Image Extension and EGL_NATIVE_BUFFER_ANDROID , as described 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 an example of code that creates an outer 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); } 
+12
source

Source: https://habr.com/ru/post/952817/


All Articles