diff mbox

Add QEMU DirectFB display driver

Message ID 1273766038-16808-1-git-send-email-julian.pidancet@citrix.com
State New
Headers show

Commit Message

Julian Pidancet May 13, 2010, 3:53 p.m. UTC
This patch implements a DirectFB driver for QEMU. It allows Qemu to
draw a VM graphic output directly in the framebuffer of the host,
without having to rely on X11.
DirectFB also provides with a generic interface take advantage of graphic
hardware acceleration for a bunch of different supported cards.

In this driver, the DirectFB library gives Qemu a pointer to mapped
video memory, which allows Qemu to update the display without extra copy.
In the case where the guest framebuffer is not compatible with the host
framebuffer, DirectFB surface blitting functions are used and can be
accellerated wherever it is possible with the hardware.

DirectFB is a thin library heavily used in embedded or minimal systems
which don't require X11 overhead. One use case would be to build a
Xen-based client-class hypervisor, with a minimal dom0 running Qemu as
device-model. The dom0 could render the domU graphical outputs on the
physical screen using this patch without having X11 installed.

The other solution would be to use the DirectFB driver for SDL which
would allow to do slightly the same as this patch. But that would mean
having to deal with an additional layer in the graphical stack, which is
not exactly what one wants from a performance or a complexity point of
view.

Signed-off-by: Julian Pidancet <julian.pidancet@citrix.com>
---
 Makefile        |    4 +
 Makefile.objs   |    1 +
 configure       |   21 +++
 console.h       |    3 +
 directfb.c      |  394 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 qemu-options.hx |   10 ++
 sysemu.h        |    1 +
 vl.c            |   12 ++
 8 files changed, 446 insertions(+), 0 deletions(-)
 create mode 100644 directfb.c

Comments

Paul Brook May 16, 2010, 1:10 a.m. UTC | #1
> The other solution would be to use the DirectFB driver for SDL which
> would allow to do slightly the same as this patch. But that would mean
> having to deal with an additional layer in the graphical stack, which is
> not exactly what one wants from a performance or a complexity point of
> view.

I don't buy your complexity argument.  Doesn't DirectFB-via-SDL already work? 
If not why not? I'm pretty sure fixing that would be way simpler than adding a 
whole new output backend.

Paul
Alexander Graf May 16, 2010, 1:14 a.m. UTC | #2
On 16.05.2010, at 03:10, Paul Brook wrote:

>> The other solution would be to use the DirectFB driver for SDL which
>> would allow to do slightly the same as this patch. But that would mean
>> having to deal with an additional layer in the graphical stack, which is
>> not exactly what one wants from a performance or a complexity point of
>> view.
> 
> I don't buy your complexity argument.  Doesn't DirectFB-via-SDL already work? 
> If not why not? I'm pretty sure fixing that would be way simpler than adding a 
> whole new output backend.

Well, I can think of size as a reason. Not compiling in SDL, but directfb, would certainly shave off dependencies on a usually rather large SDL library. I also find SDL code less readable than Qemu code in general :).

That said, I don't want to take sides - just wanted to state the obvious.


Alex
Anthony Liguori May 17, 2010, 1:30 p.m. UTC | #3
On 05/15/2010 08:10 PM, Paul Brook wrote:
>> The other solution would be to use the DirectFB driver for SDL which
>> would allow to do slightly the same as this patch. But that would mean
>> having to deal with an additional layer in the graphical stack, which is
>> not exactly what one wants from a performance or a complexity point of
>> view.
>>      
> I don't buy your complexity argument.  Doesn't DirectFB-via-SDL already work?
> If not why not? I'm pretty sure fixing that would be way simpler than adding a
> whole new output backend.
>    

Yeah, I don't buy it either.  I think performance data is probably the 
only way to justify this and I'm sceptical that if there is a 
performance advantage that it wouldn't be possible to just fix SDL's 
DirectFB support.

Regards,

Anthony Liguori

> Paul
>
>
Julian Pidancet May 17, 2010, 3:09 p.m. UTC | #4
On 05/17/2010 02:30 PM, Anthony Liguori wrote:
> On 05/15/2010 08:10 PM, Paul Brook wrote:
>>> The other solution would be to use the DirectFB driver for SDL which
>>> would allow to do slightly the same as this patch. But that would mean
>>> having to deal with an additional layer in the graphical stack, which is
>>> not exactly what one wants from a performance or a complexity point of
>>> view.
>>>      
>> I don't buy your complexity argument.  Doesn't DirectFB-via-SDL already work?
>> If not why not? I'm pretty sure fixing that would be way simpler than adding a
>> whole new output backend.
>>    
> 
> Yeah, I don't buy it either.  I think performance data is probably the 
> only way to justify this and I'm sceptical that if there is a 
> performance advantage that it wouldn't be possible to just fix SDL's 
> DirectFB support.
> 

I don't think wether fixing or not SDL is the debate here, the question would be more wether or not we want to add a lightweight display driver to qemu. Also, I think a DirectFB driver is fairly easy to maintain.

I will get some performance data as soon as I have some time.

By the way, sorry for the patch reposts, it seems that my smtp server had quite some trouble to relay messages last week.
Anthony Liguori May 17, 2010, 4:28 p.m. UTC | #5
On 05/17/2010 10:09 AM, Julian Pidancet wrote:
> On 05/17/2010 02:30 PM, Anthony Liguori wrote:
>    
>> On 05/15/2010 08:10 PM, Paul Brook wrote:
>>      
>>>> The other solution would be to use the DirectFB driver for SDL which
>>>> would allow to do slightly the same as this patch. But that would mean
>>>> having to deal with an additional layer in the graphical stack, which is
>>>> not exactly what one wants from a performance or a complexity point of
>>>> view.
>>>>
>>>>          
>>> I don't buy your complexity argument.  Doesn't DirectFB-via-SDL already work?
>>> If not why not? I'm pretty sure fixing that would be way simpler than adding a
>>> whole new output backend.
>>>
>>>        
>> Yeah, I don't buy it either.  I think performance data is probably the
>> only way to justify this and I'm sceptical that if there is a
>> performance advantage that it wouldn't be possible to just fix SDL's
>> DirectFB support.
>>
>>      
> I don't think wether fixing or not SDL is the debate here, the question would be more wether or not we want to add a lightweight display driver to qemu. Also, I think a DirectFB driver is fairly easy to maintain.
>    

Generally speaking, adding DirectFB doesn't seem like a net win to me.  
We still have to maintain SDL so now there's just more code to 
maintain.  I'd rather there be one way of doing things that everybody 
focused on making work best than have two ways to do the same thing (if 
at all possible).

Regards,

Anthony Liguori

