Commit 7d957bd8cbcbf56f7916d375e65042d767f544b5

Authored by aliguori
1 parent 8927bcfd

DisplayState interface change (Stefano Stabellini)

This patch changes the DisplayState interface adding support for
multiple frontends at the same time (sdl and vnc) and implements most
of the benefit of the shared_buf patch without the added complexity.

Currently DisplayState is managed by sdl (or vnc) and sdl (or vnc) is
also responsible for allocating the data and setting the depth.
Vga.c (or another backend) will do any necessary conversion.

The idea is to change it so that is vga.c (or another backend) together
with console.c that fully manage the DisplayState interface allocating
data and setting the depth (either 16 or 32 bit, if the guest uses a
different resolution or is in text mode, vga.c (or another backend) is
in charge of doing the conversion seamlessly).

The other idea is that DisplayState supports *multiple* frontends
like sdl and vnc; each of them can register some callbacks to be called
when a display event occurs.

The interesting changes are:

- the new structures and related functions in console.h and console.c

in particular the following functions are very helpful to manage a
DisplaySurface:

qemu_create_displaysurface
qemu_resize_displaysurface
qemu_create_displaysurface_from
qemu_free_displaysurface

- console_select and qemu_console_resize in console.c
this two functions manage multiple consoles on a single host display

- moving code around in hw/vga.c
as for the shared_buf patch this is necessary to be able to handle a dynamic
DisplaySurface bpp

- changes to vga_draw_graphic in hw/vga.c
this is the place where the DisplaySurface buffer is shared with the
videoram, when possible;


Compared to the last version the only changes are:

- do not remove support to dpy_copy in cirrus_vga
- change the name of the displaysurface handling functions

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6336 c046a42c-6fe2-441c-8c8c-71466251a162
console.c
... ... @@ -1044,12 +1044,15 @@ void console_select(unsigned int index)
1044 1044  
1045 1045 if (index >= MAX_CONSOLES)
1046 1046 return;
  1047 + active_console->g_width = ds_get_width(active_console->ds);
  1048 + active_console->g_height = ds_get_height(active_console->ds);
1047 1049 s = consoles[index];
1048 1050 if (s) {
  1051 + DisplayState *ds = s->ds;
1049 1052 active_console = s;
1050   - if (s->console_type != TEXT_CONSOLE && s->g_width && s->g_height
1051   - && (s->g_width != ds_get_width(s->ds) || s->g_height != ds_get_height(s->ds)))
1052   - dpy_resize(s->ds, s->g_width, s->g_height);
  1053 + ds->surface = qemu_resize_displaysurface(ds->surface, s->g_width,
  1054 + s->g_height, 32, 4 * s->g_width);
  1055 + dpy_resize(s->ds);
1053 1056 vga_hw_invalidate();
1054 1057 }
1055 1058 }
... ... @@ -1157,16 +1160,6 @@ void kbd_put_keysym(int keysym)
1157 1160 static void text_console_invalidate(void *opaque)
1158 1161 {
1159 1162 TextConsole *s = (TextConsole *) opaque;
1160   -
1161   - if (s->g_width != ds_get_width(s->ds) || s->g_height != ds_get_height(s->ds)) {
1162   - if (s->console_type == TEXT_CONSOLE_FIXED_SIZE)
1163   - dpy_resize(s->ds, s->g_width, s->g_height);
1164   - else {
1165   - s->g_width = ds_get_width(s->ds);
1166   - s->g_height = ds_get_height(s->ds);
1167   - text_console_resize(s);
1168   - }
1169   - }
1170 1163 console_refresh(s);
1171 1164 }
1172 1165  
... ... @@ -1346,13 +1339,12 @@ CharDriverState *text_console_init(DisplayState *ds, const char *p)
1346 1339  
1347 1340 void qemu_console_resize(QEMUConsole *console, int width, int height)
1348 1341 {
1349   - if (console->g_width != width || console->g_height != height
1350   - || !ds_get_data(console->ds)) {
1351   - console->g_width = width;
1352   - console->g_height = height;
1353   - if (active_console == console) {
1354   - dpy_resize(console->ds, width, height);
1355   - }
  1342 + console->g_width = width;
  1343 + console->g_height = height;
  1344 + if (active_console == console) {
  1345 + DisplayState *ds = console->ds;
  1346 + ds->surface = qemu_resize_displaysurface(ds->surface, width, height, 32, 4 * width);
  1347 + dpy_resize(console->ds);
1356 1348 }
1357 1349 }
1358 1350  
... ... @@ -1360,12 +1352,137 @@ void qemu_console_copy(QEMUConsole *console, int src_x, int src_y,
1360 1352 int dst_x, int dst_y, int w, int h)
1361 1353 {
1362 1354 if (active_console == console) {
1363   - if (console->ds->dpy_copy)
1364   - console->ds->dpy_copy(console->ds,
1365   - src_x, src_y, dst_x, dst_y, w, h);
1366   - else {
1367   - /* TODO */
1368   - console->ds->dpy_update(console->ds, dst_x, dst_y, w, h);
1369   - }
  1355 + dpy_copy(console->ds, src_x, src_y, dst_x, dst_y, w, h);
1370 1356 }
1371 1357 }
  1358 +
  1359 +static PixelFormat qemu_default_pixelformat(int bpp)
  1360 +{
  1361 + PixelFormat pf;
  1362 +
  1363 + memset(&pf, 0x00, sizeof(PixelFormat));
  1364 +
  1365 + pf.bits_per_pixel = bpp;
  1366 + pf.bytes_per_pixel = bpp / 8;
  1367 + pf.depth = bpp == 32 ? 24 : bpp;
  1368 +
  1369 + switch (bpp) {
  1370 + case 8:
  1371 + pf.rmask = 0x000000E0;
  1372 + pf.gmask = 0x0000001C;
  1373 + pf.bmask = 0x00000003;
  1374 + pf.rmax = 7;
  1375 + pf.gmax = 7;
  1376 + pf.bmax = 3;
  1377 + pf.rshift = 5;
  1378 + pf.gshift = 2;
  1379 + pf.bshift = 0;
  1380 + break;
  1381 + case 16:
  1382 + pf.rmask = 0x0000F800;
  1383 + pf.gmask = 0x000007E0;
  1384 + pf.bmask = 0x0000001F;
  1385 + pf.rmax = 31;
  1386 + pf.gmax = 63;
  1387 + pf.bmax = 31;
  1388 + pf.rshift = 11;
  1389 + pf.gshift = 5;
  1390 + pf.bshift = 0;
  1391 + break;
  1392 + case 24:
  1393 + case 32:
  1394 + pf.rmask = 0x00FF0000;
  1395 + pf.gmask = 0x0000FF00;
  1396 + pf.bmask = 0x000000FF;
  1397 + pf.rmax = 255;
  1398 + pf.gmax = 255;
  1399 + pf.bmax = 255;
  1400 + pf.rshift = 16;
  1401 + pf.gshift = 8;
  1402 + pf.bshift = 0;
  1403 + break;
  1404 + default:
  1405 + break;
  1406 + }
  1407 + return pf;
  1408 +}
  1409 +
  1410 +DisplaySurface* qemu_create_displaysurface(int width, int height, int bpp, int linesize)
  1411 +{
  1412 + DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
  1413 + if (surface == NULL) {
  1414 + fprintf(stderr, "qemu_create_displaysurface: malloc failed\n");
  1415 + exit(1);
  1416 + }
  1417 +
  1418 + surface->width = width;
  1419 + surface->height = height;
  1420 + surface->linesize = linesize;
  1421 + surface->pf = qemu_default_pixelformat(bpp);
  1422 +#ifdef WORDS_BIGENDIAN
  1423 + surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
  1424 +#else
  1425 + surface->flags = QEMU_ALLOCATED_FLAG;
  1426 +#endif
  1427 + surface->data = (uint8_t*) qemu_mallocz(surface->linesize * surface->height);
  1428 + if (surface->data == NULL) {
  1429 + fprintf(stderr, "qemu_create_displaysurface: malloc failed\n");
  1430 + exit(1);
  1431 + }
  1432 +
  1433 + return surface;
  1434 +}
  1435 +
  1436 +DisplaySurface* qemu_resize_displaysurface(DisplaySurface *surface,
  1437 + int width, int height, int bpp, int linesize)
  1438 +{
  1439 + surface->width = width;
  1440 + surface->height = height;
  1441 + surface->linesize = linesize;
  1442 + surface->pf = qemu_default_pixelformat(bpp);
  1443 + if (surface->flags & QEMU_ALLOCATED_FLAG)
  1444 + surface->data = (uint8_t*) qemu_realloc(surface->data, surface->linesize * surface->height);
  1445 + else
  1446 + surface->data = (uint8_t*) qemu_malloc(surface->linesize * surface->height);
  1447 + if (surface->data == NULL) {
  1448 + fprintf(stderr, "qemu_resize_displaysurface: malloc failed\n");
  1449 + exit(1);
  1450 + }
  1451 +#ifdef WORDS_BIGENDIAN
  1452 + surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
  1453 +#else
  1454 + surface->flags = QEMU_ALLOCATED_FLAG;
  1455 +#endif
  1456 +
  1457 + return surface;
  1458 +}
  1459 +
  1460 +DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
  1461 + int linesize, uint8_t *data)
  1462 +{
  1463 + DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
  1464 + if (surface == NULL) {
  1465 + fprintf(stderr, "qemu_create_displaysurface_from: malloc failed\n");
  1466 + exit(1);
  1467 + }
  1468 +
  1469 + surface->width = width;
  1470 + surface->height = height;
  1471 + surface->linesize = linesize;
  1472 + surface->pf = qemu_default_pixelformat(bpp);
  1473 +#ifdef WORDS_BIGENDIAN
  1474 + surface->flags = QEMU_BIG_ENDIAN_FLAG;
  1475 +#endif
  1476 + surface->data = data;
  1477 +
  1478 + return surface;
  1479 +}
  1480 +
  1481 +void qemu_free_displaysurface(DisplaySurface *surface)
  1482 +{
  1483 + if (surface == NULL)
  1484 + return;
  1485 + if (surface->flags & QEMU_ALLOCATED_FLAG)
  1486 + qemu_free(surface->data);
  1487 + qemu_free(surface);
  1488 +}
