OpenGL thread and CVDisplayLink


#1

Hi,

juce_OpenGLContext.cpp has many "#if ! JUCE_ANDROID"s because in Android JUCE does not create a thread for OpenGL rendering, and registers callbacks instead.

My co-worker (as well as Apple's docs*) claims that in OS X too one should register render callbacks (via CVDisplayLink) to get better behavior wrt garanteeing that frames are rendered per screen frames.

I made a small commit which defines JUCE_OPENGL_CREATE_JUCE_RENDER_THREAD instead of using "! JUCE_ANDROID" at https://github.com/soundradix/JUCE/commit/480da77d09fc6cf5cedfb593e2ee7680dfbb54b0

The goal is to then change the osx implementation to use CVDisplayLink and so that JUCE_OPENGL_CREATE_JUCE_RENDER_THREAD will not be set in os x too and it will use CVDisplayLink.

Can you take a look at this change and hopefully incorporate it into JUCE if you like it?

This commit also makes OpenGLContext::CachedImage not inherit from Thread on Android (where the thread is never started), and has some related changes.

Note that I have not tested my changes on Android and don't have an Android device to test on..

Cheers, Yair

* https://developer.apple.com/library/mac/qa/qa1385/_index.html


#2

Thanks - this seems pretty sensible stuff, I can certainly use this flag instead of hard-wiring it to android.


#3

Thanks for the quick response!

W
hile trying to add CVDisplayLink, I noticed some possible issues in Android regarding shutdown (both before and after the patch):

* I can't find a place calling shutdownOnThread / openGLContextClosing other than OpenGLContext::CachedImage::run which never ran in Android

* A possible deadlock on shutdown wrt to "mmLock = new MessageManagerLock (Thread::getCurrentThread());" in renderFrame. Thread::getCurrentThread() returns nullptr in CVDisplayLink threads, and probably returns the same in the Android render callbacks. This makes MessageManagerLock use "enter" rather than "tryEnter", and the component destruction's unregistering of the callback may wait until the render callback is finished, causing a deadlock. Before the patch it used "this" rather than "Thread::getCurrentThread()",  which is weird given that "this" is a thread that never starts (on Android).

Cheers, Yair


#4

Unfortunately this patch has caused problems with Android and OpenGL.  The main issue stems from the use of mmLock = new MessageManagerLock (Thread::getCurrentThread());  which doesn't work properly when called in the context of the android opengl thread, since it was never created with JUCE and getCurrentThread() does not return a proper value.

I will revert most of this,  and report back my findings.


#5

Actually, it's worse than this, because getCurrentThread appears to return random *other* existing threads in the system... and is definitely inappropriate for this use, which causes JNI assertions and other madness.


#6

Well, there may be something else afoot causing the crashing issues that several of us are seeing related to suspend/resume detach/attach opengl contexts, as reverting this patch didn't solve the issue.  However, I still have concerns about the use of getCurrentThread() here....  

Refer to this thread: http://www.juce.com/forum/topic/sigsegv-postmessagetosystemqueue-callstack

[EDIT]: see the link above for code fix and resolution of the crashing issue


#7

So ... there is currently no cross-platform vsync callback implemented in JUCE?

In that case how is GL/graphics rendering done? Just some generic 60Hz Timer creating paint events?