OpenGLComponent features

I’ve just been making some cunning changes that mean that the OpenGLComponent can now contain other sub-components. The juce demo now shows this by adding a couple of sliders to the GL page.

Would be interested to hear of your experiences with this if you want to try it!

The overlaid child components are rendered using the openGL renderer, and their content is cached in a framebuffer, so for overlaid objects that don’t change much, this should be a very fast and simple way to do it.

I’ve had to refactor a bunch of stuff to get to this stage, so if you’re doing anything unusual and this breaks it, please let me know. Things to note are the new OpenGLComponent constructor which now takes a set of settings flags, and if you’re using the background threaded rendering mode, the sub-components won’t work (although it might actually be possible for me to get that going…)

I just tried to open the OpenGL demo in the new Juce Demo and got a crash (the call stack is useless so i’ll only paste what i got from the output console)

Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aed6c..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aed6c..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aed6c..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aea48..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aea48..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aea48..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aed6c..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aed6c..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aed6c..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aed6c..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aed6c..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aed6c..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aea48..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aea48..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aea48..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aed6c..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aed6c..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aed6c..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aed6c..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aed6c..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aed6c..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aea48..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aea48..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aea48..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aed6c..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aed6c..
Expression::EvaluationError: Unknown symbol: parent
First-chance exception at 0x7663b9bc in JuceDemo.exe: Microsoft C++ exception: juce::Expression::Helpers::EvaluationError at memory location 0x003aed6c..
'JuceDemo.exe': Loaded 'C:\Windows\SysWOW64\nvoglv32.dll', Cannot find or open the PDB file
The thread 'Win32 Thread' (0xc98) has exited with code 0 (0x0).
The thread 'Win32 Thread' (0x12fc) has exited with code 0 (0x0).
The thread 'Win32 Thread' (0x39c) has exited with code 0 (0x0).
First-chance exception at 0x69b7adc0 in JuceDemo.exe: 0xC0000005: Access violation reading location 0x00000000.
First-chance exception at 0x69b7f907 in JuceDemo.exe: 0xC0000005: Access violation reading location 0x0088bb3c.
Unhandled exception at 0x69b7f907 in JuceDemo.exe: 0xC0000005: Access violation reading location 0x0088bb3c.

Those are internal exceptions. They’re supposed to happen, it’s not a bug - just ignore them.

Yeah but after those Juce Demo crashes. So it’s hard to ignore. This happens when i choose the OpenGL demo from the list of demos.

(No, I haven’t tried the latest changes), but I have a question about OpenGL.

Is every Juce-supported platform hosting OpenGL natively? Can I assume that the user will always have
OpenGL on his/her system?

Oh, I see. Hmm. Doesn’t crash here - can you get a better stack trace?

[quote=“Mike”](No, I haven’t tried the latest changes), but I have a question about OpenGL.

Is every Juce-supported platform hosting OpenGL natively? Can I assume that the user will always have
OpenGL on his/her system?[/quote]

These days that’s probably a pretty safe bet.

I narrowed it down, the crash happens here:

    void flushQuads() noexcept
    {
        if (quadQueueActive)
        {
            if (numVertices > 0)
            {
                glDrawArrays (GL_TRIANGLES, 0, numVertices); <-- this crashes, can't step into it
                numVertices = 0;
            }

            quadQueueActive = false;
            glDisableClientState (GL_COLOR_ARRAY);
        }
    }

The stack trace when i break at that line:

