[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] Re: [PATCH 5/5] linux fbdev display driver.
From: |
Julian Pidancet |
Subject: |
[Qemu-devel] Re: [PATCH 5/5] linux fbdev display driver. |
Date: |
Wed, 16 Jun 2010 17:22:48 +0100 |
User-agent: |
Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.9) Gecko/20100330 Shredder/3.0.4 |
On 06/16/2010 01:44 PM, Stefano Stabellini wrote:
>
> the patch still doesn't use the display allocator interface, but it
> shouldn't be difficult to implement support for it on top of this patch,
> so it is fine by me.
>
This patch adds display allocator support in the fbdev driver.
This way we avoid memcpying when the guest surface is compatible with the
physical surface.
diff --git a/fbdev.c b/fbdev.c
index 54f2381..83104c0 100644
--- a/fbdev.c
+++ b/fbdev.c
@@ -69,11 +69,10 @@ static int fb_switch_state = FB_ACTIVE;
static DisplayChangeListener *dcl;
static QemuPfConv *conv;
static PixelFormat fbpf;
-static int resize_screen;
-static int redraw_screen;
static int cx, cy, cw, ch;
static int debug = 0;
static Notifier exit_notifier;
+uint8_t *guest_surface;
/* fwd decls */
static int fbdev_activate_vt(int tty, int vtno, bool wait);
@@ -786,10 +785,10 @@ static void fbdev_render(DisplayState *ds, int x, int y,
int w, int h)
uint8_t *src;
int line;
- if (!conv)
+ if (!conv || !guest_surface)
return;
- src = ds_get_data(ds) + y * ds_get_linesize(ds)
+ src = guest_surface + y * ds_get_linesize(ds)
+ x * ds_get_bytes_per_pixel(ds);
dst = fb_mem + y * fb_fix.line_length
+ x * fbpf.bytes_per_pixel;
@@ -819,46 +818,50 @@ static void fbdev_update(DisplayState *ds, int x, int y,
int w, int h)
if (fb_switch_state != FB_ACTIVE)
return;
- if (resize_screen) {
- if (debug)
- fprintf(stderr, "%s: handle resize\n", __FUNCTION__);
- resize_screen = 0;
- cx = 0; cy = 0;
- cw = ds_get_width(ds);
- ch = ds_get_height(ds);
- if (ds_get_width(ds) < fb_var.xres) {
- cx = (fb_var.xres - ds_get_width(ds)) / 2;
- }
- if (ds_get_height(ds) < fb_var.yres) {
- cy = (fb_var.yres - ds_get_height(ds)) / 2;
- }
+ if (guest_surface != NULL) {
+ fbdev_render(ds, x, y, w, h);
+ }
+}
- if (conv) {
- qemu_pf_conv_put(conv);
- }
- conv = qemu_pf_conv_get(&fbpf, &ds->surface->pf);
- if (conv == NULL) {
- fprintf(stderr, "fbdev: unsupported PixelFormat conversion\n");
- }
+static void fbdev_setdata(DisplayState *ds)
+{
+ if (conv) {
+ qemu_pf_conv_put(conv);
}
- if (redraw_screen) {
- if (debug)
- fprintf(stderr, "%s: handle redraw\n", __FUNCTION__);
- redraw_screen = 0;
- fbdev_cls();
- x = 0; y = 0; w = ds_get_width(ds); h = ds_get_height(ds);
+ conv = qemu_pf_conv_get(&fbpf, &ds->surface->pf);
+ if (conv == NULL) {
+ fprintf(stderr, "fbdev: unsupported PixelFormat conversion\n");
}
- fbdev_render(ds, x, y, w, h);
+ guest_surface = ds_get_data(ds);
}
static void fbdev_resize(DisplayState *ds)
{
- if (debug)
- fprintf(stderr, "%s: request resize+redraw\n", __FUNCTION__);
- resize_screen++;
- redraw_screen++;
+ int is_video_ptr;
+
+ if (fb_switch_state == FB_ACTIVE) {
+ fbdev_cls();
+ }
+
+ is_video_ptr = ds_get_data(ds) >= fb_mem + fb_mem_offset &&
+ ds_get_data(ds) < fb_mem + fb_fix.smem_len + fb_mem_offset;
+
+ if (ds_get_bits_per_pixel(ds) != fbpf.bits_per_pixel ||
+ ds_get_linesize(ds) != fb_fix.line_length ||
+ !is_video_ptr) {
+ cx = 0; cy = 0;
+ if (ds_get_width(ds) < fb_var.xres) {
+ cx = (fb_var.xres - ds_get_width(ds)) / 2;
+ }
+ if (ds_get_height(ds) < fb_var.yres) {
+ cy = (fb_var.yres - ds_get_height(ds)) / 2;
+ }
+ fbdev_setdata(ds);
+ } else {
+ guest_surface = NULL;
+ }
}
static void fbdev_refresh(DisplayState *ds)
@@ -866,21 +869,17 @@ static void fbdev_refresh(DisplayState *ds)
switch (fb_switch_state) {
case FB_REL_REQ:
fbdev_switch_release();
+ vga_hw_invalidate();
case FB_INACTIVE:
return;
case FB_ACQ_REQ:
fbdev_switch_acquire();
- redraw_screen++;
- if (debug)
- fprintf(stderr, "%s: request redraw\n", __FUNCTION__);
+ vga_hw_invalidate();
case FB_ACTIVE:
break;
}
vga_hw_update();
- if (redraw_screen) {
- fbdev_update(ds, 0, 0, 0, 0);
- }
}
static void fbdev_exit_notifier(Notifier *notifier)
@@ -888,8 +887,58 @@ static void fbdev_exit_notifier(Notifier *notifier)
fbdev_cleanup();
}
+static DisplaySurface *fbdev_create_displaysurface(int width, int height)
+{
+ DisplaySurface *surface = qemu_mallocz(sizeof (DisplaySurface));
+
+ surface->width = width;
+ surface->height = height;
+
+ surface->pf = fbpf;
+ surface->linesize = fb_fix.line_length;
+
+ if (fb_switch_state == FB_INACTIVE) {
+ surface->flags = QEMU_ALLOCATED_FLAG;
+ surface->data = qemu_mallocz(surface->linesize * surface->height);
+ } else {
+ surface->flags = QEMU_REALPIXELS_FLAG;
+ surface->data = fb_mem;
+
+ if (width < fb_var.xres)
+ surface->data += ((fb_var.xres - width) / 2) *
fbpf.bytes_per_pixel;
+ if (height < fb_var.yres)
+ surface->data += ((fb_var.yres - height) / 2) * fb_fix.line_length;
+ }
+
+ return surface;
+}
+
+static void fbdev_free_displaysurface(DisplaySurface *surface)
+{
+ if (surface == NULL)
+ return;
+
+ if (surface->flags & QEMU_ALLOCATED_FLAG) {
+ qemu_free(surface->data);
+ }
+
+ surface->data = NULL;
+
+ qemu_free(surface);
+}
+
+static DisplaySurface *fbdev_resize_displaysurface(DisplaySurface *surface,
+ int width,
+ int height)
+{
+ fbdev_free_displaysurface(surface);
+ return fbdev_create_displaysurface(width, height);
+}
+
void fbdev_display_init(DisplayState *ds, const char *device)
{
+ DisplayAllocator *da;
+
if (dcl != NULL) {
if (debug)
fprintf(stderr, "%s: already active\n", __FUNCTION__);
@@ -910,7 +959,17 @@ void fbdev_display_init(DisplayState *ds, const char
*device)
dcl->dpy_update = fbdev_update;
dcl->dpy_resize = fbdev_resize;
dcl->dpy_refresh = fbdev_refresh;
+ dcl->dpy_setdata = fbdev_setdata;
register_displaychangelistener(ds, dcl);
+
+ da = qemu_mallocz(sizeof (DisplayAllocator));
+ da->create_displaysurface = fbdev_create_displaysurface;
+ da->resize_displaysurface = fbdev_resize_displaysurface;
+ da->free_displaysurface = fbdev_free_displaysurface;
+
+ if (register_displayallocator(ds, da) == da) {
+ dpy_resize(ds);
+ }
}
void fbdev_display_uninit(void)
--
Julian Pidancet <address@hidden>
- [Qemu-devel] [PATCH 0/5] fbdev display driver + misc bits, Gerd Hoffmann, 2010/06/15
- [Qemu-devel] [PATCH 2/5] add unregister_displaychangelistener, Gerd Hoffmann, 2010/06/15
- [Qemu-devel] [PATCH 3/5] Fix and simplify gui timer logic., Gerd Hoffmann, 2010/06/15
- [Qemu-devel] [PATCH 1/5] QLIST-ify display change listeners., Gerd Hoffmann, 2010/06/15
- [Qemu-devel] [PATCH 4/5] add pflib: PixelFormat conversion library., Gerd Hoffmann, 2010/06/15
- [Qemu-devel] [PATCH 5/5] linux fbdev display driver., Gerd Hoffmann, 2010/06/15
- [Qemu-devel] Re: [PATCH 5/5] linux fbdev display driver., Stefano Stabellini, 2010/06/16
- [Qemu-devel] Re: [PATCH 5/5] linux fbdev display driver.,
Julian Pidancet <=
- [Qemu-devel] Re: [PATCH 5/5] linux fbdev display driver., Gerd Hoffmann, 2010/06/17
- [Qemu-devel] Re: [PATCH 5/5] linux fbdev display driver., Julian Pidancet, 2010/06/17
- Re: [Qemu-devel] Re: [PATCH 5/5] linux fbdev display driver., Julian Pidancet, 2010/06/17
- Re: [Qemu-devel] Re: [PATCH 5/5] linux fbdev display driver., Gerd Hoffmann, 2010/06/18
- Re: [Qemu-devel] Re: [PATCH 5/5] linux fbdev display driver., Julian Pidancet, 2010/06/18
Re: [Qemu-devel] [PATCH 0/5] fbdev display driver + misc bits, Julian Pidancet, 2010/06/24