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.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.opengles.GL10;
@ -61,10 +64,12 @@ public class MapView extends GLSurfaceView {
static final Logger log = LoggerFactory.getLogger(MapView.class); 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 * 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() { private static void init() {
System.loadLibrary("vtm-jni"); System.loadLibrary("vtm-jni");
@ -122,8 +127,12 @@ public class MapView extends GLSurfaceView {
mMap = new AndroidMap(this); mMap = new AndroidMap(this);
/* Initialize Renderer */ /* Initialize Renderer */
//setEGLContextClientVersion(targetGLESVersion); try {
setEGLContextFactory(new GlContextFactory()); setEGLContextFactory(new GlContextFactory());
} catch (Throwable t) {
log.error("Falling back to GLES 2", t);
setEGLContextClientVersion(2);
}
setEGLConfigChooser(new GlConfigChooser()); setEGLConfigChooser(new GlConfigChooser());
if (GLAdapter.debug) if (GLAdapter.debug)
@ -301,16 +310,58 @@ public class MapView extends GLSurfaceView {
super(map); 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 @Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) { public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// Check OpenGL ES version try {
String versionStr = gl.glGetString(GL10.GL_VERSION); // Create a minimum supported OpenGL ES context, then check:
int versionIndex = "OpenGL ES ".length(); String versionString = gl.glGetString(GL10.GL_VERSION);
float version = Float.parseFloat(versionStr.substring(versionIndex, versionIndex + 3)); log.info("Version: " + versionString);
if (version >= 3) // The version format is displayed as: "OpenGL ES <major>.<minor>"
GLAdapter.init(new AndroidGL30()); // followed by optional content provided by the implementation.
else
// 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()); GLAdapter.init(new AndroidGL());
}
super.onSurfaceCreated(); super.onSurfaceCreated();
} }

View File

@ -1,5 +1,6 @@
/* /*
* Copyright 2019 Gustl22 * Copyright 2019 Gustl22
* Copyright 2019 devemux86
* *
* This program is free software: you can redistribute it and/or modify it under the * 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 * 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; 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 { public class GlContextFactory implements GLSurfaceView.EGLContextFactory {
@ -48,15 +51,15 @@ public class GlContextFactory implements GLSurfaceView.EGLContextFactory {
@Override @Override
public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) { 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); 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); EGLContext context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
boolean success = checkEglError("After eglCreateContext " + MapView.targetGLESVersion, egl); boolean success = checkEglError("After eglCreateContext " + MapView.targetGLESVersion, egl);
if ((!success || context == null) && MapView.targetGLESVersion > 2) { if ((!success || context == null) && MapView.targetGLESVersion > 2) {
log.warn("Falling back to GLES 2"); log.warn("Falling back to GLES 2");
MapView.targetGLESVersion = 2; MapView.targetGLESVersion = 2.0;
return createContext(egl, display, eglConfig); return createContext(egl, display, eglConfig);
} }
log.info("Returning a GLES " + MapView.targetGLESVersion + " context"); log.info("Returning a GLES " + MapView.targetGLESVersion + " context");