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

Create OpenGL on Android with GLSurfaceView #1662

Closed
kkaefer opened this issue May 29, 2015 · 18 comments
Closed

Create OpenGL on Android with GLSurfaceView #1662

kkaefer opened this issue May 29, 2015 · 18 comments
Assignees
Labels
Android Mapbox Maps SDK for Android

Comments

@kkaefer
Copy link
Member

kkaefer commented May 29, 2015

Instead of creating the OpenGL context on the C++ side, we should use the GLSurfaceView object and only use the JNI bindings to implement the GLSurfaceView.Renderer#onDrawFrame() method.

@kkaefer kkaefer added the Android Mapbox Maps SDK for Android label May 29, 2015
@hanchao
Copy link
Contributor

hanchao commented Jun 3, 2015

@incanus
Copy link
Contributor

incanus commented Jul 28, 2015

@ljbade has been researching this.

@ljbade
Copy link
Contributor

ljbade commented Jul 29, 2015

Progress being made in https://github.com/mapbox/mapbox-gl-native/tree/android-glsurfaceview

Currently compiles, have not tried running it yet.

Still lots of work remaining currently TODOed.

@ljbade
Copy link
Contributor

ljbade commented Jul 31, 2015

Progress now at the first native crash:

07-31 12:09:38.414  29174-29251/com.mapbox.mapboxgl.testapp A/libc﹕ Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 29251 (GLThread 165793)

@ljbade
Copy link
Contributor

ljbade commented Aug 7, 2015

Fixed that crash caused by something in the GL version logging. This will be moved to Java at some stage. In mean time I just commented it out.

I now get a black map but I can move it around and rotate it.

Building debug build to see what sort of GL errors we are getting.

@ljbade
Copy link
Contributor

ljbade commented Aug 7, 2015

Crashes somewhere in the GL thread at log.cpp line 38. Not sure why yet need to trace it.

But commenting out this line allows the us to get to an actual GL error which triggers an assert().

@ljbade
Copy link
Contributor

ljbade commented Aug 7, 2015

Ah it looks like it is related to the thread context stuff.

#0  basic_string (this=<optimized out>, __str=...) at ../../src/mbgl/util/thread_context.hpp:39
#1  getName () at ../../src/mbgl/util/thread_context.hpp:39
#2  mbgl::Log::record (severity=mbgl::Debug, event=mbgl::JNI, code=4294967295, msg=...) at ../../src/mbgl/platform/log.cpp:52
#3  0xa1b2c774 in mbgl::Log::record (severity=mbgl::Debug, event=mbgl::JNI, format=<optimized out>) at ../../src/mbgl/platform/log.cpp:38
#4  0xa1adae00 in Record<char const (&) [21]> (severity=mbgl::Debug, event=mbgl::JNI, args=...) at ../../include/mbgl/platform/log.hpp:59
#5  Debug<char const (&) [21]> (event=mbgl::JNI, args=...) at ../../include/mbgl/platform/log.hpp:36
#6  (anonymous namespace)::nativeSurfaceCreated (env=<optimized out>, obj=<optimized out>, nativeMapViewPtr=<optimized out>)
    at ../../android/cpp/jni.cpp:337
#7  0xa310e214 in ?? ()

@kkaefer When GLSurfaceView calls into C++ to draw a frame it does it from a thread created in Java instead of C++. What do I do to ensure the thread context stuff is correctly set up for such a thread?

@mb12
Copy link

mb12 commented Aug 7, 2015

You can call Map::renderSync. It is thread safe. It blocks the calling thread until one frame render finishes in the map thread.

@ljbade
Copy link
Contributor

ljbade commented Aug 7, 2015

@mb12 That is the function I am using.

@mb12
Copy link

mb12 commented Aug 7, 2015

Are you creating EGLContext in java using egl.eglCreateContext or in native C++ code? If you are creating it on java side, make sure that that egl.eglMakeCurrent is called on map thread from NativeMapView::activate etc.

@ljbade
Copy link
Contributor

ljbade commented Aug 10, 2015

After discussion with @kkaefer I think we may have found a fatal mismatch between the design of the native MapView and GLSurfaceView.

MapView always creates it's own GL rendering thread which needs a GL context via the activate function we override. When you call renderAsync it triggers the rendering on this thread.

GLSurfaceView also creates a GL rendering thread with a context which it uses to call the draw callback. However Java does not provide access to the EGL handle which we need in native to change the thread the GL context it bound to.

At this stage I don't think there is a workaround for this.

@incanus
Copy link
Contributor

incanus commented Aug 11, 2015

Unless I'm misunderstanding, we can do similar to what we do in iOS. Over there, we use Apple's GLKView, which is a simplified OpenGL ES managed view, with its own render thread. What we do is call renderSync, though, which blocks and calls on the GL map render thread.

@mb12
Copy link

mb12 commented Aug 11, 2015

GLKView does not create its own thread. GLSurfaceView in that sense is more like GLKViewController. Is GLSurfaceView preferred because it would help get rid of the calls to eglCreateContext, eglSwapBuffers etc.?

@incanus
Copy link
Contributor

incanus commented Aug 11, 2015

GLKView does not create its own thread.

I could be mistaken — did some brief looking into this a while back. My overall point is that we call renderSync from whatever thread and it doesn't matter what the calling thread is.

@ljbade
Copy link
Contributor

ljbade commented Aug 11, 2015

@mb12 yeah the idea was to not rely on EGL/not very well documented parts of the Android system and instead use the OpenGL solution Google support/advertise in their documentation.

However it may not be worth the pain.

@incanus It is able to be called from any thread. However the View class has activate/deactivate methods that you are supposed to override with code to bind the GL context to the Map render thread.

Currently we can use EGL to implement these methods. However with GLSurfaceView we cannot use EGL and are stuck with the context being bound to the Java render thread.

@incanus
Copy link
Contributor

incanus commented Aug 11, 2015

Aha, that's the piece I was missing!

@ljbade
Copy link
Contributor

ljbade commented Aug 11, 2015

I was doing a bit of diving in https://android.googlesource.com/platform/frameworks/base/+/master/opengl/java/android/opengl/GLSurfaceView.java

It looks like if we implement http://developer.android.com/reference/android/opengl/GLSurfaceView.EGLContextFactory.html we can grab the EGL handle which may allow us to change the bound thread.

However we then have to wrangle with getting the context unbound from the Java thread which might be possible but will be very unstable due to the design of GLSurfaceView

@ljbade
Copy link
Contributor

ljbade commented Aug 11, 2015

I think I will close for now.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Android Mapbox Maps SDK for Android
Projects
None yet
Development

No branches or pull requests

5 participants