Sunday, February 9, 2014

Game Streaming on X1 Carbon 2nd Gen Haswell with Linux

I'm running Ubuntu 13.10 on my new X1 Carbon 2nd Gen.  I debated whether to get a laptop with dedicated graphics card like the new XPS15 9530 or the Razer Blade, but then read about some solutions people are using to stream games from a dedicated gaming rig to a less-powerful linux laptop and thought I'd give it a try, so I bought the X1.  My goal is to be able to play less-intense games on the laptop stand-alone, but to be able to play more intense games when I'm at home and connected to my gaming rig.

Obviously the experience on the laptop will not be as good as playing directly on a desktop with dedicated graphics, but lately it seems to be getting pretty good.

If you're not familiar with the concept of streaming games, there are a few things you should check out:


Steam In-Home Streaming:

Steam in-home streaming is in beta now, but it's working pretty well for me and I'm using it on wireless N.  Ethernet or wireless AC will probably improve the experience.  Not every game works - in particular if they don't support the "steam overlay" they won't work.

Games I've tried that work well:  Blackguards, Skyrim, XCOM

Game that didn't work:  Star Wars the Old Republic.

I haven't tested extensively, and obviously I'm not playing the most demanding games for low latency and high frame rates.  But to hear about other people's experiences check out the steam forums.

To get into the beta you need to join the forum group from the link above.  I got into the beta the day after I joined the forum group, but YMMV.

Splashtop:

Splashtop was developed initially for iPads to connect to desktops, but now there is a beta linux client that you can install through the Ubuntu software center.  I couldn't work out another way of installing it. 

The performance is pretty amazing if you're used to using remote desktop'ing with RDP or VNC protocols.  Sound worked out of the box as well.  The main issue I had with Splashtop is that mouse movements are not transmitted to the host, so the mouse cursor stays in the same position on the host while you're moving it, then "teleports" when you click.  That's a problem for most games.  Some people have used Synergy to solve that problem.  I haven't tried it.  Synergy is a general-purpose software to share a usb keyboard and mouse between computers on your network, which is interesting in its own right for kvm-switch-style functionality.

When you install splashtop initially, it will only give you low-resolution options, but there's a configuration file you can edit to give you 1920x1080.  Instructions here.

Teamviewer:

The Teamviewer linux client uses Wine to run.  You can download a .deb install from the Teamviewer website and then install it using "dpkg -i".  My experience on Ubuntu 13.10, though, was that sound doesn't work because there's no pulseaudio driver in the wine libraries that are packaged as part of the Teamviewer installation.  I found a fix that involved copying the pulseaudio library from a working copying the pulseaudio driver from a working Wine installation to the Teamviewer wine directory, but it didn't work for me on 13.10.

Some other free software alternatives:

RealVNC is way too slow for transmitting graphics.  TightVNC is supposed to be faster, but I haven't tried it.  TurboVNC and TigerVNC are forks of TightVNC, and might also be worth trying.  The big difference in performance comes from compressing the stream from the host to the client.  Particularly when the compression can be performed on the GPU rather than the CPU.  I do not know at this point how that's working between the different solutions I've tried.

Installing Ubuntu 13.10 on Gen 2 (Haswell) Lenovo X1 Carbon

I recently bought the new X1 Carbon Gen 2 with a 2560x1440 touchscreen, 8GB RAM and 256GB SSD.  I installed Ubuntu Linux 13.10 on it, and it's been a great experience so far.  I absolutely love the laptop and linux runs very well on it.

Summary of what's working:

  • Wireless -- works out of the box
  • Touchscreen -- out of the box you only get left-click, but you can enable gestures with Touchegg (see bekow).
  • Touchpad -- works out of the box but not well.  Can be fixed with some X11 config changes (see below)
  • Function keys -- the X1 has an "adaptive keyboard" where the function keys are an LCD strip, displaying context-sensitive keys.  Out of the box the basic function keys (F1-F12) are displayed and work fine, even in BIOS.  So far I haven't been able to cycle through different sets of buttons.
  • Hibernate --  "sudo pm-hibernate" works out of the box
  • External display on HDMI port -- plugging in a 1920x1080 external display to the HDMI port worked out of the box.  No luck with the mini displayport yet.
  • Bluetooth -- hci0 was soft-blocked by default, but easily unblocked and then works like a charm.
  • Automatic switching to usb headset audio & mic - worked out of the box
  • Trackpoint (the little red button in the middle of the keyboard) - works out of the box

