Raspberry PI rendering performance

Hi, I have been working with JUCE for quite a time on Windows. Now I have a project where I need to render a simple text animation on Rapberry PI. I thought since I am already familiar with JUCE I might give it a shot...

 

Well I have been able to build JUCE on my Raspberry PI (model B+). I used this process to install the additional libraries needed to build JUCE:

https://github.com/rec/echomesh/blob/master/documentation/Building%20Juce%20applications%20on%20the%20Raspberry%20Pi.md

 

What I want to do is to render 3 digits inside the rectangle of the whole screen. And then at some point shrink the text bounding box a bit to the top and make another short text come up from the bottom. A real simple animation. After few seconds the text at the bottom should go away and the 3 digits should show again stretched on the entire window.

 

I created an Animated Application from the Introjucer template. I have overriden the paint method in MainContentComponent like this:

 

 void paint (Graphics& g) override
    {        
        // (Our component is opaque, so we must completely fill the background with a solid colour)
        g.fillAll (Colours::black);

        g.setColour(Colours::white);

        Rectangle<float> numberArea = layout.getCurrentNumberArea();
        Rectangle<float> bottomArea = layout.getCurrentBottomArea();

        Font f;        
        f.setHeight(numberArea.getHeight());
        g.setFont(f);

        g.drawText("727", numberArea, Justification::centred, false);

        f.setHeight(bottomArea.getHeight());
        g.setFont(f);
        g.drawText("simple text", bottomArea, Justification::centred, 1);

    }

 

In update() I just compute the Rectangles that are returned by layout.getCurrentNumberArea() and layout.getCurrentBottomArea().

 

On my Windows PC this runs just fine (I have set 60 FPS for the animation using setFramesPerSecond (60)). But when I made a Linux build in Introjucer and copied it to the Raspberry and build&run it, it runs like 3 FPS, which is completely useles.

 

Well in theory this should work even on Raspberry as it is capable of realtime decoding 1080p H264 video. I guess that using Graphics object is too inefficient for rendering on such a slow device. And I dont even use any transformations I just set a different text height to keep it simple.

 

Do you have any advice on what should I try?

 

And related questions:

Is Graphics object rendering hardware accelerated?

Can I make it faster somehow?

Is it somehow possible that the things are so slow beacuse I did not build the JUCE right? For example i have skiped the point 4 in the instructions above and it built just fine.

 

Also I guess I can use OpenGL rendering directly but I'd like to avoid that as it is really a simple aplication that only displays some short text. I remember from my school days that rendering a nice text in OpenGL was not exactly a job done in a matter of hours...

 

Thanks

 

//Edit:

this thread might be of some relevance as the slow text rendering is mentioned there as well (although it's not about Raspberry):

http://www.juce.com/forum/topic/opengl-renderer-drawing-performance

this thread mentions that JUCE OpenGL on Raspberry is very slow:

http://www.juce.com/forum/topic/juce-raspberry-pi-opengl?page=2

Rendering on the raspberry pi is quite slow for several reasons.

1. The first and foremost reason is that most raspberry pi distributions default to a 16-bit colour depth (5-6-5 channel configuration) X server. This makes blending operations quite involved. You can change the display depth in the config.txt file in the boot partition of the pi:

framebuffer_depth=32
framebuffer_ignore_alpha=1

A higher bit depth however, will obviously further limit available system memory on an already memory constrained device.

2. The raspberry pi currently only supports OpenGL ES. This means that OpenGL falls back to software rendering if used under X11 which is horribly slow. There really isn't a very good solution for this as there are only two ways to use hardware accelerated graphics on the pi at the moment: i) either use OpenGL ES directly, i.e. without starting any window server. JUCE currently does not support this but it shouldn't be too hard to modify the source code to get this to work. However, you would only be able to create fullscreen apps with this approach as ... well.. you have no window server. ii) use wayland: a new window server which can use OpenGL ES as a backend and has good support on the pi. Unfortunately there is no wayland support in JUCE at the moment and adding it to JUCE would be quite involved.

