Mapbox源码分析之地图渲染

简介:

通过源码,我们来一步步分析Mapbox地图引擎如何进行不同数据源的地图渲染的,这里是基于5.3.0的版本.

首先,我们找到地图的核心类,MapView,这个view就是用来显示地图的,它是在mapbox.mapboxsdk.maps包下,看到它的初始化之后,发现它有这么一个方法,叫做initialiseDrawingSurface(),从名字上看可以看出这是一个初始化画布的方法,我们看下它的实现.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
private void initialiseDrawingSurface(MapboxMapOptions options) {
if (options.getTextureMode()) {
TextureView textureView = new TextureView(getContext());
mapRenderer = new TextureViewMapRenderer(getContext(), textureView) {
@Override
protected void onSurfaceCreated(GL10 gl, EGLConfig config) {
MapView.this.post(new Runnable() {
@Override
public void run() {
// Initialise only once
if (mapboxMap == null) {
initialiseMap();
mapboxMap.onStart();
}
}
});
super.onSurfaceCreated(gl, config);
}
};
addView(textureView, 0);
} else {
GLSurfaceView glSurfaceView = (GLSurfaceView) findViewById(R.id.surfaceView);
glSurfaceView.setZOrderMediaOverlay(mapboxMapOptions.getRenderSurfaceOnTop());
mapRenderer = new GLSurfaceViewMapRenderer(getContext(), glSurfaceView) {
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
MapView.this.post(new Runnable() {
@Override
public void run() {
// Initialise only once
if (mapboxMap == null) {
initialiseMap();
mapboxMap.onStart();
}
}
});
super.onSurfaceCreated(gl, config);
}
};
glSurfaceView.setVisibility(View.VISIBLE);
}
nativeMapView = new NativeMapView(this, mapRenderer);
nativeMapView.resizeView(getMeasuredWidth(), getMeasuredHeight());
}

这里我们可以看出来,它首先根据选项区分使用TextureView作为view载体,还是GLSurfaceView作为view载体,然后分别讲TextureView和GLSurfaceView通过自定义的两个渲染器TextureViewMapRenderer和GLSurfaceViewMapRenderer的构造方法传递进去进行绑定.这里我们看GLSurfaceViewMapRenderer这个类.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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 onStop() {
glSurfaceView.onPause();
}
@Override
public void onStart() {
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.
* <p>
* Called from the renderer frontend to schedule a render.
*/
@Override
public void requestRender() {
glSurfaceView.requestRender();
}
/**
* May be called from any thread.
* <p>
* Schedules work to be performed on the MapRenderer thread.
*
* @param runnable the runnable to execute
*/
@Override
public void queueEvent(Runnable runnable) {
glSurfaceView.queueEvent(runnable);
}}

从这个源码我们可以看出来它并未做什么工作,只是在构造方法里做了一些基础配置,和绑定了GLSurfaceView.Renderer渲染器.其它都丢到TextureViewMapRenderer和GLSurfaceViewMapRenderer共同的父类MapRenderer里了,这里我们看下MapRenderer又做了什么

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@CallSuper
protected void onSurfaceCreated(GL10 gl, EGLConfig config) {
nativeOnSurfaceCreated();
}
@CallSuper
protected void onSurfaceChanged(GL10 gl, int width, int height) {
if (width < 0) {
throw new IllegalArgumentException("fbWidth cannot be negative.");
}
if (height < 0) {
throw new IllegalArgumentException("fbHeight cannot be negative.");
}
if (width > 65535) {
throw new IllegalArgumentException(
"fbWidth cannot be greater than 65535.");
}
if (height > 65535) {
throw new IllegalArgumentException(
"fbHeight cannot be greater than 65535.");
}
gl.glViewport(0, 0, width, height);
nativeOnSurfaceChanged(width, height);
}
@CallSuper
protected void onDrawFrame(GL10 gl) {
nativeRender();
if (onFpsChangedListener != null) {
updateFps();
}
}

我们看到MapRenderer也声明了onSurfaceCreated(),onSurfaceChanged(),onDrawFrame()方法,并加上@CallSuper注解用于子类必须调用父类这三个方法,但是我们看到他们也并未做什么,而是分别调用了native*()将实现放入底层,这样性能会更好一些,一般onSurfaceCreated()是进行一些初始化配置的工作,onSurfaceChanged()执行画面有改变的时候,onDrawFrame()执行绘制的工作.这里我们跟踪onDrawFrame()内调用的nativeRender()方法

这里我们看到与MapRenderer对应的实现底层文件map_renderer.cpp,这里我们看到它的registerNative()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void MapRenderer::registerNative(jni::JNIEnv& env) {
// Lookup the class
MapRenderer::javaClass = *jni::Class<MapRenderer>::Find(env).NewGlobalRef(env).release();
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
// Register the peer
jni::RegisterNativePeer<MapRenderer>(env, MapRenderer::javaClass, "nativePtr",
std::make_unique<MapRenderer, JNIEnv&, jni::Object<MapRenderer>, jni::Object<FileSource>, jni::jfloat, jni::String>,
"nativeInitialize", "finalize",
METHOD(&MapRenderer::render, "nativeRender"),
METHOD(&MapRenderer::onSurfaceCreated,
"nativeOnSurfaceCreated"),
METHOD(&MapRenderer::onSurfaceChanged,
"nativeOnSurfaceChanged"));
}

这里我们看到它将上层的nativeRender()方法和自己的render()方法进行绑定,我们接着看它的render()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
void MapRenderer::render(JNIEnv&) {
assert (renderer);
std::shared_ptr<UpdateParameters> params;
{
// Lock on the parameters
std::unique_lock<std::mutex> lock(updateMutex);
if (!updateParameters) return;
// Hold on to the update parameters during render
params = updateParameters;
}
// Activate the backend
BackendScope backendGuard { *backend };
// Ensure that the "current" scheduler on the render thread is
// this scheduler.
Scheduler::SetCurrent(this);
if (framebufferSizeChanged) {
backend->updateViewPort();
framebufferSizeChanged = false;
}
renderer->render(*params);
// Deliver the snapshot if requested
if (snapshotCallback) {
snapshotCallback->operator()(backend->readFramebuffer());
snapshotCallback.reset();
}
}

这里我们看到了这么一行代码renderer->render(*params);它将有关更新数据传入底层Renderer类中的render()方法,继续往下看

1
2
3
void Renderer::render(const UpdateParameters& updateParameters) {
impl->render(updateParameters);
}

这里我们看到它将实现都放到它的Impl实现类,即renderer_impl文件里.这里我们看到render()方法中这行代码

1
2
3
4
5
for (const auto& entry : renderSources) {
if (entry.second->isEnabled()) {
entry.second->startRender(parameters);
}
}

这里通过RenderSource.startRender()方法开始渲染,其startRender()方法是虚函数,其子类RenderAnnotationSource,RenderGeoJSONSource,RenderRasterSource,RenderVectorSource,RenderImageSource分别继承并实现了它.