OpenGL issue on Mac only since 6.01

We are hitting an assertion and a resultant crash in our Mac OpenGL app at the following line:

With the error:
***** GL_INVALID_VALUE at /Users/adamelemental/dev/x-io/x-IMU3/x-IMU3-GUI/JUCE/modules/juce_opengl/opengl/juce_OpenGLShaderProgram.cpp : 97

This issue appears after the following commit: https://github.com/juce-framework/JUCE/commit/270237be9ba9ff0a35f4ae71ba08f51cf265da11

Removing the #if JUCE_MAC section in setContinuousRepainting introduced in that commit fixes the issue:

void OpenGLContext::setContinuousRepainting (bool shouldContinuouslyRepaint) noexcept
{
    continuousRepaint = shouldContinuouslyRepaint;

//    #if JUCE_MAC
//     if (auto* component = getTargetComponent())
//     {
//         detach();
//         attachment.reset (new Attachment (*this, *component));
//     }
//    #endif

    triggerRepaint();
}

However I’m not sure what detach and reattach is doing there and what the implications might be for removing that code.

Stack trace:

juce::checkGLError(char const*, int) juce_opengl.cpp:216
juce::OpenGLShaderProgram::addShader(juce::String const&, unsigned int) juce_OpenGLShaderProgram.cpp:97
juce::OpenGLShaderProgram::addVertexShader(juce::String const&) juce_OpenGLShaderProgram.cpp:101
LineShader2D::create(juce::OpenGLContext&) LineShader.h:125
Plot2D::newOpenGLContextCreated() Plot2D.cpp:294
WindowOpenGLContext::addRenderingTarget(std::__1::shared_ptrjuce::OpenGLRenderer)::_0::operator()(juce::OpenGLContext&) const WindowOpenGLContext.cpp:93 decltype(std::__1::forward<WindowOpenGLContext::addRenderingTarget(std::__1::shared_ptr<juce::OpenGLRenderer>)::_0&>(fp)(std::__1::forwardjuce::OpenGLContext&(fp0))) std::__1::__invoke<WindowOpenGLContext::addRenderingTarget(std::__1::shared_ptrjuce::OpenGLRenderer)::_0&, juce::OpenGLContext&>(WindowOpenGLContext::addRenderingTarget(std::__1::shared_ptr<juce::OpenGLRenderer>)::_0&, juce::OpenGLContext&) type_traits:4361
void std::__1::__invoke_void_return_wrapper::__call<WindowOpenGLContext::addRenderingTarget(std::__1::shared_ptrjuce::OpenGLRenderer)::_0&, juce::OpenGLContext&>(WindowOpenGLContext::addRenderingTarget(std::__1::shared_ptr<juce::OpenGLRenderer>)::_0&, juce::OpenGLContext&) __functional_base:349
std::__1::__function::__alloc_func<WindowOpenGLContext::addRenderingTarget(std::__1::shared_ptrjuce::OpenGLRenderer)::_0, std::__1::allocator<WindowOpenGLContext::addRenderingTarget(std::__1::shared_ptr<juce::OpenGLRenderer>)::_0>, void (juce::OpenGLContext&)>::operator()(juce::OpenGLContext&) functional:1527
std::__1::__function::__func<WindowOpenGLContext::addRenderingTarget(std::__1::shared_ptrjuce::OpenGLRenderer)::_0, std::__1::allocator<WindowOpenGLContext::addRenderingTarget(std::__1::shared_ptr<juce::OpenGLRenderer>)::_0>, void (juce::OpenGLContext&)>::operator()(juce::OpenGLContext&) functional:1651
std::__1::__function::__value_func<void (juce::OpenGLContext&)>::operator()(juce::OpenGLContext&) const functional:1799
std::__1::function<void (juce::OpenGLContext&)>::operator()(juce::OpenGLContext&) const functional:2347
WindowOpenGLContext::renderOpenGL() WindowOpenGLContext.cpp:155
juce::OpenGLContext::CachedImage::renderFrame() juce_OpenGLContext.cpp:255
juce::OpenGLContext::CachedImage::runJob() juce_OpenGLContext.cpp:482
juce::ThreadPool::runNextJob(juce::ThreadPool::ThreadPoolThread&) juce_ThreadPool.cpp:384
juce::ThreadPool::ThreadPoolThread::run() juce_ThreadPool.cpp:36
juce::thread::threadEntryPoint() juce_Thread.cpp:96
juce::juce_threadEntryPoint(void*) juce_Thread.cpp:118
juce::threadEntryProc(void*) juce_posix_SharedCode.h:838
_pthread_body 0x00007fff77cc52eb
_pthread_start 0x00007fff77cc8249
thread_start 0x00007fff77cc440d

If necessary, I can make a small example, to reproduce the issue.

Detaching and re-attaching the context is required there for the CVLinkDisplayWrapper to be enabled/disabled depending on the continous repainting setting (we use CVDisplayLink to drive the continous repainting on macOS). A short, reproducible example would be really helpful - I did some testing of toggling continous repainting on/off on a 500ms timer in the OpenGLDemo and it doesn’t crash, so it would be interesting to see what’s triggering the crash in your code.

Hi @ed95 apologies for the delayed response!

I attach a zip of an example project, using the relevant classes from the problem app, which crashes since JUCE 6.01 when removing OpenGL “widgets”.

OpenGLCrash example.zip (33.5 KB)

Sorry for the delay. I’ve taken a look at the example project and can reproduce a crash but on a different line to you - for me it’s crashing on this line of Plot2D.cpp when you have 2 or more “widgets” and remove one of them:

glDrawArrays(GL_LINE_STRIP, 0, static_cast<GLuint> (numDatapointsExpected - 1));

I haven’t dug into it too deeply but it looks like there is something racey going on with the enabled vertex arrays, perhaps it’s referencing a deleted array from the removed widget? I don’t think this is related to the CVDisplayLink changes though.

1 Like

Thanks Ed, I finally got round to investigating this further, thanks for checking it out. I’ll report back with findings once its sorted.