--- title: agl-compositor --- # Wayland compositor When the AGL project was started, weston was chosen as the compositor, which is the reference implementation of a Wayland compositor, while for window management functionality it relied on *ivi-shell* (In-Vehicle Infotainment) together with an extension, called [wayland-ivi-exension](https://github.com/GENIVI/wayland-ivi-extension). A demo platform image of AGL comes with a handful of demo applications, done with the Qt, which abstracts the protocol communication between the client and the compositor. Additional functionality was in place under the form of library, to control and signal back to the compositor when applications were started, among other things. Management of applications, starting, running and stopping them is done in AGL with AFM [Application Framework Management](5_appfw.md), which is an umbrella name to denote the suite of tools and daemons that handle all of that. It is integrated with systemd and with the current security model, SMACK (Simplified Mandatory Access Control Kernel), a Linux kernel security module. Applications can use AFM to hang off data, and to pass it down to other services. Together with AFM, and with the help of a library, applications could tell the compositor which application to activate or to switch to. ## Simplifying the graphical stack Trimming down these abstractions, simplifying the way clients interact with the compositor, and avoid using modules that aren't really maintained upstream were the reasons behind looking at alternatives to ivi-shell. On the desktop, [xdg-shell](https://gitlab.freedesktop.org/wayland/wayland-protocols/-/raw/master/stable/xdg-shell/xdg-shell.xml) is currently de-facto protocol for handling all window management related functionality. Wayland protocol has a window-like interface embedded into its protocol (called wl_shell), but *xdg-shell* has long time ago deprecated it and instead of adding it in the wayland protocol namespace, it was integrated together with some other useful protocols, into [wayland-protocols](https://gitlab.freedesktop.org/wayland/wayland-protocols) project. The whole purpose of wayland-protocols is to enhance the Wayland protocol with new functionality and bring new extensions entirely. Compositors are free to implement, modify, enhance, and add new extensions to wayland-protocols but they need to do so in consensus. Besides the core wayland protocol and extended functionality from wayland-protocols, a compositor can provide and implement additional protocol extensions (custom to that compositor). By using such private extensions we align with the AGL project and its requirements, without compromising specific functionality and allows to add or improve the current ones. With that in mind, the approach was to create a new compositor, called [agl-compositor](https://gerrit.automotivelinux.org/gerrit/admin/repos/src/agl-compositor) and implement dedicated private extensions, rather than trying to modify weston itself, which AGL project would have been required to keep and maintain for itself, as a fork. ## A compositor based on libweston The compositor used currently in AGL, just like weston, is built on top of *libweston* and *libweston-desktop*. The latter, among other things, is required as it provides the server side implementation of the xdg-shell protocol which underlying toolkits (like Qt/Chromium project) makes use of to deliver desktop-like functionality. The former is used to provide back-ends and rendering support, effectively managing the HW, besides implementing the wayland protocol. The high-level goal of [libweston](https://wayland.pages.freedesktop.org/weston/toc/libweston.html) is to decouple the compositor from the shell implementation. Traditionally, clients were entirely separated from the window manager, the desktop environment and the display server. In wayland all these are conceptually under the same entity though they are implemented as different (UNIX) processes, or as a different namespaces with front and back-end APIs, exposed by libraries. The compositor and the shell driving the UI should be seen as one and the same, and in practice, this happens on desktop environments. For AGL, the shell client can be represented under different forms, as well as the fact that the process management has another layer baked-in to handle MAC (Mandatory Access Control) labels and use the above-mentioned Application Framework Management. These are all tightly integrated and therefore, the AGL compositor will not automatically start the shell client, although there's code to handle that. One can modify the configuration file, add the shell client path, and the compositor will attempt to start it. ## Private extensions Compositors can define and implement custom extensions to further control application behaviour. For AGL, we have two private extensions defined. One targeted at defining surface roles commonly found in desktop environments (like panels, and backgrounds), which a shell client would bind to, and one targeted at regular application(s) that might require additional functionality: being able to display/activate its own surface or other's application surface, implement some kind of split screen management of windows, or dialog/pop-ups that exhibit always-on-top property even if the active surface has been changed. ![Layers_
var sm_helper_8h =
[
    [ "sound_property_s", "structsound__property__s.html", "structsound__property__s" ],
    [ "availability_s", "structavailability__s.html", "structavailability__s" ],
    [ "notification_config_s", "structnotification__config__s.html", "structnotification__config__s" ],
    [ "main_sound_property_s", "structmain__sound__property__s.html", "structmain__sound__property__s" ],
    [ "domain_data", "structdomain__data.html", "structdomain__data" ],
    [ "_GNU_SOURCE", "sm-helper_8h.html#a369266c24eacffb87046522897a570d5", null ],
    [ "AFB_BINDING_VERSION", "sm-helper_8h.html#ad2c1fbc92ba364fcf83f15e6d0af66f0", null ],
    [ "REQ_ERROR", "sm-helper_8h.html#ab0d62ccfa9c3ab87f090f67c3d50adce", null ],
    [ "REQ_ERROR", "sm-helper_8h.html#aa49f1dbbf26f01627a5737cf43aad899", [
      [ "REQ_FAIL", "sm-helper_8h.html#aa49f1dbbf26f01627a5737cf43aad899a96a855966bc63045222b3dcac524cee1", null ],
      [ "REQ_OK", "sm-helper_8h.html#aa49f1dbbf26f01627a5737cf43aad899ab093abb14c097b3b7719debb04d5e8ee", null ],
      [ "NOT_NUMBER", "sm-helper_8h.html#aa49f1dbbf26f01627a5737cf43aad899aa223eed65c9bee2bf1f4cdecaf90d66a", null ],
      [ "OUT_RANGE", "sm-helper_8h.html#aa49f1dbbf26f01627a5737cf43aad899add1c84bf80c5f80741ee8f37fef1e12b", null ]
    ] ],
    [ "create_domain_data", "sm-helper_8h.html#a6b6746be407c77c641065a76fcbff019", null ],
    [ "create_source_data", "sm-helper_8h.html#a3da984668307f39d541053eba1d78a83", null ],
    [ "get_value_int16", "sm-helper_8h.html#a2e62366684e39ea94436bf017e416827", null ],
    [ "get_value_int32", "sm-helper_8h.html#ac5b0370643c520377afd3fd4891918d2", null ],
    [ "get_value_uint16", "sm-helper_8h.html#a649900645417f2df3a70b9ad67529f53", null ],
    [ "sm_add_object_to_json_object", "sm-helper_8h.html#abce7df03d817a3356071f1563011b77f", null ],
    [ "sm_add_object_to_json_object_func", "sm-helper_8h.html#a67cdeffaf2fd293c9f7de73c64e851a9", null ],
    [ "sm_search_event_name_index", "sm-helper_8h.html#a971c6c55c9b04ae87c377fbde6a4c6f6", null ],
    [ "sm_search_routing_event_name_index", "sm-helper_8h.html#a2a63791cfba48b0456aefafe237e419e", null ]
];
engine, to execute a rule match for that event. Further more, the framework allows adding new states and events and the default implementation has code for handling events like showing or hiding the application specified in the policy rule. The most common example to exemplify this feature is the ability to show a custom application, like displaying the rear view camera application, when the automobile has been put in reverse. For deadling with these kind of rules, `ivi_policy_api::policy_rule_allow_to_add()` can be used to control if policy rules could be added or not. Finally, we have `ivi_policy_api::policy_rule_try_event()` which is executed for each policy rule added, by using the policy API `ivi_policy_add()` function. By default the policy framework it will add the 'show', and 'hide' events and the 'start', 'stop' and 'reverse' states. An special type, assigned by default is 'invalid'. A **state change** has to be propagated to the compositor, which can happen by using `ivi_policy_state_change()` function, and which signals the compositor the state change took place, in order to apply the policy rules, and implicitly to call the event handler `ivi_policy_api::policy_rule_try_event()`. ## Back-ends and specific options for agl-compositor The compositor has support for the following back-ends: * **DRM/KMS** - runs a stand-alone back-end, uses Direct Rendering Manager/Kernel Modesetting and evdev, that is utilizes and runs on real or virtualized HW (qemu/Vbox/etc). * **Wayland** - runs as a Wayland application, nested in another Wayland compositor instance * **X11** - run as a x11 application, nested in a X11 display server instance ### Building and running the compositor on different platforms The compositor can run on desktop machines as easily as it does on AGL platform. It should infer, depending on the environment, if it is being compiled with the AGL SDK, or with the host build system. Running would also be inferred from the environment. The compositor has some additional configuration options like: * `--debug` - enables the screenshooter interface, useful if one would want to take a screenshot using `agl-screenshooter` client. This might be seen as a security risk to it only be enabled in the AGL platform if built with agl-devel DISTRO FEATURES. Additional configuration ini options have been added to help with the CI integration. Worth mentioning are: * `activate-by-default=[true]` - if the surface of the client should be displayed when the application started. Present in the `[core]` section. By default set to `true`. Setting it to `false` will not activate, by default, the client's surface when started. * `hide-cursor=[false]` - do not advertise pointer/cursor to clients. Present in the `[core]` section. ## Running with software rendering By default the compositor will attempt to use the GL-renderer, and implicitly the GPU. One could instead use the CPU, by making use of the Pixman library. To use it in the compositor append `--use-pixman` to the command line. This purely software approach has the benefit that would not rely at all on any GL implementatation or library. In constrast, even if the GL-renderer is used, in some situations it won't be able to use the GPU supported implementation and fallback to sofware based one, and for instance that might happen when running in virtualized environments. Both approaches could end up not actually using the GPU, but the latter does actually use the GL library and perform the operations in software, while the former does not use any GL whatsover. All back-ends support disabling the GL-render to make sure it does not interfere with the composing process. ## Multiple output set-up and touch input devices There's no deterministic way in which the compositor enables the outputs and depending on the input devices, specifically touch input devices, and the way the connectors are wired, a touch input device might be associated with a different output than the one intended. A consistent way, that survives a reboot, is to use [udev rules](https://man7.org/linux/man-pages/man7/udev.7.html), which libweston would be able to use such that a particular output is tied/associated to a particular touch input device. For instance, assuming that you have a set-up consisting of 4 outputs, a 4 touch input devices, when the outputs are being enabled the compositor front-end will associate all 4 touch input device -- if they haven't been previously being associated to a particular output, to the first enabled output. In order to avoid that, and associate each touch input device to their respective output an udev rule can be installed, for the default seat (named `seat0`). Example of a udev rule: ``` SUBSYSTEM=="input", ATTRS{idVendor}=="222a", ATTRS{idProduct}=="004a", OWNER="display", ENV{ID_SEAT}="seat0", ENV{WL_OUTPUT}="HDMI-A-1" SUBSYSTEM=="input", ATTRS{idVendor}=="222a", ATTRS{idProduct}=="004b", OWNER="display", ENV{ID_SEAT}="seat0", ENV{WL_OUTPUT}="HDMI-A-2" SUBSYSTEM=="input", ATTRS{idVendor}=="222a", ATTRS{idProduct}=="004c", OWNER="display", ENV{ID_SEAT}="seat0", ENV{WL_OUTPUT}="HDMI-A-3" SUBSYSTEM=="input", ATTRS{idVendor}=="222a", ATTRS{idProduct}=="004d", OWNER="display", ENV{ID_SEAT}="seat0", ENV{WL_OUTPUT}="HDMI-A-4" ``` Add the following under `/etc/udev/rules.d/91-output.rules` and reload udev rules for these changes to take effect: $ udevadm control --reload-rules && udevadm trigger Note that in the above example, we use physical seat, named `seat0` which is the default physical seat. You can verify that these changes have been applied by checking the compositor logs (under `/run/platform/display/compositor.log` file) You should be seeing `CONNECTOR-NO by udev` message like the following: ``` associating input device event0 with output HDMI-A-1 (HDMI-A-1 by udev) ``` vs ``` associating input device event0 with output HDMI-A-2 (none by udev) ``` where the rules are either incorrect or badly written. Retrieving device attributes could be done archaically using `lsusb` or `lspci` or using `udevadm info -a /dev/input/event*` which can provide with a multitude of attributes to use. In our above example we only relied `idVendor` and `idProduct` but potentially other attributes might be used.