Howto:New Canvas Execution Model

From FlightGear wiki
Jump to: navigation, search
This article is a stub. You can help the wiki by expanding it.


RFC (03/2020)


Cquote1.png once it [Canvas] is in simgear It should be really multi-viewer/threading capable. Everything that is not, might be changed at some time to match this criterion.

Such a change often comes with changes in the behavior that are not strictly needed but where people started relying on at some time. So better think about that at the first time.

— Mathias Fröhlich (2012-10-22). Re: [Flightgear-devel] Canvas reuse/restructuring.
(powered by Instant-Cquotes)


This is a collection of ideas, discussions and patches with the goal of moving certain types of Canvas code out of the main loop into a dedicated background thread/process.


We have more and more aircraft that feature comparatively complex avionics, implemented on top of the Canvas stack via Nasal. Depending on the number of simulated displays/avionics, there is a fair share of property I/O going on, including a fair amount of redundant I/O, because many avionics/display instances share certain I/O requirements (think access to /position, /orientation etc.)

Many modern aircraft will feature between 6-8 Canvas-based MFDs that may be shown/updated at the same time.

For the time being, the free-form nature of Canvas/Nasal based avionics means that most avionics don't use any dedicated frameworks or standard patterns to formalize if/how and when crucial state is updated.

This includes property tree state, as well as other state retrieve via FlightGear extension functions (think Nasal/cppbind).

Thus, a number of complex cockpits have been demonstrated to be affected by the number of Nasal/Canvas based displays. Often, this is due to the structure of existing legacy code.


This article is intended to provide a comprehensive summary of the various discussions and proposals we have seen in the context of adapting the Canvas system to come up with a new execution mode/model, with the ultimate goal of improving run-time performance - which may include, but isn't restricted to, optionally moving certain aspects of a Canvas-based display out of the main loop into dedicated background threads.

Furthermore, the goal is come up with an execution model that is backwards compatible, and strictly "opt-in" for any functionality that cannot be provided in a safe fashion.

Canvas Architecture

WIP.png Work in progress
This article or section will be worked on in the upcoming hours or days.
See history for the latest developments.

The Canvas system is primarily implemented in C++, it's a listener based subsystem that watches the global property tree for relevant updates/changes, specifically accesses to /canvas are monitored.

Under the hood, each Canvas is implemented as an owner-drawn gauge (OD_Gauge), canvas textures are positioned in the scene using a texture visitor (OSG), replacing static textures as needed.

Each Canvas texture is then composed of so called "elements", the lowest-level element being the "group" which is primarily used to logically structure/organize a texture into a hierarchy of lower-level building blocks. Therefore, each Canvas texture always has a "root" node, which is a group.

In turn, each group may consist of specific "element" implementations, i.e. to render certain types of context, such as:

  • text
  • paths
  • raster images

(and any combination of these)

In addition, there are higher level helpers implemented in scripting space, e.g. a "window" class implemented on top of the image element. Or support for SVG graphics, implemented on top of the OpenVG based path handling support. Also, there is a special group type to handle specifically geographic projections, for mapping/charting purposes.