>	JuceDemo.exe!juce::OpenGLRenderer::GLState::flushQuads()  Line 1134	C++
 	JuceDemo.exe!juce::OpenGLRenderer::GLState::renderImage(const juce::OpenGLTextureFromImage & image, const juce::Rectangle<int> & clip, const juce::AffineTransform & transform, float alpha, const juce::PositionedTexture * mask1, const juce::PositionedTexture * mask2, const bool replaceExistingContents, const bool isTiled)  Line 910	C++
 	JuceDemo.exe!juce::ClipRegion_RectangleList::drawImage(const juce::OpenGLTextureFromImage & source, const juce::AffineTransform & transform, float alpha, const juce::Rectangle<int> & clipArea, const juce::PositionedTexture * mask)  Line 1791	C++
 	JuceDemo.exe!juce::OpenGLRenderer::SavedState::drawImage(const juce::Image & image, const juce::AffineTransform & trans)  Line 2145 + 0x51 bytes	C++
 	JuceDemo.exe!juce::OpenGLRenderer::drawImage(const juce::Image & im, const juce::AffineTransform & t)  Line 2271 + 0x26 bytes	C++
 	JuceDemo.exe!juce::Graphics::drawImageTransformed(const juce::Image & imageToDraw, const juce::AffineTransform & transform, const bool fillAlphaChannelWithCurrentBrush)  Line 722	C++
 	JuceDemo.exe!juce::Graphics::drawImage(const juce::Image & imageToDraw, int dx, int dy, int dw, int dh, int sx, int sy, int sw, int sh, const bool fillAlphaChannelWithCurrentBrush)  Line 700 + 0xfc bytes	C++
 	JuceDemo.exe!juce::Graphics::drawImageWithin(const juce::Image & imageToDraw, const int destX, const int destY, const int destW, const int destH, const juce::RectanglePlacement & placementWithinTarget, const bool fillAlphaChannelWithCurrentBrush)  Line 684	C++
 	JuceDemo.exe!DemoOpenGLCanvas::createLogoImage()  Line 186 + 0x57 bytes	C++
 	JuceDemo.exe!DemoOpenGLCanvas::newOpenGLContextCreated()  Line 69 + 0x9 bytes	C++
 	JuceDemo.exe!juce::OpenGLComponent::updateContext()  Line 464	C++
 	JuceDemo.exe!juce::OpenGLComponent::OpenGLCachedComponentImage::paint(juce::Graphics & __formal)  Line 259	C++
 	JuceDemo.exe!juce::Component::paintWithinParentContext(juce::Graphics & g)  Line 1865	C++
 	JuceDemo.exe!juce::Component::paintComponentAndChildren(juce::Graphics & g)  Line 1931	C++
 	JuceDemo.exe!juce::Component::paintEntireComponent(juce::Graphics & g, const bool ignoreAlphaLevel)  Line 1973	C++
 	JuceDemo.exe!juce::Component::paintWithinParentContext(juce::Graphics & g)  Line 1867	C++
 	JuceDemo.exe!juce::Component::paintComponentAndChildren(juce::Graphics & g)  Line 1931	C++
 	JuceDemo.exe!juce::Component::paintEntireComponent(juce::Graphics & g, const bool ignoreAlphaLevel)  Line 1973	C++
 	JuceDemo.exe!juce::Component::paintWithinParentContext(juce::Graphics & g)  Line 1867	C++
 	JuceDemo.exe!juce::Component::paintComponentAndChildren(juce::Graphics & g)  Line 1931	C++
 	JuceDemo.exe!juce::Component::paintEntireComponent(juce::Graphics & g, const bool ignoreAlphaLevel)  Line 1973	C++
 	JuceDemo.exe!juce::ComponentPeer::handlePaint(juce::LowLevelGraphicsContext & contextToPaintTo)  Line 137	C++
 	JuceDemo.exe!juce::HWNDComponentPeer::handlePaintMessage()  Line 1367	C++
 	JuceDemo.exe!juce::HWNDComponentPeer::peerWindowProc(HWND__ * h, unsigned int message, unsigned int wParam, long lParam)  Line 2125	C++
 	JuceDemo.exe!juce::HWNDComponentPeer::windowProc(HWND__ * h, unsigned int message, unsigned int wParam, long lParam)  Line 2077 + 0x18 bytes	C++

Ok… The only time I’ve seen that happen before was when I tried sending more triangles to the GL driver than it could cope with.

In the OpenGLRenderer code there’s a maximum number of vertices:

