qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 3 of 3] [UPDATE] vga shared buffer


From: Stefano Stabellini
Subject: [Qemu-devel] [PATCH 3 of 3] [UPDATE] vga shared buffer
Date: Fri, 29 Aug 2008 15:51:42 +0100
User-agent: Thunderbird 2.0.0.14 (X11/20080505)

Stefano Stabellini wrote:

> This patch implements sharing of the display pixel buffer between
> vnc.c and vga.c, in order to save a lot of memcpy's.
> 



This is a small update to the "shared buffer" patch: I had to move few
lines of code in vga.c to be sure that any colour depth change in
DisplayState caused by dpy_resize_shared is reflected in the same
screen update.
Besides I moved the call to setdata after the palette update (sdl is
going to support palette for 8 bit colour depths).

Signed-off-by: Stefano Stabellini <address@hidden>

---

diff --git a/console.c b/console.c
index cb85272..b5d7d86 100644
--- a/console.c
+++ b/console.c
@@ -1327,12 +1327,20 @@ CharDriverState *text_console_init(DisplayState *ds, 
const char *p)
 
 void qemu_console_resize(QEMUConsole *console, int width, int height)
 {
-    if (console->g_width != width || console->g_height != height
-        || !console->ds->data) {
-        console->g_width = width;
-        console->g_height = height;
-        if (active_console == console) {
-            dpy_resize(console->ds, width, height);
-        }
+    console->g_width = width;
+    console->g_height = height;
+    if (active_console == console) {
+        dpy_resize(console->ds, width, height);
+    }
+}
+
+void qemu_console_resize_shared(QEMUConsole *console, int width, int height,
+                                int depth, int linesize, void *pixels)
+{
+    console->g_width = width;
+    console->g_height = height;
+    if (active_console == console) {
+        dpy_resize_shared(console->ds, width, height, depth, linesize, pixels);
     }
 }
+
diff --git a/console.h b/console.h
index fcac1eb..a054d97 100644
--- a/console.h
+++ b/console.h
@@ -84,9 +84,12 @@ struct DisplayState {
     struct QEMUTimer *gui_timer;
     uint64_t gui_timer_interval;
     int idle; /* there is nothing to update (window invisible), set by vnc/sdl 
*/
+    int shared_buf;
 
     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_resize_shared)(struct DisplayState *s, int w, int h, int depth, 
int linesize, void *pixels);
+    void (*dpy_setdata)(DisplayState *s, 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);
@@ -108,6 +111,11 @@ static inline void dpy_resize(DisplayState *s, int w, int 
h)
     s->dpy_resize(s, w, h);
 }
 
+static inline void dpy_resize_shared(DisplayState *s, int w, int h, int depth, 
int linesize, void *pixels)
+{
+    s->dpy_resize_shared(s, w, h, depth, linesize, pixels);
+}
+
 static inline void dpy_cursor(DisplayState *s, int x, int y)
 {
     if (s->dpy_text_cursor)
@@ -140,6 +148,8 @@ CharDriverState *text_console_init(DisplayState *ds, const 
char *p);
 void console_select(unsigned int index);
 void console_color_init(DisplayState *ds);
 void qemu_console_resize(QEMUConsole *console, int width, int height);
+void qemu_console_resize_shared(QEMUConsole *console, int width, int height,
+                                int depth, int linesize, void *pixels);
 
 /* sdl.c */
 void sdl_display_init(DisplayState *ds, int full_screen, int no_frame);
diff --git a/hw/vga.c b/hw/vga.c
index eb0bae8..6e40d3d 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -1078,6 +1078,10 @@ static const uint8_t cursor_glyph[32 * 4] = {
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 };
 
+typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, 
unsigned b);
+
+static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS];
+
 /*
  * Text mode update
  * Missing:
@@ -1099,9 +1103,6 @@ static void vga_draw_text(VGAState *s, int full_update)
     vga_draw_glyph8_func *vga_draw_glyph8;
     vga_draw_glyph9_func *vga_draw_glyph9;
 
-    full_update |= update_palette16(s);
-    palette = s->last_palette;
-
     /* compute font data address (in plane 2) */
     v = s->sr[3];
     offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