> I will get some performance data as soon as I have some time.
>
> By the way, sorry for the patch reposts, it seems that my smtp server had quite some trouble to relay messages last week.
>
>
Gerd Hoffmann May 17, 2010, 8:20 p.m. UTC | #6
On 05/16/10 03:10, Paul Brook wrote:
>> The other solution would be to use the DirectFB driver for SDL which
>> would allow to do slightly the same as this patch. But that would mean
>> having to deal with an additional layer in the graphical stack, which is
>> not exactly what one wants from a performance or a complexity point of
>> view.
>
> I don't buy your complexity argument.  Doesn't DirectFB-via-SDL already work?

Run a guest.  Switch to another (host) virtual terminal.  Watch qemu 
continue drawing on the framebuffer.  Doesn't count as "working" in my book.

> If not why not? I'm pretty sure fixing that would be way simpler than adding a
> whole new output backend.

Didn't investigate where the bug is and how hard it would be to fix it.

cheers,
   Gerd
Anthony Liguori May 17, 2010, 8:32 p.m. UTC | #7
On 05/17/2010 03:20 PM, Gerd Hoffmann wrote:
> On 05/16/10 03:10, Paul Brook wrote:
>>> The other solution would be to use the DirectFB driver for SDL which
>>> would allow to do slightly the same as this patch. But that would mean
>>> having to deal with an additional layer in the graphical stack, 
>>> which is
>>> not exactly what one wants from a performance or a complexity point of
>>> view.
>>
>> I don't buy your complexity argument.  Doesn't DirectFB-via-SDL 
>> already work?
>
> Run a guest.  Switch to another (host) virtual terminal.  Watch qemu 
> continue drawing on the framebuffer.  Doesn't count as "working" in my 
> book.

A common theme with SDL seems to be that it does lots of things poorly.  
I wonder if we'd be better suited just dropping SDL and focusing on 
doing a few things well.

The fact that we have cocoa support in the tree is basically an 
admission of failure with SDL.

Regards,

Anthony Liguori

>> If not why not? I'm pretty sure fixing that would be way simpler than 
>> adding a
>> whole new output backend.
>
> Didn't investigate where the bug is and how hard it would be to fix it.
>
> cheers,
>   Gerd
>
>
malc May 17, 2010, 9:35 p.m. UTC | #8
On Mon, 17 May 2010, Anthony Liguori wrote:

> On 05/17/2010 03:20 PM, Gerd Hoffmann wrote:
> > On 05/16/10 03:10, Paul Brook wrote:
> > > > The other solution would be to use the DirectFB driver for SDL which
> > > > would allow to do slightly the same as this patch. But that would mean
> > > > having to deal with an additional layer in the graphical stack, which is
> > > > not exactly what one wants from a performance or a complexity point of
> > > > view.
> > > 
> > > I don't buy your complexity argument.  Doesn't DirectFB-via-SDL already
> > > work?
> > 
> > Run a guest.  Switch to another (host) virtual terminal.  Watch qemu
> > continue drawing on the framebuffer.  Doesn't count as "working" in my book.
> 
> A common theme with SDL seems to be that it does lots of things poorly.  I
> wonder if we'd be better suited just dropping SDL and focusing on doing a few
> things well.

There's one thing that SDL does marvelously well - it's just one fairly
small and self contained library that doesn't unleash dependency hell on
the user.

> The fact that we have cocoa support in the tree is basically an admission of
> failure with SDL.

I don't think so, the way i see it: someone had an itch (i.e. an
application that does not integrate well with his windowing environment)
and he scratched it.
Anthony Liguori May 17, 2010, 9:43 p.m. UTC | #9
On 05/17/2010 04:35 PM, malc wrote:
> There's one thing that SDL does marvelously well - it's just one fairly
> small and self contained library that doesn't unleash dependency hell on
> the user.
>    
>> The fact that we have cocoa support in the tree is basically an admission of
>> failure with SDL.
>>      
> I don't think so, the way i see it: someone had an itch (i.e. an
> application that does not integrate well with his windowing environment)
> and he scratched it.
>    

SDL doesn't integrate well into a modern Gnome desktop either.  I don't 
see why we have Cocoa and not Gtk.  If the answer is, someone needs to 
send patches, expect patches soon :-)

Regards,

Anthony Liguori
malc May 17, 2010, 9:45 p.m. UTC | #10
On Mon, 17 May 2010, Anthony Liguori wrote:

> On 05/17/2010 04:35 PM, malc wrote:
> > There's one thing that SDL does marvelously well - it's just one fairly
> > small and self contained library that doesn't unleash dependency hell on
> > the user.
> >    
> > > The fact that we have cocoa support in the tree is basically an admission
> > > of
> > > failure with SDL.
> > >      
> > I don't think so, the way i see it: someone had an itch (i.e. an
> > application that does not integrate well with his windowing environment)
> > and he scratched it.
> >    
> 
> SDL doesn't integrate well into a modern Gnome desktop either.  I don't see
> why we have Cocoa and not Gtk.  If the answer is, someone needs to send
> patches, expect patches soon :-)
> 

If those patches don't try to force Gnome on me (by removing SDL that is
and being optional) let them come.
Alexander Graf May 17, 2010, 10:26 p.m. UTC | #11
On 17.05.2010, at 23:45, malc wrote:

> On Mon, 17 May 2010, Anthony Liguori wrote:
> 
>> On 05/17/2010 04:35 PM, malc wrote:
>>> There's one thing that SDL does marvelously well - it's just one fairly
>>> small and self contained library that doesn't unleash dependency hell on
>>> the user.
>>> 
>>>> The fact that we have cocoa support in the tree is basically an admission
>>>> of
>>>> failure with SDL.
>>>> 
>>> I don't think so, the way i see it: someone had an itch (i.e. an
>>> application that does not integrate well with his windowing environment)
>>> and he scratched it.
>>> 
>> 
>> SDL doesn't integrate well into a modern Gnome desktop either.  I don't see
>> why we have Cocoa and not Gtk.  If the answer is, someone needs to send
>> patches, expect patches soon :-)
>> 
> 
> If those patches don't try to force Gnome on me (by removing SDL that is
> and being optional) let them come.

I'm trying to think of a project where the clean separation between multiple video outputs implemented in the backend and a separate frontend worked out. So far the only case that has a strikingly similar architecture coming to my mind is mplayer. And I wouldn't call mplayer's GUI story a huge success.

In fact, couldn't we rather keep all graphic output out of qemu and just expose VNC, possibly with self-made additions to the protocol to speed up local rendering (thinking an SHM extension here)? Then we could still offer a separate SDL based viewer that could do the same things it does now. But we'd also open up the gate for a whole new integration level with possible GUIs.


Alex
malc May 17, 2010, 10:42 p.m. UTC | #12
On Tue, 18 May 2010, Alexander Graf wrote:

