[android] schedule work on the gl thread using GLSurfaceView#queueEvent
This commit is contained in:
committed by
Ivo van Dongen
parent
347d7c19c0
commit
15a47d116a
@@ -28,6 +28,7 @@ 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.renderer.GlSurfaceViewRenderThread;
|
||||
import com.mapbox.mapboxsdk.maps.widgets.CompassView;
|
||||
import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
|
||||
import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
|
||||
@@ -312,6 +313,8 @@ public class MapView extends FrameLayout {
|
||||
});
|
||||
glSurfaceView.setRenderMode(RENDERMODE_WHEN_DIRTY);
|
||||
glSurfaceView.setVisibility(View.VISIBLE);
|
||||
|
||||
nativeMapView.setRenderThread(new GlSurfaceViewRenderThread(glSurfaceView));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -494,15 +497,6 @@ public class MapView extends FrameLayout {
|
||||
// Rendering
|
||||
//
|
||||
|
||||
// Called when the map needs to be rerendered
|
||||
// Called via JNI from NativeMapView
|
||||
protected void onInvalidate() {
|
||||
if (glSurfaceView != null) {
|
||||
glSurfaceView.requestRender();
|
||||
}
|
||||
// TODO: removable? postInvalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int width, int height, int oldw, int oldh) {
|
||||
if (destroyed) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.mapbox.mapboxsdk.camera.CameraPosition;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
|
||||
import com.mapbox.mapboxsdk.geometry.ProjectedMeters;
|
||||
import com.mapbox.mapboxsdk.maps.renderer.RenderThread;
|
||||
import com.mapbox.mapboxsdk.storage.FileSource;
|
||||
import com.mapbox.mapboxsdk.style.layers.CannotAddLayerException;
|
||||
import com.mapbox.mapboxsdk.style.layers.Filter;
|
||||
@@ -52,6 +53,9 @@ final class NativeMapView implements GLSurfaceView.Renderer {
|
||||
// Used for callbacks
|
||||
private MapView mapView;
|
||||
|
||||
// Used to schedule work on the render thread
|
||||
private RenderThread renderThread;
|
||||
|
||||
//Hold a reference to prevent it from being GC'd as long as it's used on the native side
|
||||
private final FileSource fileSource;
|
||||
|
||||
@@ -69,7 +73,7 @@ final class NativeMapView implements GLSurfaceView.Renderer {
|
||||
// Constructors
|
||||
//
|
||||
|
||||
public NativeMapView(MapView mapView) {
|
||||
public NativeMapView(final MapView mapView) {
|
||||
Context context = mapView.getContext();
|
||||
fileSource = FileSource.getInstance(context);
|
||||
|
||||
@@ -84,6 +88,10 @@ final class NativeMapView implements GLSurfaceView.Renderer {
|
||||
// Methods
|
||||
//
|
||||
|
||||
public void setRenderThread(RenderThread renderThread) {
|
||||
this.renderThread = renderThread;
|
||||
}
|
||||
|
||||
private boolean isDestroyedOn(String callingMethod) {
|
||||
if (destroyed && !TextUtils.isEmpty(callingMethod)) {
|
||||
Timber.e(
|
||||
@@ -104,7 +112,8 @@ final class NativeMapView implements GLSurfaceView.Renderer {
|
||||
if (isDestroyedOn("update")) {
|
||||
return;
|
||||
}
|
||||
nativeUpdate();
|
||||
|
||||
requestRender();
|
||||
}
|
||||
|
||||
public void render() {
|
||||
@@ -864,9 +873,28 @@ final class NativeMapView implements GLSurfaceView.Renderer {
|
||||
// Callbacks
|
||||
//
|
||||
|
||||
protected void onInvalidate() {
|
||||
if (mapView != null) {
|
||||
mapView.onInvalidate();
|
||||
/**
|
||||
* Called from JNI whenever the native map
|
||||
* needs rendering.
|
||||
*/
|
||||
protected void requestRender() {
|
||||
if (renderThread != null) {
|
||||
renderThread.requestRender();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from JNI when work needs to be processed on
|
||||
* the Renderer Thread.
|
||||
*/
|
||||
protected void requestProcessing() {
|
||||
if (renderThread != null) {
|
||||
renderThread.queueEvent(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
nativeProcess();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -905,6 +933,8 @@ final class NativeMapView implements GLSurfaceView.Renderer {
|
||||
|
||||
private native void nativeDestroy();
|
||||
|
||||
private native void nativeProcess();
|
||||
|
||||
private native void nativeInitializeDisplay();
|
||||
|
||||
private native void nativeTerminateDisplay();
|
||||
@@ -1130,9 +1160,7 @@ final class NativeMapView implements GLSurfaceView.Renderer {
|
||||
void addSnapshotCallback(@NonNull MapboxMap.SnapshotReadyCallback callback) {
|
||||
snapshotReadyCallback = callback;
|
||||
scheduleTakeSnapshot();
|
||||
mapView.onInvalidate();
|
||||
// TODO. this should do a request render
|
||||
//render();
|
||||
renderThread.requestRender();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.mapbox.mapboxsdk.maps.renderer;
|
||||
|
||||
import android.opengl.GLSurfaceView;
|
||||
|
||||
/**
|
||||
* {@link RenderThread} implementation that schedules using the
|
||||
* {@link GLSurfaceView} thread.
|
||||
*/
|
||||
public class GlSurfaceViewRenderThread implements RenderThread {
|
||||
private final GLSurfaceView surfaceView;
|
||||
|
||||
public GlSurfaceViewRenderThread(GLSurfaceView surfaceView) {
|
||||
this.surfaceView = surfaceView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestRender() {
|
||||
surfaceView.requestRender();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queueEvent(Runnable runnable) {
|
||||
surfaceView.queueEvent(runnable);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.mapbox.mapboxsdk.maps.renderer;
|
||||
|
||||
/**
|
||||
* Created by ivo on 11/09/2017.
|
||||
*/
|
||||
|
||||
public interface RenderThread {
|
||||
|
||||
void requestRender();
|
||||
|
||||
void queueEvent(Runnable runnable);
|
||||
}
|
||||
@@ -44,20 +44,18 @@ public:
|
||||
|
||||
// Only safe on the GL Thread
|
||||
void process() {
|
||||
while (true) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
|
||||
if (queue.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto scheduled = queue.front();
|
||||
queue.pop();
|
||||
|
||||
lock.unlock();
|
||||
|
||||
Mailbox::maybeReceive(scheduled);
|
||||
if (queue.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto scheduled = queue.front();
|
||||
queue.pop();
|
||||
|
||||
lock.unlock();
|
||||
|
||||
Mailbox::maybeReceive(scheduled);
|
||||
}
|
||||
|
||||
// Only safe to access on the GL Thread
|
||||
|
||||
@@ -58,10 +58,11 @@ AndroidRendererFrontend::AndroidRendererFrontend(float pixelRatio,
|
||||
FileSource& fileSource,
|
||||
Scheduler& scheduler,
|
||||
std::string programCacheDir,
|
||||
InvalidateCallback invalidate)
|
||||
RequestRenderCallback requestRender,
|
||||
RequestProcessingCallback requestProcessing)
|
||||
: backend(std::make_unique<AndroidRendererBackend>())
|
||||
, glThread(std::make_unique<AndroidGLThread>(
|
||||
invalidate,
|
||||
std::move(requestProcessing),
|
||||
*backend,
|
||||
pixelRatio,
|
||||
fileSource,
|
||||
@@ -69,8 +70,8 @@ AndroidRendererFrontend::AndroidRendererFrontend(float pixelRatio,
|
||||
GLContextMode::Unique,
|
||||
programCacheDir
|
||||
))
|
||||
, asyncInvalidate([=]() {
|
||||
invalidate();
|
||||
, asyncInvalidate([requestRender=std::move(requestRender)]() {
|
||||
requestRender();
|
||||
})
|
||||
, mapRunLoop(util::RunLoop::Get()) {
|
||||
}
|
||||
@@ -112,9 +113,6 @@ void AndroidRendererFrontend::render() {
|
||||
params = updateParameters;
|
||||
}
|
||||
|
||||
// Process the gl thread mailbox
|
||||
glThread->process();
|
||||
|
||||
// Activate the backend
|
||||
BackendScope backendGuard { *backend };
|
||||
|
||||
@@ -130,6 +128,11 @@ void AndroidRendererFrontend::render() {
|
||||
glThread->renderer->render(*params);
|
||||
}
|
||||
|
||||
void AndroidRendererFrontend::process() {
|
||||
// Process the gl thread mailbox
|
||||
glThread->process();
|
||||
}
|
||||
|
||||
void AndroidRendererFrontend::onLowMemory() {
|
||||
assert (glThread);
|
||||
glThread->actor().invoke(&Renderer::onLowMemory);
|
||||
|
||||
@@ -30,13 +30,15 @@ class AndroidRendererBackend;
|
||||
|
||||
class AndroidRendererFrontend : public RendererFrontend {
|
||||
public:
|
||||
using InvalidateCallback = std::function<void ()>;
|
||||
using RequestRenderCallback = std::function<void ()>;
|
||||
using RequestProcessingCallback = std::function<void ()>;
|
||||
|
||||
AndroidRendererFrontend(float pixelRatio,
|
||||
mbgl::FileSource&,
|
||||
mbgl::Scheduler&,
|
||||
std::string programCacheDir,
|
||||
InvalidateCallback);
|
||||
RequestRenderCallback,
|
||||
RequestProcessingCallback);
|
||||
~AndroidRendererFrontend() override;
|
||||
|
||||
void reset() override;
|
||||
@@ -46,6 +48,7 @@ public:
|
||||
|
||||
// Called from OpenGL Thread
|
||||
void render();
|
||||
void process();
|
||||
|
||||
// Feature querying
|
||||
std::vector<Feature> queryRenderedFeatures(const ScreenCoordinate&, const RenderedQueryOptions&) const;
|
||||
|
||||
@@ -78,7 +78,8 @@ NativeMapView::NativeMapView(jni::JNIEnv& _env,
|
||||
*threadPool,
|
||||
jni::Make<std::string>(_env,
|
||||
_programCacheDir),
|
||||
[this] { this->invalidate(); });
|
||||
[this] { this->requestRender(); },
|
||||
[this] { this->requestProcessing(); });
|
||||
|
||||
// Create the core map
|
||||
map = std::make_unique<mbgl::Map>(*rendererFrontend, *this,
|
||||
@@ -97,17 +98,23 @@ NativeMapView::~NativeMapView() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to java NativeMapView#onInvalidate().
|
||||
* Callback to java NativeMapView#requestRender().
|
||||
*
|
||||
* Called to invalidate the View and schedule a render on the next
|
||||
* Called to schedule a render on the next
|
||||
* runloop iteration.
|
||||
*/
|
||||
void NativeMapView::invalidate() {
|
||||
void NativeMapView::requestRender() {
|
||||
android::UniqueEnv _env = android::AttachEnv();
|
||||
static auto onInvalidate = javaClass.GetMethod<void ()>(*_env, "onInvalidate");
|
||||
static auto onInvalidate = javaClass.GetMethod<void ()>(*_env, "requestRender");
|
||||
javaPeer->Call(*_env, onInvalidate);
|
||||
}
|
||||
|
||||
void NativeMapView::requestProcessing() {
|
||||
android::UniqueEnv _env = android::AttachEnv();
|
||||
static auto requestProcessing = javaClass.GetMethod<void ()>(*_env, "requestProcessing");
|
||||
javaPeer->Call(*_env, requestProcessing);
|
||||
}
|
||||
|
||||
/**
|
||||
* From mbgl::RendererBackend. Callback to java NativeMapView#onMapChanged(int).
|
||||
*
|
||||
@@ -195,8 +202,9 @@ void NativeMapView::render(jni::JNIEnv& ) {
|
||||
updateFps();
|
||||
}
|
||||
|
||||
void NativeMapView::update(jni::JNIEnv&) {
|
||||
invalidate();
|
||||
// Called from the OpenGL renderer thread
|
||||
void NativeMapView::process(jni::JNIEnv&) {
|
||||
rendererFrontend->process();
|
||||
}
|
||||
|
||||
void NativeMapView::resizeView(jni::JNIEnv&, int w, int h) {
|
||||
@@ -1004,7 +1012,7 @@ void NativeMapView::registerNative(jni::JNIEnv& env) {
|
||||
"nativeInitialize",
|
||||
"nativeDestroy",
|
||||
METHOD(&NativeMapView::render, "nativeRender"),
|
||||
METHOD(&NativeMapView::update, "nativeUpdate"),
|
||||
METHOD(&NativeMapView::process, "nativeProcess"),
|
||||
METHOD(&NativeMapView::resizeView, "nativeResizeView"),
|
||||
METHOD(&NativeMapView::resizeFramebuffer, "nativeResizeFramebuffer"),
|
||||
METHOD(&NativeMapView::getStyleUrl, "nativeGetStyleUrl"),
|
||||
|
||||
@@ -73,7 +73,10 @@ public:
|
||||
void onSourceChanged(mbgl::style::Source&) override;
|
||||
|
||||
// Signal the view system, we want to redraw
|
||||
void invalidate();
|
||||
void requestRender();
|
||||
|
||||
// Request processing on the GL Thread
|
||||
void requestProcessing();
|
||||
|
||||
// JNI //
|
||||
|
||||
@@ -81,9 +84,10 @@ public:
|
||||
void onSurfaceCreated(jni::JNIEnv&);
|
||||
|
||||
// Called on OpenGL Thread
|
||||
void render(jni::JNIEnv&);
|
||||
void process(jni::JNIEnv&);
|
||||
|
||||
void update(jni::JNIEnv&);
|
||||
// Called on OpenGL Thread
|
||||
void render(jni::JNIEnv&);
|
||||
|
||||
void resizeView(jni::JNIEnv&, int, int);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user