@@ -1135,7 +1136,6 @@ static void vga_draw_text(VGAState *s, int full_update)
         cw = 9;
     if (s->sr[1] & 0x08)
         cw = 16; /* NOTE: no 18 pixel wide */
-    x_incr = cw * ((s->ds->depth + 7) >> 3);
     width = (s->cr[0x01] + 1);
     if (s->cr[0x06] == 100) {
         /* ugly hack for CGA 160x100x16 - explain me the logic */
@@ -1152,16 +1152,23 @@ static void vga_draw_text(VGAState *s, int full_update)
     }
 
     if (width != s->last_width || height != s->last_height ||
-        cw != s->last_cw || cheight != s->last_ch) {
+        cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
         s->last_scr_width = width * cw;
         s->last_scr_height = height * cheight;
         qemu_console_resize(s->console, s->last_scr_width, s->last_scr_height);
+        s->last_depth = 0;
         s->last_width = width;
         s->last_height = height;
         s->last_ch = cheight;
         s->last_cw = cw;
         full_update = 1;
     }
+    s->rgb_to_pixel =
+        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
+    full_update |= update_palette16(s);
+    palette = s->last_palette;
+    x_incr = cw * ((s->ds->depth + 7) >> 3);
+
     cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
     if (cursor_offset != s->cursor_offset ||
         s->cr[0xa] != s->cursor_start ||
@@ -1353,8 +1360,6 @@ static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS 
* VGA_DRAW_LINE_NB] = {
     vga_draw_line32_16bgr,
 };
 
-typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, 
unsigned b);
-
 static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
     rgb_to_pixel8_dup,
     rgb_to_pixel15_dup,
@@ -1419,6 +1424,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
 {
     int y1, y, update, page_min, page_max, linesize, y_start, double_scan, 
mask;
     int width, height, shift_control, line_offset, page0, page1, bwidth, bits;
+    int ds_depth, depth, palette_update;
     int disp_width, multi_scan, multi_run;
     uint8_t *d;
     uint32_t v, addr1, addr;
@@ -1446,8 +1452,39 @@ static void vga_draw_graphic(VGAState *s, int 
full_update)
         s->double_scan = double_scan;
     }
 
+    ds_depth = s->ds->depth;
+    depth = s->get_bpp(s);
+    if (s->ds->dpy_resize_shared) {
+        if (s->line_offset != s->last_line_offset || 
+            disp_width != s->last_width ||
+            height != s->last_height ||
+            s->last_depth != depth) {
+            qemu_console_resize_shared(s->console, disp_width, height,
+                                       depth, s->line_offset, s->vram_ptr + 
(s->start_addr * 4));
+            s->last_scr_width = disp_width;
+            s->last_scr_height = height;
+            s->last_width = disp_width;
+            s->last_height = height;
+            s->last_line_offset = s->line_offset;
+            s->last_depth = depth;
+            full_update = 1;
+        }
+    } else if (disp_width != s->last_width ||
+               height != s->last_height) {
+        qemu_console_resize(s->console, disp_width, height);
+        s->last_scr_width = disp_width;
+        s->last_scr_height = height;
+        s->last_width = disp_width;
+        s->last_height = height;
+        full_update = 1;
+    }
+
+    s->rgb_to_pixel =
+        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
+
+    palette_update = 0;
     if (shift_control == 0) {
-        full_update |= update_palette16(s);
+        palette_update |= update_palette16(s);
         if (s->sr[0x01] & 8) {
             v = VGA_DRAW_LINE4D2;
             disp_width <<= 1;
@@ -1456,7 +1493,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
         }
         bits = 4;
     } else if (shift_control == 1) {
-        full_update |= update_palette16(s);
+        palette_update |= update_palette16(s);
         if (s->sr[0x01] & 8) {
             v = VGA_DRAW_LINE2D2;
             disp_width <<= 1;
@@ -1468,12 +1505,12 @@ static void vga_draw_graphic(VGAState *s, int 
full_update)
         switch(s->get_bpp(s)) {
         default:
         case 0:
-            full_update |= update_palette256(s);
+            palette_update |= update_palette256(s);
             v = VGA_DRAW_LINE8D2;
             bits = 4;
             break;
         case 8:
-            full_update |= update_palette256(s);
+            palette_update |= update_palette256(s);
             v = VGA_DRAW_LINE8;
             bits = 8;
             break;
@@ -1495,18 +1532,12 @@ static void vga_draw_graphic(VGAState *s, int 
full_update)
             break;
         }
     }
+    if (s->ds->shared_buf &&
+        (palette_update || s->ds->data != s->vram_ptr + (s->start_addr * 4)))
+        s->ds->dpy_setdata(s->ds, s->vram_ptr + (s->start_addr * 4));
+    full_update |= palette_update;
     vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + 
get_depth_index(s->ds)];
-
-    if (disp_width != s->last_width ||
-        height != s->last_height) {
-        qemu_console_resize(s->console, disp_width, height);
-        s->last_scr_width = disp_width;
-        s->last_scr_height = height;
-        s->last_width = disp_width;
-        s->last_height = height;
-        full_update = 1;
-    }
-    if (s->cursor_invalidate)
+    if (!s->ds->shared_buf && s->cursor_invalidate)
         s->cursor_invalidate(s);
 
     line_offset = s->line_offset;