> 
> On 17.05.2010, at 23:45, malc wrote:
> 
> > On Mon, 17 May 2010, Anthony Liguori wrote:
> > 
> >> On 05/17/2010 04:35 PM, malc wrote:
> >>> There's one thing that SDL does marvelously well - it's just one fairly
> >>> small and self contained library that doesn't unleash dependency hell on
> >>> the user.
> >>> 
> >>>> The fact that we have cocoa support in the tree is basically an admission
> >>>> of
> >>>> failure with SDL.
> >>>> 
> >>> I don't think so, the way i see it: someone had an itch (i.e. an
> >>> application that does not integrate well with his windowing environment)
> >>> and he scratched it.
> >>> 
> >> 
> >> SDL doesn't integrate well into a modern Gnome desktop either.  I don't see
> >> why we have Cocoa and not Gtk.  If the answer is, someone needs to send
> >> patches, expect patches soon :-)
> >> 
> > 
> > If those patches don't try to force Gnome on me (by removing SDL that is
> > and being optional) let them come.
> 
> I'm trying to think of a project where the clean separation between
> multiple video outputs implemented in the backend and a separate
> frontend worked out. So far the only case that has a strikingly
> similar architecture coming to my mind is mplayer. And I wouldn't
> call mplayer's GUI story a huge success.

Xine, VLC do have something resembling this separation too. As for
mplayer's GUI, never used it, what i did (and still) use is my own
video output device for mplayer, which is a lot faster than Xv, or
anything else for that matter, on my hardware.

> 
> In fact, couldn't we rather keep all graphic output out of qemu and
> just expose VNC, possibly with self-made additions to the protocol
> to speed up local rendering (thinking an SHM extension here)? Then
> we could still offer a separate SDL based viewer that could do the
> same things it does now. But we'd also open up the gate for a whole
> new integration level with possible GUIs.
> 

