A solution for gamma-adjustment support in Wayland

Mattias Andrée maandree at member.fsf.org
Wed Dec 7 12:10:52 UTC 2016

The following text is also available in PDF format at

### Abstract ###

With the advent of Wayland, our display server has lost a functionality
— access to the graphic cards’ colour loop-up tables — that has been
used to implement, amongst other things, ergonomic functionality. But
we now have a chance to start from scratch and do it the right way.

### Background ###

Display servers have for a long time provided access to the graphics
cards’ colour look-up tables (CLUT), so the user can adjust the colour
output to more precisely match the intended output. Since then the
CLUT have used for other things, for example invert the output, dim
the output, adjusting the white point to make the output less blue,
and even cycles through the rainbow’s colours just for fun and rapidly
cycling between red, green, and blue to repair stuck pixels.

    With the advent of Wayland, the CLUT are no longer available to
the user, instead the compositor uses colord to retrieve the profile
for the monitors and adjust, and any other feature that uses the CLUT
must be built into the compositor. This creates a numbers of problems:
developers that want to create a compositor — or just a part of the
compositor, like a window manager — must now also write the output
filters or find someone else to do it; the output filters become
coupled; a developer that wants to create a new output filter can no
longer do it as a stand-alone program, but rather must build it into
an existing program; users that want to use an output filter must
port it into the compositors they want to use that are missing that
output filter; and we run the risk that how the output filter is
controlled and configured depends on the want display server, if any,
and compositor is being used.

### Problems and Solutions ###

There are few problems that needs to be addressed when implementing
gamma support in a display server.

    A concern with letting the user access CLUT is that a program could
make the screen unreadable. One solution is to add a minimal acceptable
ramp for each monitor, or a shared one. This has the advantage that the
screen can never become unreadable, but the disadvantage is that the
user cannot intentionally make the screen unreadable. For example,
before going to sleep the user can fade out the monitor to black, or
dark, pure red, and then fade it in during the morning. An alternative
solution to add a hotkey that disables all output filters accept the
colour correction. This has the advantage that the user can easily
disable all filters when working with colour, but it has the disadvantage
that the user may not be familiar with which key to use, even if set
manually (output filters could be disabled until a key is selected). It
is of course possible to use both alternatives.

    Another concern, that is currently the case on X.org, is that if the
monitor becomes black, and the user is not familiar with how to make it
viewable again, switching virtual terminal (VT) will not save her. It is
easily solved by resetting to CLUT with only the gamma correction when a
VT-switch is requested. Similarly, this should be done when the server
is shut down or crashes. Furthermore, it is advantageous if the user is
able to SSH into the computer and reset the CLUT.

    Another problem is when multiple programs want to change the CLUT,
and when programs to not properly reset the CLUT, often because of a
crash, and the ability for a program to set the CLUT and exit without
the CLUT being reset on exit. These are problems solved with cooperative

### Cooperative Gamma ###

Cooperative gamma is a solution for letting multiple programs edit the
CLUT without overriding each other. It is already available, display
servers that expose access to the CLUT to clients, via coopgammad[1] and
libcoopgamma[2], and soon, all output filters and utilities are available
for this solution, primarily via cg-tools[3]. A compositor that provides
cooperative gamma will have all kinds of output filters available for
the simple work of porting one simple program and built it into the
compositor; and of course build the safe-guards discussed earlier.
Building cooperative gamma into compositors also mean that we do not
have to resort to ugly hacks like making a fork of colord that have
cooperative gamma.

    With cooperative gamma, the display server chains together all
filters. Each filter is given a priority number which is used to
determine it’s position in the chain. Each filter is also given a name
so that it an be update or remove later, even by another process. A
program can add a filter and exit, and can then be restarted to update
or remove the filter. The program can tell the server to remove the
filter when the program exits, so the filter is cleaned up if the
program crashes or is killed.

[1] https://github.com/maandree/coopgammad
[2] https://github.com/maandree/libcoopgamma
[3] https://github.com/maandree/cg-tools

### Protocol ###

It’s important that all Wayland compositors use the same protocol,
otherwise, all compositors need their own patch for libcoopgamma, which
will quickly become a mess. However, Wayland compositor that already
support CLUT adjustments, non-cooperatively, by clients should add a
patch to libgamma[4], which will make coopgammad work with those

    There must be a protocol for retrieving a list of video display
controllers (VDC) and the Extended Display Identification Data (EDID)
of connected monitors. Access to the EDID is important as it’s provides
away to uniquely identify a monitor, and as a way to access information
about a monitor that could be useful. Although not necessary, it is
favourable to provide access to user specified information that overrides
information in the EDID, in case the EDID is not accurate or not precise
enough. In the context of access to the CLUT, this includes measures of
the colour space, that is, the x and y values of the primaries (red,
green, and blue) and the white point, and what kind of colour space the
monitor uses. It is important that the protocol remains flexible and
does not assume that the monitor will use red, green, and blue primaries,
and only red, green, and blue. A monitor in the future could add a fourth
primary to a larger gamut.

    There should also be a protocol for identifying whether a VDC have
CLUT that can be edited, and whether the compositor supports cooperative
gamma. The size and the depth of the CLUT should should also be
retrievable. Since cooperative gamma is supported, the size and depth of
the CLUT can exceed the controller’s CLUT for better results when output
filters are chained together.

    When adding a filter to a VDC, it shall be given a life span of
either until it’s explicitly removed or until the client disconnects. It
shall also be given a priority. To match coopgammad, the priority shall
be a signed 64-bit integer, where a lower value means it’s applied
earlier in the chain of filters, and gamma correction, such as those
done by the compositor retrieved from colord, should have the priority
0. A filter is identified by three parameters: (1) the package name of
the program, this should not be the preferred package name, but rather
the package name used in the OS distribution’s software repository, (2)
the name command name of the utility, and (3) an arbitrary string which
is used to let a program apply multiple separate filters on the same
output, this string is called the rule in coopgammad.

    Adding and update a filter is done in the same why. A filter is
added if it is not present on the VDC, and update if it is present. It
should also be possible to explicitly remove a filter. Updating and
removing filters should be possible by any process, not just the monitor
that originally added it. It should be possible for a program to add
filter and exit, and then update it or remove it some other time when it
is run again. It should also be possible for a program to list all
existing filter and remove any of them.

    There should also be a protocol for listing filters. The list of
filter’s should include, for each filter, the CLUT values, the priority,
and the three identifying parameters. It should also be possible to
identify on switch VDC the filter’s are applied. In coopgammad, this is
done by requesting lists of filter’s for individual VDCs. It should
also be possible to return the resulting CLUT when the filter’s are
chained to together, here it should be possible to select the first and
list included filter by their priority. Of course, these features could
be available when listing the filters too.

    In coopgammad, the filter’s identifying parameters are formatted as
a single null-character free UTF-8 string, called class, where the
parameters are joined by two colons.

[4] https://github.com/maandree/libgamma
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 801 bytes
Desc: OpenPGP digital signature
URL: <https://lists.freedesktop.org/archives/xdg/attachments/20161207/eb25f80d/attachment.sig>

More information about the xdg mailing list