OpenGLComponent always on top even when it shouldn't be


#1

Let’s say my app has a standard DocumentWindow as the main window, and then it has two DocumentWindows as child components of the main content component. So basically there are two small windows floating around inside the big main window, sort of like an MDI.

Here’s the problem. If one of the child DocumentWindows has an OpenGLComponent, the OpenGLComponent always stays on top, even when I click on the other child DocumentWindow and drag it over the OpenGLComponent. Why is the OpenGLComponent always on top? The weird thing is that the window borders don’t stay on top, which is the correct behavior. It’s only the OpenGL itself that stays on top.

Here’s more or less what I’m doing (code modified slightly for clarity). I was just hacking around the Juce Demo app so that anyone can quickly see what I’m talking about. Just add this code to JuceDemoApplication::initialize(). And you’ll need to change the MainDemoWindow to just have a normal Component as the main content component.

		DocumentWindow *d = new DocumentWindow("test", Colours::grey, DocumentWindow::closeButton, false);
		d->setContentNonOwned(createOpenGLDemo(), true);
		d->setBounds(0, 0, 400, 300);
		theMainWindow.getContentComponent()->addAndMakeVisible(d);
 		
		d = new DocumentWindow("test", Colours::grey, DocumentWindow::closeButton, false);
		d->setContentNonOwned(createWidgetsDemo(), true);
		d->setBounds(0, 0, 400, 300);
		theMainWindow.getContentComponent()->addAndMakeVisible(d);

Any help appreciated!


#2

Anyone?


#3

Behind each Juce ::OpenGLComponent there is an hidden Juce ::ComponentPeer (a native Window) created on top of the juce::Component, that’s why component clipping is not supported by Juce but by the underlying OS. Underlying OS only know Juce top Components (with binded ComponentPeer) .So child Juce::Component clipping with OpenGL Windows are not supported.

I think it’s an unresolvable problem. Except if you decide to render your GL output in a juce::Image and draw it manualy in a standard Juce::Component.

(OpenGLComponent is deprecated in Juce 2 in favor of OpenGLRenderer and OpenGLContext, but the problem stay the same)


#4

Sorry, when I said “OpenGLComponent” it was just a force of habit :). I was doing my tests using Juce 2, and as you said, the problem is still there.

Perhaps it would be possible to solve this by having the option of any Component being backed by a native window, even if that Component doesn’t have OpenGL in it?


#5

You are right, but for cross-plateform UI portabillity, Juce take the good design choice to manage sub-component by itself. This design introduce your problem.

Another painful solution is to make your TopWindow be OpenGL.
Juce 2 introduce the ability to draw Component on top on OpenGL rendered context.
With that, all sub-component (Your DocumentWindows) will be clipped correctly by Juce.

  • The fist big problem is that you could not have child OpenGL Component in it.
    So your DocumentWindows and it’s owner must not draw anything and let the underlying OpenGLRender drawing appear !

  • Another problem is to follow the DocumentWindows bounds in the OpenGLRender drawing methods.
    And finally if you already have different OpenGLContext to draw per DocumentWindows you need to perform off screen rendering and share them with the top one for drawing.

So, in my humble opinion, the first solution of offscreen rendering in a juce::Image and drawing it in a non OpenGL Component seems to be the simple way to fix your problem.


#6

But wouldn’t that be considerably slower? Because there’d be an extra step in copying the texture from an OpenGL context to a Juce::Image.


#7

It’s slower than a simple drawing, and it takes more VRAM, you are right.
But depending on your need, your hardware and your will of optimization, it can be enough.

Combining FBO for off screen rendering and using PBO to download texture in RAM is a common thing.
With DMA and modern GPU, the hardware perform this task relatively quickly.

Good luck


#8

TBH I must remember to fix it so that when your top-level window is GL-based, you can still use subcomponents that can render GL independently - that’d be fairly easy to do by giving each one a FB to draw into, and just compositing the results.