source: trunk/packages/xen-3.1/xen-3.1/tools/ioemu/patches/vnc-fixes @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 14.9 KB
Line 
1Index: ioemu/vl.c
2===================================================================
3--- ioemu.orig/vl.c     2007-05-03 10:24:05.000000000 +0100
4+++ ioemu/vl.c  2007-05-03 10:24:05.000000000 +0100
5@@ -6597,8 +6597,10 @@
6         }
7     }
8 
9-    gui_timer = qemu_new_timer(rt_clock, gui_update, NULL);
10-    qemu_mod_timer(gui_timer, qemu_get_clock(rt_clock));
11+    if (vnc_display == -1) {
12+        gui_timer = qemu_new_timer(rt_clock, gui_update, NULL);
13+        qemu_mod_timer(gui_timer, qemu_get_clock(rt_clock));
14+    }
15 
16 #ifdef CONFIG_GDBSTUB
17     if (use_gdbstub) {
18Index: ioemu/vnc.c
19===================================================================
20--- ioemu.orig/vnc.c    2007-05-03 10:24:05.000000000 +0100
21+++ ioemu/vnc.c 2007-05-03 10:24:05.000000000 +0100
22@@ -3,6 +3,7 @@
23  *
24  * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
25  * Copyright (C) 2006 Fabrice Bellard
26+ * Copyright (C) 2006 Christian Limpach <Christian.Limpach@xensource.com>
27  *
28  * Permission is hereby granted, free of charge, to any person obtaining a copy
29  * of this software and associated documentation files (the "Software"), to deal
30@@ -50,9 +51,11 @@
31                                 uint32_t *last_fg,
32                                 int *has_bg, int *has_fg);
33 
34+#if 0
35 #define VNC_MAX_WIDTH 2048
36 #define VNC_MAX_HEIGHT 2048
37 #define VNC_DIRTY_WORDS (VNC_MAX_WIDTH / (16 * 32))
38+#endif
39 
40 struct VncState
41 {
42@@ -63,7 +66,11 @@
43     int need_update;
44     int width;
45     int height;
46-    uint32_t dirty_row[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS];
47+    uint64_t *dirty_row;       /* screen regions which are possibly dirty */
48+    int dirty_pixel_shift;
49+    uint64_t *update_row;      /* outstanding updates */
50+    int has_update;            /* there's outstanding updates in the
51+                                * visible area */
52     char *old_data;
53     int depth; /* internal VNC frame buffer byte per pixel */
54     int has_resize;
55@@ -81,13 +88,25 @@
56 
57     VncReadEvent *read_handler;
58     size_t read_handler_expect;
59+
60+    int visible_x;
61+    int visible_y;
62+    int visible_w;
63+    int visible_h;
64+
65+    int slow_client;
66 };
67 
68+#define DIRTY_PIXEL_BITS 64
69+#define X2DP_DOWN(vs, x) ((x) >> (vs)->dirty_pixel_shift)
70+#define X2DP_UP(vs, x) \
71+  (((x) + (1ULL << (vs)->dirty_pixel_shift) - 1) >> (vs)->dirty_pixel_shift)
72+#define DP2X(vs, x) ((x) << (vs)->dirty_pixel_shift)
73+
74 /* TODO
75    1) Get the queue working for IO.
76    2) there is some weirdness when using the -S option (the screen is grey
77       and not totally invalidated
78-   3) resolutions > 1024
79 */
80 
81 static void vnc_write(VncState *vs, const void *data, size_t len);
82@@ -96,9 +115,12 @@
83 static void vnc_write_u16(VncState *vs, uint16_t value);
84 static void vnc_write_u8(VncState *vs, uint8_t value);
85 static void vnc_flush(VncState *vs);
86+static void _vnc_update_client(void *opaque);
87 static void vnc_update_client(void *opaque);
88 static void vnc_client_read(void *opaque);
89+static void framebuffer_set_updated(VncState *vs, int x, int y, int w, int h);
90 
91+#if 0
92 static inline void vnc_set_bit(uint32_t *d, int k)
93 {
94     d[k >> 5] |= 1 << (k & 0x1f);
95@@ -139,20 +161,37 @@
96     }
97     return 0;
98 }
99+#endif
100 
101-static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
102+static void set_bits_in_row(VncState *vs, uint64_t *row,
103+                           int x, int y, int w, int h)
104 {
105-    VncState *vs = ds->opaque;
106+    int x1, x2;
107     uint64_t mask;
108 
109-    h += y;
110-    if (w != 1024)
111-       mask = ((1ULL << (w / 16)) - 1) << (x / 16);
112+    if (w == 0)
113+       return;
114+
115+    x1 = X2DP_DOWN(vs, x);
116+    x2 = X2DP_UP(vs, x + w);
117+
118+    if (X2DP_UP(vs, w) != DIRTY_PIXEL_BITS)
119+       mask = ((1ULL << (x2 - x1)) - 1) << x1;
120     else
121        mask = ~(0ULL);
122 
123+    h += y;
124+    if (h > vs->ds->height)
125+        h = vs->ds->height;
126     for (; y < h; y++)
127-       vs->dirty_row[y] |= mask;
128+       row[y] |= mask;
129+}
130+
131+static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
132+{
133+    VncState *vs = ds->opaque;
134+
135+    set_bits_in_row(vs, vs->dirty_row, x, y, w, h);
136 }
137 
138 static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
139@@ -169,16 +208,23 @@
140 static void vnc_dpy_resize(DisplayState *ds, int w, int h)
141 {
142     VncState *vs = ds->opaque;
143+    int o;
144 
145     ds->data = realloc(ds->data, w * h * vs->depth);
146     vs->old_data = realloc(vs->old_data, w * h * vs->depth);
147+    vs->dirty_row = realloc(vs->dirty_row, h * sizeof(vs->dirty_row[0]));
148+    vs->update_row = realloc(vs->update_row, h * sizeof(vs->dirty_row[0]));
149 
150-    if (ds->data == NULL || vs->old_data == NULL) {
151+    if (ds->data == NULL || vs->old_data == NULL ||
152+       vs->dirty_row == NULL || vs->update_row == NULL) {
153        fprintf(stderr, "vnc: memory allocation failed\n");
154        exit(1);
155     }
156 
157-    ds->depth = vs->depth * 8;
158+    if (ds->depth != vs->depth * 8) {
159+        ds->depth = vs->depth * 8;
160+        set_color_table(ds);
161+    }
162     ds->width = w;
163     ds->height = h;
164     ds->linesize = w * vs->depth;
165@@ -191,6 +237,10 @@
166        vs->width = ds->width;
167        vs->height = ds->height;
168     }
169+    vs->dirty_pixel_shift = 0;
170+    for (o = DIRTY_PIXEL_BITS; o < ds->width; o *= 2)
171+       vs->dirty_pixel_shift++;
172+    framebuffer_set_updated(vs, 0, 0, ds->width, ds->height);
173 }
174 
175 /* fastest code */
176@@ -326,8 +376,20 @@
177     int y = 0;
178     int pitch = ds->linesize;
179     VncState *vs = ds->opaque;
180+    int updating_client = !vs->slow_client;
181 
182-    vnc_update_client(vs);
183+    if (src_x < vs->visible_x || src_y < vs->visible_y ||
184+       dst_x < vs->visible_x || dst_y < vs->visible_y ||
185+       (src_x + w) > (vs->visible_x + vs->visible_w) ||
186+       (src_y + h) > (vs->visible_y + vs->visible_h) ||
187+       (dst_x + w) > (vs->visible_x + vs->visible_w) ||
188+       (dst_y + h) > (vs->visible_y + vs->visible_h))
189+       updating_client = 0;
190+
191+    if (updating_client) {
192+       vs->need_update = 1;
193+       _vnc_update_client(vs);
194+    }
195 
196     if (dst_y > src_y) {
197        y = h - 1;
198@@ -349,31 +411,34 @@
199        old_row += pitch;
200     }
201 
202-    vnc_write_u8(vs, 0);  /* msg id */
203-    vnc_write_u8(vs, 0);
204-    vnc_write_u16(vs, 1); /* number of rects */
205-    vnc_framebuffer_update(vs, dst_x, dst_y, w, h, 1);
206-    vnc_write_u16(vs, src_x);
207-    vnc_write_u16(vs, src_y);
208-    vnc_flush(vs);
209+    if (updating_client && vs->csock != -1 && !vs->has_update) {
210+       vnc_write_u8(vs, 0);  /* msg id */
211+       vnc_write_u8(vs, 0);
212+       vnc_write_u16(vs, 1); /* number of rects */
213+       vnc_framebuffer_update(vs, dst_x, dst_y, w, h, 1);
214+       vnc_write_u16(vs, src_x);
215+       vnc_write_u16(vs, src_y);
216+       vnc_flush(vs);
217+    } else
218+       framebuffer_set_updated(vs, dst_x, dst_y, w, h);
219 }
220 
221-static int find_dirty_height(VncState *vs, int y, int last_x, int x)
222+static int find_update_height(VncState *vs, int y, int maxy, int last_x, int x)
223 {
224     int h;
225 
226-    for (h = 1; h < (vs->height - y); h++) {
227+    for (h = 1; y + h < maxy; h++) {
228        int tmp_x;
229-       if (!vnc_get_bit(vs->dirty_row[y + h], last_x))
230+       if (!(vs->update_row[y + h] & (1ULL << last_x)))
231            break;
232        for (tmp_x = last_x; tmp_x < x; tmp_x++)
233-           vnc_clear_bit(vs->dirty_row[y + h], tmp_x);
234+           vs->update_row[y + h] &= ~(1ULL << tmp_x);
235     }
236 
237     return h;
238 }
239 
240-static void vnc_update_client(void *opaque)
241+static void _vnc_update_client(void *opaque)
242 {
243     VncState *vs = opaque;
244     int64_t now = qemu_get_clock(rt_clock);
245@@ -382,14 +447,18 @@
246        int y;
247        char *row;
248        char *old_row;
249-       uint32_t width_mask[VNC_DIRTY_WORDS];
250+       uint64_t width_mask;
251        int n_rectangles;
252        int saved_offset;
253-       int has_dirty = 0;
254+       int maxx, maxy;
255+       int tile_bytes = vs->depth * DP2X(vs, 1);
256 
257        qemu_mod_timer(vs->timer, now + VNC_REFRESH_INTERVAL);
258 
259-        vnc_set_bits(width_mask, (vs->width / 16), VNC_DIRTY_WORDS);
260+       if (vs->width != DP2X(vs, DIRTY_PIXEL_BITS))
261+           width_mask = (1ULL << X2DP_UP(vs, vs->ds->width)) - 1;
262+       else
263+           width_mask = ~(0ULL);
264 
265        /* Walk through the dirty map and eliminate tiles that
266           really aren't dirty */
267@@ -397,23 +466,25 @@
268        old_row = vs->old_data;
269 
270        for (y = 0; y < vs->ds->height; y++) {
271-           if (vnc_and_bits(vs->dirty_row[y], width_mask, VNC_DIRTY_WORDS)) {
272+           if (vs->dirty_row[y] & width_mask) {
273                int x;
274                char *ptr, *old_ptr;
275 
276                ptr = row;
277                old_ptr = old_row;
278 
279-               for (x = 0; x < vs->ds->width; x += 16) {
280-                   if (memcmp(old_ptr, ptr, 16 * vs->depth) == 0) {
281-                       vnc_clear_bit(vs->dirty_row[y], (x / 16));
282-                   } else {
283-                       has_dirty = 1;
284-                       memcpy(old_ptr, ptr, 16 * vs->depth);
285+               for (x = 0; x < X2DP_UP(vs, vs->ds->width); x++) {
286+                   if (vs->dirty_row[y] & (1ULL << x)) {
287+                       if (memcmp(old_ptr, ptr, tile_bytes)) {
288+                           vs->has_update = 1;
289+                           vs->update_row[y] |= (1ULL << x);
290+                           memcpy(old_ptr, ptr, tile_bytes);
291+                       }
292+                       vs->dirty_row[y] &= ~(1ULL << x);
293                    }
294 
295-                   ptr += 16 * vs->depth;
296-                   old_ptr += 16 * vs->depth;
297+                   ptr += tile_bytes;
298+                   old_ptr += tile_bytes;
299                }
300            }
301 
302@@ -421,7 +492,8 @@
303            old_row += vs->ds->linesize;
304        }
305 
306-       if (!has_dirty)
307+       if (!vs->has_update || vs->visible_y >= vs->ds->height ||
308+           vs->visible_x >= vs->ds->width)
309            return;
310 
311        /* Count rectangles */
312@@ -431,34 +503,56 @@
313        saved_offset = vs->output.offset;
314        vnc_write_u16(vs, 0);
315 
316-       for (y = 0; y < vs->height; y++) {
317+       maxy = vs->visible_y + vs->visible_h;
318+       if (maxy > vs->ds->height)
319+           maxy = vs->ds->height;
320+       maxx = vs->visible_x + vs->visible_w;
321+       if (maxx > vs->ds->width)
322+           maxx = vs->ds->width;
323+
324+       for (y = vs->visible_y; y < maxy; y++) {
325            int x;
326            int last_x = -1;
327-           for (x = 0; x < vs->width / 16; x++) {
328-               if (vnc_get_bit(vs->dirty_row[y], x)) {
329-                   if (last_x == -1) {
330+           for (x = X2DP_DOWN(vs, vs->visible_x);
331+                x < X2DP_UP(vs, maxx); x++) {
332+               if (vs->update_row[y] & (1ULL << x)) {
333+                   if (last_x == -1)
334                        last_x = x;
335-                   }
336-                   vnc_clear_bit(vs->dirty_row[y], x);
337+                   vs->update_row[y] &= ~(1ULL << x);
338                } else {
339                    if (last_x != -1) {
340-                       int h = find_dirty_height(vs, y, last_x, x);
341-                       send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
342+                       int h = find_update_height(vs, y, maxy, last_x, x);
343+                       send_framebuffer_update(vs, DP2X(vs, last_x), y,
344+                                               DP2X(vs, (x - last_x)), h);
345                        n_rectangles++;
346                    }
347                    last_x = -1;
348                }
349            }
350            if (last_x != -1) {
351-               int h = find_dirty_height(vs, y, last_x, x);
352-               send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
353+               int h = find_update_height(vs, y, maxy, last_x, x);
354+               send_framebuffer_update(vs, DP2X(vs, last_x), y,
355+                                       DP2X(vs, (x - last_x)), h);
356                n_rectangles++;
357            }
358        }
359        vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;
360        vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF;
361+
362+       vs->has_update = 0;
363+       vs->need_update = 0;
364        vnc_flush(vs);
365-    }
366+       vs->slow_client = 0;
367+    } else
368+       vs->slow_client = 1;
369+}
370+
371+static void vnc_update_client(void *opaque)
372+{
373+    VncState *vs = opaque;
374+
375+    vs->ds->dpy_refresh(vs->ds);
376+    _vnc_update_client(vs);
377 }
378 
379 static void vnc_timer_init(VncState *vs)
380@@ -469,8 +563,6 @@
381 
382 static void vnc_dpy_refresh(DisplayState *ds)
383 {
384-    VncState *vs = ds->opaque;
385-    vnc_timer_init(vs);
386     vga_hw_update();
387 }
388 
389@@ -506,7 +598,7 @@
390 
391 static void buffer_reset(Buffer *buffer)
392 {
393-       buffer->offset = 0;
394+    buffer->offset = 0;
395 }
396 
397 static void buffer_append(Buffer *buffer, const void *data, size_t len)
398@@ -547,12 +639,12 @@
399     if (!ret)
400        return;
401 
402-    memmove(vs->output.buffer, vs->output.buffer + ret, (vs->output.offset - ret));
403+    memmove(vs->output.buffer, vs->output.buffer + ret,
404+           vs->output.offset - ret);
405     vs->output.offset -= ret;
406 
407-    if (vs->output.offset == 0) {
408+    if (vs->output.offset == 0)
409        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
410-    }
411 }
412 
413 static void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
414@@ -584,11 +676,11 @@
415            return;
416 
417        if (!ret) {
418-           memmove(vs->input.buffer, vs->input.buffer + len, (vs->input.offset - len));
419+           memmove(vs->input.buffer, vs->input.buffer + len,
420+                   vs->input.offset - len);
421            vs->input.offset -= len;
422-       } else {
423+       } else
424            vs->read_handler_expect = ret;
425-       }
426     }
427 }
428 
429@@ -596,9 +688,9 @@
430 {
431     buffer_reserve(&vs->output, len);
432 
433-    if (buffer_empty(&vs->output)) {
434-       qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
435-    }
436+    if (buffer_empty(&vs->output))
437+       qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read,
438+                            vnc_client_write, vs);
439 
440     buffer_append(&vs->output, data, len);
441 }
442@@ -720,22 +812,25 @@
443     do_key_event(vs, down, sym);
444 }
445 
446+static void framebuffer_set_updated(VncState *vs, int x, int y, int w, int h)
447+{
448+
449+    set_bits_in_row(vs, vs->update_row, x, y, w, h);
450+
451+    vs->has_update = 1;
452+}
453+
454 static void framebuffer_update_request(VncState *vs, int incremental,
455                                       int x_position, int y_position,
456                                       int w, int h)
457 {
458-    int i;
459     vs->need_update = 1;
460-    if (!incremental) {
461-       char *old_row = vs->old_data + y_position * vs->ds->linesize;
462-
463-       for (i = 0; i < h; i++) {
464-            vnc_set_bits(vs->dirty_row[y_position + i],
465-                         (vs->ds->width / 16), VNC_DIRTY_WORDS);
466-           memset(old_row, 42, vs->ds->width * vs->depth);
467-           old_row += vs->ds->linesize;
468-       }
469-    }
470+    if (!incremental)
471+       framebuffer_set_updated(vs, x_position, y_position, w, h);
472+    vs->visible_x = x_position;
473+    vs->visible_y = y_position;
474+    vs->visible_w = w;
475+    vs->visible_h = h;
476 
477     qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock));
478 }
479@@ -843,8 +938,6 @@
480     }
481 
482     vnc_dpy_resize(vs->ds, vs->ds->width, vs->ds->height);
483-    memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
484-    memset(vs->old_data, 42, vs->ds->linesize * vs->ds->height);
485 
486     vga_hw_invalidate();
487     vga_hw_update();
488@@ -924,6 +1017,8 @@
489 {
490     char pad[3] = { 0, 0, 0 };
491 
492+    vga_hw_update();
493+
494     vs->width = vs->ds->width;
495     vs->height = vs->ds->height;
496     vnc_write_u16(vs, vs->ds->width);
497@@ -1010,11 +1105,11 @@
498        vnc_write(vs, "RFB 003.003\n", 12);
499        vnc_flush(vs);
500        vnc_read_when(vs, protocol_version, 12);
501-       memset(vs->old_data, 0, vs->ds->linesize * vs->ds->height);
502-       memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
503+       framebuffer_set_updated(vs, 0, 0, vs->ds->width, vs->ds->height);
504        vs->has_resize = 0;
505        vs->has_hextile = 0;
506        vs->ds->dpy_copy = NULL;
507+       vnc_timer_init(vs);
508     }
509 }
510 
511@@ -1071,17 +1166,15 @@
512        exit(1);
513     }
514 
515-    ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs);
516-    if (ret == -1) {
517+    ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read,
518+                              NULL, vs);
519+    if (ret == -1)
520        exit(1);
521-    }
522 
523     vs->ds->data = NULL;
524     vs->ds->dpy_update = vnc_dpy_update;
525     vs->ds->dpy_resize = vnc_dpy_resize;
526     vs->ds->dpy_refresh = vnc_dpy_refresh;
527 
528-    memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
529-
530     vnc_dpy_resize(vs->ds, 640, 400);
531 }
532Index: ioemu/vl.h
533===================================================================
534--- ioemu.orig/vl.h     2007-05-03 10:24:05.000000000 +0100
535+++ ioemu/vl.h  2007-05-03 10:24:05.000000000 +0100
536@@ -319,6 +319,7 @@
537 int is_graphic_console(void);
538 CharDriverState *text_console_init(DisplayState *ds);
539 void console_select(unsigned int index);
540+void set_color_table(DisplayState *ds);
541 
542 /* serial ports */
543 
Note: See TracBrowser for help on using the repository browser.