New OpenGL classes


#1

After much longer than I expected it to take, I’ve finally checked-in my changes to the way the openGL classes work!

The TL;DR is:

  • OpenGLComponent no longer exists
  • Instead, you create an OpenGLContext object yourself, and then attach it to ANY component using the attachTo() method.
  • That’ll take care of rendering the component paint() using a GL 2D context, so you can use it to GL-accelerate the rendering on any component without needing to change the component itself.
  • If you want to use a renderOpenGL() callback, you just have to provide an object that inherits from OpenGLRenderer, and pass that to the context object to use. (Doing this means you’ll end up with something pretty similar to the way it all used to work, as OpenGLRenderer has similar callbacks to the old OpenGLComponent class)
  • Before you delete your OpenGLRenderer object or your component, you call OpenGLContext::detach() (or delete the context) to let it clean-up.
  • If you want to specify pixel formats, etc, you tell the context object about that before calling attachTo()

This new arrangement also fits with the way the Android classes work, which means that GL’s now also available on Android! (Well, on devices that support GLES 2.0)

Have a look at the juce demo for an example - in fact there are actually very few lines of code that needed to change to make that work.

Enjoy! Your feedback on whether it all works smoothly would be much appreciated, and let me know if I’ve forgotten to implement any vital bits of functionality that you need!


#2

Nice work Jules!

Everything ran smoothly for me.

Tested:
OpenGL Demo
Graphics Rendering Demo using OpenGL Renderer

Tested On:
Win 7 x64 - Geforce GT 440
Win 7 x64 - Geforce 9400m
OS X 10.7 x64 - Geforce 9400m
Win 7 x64 - Radeon HD5770

No Issues.


#3

Awesome work Jules.

Still crash though on intel series-4 integrated (two year old) systems, where the driver doesnt support some ogl extensions.


#4

Great work!

(Mac OS 10.6 NVIDIA GeForce 9400)


#5

Very cool!

Quick test on a MacBook pro, first running OS X 10.7, then bootcamp’ed to Windows 7 32 bit both looked good.

I’ll try Android and iOS on devices soon.


#6

Amazing job! I couldn’t spot any difference in the rendering demos when switching to the OpenGL rendering, and all rendering times seem to decrease significantly (as long as I don’t enable clipping).

Win 7 64bit / Geforce 8400 GT


#7

I’m a little confused. Will this benefit my application’s main window if I use it? Or do I need to draw in 3D or something?


#8

If I understand the demo code correctly, all you have to do is attach an OpenGLContext to your top-level component, and all your child component will paint into a Graphics context that will use OpenGL instead of the software renderer. Especially rendering scaled images is a lot faster in the demo then.

You don’t have to, but if you want to use plain OpenGL code to render something special in 2d or 3d, you can now add standard child components on top (which wasn’t possible before with the OpenGLComponent)


#9

This is pretty cool. Haven’t tried it on Android devices yet, but I am having some problems getting it to deploy on iOS 5.0.1 on an iPad 1. I get the following error if I run it through XCode:


#10

I’ve compiled the demo in Win XP Pro and it crashes. There’s a problem rendering the title bar.
Run the app, click “Use OpenGL renderer” and move the window around, it crashes in a couple of secs.

“Unhandled exception at 0x009dc7a7 in JuceDemo.exe: 0xC0000005: Access violation writing location 0x987e9100.”

Call stack:

JuceDemo.exe!juce::PixelARGB::set<juce::PixelARGB>(const juce::PixelARGB & src)  Line 159 + 0xb bytes	C++
JuceDemo.exe!juce::SoftwareRendererClasses::SolidColourEdgeTableRenderer<juce::PixelARGB,0>::replaceLine(juce::PixelARGB * dest, const juce::PixelARGB & colour, int width)  Line 167	C++
JuceDemo.exe!juce::SoftwareRendererClasses::SolidColourEdgeTableRenderer<juce::PixelARGB,0>::handleEdgeTableLineFull(const int x, const int width)  Line 99	C++
JuceDemo.exe!juce::SoftwareRendererClasses::ClipRegion_RectangleList::SubRectangleIterator::iterate<juce::SoftwareRendererClasses::SolidColourEdgeTableRenderer<juce::PixelARGB,0> >(juce::SoftwareRendererClasses::SolidColourEdgeTableRenderer<juce::PixelARGB,0> & r)  Line 1577	C++
JuceDemo.exe!juce::SoftwareRendererClasses::ClipRegionBase::renderSolidFill<juce::SoftwareRendererClasses::ClipRegion_RectangleList::SubRectangleIterator,juce::PixelARGB>(juce::SoftwareRendererClasses::ClipRegion_RectangleList::SubRectangleIterator & iter, const juce::Image::BitmapData & destData, const juce::PixelARGB & fillColour, const bool replaceContents, juce::PixelARGB * __formal)  Line 1163	C++
JuceDemo.exe!juce::SoftwareRendererClasses::ClipRegion_RectangleList::fillRectWithColour(juce::Image::BitmapData & destData, const juce::Rectangle<int> & area, const juce::PixelARGB & colour, bool replaceContents)  Line 1472 + 0x18 bytes	C++
JuceDemo.exe!juce::LowLevelGraphicsSoftwareRenderer::SavedState::fillRect(const juce::Rectangle<int> & r, const bool replaceContents)  Line 1868 + 0x8f bytes	C++
JuceDemo.exe!juce::LowLevelGraphicsSoftwareRenderer::fillRect(const juce::Rectangle<int> & r, const bool replaceExistingContents)  Line 2177	C++
JuceDemo.exe!juce::Graphics::fillAll(const juce::Colour & colourToUse)  Line 369	C++
JuceDemo.exe!ContentComp::paint(juce::Graphics & g)  Line 55	C++
JuceDemo.exe!juce::Component::paintComponentAndChildren(juce::Graphics & g)  Line 1880	C++
JuceDemo.exe!juce::Component::paintEntireComponent(juce::Graphics & g, const bool ignoreAlphaLevel)  Line 1968	C++
JuceDemo.exe!juce::ComponentPeer::handlePaint(juce::LowLevelGraphicsContext & contextToPaintTo)  Line 135	C++
JuceDemo.exe!juce::HWNDComponentPeer::handlePaintMessage()  Line 1487	C++

