Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Reset the native renderer only when the GL thread exits #14841

Merged
merged 1 commit into from
Jun 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import android.graphics.Bitmap;
import android.graphics.PointF;
import android.graphics.drawable.ColorDrawable;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.support.annotation.CallSuper;
import android.support.annotation.NonNull;
Expand All @@ -19,6 +18,7 @@
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;

import com.mapbox.android.gestures.AndroidGesturesManager;
import com.mapbox.mapboxsdk.MapStrictMode;
import com.mapbox.mapboxsdk.Mapbox;
Expand All @@ -29,18 +29,20 @@
import com.mapbox.mapboxsdk.location.LocationComponent;
import com.mapbox.mapboxsdk.maps.renderer.MapRenderer;
import com.mapbox.mapboxsdk.maps.renderer.glsurfaceview.GLSurfaceViewMapRenderer;
import com.mapbox.mapboxsdk.maps.renderer.glsurfaceview.MapboxGLSurfaceView;
import com.mapbox.mapboxsdk.maps.renderer.textureview.TextureViewMapRenderer;
import com.mapbox.mapboxsdk.maps.widgets.CompassView;
import com.mapbox.mapboxsdk.net.ConnectivityReceiver;
import com.mapbox.mapboxsdk.storage.FileSource;
import com.mapbox.mapboxsdk.utils.BitmapUtils;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import static com.mapbox.mapboxsdk.maps.widgets.CompassView.TIME_MAP_NORTH_ANIMATION;
import static com.mapbox.mapboxsdk.maps.widgets.CompassView.TIME_WAIT_IDLE;

