diff --git a/android/gradle_project/allegro/src/main/java/org/liballeg/android/AllegroEGL.java b/android/gradle_project/allegro/src/main/java/org/liballeg/android/AllegroEGL.java index 0c0b91d267..1aa998f0a5 100644 --- a/android/gradle_project/allegro/src/main/java/org/liballeg/android/AllegroEGL.java +++ b/android/gradle_project/allegro/src/main/java/org/liballeg/android/AllegroEGL.java @@ -10,7 +10,8 @@ class AllegroEGL { private static final String TAG = "AllegroEGL"; - private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; + private static final int EGL_CONTEXT_MAJOR_VERSION = 0x3098; + private static final int EGL_CONTEXT_MINOR_VERSION = 0x30fb; private static final int EGL_OPENGL_ES_BIT = 1; private static final int EGL_OPENGL_ES2_BIT = 4; @@ -184,11 +185,26 @@ void egl_getConfigAttribs(int index, int ret[]) } } + private int[] versionAttribList(int major, int minor) + { + return new int[] { + EGL_CONTEXT_MAJOR_VERSION, major, + EGL_CONTEXT_MINOR_VERSION, minor, + EGL10.EGL_NONE + }; + } + + private int versionCode(int major, int minor) + { + return (major << 8) | minor; + } + /* Return values: * 0 - failure * 1 - success */ - int egl_createContext(int configIndex, boolean programmable_pipeline) + int egl_createContext(int configIndex, boolean programmable_pipeline, + int major, int minor, boolean isRequiredMajor, boolean isRequiredMinor) { Log.d(TAG, "egl_createContext"); @@ -198,21 +214,55 @@ int egl_createContext(int configIndex, boolean programmable_pipeline) matchingConfigs = null; attribMap = null; - int version = (programmable_pipeline) ? 2 : 1; - int[] attribs = { - EGL_CONTEXT_CLIENT_VERSION, version, - EGL10.EGL_NONE - }; + // we'll attempt to create a GLES context of version major.minor. + // if major == minor == 0, then the user did not request a specific version. + // minMajor.minMinor is the minimum acceptable version. + + int minMajor = (programmable_pipeline || major >= 2) ? 2 : 1; + int minMinor = 0; + + if (isRequiredMajor && major > minMajor) + minMajor = major; + if (isRequiredMinor && minor > minMinor) + minMinor = minor; + + int minVersion = versionCode(minMajor, minMinor); + int wantedVersion = versionCode(major, minor); + if (wantedVersion < minVersion) { + if(isRequiredMajor || isRequiredMinor) { + Log.d(TAG, "Can't require OpenGL ES version " + major + "." + minor); + return 0; + } + major = minMajor; + minor = minMinor; + wantedVersion = minVersion; + } + + Log.d(TAG, "egl_createContext: requesting OpenGL ES " + major + "." + minor); + + // request a GLES context version major.minor EGLContext ctx = egl.eglCreateContext(egl_Display, chosenConfig, - EGL10.EGL_NO_CONTEXT, attribs); + EGL10.EGL_NO_CONTEXT, versionAttribList(major, minor)); if (ctx == EGL10.EGL_NO_CONTEXT) { + // failed to create a GLES context of the requested version checkEglError("eglCreateContext", egl); - Log.d(TAG, "egl_createContext no context"); - return 0; + Log.d(TAG, "egl_createContext failed. min version is " + + minMajor + "." + minMinor); + + // try the min version instead, unless the user required the failed version + if ((wantedVersion == minVersion) || (EGL10.EGL_NO_CONTEXT == (ctx = + egl.eglCreateContext(egl_Display, chosenConfig, EGL10.EGL_NO_CONTEXT, + versionAttribList(minMajor, minMinor)) + ))) { + // failed again + checkEglError("eglCreateContext", egl); + Log.d(TAG, "egl_createContext no context"); + return 0; + } } - Log.d(TAG, "EGL context (OpenGL ES " + version + ") created"); + Log.d(TAG, "egl_createContext: success"); egl_Context = ctx; return 1; diff --git a/android/gradle_project/allegro/src/main/java/org/liballeg/android/AllegroSurface.java b/android/gradle_project/allegro/src/main/java/org/liballeg/android/AllegroSurface.java index 80dd12ff5d..8d9fd6d1d5 100644 --- a/android/gradle_project/allegro/src/main/java/org/liballeg/android/AllegroSurface.java +++ b/android/gradle_project/allegro/src/main/java/org/liballeg/android/AllegroSurface.java @@ -47,9 +47,11 @@ void egl_getConfigAttribs(int index, int ret[]) egl.egl_getConfigAttribs(index, ret); } - int egl_createContext(int configIndex, boolean programmable_pipeline) + int egl_createContext(int configIndex, boolean programmable_pipeline, + int major, int minor, boolean isRequiredMajor, boolean isRequiredMinor) { - return egl.egl_createContext(configIndex, programmable_pipeline); + return egl.egl_createContext(configIndex, programmable_pipeline, + major, minor, isRequiredMajor, isRequiredMinor); } boolean egl_createSurface() diff --git a/src/android/android_display.c b/src/android/android_display.c index 1148aa36d0..1dc146755b 100644 --- a/src/android/android_display.c +++ b/src/android/android_display.c @@ -241,8 +241,12 @@ static bool _al_android_init_display(JNIEnv *env, { ALLEGRO_SYSTEM_ANDROID *system = (void *)al_get_system_driver(); ALLEGRO_DISPLAY *d = (ALLEGRO_DISPLAY *)display; + const ALLEGRO_EXTRA_DISPLAY_SETTINGS *extras = &main_thread_display_settings; int config_index; bool programmable_pipeline; + int major_version, minor_version; + bool is_required_major, is_required_minor; + bool is_suggested_major, is_suggested_minor; int ret; ASSERT(system != NULL); @@ -268,10 +272,22 @@ static bool _al_android_init_display(JNIEnv *env, } programmable_pipeline = (d->flags & ALLEGRO_PROGRAMMABLE_PIPELINE); + major_version = extras->settings[ALLEGRO_OPENGL_MAJOR_VERSION]; + minor_version = extras->settings[ALLEGRO_OPENGL_MINOR_VERSION]; + is_required_major = (extras->required & ((int64_t)1 << ALLEGRO_OPENGL_MAJOR_VERSION)); + is_required_minor = (extras->required & ((int64_t)1 << ALLEGRO_OPENGL_MINOR_VERSION)); + is_suggested_major = (extras->suggested & ((int64_t)1 << ALLEGRO_OPENGL_MAJOR_VERSION)); + is_suggested_minor = (extras->suggested & ((int64_t)1 << ALLEGRO_OPENGL_MINOR_VERSION)); + + if (!is_required_major && !is_suggested_major) // "don't care" + major_version = 0; + if (!is_required_minor && !is_suggested_minor) + minor_version = 0; ALLEGRO_DEBUG("calling egl_createContext"); ret = _jni_callIntMethodV(env, display->surface_object, - "egl_createContext", "(IZ)I", config_index, programmable_pipeline); + "egl_createContext", "(IZIIZZ)I", config_index, programmable_pipeline, + major_version, minor_version, is_required_major, is_required_minor); if (!ret) { // XXX should probably destroy the AllegroSurface here ALLEGRO_ERROR("failed to create egl context!");