From: Julian Pidancet <julian.pidancet@citrix.com>
To: Stefano Stabellini <Stefano.Stabellini@eu.citrix.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>,
"qemu-devel@nongnu.org" <qemu-devel@nongnu.org>
Subject: [Qemu-devel] Re: [PATCH 5/5] linux fbdev display driver.
Date: Wed, 16 Jun 2010 17:22:48 +0100 [thread overview]
Message-ID: <4C18FA58.5080808@citrix.com> (raw)
In-Reply-To: <alpine.DEB.2.00.1006161342110.3401@kaball-desktop>
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 <julian.pidancet@citrix.com>
next prev parent reply other threads:[~2010-06-16 16:18 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-06-15 10:05 [Qemu-devel] [PATCH 0/5] fbdev display driver + misc bits Gerd Hoffmann
2010-06-15 10:05 ` [Qemu-devel] [PATCH 1/5] QLIST-ify display change listeners Gerd Hoffmann
2010-06-15 10:05 ` [Qemu-devel] [PATCH 2/5] add unregister_displaychangelistener Gerd Hoffmann
2010-06-15 10:05 ` [Qemu-devel] [PATCH 3/5] Fix and simplify gui timer logic Gerd Hoffmann
2010-06-15 10:05 ` [Qemu-devel] [PATCH 4/5] add pflib: PixelFormat conversion library Gerd Hoffmann
2010-06-15 10:05 ` [Qemu-devel] [PATCH 5/5] linux fbdev display driver Gerd Hoffmann
2010-06-16 12:44 ` [Qemu-devel] " Stefano Stabellini
2010-06-16 16:22 ` Julian Pidancet [this message]
2010-06-17 10:43 ` Gerd Hoffmann
2010-06-17 14:29 ` Julian Pidancet
2010-06-17 16:25 ` Julian Pidancet
2010-06-18 7:32 ` Gerd Hoffmann
2010-06-18 12:00 ` Julian Pidancet
2010-06-24 18:38 ` [Qemu-devel] [PATCH 0/5] fbdev display driver + misc bits Julian Pidancet
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4C18FA58.5080808@citrix.com \
--to=julian.pidancet@citrix.com \
--cc=Stefano.Stabellini@eu.citrix.com \
--cc=kraxel@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.