Android: Can't create an EGL context for OpenGL-ES 3.0, Initializing EGL always returns V 1.0

Viewed 972

After I ran into this same problem while trying to write a Flutter Plugin for OpenGL ES on Android I decided to test if my code would work in a native Android Java App.

Unfortunately I see the exact same behavior. I always get EGL version V1.0 and am not able to create a EGL context for GLES 3.0 and make it current.

Already when calling eglCreateContext I get an bad attribute error unless I remove all attributes when choosing the config. In that case I can create the context and make it current but it is OpenGL V1.1 when checking the version.

When tyring to make it current I get a bad match error. I have almost the same code running on Windows and Mac and when I directly load libegl.so from Flutter using FFI to directly use the C library I get EGL V 1.4/1.5 and can create a context.

You can find the Android test project here: https://github.com/escamoteur/EGL_Test_Android_Native

I'm not an native Android developer so maybe my approach to test the code in an click handler of a button is just not legal. If so please give me a hint where to try it better. In the end this code should do some GLES off screen rendering and I need to share the context with code that directly uses the GLES c library.

This is the current code

            public void onClick(View view) {
                EGLDisplay display = EGL14.eglGetDisplay(EGL_DEFAULT_DISPLAY);
                //EGLDisplay display = EGL14.eglGetCurrentDisplay();

                int[] version = new int[2];
                boolean initializeResult = EGL14.eglInitialize(display, version, 0, version, 1);
                if (!initializeResult) {
                    int error = EGL14.eglGetError();

                    Log.i("EGL InitError", "eglInit failed");
                    return;
                }

                Log.i("FlutterWegGL", "EGL version is " + version[0] + "." + version[1]);


                int[] attribute_list = new int[]{
                        EGL_RENDERABLE_TYPE,
                        EGL_OPENGL_ES3_BIT_KHR,
                        EGL_RED_SIZE, 8,
                        EGL_GREEN_SIZE, 8,
                        EGL_BLUE_SIZE, 8,
                        EGL_ALPHA_SIZE, 8,
                        EGL_DEPTH_SIZE, 16,
                        EGL_NONE};

                int[] configsCount = new int[1];
                EGLConfig[] configs = new EGLConfig[1];
                EGLConfig config;
                boolean chooseConfigResult = EGL14.eglChooseConfig(display, attribute_list, 0, configs, 0, 1, configsCount, 0);
                if (!chooseConfigResult) {
                    Log.i("EGL InitError", "eglChooseConfig failed");
                    return;
                }

                config = configs[0];

                int[] surfaceAttributes = new int[]{
                        EGL_WIDTH, 16,
                        EGL_HEIGHT, 16,
                        EGL_NONE
                };

                // This is just a dummy surface that it needed to make an OpenGL context current (bind it to this thread)
                EGLSurface dummySurfaceForDartSide = EGL14.eglCreatePbufferSurface(display, config, surfaceAttributes, 0);
                EGLSurface dummySurfaceForPlugin = EGL14.eglCreatePbufferSurface(display, config, surfaceAttributes, 0);

                Log.i("FlutterWegGL", "EGL Error: " + EGL14.eglGetError());

                    int[] attribList = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL14.EGL_NONE};
                EGLContext eglContext = EGL14.eglCreateContext(display, config, EGL_NO_CONTEXT, attribute_list, 0);
                Log.i("FlutterWegGL", "EGL Error: " + EGL14.eglGetError());
                /// we send back the context. This might look a bit strange, but is necessary to allow this function to be called
                /// from Dart Isolates.

                if (!eglMakeCurrent(display, dummySurfaceForPlugin, dummySurfaceForPlugin, eglContext)) {
                    int eglerror = EGL14.eglGetError();

                    Log.i("FlutterWegGL", "Error: MakeCurrent " + eglerror);
                }
                String v = GLES30.glGetString(GL_VENDOR);
                int error = glGetError();
                if (error != GL_NO_ERROR)
                {

                    Log.i("FlutterWegGL", "GLError: " + error);
                }
                String r = GLES30.glGetString(GL_RENDERER);
                String v2 = GLES30.glGetString(GL_VERSION);


                Log.i("FlutterWegGL", "OpenGL initialized: Vendor:" + v + " renderer: " + r + " Version: " + v2);

I also added

    <uses-feature android:glEsVersion="0x00030000" android:required="true" />

to the manifest but it didn't change anything

And I think with this SDK settings it should be no problem to get an EGL > V1.0

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.2"

    defaultConfig {
        applicationId "com.example.egl_test"
        minSdkVersion 28
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

Update

I tried the same with the import javax.microedition.khronos.egl.EGL10 bindings and with them I can create OpenGL contexts for OpenGL-ES 3.0 without a problem.

After that I can call `EGL14.getCurrentContext' so that I can acess the native EGLContext handle

This seems to work but looks like an ugly hack

0 Answers
Related