summaryrefslogtreecommitdiff
path: root/platform/android/MapboxGLAndroidSDK/src/main/java/com
diff options
context:
space:
mode:
authorIvo van Dongen <info@ivovandongen.nl>2017-07-21 16:15:30 +0300
committerIvo van Dongen <ivovandongen@users.noreply.github.com>2017-09-22 23:33:56 +0300
commit347d7c19c0a70f91252163b14e37583eea83fdd5 (patch)
treec46968ba9fb947be6b6387ab18b10a0fede35f59 /platform/android/MapboxGLAndroidSDK/src/main/java/com
parente780cdc29ee82459a75db5aba2e72c5536a2d1b0 (diff)
downloadqtlocation-mapboxgl-347d7c19c0a70f91252163b14e37583eea83fdd5.tar.gz
[android] async rendering
- introduces GLSurfaceView - introduces Orchestration thread - renders on the gl thread
Diffstat (limited to 'platform/android/MapboxGLAndroidSDK/src/main/java/com')
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/egl/EGLConfigChooser.java293
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/egl/EGLConfigException.java21
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java179
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java51
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/Compare.java27
5 files changed, 425 insertions, 146 deletions
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
new file mode 100644
index 0000000000..7fc70716da
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/egl/EGLConfigChooser.java
@@ -0,0 +1,293 @@
+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<Config> {
+ 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<Config> 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
new file mode 100644
index 0000000000..3f576d0eda
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/egl/EGLConfigException.java
@@ -0,0 +1,21 @@
+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 4d2019d68b..a920bed720 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
@@ -1,10 +1,9 @@
package com.mapbox.mapboxsdk.maps;
import android.content.Context;
-import android.graphics.Canvas;
import android.graphics.PointF;
-import android.graphics.SurfaceTexture;
import android.os.Build;
+import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.support.annotation.CallSuper;
import android.support.annotation.IntDef;
@@ -16,10 +15,6 @@ import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
@@ -32,6 +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.egl.EGLConfigChooser;
import com.mapbox.mapboxsdk.maps.widgets.CompassView;
import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
@@ -45,10 +41,14 @@ import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
import timber.log.Timber;
import static com.mapbox.mapboxsdk.maps.widgets.CompassView.TIME_MAP_NORTH_ANIMATION;
import static com.mapbox.mapboxsdk.maps.widgets.CompassView.TIME_WAIT_IDLE;
+import static android.opengl.GLSurfaceView.RENDERMODE_WHEN_DIRTY;
/**
* <p>
@@ -72,7 +72,6 @@ public class MapView extends FrameLayout {
private NativeMapView nativeMapView;
private MapboxMapOptions mapboxMapOptions;
private boolean destroyed;
- private boolean hasSurface;
private MyLocationView myLocationView;
private CompassView compassView;
@@ -86,6 +85,8 @@ public class MapView extends FrameLayout {
private Bundle savedInstanceState;
private final CopyOnWriteArrayList<OnMapChangedListener> onMapChangedListeners = new CopyOnWriteArrayList<>();
+ private GLSurfaceView glSurfaceView;
+
@UiThread
public MapView(@NonNull Context context) {
super(context);
@@ -280,10 +281,37 @@ public class MapView extends FrameLayout {
}
private void initialiseDrawingSurface() {
- SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
- surfaceView.setZOrderMediaOverlay(mapboxMapOptions.getRenderSurfaceOnTop());
- surfaceView.getHolder().addCallback(new SurfaceCallback());
- surfaceView.setVisibility(View.VISIBLE);
+ glSurfaceView = (GLSurfaceView) findViewById(R.id.surfaceView);
+ glSurfaceView.setZOrderMediaOverlay(mapboxMapOptions.getRenderSurfaceOnTop());
+ glSurfaceView.setEGLContextClientVersion(2);
+ glSurfaceView.setEGLConfigChooser(new EGLConfigChooser());
+ glSurfaceView.setRenderer(new GLSurfaceView.Renderer() {
+
+ @Override
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ MapView.this.post(new Runnable() {
+ @Override
+ public void run() {
+ initialiseMap();
+ mapboxMap.onStart();
+ }
+ });
+
+ nativeMapView.onSurfaceCreated(gl, config);
+ }
+
+ @Override
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
+ nativeMapView.onSurfaceChanged(gl, width, height);
+ }
+
+ @Override
+ public void onDrawFrame(GL10 gl) {
+ nativeMapView.onDrawFrame(gl);
+ }
+ });
+ glSurfaceView.setRenderMode(RENDERMODE_WHEN_DIRTY);
+ glSurfaceView.setVisibility(View.VISIBLE);
}
/**
@@ -314,7 +342,9 @@ public class MapView extends FrameLayout {
*/
@UiThread
public void onResume() {
- // replaced by onStart in v5.0.0
+ if (glSurfaceView != null) {
+ glSurfaceView.onResume();
+ }
}
/**
@@ -322,7 +352,9 @@ public class MapView extends FrameLayout {
*/
@UiThread
public void onPause() {
- // replaced by onStop in v5.0.0
+ if (glSurfaceView != null) {
+ glSurfaceView.onPause();
+ }
}
/**
@@ -465,24 +497,10 @@ public class MapView extends FrameLayout {
// Called when the map needs to be rerendered
// Called via JNI from NativeMapView
protected void onInvalidate() {
- postInvalidate();
- }
-
- @Override
- public void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- if (isInEditMode()) {
- return;
+ if (glSurfaceView != null) {
+ glSurfaceView.requestRender();
}
-
- if (destroyed) {
- return;
- }
-
- if (!hasSurface) {
- return;
- }
- nativeMapView.render();
+ // TODO: removable? postInvalidate();
}
@Override
@@ -496,103 +514,6 @@ public class MapView extends FrameLayout {
}
}
- private class SurfaceCallback implements SurfaceHolder.Callback {
-
- private Surface surface;
-
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- if (nativeMapView == null) {
- nativeMapView = new NativeMapView(MapView.this);
- nativeMapView.createSurface(surface = holder.getSurface());
- nativeMapView.resizeView(getWidth(), getHeight());
- initialiseMap();
- mapboxMap.onStart();
- } else {
- nativeMapView.createSurface(surface = holder.getSurface());
- }
-
- hasSurface = true;
- }
-
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- if (destroyed) {
- return;
- }
- nativeMapView.resizeFramebuffer(width, height);
- }
-
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- hasSurface = false;
-
- if (nativeMapView != null) {
- // occurs when activity goes to background
- nativeMapView.destroySurface();
- }
- surface.release();
- }
- }
-
- // This class handles TextureView callbacks
- private class SurfaceTextureListener implements TextureView.SurfaceTextureListener {
-
- private Surface surface;
-
- // Called when the native surface texture has been created
- // Must do all EGL/GL ES initialization here
- @Override
- public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
- if (nativeMapView == null) {
- nativeMapView = new NativeMapView(MapView.this);
- nativeMapView.createSurface(this.surface = new Surface(surface));
- nativeMapView.resizeFramebuffer(width, height);
- nativeMapView.resizeView(width, height);
- initialiseMap();
- mapboxMap.onStart();
- } else {
- nativeMapView.createSurface(this.surface = new Surface(surface));
- }
-
- hasSurface = true;
- }
-
- // Called when the native surface texture has been destroyed
- // Must do all EGL/GL ES destruction here
- @Override
- public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
- hasSurface = false;
-
- if (nativeMapView != null) {
- nativeMapView.destroySurface();
- }
- this.surface.release();
- return true;
- }
-
- // Called when the format or size of the native surface texture has been changed
- // Must handle window resizing here.
- @Override
- public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
- if (destroyed) {
- return;
- }
-
- nativeMapView.resizeFramebuffer(width, height);
- }
-
- // Called when the SurfaceTexure frame is drawn to screen
- // Must sync with UI here
- @Override
- public void onSurfaceTextureUpdated(SurfaceTexture surface) {
- if (destroyed) {
- return;
- }
- mapboxMap.onUpdateRegionChange();
- }
- }
-
//
// View events
//
@@ -612,7 +533,9 @@ public class MapView extends FrameLayout {
return;
}
- if (nativeMapView != null) {
+ if (nativeMapView == null) {
+ nativeMapView = new NativeMapView(this);
+ } else if (mapZoomButtonController != null) {
mapZoomButtonController.setVisible(visibility == View.VISIBLE);
}
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
index 4f5037e4b3..a97b7cc8f2 100755
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
@@ -4,12 +4,12 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PointF;
import android.graphics.RectF;
+import android.opengl.GLSurfaceView;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.DisplayMetrics;
-import android.view.Surface;
import com.mapbox.mapboxsdk.LibraryLoader;
import com.mapbox.mapboxsdk.annotations.Icon;
@@ -35,10 +35,13 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
import timber.log.Timber;
// Class that wraps the native methods for convenience
-final class NativeMapView {
+final class NativeMapView implements GLSurfaceView.Renderer {
// Flag to indicating destroy was called
private boolean destroyed = false;
@@ -97,20 +100,6 @@ final class NativeMapView {
destroyed = true;
}
- public void createSurface(Surface surface) {
- if (isDestroyedOn("createSurface")) {
- return;
- }
- nativeCreateSurface(surface);
- }
-
- public void destroySurface() {
- if (isDestroyedOn("destroySurface")) {
- return;
- }
- nativeDestroySurface();
- }
-
public void update() {
if (isDestroyedOn("update")) {
return;
@@ -156,7 +145,7 @@ final class NativeMapView {
nativeResizeView(width, height);
}
- public void resizeFramebuffer(int fbWidth, int fbHeight) {
+ private void resizeFramebuffer(int fbWidth, int fbHeight) {
if (isDestroyedOn("resizeFramebuffer")) {
return;
}
@@ -1141,6 +1130,32 @@ final class NativeMapView {
void addSnapshotCallback(@NonNull MapboxMap.SnapshotReadyCallback callback) {
snapshotReadyCallback = callback;
scheduleTakeSnapshot();
- render();
+ mapView.onInvalidate();
+ // TODO. this should do a request render
+ //render();
+ }
+
+ //
+ // GLSurfaceView.Renderer
+ //
+
+ @Override
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ Timber.i("[%s] onSurfaceCreated", Thread.currentThread().getName());
+ //TODO: callback to map to re-create renderer?
+ }
+
+ @Override
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
+ Timber.i("[%s] onSurfaceChanged %sx%s", Thread.currentThread().getName(), width, height);
+ // Sets the current view port to the new size.
+ gl.glViewport(0, 0, width, height);
+ resizeFramebuffer(width, height);
+ // resizeView(width, height); Done from MapView#onSizeChanged
+ }
+
+ @Override
+ public void onDrawFrame(GL10 gl) {
+ nativeRender();
}
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/Compare.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/Compare.java
new file mode 100644
index 0000000000..c7d7a13a3d
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/Compare.java
@@ -0,0 +1,27 @@
+package com.mapbox.mapboxsdk.utils;
+
+/**
+ * Comparisons from std sdk, which aren't available in API level <= 15
+ */
+public class Compare {
+
+ /**
+ * @see Integer#compare(int, int)
+ * @param x left side
+ * @param y right side
+ * @return std compare value
+ */
+ public static int compare(int x, int y) {
+ return (x < y) ? -1 : ((x == y) ? 0 : 1);
+ }
+
+ /**
+ * @see Boolean#compare(boolean, boolean)
+ * @param x left side
+ * @param y right side
+ * @return std compare value
+ */
+ public static int compare(boolean x, boolean y) {
+ return (x == y) ? 0 : (x ? 1 : -1);
+ }
+}