OpenGLContext not rendering (or doing anything) at all?

So I have a class called Visualiser that draws a bunch of audio data and I want to attach an OpenGLContext to see if that gives me a performance boost. I have the class inherit from OpenGLAppComponent (which sets continuous painting to true) and in my constructor, I have openGLContext.setComponentPaintingEnabled(true) so it draws my paint function continuously.

But it doesn’t draw on its own. And if I trigger repaint() from a timer elsewhere, I can see in Instruments that it’s still drawing from the main thread, not an OpenGL thread. I put DBG(“foo”) inside the overriden render function and it never prints to the console so that tells me its just not working at all.

Does anybody know if I missed something?

Are you expecting it to render the Juce stuff? It’s a Open-GL window, you’ll need to create your own OpenGL code, sorry. :slight_smile: See the examples? They are good to build upon.

It should still draw in paint() if you’ve enabled setComponentPaintingEnabled(true)… but render() not being called at all sounds like something else is wrong.

Do you happen to be using either Component::setCachedComponentImage() or Component::setBufferedToImage() on the visualiser component? OpenGLContext achieves its texture updating by attaching itself to a component as a cached image object, so if you use either of those methods you may break the GL context attachment

1 Like

Hmm, it’s not that I’m opposed to writing GLSL, it’s that my colleague told me I may be able to get a performance boost from attaching an OpenGLContext even without writing shaders and such. Even the Juce docs confirm this.

Check out the description for setComponentPaintingEnabled(), it says it will draw the Juce paint method:

If this is false, then only your OpenGLRenderer will be used to perform any rendering. If true, then each time your target’s paint() method needs to be called, an OpenGLGraphicsContext will be used to render it, (after calling your OpenGLRenderer if there is one).

Yeah, that’s what I thought. Hmm, no I’m not using either of those. The only thing that’s somewhat strange although not that strange is that my visualiser is a shared pointer owned by two parents. Is there some possibility that the ownership of the context is getting jumbled or something?

That should still be fine, as long as the parents aren’t trying to each set the visualiser as a child component (if the parents are even components themselves, that is)

Your best bet is probably setting some breakpoints inside JUCE’s OpenGLContext code to see why the attachment isn’t being made. For example, your visualiser might not be meeting the requirements for this canBeAttached() method:

That method seems to be called when OpenGLContext::attachTo() is called, or if the target component has its visibility changed, or if its peer (window) changed, or if it’s moved/resized…

I would think your component would pass the requirements somewhere between all that, but you will probably have to breakpoint to see when (and why) it doesn’t pass :slight_smile:

1 Like

Great idea!

Okay this is starting to push my knowledge limits a little but I can see that context.coverrideCanAttach is false which is correct. Can’t exactly see width or height from here. I’m just posting it in case you see something I don’t…

I wonder what that overrideCanAttach is even for… it’s a private member of OpenGLContext that is always set to false and never changes from what I can see in JUCE’s source :stuck_out_tongue:

My advice would be to print the bounds and then check what boolean is actually going to be returned by that isShowingOrMinimised() function. Then you can see what’s going on a bit easier, and reset the JUCE code back when you’re done. Maybe something like:

bool canBeAttached (const Component& comp) noexcept
    // can easily see these in Xcode's debugger now
    bool showOrMinResult = isShowingOrMinimised (comp)

    // ignoring overrideCanAttach for now
    bool result = comp.getWidth() > 0 && comp.getHeight() > 0 && showOrMinResult;

    if (!result)
        jassertfalse; // force the program to stop here so we can see what's going on

    return result;

Whenever result is false and that assertion stops the program, you can check out the call stack and see when the attachment is trying to be made. If it’s happening every time there’s some sort of underlying issue…

If attachTo() fails, then adding the visualiser and making it visible fails, then resizing the visualiser fails, there must be a peer missing or some visibility setting is wrong somewhere along the line. Considering its painting normally without OpenGL though I would be surprised if that were the case!

You can find the call stack view in the left panel in Xcode, under the “hamburger” looking icon. It will show a stack trace any time the debugger has paused the running app (via assertion or breakpoints):

1 Like

This helped tremendously. Thank you so much. I’ve been grinding at it, trying different things for like two days now. Figured it was time to put it here and see if you have any more thoughts.

There is only one Visualiser but it looks like it gets created several times. Not sure why. I can still see that the render function is not called.

HOWEVER, it turns out it actually works in the standalone app only. If I open it as a standalone, suddenly the render function is getting called all over the place. Curiouser…

Okay so redoing everything such that the context is no longer a shared pointer created in the audio processor and copied by the editor and is instead created as a regular object in the editor. The editor just points to the processor to it each time it’s created. Anyways, it draws on the open gl thread now :smiley:

1 Like