... ...
console.h
... ... @@ -73,75 +73,168 @@ void kbd_put_keysym(int keysym);
73 73  
74 74 /* consoles */
75 75  
76   -struct DisplayState {
77   - uint8_t *data;
78   - int linesize;
79   - int depth;
80   - int bgr; /* BGR color order instead of RGB. Only valid for depth == 32 */
  76 +#define QEMU_BIG_ENDIAN_FLAG 0x01
  77 +#define QEMU_ALLOCATED_FLAG 0x02
  78 +
  79 +struct PixelFormat {
  80 + uint8_t bits_per_pixel;
  81 + uint8_t bytes_per_pixel;
  82 + uint8_t depth; /* color depth in bits */
  83 + uint32_t rmask, gmask, bmask, amask;
  84 + uint8_t rshift, gshift, bshift, ashift;
  85 + uint8_t rmax, gmax, bmax, amax;
  86 +};
  87 +
  88 +struct DisplaySurface {
  89 + uint8_t flags;
81 90 int width;
82 91 int height;
83   - void *opaque;
84   - struct QEMUTimer *gui_timer;
  92 + int linesize; /* bytes per line */
  93 + uint8_t *data;
  94 +
  95 + struct PixelFormat pf;
  96 +};
  97 +
  98 +struct DisplayChangeListener {
  99 + int idle;
85 100 uint64_t gui_timer_interval;
86   - int idle; /* there is nothing to update (window invisible), set by vnc/sdl */
87 101  
88 102 void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h);
89   - void (*dpy_resize)(struct DisplayState *s, int w, int h);
  103 + void (*dpy_resize)(struct DisplayState *s);
  104 + void (*dpy_setdata)(struct DisplayState *s);
90 105 void (*dpy_refresh)(struct DisplayState *s);
91 106 void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y,
92 107 int dst_x, int dst_y, int w, int h);
93 108 void (*dpy_fill)(struct DisplayState *s, int x, int y,
94 109 int w, int h, uint32_t c);
95 110 void (*dpy_text_cursor)(struct DisplayState *s, int x, int y);
  111 +
  112 + struct DisplayChangeListener *next;
  113 +};
  114 +
  115 +struct DisplayState {
  116 + struct DisplaySurface *surface;
  117 + void *opaque;
  118 + struct QEMUTimer *gui_timer;
  119 +
  120 + struct DisplayChangeListener* listeners;
  121 +
96 122 void (*mouse_set)(int x, int y, int on);
97 123 void (*cursor_define)(int width, int height, int bpp, int hot_x, int hot_y,
98 124 uint8_t *image, uint8_t *mask);
99 125 };
100 126  
  127 +DisplaySurface* qemu_create_displaysurface(int width, int height, int bpp, int linesize);
  128 +DisplaySurface* qemu_resize_displaysurface(DisplaySurface *surface,
  129 + int width, int height, int bpp, int linesize);
  130 +DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
  131 + int linesize, uint8_t *data);
  132 +void qemu_free_displaysurface(DisplaySurface *surface);
  133 +
  134 +static inline int is_buffer_shared(DisplaySurface *surface)
  135 +{
  136 + return (!(surface->flags & QEMU_ALLOCATED_FLAG));
  137 +}
  138 +
  139 +static inline void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl)
  140 +{
  141 + dcl->next = ds->listeners;
  142 + ds->listeners = dcl;
  143 +}
  144 +
101 145 static inline void dpy_update(DisplayState *s, int x, int y, int w, int h)
102 146 {
103   - s->dpy_update(s, x, y, w, h);
  147 + struct DisplayChangeListener *dcl = s->listeners;
  148 + while (dcl != NULL) {
  149 + dcl->dpy_update(s, x, y, w, h);
  150 + dcl = dcl->next;
  151 + }
104 152 }
105 153  
106   -static inline void dpy_resize(DisplayState *s, int w, int h)
  154 +static inline void dpy_resize(DisplayState *s)
107 155 {
108   - s->dpy_resize(s, w, h);
  156 + struct DisplayChangeListener *dcl = s->listeners;
  157 + while (dcl != NULL) {
  158 + dcl->dpy_resize(s);
  159 + dcl = dcl->next;
  160 + }
109 161 }
110 162  
111   -static inline void dpy_cursor(DisplayState *s, int x, int y)
  163 +static inline void dpy_setdata(DisplayState *s)