This idea is not new, nothing has come out of it till this day, so the
answer to your question (couldn't we...) is probably: no, we couldn't.
Anthony Liguori May 17, 2010, 10:46 p.m. UTC | #13
On 05/17/2010 05:26 PM, Alexander Graf wrote:
> I'm trying to think of a project where the clean separation between multiple video outputs implemented in the backend and a separate frontend worked out. So far the only case that has a strikingly similar architecture coming to my mind is mplayer. And I wouldn't call mplayer's GUI story a huge success.
>
> In fact, couldn't we rather keep all graphic output out of qemu and just expose VNC, possibly with self-made additions to the protocol to speed up local rendering (thinking an SHM extension here)?

I think the whole reason this has failed is that if the GUI is a 
separate project, the path of least resistance is to use existing 
interfaces instead of inventing new ones.  That means these GUIs tend to 
be restricted by whatever management interface exists which isn't 
actually good enough.

You really need to have the GUI as part of the main project such that 
when it needs a new interface, it can be added very easily.

>   Then we could still offer a separate SDL based viewer that could do the same things it does now. But we'd also open up the gate for a whole new integration level with possible GUIs.
>    

You could, but I think it introduces more complexity which just is going 
to get in the way of building a good GUI.

Regards,

Anthony Liguori

> Alex
>
>
Anthony Liguori May 17, 2010, 10:47 p.m. UTC | #14
On 05/17/2010 05:42 PM, malc wrote:
>> In fact, couldn't we rather keep all graphic output out of qemu and
>> just expose VNC, possibly with self-made additions to the protocol
>> to speed up local rendering (thinking an SHM extension here)? Then
>> we could still offer a separate SDL based viewer that could do the
>> same things it does now. But we'd also open up the gate for a whole
>> new integration level with possible GUIs.
>>
>>      
> This idea is not new, nothing has come out of it till this day, so the
> answer to your question (couldn't we...) is probably: no, we couldn't.
>    

Because shared memory is just a graphics optimization and for most 
users, the difference between gtk-vnc and native SDL isn't noticable.  
So if a shared memory transport was the key missing piece, we'd have an 
awesome GUI based on gtk-vnc that just had slower graphics.

IMHO, the problem with an external GUI is that the interaction just gets 
too complicated.

Regards,

Anthony Liguori
Alexander Graf May 17, 2010, 10:49 p.m. UTC | #15
On 18.05.2010, at 00:46, Anthony Liguori wrote:

> On 05/17/2010 05:26 PM, Alexander Graf wrote:
>> I'm trying to think of a project where the clean separation between multiple video outputs implemented in the backend and a separate frontend worked out. So far the only case that has a strikingly similar architecture coming to my mind is mplayer. And I wouldn't call mplayer's GUI story a huge success.
>> 
>> In fact, couldn't we rather keep all graphic output out of qemu and just expose VNC, possibly with self-made additions to the protocol to speed up local rendering (thinking an SHM extension here)?
> 
> I think the whole reason this has failed is that if the GUI is a separate project, the path of least resistance is to use existing interfaces instead of inventing new ones.  That means these GUIs tend to be restricted by whatever management interface exists which isn't actually good enough.
> 
> You really need to have the GUI as part of the main project such that when it needs a new interface, it can be added very easily.

I agree on that part.

> 
>>  Then we could still offer a separate SDL based viewer that could do the same things it does now. But we'd also open up the gate for a whole new integration level with possible GUIs.
>>   
> 
> You could, but I think it introduces more complexity which just is going to get in the way of building a good GUI.

The main benefit I see by taking an always-vnc approach would be that everything becomes 100% networkable. There's nothing getting in your way because you're doing things on a remote machine. And you even get the same look&feel you got from the local connection because it's the same tool connecting you.

But yeah, maybe it does add too much complexity. I don't know.


Alex
Anthony Liguori May 17, 2010, 10:54 p.m. UTC | #16
On 05/17/2010 05:49 PM, Alexander Graf wrote:
>>>   Then we could still offer a separate SDL based viewer that could do the same things it does now. But we'd also open up the gate for a whole new integration level with possible GUIs.
>>>
>>>        
>> You could, but I think it introduces more complexity which just is going to get in the way of building a good GUI.
>>      
> The main benefit I see by taking an always-vnc approach would be that everything becomes 100% networkable. There's nothing getting in your way because you're doing things on a remote machine. And you even get the same look&feel you got from the local connection because it's the same tool connecting you.
>    

My current thinking with GUIs is that network transparency is more 
trouble than it's worth.

The problem is, simple things end up being overly complicated.  You 
can't just pop up a file dialog box to select a new CD-ROM ISO because 
you can't browse files on a remote machine.  Instead, you need to have 
something like a "pool" concept or something like that.

Regards,

Anthony Liguori

> But yeah, maybe it does add too much complexity. I don't know.
>
>
> Alex
>
>
Alexander Graf May 17, 2010, 10:55 p.m. UTC | #17
On 18.05.2010, at 00:47, Anthony Liguori wrote:

> On 05/17/2010 05:42 PM, malc wrote:
>>> In fact, couldn't we rather keep all graphic output out of qemu and
>>> just expose VNC, possibly with self-made additions to the protocol
>>> to speed up local rendering (thinking an SHM extension here)? Then
>>> we could still offer a separate SDL based viewer that could do the
>>> same things it does now. But we'd also open up the gate for a whole
>>> new integration level with possible GUIs.
>>> 
>>>     
>> This idea is not new, nothing has come out of it till this day, so the
>> answer to your question (couldn't we...) is probably: no, we couldn't.
>>   
> 
> Because shared memory is just a graphics optimization and for most users, the difference between gtk-vnc and native SDL isn't noticable.  So if a shared memory transport was the key missing piece, we'd have an awesome GUI based on gtk-vnc that just had slower graphics.

Well, there's also the missing QMP part :)

> IMHO, the problem with an external GUI is that the interaction just gets too complicated.

What interaction do you mean? I'm not advocating to move the GUI to a different project. I was more thinking of a separation like with perf where the kernel side does the recording and the userspace side does the displaying of profiling results. Qemu would run the VM and the tightly coupled viewer app would show it.

If you like, we could even move the backend qemu to "qemu-backend" and have the normally invoked binaries be the GUI application that just runs the respective qemu-backend application. That way it'd be 100% seamless for the average user, but qemu -demonize becomes really powerful.


Alex
Alexander Graf May 17, 2010, 10:59 p.m. UTC | #18
On 18.05.2010, at 00:54, Anthony Liguori wrote:

> On 05/17/2010 05:49 PM, Alexander Graf wrote:
>>>>  Then we could still offer a separate SDL based viewer that could do the same things it does now. But we'd also open up the gate for a whole new integration level with possible GUIs.
>>>> 
>>>>       
>>> You could, but I think it introduces more complexity which just is going to get in the way of building a good GUI.
>>>     
>> The main benefit I see by taking an always-vnc approach would be that everything becomes 100% networkable. There's nothing getting in your way because you're doing things on a remote machine. And you even get the same look&feel you got from the local connection because it's the same tool connecting you.
>>   
> 
> My current thinking with GUIs is that network transparency is more trouble than it's worth.
> 
> The problem is, simple things end up being overly complicated.  You can't just pop up a file dialog box to select a new CD-ROM ISO because you can't browse files on a remote machine.  Instead, you need to have something like a "pool" concept or something like that.

Yeah - VMware solved that by showing you a dialog with the remote file system. Pretty ugly.
Another solution to that would be to only enable the dialog box when target == localhost.

As soon as we look at server workloads, we do need to have network transparency. But I guess most of this talk is moot anyways, since we have VNC now. So if there is someone willing to take up on a GUI, he can just do so the same as he could with a unified backend.


Alex
Anthony Liguori May 17, 2010, 11:17 p.m. UTC | #19
On 05/17/2010 05:55 PM, Alexander Graf wrote:
>> IMHO, the problem with an external GUI is that the interaction just gets too complicated.
>>      
> What interaction do you mean? I'm not advocating to move the GUI to a different project. I was more thinking of a separation like with perf where the kernel side does the recording and the userspace side does the displaying of profiling results. Qemu would run the VM and the tightly coupled viewer app would show it.
>    

If it's the same project, why go through the extra work of plumbing 
everything through an RPC interface?  I'm suggesting that we want to 
make writing a good GUI as easy as possible and IMHO that means not 
putting up an artificial constraint like everything needs to be done 
through RPC.

But we're putting the cart before the horse.  Let's save this argument 
until we have some patches :-)

Regards,

Anthony Liguori

> If you like, we could even move the backend qemu to "qemu-backend" and have the normally invoked binaries be the GUI application that just runs the respective qemu-backend application. That way it'd be 100% seamless for the average user, but qemu -demonize becomes really powerful.
>
>
> Alex
>
>
K D May 18, 2010, 12:26 a.m. UTC | #20
Hi

I am able to boot my custom kernel off of bare hardware, but when I try to boot this with qemu it hangs after first two lines of print about BIOS. i tried booting through qemu image and also via '-kernel' arg. same result in both cases. i verified that with same qeumu-system-x86_64 i could boot ubuntu kernel/initrd in qemu image and also with -kernel arg but not my kernel.

i'm using pc-bios dir as is with all its subdirs and using it as "-L path_to_pc-bios". can someone help me understand what could be going on. 

 appreciate your help.
kd
Kevin Wolf May 18, 2010, 8:09 a.m. UTC | #21
Am 17.05.2010 23:43, schrieb Anthony Liguori:
> On 05/17/2010 04:35 PM, malc wrote:
>> There's one thing that SDL does marvelously well - it's just one fairly
>> small and self contained library that doesn't unleash dependency hell on
>> the user.
>>    
>>> The fact that we have cocoa support in the tree is basically an admission of
>>> failure with SDL.
>>>      
>> I don't think so, the way i see it: someone had an itch (i.e. an
>> application that does not integrate well with his windowing environment)
>> and he scratched it.
>>    
> 
> SDL doesn't integrate well into a modern Gnome desktop either.  I don't 
> see why we have Cocoa and not Gtk.  If the answer is, someone needs to 
> send patches, expect patches soon :-)

So with this argument, we'll not only get a GTK backend, but Qt and
Windows backends, too? But then you can't reasonably say any more that
DirectFB would be too much additional code to maintain.

Kevin
Stefano Stabellini May 18, 2010, 9:12 a.m. UTC | #22
On Tue, 18 May 2010, Kevin Wolf wrote:
> Am 17.05.2010 23:43, schrieb Anthony Liguori:
> > On 05/17/2010 04:35 PM, malc wrote:
> >> There's one thing that SDL does marvelously well - it's just one fairly
> >> small and self contained library that doesn't unleash dependency hell on
> >> the user.
> >>    
> >>> The fact that we have cocoa support in the tree is basically an admission of
> >>> failure with SDL.
> >>>      
> >> I don't think so, the way i see it: someone had an itch (i.e. an
> >> application that does not integrate well with his windowing environment)
> >> and he scratched it.
> >>    
> > 
> > SDL doesn't integrate well into a modern Gnome desktop either.  I don't 
> > see why we have Cocoa and not Gtk.  If the answer is, someone needs to 
> > send patches, expect patches soon :-)
> 
> So with this argument, we'll not only get a GTK backend, but Qt and
> Windows backends, too? But then you can't reasonably say any more that
> DirectFB would be too much additional code to maintain.
 
My personal opinion is that SDL does a decent job at rendering a window
in a X11 environment, but given the current SDL limitation with
directfb, we need another output mechanism to cover that case, so that
we can have multiple guests fullscreen on different host virtual
terminals. This is an important use case for embedded environments.