2 Likes

Thanks a lot for a great answer. I will try to adjust the frame buffer_depth as I dont really need much memory for displaying two lines of text, and nothing else has to run on the PI at the same time. I doubt it will move the performance an order of magnitude though...

 

I will let you know the result but I will probably have to try some of the alternatives you suggested in point 2.

 

//Edit: That's strange increasing the frame buffer depth makes the application run more that 2 times slower. I will try to adjust the memory split and try once more but the problem is definitelly the software rendering...

OK, I just need to know who's to "blame" for the fact that the HW acceleration doesn't kick in. Is it the problem with X11 or is it that JUCE only supports OpenGL rendering and not OpenGL ES? If it is the first I really need to use OpenGL ES directly. If it is the second case, I may still have hope, that some other framework might do the trick (i.e. QT or something...) and will be able to use OpenGL ES for HW acceleration of font rendering. As for the Wayland option: I am a complete an utter Linux noob and that thing seems a way over my head for the moment.

 

Thanks

Well, I guess it's both: if there would be an OpenGL ES backend for X11 then JUCE would just work out of the box. On the other hand, if JUCE would have an OpenGL ES backend then obviously you would also have hardware accelerated rendering (albeit without the windowing). Wayland support would be the cherry on top.

I'm surprised by your finding that things get slower when enabling 32-bit depth. I found that the JUCE demo runs a bit more fluent when running under 32-bit colour depth but it may depend on what you are rendering if it is fast or not. Maybe text rendering is faster under 16-bit - I haven't tried this. Have you tried the JuceDemo? 

Also, please also note that there are many hacks out in the wild that might do what you want: "hardware accelerated OpenGL under X11". For instance a quick google search brings up some interesting pages:

 

https://www.raspberrypi.org/forums/viewtopic.php?f=63&t=28294

https://www.youtube.com/watch?v=8Fy63w6WxOw

 

However, I don't think that any of the established raspberry pi solutions offer OpenGL under X11.

 

I'm surprised by your finding that things get slower when enabling 32-bit depth.

It really is. I tried reverting back to 16 bit and it ran more then 2 times faster than 32bit. To be sure I switched again to 32bit and again to 16bit. The results were consistent, though the problem might not necessarily be with the font rendering, the overall application performance was just worse.

 

As for the JUCE demo. It seems that none of the JUCE examples (the demo included) does not work. When I launch any of them, it looks OK, but the windows are completely unresponsive. It does not react to any mouse events apart from the actions that causes any popup menu to appear. In those cases the popup menu is shown but the items the mouse is over are not highligted and all those menus never go away, as if the windows doesn't want to refresh. So in the end after clicking on the menu tabs, or rightclicking anywhere just clutters the whole window with popup menus.

 

Thanks for the links I have looked at them and that one with the QT hack solution seems to be promising, I'll dig more into it.

 

//edit deleted wrong information

“As for the JUCE demo. It seems that none of the JUCE examples (the demo included) does not work. When I launch any of them, it looks OK, but the windows are completely unresponsive.”

Ahhh I think you are using an old version of JUCE. We fixed this (or a very similar issue) some weeks ago. Try using the version on github https://github.com/julianstorer/JUCE/

Sorry, I had to put this project aside for some time.

 

Anyway I thought I had the latest version as I had just downloaded it from JUCE download page. I got the zip file for Linux. The only way I could have had some old version is if you somehow forgot to update the zip file.

 

To be sure I downloaded the current version today directly from github using git clone. Now i get some weird error that x11/extensions/Xrandr.h is missing while compiling juce_gui_basics (at least i think it was this file, i incidentally unplugged the memory card as i touched the Raspberry board and now have start all over again an it takes hours to compile the demo app). Well I am a complete and utter Linux noob but it seems some prerequisite is missing. I thought that JUCE is self-contained and does not need any aditional installations...

 