JuceDemo.exe!juce::HWNDComponentPeer::peerWindowProc(HWND__ * h, unsigned int message, unsigned int wParam, long lParam) Line 2156 C++
JuceDemo.exe!juce::HWNDComponentPeer::windowProc(HWND__ * h, unsigned int message, unsigned int wParam, long lParam) Line 2102 + 0x18 bytes C++
user32.dll!7e398734()
[Frames below may be incorrect and/or missing, no symbols loaded for user32.dll]
user32.dll!7e398816()
user32.dll!7e3aa013()
user32.dll!7e3aa039()
opengl32.dll!5f14699b()
user32.dll!7e398734()
user32.dll!7e3abdf1()
user32.dll!7e3a8ea0()
user32.dll!7e3a8eec()
ntdll.dll!7c91e453()
user32.dll!7e3a99ff()
JuceDemo.exe!juce::HWNDComponentPeer::setPosition(int x, int y) Line 550 C++
JuceDemo.exe!juce::FlacNamespace::add_subframe_(juce::FlacNamespace::FLAC__StreamEncoder * encoder, unsigned int blocksize, unsigned int subframe_bps, const juce::FlacNamespace::FLAC__Subframe * subframe, juce::FlacNamespace::FLAC__BitWriter * frame) Line 3424 + 0x8 bytes C++


#11

Thanks folks!

Erm… That file only contain 2200 lines, I think you may need to sort out your version!

Yes, I think I still need to sort out a few edge-cases… Which extension in particular is failing?

That stack trace is from the fallback renderer, because your machine doesn’t support shaders… Thanks, I’ll do a bit more testing of that code-path, (I’ve obviously been concentrating on getting shader stuff working)


#12

You’re right - I accidentally built from the wrong juce folder. I can’t test it now, but if you don’t hear anything further then you can assume that was the only issue. :slight_smile:


#13

The new OpenGL classes don’t seem to work with OS X 10.5 (tested only on ppc but I believe it’s the same on intel, my intel machines have newer oses…).

The reason is that OS X 10.5 (and I believe 10.6 < 10.6.3) doesn’t support OpenGL 3 functions such as glBindRenderbuffer. Instead, one needs to call an (afaik) identical function suffixed with EXT, such as glBindRenderbufferEXT.

I sent you a pull request for the fix at https://github.com/julianstorer/JUCE/pull/2
(btw congrats for the github move)
Cheers, Yair.


#14

Jules said no to accepting pull requests via github. Which is a little bit disappointing…


#15

I’m not going to use any pull requests directly, but I will take a look at the diff so I can see what you’ve done, and will fix up the 10.5 calls, so thanks!


#16

great job Jules, very impressive !

When using openGL to accelerate general UI drawing, is the best strategy always to attach it to the main view ?
Anything that would obviously be slower in openGL than in CPU ?


#17

[quote=“thomas”]great job Jules, very impressive !

When using openGL to accelerate general UI drawing, is the best strategy always to attach it to the main view ?
Anything that would obviously be slower in openGL than in CPU ?[/quote]

Most things should be quicker, but obviously not everything… Certainly drawing big areas of colour or gradients will be quicker, but if you have many very small areas of gradients, that could be slower, as each gradient would need to be sent as a texture first.


#18

Great news ! 8)


#19

Ok… What I don’t understand is that when I tried building against the 10.5 SDK, all the code compiled and linked happily… I’ve not got a 10.5 system here to test the result, but since the 10.5 SDK obviously doesn’t contain any functions that aren’t available in 10.5, I don’t understand how it could fail to work??


#20

…and just looking at your suggested changes, why did you remove CGLGetCurrentContext() ? According to the docs, that function has been available since 10.0 (?)