Sunday, April 23, 2006

VNC in QEmu

As I mentioned in a previous post, I have been developing a VNC patch for QEmu. QEmu is a really great platform to explore different ideas as it's entirely in userspace and therefore is somewhat sane to debug. The two ideas I've been examining are both accelerations for VNC and so far have shown promising results.

The first is what I'll refer to as subtiling. A fundamental VNC optimization is to only transmit the portions of the screen that change to the client. The easiest way to do that is to keep track of which portions of the screen change and then transmit those portions during your normal update event. In a virtualized environment, it's a bit harder to keep track of which regions change because it's just memory being written to. This means you usually end up with oversized dirty regions. This tends to result in 1-2 orders of magnitude more data being marked dirty than there really is. To eliminate this, it becomes necessary to maintain a copy of the client framebuffer (that is, the framebuffer that you think the client has). When it comes time to transmit an update, instead of blindly transmitting dirty regions, I've implemented a "subtiling" algorithm which compares against our copy of the client framebuffer to determine which regions have really changed.

The second optimization I've implemented is video-to-video blit acceleration. The basic idea is that most modern VGA hardware (and more important, the Cirrus card that QEmu emulates) implements 2d acceleration routines. In the case of the Cirrus card, this is a fast copy between video memory (optionally using one of a number of ROP operators). With the right filtering and a little magic, we can convert this video-to-video copy into a VNC CopyRect operation. I suspected that this would be a useful optimization but I had no idea how much of a difference it would make. I was surprised to learn just how many places a modern operating system makes use of accelerated copying. When you scroll a web page in internet explorer, Windows uses 2d acceleration. The result is an extremely usable interface that is awfully pleasant to use even over the network. In fact, even with a poor encoding, the interface is at least as responsive on my local LAN as a real VNC server.

Tonight I got a chance to talk to Fabrice about this patch and he seemed to be happy with it. In fact, it looks like I've got a shot of getting it in for the next release. The code is quite ugly right now but hopefully I'll have something that's much cleaner by the end of the week. Then I can start looking at reusing it for Xen so I can finally get rid of the libvncserver dependency for the VFB.