Any ideas?

 

//edit: Yes, it is juce_gui_basics, the error message is:

 

Compiling juce_gui_basics.cpp
../../../../modules/juce_gui_basics/juce_gui_basics.cpp:110:37: fatal error: X11/extensions/Xrandr.h: No such file or directory
   #include <X11/extensions/Xrandr.h>

 

The newest version is always on github. The zip is merely the latest tagged version which can be several months old. 

To compile on linux you now additionally require the Xrandr development files. On Ubuntu or debian based distributions you can install this with:

sudo apt-get install libxrandr-dev

Note that Xrandr development files are only a compile-time dependancy: your JUCE app users will not need to have Xrandr installed to use your JUCE app.

You can also disable Xrandr alltogether by specifying JUCE_USE_XRANDR=0 in "Extra Preprocessor definitions" section of the "Linux Makefile" target in the Introjucer. However, I recommend installing libxrandr-dev instead if you can.

I hope this helps!

 

Thanks, now it compiles but when I try to run the Demo executable the window does not show at all (although there is the JuceDemo tab on the taskbar) and in the console I get the following output:

 

pi@raspberrypi ~/dev/JUCE/JUCE/examples/Demo/Builds/Linux/build $ ./JuceDemo
JUCE v3.1.1
ERROR: X returned BadValue (integer parameter out of range for operation) for operation X_ConfigureWindow
ERROR: X returned BadValue (integer parameter out of range for operation) for operation X_ConfigureWindow
ERROR: X returned BadValue (integer parameter out of range for operation) for operation X_ConfigureWindow
ERROR: X returned BadValue (integer parameter out of range for operation) for operation X_ConfigureWindow
ERROR: X returned BadValue (integer parameter out of range for operation) for operation X_ConfigureWindow
ERROR: X returned BadValue (integer parameter out of range for operation) for operation X_ConfigureWindow
ERROR: X returned BadValue (integer parameter out of range for operation) for operation X_ConfigureWindow
ERROR: X returned BadValue (integer parameter out of range for operation) for operation X_ConfigureWindow
JUCE Assertion failure in juce_Component.cpp:1322
JUCE Assertion failure in juce_Component.cpp:737

Ahhh interesting. I've seen this happen when your display driver reports some messed-up screen geometry . Can you type-in xrandr into a terminal and send me the output. I'm guessing that the physical screen size (in mm) reported by xrandr might be something stupid on the raspberry pi. I'll add some sanity checks to the DPI caclulation which should get rid of this problem. I'll keep you posted.

OK issue is fixed on latest tip. Xrandr was in deed returning a zero-sized screen geometry on the pi causing an infinitely high scale factor.

Sorry again for the late answer, so litle time these days...

xrandr output:

xrandr: Failed to get size of gamma for output default
Screen 0: minimum 1600 x 900, current 1600 x 900, maximum 1600 x 900
default connected 1600x900+0+0 0mm x 0mm
   1600x900        0.0*

 

OK, the physical screen size is obviously not right...

 

I seem to have similar problem while launching QT built application:

EGLFS: Unable to query physical screen size, defaulting to 100 dpi.
EGLFS: To override, set QT_QPA_EGLFS_PHYSICAL_WIDTH and QT_QPA_EGLFS_PHYSICAL_HEIGHT (in millimeters).

As for the OpenGL ES support we discussed earlier. I have been able to build and run QT5.2 QML application in fullscreen as suggested in the link you posted. So thanks for that!

 

//edit: sorry I missed the last post (it overflowed to the next page) - thanks for the fix (in general - for this project i'll stick with QT because of the performance).

Sorry to resurrect an old thread, I’m working on a full-screen app for a Raspberry Pi and wondering if there are any examples of using OpenGL ES directly as suggested here? I assume this is whats used on Android too.

Not from me… In the end I just solved it by migrating it to QT Quick which supports OpenGL ES acceleration even on X. In that app I didn’t need any audio…

1 Like