FlightGear and OpenGL ES

From FlightGear wiki
Jump to navigation Jump to search
This article is a stub. You can help the wiki by expanding it.
OpenGL ES compatible subset of FlightGear
Started in 04/2020
Description identify, patch and build a subset of FlightGear compatible with GLES
Contributor(s) talks
Status RFC

Some FG users are very interested in seeing how FlightGear runs on lower end/embedded hardware (think RPi-style) using OpenGL ES This is a link to a Wikipedia article.

The bigger issue here is we need to ditch PUI (which is in progress) and some OpenGL 1.0 code (HUD, 2D panels especially - can be #ifdef for now) so we can enable Core profile on Mac - since Mac 4.x support (we only hit about 4.3 alas, but with some extensions to get in sight of 4.5) is Core profile only, no Compatability mode.

I *believe* the new open-source Intel-Mesa drivers on Linux (which are supposed to decent quality, and even fast) might be in the same situation.[1]

Probably to do it initially, GLES1 would have to be used - I think GLES2 has no fixed function - and simgear/flightgear would have to be patched to use only OSG calls (if possible), e.g. by excluding features/subsystems that still use legacy OpenGL code incompatible with GLES.

OSG can have GLES{1,2} support without windowing compiled in.

OpenGL 1 and 2 can be mixed but OpenGL ES 1 and OpenGL ES 2 can't. There is a performance price to pay for this backward compatibility. For this reason, we should get rid of PLib because this (old) code is all OpenGL 1 that may slowdown the all rendering pipeline.

For historical reasons, Flightgear and Simgear are mixing OpenGL 1 (old code) and OpenGL 2 (more recent code).[2]


1rightarrow.png See Howto:Optimizing FlightGear for mobile devices for the main article about this subject.

The OpenSceneGraph port initiated in 2006 has never been fully completed, so that there is a certain amount of code making use of legacy OpenGL calls, which complicates modernizing the renderer.

In particular, this means that Supporting multiple renderers is unnecessarily complicated, unifying the 2D rendering back-end is a long standing challenge. It's only since just very recently, that supporting different renderers is being worked on thanks to the Compositor effort.

But even then, phasing out legacy code or porting it, still needs to be addressed sooner or later.

Being able to run fgfs on such, comparatively low-powered, systems using OpenGL ES can actually be a good thing for fgfs as a whole - it can help us understand bottlenecks that are hardly visible on typical gaming/developer rigs, but that may still show up over time (think leaking listeners/memory) - this sort of thing can also be considered the prerequisite for people wanting to target/build/run fgfs on other embedded hardware, such as thin clients with integrated GPUs or even mobile phones/tablets (think Android)

we need to remove PUI and change the Canvas not to use Shiva, to be ES2 compatible or Core-profile compatible.[3]

In other words, if the right people were to team up to specifically target such hardware, this could also mean significant performance improvements for people on powerful gaming rigs.


For starters, we can try the FlightGear Headless option to build a fgfs version without showing any graphics at all.

The next step will be identifying and excluding problematic sources (those containing legacy/raw OpenGL code, e.g. using glBegin() or glEnable() respectively):


void RenderArea2D::RenderQuad( const SGVec2f *p) {
        glNormal3f(0.0f, 0.0f, 0.0f);
        glVertex2fv( p[0].data() );
        glVertex2fv( p[1].data() );
        glVertex2fv( p[2].data() );
        glVertex2fv( p[3].data() );

Whenever FlightGear sources contain such or similar code, it is pretty safe to assume that we will need to port/exclude such modules from compilation to ensure that no legacy OpenGL code is executed at runtime.


This means, we'll need to review/disable the compilation of the following folders in $FG_SRC and patch up all hard-coded references to these systems:

  • Instrumentation/HUD
  • Cockpit
  • GUI

In addition, there's Viewer/PUICamera.cxx which references glEnable()

Example: Disabling PUI

1rightarrow.png See Developing using CMake for the main article about this subject.

We should add separate build options to explicitly disable certain features individually.

The bigger issue here is we need to ditch PUI (which is in progress) and some OpenGL 1.0 code (HUD, 2D panels especially - can be #ifdef for now) so we can enable Core profile on Mac - since Mac 4.x support (we only hit about 4.3 alas, but with some extensions to get in sight of 4.5) is Core profile only, no Compatability mode.[4]

Knowing that PUI contains legacy OpenGL code and knowing it's scheduled to be removed anyway because it isn't compatible with modern OpenGL, we will disable it completely without reviewing/porting individual PUI files. This means opening $FG_SRC/CMakeLists.txt to add a new option to disable PUI.

Successfully disabling a feature means primarily:

  • adding a corresponding new build option to the top-level CMakeLists.txt (e.g. DISABLE_PUI)
  • opening fg_init.cxx and navigating to the lines where the feature/subsystem is initialized
  • wrapping the corresponding code in between #ifdef...#endif blocks
  • locating any remaining references to the subsystem in question and repeating the last step there to ensure that removed subsystems are not accessed at runtime


option(SYSTEM_CPPUNIT    "Set to ON to build Flightgear with the system's CppUnit library")
option(DISABLE_PUI    "Set to ON to build Flightgear without PUI support")


We will be adding #ifdef macros to the sources in question, and update CMakeLists.txt accordingly.

Ideally, in conjunction with a feature-specific build option to disable the corresponding feature (think PUI or the HUD).

Thus, after editing CMakeLists.txt, we need to open fg_init.cxx to prevent initalization of PUI.


    // Create and register the XML GUI.
    globals->add_subsystem("gui", new NewGUI, SGSubsystemMgr::INIT);

So, after editing fg_init.cxx to prevent the PUI GUI from getting initialized by FlightGear, we will need to find remaining hard-coded references to it, to fix those up and deal with PUI not being available. This means grepping $FG_SRC for any references to "pui" to locate remaining get_subsystem() calls. (FIXME: new subsystem lookups use templates), this will include code in unrelated modules, e.g. fgcommands (think menu bindings) accessing the GUI via something like get_subsystem("gui");


    NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
    if (!gui) {
      return false;

Thus, it makes sense to intercept registration of these fgcommands at the bottom of the file by wrapping these inside ifdef macros:


 * Table of built-in commands.
 * New commands do not have to be added here; any module in the application
 * can add a new command using globals->get_commands()->addCommand(...).
static struct {
  const char * name;
  SGCommandMgr::command_t command;
} built_ins [] = {
    { "exit", do_exit },
    { "reset", do_reset },
    { "reposition", do_reposition },
    { "switch-aircraft", do_switch_aircraft },
    { "panel-load", do_panel_load },
    { "preferences-load", do_preferences_load },
    { "toggle-fullscreen", do_toggle_fullscreen },
    { "screen-capture", do_screen_capture },
    { "hires-screen-capture", do_hires_screen_capture },
    { "tile-cache-reload", do_tile_cache_reload },
    { "dialog-new", do_dialog_new },
    { "dialog-show", do_dialog_show },
    { "dialog-close", do_dialog_close },
    { "dialog-update", do_dialog_update },
    { "dialog-apply", do_dialog_apply },
    { "open-browser", do_open_browser },
    { "gui-redraw", do_gui_redraw },
    { "add-model", do_add_model },
    { "presets-commit", do_presets_commit },
    { "press-cockpit-button", do_press_cockpit_button },
    { "release-cockpit-button", do_release_cockpit_button },
    { "dump-scenegraph", do_dump_scene_graph },
    { "dump-terrainbranch", do_dump_terrain_branch },
    { "print-visible-scene", do_print_visible_scene_info },
    { "reload-shaders", do_reload_shaders },
    { "reload-materials", do_materials_reload },
    { "open-launcher", do_open_launcher },
    { 0, 0 }			// zero-terminated

This will ensure that fgcommands that are PUI related won't be available in a non-PUI build.

We will also need to look for other files accessing the "NewGUI" subsystem grep -nr "NewGUI" -l:


Since we have excluded $FG_ROOT/GUI from the build and updated fg_init.cxx, we will only need to review/patch these files to ensure that there are no hard-coded references to PUI if it's not available, using the same ifdef based approach.

Obviously, fgdata level resources like menu bindings and/or Nasal code may still try to execute such bindings.

Finally, there may still be other PUI specific references in the source tree ($FG_SRC), so that it does help to check the other folders next: grep -nr "PUI" -l

Since we have excluded $FG_SRC/GUI from the compilation, we can safely ignore any references to that folder, with the remaining ones being:


The renderer is basically just referencing the PUI camera so that the GUI can be drawn, whereas canvas_mgr merely acccesses the PUI subsystem to be able to render canvas based textures. In other words, both references can be easily removed for testing purposes.

Affected features and sources

Feature Directory Notes Status
PUI $FG_SRC/GUI trivial to disable, can be replaced via Phi. Is in the process of being replaced by an optional QtQuick runtime 70}% completed
2D Panels $FG_SRC/Cockpit see Populate /canvas property tree for the 2D panel

There's also a branch (which is a few of years old) contains WIP on implementing 2D panels as canvas. It uses the same loading / updating logic in C++ (for 100% compatibility), but rather than building custom rendering, it builds up a Canvas element hierarchy in C++.[5][6]

80}% completed
Canvas Path (Shiva) $SG_SRC/canvas Likely using NanoVG, see Scott's summary: Pending Pending
Effects $FG_ROOT/Effects will include Shaders and probably involve a custom Compositor pipeline 70}% completed

In addition, SimGear needs special treatment, too [7]. Using the same heuristics as before (based on grepping $SG_SRC for glBegin and glEnable, we end up with the following sources (ignoring Canvas Path /shivavg, which is dealt with already above):

simgear/scene/tgdb/SGVasiDrawable.cxx:42:    glBegin(GL_POINTS);

Feature Directory Notes Status


OpenGL ES This is a link to a Wikipedia article

Vertex buffer objects

Canvas.Path (OpenVG)

Will likely need to replace shiva vg with an OpenGL 2.0 based implementation like nanovg [8].

Community talks



Related content