I don't think GTK or Qt would add much to what SDL already offers,
unless we want to develop our own management GUI for qemu, but I don't
think is a very good idea.
I think it would be better to implement an accelerated frontend for
rendering the framebuffer, like opengl or xv.
Gerd Hoffmann May 18, 2010, 9:23 a.m. UTC | #23
On 05/18/10 11:12, Stefano Stabellini wrote:
> I think it would be better to implement an accelerated frontend for
> rendering the framebuffer, like opengl or xv.

Well.  xv is pretty pointless IMHO.  gl makes sense.  But to have some 
effect this needs some major restructions in qemu, the current 
DisplayState infrastructure can't handle anything but a simple, stupid 
framebuffer.  There isn't much to accelerate, except maybe scaling the 
guest display to fullscreen on the host.

qxl + spice will change that though.  qxl is a paravirtualized gfx 
adapter.   Guest sends rendering commands.  The spice protocol sends the 
rendering commands over the wire to the spice client, which in turn will 
render them (and can use gl to accelerate that).

cheers,
   Gerd
Stefano Stabellini May 18, 2010, 9:29 a.m. UTC | #24
On Tue, 18 May 2010, Gerd Hoffmann wrote:
> On 05/18/10 11:12, Stefano Stabellini wrote:
> > I think it would be better to implement an accelerated frontend for
> > rendering the framebuffer, like opengl or xv.
> 
> Well.  xv is pretty pointless IMHO.  gl makes sense.  But to have some 
> effect this needs some major restructions in qemu, the current 
> DisplayState infrastructure can't handle anything but a simple, stupid 
> framebuffer.  There isn't much to accelerate, except maybe scaling the 
> guest display to fullscreen on the host.
> 
> qxl + spice will change that though.  qxl is a paravirtualized gfx 
> adapter.   Guest sends rendering commands.  The spice protocol sends the 
> rendering commands over the wire to the spice client, which in turn will 
> render them (and can use gl to accelerate that).
 
Is the spice client going to live in qemu, or is it going to be
separate?
Gerd Hoffmann May 18, 2010, 9:39 a.m. UTC | #25
On 05/18/10 11:29, Stefano Stabellini wrote:
> On Tue, 18 May 2010, Gerd Hoffmann wrote:
>> On 05/18/10 11:12, Stefano Stabellini wrote:
>>> I think it would be better to implement an accelerated frontend for
>>> rendering the framebuffer, like opengl or xv.
>>
>> Well.  xv is pretty pointless IMHO.  gl makes sense.  But to have some
>> effect this needs some major restructions in qemu, the current
>> DisplayState infrastructure can't handle anything but a simple, stupid
>> framebuffer.  There isn't much to accelerate, except maybe scaling the
>> guest display to fullscreen on the host.
>>
>> qxl + spice will change that though.  qxl is a paravirtualized gfx
>> adapter.   Guest sends rendering commands.  The spice protocol sends the
>> rendering commands over the wire to the spice client, which in turn will
>> render them (and can use gl to accelerate that).
>
> Is the spice client going to live in qemu, or is it going to be
> separate?

Separate.

project website: http://www.spice-space.org/
spice bits: http://cgit.freedesktop.org/~kraxel/spice/log/?h=api.v6
qemu patches: http://cgit.freedesktop.org/spice/qemu/log/?h=spice.v6.0

cheers,
   Gerd
Stefano Stabellini May 18, 2010, 10:34 a.m. UTC | #26
On Tue, 18 May 2010, Gerd Hoffmann wrote:
> On 05/18/10 11:29, Stefano Stabellini wrote:
> > On Tue, 18 May 2010, Gerd Hoffmann wrote:
> >> On 05/18/10 11:12, Stefano Stabellini wrote:
> >>> I think it would be better to implement an accelerated frontend for
> >>> rendering the framebuffer, like opengl or xv.
> >>
> >> Well.  xv is pretty pointless IMHO.  gl makes sense.  But to have some
> >> effect this needs some major restructions in qemu, the current
> >> DisplayState infrastructure can't handle anything but a simple, stupid
> >> framebuffer.  There isn't much to accelerate, except maybe scaling the
> >> guest display to fullscreen on the host.
> >>
> >> qxl + spice will change that though.  qxl is a paravirtualized gfx
> >> adapter.   Guest sends rendering commands.  The spice protocol sends the
> >> rendering commands over the wire to the spice client, which in turn will
> >> render them (and can use gl to accelerate that).
> >
> > Is the spice client going to live in qemu, or is it going to be
> > separate?
> 
> Separate.
> 
> project website: http://www.spice-space.org/
> spice bits: http://cgit.freedesktop.org/~kraxel/spice/log/?h=api.v6
> qemu patches: http://cgit.freedesktop.org/spice/qemu/log/?h=spice.v6.0

Then I guess we don't actually need any accelerated rendering in qemu,
even though it might still be nice for avoiding a memcpy.

I am curious about one thing: if the spice client is running on the same
host as the VM and qemu, is there any plan for sharing memory somehow
between the two components? OR is it not believed to be necessary to
reach good performances?
Gerd Hoffmann May 18, 2010, 11:20 a.m. UTC | #27
On 05/18/10 12:34, Stefano Stabellini wrote:

> I am curious about one thing: if the spice client is running on the same
> host as the VM and qemu, is there any plan for sharing memory somehow
> between the two components? OR is it not believed to be necessary to
> reach good performances?

Well.  We don't have shm for vnc.  And I think the reason simply is that 
it feels fast enougth even without shm.  Spice tries to reduce the 
network bandwith needed with image caching, so with spice the gains by 
using shm should be even smaller than with vnc.

I'm not aware of anyone trying + benchmark it, but I don't expect major 
gains.

cheers,
   Gerd
Anthony Liguori May 18, 2010, 1:02 p.m. UTC | #28
On 05/18/2010 03:09 AM, Kevin Wolf wrote:
> Am 17.05.2010 23:43, schrieb Anthony Liguori:
>    
>> On 05/17/2010 04:35 PM, malc wrote:
>>      
>>> There's one thing that SDL does marvelously well - it's just one fairly
>>> small and self contained library that doesn't unleash dependency hell on
>>> the user.
>>>
>>>        
>>>> The fact that we have cocoa support in the tree is basically an admission of
>>>> failure with SDL.
>>>>
>>>>          
>>> I don't think so, the way i see it: someone had an itch (i.e. an
>>> application that does not integrate well with his windowing environment)
>>> and he scratched it.
>>>
>>>        
>> SDL doesn't integrate well into a modern Gnome desktop either.  I don't
>> see why we have Cocoa and not Gtk.  If the answer is, someone needs to
>> send patches, expect patches soon :-)
>>      
> So with this argument, we'll not only get a GTK backend, but Qt and
> Windows backends, too? But then you can't reasonably say any more that
> DirectFB would be too much additional code to maintain.
>    

