From fd5f357d1d244a13c5b51b66829f47beda4ca1ed Mon Sep 17 00:00:00 2001 From: Ivo van Dongen Date: Tue, 31 Oct 2017 12:31:13 +0200 Subject: [android] move egl under renderer package --- .../com/mapbox/mapboxsdk/egl/EGLConfigChooser.java | 293 --------------------- .../mapbox/mapboxsdk/egl/EGLConfigException.java | 21 -- .../java/com/mapbox/mapboxsdk/maps/MapView.java | 2 +- .../maps/renderer/GLSurfaceViewMapRenderer.java | 84 ------ .../maps/renderer/egl/EGLConfigChooser.java | 293 +++++++++++++++++++++ .../maps/renderer/egl/EGLConfigException.java | 21 ++ .../glsurfaceview/GLSurfaceViewMapRenderer.java | 81 ++++++ 7 files changed, 396 insertions(+), 399 deletions(-) delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/egl/EGLConfigChooser.java delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/egl/EGLConfigException.java delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/GLSurfaceViewMapRenderer.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/egl/EGLConfigChooser.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/egl/EGLConfigException.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/glsurfaceview/GLSurfaceViewMapRenderer.java (limited to 'platform') diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/egl/EGLConfigChooser.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/egl/EGLConfigChooser.java deleted file mode 100644 index 7fc70716da..0000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/egl/EGLConfigChooser.java +++ /dev/null @@ -1,293 +0,0 @@ -package com.mapbox.mapboxsdk.egl; - -import android.opengl.GLSurfaceView; -import android.support.annotation.NonNull; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.egl.EGLDisplay; - -import timber.log.Timber; - -import static com.mapbox.mapboxsdk.utils.Compare.compare; -import static javax.microedition.khronos.egl.EGL10.EGL_ALPHA_MASK_SIZE; -import static javax.microedition.khronos.egl.EGL10.EGL_ALPHA_SIZE; -import static javax.microedition.khronos.egl.EGL10.EGL_BLUE_SIZE; -import static javax.microedition.khronos.egl.EGL10.EGL_BUFFER_SIZE; -import static javax.microedition.khronos.egl.EGL10.EGL_COLOR_BUFFER_TYPE; -import static javax.microedition.khronos.egl.EGL10.EGL_CONFIG_CAVEAT; -import static javax.microedition.khronos.egl.EGL10.EGL_DEPTH_SIZE; -import static javax.microedition.khronos.egl.EGL10.EGL_GREEN_SIZE; -import static javax.microedition.khronos.egl.EGL10.EGL_NONE; -import static javax.microedition.khronos.egl.EGL10.EGL_RED_SIZE; -import static javax.microedition.khronos.egl.EGL10.EGL_RENDERABLE_TYPE; -import static javax.microedition.khronos.egl.EGL10.EGL_RGB_BUFFER; -import static javax.microedition.khronos.egl.EGL10.EGL_SAMPLES; -import static javax.microedition.khronos.egl.EGL10.EGL_SAMPLE_BUFFERS; -import static javax.microedition.khronos.egl.EGL10.EGL_STENCIL_SIZE; -import static javax.microedition.khronos.egl.EGL10.EGL_SURFACE_TYPE; -import static javax.microedition.khronos.egl.EGL10.EGL_WINDOW_BIT; - -/** - * Selects the right EGLConfig needed for `mapbox-gl-native` - */ -public class EGLConfigChooser implements GLSurfaceView.EGLConfigChooser { - - /** - * Requires API level 17 - * - * @see android.opengl.EGL14.EGL_CONFORMANT; - */ - @SuppressWarnings("JavadocReference") - private static final int EGL_CONFORMANT = 0x3042; - - /** - * Requires API level 17 - * - * @see android.opengl.EGL14.EGL_OPENGL_ES2_BIT; - */ - @SuppressWarnings("JavadocReference") - private static final int EGL_OPENGL_ES2_BIT = 0x0004; - - @Override - public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { - int[] configAttribs = getConfigAttributes(); - - // Determine number of possible configurations - int[] numConfigs = getNumberOfConfigurations(egl, display, configAttribs); - if (numConfigs[0] < 1) { - Timber.e("eglChooseConfig() returned no configs."); - throw new EGLConfigException("eglChooseConfig() failed"); - } - - // Get all possible configurations - EGLConfig[] possibleConfigurations = getPossibleConfigurations(egl, display, configAttribs, numConfigs); - - // Choose best match - EGLConfig config = chooseBestMatchConfig(egl, display, possibleConfigurations); - if (config == null) { - Timber.e("No config chosen"); - throw new EGLConfigException("No config chosen"); - } - - return config; - } - - private int[] getNumberOfConfigurations(EGL10 egl, EGLDisplay display, int[] configAttributes) { - int[] numConfigs = new int[1]; - if (!egl.eglChooseConfig(display, configAttributes, null, 0, numConfigs)) { - Timber.e("eglChooseConfig(NULL) returned error %d", egl.eglGetError()); - throw new EGLConfigException("eglChooseConfig() failed"); - } - return numConfigs; - } - - private EGLConfig[] getPossibleConfigurations(EGL10 egl, EGLDisplay display, - int[] configAttributes, int[] numConfigs) { - EGLConfig[] configs = new EGLConfig[numConfigs[0]]; - if (!egl.eglChooseConfig(display, configAttributes, configs, numConfigs[0], numConfigs)) { - Timber.e("eglChooseConfig() returned error %d", egl.eglGetError()); - throw new EGLConfigException("eglChooseConfig() failed"); - } - return configs; - } - - // Quality - enum BufferFormat { - Format16Bit(3), - Format32BitNoAlpha(1), - Format32BitAlpha(2), - Format24Bit(0), - Unknown(4); - - int value; - - BufferFormat(int value) { - this.value = value; - } - } - - enum DepthStencilFormat { - Format16Depth8Stencil(1), - Format24Depth8Stencil(0); - - int value; - - DepthStencilFormat(int value) { - this.value = value; - } - } - - private EGLConfig chooseBestMatchConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs) { - class Config implements Comparable { - private final BufferFormat bufferFormat; - private final DepthStencilFormat depthStencilFormat; - private final boolean isNotConformant; - private final boolean isCaveat; - private final int index; - private final EGLConfig config; - - public Config(BufferFormat bufferFormat, DepthStencilFormat depthStencilFormat, - boolean isNotConformant, boolean isCaveat, int index, EGLConfig config) { - this.bufferFormat = bufferFormat; - this.depthStencilFormat = depthStencilFormat; - this.isNotConformant = isNotConformant; - this.isCaveat = isCaveat; - this.index = index; - this.config = config; - } - - - @Override - public int compareTo(@NonNull Config other) { - int i = compare(bufferFormat.value, other.bufferFormat.value); - if (i != 0) { - return i; - } - - i = compare(depthStencilFormat.value, other.depthStencilFormat.value); - if (i != 0) { - return i; - } - - i = compare(isNotConformant, other.isNotConformant); - if (i != 0) { - return i; - } - - i = compare(isCaveat, other.isCaveat); - if (i != 0) { - return i; - } - - i = compare(index, other.index); - if (i != 0) { - return i; - } - - return 0; - } - } - - List matches = new ArrayList<>(); - - int i = 0; - for (EGLConfig config : configs) { - i++; - - int caveat = getConfigAttr(egl, display, config, EGL_CONFIG_CAVEAT); - int conformant = getConfigAttr(egl, display, config, EGL_CONFORMANT); - int bits = getConfigAttr(egl, display, config, EGL_BUFFER_SIZE); - int red = getConfigAttr(egl, display, config, EGL_RED_SIZE); - int green = getConfigAttr(egl, display, config, EGL_GREEN_SIZE); - int blue = getConfigAttr(egl, display, config, EGL_BLUE_SIZE); - int alpha = getConfigAttr(egl, display, config, EGL_ALPHA_SIZE); - int alphaMask = getConfigAttr(egl, display, config, EGL_ALPHA_MASK_SIZE); - int depth = getConfigAttr(egl, display, config, EGL_DEPTH_SIZE); - int stencil = getConfigAttr(egl, display, config, EGL_STENCIL_SIZE); - int sampleBuffers = getConfigAttr(egl, display, config, EGL_SAMPLE_BUFFERS); - int samples = getConfigAttr(egl, display, config, EGL_SAMPLES); - - boolean configOk = (depth == 24) || (depth == 16); - configOk &= stencil == 8; - configOk &= sampleBuffers == 0; - configOk &= samples == 0; - - // Filter our configs first for depth, stencil and anti-aliasing - if (configOk) { - // Work out the config's buffer format - BufferFormat bufferFormat; - if ((bits == 16) && (red == 5) && (green == 6) && (blue == 5) && (alpha == 0)) { - bufferFormat = BufferFormat.Format16Bit; - } else if ((bits == 32) && (red == 8) && (green == 8) && (blue == 8) && (alpha == 0)) { - bufferFormat = BufferFormat.Format32BitNoAlpha; - } else if ((bits == 32) && (red == 8) && (green == 8) && (blue == 8) && (alpha == 8)) { - bufferFormat = BufferFormat.Format32BitAlpha; - } else if ((bits == 24) && (red == 8) && (green == 8) && (blue == 8) && (alpha == 0)) { - bufferFormat = BufferFormat.Format24Bit; - } else { - bufferFormat = BufferFormat.Unknown; - } - - // Work out the config's depth stencil format - DepthStencilFormat depthStencilFormat; - if ((depth == 16) && (stencil == 8)) { - depthStencilFormat = DepthStencilFormat.Format16Depth8Stencil; - } else { - depthStencilFormat = DepthStencilFormat.Format24Depth8Stencil; - } - - boolean isNotConformant = (conformant & EGL_OPENGL_ES2_BIT) != EGL_OPENGL_ES2_BIT; - boolean isCaveat = caveat != EGL_NONE; - - // Ignore formats we don't recognise - if (bufferFormat != BufferFormat.Unknown) { - matches.add(new Config(bufferFormat, depthStencilFormat, isNotConformant, isCaveat, i, config)); - } - } - - } - - // Sort - Collections.sort(matches); - - if (matches.size() == 0) { - throw new EGLConfigException("No matching configurations after filtering"); - } - - Config bestMatch = matches.get(0); - - if (bestMatch.isCaveat) { - Timber.w("Chosen config has a caveat."); - } - - if (bestMatch.isNotConformant) { - Timber.w("Chosen config is not conformant."); - } - - return bestMatch.config; - } - - private int getConfigAttr(EGL10 egl, EGLDisplay display, EGLConfig config, int attributeName) { - int[] attributevalue = new int[1]; - if (!egl.eglGetConfigAttrib(display, config, attributeName, attributevalue)) { - Timber.e("eglGetConfigAttrib(%d) returned error %d", attributeName, egl.eglGetError()); - throw new EGLConfigException("eglGetConfigAttrib() failed"); - } - return attributevalue[0]; - } - - - private int[] getConfigAttributes() { - boolean emulator = inEmulator(); - Timber.i("In emulator: %s", emulator); - - // Get all configs at least RGB 565 with 16 depth and 8 stencil - return new int[] { - EGL_CONFIG_CAVEAT, EGL_NONE, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_BUFFER_SIZE, 16, - EGL_RED_SIZE, 5, - EGL_GREEN_SIZE, 6, - EGL_BLUE_SIZE, 5, - EGL_ALPHA_SIZE, 0, - EGL_DEPTH_SIZE, 16, - EGL_STENCIL_SIZE, 8, - (emulator ? EGL_NONE : EGL_CONFORMANT), EGL_OPENGL_ES2_BIT, - (emulator ? EGL_NONE : EGL_COLOR_BUFFER_TYPE), EGL_RGB_BUFFER, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_NONE - }; - } - - /** - * Detect if we are in emulator. - */ - private boolean inEmulator() { - return System.getProperty("ro.kernel.qemu") != null; - } -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/egl/EGLConfigException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/egl/EGLConfigException.java deleted file mode 100644 index 3f576d0eda..0000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/egl/EGLConfigException.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.mapbox.mapboxsdk.egl; - -/** - * Used for EGL configuration exceptions - */ -public class EGLConfigException extends RuntimeException { - public EGLConfigException() { - } - - public EGLConfigException(String message) { - super(message); - } - - public EGLConfigException(String message, Throwable cause) { - super(message, cause); - } - - public EGLConfigException(Throwable cause) { - super(cause); - } -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java index 4fc2a1dffc..c316ea27d8 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java @@ -27,7 +27,7 @@ import com.mapbox.mapboxsdk.annotations.Annotation; import com.mapbox.mapboxsdk.annotations.MarkerViewManager; import com.mapbox.mapboxsdk.constants.MapboxConstants; import com.mapbox.mapboxsdk.constants.Style; -import com.mapbox.mapboxsdk.maps.renderer.GLSurfaceViewMapRenderer; +import com.mapbox.mapboxsdk.maps.renderer.glsurfaceview.GLSurfaceViewMapRenderer; import com.mapbox.mapboxsdk.maps.renderer.MapRenderer; import com.mapbox.mapboxsdk.maps.widgets.CompassView; import com.mapbox.mapboxsdk.maps.widgets.MyLocationView; diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/GLSurfaceViewMapRenderer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/GLSurfaceViewMapRenderer.java deleted file mode 100644 index d0ec9f9495..0000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/GLSurfaceViewMapRenderer.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.mapbox.mapboxsdk.maps.renderer; - -import android.content.Context; -import android.opengl.GLSurfaceView; - -import com.mapbox.mapboxsdk.egl.EGLConfigChooser; - -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.opengles.GL10; - -import static android.opengl.GLSurfaceView.RENDERMODE_WHEN_DIRTY; - -/** - * The {@link GLSurfaceViewMapRenderer} encapsulates the GL thread and - * {@link GLSurfaceView} specifics to render the map. - * - * @see MapRenderer - */ -public class GLSurfaceViewMapRenderer extends MapRenderer implements GLSurfaceView.Renderer { - - private final GLSurfaceView glSurfaceView; - - public GLSurfaceViewMapRenderer(Context context, GLSurfaceView glSurfaceView) { - super(context); - this.glSurfaceView = glSurfaceView; - glSurfaceView.setEGLContextClientVersion(2); - glSurfaceView.setEGLConfigChooser(new EGLConfigChooser()); - glSurfaceView.setRenderer(this); - glSurfaceView.setRenderMode(RENDERMODE_WHEN_DIRTY); - } - - @Override - public void onPause() { - if (glSurfaceView != null) { - glSurfaceView.onPause(); - } - } - - @Override - public void onResume() { - if (glSurfaceView != null) { - glSurfaceView.onResume(); - } - } - - @Override - public void onSurfaceCreated(GL10 gl, EGLConfig config) { - super.onSurfaceCreated(gl, config); - } - - @Override - public void onSurfaceChanged(GL10 gl, int width, int height) { - super.onSurfaceChanged(gl, width, height); - } - - @Override - public void onDrawFrame(GL10 gl) { - super.onDrawFrame(gl); - } - - /** - * May be called from any thread. - *

- * Called from the renderer frontend to schedule a render. - */ - @Override - public void requestRender() { - glSurfaceView.requestRender(); - } - - /** - * May be called from any thread. - *

- * Schedules work to be performed on the MapRenderer thread. - * - * @param runnable the runnable to execute - */ - @Override - public void queueEvent(Runnable runnable) { - glSurfaceView.queueEvent(runnable); - } - - -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/egl/EGLConfigChooser.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/egl/EGLConfigChooser.java new file mode 100644 index 0000000000..b6f467708f --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/egl/EGLConfigChooser.java @@ -0,0 +1,293 @@ +package com.mapbox.mapboxsdk.maps.renderer.egl; + +import android.opengl.GLSurfaceView; +import android.support.annotation.NonNull; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.egl.EGLDisplay; + +import timber.log.Timber; + +import static com.mapbox.mapboxsdk.utils.Compare.compare; +import static javax.microedition.khronos.egl.EGL10.EGL_ALPHA_MASK_SIZE; +import static javax.microedition.khronos.egl.EGL10.EGL_ALPHA_SIZE; +import static javax.microedition.khronos.egl.EGL10.EGL_BLUE_SIZE; +import static javax.microedition.khronos.egl.EGL10.EGL_BUFFER_SIZE; +import static javax.microedition.khronos.egl.EGL10.EGL_COLOR_BUFFER_TYPE; +import static javax.microedition.khronos.egl.EGL10.EGL_CONFIG_CAVEAT; +import static javax.microedition.khronos.egl.EGL10.EGL_DEPTH_SIZE; +import static javax.microedition.khronos.egl.EGL10.EGL_GREEN_SIZE; +import static javax.microedition.khronos.egl.EGL10.EGL_NONE; +import static javax.microedition.khronos.egl.EGL10.EGL_RED_SIZE; +import static javax.microedition.khronos.egl.EGL10.EGL_RENDERABLE_TYPE; +import static javax.microedition.khronos.egl.EGL10.EGL_RGB_BUFFER; +import static javax.microedition.khronos.egl.EGL10.EGL_SAMPLES; +import static javax.microedition.khronos.egl.EGL10.EGL_SAMPLE_BUFFERS; +import static javax.microedition.khronos.egl.EGL10.EGL_STENCIL_SIZE; +import static javax.microedition.khronos.egl.EGL10.EGL_SURFACE_TYPE; +import static javax.microedition.khronos.egl.EGL10.EGL_WINDOW_BIT; + +/** + * Selects the right EGLConfig needed for `mapbox-gl-native` + */ +public class EGLConfigChooser implements GLSurfaceView.EGLConfigChooser { + + /** + * Requires API level 17 + * + * @see android.opengl.EGL14.EGL_CONFORMANT; + */ + @SuppressWarnings("JavadocReference") + private static final int EGL_CONFORMANT = 0x3042; + + /** + * Requires API level 17 + * + * @see android.opengl.EGL14.EGL_OPENGL_ES2_BIT; + */ + @SuppressWarnings("JavadocReference") + private static final int EGL_OPENGL_ES2_BIT = 0x0004; + + @Override + public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { + int[] configAttribs = getConfigAttributes(); + + // Determine number of possible configurations + int[] numConfigs = getNumberOfConfigurations(egl, display, configAttribs); + if (numConfigs[0] < 1) { + Timber.e("eglChooseConfig() returned no configs."); + throw new EGLConfigException("eglChooseConfig() failed"); + } + + // Get all possible configurations + EGLConfig[] possibleConfigurations = getPossibleConfigurations(egl, display, configAttribs, numConfigs); + + // Choose best match + EGLConfig config = chooseBestMatchConfig(egl, display, possibleConfigurations); + if (config == null) { + Timber.e("No config chosen"); + throw new EGLConfigException("No config chosen"); + } + + return config; + } + + private int[] getNumberOfConfigurations(EGL10 egl, EGLDisplay display, int[] configAttributes) { + int[] numConfigs = new int[1]; + if (!egl.eglChooseConfig(display, configAttributes, null, 0, numConfigs)) { + Timber.e("eglChooseConfig(NULL) returned error %d", egl.eglGetError()); + throw new EGLConfigException("eglChooseConfig() failed"); + } + return numConfigs; + } + + private EGLConfig[] getPossibleConfigurations(EGL10 egl, EGLDisplay display, + int[] configAttributes, int[] numConfigs) { + EGLConfig[] configs = new EGLConfig[numConfigs[0]]; + if (!egl.eglChooseConfig(display, configAttributes, configs, numConfigs[0], numConfigs)) { + Timber.e("eglChooseConfig() returned error %d", egl.eglGetError()); + throw new EGLConfigException("eglChooseConfig() failed"); + } + return configs; + } + + // Quality + enum BufferFormat { + Format16Bit(3), + Format32BitNoAlpha(1), + Format32BitAlpha(2), + Format24Bit(0), + Unknown(4); + + int value; + + BufferFormat(int value) { + this.value = value; + } + } + + enum DepthStencilFormat { + Format16Depth8Stencil(1), + Format24Depth8Stencil(0); + + int value; + + DepthStencilFormat(int value) { + this.value = value; + } + } + + private EGLConfig chooseBestMatchConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs) { + class Config implements Comparable { + private final BufferFormat bufferFormat; + private final DepthStencilFormat depthStencilFormat; + private final boolean isNotConformant; + private final boolean isCaveat; + private final int index; + private final EGLConfig config; + + public Config(BufferFormat bufferFormat, DepthStencilFormat depthStencilFormat, + boolean isNotConformant, boolean isCaveat, int index, EGLConfig config) { + this.bufferFormat = bufferFormat; + this.depthStencilFormat = depthStencilFormat; + this.isNotConformant = isNotConformant; + this.isCaveat = isCaveat; + this.index = index; + this.config = config; + } + + + @Override + public int compareTo(@NonNull Config other) { + int i = compare(bufferFormat.value, other.bufferFormat.value); + if (i != 0) { + return i; + } + + i = compare(depthStencilFormat.value, other.depthStencilFormat.value); + if (i != 0) { + return i; + } + + i = compare(isNotConformant, other.isNotConformant); + if (i != 0) { + return i; + } + + i = compare(isCaveat, other.isCaveat); + if (i != 0) { + return i; + } + + i = compare(index, other.index); + if (i != 0) { + return i; + } + + return 0; + } + } + + List matches = new ArrayList<>(); + + int i = 0; + for (EGLConfig config : configs) { + i++; + + int caveat = getConfigAttr(egl, display, config, EGL_CONFIG_CAVEAT); + int conformant = getConfigAttr(egl, display, config, EGL_CONFORMANT); + int bits = getConfigAttr(egl, display, config, EGL_BUFFER_SIZE); + int red = getConfigAttr(egl, display, config, EGL_RED_SIZE); + int green = getConfigAttr(egl, display, config, EGL_GREEN_SIZE); + int blue = getConfigAttr(egl, display, config, EGL_BLUE_SIZE); + int alpha = getConfigAttr(egl, display, config, EGL_ALPHA_SIZE); + int alphaMask = getConfigAttr(egl, display, config, EGL_ALPHA_MASK_SIZE); + int depth = getConfigAttr(egl, display, config, EGL_DEPTH_SIZE); + int stencil = getConfigAttr(egl, display, config, EGL_STENCIL_SIZE); + int sampleBuffers = getConfigAttr(egl, display, config, EGL_SAMPLE_BUFFERS); + int samples = getConfigAttr(egl, display, config, EGL_SAMPLES); + + boolean configOk = (depth == 24) || (depth == 16); + configOk &= stencil == 8; + configOk &= sampleBuffers == 0; + configOk &= samples == 0; + + // Filter our configs first for depth, stencil and anti-aliasing + if (configOk) { + // Work out the config's buffer format + BufferFormat bufferFormat; + if ((bits == 16) && (red == 5) && (green == 6) && (blue == 5) && (alpha == 0)) { + bufferFormat = BufferFormat.Format16Bit; + } else if ((bits == 32) && (red == 8) && (green == 8) && (blue == 8) && (alpha == 0)) { + bufferFormat = BufferFormat.Format32BitNoAlpha; + } else if ((bits == 32) && (red == 8) && (green == 8) && (blue == 8) && (alpha == 8)) { + bufferFormat = BufferFormat.Format32BitAlpha; + } else if ((bits == 24) && (red == 8) && (green == 8) && (blue == 8) && (alpha == 0)) { + bufferFormat = BufferFormat.Format24Bit; + } else { + bufferFormat = BufferFormat.Unknown; + } + + // Work out the config's depth stencil format + DepthStencilFormat depthStencilFormat; + if ((depth == 16) && (stencil == 8)) { + depthStencilFormat = DepthStencilFormat.Format16Depth8Stencil; + } else { + depthStencilFormat = DepthStencilFormat.Format24Depth8Stencil; + } + + boolean isNotConformant = (conformant & EGL_OPENGL_ES2_BIT) != EGL_OPENGL_ES2_BIT; + boolean isCaveat = caveat != EGL_NONE; + + // Ignore formats we don't recognise + if (bufferFormat != BufferFormat.Unknown) { + matches.add(new Config(bufferFormat, depthStencilFormat, isNotConformant, isCaveat, i, config)); + } + } + + } + + // Sort + Collections.sort(matches); + + if (matches.size() == 0) { + throw new EGLConfigException("No matching configurations after filtering"); + } + + Config bestMatch = matches.get(0); + + if (bestMatch.isCaveat) { + Timber.w("Chosen config has a caveat."); + } + + if (bestMatch.isNotConformant) { + Timber.w("Chosen config is not conformant."); + } + + return bestMatch.config; + } + + private int getConfigAttr(EGL10 egl, EGLDisplay display, EGLConfig config, int attributeName) { + int[] attributevalue = new int[1]; + if (!egl.eglGetConfigAttrib(display, config, attributeName, attributevalue)) { + Timber.e("eglGetConfigAttrib(%d) returned error %d", attributeName, egl.eglGetError()); + throw new EGLConfigException("eglGetConfigAttrib() failed"); + } + return attributevalue[0]; + } + + + private int[] getConfigAttributes() { + boolean emulator = inEmulator(); + Timber.i("In emulator: %s", emulator); + + // Get all configs at least RGB 565 with 16 depth and 8 stencil + return new int[] { + EGL_CONFIG_CAVEAT, EGL_NONE, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_BUFFER_SIZE, 16, + EGL_RED_SIZE, 5, + EGL_GREEN_SIZE, 6, + EGL_BLUE_SIZE, 5, + EGL_ALPHA_SIZE, 0, + EGL_DEPTH_SIZE, 16, + EGL_STENCIL_SIZE, 8, + (emulator ? EGL_NONE : EGL_CONFORMANT), EGL_OPENGL_ES2_BIT, + (emulator ? EGL_NONE : EGL_COLOR_BUFFER_TYPE), EGL_RGB_BUFFER, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + } + + /** + * Detect if we are in emulator. + */ + private boolean inEmulator() { + return System.getProperty("ro.kernel.qemu") != null; + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/egl/EGLConfigException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/egl/EGLConfigException.java new file mode 100644 index 0000000000..d5a1c9951f --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/egl/EGLConfigException.java @@ -0,0 +1,21 @@ +package com.mapbox.mapboxsdk.maps.renderer.egl; + +/** + * Used for EGL configuration exceptions + */ +public class EGLConfigException extends RuntimeException { + public EGLConfigException() { + } + + public EGLConfigException(String message) { + super(message); + } + + public EGLConfigException(String message, Throwable cause) { + super(message, cause); + } + + public EGLConfigException(Throwable cause) { + super(cause); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/glsurfaceview/GLSurfaceViewMapRenderer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/glsurfaceview/GLSurfaceViewMapRenderer.java new file mode 100644 index 0000000000..ba2e118faa --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/glsurfaceview/GLSurfaceViewMapRenderer.java @@ -0,0 +1,81 @@ +package com.mapbox.mapboxsdk.maps.renderer.glsurfaceview; + +import android.content.Context; +import android.opengl.GLSurfaceView; + +import com.mapbox.mapboxsdk.maps.renderer.MapRenderer; +import com.mapbox.mapboxsdk.maps.renderer.egl.EGLConfigChooser; + +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; + +import static android.opengl.GLSurfaceView.RENDERMODE_WHEN_DIRTY; + +/** + * The {@link GLSurfaceViewMapRenderer} encapsulates the GL thread and + * {@link GLSurfaceView} specifics to render the map. + * + * @see MapRenderer + */ +public class GLSurfaceViewMapRenderer extends MapRenderer implements GLSurfaceView.Renderer { + + private final GLSurfaceView glSurfaceView; + + public GLSurfaceViewMapRenderer(Context context, GLSurfaceView glSurfaceView) { + super(context); + this.glSurfaceView = glSurfaceView; + glSurfaceView.setEGLContextClientVersion(2); + glSurfaceView.setEGLConfigChooser(new EGLConfigChooser()); + glSurfaceView.setRenderer(this); + glSurfaceView.setRenderMode(RENDERMODE_WHEN_DIRTY); + } + + @Override + public void onPause() { + glSurfaceView.onPause(); + } + + @Override + public void onResume() { + glSurfaceView.onResume(); + } + + @Override + public void onSurfaceCreated(GL10 gl, EGLConfig config) { + super.onSurfaceCreated(gl, config); + } + + @Override + public void onSurfaceChanged(GL10 gl, int width, int height) { + super.onSurfaceChanged(gl, width, height); + } + + @Override + public void onDrawFrame(GL10 gl) { + super.onDrawFrame(gl); + } + + /** + * May be called from any thread. + *

+ * Called from the renderer frontend to schedule a render. + */ + @Override + public void requestRender() { + glSurfaceView.requestRender(); + } + + /** + * May be called from any thread. + *

+ * Schedules work to be performed on the MapRenderer thread. + * + * @param runnable the runnable to execute + */ + @Override + public void queueEvent(Runnable runnable) { + glSurfaceView.queueEvent(runnable); + } + + +} -- cgit v1.2.1