112 164 {
113   - if (s->dpy_text_cursor)
114   - s->dpy_text_cursor(s, x, y);
  165 + struct DisplayChangeListener *dcl = s->listeners;
  166 + while (dcl != NULL) {
  167 + if (dcl->dpy_setdata) dcl->dpy_setdata(s);
  168 + dcl = dcl->next;
  169 + }
  170 +}
  171 +
  172 +static inline void dpy_refresh(DisplayState *s)
  173 +{
  174 + struct DisplayChangeListener *dcl = s->listeners;
  175 + while (dcl != NULL) {
  176 + if (dcl->dpy_refresh) dcl->dpy_refresh(s);
  177 + dcl = dcl->next;
  178 + }
  179 +}
  180 +
  181 +static inline void dpy_copy(struct DisplayState *s, int src_x, int src_y,
  182 + int dst_x, int dst_y, int w, int h) {
  183 + struct DisplayChangeListener *dcl = s->listeners;
  184 + while (dcl != NULL) {
  185 + if (dcl->dpy_copy)
  186 + dcl->dpy_copy(s, src_x, src_y, dst_x, dst_y, w, h);
  187 + else /* TODO */
  188 + dcl->dpy_update(s, dst_x, dst_y, w, h);
  189 + dcl = dcl->next;
  190 + }
  191 +}
  192 +
  193 +static inline void dpy_fill(struct DisplayState *s, int x, int y,
  194 + int w, int h, uint32_t c) {
  195 + struct DisplayChangeListener *dcl = s->listeners;
  196 + while (dcl != NULL) {
  197 + if (dcl->dpy_fill) dcl->dpy_fill(s, x, y, w, h, c);
  198 + dcl = dcl->next;
  199 + }
  200 +}
  201 +
  202 +static inline void dpy_cursor(struct DisplayState *s, int x, int y) {
  203 + struct DisplayChangeListener *dcl = s->listeners;
  204 + while (dcl != NULL) {
  205 + if (dcl->dpy_text_cursor) dcl->dpy_text_cursor(s, x, y);
  206 + dcl = dcl->next;
  207 + }
115 208 }
116 209  
117 210 static inline int ds_get_linesize(DisplayState *ds)
118 211 {
119   - return ds->linesize;
  212 + return ds->surface->linesize;
120 213 }
121 214  
122 215 static inline uint8_t* ds_get_data(DisplayState *ds)
123 216 {
124   - return ds->data;
  217 + return ds->surface->data;
125 218 }
126 219  
127 220 static inline int ds_get_width(DisplayState *ds)
128 221 {
129   - return ds->width;
  222 + return ds->surface->width;
130 223 }
131 224  
132 225 static inline int ds_get_height(DisplayState *ds)
133 226 {
134   - return ds->height;
  227 + return ds->surface->height;
135 228 }
136 229  
137 230 static inline int ds_get_bits_per_pixel(DisplayState *ds)
138 231 {
139   - return ds->depth;
  232 + return ds->surface->pf.bits_per_pixel;
140 233 }
141 234  
142 235 static inline int ds_get_bytes_per_pixel(DisplayState *ds)
143 236 {
144   - return (ds->depth / 8);
  237 + return ds->surface->pf.bytes_per_pixel;
145 238 }
146 239  
147 240 typedef unsigned long console_ch_t;
... ...
curses.c
... ... @@ -97,13 +97,13 @@ static void curses_calc_pad(void)
97 97 }
98 98 }
99 99  
100   -static void curses_resize(DisplayState *ds, int w, int h)
  100 +static void curses_resize(DisplayState *ds)
101 101 {
102   - if (w == gwidth && h == gheight)
  102 + if (ds_get_width(ds) == gwidth && ds_get_height(ds) == gheight)
103 103 return;
104 104  
105   - gwidth = w;
106   - gheight = h;
  105 + gwidth = ds_get_width(ds);
  106 + gheight = ds_get_height(ds);
107 107  
108 108 curses_calc_pad();
109 109 }
... ... @@ -169,8 +169,8 @@ static void curses_refresh(DisplayState *ds)
169 169 clear();
170 170 refresh();
171 171 curses_calc_pad();
172   - ds->width = FONT_WIDTH * width;
173   - ds->height = FONT_HEIGHT * height;
  172 + ds->surface->width = FONT_WIDTH * width;
  173 + ds->surface->height = FONT_HEIGHT * height;
174 174 vga_hw_invalidate();
175 175 invalidate = 0;
176 176 }
... ... @@ -197,8 +197,8 @@ static void curses_refresh(DisplayState *ds)
197 197 refresh();
198 198 curses_calc_pad();
199 199 curses_update(ds, 0, 0, width, height);
200   - ds->width = FONT_WIDTH * width;
201   - ds->height = FONT_HEIGHT * height;
  200 + ds->surface->width = FONT_WIDTH * width;
  201 + ds->surface->height = FONT_HEIGHT * height;
202 202 continue;
203 203 }
204 204 #endif
... ... @@ -338,6 +338,7 @@ static void curses_keyboard_setup(void)
338 338  
339 339 void curses_display_init(DisplayState *ds, int full_screen)
340 340 {
  341 + DisplayChangeListener *dcl;
341 342 #ifndef _WIN32
342 343 if (!isatty(1)) {
343 344 fprintf(stderr, "We need a terminal output\n");
... ... @@ -357,18 +358,19 @@ void curses_display_init(DisplayState *ds, int full_screen)
357 358 #endif
358 359 #endif
359 360  
360   - ds->data = (void *) screen;
361   - ds->linesize = 0;
362   - ds->depth = 0;
363   - ds->width = 640;
364   - ds->height = 400;
365   - ds->dpy_update = curses_update;
366   - ds->dpy_resize = curses_resize;
367   - ds->dpy_refresh = curses_refresh;
368   - ds->dpy_text_cursor = curses_cursor_position;
  361 + dcl = (DisplayChangeListener *) qemu_mallocz(sizeof(DisplayChangeListener));
  362 + if (!dcl)
  363 + exit(1);
  364 + dcl->dpy_update = curses_update;
  365 + dcl->dpy_resize = curses_resize;
  366 + dcl->dpy_refresh = curses_refresh;
  367 + dcl->dpy_text_cursor = curses_cursor_position;
  368 + register_displaychangelistener(ds, dcl);
  369 + qemu_free_displaysurface(ds->surface);
  370 + ds->surface = qemu_create_displaysurface_from(80, 25, 0, 0, (uint8_t*) screen);
369 371  
370 372 invalidate = 1;
371 373  
372 374 /* Standard VGA initial text mode dimensions */
373   - curses_resize(ds, 80, 25);
  375 + curses_resize(ds);
374 376 }
... ...
hw/cirrus_vga.c
... ... @@ -793,22 +793,9 @@ static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
793 793 if (BLTUNSAFE(s))
794 794 return 0;
795 795  
796   - if (s->ds->dpy_copy) {
797   - cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->start_addr,
798   - s->cirrus_blt_srcaddr - s->start_addr,
799   - s->cirrus_blt_width, s->cirrus_blt_height);
800   - } else {
801   - (*s->cirrus_rop) (s, s->vram_ptr +
802   - (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
803   - s->vram_ptr +
804   - (s->cirrus_blt_srcaddr & s->cirrus_addr_mask),
805   - s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
806   - s->cirrus_blt_width, s->cirrus_blt_height);
807   -
808   - cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
809   - s->cirrus_blt_dstpitch, s->cirrus_blt_width,
810   - s->cirrus_blt_height);
811   - }
  796 + cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->start_addr,
  797 + s->cirrus_blt_srcaddr - s->start_addr,
  798 + s->cirrus_blt_width, s->cirrus_blt_height);
812 799  
813 800 return 1;
814 801 }
... ...
hw/nseries.c
... ... @@ -1360,7 +1360,8 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
1360 1360 /* FIXME: We shouldn't really be doing this here. The LCD controller
1361 1361 will set the size once configured, so this just sets an initial
1362 1362 size until the guest activates the display. */
1363   - dpy_resize(ds, 800, 480);
  1363 + ds->surface = qemu_resize_displaysurface(ds->surface, 800, 480, 32, 4 * 800);
  1364 + dpy_resize(ds);