Yes, that's the point.  Instead of having a single backend (SDL) and 
expecting SDL to do everything for us, we would support multiple 
backends (like DirectFB).

Regards,

Anthony Liguori

> Kevin
>
diff mbox

Patch

diff --git a/Makefile b/Makefile
index eb9e02b..6932c81 100644
--- a/Makefile
+++ b/Makefile
@@ -106,6 +106,10 @@  sdl.o: sdl.c keymaps.h sdl_keysym.h sdl_zoom.h
 
 sdl.o audio/sdlaudio.o sdl_zoom.o baum.o: QEMU_CFLAGS += $(SDL_CFLAGS)
 
+directfb.o: directfb.c
+
+directfb.o: QEMU_CFLAGS += $(DIRECTFB_CFLAGS)
+
 acl.o: acl.h acl.c
 
 vnc.h: vnc-tls.h vnc-auth-vencrypt.h vnc-auth-sasl.h keymaps.h
diff --git a/Makefile.objs b/Makefile.objs
index ecdd53e..0904b07 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -102,6 +102,7 @@  common-obj-y += $(addprefix audio/, $(audio-obj-y))
 common-obj-y += keymaps.o
 common-obj-$(CONFIG_SDL) += sdl.o sdl_zoom.o x_keymap.o
 common-obj-$(CONFIG_CURSES) += curses.o
+common-obj-$(CONFIG_DIRECTFB) += directfb.o
 common-obj-y += vnc.o acl.o d3des.o
 common-obj-y += vnc-encoding-zlib.o vnc-encoding-hextile.o
 common-obj-y += iov.o
diff --git a/configure b/configure
index 36d028f..eb73415 100755
--- a/configure
+++ b/configure
@@ -258,6 +258,7 @@  kvm=""
 kvm_para=""
 nptl=""
 sdl=""
+directfb="no"
 sparse="no"
 uuid=""
 vde=""
@@ -502,6 +503,10 @@  for opt do
   ;;
   --sysconfdir=*) sysconfdir="$optarg"
   ;;
+  --disable-directfb) directfb="no"
+  ;;
+  --enable-directfb) directfb="yes"
+  ;;
   --disable-sdl) sdl="no"
   ;;
   --enable-sdl) sdl="yes"
@@ -763,6 +768,8 @@  echo "  --disable-strip          disable stripping binaries"
 echo "  --disable-werror         disable compilation abort on warning"
 echo "  --disable-sdl            disable SDL"
 echo "  --enable-sdl             enable SDL"
+echo "  --disable-directfb       disable DirectFB"
+echo "  --enable-directfb        enable DirectFB"
 echo "  --enable-cocoa           enable COCOA (Mac OS X only)"
 echo "  --audio-drv-list=LIST    set audio drivers list:"
 echo "                           Available drivers: $audio_possible_drivers"
@@ -1062,6 +1069,15 @@  if test "$sparse" != "no" ; then
 fi
 
 ##########################################
+# DirectFB probe
+
+if test "$directfb" = "yes" ; then
+  directfb_libs=`directfb-config --libs`
+  directfb_cflags=`directfb-config --cflags`
+  libs_softmmu="$directfb_libs $libs_softmmu"
+fi
+
+##########################################
 # SDL probe
 
 if $pkgconfig sdl --modversion >/dev/null 2>&1; then
@@ -1999,6 +2015,7 @@  if test "$darwin" = "yes" ; then
     echo "Cocoa support     $cocoa"
 fi
 echo "SDL support       $sdl"
+echo "DirectFB support  $directfb"
 echo "curses support    $curses"
 echo "curl support      $curl"
 echo "check support     $check_utests"
@@ -2169,6 +2186,10 @@  fi
 if test "$cocoa" = "yes" ; then
   echo "CONFIG_COCOA=y" >> $config_host_mak
 fi
+if test "$directfb" = "yes" ; then
+  echo "CONFIG_DIRECTFB=y" >> $config_host_mak
+  echo "DIRECTFB_CFLAGS=$directfb_cflags" >> $config_host_mak
+fi
 if test "$curses" = "yes" ; then
   echo "CONFIG_CURSES=y" >> $config_host_mak
 fi
diff --git a/console.h b/console.h
index 6def115..d1dd211 100644
--- a/console.h
+++ b/console.h
@@ -335,6 +335,9 @@  void qemu_console_resize(DisplayState *ds, int width, int height);
 void qemu_console_copy(DisplayState *ds, int src_x, int src_y,
                        int dst_x, int dst_y, int w, int h);
 
+/* directfb.c */
+void directfb_display_init(DisplayState *ds);
+
 /* sdl.c */
 void sdl_display_init(DisplayState *ds, int full_screen, int no_frame);
 
