Skip to content

Color state transform plumbing

Jonas Ådahl requested to merge jadahl/mutter:wip/color-state-plumbing into main

This branch implements support for transforming SDR (sRGB) to a HDR enabled output, while allowing HDR content to stay intact.

Roughly what it does is, when HDR mode is enabled via the experimental property, all the stage views that represents outputs where HDR actually managed to be enabled starts to composite in a linear variant of the target color space (which will be BT.2020) via an intermediate framebuffer. Each thing being painted should then transform its pixels to fit in this color space, using an EOTF, a color space mapping matrix and luminance adaptation.

Once a frame is composited, the linear buffer is then painted to the scanout framebuffer, while turning the linear values into non-linear (using an inverse EOTF), as is expected by the kernel and monitors.

To make this relatively easy, there is now a function (clutter_color_state_get_transform_snippet()) that takes a source and a target color state (a color state consists of a color space, a transfer function, and a color encoding). It spits out a CoglSnippet that can be added to the end of a CoglPipeline that already produces pixel values, and it will make sure the output of the shader is correct.

As there now will be a few more pipelines floating around, i.e. N for every pipeline we had before (where N is the number of combinations of color state transformations, which I'd expect to be at most 4 in a HDR setup (SDR -> SDR & SDR -> HDR & HDR -> HDR & HDR -> SDR)). To make that easier to deal with, a color transformation aware pipeline cache is introduced: ClutterPipelineCache. Its purpose is to allow users that previously used named pipelines, or other caching methods, to put the pipelines in the cache while passing a color transformation combination, and then have the cache figure out which actual cached pipeline to use.

This is still a draft, for 2 major reasons:

  • Only MetaShapedTexture and MetaBackgroundContent (dropped this, might readd after fixing isssues) has been adapted. All the other paint nodes only have some untested sketched out code so far.
    • The adaptation is not ideal; ideally CoglPipeline generation needs to happen from within the paint node machinery, while it is now a prepared CoglPipeline passed into the paint node constructor, effectively ignoring things like working in a layer paint node.
    • Paint nodes now automatically add color state transformations in the draw step, by looking at the color state current to the paint context.
  • GNOME Shell needs to learn how to use ClutterColorState, ClutterPipelineCache and clutter_color_state_get_transform_snippet(), as well as hooking it all into updated paint node APIs
  • GNOME Shell needs to use paint nodes, and needs learn how to manage ClutterColorState in the ClutterPaintContext.
  • Direct scanout needs to be inhibited, which it currently isn't
  • Compositing HDR content is so far untested, needs some way to override the color state of arbitrary surfaces, perhaps via o.g.M.DebugControl?

It also currently contains !2016 (merged), !3429 (merged) and !3432 (merged).

Edited by Jonas Ådahl

Merge request reports