1364 1365 }
1365 1366  
1366 1367 static struct arm_boot_info n800_binfo = {
... ...
hw/palm.c
... ... @@ -277,7 +277,8 @@ static void palmte_init(ram_addr_t ram_size, int vga_ram_size,
277 277 /* FIXME: We shouldn't really be doing this here. The LCD controller
278 278 will set the size once configured, so this just sets an initial
279 279 size until the guest activates the display. */
280   - dpy_resize(ds, 320, 320);
  280 + ds->surface = qemu_resize_displaysurface(ds->surface, 320, 320, 32, 4 * 320);
  281 + dpy_resize(ds);
281 282 }
282 283  
283 284 QEMUMachine palmte_machine = {
... ...
hw/vga.c
... ... @@ -1243,6 +1243,10 @@ static void vga_get_text_resolution(VGAState *s, int *pwidth, int *pheight,
1243 1243 *pcheight = cheight;
1244 1244 }
1245 1245  
  1246 +typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
  1247 +
  1248 +static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS];
  1249 +
1246 1250 /*
1247 1251 * Text mode update
1248 1252 * Missing:
... ... @@ -1266,9 +1270,6 @@ static void vga_draw_text(VGAState *s, int full_update)
1266 1270  
1267 1271 vga_dirty_log_stop(s);
1268 1272  
1269   - full_update |= update_palette16(s);
1270   - palette = s->last_palette;
1271   -
1272 1273 /* compute font data address (in plane 2) */
1273 1274 v = s->sr[3];
1274 1275 offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
... ... @@ -1303,16 +1304,23 @@ static void vga_draw_text(VGAState *s, int full_update)
1303 1304 }
1304 1305  
1305 1306 if (width != s->last_width || height != s->last_height ||
1306   - cw != s->last_cw || cheight != s->last_ch) {
  1307 + cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
1307 1308 s->last_scr_width = width * cw;
1308 1309 s->last_scr_height = height * cheight;
1309 1310 qemu_console_resize(s->console, s->last_scr_width, s->last_scr_height);
  1311 + s->last_depth = 0;
1310 1312 s->last_width = width;
1311 1313 s->last_height = height;
1312 1314 s->last_ch = cheight;
1313 1315 s->last_cw = cw;
1314 1316 full_update = 1;
1315 1317 }
  1318 + s->rgb_to_pixel =
  1319 + rgb_to_pixel_dup_table[get_depth_index(s->ds)];
  1320 + full_update |= update_palette16(s);
  1321 + palette = s->last_palette;
  1322 + x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
  1323 +