diff --git a/directfb.c b/directfb.c
new file mode 100644
index 0000000..6dea99a
--- /dev/null
+++ b/directfb.c
@@ -0,0 +1,394 @@ 
+/*
+ * QEMU DirectFB display driver
+ *
+ * Copyright (c) 2010 Citrix Systems, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <console.h>
+#include <keymaps.h>
+
+#include <directfb.h>
+
+static IDirectFB *dfb = NULL;
+static IDirectFBSurface *primary = NULL;
+static IDirectFBEventBuffer *events = NULL;
+static IDirectFBSurface *guest = NULL;
+
+static void *screen_data = NULL;
+static int screen_pitch = 0;
+static int screen_bpp = 0;
+static int screen_width  = 0;
+static int screen_height = 0;
+static int scaling = 0;
+
+#define DIRECTFB_IS_VIDEO_PTR(p) \
+    (p >= (uint8_t *) screen_data && \
+     p < (uint8_t *) screen_data + screen_height * screen_pitch)
+
+static DFBSurfacePixelFormat directfb_bpp_to_pixelformat(int bpp)
+{
+    switch (bpp) {
+        case 16:
+            return DSPF_RGB16;
+        case 24:
+            return DSPF_RGB24;
+        case 32:
+            return DSPF_RGB32;
+        default:
+            return DSPF_UNKNOWN;
+    }
+}
+
+static void directfb_clearscreen(void)
+{
+    if (screen_data != NULL) {
+        /* Surface is locked */
+        memset(screen_data, 0x0,
+               screen_pitch * screen_height);
+    } else {
+        primary->SetColor(primary, 0x0, 0x0, 0x0, 0x0);
+        primary->FillRectangle(primary, 0, 0, screen_width, screen_height);
+    }
+}
+
+static void directfb_update(struct DisplayState *s, int x, int y, int w, int h)
+{
+    DFBRegion region = {x, y, x + w, y + h};
+
+    if (guest) {
+        if (scaling) {
+            primary->StretchBlit(primary, guest, NULL, NULL);
+        } else {
+            int xoff = (screen_width - ds_get_width(s)) / 2;
+            int yoff = (screen_height - ds_get_height(s)) / 2;
+
+            primary->Blit(primary, guest, NULL, xoff, yoff);
+
+            region.x1 += xoff;
+            region.y1 += yoff;
+            region.x2 += xoff;
+            region.x2 += yoff;
+        }
+    }
+
+    primary->Flip(primary, &region, DSFLIP_NONE);
+}
+
+static void directfb_setdata(DisplayState *s)
+{
+    DFBSurfaceDescription dsc;
+
+    if (guest) {
+        guest->Release(guest);
+        guest = NULL;
+    }
+
+    dsc.flags = DSDESC_WIDTH | DSDESC_HEIGHT |
+                DSDESC_PIXELFORMAT | DSDESC_PREALLOCATED;
+    dsc.width = ds_get_width(s);
+    dsc.height = ds_get_height(s);
+    dsc.pixelformat = directfb_bpp_to_pixelformat(ds_get_bits_per_pixel(s));
+    dsc.preallocated[0].data = ds_get_data(s);
+    dsc.preallocated[0].pitch = ds_get_linesize(s);
+
+    dfb->CreateSurface(dfb, &dsc, &guest);
+}
+
+static void directfb_resize(struct DisplayState *s)
+{
+    directfb_clearscreen();
+
+    if (scaling || ds_get_bits_per_pixel(s) != screen_bpp ||
+        ds_get_linesize(s) != screen_pitch ||
+        !DIRECTFB_IS_VIDEO_PTR(ds_get_data(s))) {
+
+        directfb_setdata(s);
+    } else {
+        if (guest) {
+            guest->Release(guest);
+            guest = NULL;
+        }
+    }
+}
+
+static int directfb_buttons_state(DFBInputEvent *ev)
+{
+    int buttons = 0;
+
+    if (ev->buttons & DIBM_LEFT) {
+        buttons |= MOUSE_EVENT_LBUTTON;
+    }
+    if (ev->buttons & DIBM_RIGHT) {
+        buttons |= MOUSE_EVENT_RBUTTON;
+    }
+    if (ev->buttons & DIBM_MIDDLE) {
+        buttons |= MOUSE_EVENT_MBUTTON;
+    }
+
+    return buttons;
+}
+
+static void directfb_put_keycode(char keycode, int up)
+{
+    int scancode = keycode;
+
+    /* Pause/Break */
+    if (keycode == 119) {
+	scancode = 0x45;
+        kbd_put_keycode(0xe1);
+        kbd_put_keycode(0x1d | up ? 0x80 : 0x0);
+    } else {
+        /* grey key */
+        if (keycode >= 0x60 && keycode < 0x70) {
+            const char esc[16] = {0x1c, 0x1d, 0x35, 0x37,
+                                  0x38, 0x46, 0x47, 0x48,
+                                  0x49, 0x4b, 0x4d, 0x4f,
+                                  0x50, 0x51, 0x52, 0x53};
+            scancode = esc[keycode - 0x60];
+            kbd_put_keycode(0xe0);
+
+            /* PrintScreen */
+            if (keycode == 99) {
+                scancode = 0x37;
+                kbd_put_keycode(0x2a | up ? 0x80 : 0x0);
+                kbd_put_keycode(0xe0);
+            }
+        }
+    }
+
+    kbd_put_keycode(scancode | (up ? 0x80 : 0x0));
+}
+
+static void directfb_toggle_fullscreen(struct DisplayState *ds)
+{
+    scaling = !scaling;
+
+    vga_hw_invalidate();
+    vga_hw_update();
+}
+
+static void directfb_refresh(struct DisplayState *s)
+{
+    DFBInputEvent ev;
+
+    vga_hw_update();
+
+    while (events->GetEvent(events, DFB_EVENT(&ev)) == DFB_OK) {
+        switch (ev.type) {
+            case DIET_KEYRELEASE:
+                directfb_put_keycode(ev.key_code, 1);
+                break;
+            case DIET_KEYPRESS:
+                /* Toggle centered/fullscreen */
+                if ((ev.modifiers & DIMM_CONTROL) &&
+                    (ev.modifiers & DIMM_ALT) &&
+                    (ev.key_id == DIKI_ENTER)) {
+                    directfb_toggle_fullscreen(s);
+                    break;
+                }
+                directfb_put_keycode(ev.key_code, 0);
+                break;
+            case DIET_BUTTONPRESS:
+            case DIET_BUTTONRELEASE:
+            case DIET_AXISMOTION:
+            {
+                int buttons = directfb_buttons_state(&ev);
+                int dx = 0;
+                int dy = 0;
+                int dz = 0;
+
+                if (ev.type == DIET_AXISMOTION) {
+                    if (ev.axis == DIAI_X) {
+                        dx = ev.axisrel;
+                    }
+                    if (ev.axis == DIAI_Y) {
+                        dy = ev.axisrel;
+                    }
+                    if (ev.axis == DIAI_Z) {
+                        dz = ev.axisrel;
+                    }
+                }
+
+                kbd_mouse_event(dx, dy, dz, buttons);
+                break;
+            }
+            case DIET_UNKNOWN:
+            default:
+                break;
+
+        }
+    }
+}
+
+static DisplaySurface* directfb_create_displaysurface(int width, int height)
+{
+    DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
+    DFBSurfacePixelFormat spf;
+    surface->width = width;
+    surface->height = height;
+
+    primary->GetPixelFormat(primary, &spf);
+
+    if (scaling) {
+        int bytes_per_pixel = DFB_BYTES_PER_PIXEL(spf);
+
+        if (bytes_per_pixel != 2 && bytes_per_pixel != 4) {
+            bytes_per_pixel = 4;
+        }
+
+        surface->pf = qemu_default_pixelformat(8 * bytes_per_pixel);
+        surface->linesize = width * bytes_per_pixel;
+
+        surface->flags = QEMU_ALLOCATED_FLAG;
+        surface->data = qemu_mallocz(surface->linesize * surface->height);
+    } else {
+        primary->Lock(primary, DSLF_READ | DSLF_WRITE, &screen_data, &screen_pitch);
+        surface->pf = qemu_default_pixelformat(screen_bpp);
+        surface->flags = QEMU_REALPIXELS_FLAG;
+        surface->linesize = screen_pitch;
+        surface->data = screen_data +
+                        ((screen_height - height) / 2) * screen_pitch +
+                        ((screen_width - width) / 2) * (screen_bpp / 8);
+    }
+
+    return surface;
+}
+
+static void directfb_free_displaysurface(DisplaySurface *surface)
+{
+    if (surface == NULL)
+        return;
+
+    if (surface->flags & QEMU_ALLOCATED_FLAG) {
+        qemu_free(surface->data);
+    } else if (surface->flags & QEMU_REALPIXELS_FLAG) {
+        primary->Unlock(primary);
+        screen_data = NULL;
+        screen_pitch = 0;
+    }
+
+    surface->data = NULL;
+
+    qemu_free(surface);
+}
+
+static DisplaySurface* directfb_resize_displaysurface(DisplaySurface *surface,
+                                                      int width,
+                                                      int height)
+{
+    directfb_free_displaysurface(surface);
+    return directfb_create_displaysurface(width, height);
+}
+
+static DFBEnumerationResult directfb_attach_inputdevice(DFBInputDeviceID device_id,
+                                                        DFBInputDeviceDescription desc,
+                                                        void *data)
+{
+    if (!strcmp(desc.vendor, "Linux")) {
+        return DFENUM_OK;
+    }
+
+    if (desc.type == DIDID_KEYBOARD || desc.type | DIDTF_MOUSE) {
+        IDirectFBInputDevice *device;
+
+        dfb->GetInputDevice(dfb, device_id, &device);
+
+        if (events == NULL) {
+            device->CreateEventBuffer(device, &events);
+        } else {
+            device->AttachEventBuffer(device, events);
+        }
+    }
+
+    return DFENUM_OK;
+}
+
+void directfb_display_init(DisplayState *ds)
+{
+    DisplayChangeListener *dcl;
+    DisplayAllocator *da;
+    DFBResult status;
+    DFBSurfaceDescription dsc;
+    DFBSurfaceCapabilities caps;
+    DFBSurfacePixelFormat spf;
+
+    /*
+     * Prevent DirectFB to read qemu command line argument in procfs and
+     * parse it.
+     */
+    char prog_name[] = "qemu";
+    char *prog_argv[] = {prog_name};
+    char **dfb_argv = prog_argv;
+    int dfb_argc = 1;
+
+    status = DirectFBInit(&dfb_argc, &dfb_argv);
+    if (status != DFB_OK) {
+        fprintf(stderr, "Could not initialize DirectFB(%d) - exiting\n", status);
+        exit(1);
+    }
+
+    DirectFBCreate(&dfb);
+    dfb->SetCooperativeLevel(dfb, DFSCL_FULLSCREEN);
+    dsc.flags = DSDESC_CAPS;
+    dsc.caps = DSCAPS_PRIMARY | DSCAPS_VIDEOONLY | DSCAPS_SHARED;
+    status = dfb->CreateSurface(dfb, &dsc, &primary);
+
+    if (status != DFB_OK) {
+        fprintf(stderr, "Could not create DirectFB surface(%d) - exiting\n", status);
+        exit(1);
+    }
+
+    /* Double check surface capabilities */
+    primary->GetCapabilities(primary, &caps);
+    if ((caps & dsc.caps) != dsc.caps ||
+        caps & DSCAPS_FLIPPING || caps & DSCAPS_INTERLACED ||
+        caps & DSCAPS_SYSTEMONLY) {
+        fprintf(stderr, "Wrong DirectFB surface capabilities - exiting\n");
+        exit(1);
+    }
+
+    primary->GetSize(primary, &screen_width, &screen_height);
+    primary->GetPixelFormat(primary, &spf);
+    screen_bpp = DFB_BITS_PER_PIXEL(spf);
+
+    dfb->EnumInputDevices(dfb, directfb_attach_inputdevice, NULL);
+
+    fprintf(stderr, "Initialized QEMU DirectFB driver. (%dx%d)\n",
+            screen_width, screen_height);
+
+    dcl = qemu_mallocz(sizeof(DisplayChangeListener));
+    dcl->dpy_update = directfb_update;
+    dcl->dpy_resize = directfb_resize;
+    dcl->dpy_refresh = directfb_refresh;
+    dcl->dpy_setdata = directfb_setdata;
+    register_displaychangelistener(ds, dcl);
+
+    da = qemu_mallocz(sizeof(DisplayAllocator));
+    da->create_displaysurface = directfb_create_displaysurface;
+    da->resize_displaysurface = directfb_resize_displaysurface;
+    da->free_displaysurface = directfb_free_displaysurface;
+
+    directfb_clearscreen();
+
+    if (register_displayallocator(ds, da) == da) {
+        dpy_resize(ds);
+    }
+}
diff --git a/qemu-options.hx b/qemu-options.hx
index 12f6b51..a4bdfbe 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -608,6 +608,16 @@  QEMU can display the VGA output when in text mode using a
 curses/ncurses interface.  Nothing is displayed in graphical mode.
 ETEXI
 