Expand Down Expand Up @@ -295,7 +297,7 @@ protected void onSurfaceCreated(GL10 gl, EGLConfig config) {

addView(textureView, 0);
} else {
GLSurfaceView glSurfaceView = new GLSurfaceView(getContext());
MapboxGLSurfaceView glSurfaceView = new MapboxGLSurfaceView(getContext());
glSurfaceView.setZOrderMediaOverlay(mapboxMapOptions.getRenderSurfaceOnTop());
mapRenderer = new GLSurfaceViewMapRenderer(getContext(), glSurfaceView, localFontFamily) {
@Override
Expand Down Expand Up @@ -505,7 +507,7 @@ public boolean onGenericMotionEvent(@NonNull MotionEvent event) {
*/
@UiThread
public void onLowMemory() {
if (nativeMapView != null && mapboxMap != null && !destroyed ) {
if (nativeMapView != null && mapboxMap != null && !destroyed) {
nativeMapView.onLowMemory();
}
}
Expand Down Expand Up @@ -745,7 +747,6 @@ public void removeOnDidBecomeIdleListener(@NonNull OnDidBecomeIdleListener liste
}

/**
*
* Set a callback that's invoked when the style has finished loading.
*
* @param listener The callback that's invoked when the style has finished loading
Expand Down Expand Up @@ -801,12 +802,14 @@ public void removeOnStyleImageMissingListener(@NonNull OnStyleImageMissingListen

/**
* Set a callback that's invoked when map needs to release unused image resources.
*
* <p>
* A callback will be called only for unused images that were provided by the client via
* {@link OnStyleImageMissingListener#onStyleImageMissing(String)} listener interface.
*
* </p>
* <p>
LukasPaczos marked this conversation as resolved.
Show resolved Hide resolved
* By default, platform will remove unused images from the style. By adding listener, default
* behavior can be overridden and client can control whether to release unused resources.
* </p>
*
* @param listener The callback that's invoked when map needs to release unused image resources
*/
Expand All @@ -816,9 +819,10 @@ public void addOnCanRemoveUnusedStyleImageListener(@NonNull OnCanRemoveUnusedSty

/**
* Removes a callback that's invoked when map needs to release unused image resources.
*
* <p>
LukasPaczos marked this conversation as resolved.
Show resolved Hide resolved
* When all listeners are removed, platform will fallback to default behavior, which is to remove
* unused images from the style.
* </p>
*
* @param listener The callback that's invoked when map needs to release unused image resources
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ public void removeAnnotations(long[] ids) {
@Override
@NonNull
public long[] queryPointAnnotations(RectF rect) {
if (checkState("queryPointAnnotations") || !mapRenderer.hasSurface()) {
if (checkState("queryPointAnnotations")) {
return new long[] {};
}
return nativeQueryPointAnnotations(rect);
Expand All @@ -541,7 +541,7 @@ public long[] queryPointAnnotations(RectF rect) {
@Override
@NonNull
public long[] queryShapeAnnotations(RectF rectF) {
if (checkState("queryShapeAnnotations") || !mapRenderer.hasSurface()) {
if (checkState("queryShapeAnnotations")) {
return new long[] {};
}
return nativeQueryShapeAnnotations(rectF);
Expand Down Expand Up @@ -573,7 +573,7 @@ public void setVisibleCoordinateBounds(LatLng[] coordinates, RectF padding, doub

@Override
public void onLowMemory() {
if (checkState("onLowMemory") || !mapRenderer.hasSurface()) {
if (checkState("onLowMemory")) {
return;
}
nativeOnLowMemory();
Expand Down Expand Up @@ -890,7 +890,7 @@ public Bitmap getImage(String name) {
public List<Feature> queryRenderedFeatures(@NonNull PointF coordinates,
@Nullable String[] layerIds,
@Nullable Expression filter) {
if (checkState("queryRenderedFeatures") || !mapRenderer.hasSurface()) {
if (checkState("queryRenderedFeatures")) {
return new ArrayList<>();
}
Feature[] features = nativeQueryRenderedFeaturesForPoint(coordinates.x / pixelRatio,
Expand All @@ -903,7 +903,7 @@ public List<Feature> queryRenderedFeatures(@NonNull PointF coordinates,
public List<Feature> queryRenderedFeatures(@NonNull RectF coordinates,
@Nullable String[] layerIds,
@Nullable Expression filter) {
if (checkState("queryRenderedFeatures") || !mapRenderer.hasSurface()) {
if (checkState("queryRenderedFeatures")) {
return new ArrayList<>();
}
Feature[] features = nativeQueryRenderedFeaturesForBox(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@
import android.support.annotation.CallSuper;
import android.support.annotation.Keep;
import android.support.annotation.NonNull;

import com.mapbox.mapboxsdk.LibraryLoader;
import com.mapbox.mapboxsdk.log.Logger;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.storage.FileSource;

import java.util.concurrent.atomic.AtomicBoolean;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

Expand All @@ -34,7 +33,6 @@ public abstract class MapRenderer implements MapRendererScheduler {
private long nativePtr = 0;
private double expectedRenderTime = 0;
private MapboxMap.OnFpsChangedListener onFpsChangedListener;
protected AtomicBoolean hasSurface = new AtomicBoolean();

public MapRenderer(@NonNull Context context, String localIdeographFontFamily) {
float pixelRatio = context.getResources().getDisplayMetrics().density;
Expand Down Expand Up @@ -160,13 +158,4 @@ public void setMaximumFps(int maximumFps) {
}
expectedRenderTime = 1E9 / maximumFps;
}

/**
* Returns true if renderer has a surface to draw on.
*
* @return returns if renderer has a surface, false otherwise
*/
public boolean hasSurface() {
return hasSurface.get();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.support.annotation.NonNull;
import android.view.SurfaceHolder;

import com.mapbox.mapboxsdk.maps.renderer.MapRenderer;
import com.mapbox.mapboxsdk.maps.renderer.egl.EGLConfigChooser;
Expand All @@ -22,10 +21,10 @@
public class GLSurfaceViewMapRenderer extends MapRenderer implements GLSurfaceView.Renderer {

@NonNull
private final GLSurfaceView glSurfaceView;
private final MapboxGLSurfaceView glSurfaceView;

public GLSurfaceViewMapRenderer(Context context,
GLSurfaceView glSurfaceView,
MapboxGLSurfaceView glSurfaceView,
String localIdeographFontFamily) {
super(context, localIdeographFontFamily);
this.glSurfaceView = glSurfaceView;
Expand All @@ -34,18 +33,13 @@ public GLSurfaceViewMapRenderer(Context context,
glSurfaceView.setRenderer(this);
glSurfaceView.setRenderMode(RENDERMODE_WHEN_DIRTY);
glSurfaceView.setPreserveEGLContextOnPause(true);
glSurfaceView.getHolder().addCallback(new SurfaceHolderCallbackAdapter() {

@Override
public void surfaceCreated(SurfaceHolder holder) {
super.surfaceCreated(holder);
hasSurface.set(true);
}

glSurfaceView.setDetachedListener(new MapboxGLSurfaceView.OnGLSurfaceViewDetachedListener() {
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
super.surfaceDestroyed(holder);
hasSurface.set(false);
public void onGLSurfaceViewDetached() {
// because the GL thread is destroyed when the view is detached from window,
// we need to ensure releasing the native renderer as well.
// This avoids releasing it only when the view is being recreated, which is already on a new GL thread,
// and leads to JNI crashes like https://github.com/mapbox/mapbox-gl-native/issues/14618
nativeReset();
}
});
Expand Down Expand Up @@ -103,9 +97,6 @@ public void onDrawFrame(GL10 gl) {
*/
@Override
public void requestRender() {
if (!hasSurface.get()) {
return;
}
glSurfaceView.requestRender();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.mapbox.mapboxsdk.maps.renderer.glsurfaceview;

import android.content.Context;
import android.opengl.GLSurfaceView;
import android.support.annotation.NonNull;
import android.util.AttributeSet;

/**
* {@link GLSurfaceView} extension that notifies a listener when the view is detached from window,
* which is the point of destruction of the GL thread.
*/
public class MapboxGLSurfaceView extends GLSurfaceView {

private OnGLSurfaceViewDetachedListener detachedListener;

public MapboxGLSurfaceView(Context context) {
super(context);
}

public MapboxGLSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
}

@Override
protected void onDetachedFromWindow() {
if (detachedListener != null) {
detachedListener.onGLSurfaceViewDetached();
}
super.onDetachedFromWindow();
}

/**
* Set a listener that gets notified when the view is detached from window.
*
* @param detachedListener listener
*/
public void setDetachedListener(@NonNull OnGLSurfaceViewDetachedListener detachedListener) {
if (this.detachedListener != null) {
throw new IllegalArgumentException("Detached from window listener has been already set.");
}
this.detachedListener = detachedListener;
}

/**
* Listener interface that notifies when a {@link MapboxGLSurfaceView} is detached from window.
*/
public interface OnGLSurfaceViewDetachedListener {

/**
* Called when a {@link MapboxGLSurfaceView} is detached from window.
*/
void onGLSurfaceViewDetached();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ public TextureViewMapRenderer(@NonNull Context context,
@Override
protected void onSurfaceCreated(GL10 gl, EGLConfig config) {
super.onSurfaceCreated(gl, config);
hasSurface.set(true);
}

/**
Expand All @@ -59,7 +58,6 @@ protected void onSurfaceChanged(GL10 gl, int width, int height) {
*/
@Override
protected void onSurfaceDestroyed() {
hasSurface.set(false);
super.onSurfaceDestroyed();
}

Expand Down