* [PATCH] qemu sdl blitting
@ 2008-02-29 14:20 Stefano Stabellini
2008-02-29 14:23 ` Stefano Stabellini
2008-02-29 17:37 ` Stefano Stabellini
0 siblings, 2 replies; 3+ messages in thread
From: Stefano Stabellini @ 2008-02-29 14:20 UTC (permalink / raw)
To: xen-devel
[-- Attachment #1: Type: text/plain, Size: 545 bytes --]
Hi all,
right now qemu takes care of converting pixels between the guest pixel
format and the sdl pixel format, after that qemu also memcpy the
converted pixels to the sdl buffer in video ram.
This process can be improved using the SDL blit capabilities: the patch
I am attaching creates an SDL Surface from the Cirrus VGA framebuffer
and uses SDL blitting functions to convert and write pixels to video
ram. SDL blitting functions are optimized and can even be hardware
accelerated on some platforms.
Best Regards,
Stefano Stabelllini
[-- Attachment #2: qemu-sdl-blit.patch --]
[-- Type: text/x-patch, Size: 6783 bytes --]
diff -r 2a8eaba24bf0 tools/ioemu/hw/vga.c
--- a/tools/ioemu/hw/vga.c Tue Feb 26 15:11:51 2008 +0000
+++ b/tools/ioemu/hw/vga.c Fri Feb 29 10:49:17 2008 +0000
@@ -1481,7 +1481,7 @@ static void vga_draw_graphic(VGAState *s
static void vga_draw_graphic(VGAState *s, int full_update)
{
int y1, y, update, linesize, y_start, double_scan, mask, depth;
- int width, height, shift_control, line_offset, bwidth;
+ int width, height, shift_control, line_offset, bwidth, changed_flag;
ram_addr_t page0, page1;
int disp_width, multi_scan, multi_run;
uint8_t *d;
@@ -1554,10 +1554,12 @@ static void vga_draw_graphic(VGAState *s
}
vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
+ changed_flag = 0;
depth = s->get_bpp(s);
- if (s->ds->dpy_colourdepth != NULL && s->ds->depth != depth) {
- if (depth != 24 || s->ds->depth != 32)
+ if (s->ds->dpy_colourdepth != NULL &&
+ (s->ds->depth != depth || !s->ds->shared_buf)) {
s->ds->dpy_colourdepth(s->ds, depth);
+ changed_flag = 1;
}
if (disp_width != s->last_width ||
height != s->last_height) {
@@ -1567,9 +1569,10 @@ static void vga_draw_graphic(VGAState *s
s->last_width = disp_width;
s->last_height = height;
full_update = 1;
- }
- if (s->ds->shared_buf && s->ds->data != s->vram_ptr + (s->start_addr * 4))
- s->ds->data = s->vram_ptr + (s->start_addr * 4);
+ changed_flag = 1;
+ }
+ if (s->ds->shared_buf && (changed_flag || s->ds->data != s->vram_ptr + (s->start_addr * 4)))
+ s->ds->dpy_setdata(s->ds, s->vram_ptr + (s->start_addr * 4));
if (!s->ds->shared_buf && s->cursor_invalidate)
s->cursor_invalidate(s);
diff -r 2a8eaba24bf0 tools/ioemu/sdl.c
--- a/tools/ioemu/sdl.c Tue Feb 26 15:11:51 2008 +0000
+++ b/tools/ioemu/sdl.c Fri Feb 29 13:08:18 2008 +0000
@@ -30,6 +30,7 @@
#endif
static SDL_Surface *screen;
+static SDL_Surface *shared = NULL;
static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
static int last_vm_running;
static int gui_saved_grab;
@@ -47,7 +48,46 @@ static void sdl_update(DisplayState *ds,
static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
{
// printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
- SDL_UpdateRect(screen, x, y, w, h);
+
+ if (shared) {
+ SDL_Rect rec;
+ rec.x = x;
+ rec.y = y;
+ rec.w = w;
+ rec.h = h;
+ SDL_BlitSurface(shared, &rec, screen, &rec);
+ }
+ SDL_Flip(screen);
+}
+
+static void sdl_setdata(DisplayState *ds, void *pixels)
+{
+ uint32_t rmask, gmask, bmask, amask = 0;
+ switch (ds->depth) {
+ case 8:
+ rmask = 0x000000E0;
+ gmask = 0x0000001C;
+ bmask = 0x00000003;
+ break;
+ case 16:
+ rmask = 0x0000F800;
+ gmask = 0x000007E0;
+ bmask = 0x0000001F;
+ break;
+ case 24:
+ rmask = 0x00FF0000;
+ gmask = 0x0000FF00;
+ bmask = 0x000000FF;
+ break;
+ case 32:
+ rmask = 0x00FF0000;
+ gmask = 0x0000FF00;
+ bmask = 0x000000FF;
+ default:
+ return;
+ }
+ shared = SDL_CreateRGBSurfaceFrom(pixels, width, height, ds->depth, ds->linesize, rmask , gmask, bmask, amask);
+ ds->data = pixels;
}
static void sdl_resize(DisplayState *ds, int w, int h)
@@ -56,7 +96,7 @@ static void sdl_resize(DisplayState *ds,
// printf("resizing to %d %d\n", w, h);
- flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
+ flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL|SDL_DOUBLEBUF|SDL_HWPALETTE;
if (gui_fullscreen)
flags |= SDL_FULLSCREEN;
@@ -78,16 +118,28 @@ static void sdl_resize(DisplayState *ds,
fprintf(stderr, "Could not open SDL display\n");
exit(1);
}
- ds->data = screen->pixels;
- ds->linesize = screen->pitch;
- ds->depth = screen->format->BitsPerPixel;
- if (ds->depth == 32 && screen->format->Rshift == 0) {
- ds->bgr = 1;
- } else {
- ds->bgr = 0;
- }
ds->width = w;
ds->height = h;
+ if (!ds->shared_buf) {
+ ds->depth = screen->format->BitsPerPixel;
+ if (ds->depth == 32 && screen->format->Rshift == 0) {
+ ds->bgr = 1;
+ } else {
+ ds->bgr = 0;
+ }
+ ds->data = screen->pixels;
+ ds->linesize = screen->pitch;
+ } else {
+ ds->linesize = (ds->depth / 8) * w;
+ }
+}
+
+static void sdl_colourdepth(DisplayState *ds, int depth)
+{
+ if (!depth || !ds->depth) return;
+ ds->shared_buf = 1;
+ ds->depth = depth;
+ ds->linesize = width * depth / 8;
}
/* generic keyboard conversion */
@@ -508,7 +560,8 @@ void sdl_display_init(DisplayState *ds,
ds->dpy_update = sdl_update;
ds->dpy_resize = sdl_resize;
ds->dpy_refresh = sdl_refresh;
- ds->dpy_colourdepth = NULL;
+ ds->dpy_colourdepth = sdl_colourdepth;
+ ds->dpy_setdata = sdl_setdata;
sdl_resize(ds, 640, 400);
sdl_update_caption();
diff -r 2a8eaba24bf0 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h Tue Feb 26 15:11:51 2008 +0000
+++ b/tools/ioemu/vl.h Wed Feb 27 14:39:15 2008 +0000
@@ -940,6 +940,7 @@ struct DisplayState {
void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h);
void (*dpy_resize)(struct DisplayState *s, int w, int h);
void (*dpy_colourdepth)(struct DisplayState *s, int depth);
+ void (*dpy_setdata)(DisplayState *ds, void *pixels);
void (*dpy_refresh)(struct DisplayState *s);
void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y, int dst_x, int dst_y, int w, int h);
};
diff -r 2a8eaba24bf0 tools/ioemu/vnc.c
--- a/tools/ioemu/vnc.c Tue Feb 26 15:11:51 2008 +0000
+++ b/tools/ioemu/vnc.c Fri Feb 29 11:43:27 2008 +0000
@@ -1621,6 +1621,11 @@ static void pixel_format_message (VncSta
vnc_write(vs, pad, 3); /* padding */
}
+static void vnc_dpy_setdata(DisplayState *ds, void *pixels)
+{
+ ds->data = pixels;
+}
+
static void vnc_dpy_colourdepth(DisplayState *ds, int depth)
{
int host_big_endian_flag;
@@ -1628,6 +1633,7 @@ static void vnc_dpy_colourdepth(DisplayS
switch (depth) {
case 24:
+ if (ds->depth == 32) return;
ds->shared_buf = 0;
depth = 32;
break;
@@ -2480,6 +2486,7 @@ void vnc_display_init(DisplayState *ds)
vs->ds->dpy_update = vnc_dpy_update;
vs->ds->dpy_resize = vnc_dpy_resize;
vs->ds->dpy_colourdepth = vnc_dpy_colourdepth;
+ vs->ds->dpy_setdata = vnc_dpy_setdata;
vs->ds->dpy_refresh = vnc_dpy_refresh;
vs->ds->width = 640;
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] qemu sdl blitting
2008-02-29 14:20 [PATCH] qemu sdl blitting Stefano Stabellini
@ 2008-02-29 14:23 ` Stefano Stabellini
2008-02-29 17:37 ` Stefano Stabellini
1 sibling, 0 replies; 3+ messages in thread
From: Stefano Stabellini @ 2008-02-29 14:23 UTC (permalink / raw)
To: xen-devel
Stefano Stabellini wrote:
> Hi all,
> right now qemu takes care of converting pixels between the guest pixel
> format and the sdl pixel format, after that qemu also memcpy the
> converted pixels to the sdl buffer in video ram.
> This process can be improved using the SDL blit capabilities: the patch
> I am attaching creates an SDL Surface from the Cirrus VGA framebuffer
> and uses SDL blitting functions to convert and write pixels to video
> ram. SDL blitting functions are optimized and can even be hardware
> accelerated on some platforms.
>
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] qemu sdl blitting
2008-02-29 14:20 [PATCH] qemu sdl blitting Stefano Stabellini
2008-02-29 14:23 ` Stefano Stabellini
@ 2008-02-29 17:37 ` Stefano Stabellini
1 sibling, 0 replies; 3+ messages in thread
From: Stefano Stabellini @ 2008-02-29 17:37 UTC (permalink / raw)
To: xen-devel
[-- Attachment #1: Type: text/plain, Size: 167 bytes --]
I found a little mistake in the patch (a break statement missing), so I
am reposting it fixed.
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
[-- Attachment #2: qemu-sdl-blit.patch --]
[-- Type: text/x-patch, Size: 6845 bytes --]
diff -r 9049b0b62e08 tools/ioemu/hw/vga.c
--- a/tools/ioemu/hw/vga.c Fri Feb 29 10:30:28 2008 +0000
+++ b/tools/ioemu/hw/vga.c Fri Feb 29 16:26:27 2008 +0000
@@ -1481,7 +1481,7 @@ static void vga_draw_graphic(VGAState *s
static void vga_draw_graphic(VGAState *s, int full_update)
{
int y1, y, update, linesize, y_start, double_scan, mask, depth;
- int width, height, shift_control, line_offset, bwidth;
+ int width, height, shift_control, line_offset, bwidth, changed_flag;
ram_addr_t page0, page1;
int disp_width, multi_scan, multi_run;
uint8_t *d;
@@ -1554,10 +1554,12 @@ static void vga_draw_graphic(VGAState *s
}
vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
+ changed_flag = 0;
depth = s->get_bpp(s);
- if (s->ds->dpy_colourdepth != NULL && s->ds->depth != depth) {
- if (depth != 24 || s->ds->depth != 32)
- s->ds->dpy_colourdepth(s->ds, depth);
+ if (s->ds->dpy_colourdepth != NULL &&
+ (s->ds->depth != depth || !s->ds->shared_buf)) {
+ s->ds->dpy_colourdepth(s->ds, depth);
+ changed_flag = 1;
}
if (disp_width != s->last_width ||
height != s->last_height) {
@@ -1567,9 +1569,10 @@ static void vga_draw_graphic(VGAState *s
s->last_width = disp_width;
s->last_height = height;
full_update = 1;
- }
- if (s->ds->shared_buf && s->ds->data != s->vram_ptr + (s->start_addr * 4))
- s->ds->data = s->vram_ptr + (s->start_addr * 4);
+ changed_flag = 1;
+ }
+ if (s->ds->shared_buf && (changed_flag || s->ds->data != s->vram_ptr + (s->start_addr * 4)))
+ s->ds->dpy_setdata(s->ds, s->vram_ptr + (s->start_addr * 4));
if (!s->ds->shared_buf && s->cursor_invalidate)
s->cursor_invalidate(s);
diff -r 9049b0b62e08 tools/ioemu/sdl.c
--- a/tools/ioemu/sdl.c Fri Feb 29 10:30:28 2008 +0000
+++ b/tools/ioemu/sdl.c Fri Feb 29 17:03:17 2008 +0000
@@ -30,6 +30,7 @@
#endif
static SDL_Surface *screen;
+static SDL_Surface *shared = NULL;
static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
static int last_vm_running;
static int gui_saved_grab;
@@ -47,7 +48,46 @@ static void sdl_update(DisplayState *ds,
static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
{
// printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
- SDL_UpdateRect(screen, x, y, w, h);
+ if (shared) {
+ SDL_Rect rec;
+ rec.x = x;
+ rec.y = y;
+ rec.w = w;
+ rec.h = h;
+ SDL_BlitSurface(shared, &rec, screen, &rec);
+ }
+ SDL_Flip(screen);
+}
+
+static void sdl_setdata(DisplayState *ds, void *pixels)
+{
+ uint32_t rmask, gmask, bmask, amask = 0;
+ switch (ds->depth) {
+ case 8:
+ rmask = 0x000000E0;
+ gmask = 0x0000001C;
+ bmask = 0x00000003;
+ break;
+ case 16:
+ rmask = 0x0000F800;
+ gmask = 0x000007E0;
+ bmask = 0x0000001F;
+ break;
+ case 24:
+ rmask = 0x00FF0000;
+ gmask = 0x0000FF00;
+ bmask = 0x000000FF;
+ break;
+ case 32:
+ rmask = 0x00FF0000;
+ gmask = 0x0000FF00;
+ bmask = 0x000000FF;
+ break;
+ default:
+ return;
+ }
+ shared = SDL_CreateRGBSurfaceFrom(pixels, width, height, ds->depth, ds->linesize, rmask , gmask, bmask, amask);
+ ds->data = pixels;
}
static void sdl_resize(DisplayState *ds, int w, int h)
@@ -56,7 +96,7 @@ static void sdl_resize(DisplayState *ds,
// printf("resizing to %d %d\n", w, h);
- flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
+ flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL|SDL_DOUBLEBUF|SDL_HWPALETTE;
if (gui_fullscreen)
flags |= SDL_FULLSCREEN;
@@ -78,16 +118,28 @@ static void sdl_resize(DisplayState *ds,
fprintf(stderr, "Could not open SDL display\n");
exit(1);
}
- ds->data = screen->pixels;
- ds->linesize = screen->pitch;
- ds->depth = screen->format->BitsPerPixel;
- if (ds->depth == 32 && screen->format->Rshift == 0) {
- ds->bgr = 1;
- } else {
- ds->bgr = 0;
- }
ds->width = w;
ds->height = h;
+ if (!ds->shared_buf) {
+ ds->depth = screen->format->BitsPerPixel;
+ if (ds->depth == 32 && screen->format->Rshift == 0) {
+ ds->bgr = 1;
+ } else {
+ ds->bgr = 0;
+ }
+ ds->data = screen->pixels;
+ ds->linesize = screen->pitch;
+ } else {
+ ds->linesize = (ds->depth / 8) * w;
+ }
+}
+
+static void sdl_colourdepth(DisplayState *ds, int depth)
+{
+ if (!depth || !ds->depth) return;
+ ds->shared_buf = 1;
+ ds->depth = depth;
+ ds->linesize = width * depth / 8;
}
/* generic keyboard conversion */
@@ -508,7 +560,8 @@ void sdl_display_init(DisplayState *ds,
ds->dpy_update = sdl_update;
ds->dpy_resize = sdl_resize;
ds->dpy_refresh = sdl_refresh;
- ds->dpy_colourdepth = NULL;
+ ds->dpy_colourdepth = sdl_colourdepth;
+ ds->dpy_setdata = sdl_setdata;
sdl_resize(ds, 640, 400);
sdl_update_caption();
diff -r 9049b0b62e08 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h Fri Feb 29 10:30:28 2008 +0000
+++ b/tools/ioemu/vl.h Fri Feb 29 16:32:42 2008 +0000
@@ -942,6 +942,7 @@ struct DisplayState {
void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h);
void (*dpy_resize)(struct DisplayState *s, int w, int h);
void (*dpy_colourdepth)(struct DisplayState *s, int depth);
+ void (*dpy_setdata)(DisplayState *ds, void *pixels);
void (*dpy_refresh)(struct DisplayState *s);
void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y, int dst_x, int dst_y, int w, int h);
};
diff -r 9049b0b62e08 tools/ioemu/vnc.c
--- a/tools/ioemu/vnc.c Fri Feb 29 10:30:28 2008 +0000
+++ b/tools/ioemu/vnc.c Fri Feb 29 16:30:17 2008 +0000
@@ -1621,6 +1621,11 @@ static void pixel_format_message (VncSta
vnc_write(vs, pad, 3); /* padding */
}
+static void vnc_dpy_setdata(DisplayState *ds, void *pixels)
+{
+ ds->data = pixels;
+}
+
static void vnc_dpy_colourdepth(DisplayState *ds, int depth)
{
int host_big_endian_flag;
@@ -1628,6 +1633,7 @@ static void vnc_dpy_colourdepth(DisplayS
switch (depth) {
case 24:
+ if (ds->depth == 32) return;
ds->shared_buf = 0;
depth = 32;
break;
@@ -2480,6 +2486,7 @@ void vnc_display_init(DisplayState *ds)
vs->ds->dpy_update = vnc_dpy_update;
vs->ds->dpy_resize = vnc_dpy_resize;
vs->ds->dpy_colourdepth = vnc_dpy_colourdepth;
+ vs->ds->dpy_setdata = vnc_dpy_setdata;
vs->ds->dpy_refresh = vnc_dpy_refresh;
vs->ds->width = 640;
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2008-02-29 17:37 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-02-29 14:20 [PATCH] qemu sdl blitting Stefano Stabellini
2008-02-29 14:23 ` Stefano Stabellini
2008-02-29 17:37 ` Stefano Stabellini
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.