+#ifdef CONFIG_DIRECTFB
+DEF("directfb", 0, QEMU_OPTION_directfb,
+    "-directfb       enable DirectFB\n")
+#endif
+STEXI
+@item -directfb
+@findex -directfb
+Enable DirectFB.
+ETEXI
+
 #ifdef CONFIG_SDL
 DEF("no-frame", 0, QEMU_OPTION_no_frame,
     "-no-frame       open SDL window without a frame and window decorations\n",
diff --git a/sysemu.h b/sysemu.h
index fa921df..a2cd5b0 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -98,6 +98,7 @@  typedef enum DisplayType
     DT_CURSES,
     DT_SDL,
     DT_VNC,
+    DT_DIRECTFB,
     DT_NOGRAPHIC,
 } DisplayType;
 
diff --git a/vl.c b/vl.c
index 85bcc84..e6235fa 100644
--- a/vl.c
+++ b/vl.c
@@ -3199,6 +3199,11 @@  int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_full_screen:
                 full_screen = 1;
                 break;
+#ifdef CONFIG_DIRECTFB
+            case QEMU_OPTION_directfb:
+                display_type = DT_DIRECTFB;
+                break;
+#endif
 #ifdef CONFIG_SDL
             case QEMU_OPTION_no_frame:
                 no_frame = 1;
@@ -3765,6 +3770,8 @@  int main(int argc, char **argv, char **envp)
     if (display_type == DT_DEFAULT) {
 #if defined(CONFIG_SDL) || defined(CONFIG_COCOA)
         display_type = DT_SDL;
+#elif defined(CONFIG_DIRECTFB)
+        display_type = DT_DIRECTFB;
 #else
         display_type = DT_VNC;
         vnc_display = "localhost:0,to=99";
@@ -3781,6 +3788,11 @@  int main(int argc, char **argv, char **envp)
         curses_display_init(ds, full_screen);
         break;
 #endif
+#if defined(CONFIG_DIRECTFB)
+    case DT_DIRECTFB:
+        directfb_display_init(ds);
+        break;
+#endif
 #if defined(CONFIG_SDL)
     case DT_SDL:
         sdl_display_init(ds, full_screen, no_frame);