[PATCH weston v9 00/62] Atomic modesetting support, with atomicity

Daniel Stone daniels at collabora.com
Fri Mar 3 23:05:11 UTC 2017

Hi all,
Building on the previous series, as well as the global repaint timer
series which I've just sent out for more review (thanks Pekka!), here
is v9 of atomic. The most interesting feature is that it is now atomic.

As mentioned in the patch changelogs, in order to use the atomic API
correctly, we need the global repaint hook, and thus atomicity of
modesetting. The reason is that the legacy API (e.g. drmModeSetCrtc)
will implicitly pull in other objects: when changing routing between,
say, a CRTC and a connector, it will remove the changing object's
connection from other objects, and disable them if necessary.

Atomic refuses to do this, as it demands (for locking purposes, if
nothing else) that all state be explicitly provided by the user. I have
thus, on top of the global repaint timer, implemented a fully atomic
modeset for at least all points where we need to reset all state and
program in something completely new. The steady state remains, of
course, entirely on a per-output repaint timer.

Doing this required introducing a third level of state:
drm_pending_state (bikeshed suggestions welcome, why not). So we have,
in descending ownership order:
  - drm_pending_state lives between repaint_begin to repaint_flush or
    repaint_cancel, solely to group proposed drm_output_states together
  - when the repaint is flushed, the drm_output_states are exploded to
    be treated individually, and are no longer owned by the
    drm_pending_state, which is discarded
  - the drm_output_state is primarily a collection of drm_plane_states,
    which are what own the drm_fbs

I've addressed all pending review comments I've got, and thanks to
testing from Fabien DESSENNE and Tiago Gomes as well as what I've found
in my own travels, fixed some bugs too.

Eagle eyes will note that this series introduces dependencies on three
unmerged kernel patches.

The first is the per-CRTC atomic completion interface, which we need in
order to actually do this correctly. It introduces a crtc_id variable
into atomic completion events, so we can tell outputs apart (as one
event is sent for each CRTC). It can be found here:

The second is the drmModeGetPlane2 ioctl, which we use to discover the
set of supported format modifiers. This is not critical, as it is
purely a new feature, but still getting acks would be nice. It can be
found here:

The third is the GBM counterpart to GetPlane2, where we pass GBM a list
of supported modiifers, so we can render our composition output into
tiled or compressed buffers. It can be found here:

New kernel uABI must come with a real-world user (that's us!), where the
use of the interface is acked, before merge. So it would be very nice to
get feedback on our use of these interfaces, and any potential pitfalls,
so we can get them merged into the kernel before we depend on them.

The series can be pulled from Git at:

It can be considered in several groups:

The pixel-format helpers are largely standalone, and I would welcome
any review on these, as well as anyone who feels like porting
gl-renderer to use them ...

03-10 are already largely reviewed by Pekka, adding a refcount to
drm_fb so we can reuse them. One benefit of explicit refcounting is
that we don't have to re-render every time we hit repaint: if the only
changed content is on an overlay, the composited content can just be
reused from the last frame. Pekka has already reviewed these, but more
eyes are never a bad thing. If nothing horrible comes up in review
here, I'm inclined to merge them reasonably soon.

11-19 lay the groundwork for treating all the state we have from
repaint as, well, state. This is the core building block of atomic: we
build up a full view of the _proposed_ state during atomic, and
repeatedly test it, discarding it if it fails. The previous structure
assumed a very linear progression through a repaint cycle, which no
longer holds true in our brave new world.

20-22 are mostly about how we use DRM properties, and putting in a
more robust structure around them to reduce a lot of boilerplate.
They may look familiar, but have been substantially changed since the
last series.

23-25 introduce the three levels of state object. These changes are
mostly mechanical, thanks to the 11-19 prep work.

26-33 include a couple of smaller patches, but are mostly about using
the new state objects everywhere, moving the separate users over
one by one. By patch 33, our normal paths do not call any of the DRM
state modification functions (drmModeSetCrtc, drmModePageFlip,
drmModeSetCursor, drmModeSetPlane) other than through applying a
state object.

34-37 are surprisingly small: since our only path to changing state is
contained in the one place, we just add an alternate route which
applies that state through the atomic API. At this point, we are gaining
little to no benefit from the atomic API (bar faster startup times from
not blocking serially on drmModeSetCrtc), but we are at least using it.

38-45 begin to attack the state _generation_ path in assign_planes,
extracting common helpers. The old path had a mismatch of capability:
between scanout, overlay and cursor, it was a crapshoot as to whether
the particular path would support viewport/scaling/cropping, or dmabuf,
etc. This part of the series pulls them towards more common code.

46-50 take advantage of the above, by adding support for complex client
dmabuf buffers: multi-planar, or with modifiers.

51-60 returns to the state generation path, splitting it in two. It
takes an incremental approach of generating a proposed state with
overlay planes in use, testing it (the atomic API _requires_ kernel
drivers to provide a meaningful 'will this state work if I set it?'
path), and tearing it down if it fails. This required some fairly
heavy surgery on assign_planes, but leaves us with some
self-contained walks. Some 

61 and 62 add support for rendering tiled/compressed buffers for
composition output through GBM. They depend on unmerged kernel/Mesa ABI
so are not currently suitable for merging, though again, having review
and acks on these is going to be essential to getting those ABIs merged
in the first place.

I've tested these on Intel (Skylake, dual-head), Rockchip (with the
Mali driver), RPi2 (VC4 driver), and a DragonBoard 410c (with
Freedreno). I have a few more systems I'll try to bring up and do more
testing on over the next couple of weeks. But the nice takeaway is that
I could start weston-simple-egl -o, move my cursor over it, and observe
that simple-egl was promoted to a plane, with no other repaints at all.
Previously this wouldn't happen for many reasons: Weston would
recomposite all non-plane content, even if unchanged, the different
outputs would try to steal planes from each other and thus constantly
force repaints on each other, etc.

As always, I'm more than open to any suggestions, or even dumb
questions: 'I don't understand this, what is it / why does it exist?',
is probably a good pointer for me to go write some documentation. I
will happily walk through all of this with anyone who wants to review

Have a great weekend.


More information about the wayland-devel mailing list