Plymouth ⟶ X transition

November 28, 2009

So one of the big polish bits in the boot process is the transition from plymouth to X. In Fedora, we worked to make it as seemless as possible when we first started on the Better Startup stuff a few releases ago.

If you haven’t seen it, when boot up finishes, plymouth settles down the boot splash to a transitionable animation frame, then the mouse pointer shows up, and GDM’s background cross fades in while the login window maps and expands to show frequently logged in users. In the best case, this transition all happens without any flicker, resolution changes, black intermediate screens, or console text showing up.

The way we accomplished this was:

  1. I gave “plymouth quit” a “–retain-splash” option which told plymouth to keep the boot splash’s contents on screen even after plymouth exits
  2. krh and ajax added a -nr option to the X server to make X not clear the screen to black (or a weave) at start up
  3. krh, airlied, and darktama (Ben Skeggs) added the driver backend support for -nr to intel, ati, and nouveau drivers respectiviely. Also, Bill Nottingham made -nr work with the fbdev X driver.
  4. ajax made the ugly big “X” mouse cursor not show up by default
  5. I made gdm stuff the screen contents to a pixmap referenced by the pseudo-standard _XROOTPMAP_ID root window property
  6. I also made gnome-settings-daemon cross fade from the _XROOTPMAP_ID pixmap when it loads its background. This step meant we also get a nice transition from gdm to the user’s session, because it also causes a crossfade to happen from gdm’s background to the user’s background during login.

Another big piece to the puzzle was kernel modesetting. This is what makes sure the right mode is set at boot up from the start. Jesse Barnes and krh did most of the work for that in the Intel driver (based on top of the memory manager work anholt, keithp, and other Intel crew did), while airlied did it for the ati driver, and darktama did it for nouveau.

This all works pretty well these days, but one big wrinkle in the whole process is the hand off from plymouth to gdm. Plymouth exits, leaving the system in KD_GRAPHICS mode and hopes that X starts and picks up the peices. This is not a very robust design, because if X doesn’t start, the system will be stuck in KD_GRAPHICS mode and the user won’t be able to switch VTs or really do anything at all, but reboot.

Furthermore, when plymouth exits, the kernel sets the scan out buffer to the frame buffer of the console. This is because the previous scan out buffer was owned by plymouth and goes away when plymouth exits. That means in order to keep things seemless we need to copy the last frame of the animation from plymouth’s framebuffer to the console frame buffer. This extra copy is unfortunate, because it means the kernel console has to be configured the same way as plymouth, but in multihead set ups it’s not. The kernel console “clones” the ttys across all heads, forcing every head to be the same resolution. But plymouth (and X) want every head to run in native resolution. This means in multihead setups we can’t do the copy because the pixel layouts aren’t the same, so we end up filling with black instead.

I’ve wanted to improve this situation for a while, but haven’t really been able to prioritize it above other various bits of work that need to be done. Since I’m on Thanksgiving break I can, in good conscience, ignore my priority list and just work on what I want, so I decided to work on this problem a bit :-)

I just merged the “no-fbcon” branch to plymouth master. It adds a new way to “deactivate” plymouth such that it’s still on screen and idly running, but X can start and take over anyway. This combined with some gdm changes to tell plymouth to go away in the appropriate way after X is started or fails to start means we solve the robustness issues and avoid the extra fbcon copy.

It actually only took a few hours to do. I probably should have made time for it before break.