OpenGL ES 3.0: sanitize Android #646

This commit is contained in:
Emux 2019-03-23 13:41:54 +02:00
parent 2f27803fc5
commit a7d50fa8fa
No known key found for this signature in database
GPG Key ID: 64ED9980896038C3
2 changed files with 68 additions and 14 deletions

View File

@ -47,6 +47,9 @@ import org.oscim.utils.Parameters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
@ -61,10 +64,12 @@ public class MapView extends GLSurfaceView {
static final Logger log = LoggerFactory.getLogger(MapView.class);
private static final Pattern GL_PATTERN = Pattern.compile("OpenGL ES (\\d(\\.\\d){0,2})");
/**
* Target OpenGL ES version, if not available fall back to OpenGL ES 2.0
*/
public static int targetGLESVersion = 3;
public static double targetGLESVersion = 3.0;
private static void init() {
System.loadLibrary("vtm-jni");
@ -122,8 +127,12 @@ public class MapView extends GLSurfaceView {
mMap = new AndroidMap(this);
/* Initialize Renderer */
//setEGLContextClientVersion(targetGLESVersion);
try {
setEGLContextFactory(new GlContextFactory());
} catch (Throwable t) {
log.error("Falling back to GLES 2", t);
setEGLContextClientVersion(2);
}
setEGLConfigChooser(new GlConfigChooser());
if (GLAdapter.debug)
@ -301,16 +310,58 @@ public class MapView extends GLSurfaceView {
super(map);
}
/**
* @return GL version as [major, minor, release]
*/
private int[] extractVersion(String versionString) {
int[] version = new int[3];
Matcher matcher = GL_PATTERN.matcher(versionString);
if (matcher.find()) {
String[] split = matcher.group(1).split("\\.");
version[0] = parseInt(split[0], 2);
version[1] = split.length < 2 ? 0 : parseInt(split[1], 0);
version[2] = split.length < 3 ? 0 : parseInt(split[2], 0);
} else {
log.error("Invalid version string: " + versionString);
version[0] = 2;
version[1] = 0;
version[2] = 0;
}
return version;
}
/**
* Forgiving parsing of GL major, minor and release versions as some manufacturers don't adhere to spec.
**/
private int parseInt(String value, int defaultValue) {
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
log.error("Error parsing number: " + value + ", assuming: " + defaultValue);
return defaultValue;
}
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// Check OpenGL ES version
String versionStr = gl.glGetString(GL10.GL_VERSION);
int versionIndex = "OpenGL ES ".length();
float version = Float.parseFloat(versionStr.substring(versionIndex, versionIndex + 3));
if (version >= 3)
try {
// Create a minimum supported OpenGL ES context, then check:
String versionString = gl.glGetString(GL10.GL_VERSION);
log.info("Version: " + versionString);
// The version format is displayed as: "OpenGL ES <major>.<minor>"
// followed by optional content provided by the implementation.
// OpenGL<space>ES<space><version number><space><vendor-specific information>.
int[] version = extractVersion(versionString);
int majorVersion = version[0];
if (majorVersion >= 3)
GLAdapter.init(new AndroidGL30());
else
GLAdapter.init(new AndroidGL());
} catch (Throwable t) {
log.error("Falling back to GLES 2", t);
GLAdapter.init(new AndroidGL());
}
super.onSurfaceCreated();
}

View File

@ -1,5 +1,6 @@
/*
* Copyright 2019 Gustl22
* Copyright 2019 devemux86
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
@ -38,7 +39,9 @@ import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
/**
* See https://github.com/libgdx/libgdx/blob/master/backends/gdx-backend-android/src/com/badlogic/gdx/backends/android/surfaceview/GLSurfaceView20.java
* https://developer.android.com/guide/topics/graphics/opengl.html#version-check
* <p>
* https://github.com/libgdx/libgdx/blob/master/backends/gdx-backend-android/src/com/badlogic/gdx/backends/android/surfaceview/GLSurfaceView20.java
*/
public class GlContextFactory implements GLSurfaceView.EGLContextFactory {
@ -48,15 +51,15 @@ public class GlContextFactory implements GLSurfaceView.EGLContextFactory {
@Override
public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
log.info("creating OpenGL ES " + MapView.targetGLESVersion + ".0 context");
log.info("creating OpenGL ES " + MapView.targetGLESVersion + " context");
checkEglError("Before eglCreateContext " + MapView.targetGLESVersion, egl);
int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, MapView.targetGLESVersion, EGL10.EGL_NONE};
int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, (int) MapView.targetGLESVersion, EGL10.EGL_NONE};
EGLContext context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
boolean success = checkEglError("After eglCreateContext " + MapView.targetGLESVersion, egl);
if ((!success || context == null) && MapView.targetGLESVersion > 2) {
log.warn("Falling back to GLES 2");
MapView.targetGLESVersion = 2;
MapView.targetGLESVersion = 2.0;
return createContext(egl, display, eglConfig);
}
log.info("Returning a GLES " + MapView.targetGLESVersion + " context");