@@ -1552,9 +1583,11 @@ static void vga_draw_graphic(VGAState *s, int 
full_update)
                 page_min = page0;
             if (page1 > page_max)
                 page_max = page1;
-            vga_draw_line(s, d, s->vram_ptr + addr, width);
-            if (s->cursor_draw_line)
-                s->cursor_draw_line(s, d, y);
+            if (!s->ds->shared_buf) {
+                vga_draw_line(s, d, s->vram_ptr + addr, width);
+                if (s->cursor_draw_line)
+                    s->cursor_draw_line(s, d, y);
+            }
         } else {
             if (y_start >= 0) {
                 /* flush to display */
@@ -1599,6 +1632,8 @@ static void vga_draw_blank(VGAState *s, int full_update)
         return;
     if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
         return;
+    s->rgb_to_pixel =
+        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
     if (s->ds->depth == 8)
         val = s->rgb_to_pixel(0, 0, 0);
     else
@@ -1625,9 +1660,6 @@ static void vga_update_display(void *opaque)
     if (s->ds->depth == 0) {
         /* nothing to do */
     } else {
-        s->rgb_to_pixel =
-            rgb_to_pixel_dup_table[get_depth_index(s->ds)];
-
         full_update = 0;
         if (!(s->ar_index & 0x20)) {
             graphic_mode = GMODE_BLANK;
diff --git a/hw/vga_int.h b/hw/vga_int.h
index 343da34..d187f1b 100644
--- a/hw/vga_int.h
+++ b/hw/vga_int.h
@@ -130,9 +130,11 @@
     uint32_t line_compare;                                              \
     uint32_t start_addr;                                                \
     uint32_t plane_updated;                                             \
+    uint32_t last_line_offset;                                          \
     uint8_t last_cw, last_ch;                                           \
     uint32_t last_width, last_height; /* in chars or pixels */          \
     uint32_t last_scr_width, last_scr_height; /* in pixels */           \
+    uint32_t last_depth; /* in bits */                                  \
     uint8_t cursor_start, cursor_end;                                   \
     uint32_t cursor_offset;                                             \
     unsigned int (*rgb_to_pixel)(unsigned int r,                        \
diff --git a/vnc.c b/vnc.c
index d021b50..7793392 100644
--- a/vnc.c
+++ b/vnc.c
@@ -289,13 +289,28 @@ static void vnc_framebuffer_update(VncState *vs, int x, 
int y, int w, int h,
     vnc_write_s32(vs, encoding);
 }
 
-static void vnc_dpy_resize(DisplayState *ds, int w, int h)
+static void vnc_dpy_resize_shared(DisplayState *ds, int w, int h, int depth, 
int linesize, void *pixels)
 {
+    static int allocated;
     int size_changed;
     VncState *vs = ds->opaque;
 
-    ds->data = qemu_realloc(ds->data, w * h * vs->depth);
-    vs->old_data = qemu_realloc(vs->old_data, w * h * vs->depth);
+    vnc_colourdepth(ds, depth);
+    if (!ds->shared_buf) {
+        ds->linesize = w * vs->depth;
+        if (allocated)
+            ds->data = realloc(ds->data,  h * ds->linesize);
+        else
+            ds->data = malloc(h * ds->linesize);
+        allocated = 1;
+    } else {
+        ds->linesize = linesize;
+        if (allocated) {
+            free(ds->data);
+            allocated = 0;
+        }
+    }
+    vs->old_data = qemu_realloc(vs->old_data, h * ds->linesize);
 
     if (ds->data == NULL || vs->old_data == NULL) {
        fprintf(stderr, "vnc: memory allocation failed\n");
@@ -309,7 +324,6 @@ static void vnc_dpy_resize(DisplayState *ds, int w, int h)
     size_changed = ds->width != w || ds->height != h;
     ds->width = w;
     ds->height = h;
-    ds->linesize = w * vs->depth;
     if (size_changed) {
         vs->width = ds->width;
         vs->height = ds->height;
@@ -324,6 +338,12 @@ static void vnc_dpy_resize(DisplayState *ds, int w, int h)
 
     memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
     memset(vs->old_data, 42, vs->ds->linesize * vs->ds->height);
+    if (ds->shared_buf) ds->data = pixels;
+}
+
+static void vnc_dpy_resize(DisplayState *ds, int w, int h)
+{
+    vnc_dpy_resize_shared(ds, w, h, 0, w * (ds->depth / 8), NULL);
 }
 
 /* fastest code */
@@ -496,6 +516,9 @@ static void vnc_copy(DisplayState *ds, int src_x, int 
src_y, int dst_x, int dst_
     int pitch = ds->linesize;
     VncState *vs = ds->opaque;
 
+    if (ds->shared_buf)
+        return;
+
     vnc_update_client(vs);
 
     if (dst_y > src_y) {
@@ -1247,9 +1270,6 @@ static void set_pixel_format(VncState *vs,
     vs->blue_shift = blue_shift;
     vs->blue_max = blue_max;
     vs->pix_bpp = bits_per_pixel / 8;
-
-    vga_hw_invalidate();
-    vga_hw_update();
 }
 
 static void pixel_format_message (VncState *vs) {
@@ -1303,6 +1323,11 @@ static void pixel_format_message (VncState *vs) {
     vnc_write(vs, pad, 3);           /* padding */
 }
 
+static void vnc_dpy_setdata(DisplayState *ds, void *pixels)
+{
+    ds->data = pixels;
+}
+
 static void vnc_colourdepth(DisplayState *ds, int depth)
 {
     int host_big_endian_flag;
@@ -1310,13 +1335,16 @@ static void vnc_colourdepth(DisplayState *ds, int depth)
 
     switch (depth) {
         case 24:
+            ds->shared_buf = 0;
             if (ds->depth == 32) return;
             depth = 32;
             break;
         case 8:
         case 0:
+            ds->shared_buf = 0;
             return;
         default:
+            ds->shared_buf = 1;
             break;
     }
 
@@ -2172,9 +2200,14 @@ void vnc_display_init(DisplayState *ds)
     vs->ds->data = NULL;
     vs->ds->dpy_update = vnc_dpy_update;
     vs->ds->dpy_resize = vnc_dpy_resize;
+    vs->ds->dpy_setdata = vnc_dpy_setdata;
+    vs->ds->dpy_resize_shared = vnc_dpy_resize_shared;
     vs->ds->dpy_refresh = NULL;
 
-    vnc_dpy_resize(vs->ds, 640, 400);
+    vs->ds->width = 640;
+    vs->ds->height = 400;
+    vs->ds->linesize = 640 * 4;
+    vnc_dpy_resize_shared(ds, ds->width, ds->height, 24, ds->linesize, NULL);
 }
 
 #if CONFIG_VNC_TLS




reply via email to

[Prev in Thread] Current Thread [Next in Thread]