1316 1324 cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1317 1325 if (cursor_offset != s->cursor_offset ||
1318 1326 s->cr[0xa] != s->cursor_start ||
... ... @@ -1504,8 +1512,6 @@ static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1504 1512 vga_draw_line32_16bgr,
1505 1513 };
1506 1514  
1507   -typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1508   -
1509 1515 static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
1510 1516 rgb_to_pixel8_dup,
1511 1517 rgb_to_pixel15_dup,
... ... @@ -1580,7 +1586,7 @@ static void vga_sync_dirty_bitmap(VGAState *s)
1580 1586 */
1581 1587 static void vga_draw_graphic(VGAState *s, int full_update)
1582 1588 {
1583   - int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
  1589 + int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask, depth;
1584 1590 int width, height, shift_control, line_offset, page0, page1, bwidth, bits;
1585 1591 int disp_width, multi_scan, multi_run;
1586 1592 uint8_t *d;
... ... @@ -1663,16 +1669,41 @@ static void vga_draw_graphic(VGAState *s, int full_update)
1663 1669 }
1664 1670 vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1665 1671  
1666   - if (disp_width != s->last_width ||
1667   - height != s->last_height) {
1668   - qemu_console_resize(s->console, disp_width, height);
  1672 + depth = s->get_bpp(s);
  1673 + if (s->line_offset != s->last_line_offset ||
  1674 + disp_width != s->last_width ||
  1675 + height != s->last_height ||
  1676 + s->last_depth != depth) {
  1677 + if (depth == 16 || depth == 32) {
  1678 + if (is_graphic_console()) {
  1679 + qemu_free_displaysurface(s->ds->surface);
  1680 + s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
  1681 + s->line_offset,
  1682 + s->vram_ptr + (s->start_addr * 4));
  1683 + dpy_resize(s->ds);
  1684 + } else {
  1685 + qemu_console_resize(s->console, disp_width, height);
  1686 + }
  1687 + } else {
  1688 + qemu_console_resize(s->console, disp_width, height);
  1689 + }
1669 1690 s->last_scr_width = disp_width;
1670 1691 s->last_scr_height = height;
1671 1692 s->last_width = disp_width;
1672 1693 s->last_height = height;
  1694 + s->last_line_offset = s->line_offset;
  1695 + s->last_depth = depth;
1673 1696 full_update = 1;
  1697 + } else if (is_graphic_console() && is_buffer_shared(s->ds->surface) &&
  1698 + (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
  1699 + s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
  1700 + dpy_setdata(s->ds);
1674 1701 }
1675   - if (s->cursor_invalidate)
  1702 +
  1703 + s->rgb_to_pixel =
  1704 + rgb_to_pixel_dup_table[get_depth_index(s->ds)];
  1705 +
  1706 + if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1676 1707 s->cursor_invalidate(s);
1677 1708  
1678 1709 line_offset = s->line_offset;
... ... @@ -1718,9 +1749,11 @@ static void vga_draw_graphic(VGAState *s, int full_update)
1718 1749 page_min = page0;
1719 1750 if (page1 > page_max)
1720 1751 page_max = page1;
1721   - vga_draw_line(s, d, s->vram_ptr + addr, width);
1722   - if (s->cursor_draw_line)
1723   - s->cursor_draw_line(s, d, y);
  1752 + if (!(is_buffer_shared(s->ds->surface))) {
  1753 + vga_draw_line(s, d, s->vram_ptr + addr, width);
  1754 + if (s->cursor_draw_line)
  1755 + s->cursor_draw_line(s, d, y);
  1756 + }
1724 1757 } else {
1725 1758 if (y_start >= 0) {
1726 1759 /* flush to display */
... ... @@ -1767,6 +1800,8 @@ static void vga_draw_blank(VGAState *s, int full_update)
1767 1800 return;
1768 1801 vga_dirty_log_stop(s);
1769 1802  
  1803 + s->rgb_to_pixel =
  1804 + rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1770 1805 if (ds_get_bits_per_pixel(s->ds) == 8)
1771 1806 val = s->rgb_to_pixel(0, 0, 0);
1772 1807 else
... ... @@ -1793,9 +1828,6 @@ static void vga_update_display(void *opaque)
1793 1828 if (ds_get_bits_per_pixel(s->ds) == 0) {
1794 1829 /* nothing to do */
1795 1830 } else {
1796   - s->rgb_to_pixel =
1797   - rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1798   -
1799 1831 full_update = 0;
1800 1832 if (!(s->ar_index & 0x20)) {
1801 1833 graphic_mode = GMODE_BLANK;
... ... @@ -1966,7 +1998,9 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
1966 1998 cw != s->last_cw || cheight != s->last_ch) {
1967 1999 s->last_scr_width = width * cw;
1968 2000 s->last_scr_height = height * cheight;
1969   - qemu_console_resize(s->console, width, height);
  2001 + s->ds->surface->width = width;
  2002 + s->ds->surface->height = height;
  2003 + dpy_resize(s->ds);
1970 2004 s->last_width = width;
1971 2005 s->last_height = height;
1972 2006 s->last_ch = cheight;
... ... @@ -2047,7 +2081,9 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
2047 2081 s->last_width = 60;
2048 2082 s->last_height = height = 3;
2049 2083 dpy_cursor(s->ds, -1, -1);
2050   - qemu_console_resize(s->console, s->last_width, height);
  2084 + s->ds->surface->width = s->last_width;
  2085 + s->ds->surface->height = height;
  2086 + dpy_resize(s->ds);
2051 2087  
2052 2088 for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2053 2089 console_write_ch(dst ++, ' ');
... ... @@ -2505,12 +2541,8 @@ static void vga_save_dpy_update(DisplayState *s,
2505 2541 {
2506 2542 }
2507 2543  
2508   -static void vga_save_dpy_resize(DisplayState *s, int w, int h)
  2544 +static void vga_save_dpy_resize(DisplayState *s)
2509 2545 {
2510   - s->linesize = w * 4;
2511   - s->data = qemu_mallocz(h * s->linesize);
2512   - vga_save_w = w;
2513   - vga_save_h = h;
2514 2546 }
2515 2547  
2516 2548 static void vga_save_dpy_refresh(DisplayState *s)
... ... @@ -2570,24 +2602,29 @@ static void vga_screen_dump_common(VGAState *s, const char *filename,
2570 2602 int w, int h)
2571 2603 {
2572 2604 DisplayState *saved_ds, ds1, *ds = &ds1;
  2605 + DisplayChangeListener dcl;
2573 2606  
2574 2607 /* XXX: this is a little hackish */
2575 2608 vga_invalidate_display(s);
2576 2609 saved_ds = s->ds;
2577 2610  
2578 2611 memset(ds, 0, sizeof(DisplayState));
2579   - ds->dpy_update = vga_save_dpy_update;
2580   - ds->dpy_resize = vga_save_dpy_resize;
2581   - ds->dpy_refresh = vga_save_dpy_refresh;
2582   - ds->depth = 32;
  2612 + memset(&dcl, 0, sizeof(DisplayChangeListener));
  2613 + dcl.dpy_update = vga_save_dpy_update;
  2614 + dcl.dpy_resize = vga_save_dpy_resize;
  2615 + dcl.dpy_refresh = vga_save_dpy_refresh;
  2616 + register_displaychangelistener(ds, &dcl);
  2617 + ds->surface = qemu_create_displaysurface(ds_get_width(saved_ds),
  2618 + ds_get_height(saved_ds), 32, 4 * ds_get_width(saved_ds));
2583 2619  
2584   - ds->linesize = w * sizeof(uint32_t);
2585   - ds->data = qemu_mallocz(h * ds->linesize);
2586 2620 s->ds = ds;
2587 2621 s->graphic_mode = -1;
2588 2622 vga_update_display(s);
2589   - ppm_save(filename, ds->data, w, h, ds->linesize);
2590   - qemu_free(ds->data);
  2623 +
  2624 + ppm_save(filename, ds_get_data(ds), vga_save_w, vga_save_h,
  2625 + ds_get_linesize(ds));
  2626 +
  2627 + qemu_free_displaysurface(ds->surface);
2591 2628 s->ds = saved_ds;
2592 2629 }
2593 2630  
... ...
hw/vga_int.h
... ... @@ -154,9 +154,11 @@ typedef void (* vga_update_retrace_info_fn)(struct VGAState *s);
154 154 uint32_t line_compare; \
155 155 uint32_t start_addr; \
156 156 uint32_t plane_updated; \
  157 + uint32_t last_line_offset; \
157 158 uint8_t last_cw, last_ch; \
158 159 uint32_t last_width, last_height; /* in chars or pixels */ \
159 160 uint32_t last_scr_width, last_scr_height; /* in pixels */ \
  161 + uint32_t last_depth; /* in bits */ \
160 162 uint8_t cursor_start, cursor_end; \
161 163 uint32_t cursor_offset; \
162 164 unsigned int (*rgb_to_pixel)(unsigned int r, \
... ...
qemu-common.h
... ... @@ -166,6 +166,9 @@ typedef struct HCIInfo HCIInfo;
166 166 typedef struct AudioState AudioState;
167 167 typedef struct BlockDriverState BlockDriverState;
168 168 typedef struct DisplayState DisplayState;
  169 +typedef struct DisplayChangeListener DisplayChangeListener;
  170 +typedef struct DisplaySurface DisplaySurface;
  171 +typedef struct PixelFormat PixelFormat;
169 172 typedef struct TextConsole TextConsole;
170 173 typedef TextConsole QEMUConsole;
171 174 typedef struct CharDriverState CharDriverState;
... ...
... ... @@ -31,7 +31,9 @@
31 31 #include <signal.h>
32 32 #endif
33 33  
34   -static SDL_Surface *screen;
  34 +static DisplayChangeListener *dcl;
  35 +static SDL_Surface *real_screen;
  36 +static SDL_Surface *guest_screen = NULL;
35 37 static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
36 38 static int last_vm_running;
37 39 static int gui_saved_grab;
... ... @@ -52,11 +54,34 @@ static SDL_Cursor *guest_sprite = 0;
52 54  
53 55 static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
54 56 {
  57 + SDL_Rect rec;
  58 + rec.x = x;
  59 + rec.y = y;
  60 + rec.w = w;
  61 + rec.h = h;
55 62 // printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
56   - SDL_UpdateRect(screen, x, y, w, h);
  63 +
  64 + SDL_BlitSurface(guest_screen, &rec, real_screen, &rec);
  65 + SDL_Flip(real_screen);
  66 +}
  67 +
  68 +static void sdl_setdata(DisplayState *ds)
  69 +{
  70 + SDL_Rect rec;
  71 + rec.x = 0;
  72 + rec.y = 0;
  73 + rec.w = real_screen->w;
  74 + rec.h = real_screen->h;
  75 +
  76 + if (guest_screen != NULL) SDL_FreeSurface(guest_screen);
  77 +
  78 + guest_screen = SDL_CreateRGBSurfaceFrom(ds_get_data(ds), ds_get_width(ds), ds_get_height(ds),
  79 + ds_get_bits_per_pixel(ds), ds_get_linesize(ds),
  80 + ds->surface->pf.rmask, ds->surface->pf.gmask,
  81 + ds->surface->pf.bmask, ds->surface->pf.amask);
57 82 }
58 83  
59   -static void sdl_resize(DisplayState *ds, int w, int h)
  84 +static void sdl_resize(DisplayState *ds)
60 85 {
61 86 int flags;
62 87  
... ... @@ -68,40 +93,23 @@ static void sdl_resize(DisplayState *ds, int w, int h)
68 93 if (gui_noframe)
69 94 flags |= SDL_NOFRAME;
70 95  
71   - width = w;
72   - height = h;
73   -
74 96 again:
75   - screen = SDL_SetVideoMode(w, h, 0, flags);
76   - if (!screen) {
  97 + real_screen = SDL_SetVideoMode(ds_get_width(ds), ds_get_height(ds), 0, flags);
  98 + if (!real_screen) {
77 99 fprintf(stderr, "Could not open SDL display\n");
78 100 exit(1);
79 101 }
80   - if (!screen->pixels && (flags & SDL_HWSURFACE) && (flags & SDL_FULLSCREEN)) {
  102 + if (!real_screen->pixels && (flags & SDL_HWSURFACE) && (flags & SDL_FULLSCREEN)) {
81 103 flags &= ~SDL_HWSURFACE;
82 104 goto again;
83 105 }
84 106  
85   - if (!screen->pixels) {
  107 + if (!real_screen->pixels) {
86 108 fprintf(stderr, "Could not open SDL display\n");
87 109 exit(1);
88 110 }
89   - ds->data = screen->pixels;
90   - ds->linesize = screen->pitch;
91   - ds->depth = screen->format->BitsPerPixel;
92   - /* SDL BitsPerPixel never indicates any values other than
93   - multiples of 8, so we need to check for strange depths. */
94   - if (ds->depth == 16) {
95   - uint32_t mask;
96   -
97   - mask = screen->format->Rmask;
98   - mask |= screen->format->Gmask;
99   - mask |= screen->format->Bmask;
100   - if ((mask & 0x8000) == 0)
101   - ds->depth = 15;
102   - }
103   - ds->width = w;
104   - ds->height = h;
  111 +
  112 + sdl_setdata(ds);
105 113 }
106 114  
107 115 /* generic keyboard conversion */
... ... @@ -337,7 +345,7 @@ static void sdl_send_mouse_event(int dx, int dy, int dz, int x, int y, int state
337 345 static void toggle_full_screen(DisplayState *ds)
338 346 {
339 347 gui_fullscreen = !gui_fullscreen;
340   - sdl_resize(ds, screen->w, screen->h);
  348 + sdl_resize(ds);
341 349 if (gui_fullscreen) {
342 350 gui_saved_grab = gui_grab;
343 351 sdl_grab_start();
... ... @@ -366,7 +374,7 @@ static void sdl_refresh(DisplayState *ds)
366 374 while (SDL_PollEvent(ev)) {
367 375 switch (ev->type) {
368 376 case SDL_VIDEOEXPOSE:
369   - sdl_update(ds, 0, 0, screen->w, screen->h);
  377 + sdl_update(ds, 0, 0, real_screen->w, real_screen->h);
370 378 break;
371 379 case SDL_KEYDOWN:
372 380 case SDL_KEYUP:
... ... @@ -521,12 +529,12 @@ static void sdl_refresh(DisplayState *ds)
521 529 if (ev->active.state & SDL_APPACTIVE) {
522 530 if (ev->active.gain) {
523 531 /* Back to default interval */
524   - ds->gui_timer_interval = 0;
525   - ds->idle = 0;
  532 + dcl->gui_timer_interval = 0;
  533 + dcl->idle = 0;
526 534 } else {
527 535 /* Sleeping interval */
528   - ds->gui_timer_interval = 500;
529   - ds->idle = 1;
  536 + dcl->gui_timer_interval = 500;
  537 + dcl->idle = 1;
530 538 }
531 539 }
532 540 break;
... ... @@ -539,7 +547,7 @@ static void sdl_refresh(DisplayState *ds)
539 547 static void sdl_fill(DisplayState *ds, int x, int y, int w, int h, uint32_t c)
540 548 {
541 549 SDL_Rect dst = { x, y, w, h };
542   - SDL_FillRect(screen, &dst, c);
  550 + SDL_FillRect(real_screen, &dst, c);
543 551 }
544 552  
545 553 static void sdl_mouse_warp(int x, int y, int on)
... ... @@ -635,14 +643,18 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
635 643 exit(1);
636 644 }
637 645  
638   - ds->dpy_update = sdl_update;
639   - ds->dpy_resize = sdl_resize;
640   - ds->dpy_refresh = sdl_refresh;
641   - ds->dpy_fill = sdl_fill;
  646 + dcl = qemu_mallocz(sizeof(DisplayChangeListener));
  647 + if (!dcl)
  648 + exit(1);
  649 + dcl->dpy_update = sdl_update;
  650 + dcl->dpy_resize = sdl_resize;
  651 + dcl->dpy_refresh = sdl_refresh;
  652 + dcl->dpy_setdata = sdl_setdata;
  653 + dcl->dpy_fill = sdl_fill;
642 654 ds->mouse_set = sdl_mouse_warp;
643 655 ds->cursor_define = sdl_mouse_define;
  656 + register_displaychangelistener(ds, dcl);
644 657  
645   - sdl_resize(ds, 640, 400);
646 658 sdl_update_caption();
647 659 SDL_EnableKeyRepeat(250, 50);
648 660 gui_grab = 0;
... ...
... ... @@ -193,6 +193,7 @@ enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
193 193 DisplayState display_state;
194 194 int nographic;
195 195 static int curses;
  196 +static int sdl;
196 197 const char* keyboard_layout = NULL;
197 198 int64_t ticks_per_sec;
198 199 ram_addr_t ram_size;
... ... @@ -2764,20 +2765,21 @@ static void dumb_update(DisplayState *ds, int x, int y, int w, int h)
2764 2765 {
2765 2766 }
2766 2767  
2767   -static void dumb_resize(DisplayState *ds, int w, int h)
  2768 +static void dumb_resize(DisplayState *ds)
2768 2769 {
2769 2770 }
2770 2771  
2771 2772 static void dumb_display_init(DisplayState *ds)
2772 2773 {
2773   - ds->data = NULL;
2774   - ds->linesize = 0;
2775   - ds->depth = 0;
2776   - ds->dpy_update = dumb_update;
2777   - ds->dpy_resize = dumb_resize;
2778   - ds->dpy_refresh = NULL;
2779   - ds->gui_timer_interval = 0;
2780   - ds->idle = 1;
  2774 + DisplayChangeListener *dcl = qemu_mallocz(sizeof(DisplayChangeListener));
  2775 + if (!dcl)
  2776 + exit(1);
  2777 + dcl->dpy_update = dumb_update;
  2778 + dcl->dpy_resize = dumb_resize;
  2779 + dcl->dpy_refresh = NULL;
  2780 + dcl->idle = 1;
  2781 + dcl->gui_timer_interval = 500;
  2782 + register_displaychangelistener(ds, dcl);
2781 2783 }
2782 2784  
2783 2785 /***********************************************************/
... ... @@ -3360,13 +3362,19 @@ static QEMUMachine *find_machine(const char *name)
3360 3362  
3361 3363 static void gui_update(void *opaque)
3362 3364 {
  3365 + uint64_t interval = GUI_REFRESH_INTERVAL;
3363 3366 DisplayState *ds = opaque;
3364   - ds->dpy_refresh(ds);
3365   - qemu_mod_timer(ds->gui_timer,
3366   - (ds->gui_timer_interval ?
3367   - ds->gui_timer_interval :
3368   - GUI_REFRESH_INTERVAL)
3369   - + qemu_get_clock(rt_clock));
  3367 + DisplayChangeListener *dcl = ds->listeners;
  3368 +
  3369 + dpy_refresh(ds);
  3370 +
  3371 + while (dcl != NULL) {
  3372 + if (dcl->gui_timer_interval &&
  3373 + dcl->gui_timer_interval < interval)
  3374 + interval = dcl->gui_timer_interval;
  3375 + dcl = dcl->next;
  3376 + }
  3377 + qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock(rt_clock));
3370 3378 }
3371 3379  
3372 3380 struct vm_change_state_entry {
... ... @@ -3848,6 +3856,7 @@ static void help(int exitcode)
3848 3856 "-no-frame open SDL window without a frame and window decorations\n"
3849 3857 "-alt-grab use Ctrl-Alt-Shift to grab mouse (instead of Ctrl-Alt)\n"
3850 3858 "-no-quit disable SDL window close capability\n"
  3859 + "-sdl enable SDL\n"
3851 3860 #endif
3852 3861 #ifdef TARGET_I386
3853 3862 "-no-fd-bootchk disable boot signature checking for floppy disks\n"
... ... @@ -4064,6 +4073,7 @@ enum {
4064 4073 QEMU_OPTION_no_frame,
4065 4074 QEMU_OPTION_alt_grab,
4066 4075 QEMU_OPTION_no_quit,
  4076 + QEMU_OPTION_sdl,
4067 4077 QEMU_OPTION_pidfile,
4068 4078 QEMU_OPTION_no_kqemu,
4069 4079 QEMU_OPTION_kernel_kqemu,
... ... @@ -4176,6 +4186,7 @@ static const QEMUOption qemu_options[] = {
4176 4186 { "no-frame", 0, QEMU_OPTION_no_frame },
4177 4187 { "alt-grab", 0, QEMU_OPTION_alt_grab },
4178 4188 { "no-quit", 0, QEMU_OPTION_no_quit },
  4189 + { "sdl", 0, QEMU_OPTION_sdl },
4179 4190 #endif
4180 4191 { "pidfile", HAS_ARG, QEMU_OPTION_pidfile },
4181 4192 { "win2k-hack", 0, QEMU_OPTION_win2k_hack },
... ... @@ -4495,6 +4506,7 @@ int main(int argc, char **argv, char **envp)
4495 4506 const char *kernel_filename, *kernel_cmdline;
4496 4507 const char *boot_devices = "";
4497 4508 DisplayState *ds = &display_state;
  4509 + DisplayChangeListener *dcl;
4498 4510 int cyls, heads, secs, translation;
4499 4511 const char *net_clients[MAX_NET_CLIENTS];
4500 4512 int nb_net_clients;
... ... @@ -5007,6 +5019,9 @@ int main(int argc, char **argv, char **envp)
5007 5019 case QEMU_OPTION_no_quit:
5008 5020 no_quit = 1;
5009 5021 break;
  5022 + case QEMU_OPTION_sdl:
  5023 + sdl = 1;
  5024 + break;
5010 5025 #endif
5011 5026 case QEMU_OPTION_pidfile:
5012 5027 pid_file = optarg;
... ... @@ -5404,6 +5419,7 @@ int main(int argc, char **argv, char **envp)
5404 5419  
5405 5420 /* terminal init */
5406 5421 memset(&display_state, 0, sizeof(display_state));
  5422 + ds->surface = qemu_create_displaysurface(640, 480, 32, 640 * 4);
5407 5423 if (nographic) {
5408 5424 if (curses) {
5409 5425 fprintf(stderr, "fatal: -nographic can't be used with -curses\n");
... ... @@ -5411,26 +5427,30 @@ int main(int argc, char **argv, char **envp)
5411 5427 }
5412 5428 /* nearly nothing to do */
5413 5429 dumb_display_init(ds);
5414   - } else if (vnc_display != NULL) {
5415   - vnc_display_init(ds);
5416   - if (vnc_display_open(ds, vnc_display) < 0)
5417   - exit(1);
5418   - } else
  5430 + } else {
5419 5431 #if defined(CONFIG_CURSES)
5420   - if (curses) {
5421   - curses_display_init(ds, full_screen);
5422   - } else
  5432 + if (curses) {
  5433 + /* At the moment curses cannot be used with other displays */
  5434 + curses_display_init(ds, full_screen);
  5435 + } else
5423 5436 #endif
5424   - {
  5437 + {
  5438 + if (vnc_display != NULL) {
  5439 + vnc_display_init(ds);
  5440 + if (vnc_display_open(ds, vnc_display) < 0)
  5441 + exit(1);
  5442 + }
  5443 + if (sdl || !vnc_display)
5425 5444 #if defined(CONFIG_SDL)
5426   - sdl_display_init(ds, full_screen, no_frame);
  5445 + sdl_display_init(ds, full_screen, no_frame);
5427 5446 #elif defined(CONFIG_COCOA)
5428   - cocoa_display_init(ds, full_screen);
  5447 + cocoa_display_init(ds, full_screen);
5429 5448 #else
5430   - dumb_display_init(ds);
  5449 + dumb_display_init(ds);
5431 5450 #endif
  5451 + }
5432 5452 }
5433   -
  5453 + dpy_resize(ds);
5434 5454 #ifndef _WIN32
5435 5455 /* must be after terminal init, SDL library changes signal handlers */
5436 5456 termsig_setup();
... ... @@ -5541,11 +5561,14 @@ int main(int argc, char **argv, char **envp)
5541 5561 }
5542 5562 }
5543 5563  
5544   - if (display_state.dpy_refresh) {
5545   - display_state.gui_timer = qemu_new_timer(rt_clock, gui_update, &display_state);
5546   - qemu_mod_timer(display_state.gui_timer, qemu_get_clock(rt_clock));
  5564 + dcl = ds->listeners;
  5565 + while (dcl != NULL) {
  5566 + if (dcl->dpy_refresh != NULL) {
  5567 + display_state.gui_timer = qemu_new_timer(rt_clock, gui_update, &display_state);
  5568 + qemu_mod_timer(display_state.gui_timer, qemu_get_clock(rt_clock));
  5569 + }
  5570 + dcl = dcl->next;
5547 5571 }
5548   -
5549 5572 #ifdef CONFIG_GDBSTUB
5550 5573 if (use_gdbstub) {
5551 5574 /* XXX: use standard host:port notation and modify options
... ...
... ... @@ -180,6 +180,7 @@ struct VncState
180 180 };
181 181  
182 182 static VncState *vnc_state; /* needed for info vnc */
  183 +static DisplayChangeListener *dcl;
183 184  
184 185 void do_info_vnc(void)
185 186 {
... ... @@ -213,7 +214,7 @@ static void vnc_flush(VncState *vs);
213 214 static void vnc_update_client(void *opaque);
214 215 static void vnc_client_read(void *opaque);
215 216  
216   -static void vnc_colordepth(DisplayState *ds, int depth);
  217 +static void vnc_colordepth(DisplayState *ds);
217 218  
218 219 static inline void vnc_set_bit(uint32_t *d, int k)
219 220 {
... ... @@ -291,35 +292,30 @@ static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
291 292 vnc_write_s32(vs, encoding);
292 293 }
293 294  
294   -static void vnc_dpy_resize(DisplayState *ds, int w, int h)
  295 +static void vnc_dpy_resize(DisplayState *ds)
295 296 {
296 297 int size_changed;
297 298 VncState *vs = ds->opaque;
298 299  
299   - ds->data = qemu_realloc(ds->data, w * h * vs->depth);
300   - vs->old_data = qemu_realloc(vs->old_data, w * h * vs->depth);
  300 + vs->old_data = qemu_realloc(vs->old_data, ds_get_linesize(ds) * ds_get_height(ds));
301 301  
302   - if (ds->data == NULL || vs->old_data == NULL) {
  302 + if (vs->old_data == NULL) {
303 303 fprintf(stderr, "vnc: memory allocation failed\n");
304 304 exit(1);
305 305 }
306 306  
307   - if (ds->depth != vs->depth * 8) {
308   - ds->depth = vs->depth * 8;
  307 + if (ds_get_bytes_per_pixel(ds) != vs->depth)
309 308 console_color_init(ds);
310   - }
311   - size_changed = ds->width != w || ds->height != h;
312   - ds->width = w;
313   - ds->height = h;
314   - ds->linesize = w * vs->depth;
  309 + vnc_colordepth(ds);
  310 + size_changed = ds_get_width(ds) != vs->width || ds_get_height(ds) != vs->height;
315 311 if (size_changed) {
316   - vs->width = ds->width;
317   - vs->height = ds->height;
  312 + vs->width = ds_get_width(ds);
  313 + vs->height = ds_get_height(ds);
318 314 if (vs->csock != -1 && vs->has_resize) {
319 315 vnc_write_u8(vs, 0); /* msg id */
320 316 vnc_write_u8(vs, 0);
321 317 vnc_write_u16(vs, 1); /* number of rects */
322   - vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, -223);
  318 + vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds), -223);
323 319 vnc_flush(vs);
324 320 }
325 321 }
... ... @@ -494,36 +490,10 @@ static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
494 490  
495 491 static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
496 492 {
497   - int src, dst;
498   - uint8_t *src_row;
499   - uint8_t *dst_row;
500   - char *old_row;
501   - int y = 0;
502   - int pitch = ds_get_linesize(ds);
503 493 VncState *vs = ds->opaque;
504 494  
505 495 vnc_update_client(vs);
506 496  
507   - if (dst_y > src_y) {
508   - y = h - 1;
509   - pitch = -pitch;
510   - }
511   -
512   - src = (ds_get_linesize(ds) * (src_y + y) + vs->depth * src_x);
513   - dst = (ds_get_linesize(ds) * (dst_y + y) + vs->depth * dst_x);
514   -
515   - src_row = ds_get_data(ds) + src;
516   - dst_row = ds_get_data(ds) + dst;
517   - old_row = vs->old_data + dst;
518   -
519   - for (y = 0; y < h; y++) {
520   - memmove(old_row, src_row, w * vs->depth);
521   - memmove(dst_row, src_row, w * vs->depth);
522   - src_row += pitch;
523   - dst_row += pitch;
524   - old_row += pitch;
525   - }
526   -
527 497 vnc_write_u8(vs, 0); /* msg id */
528 498 vnc_write_u8(vs, 0);
529 499 vnc_write_u16(vs, 1); /* number of rects */
... ... @@ -770,7 +740,7 @@ static int vnc_client_io_error(VncState *vs, int ret, int last_errno)
770 740 qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
771 741 closesocket(vs->csock);
772 742 vs->csock = -1;
773   - vs->ds->idle = 1;
  743 + dcl->idle = 1;
774 744 buffer_reset(&vs->input);
775 745 buffer_reset(&vs->output);
776 746 vs->need_update = 0;
... ... @@ -1226,7 +1196,7 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
1226 1196 vs->has_pointer_type_change = 0;
1227 1197 vs->has_WMVi = 0;
1228 1198 vs->absolute = -1;
1229   - vs->ds->dpy_copy = NULL;
  1199 + dcl->dpy_copy = NULL;
1230 1200  
1231 1201 for (i = n_encodings - 1; i >= 0; i--) {
1232 1202 switch (encodings[i]) {
... ... @@ -1234,7 +1204,7 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
1234 1204 vs->has_hextile = 0;
1235 1205 break;
1236 1206 case 1: /* CopyRect */
1237   - vs->ds->dpy_copy = vnc_copy;
  1207 + dcl->dpy_copy = vnc_copy;
1238 1208 break;
1239 1209 case 5: /* Hextile */
1240 1210 vs->has_hextile = 1;
... ... @@ -1387,33 +1357,25 @@ static void pixel_format_message (VncState *vs) {
1387 1357 vnc_write(vs, pad, 3); /* padding */
1388 1358 }
1389 1359  
1390   -static void vnc_colordepth(DisplayState *ds, int depth)
  1360 +static void vnc_dpy_setdata(DisplayState *ds)
  1361 +{
  1362 + /* We don't have to do anything */
  1363 +}
  1364 +
  1365 +static void vnc_colordepth(DisplayState *ds)
1391 1366 {
1392 1367 int host_big_endian_flag;
1393 1368 struct VncState *vs = ds->opaque;
1394 1369  
1395   - switch (depth) {
1396   - case 24:
1397   - if (ds->depth == 32) return;
1398   - depth = 32;
1399   - break;
1400   - case 15:
1401   - case 8:
1402   - case 0:
1403   - return;
1404   - default:
1405   - break;
1406   - }
1407   -
1408 1370 #ifdef WORDS_BIGENDIAN
1409 1371 host_big_endian_flag = 1;
1410 1372 #else
1411 1373 host_big_endian_flag = 0;
1412 1374 #endif
1413 1375  
1414   - switch (depth) {
  1376 + switch (ds_get_bits_per_pixel(ds)) {
1415 1377 case 8:
1416   - vs->depth = depth / 8;
  1378 + vs->depth = 1;
1417 1379 vs->server_red_max = 7;
1418 1380 vs->server_green_max = 7;
1419 1381 vs->server_blue_max = 3;
... ... @@ -1422,7 +1384,7 @@ static void vnc_colordepth(DisplayState *ds, int depth)
1422 1384 vs->server_blue_shift = 0;
1423 1385 break;
1424 1386 case 16:
1425   - vs->depth = depth / 8;
  1387 + vs->depth = 2;
1426 1388 vs->server_red_max = 31;
1427 1389 vs->server_green_max = 63;
1428 1390 vs->server_blue_max = 31;
... ... @@ -1448,7 +1410,7 @@ static void vnc_colordepth(DisplayState *ds, int depth)
1448 1410 vnc_write_u8(vs, 0); /* msg id */
1449 1411 vnc_write_u8(vs, 0);
1450 1412 vnc_write_u16(vs, 1); /* number of rects */
1451   - vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, 0x574D5669);
  1413 + vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds), 0x574D5669);
1452 1414 pixel_format_message(vs);
1453 1415 vnc_flush(vs);
1454 1416 } else {
... ... @@ -2237,7 +2199,7 @@ static int protocol_version(VncState *vs, uint8_t *version, size_t len)
2237 2199 static void vnc_connect(VncState *vs)
2238 2200 {
2239 2201 VNC_DEBUG("New client on socket %d\n", vs->csock);
2240   - vs->ds->idle = 0;
  2202 + dcl->idle = 0;
2241 2203 socket_set_nonblock(vs->csock);
2242 2204 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
2243 2205 vnc_write(vs, "RFB 003.008\n", 12);
... ... @@ -2247,7 +2209,7 @@ static void vnc_connect(VncState *vs)
2247 2209 memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
2248 2210 vs->has_resize = 0;
2249 2211 vs->has_hextile = 0;
2250   - vs->ds->dpy_copy = NULL;
  2212 + dcl->dpy_copy = NULL;
2251 2213 vnc_update_client(vs);
2252 2214 reset_keys(vs);
2253 2215 }
... ... @@ -2272,11 +2234,12 @@ void vnc_display_init(DisplayState *ds)
2272 2234 VncState *vs;
2273 2235  
2274 2236 vs = qemu_mallocz(sizeof(VncState));
2275   - if (!vs)
  2237 + dcl = qemu_mallocz(sizeof(DisplayChangeListener));
  2238 + if (!vs || !dcl)
2276 2239 exit(1);
2277 2240  
2278 2241 ds->opaque = vs;
2279   - ds->idle = 1;
  2242 + dcl->idle = 1;
2280 2243 vnc_state = vs;
2281 2244 vs->display = NULL;
2282 2245 vs->password = NULL;
... ... @@ -2298,13 +2261,11 @@ void vnc_display_init(DisplayState *ds)
2298 2261  
2299 2262 vs->timer = qemu_new_timer(rt_clock, vnc_update_client, vs);
2300 2263  
2301   - vs->ds->data = NULL;
2302   - vs->ds->dpy_update = vnc_dpy_update;
2303   - vs->ds->dpy_resize = vnc_dpy_resize;
2304   - vs->ds->dpy_refresh = NULL;
2305   -
2306   - vnc_colordepth(vs->ds, 32);
2307   - vnc_dpy_resize(vs->ds, 640, 400);
  2264 + dcl->dpy_update = vnc_dpy_update;
  2265 + dcl->dpy_resize = vnc_dpy_resize;
  2266 + dcl->dpy_setdata = vnc_dpy_setdata;
  2267 + dcl->dpy_refresh = NULL;
  2268 + register_displaychangelistener(ds, dcl);
2308 2269  
2309 2270 vs->as.freq = 44100;
2310 2271 vs->as.nchannels = 2;
... ...