All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 3 of 3] [UPDATE] vga shared buffer
Date: Fri, 29 Aug 2008 15:51:42 +0100	[thread overview]
Message-ID: <48B80CFE.8040008@eu.citrix.com> (raw)
In-Reply-To: <48B6C90D.9020002@eu.citrix.com>

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 <stefano.stabellini@eu.citrix.com>

---

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	other threads:[~2008-08-29 14:50 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-08-28 15:49 [Qemu-devel] [PATCH 3 of 3] vga shared buffer Stefano Stabellini
2008-08-29 14:51 ` Stefano Stabellini [this message]
2008-09-02 16:32   ` [Qemu-devel] [PATCH 3 of 3] [UPDATE] " Ian Jackson

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=48B80CFE.8040008@eu.citrix.com \
    --to=stefano.stabellini@eu.citrix.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.