enum { maxVerticesPerBlock = 192,

…does it help if you reduce that number? You can make it very low, try 32 or something just to see what happens.

I’ll be very pissed-off if this is true, because I couldn’t find any way to find out how many triangles the GL driver actually supports, and 192 was already a much lower number than I wanted to use!

Wow

Jules, do you have an amazon.co.uk wish list or anything similar?

Wishful thinking on my part, but it appears the allowsubcomponents only works when not using a background render thread?

True, although I think it might be possible to get that going too.

In fact, I was thinking of possibly changing it so that it always renders on a background thread, but locks the messagemanager when you paint your component, so it’d get the best of both worlds.

That didn’t help the same fault occurs, i tied in 64bits native mode and i got a more usable call stack. Though i tried it on my laptop and it worked fine, i don’t know what happens, can it be the graphics driver at fault ? I have a geforce card on the pc that causes the crash and a Intel card on the one that works.

>	JuceDemo.exe!juce::OpenGLRenderer::GLState::flushQuads()  Line 1135	C++
 	JuceDemo.exe!juce::OpenGLRenderer::GLState::renderImage(const juce::OpenGLTextureFromImage & image, const juce::Rectangle<int> & clip, const juce::AffineTransform & transform, float alpha, const juce::PositionedTexture * mask1, const juce::PositionedTexture * mask2, const bool replaceExistingContents, const bool isTiled)  Line 910	C++
 	JuceDemo.exe!juce::ClipRegion_RectangleList::drawImage(const juce::OpenGLTextureFromImage & source, const juce::AffineTransform & transform, float alpha, const juce::Rectangle<int> & clipArea, const juce::PositionedTexture * mask)  Line 1790 + 0x55 bytes	C++
 	JuceDemo.exe!juce::OpenGLRenderer::SavedState::drawImage(const juce::Image & image, const juce::AffineTransform & trans)  Line 2145 + 0x6b bytes	C++
 	JuceDemo.exe!juce::OpenGLRenderer::drawImage(const juce::Image & im, const juce::AffineTransform & t)  Line 2271 + 0x36 bytes	C++
 	JuceDemo.exe!juce::Graphics::drawImageTransformed(const juce::Image & imageToDraw, const juce::AffineTransform & transform, const bool fillAlphaChannelWithCurrentBrush)  Line 722	C++
 	JuceDemo.exe!juce::Graphics::drawImage(const juce::Image & imageToDraw, int dx, int dy, int dw, int dh, int sx, int sy, int sw, int sh, const bool fillAlphaChannelWithCurrentBrush)  Line 700 + 0x168 bytes	C++
 	JuceDemo.exe!juce::Graphics::drawImageWithin(const juce::Image & imageToDraw, const int destX, const int destY, const int destW, const int destH, const juce::RectanglePlacement & placementWithinTarget, const bool fillAlphaChannelWithCurrentBrush)  Line 684	C++
 	JuceDemo.exe!DemoOpenGLCanvas::createLogoImage()  Line 186 + 0x9d bytes	C++
 	JuceDemo.exe!DemoOpenGLCanvas::newOpenGLContextCreated()  Line 69 + 0xa bytes	C++
 	JuceDemo.exe!juce::OpenGLComponent::updateContext()  Line 464	C++
 	JuceDemo.exe!juce::OpenGLComponent::OpenGLCachedComponentImage::paint(juce::Graphics & __formal)  Line 259	C++
 	JuceDemo.exe!juce::Component::paintWithinParentContext(juce::Graphics & g)  Line 1865	C++

Yes, it definitely looks like it, if it’s crashing at that function call… I’ve really no idea what it must be objecting to!

FYI, and if I’m not mistaken - the nasa worldwind software uses opengl and might be worth taking a look at as it’s been in use for awhile…and…here’s their list of graphic card compatibility issues and notes. Perhaps you can glean some useful info there.

http://worldwindcentral.com/wiki/Video_Card_Compatibility#Open_GL_Diagnostic_for_World_Wind_Java

Yes, it’s java but perhaps it might contain useful tips-n-tricks embedded in the source code comments etc.

By the way, worldwind, like juce has a very nice api and is very easy to program and extend…

Hi Jules,

I tried the JUCE demo/opengl sample from module branch.

on 2 video card (PC):

With an onboard intel (Intel Graphics Media Accelerator HD (i5)), the opengl display blinks from gray to good image.
With an nVidia GT 330M, demo crashes in the nvidia driver (nvogl32.dll), and at this point juce is doing a wglMakeCurrent (from makeActive).

I’ll try it on other PCs, and driver version.

Since this is my first openGL experience, is it normal to just expect the drivers to crash like this?? It seems unbelievably shoddy to ship a driver that just bombs out, even if you feed it with junk data (which I’m sure I’m not doing!)

As far as I know, the driver should handle bad/incorrect calls.

But on windows opengl drivers maturity seems very bad.
For example Google has to emulate openGl over DirectX to implement WebGL.

http://code.google.com/p/angleproject/
(The goal of ANGLE is to allow Windows users to seamlessly run WebGL content by translating OpenGL ES 2.0 API calls to DirectX 9 API calls.)

Wow. The fact that a project like that exists is terrifying!

Jules, one of the most annoying crash with OGL I had to track down was due to not reseting the context for an operation (IIRC it dealed with textures) after an OGL call.
The issue was that the crash happened way later in non related context.
Here’s the code I need to make, you might have something equivalent to do.

        glAdjustAlignment(stride);
        glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);


        // Ok, use the attached shader
        glUseProgramObjectARB(shader->program);
        GLuint mode = GL_LINEAR; //GL_NEAREST;

        for( int i = 0; i < texturesCount; i+= 3)
        {
            // Select texture unit 1 as the active unit and bind the U texture.
            glActiveTexture(GL_TEXTURE1);
            GLint i = glGetUniformLocationARB(shader->program, "Utex");
            glUniform1iARB(i, 1);  // Bind Utex to texture unit 1
            glBindTexture(GL_TEXTURE_2D, textures[i+1]);

            // Set the texture parameters
            glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width / 2, height / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);

            glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, 1.0 );
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mode );
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mode );
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
            [...]
        }
        // Without this, ATI driver crash on Windows
        glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);

Also concerning the max number of triangle you can find this information with the following code (I guess it’s the right term):

GLint value;
glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &value);