Summary of issues:

  • Suspend -- "sudo pm-suspend" will suspend to RAM, but there's no way to resume.  You have to power off and back on.  But "hibernate" (suspend to disk) works, and the SSD is very fast so I don't mind that.
  • External display on Mini DisplayPort not working.


Not Tested:

  • Fingerprint reader
  • OneLink Docking Station (though I have one on order so I'll test that when it arrives)

The installation process:

The process I went through was:
  1. Create a bootable usb flash drive with Ubuntu 13.10
  2. Turn off UEFI in the BIOS on the Carbon X1 (hit "Enter" while the Lenovo splash screen is displayed at boot time to enter BIOS)
  3. Change the order of boot devices in BIOS so the usb flash drive is prior to the HD
  4. Boot into the usb flash drive and install
  5. Make a few easy fixes 
  6. Voila!

Touchscreen gestures:

To enable touchscreen gestures, install Touchegg:

     sudo apt-get install touchegg

Then edit ~/.config/touchegg/touchegg.conf to apply the changes you want.

You'll get some decent gestures by default.  See here for more information on tweaking touchegg.

Fixing the touchpad:

Out of the box the touchpad is barely useable, but after following these instructions I'm very pleased with it.

Enabling bluetooth:

Install BlueZ:

     sudo apt-get install bluez bluez-utils

Then check the status of your hci device(s):

     hciconfig

In my case, hic0 was software-blocked by default, so typing the following command unblocked it:

     sudo rfkill unblock hci0

For more information on linux bluetooth, see this article.


My Set-Up:

I'm running fluxbox instead of Unity, and GDM instead of LightDM as my login manager.

To install fluxbox, just type "sudo apt-get install fluxbox" and then next time you log in, you can click on "sessions" in GDM or LightDM and select fluxbox.

To install GDM or SLiM or another login manager, install it through apt-get, and the installation process will prompt you to choose with login manager you want to use as your default.  If you want to change your selection after you've installed another one, type "sudo dpkg-reconfigure GDM" and you can change it to another one.

I enjoy the fluxbox keymapping functionality.  You can run "xev" in a terminal to see what keycodes specific button presses fire.  So, for example, running "xev" and pressing the battery icon on the function key panel, I can see it returns keycode 235.  So in ~/.fluxbox keys I've added the following line:
     
     235 :Exec sudo pm-hibernate

...which makes pressing that key invoke hibernate mode.  For that to work, though, you need to change your sudoers config to not require a password for that command.  To do this, you can create a file called "power" in /etc/sudoers.d/ with the following line:

     %adm ALL=(ALL) NOPASSWD: /usr/sbin/pm-hibernate

Be careful doing this!  You should use visudo rather than a normal editor (as it will validate before writing, and you should not edit /etc/sudoers directly, but rather create a new file in /etc/sudoers.d

EDIT May 7 2014:  I discovered a simpler way to hibernate.  You can just do "systemctl hibernate" as a non-root user, and it should work without mucking around with permissions.  I'm on Arch now though so I can't confirm it works in Ubuntu.

I'm running the following applets in my systemtray in fluxbox:

  • nm-applet:  shows you a little wifi icon indicating your signal strength, and if you click on it you can select a different wireless network and so forth.
  • xfce4-power-manager:  battery monitor 

Here's a screenshot:

Kernel Parameter Weirdness:

By default my kernel parameters in GRUB are set to "quiet splash".  For some reason if I use "nomodeset" (to get a text-based login rather than graphical) then hibernate doesn't work.  No idea why that would be but I didn't spend much time on it.


UPDATE:  Feb 24, 2014 -- OneLink Dock Pro

I ordered a OneLink Dock Pro along with the X1 Carbon.  It arrived just this weekend, much later than the laptop itself.  Plugging in a monitor (1920x1080) to the dock's DVI port worked out of the box, as did USB 2.0 mouse and keyboard.  USB 3.0 hard drive also worked out of the box.  I did not test the DisplayPort connection yet, but I have a DisplayPort->HDMI adaptor on order so I'll give that a try soon.

The picture on the external monitor is not that great, somewhat "washed out" in appearance compared to the identical monitor hooked up to my desktop running Win8 sitting right next to it, using the DVI port on the NVIDIA GPU of the desktop.  I'm not sure why this is yet, or whether it'll possible to fix it.  I tweaked the brightness and contrast and it improved, and it doesn't really bother me, but it's not as nice as I'd hoped.  The "washed out" look is the same using the HDMI port on the laptop itself, or the DVI port on the dock.  I do not have a monitor with DisplayPort connection to test and, as noted above, I couldn't get the mini-DisplayPort on the laptop itself to work (I was using a mDP->DVI adaptor).

FURTHER UPDATE: Feb 24, 2014:  The "washed-out" appearance on external monitor has an easy fix.  See here for instructions.  Yay!!  Looks absolutely great now!

UPDATE:  Feb 27, 2014 -- Can't get 3 displays working with dock (built-in + 2 1920x1080)

I ordered a DisplayPort to HDMI adaptor which came in the mail today.  I'm trying to run 2 1920x1080 monitors connected to the Onelink Dock Pro, one connected to the DVI port on the dock, and the other connected via the adaptor to the DP port.  I get picture on both external monitors, but they're mirrored and I can't find a way to treat them as separate displays.  If I run "xrandr -q", only 1 device is detected for the two ports (DP2). 

If I look at /var/log/Xorg.0.log, the manufacturer info for the monitor I plug in first is detected, the second one is not shown.  This seems to indicate the dock is getting only 1 true video port sent to it, and then doing some kind of splitting.  There is a windows driver for the Onelink Dock Pro that I suspect somehow lets the OS treat the one video output stream as two distinct screens, but no joy for Linux.  Had I known that, I might've gone with the cheaper Onelink Dock with just one video port.

The issue may actually be with the Intel 4400 integrated graphics, though, because I also tried connecting one of the monitors to the onboard HDMI port, and it doesn't work while the laptop is plugged in to the dock, but works fine when I unplug the dock.  So it could be that the intel gfx driver for linux doesn't support 3 displays (although the windows driver apparently does).

Ah well, guess I'll have to wait for either an intel driver that supports 3 displays or a linux driver for the Onelink Pro Dock.

UPDATE: Mar 7, 2014 -- Still no luck with 3 displays

I got confirmation from one of the devs working on the i915 driver that 3 displays should be supported for the 4400, so I tried a newer kernel and it's still not working.  The behavior is:
  • 2 monitors connected through the OneLink Pro Dock (1 on the DVI port, another on the DisplayPort with a passive DP->DVI adaptor):  only 1 display (besides the built-in panel) is detected by 'xrandr -q'.  Both monitors display the picture, but they're mirrored with each other. 
  • 1 monitor connected through the dock DVI port, and 1 connected to the laptop HDMI port:  when I connect the HDMI cable to the laptop, the monitor connected to the dock blanks out and the display is no longer listed in 'xrandr -q', but the monitor connected via HDMI works.
I've ordered an "active" DP->DVI adaptor, and I'm hoping that'll solve it.  The 4400 has two pixel clocks, so in order to support 3 displays, 2 of them have to be sharing a pixel clock.  I'm hoping the active adaptor will allow one external monitor to share a pixel clock with the built-in laptop panel.

UPDATE: Mar 9, 2014 -- No luck with "active" adaptor

I tried the active DP->DVI adaptor with the Onelink Pro Dock.  Behavior is the same.  I did notice that when the 2nd external monitor is plugged in, I get another resolution option for "2560x1024" in xrandr, and if I select that, it does extend the picture across the two instead of mirroring, but that resolution is very poor.  I tried manually adding a resolution of 3840x1080 but that didn't work.  No idea at this point where the real problem lies, so not sure what to try next.  Might be stuck with 1 external monitor.

UPDATE: Apr 28, 2014 -- 3 displays working!

I can confirm it's possible to drive 3 displays with this set-up:
  • internal display 
  • 1 external monitor connected to the laptop's miniDisplayPort with mDP->DVI adaptor, at 1920x1080.
  • 1 external monitor connected to the OneLink Pro Dock via DVI, also at 1920x1080.
I'm running Arch Linux now, though, so apologies I can't offer a suggestion to ubuntu users.  I did try this set-up on Ubuntu 13.10 and it didn't work for some reason, but I never tried it on 14.04 before I switched to Arch.

I would of course rather use two video outputs on the Onelink Pro Dock, but apparently it uses an MST Hub to drive mutliple displays, which is not supported yet.  I can only get two external displays to be mirrored that way (and they show up as one display in xrandr as discussed above).