Commit 7b5d76dae31881d3cdb6f748ad4e84ddd7b66f3e

Authored by aliguori
1 parent 86dbdd40

DisplayAllocator interface (Stefano Stabellini)

Hi all,
this patch adds a DisplayAllocator interface that allows display
frontends (sdl in particular) to provide a preallocated display buffer
for the graphical backend to use.

Whenever a graphical backend cannot use
qemu_create_displaysurface_from because its own internal pixel format
cannot be exported directly (text mode or graphical mode with color
depth 8 or 24), it creates another display buffer in memory using
qemu_create_displaysurface and does the conversion.
This new buffer needs to be blitted into the sdl surface buffer every time
we need to update portions of the screen.
We can avoid this using the DisplayAllocator interace: sdl provides its
own implementation of qemu_create_displaysurface, giving back the sdl
surface buffer directly (as we used to do before the DisplayState
changes).
Since the buffer returned by sdl could be in bgr format we need to put
back in the handlers of that case.

This approach is good if the two following conditions are true:

1) the sdl surface is a software surface that resides in main memory;

2) the host display color depth is either 16 or 32 bpp.

If first condition is false we can have bad performances using sdl
and vnc together.
If the second condition is false performances are certainly not going to
improve but they shouldn't get worse either.

The first condition is always true, at least on linux/X11 systems; but I
believe is true also on other platforms.
The second condition is true in the vast majority of the cases.

This patch should also have the good side effect of solving the sdl
2D slowness malc was reporting on MacOS, because SDL_BlitSurface is not
going to be called anymore when the guest is in text mode or 24bpp.
However the root problem is still present so I suspect we may
still see some slowness on MacOS when the guest is in 32 or 16 bpp.

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@6839 c046a42c-6fe2-441c-8c8c-71466251a162
console.c
... ... @@ -1068,8 +1068,7 @@ void console_select(unsigned int index)
1068 1068 DisplayState *ds = s->ds;
1069 1069 active_console = s;
1070 1070 if (ds_get_bits_per_pixel(s->ds)) {
1071   - ds->surface = qemu_resize_displaysurface(ds->surface, s->g_width,
1072   - s->g_height, 32, 4 * s->g_width);
  1071 + ds->surface = qemu_resize_displaysurface(ds, s->g_width, s->g_height);
1073 1072 } else {
1074 1073 s->ds->surface->width = s->width;
1075 1074 s->ds->surface->height = s->height;
... ... @@ -1277,11 +1276,12 @@ DisplayState *graphic_console_init(vga_hw_update_ptr update,
1277 1276 DisplayState *ds;
1278 1277  
1279 1278 ds = (DisplayState *) qemu_mallocz(sizeof(DisplayState));
1280   - ds->surface = qemu_create_displaysurface(640, 480, 32, 640 * 4);
  1279 + ds->allocator = &default_allocator;
  1280 + ds->surface = qemu_create_displaysurface(ds, 640, 480);
1281 1281  
1282 1282 s = new_console(ds, GRAPHIC_CONSOLE);
1283 1283 if (s == NULL) {
1284   - qemu_free_displaysurface(ds->surface);
  1284 + qemu_free_displaysurface(ds);
1285 1285 qemu_free(ds);
1286 1286 return NULL;
1287 1287 }
... ... @@ -1429,7 +1429,7 @@ void qemu_console_resize(DisplayState *ds, int width, int height)
1429 1429 s->g_width = width;
1430 1430 s->g_height = height;
1431 1431 if (is_graphic_console()) {
1432   - ds->surface = qemu_resize_displaysurface(ds->surface, width, height, 32, 4 * width);
  1432 + ds->surface = qemu_resize_displaysurface(ds, width, height);
1433 1433 dpy_resize(ds);
1434 1434 }
1435 1435 }
... ... @@ -1552,14 +1552,14 @@ PixelFormat qemu_default_pixelformat(int bpp)
1552 1552 return pf;
1553 1553 }
1554 1554  
1555   -DisplaySurface* qemu_create_displaysurface(int width, int height, int bpp, int linesize)
  1555 +DisplaySurface* defaultallocator_create_displaysurface(int width, int height)
1556 1556 {
1557 1557 DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
1558 1558  
1559 1559 surface->width = width;
1560 1560 surface->height = height;
1561   - surface->linesize = linesize;
1562   - surface->pf = qemu_default_pixelformat(bpp);
  1561 + surface->linesize = width * 4;
  1562 + surface->pf = qemu_default_pixelformat(32);
1563 1563 #ifdef WORDS_BIGENDIAN
1564 1564 surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
1565 1565 #else
... ... @@ -1570,13 +1570,13 @@ DisplaySurface* qemu_create_displaysurface(int width, int height, int bpp, int l
1570 1570 return surface;
1571 1571 }
1572 1572  
1573   -DisplaySurface* qemu_resize_displaysurface(DisplaySurface *surface,
1574   - int width, int height, int bpp, int linesize)
  1573 +DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface,
  1574 + int width, int height)
1575 1575 {
1576 1576 surface->width = width;
1577 1577 surface->height = height;
1578   - surface->linesize = linesize;
1579   - surface->pf = qemu_default_pixelformat(bpp);
  1578 + surface->linesize = width * 4;
  1579 + surface->pf = qemu_default_pixelformat(32);
1580 1580 if (surface->flags & QEMU_ALLOCATED_FLAG)
1581 1581 surface->data = (uint8_t*) qemu_realloc(surface->data, surface->linesize * surface->height);
1582 1582 else
... ... @@ -1607,7 +1607,7 @@ DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
1607 1607 return surface;
1608 1608 }
1609 1609  
1610   -void qemu_free_displaysurface(DisplaySurface *surface)
  1610 +void defaultallocator_free_displaysurface(DisplaySurface *surface)
1611 1611 {
1612 1612 if (surface == NULL)
1613 1613 return;
... ...
console.h
... ... @@ -113,11 +113,18 @@ struct DisplayChangeListener {
113 113 struct DisplayChangeListener *next;
114 114 };
115 115  
  116 +struct DisplayAllocator {
  117 + DisplaySurface* (*create_displaysurface)(int width, int height);
  118 + DisplaySurface* (*resize_displaysurface)(DisplaySurface *surface, int width, int height);
  119 + void (*free_displaysurface)(DisplaySurface *surface);
  120 +};
  121 +
116 122 struct DisplayState {
117 123 struct DisplaySurface *surface;
118 124 void *opaque;
119 125 struct QEMUTimer *gui_timer;
120 126  
  127 + struct DisplayAllocator* allocator;
121 128 struct DisplayChangeListener* listeners;
122 129  
123 130 void (*mouse_set)(int x, int y, int on);
... ... @@ -129,15 +136,40 @@ struct DisplayState {
129 136  
130 137 void register_displaystate(DisplayState *ds);
131 138 DisplayState *get_displaystate(void);
132   -DisplaySurface* qemu_create_displaysurface(int width, int height, int bpp, int linesize);
133   -DisplaySurface* qemu_resize_displaysurface(DisplaySurface *surface,
134   - int width, int height, int bpp, int linesize);
135 139 DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
136 140 int linesize, uint8_t *data);
137   -void qemu_free_displaysurface(DisplaySurface *surface);
138 141 PixelFormat qemu_different_endianness_pixelformat(int bpp);
139 142 PixelFormat qemu_default_pixelformat(int bpp);
140 143  
  144 +extern struct DisplayAllocator default_allocator;
  145 +DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da);
  146 +DisplaySurface* defaultallocator_create_displaysurface(int width, int height);
  147 +DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface, int width, int height);
  148 +void defaultallocator_free_displaysurface(DisplaySurface *surface);
  149 +
  150 +static inline DisplaySurface* qemu_create_displaysurface(DisplayState *ds, int width, int height)
  151 +{
  152 + return ds->allocator->create_displaysurface(width, height);
  153 +}
  154 +
  155 +static inline DisplaySurface* qemu_resize_displaysurface(DisplayState *ds, int width, int height)
  156 +{
  157 + return ds->allocator->resize_displaysurface(ds->surface, width, height);
  158 +}
  159 +
  160 +static inline void qemu_free_displaysurface(DisplayState *ds)
  161 +{
  162 + ds->allocator->free_displaysurface(ds->surface);
  163 +}
  164 +
  165 +static inline int is_surface_bgr(DisplaySurface *surface)
  166 +{
  167 + if (surface->pf.bits_per_pixel == 32 && surface->pf.rshift == 0)
  168 + return 1;
  169 + else
  170 + return 0;
  171 +}
  172 +
141 173 static inline int is_buffer_shared(DisplaySurface *surface)
142 174 {
143 175 return (!(surface->flags & QEMU_ALLOCATED_FLAG));
... ...
curses.c
... ... @@ -364,7 +364,7 @@ void curses_display_init(DisplayState *ds, int full_screen)
364 364 dcl->dpy_refresh = curses_refresh;
365 365 dcl->dpy_text_cursor = curses_cursor_position;
366 366 register_displaychangelistener(ds, dcl);
367   - qemu_free_displaysurface(ds->surface);
  367 + qemu_free_displaysurface(ds);
368 368 ds->surface = qemu_create_displaysurface_from(640, 400, 0, 0, (uint8_t*) screen);
369 369  
370 370 invalidate = 1;
... ...
hw/musicpal.c
... ... @@ -831,7 +831,7 @@ static void lcd_refresh(void *opaque)
831 831 break;
832 832 LCD_REFRESH(8, rgb_to_pixel8)
833 833 LCD_REFRESH(16, rgb_to_pixel16)
834   - LCD_REFRESH(32, rgb_to_pixel32)
  834 + LCD_REFRESH(32, (is_surface_bgr(s->ds) ? rgb_to_pixel32bgr : rgb_to_pixel32))
835 835 default:
836 836 cpu_abort(cpu_single_env, "unsupported colour depth %i\n",
837 837 ds_get_bits_per_pixel(s->ds));
... ...
hw/nseries.c
... ... @@ -1362,7 +1362,7 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
1362 1362 will set the size once configured, so this just sets an initial
1363 1363 size until the guest activates the display. */
1364 1364 ds = get_displaystate();
1365   - ds->surface = qemu_resize_displaysurface(ds->surface, 800, 480, 32, 4 * 800);
  1365 + ds->surface = qemu_resize_displaysurface(ds, 800, 480);
1366 1366 dpy_resize(ds);
1367 1367 }
1368 1368  
... ...
hw/palm.c
... ... @@ -278,7 +278,7 @@ static void palmte_init(ram_addr_t ram_size, int vga_ram_size,
278 278 /* FIXME: We shouldn't really be doing this here. The LCD controller
279 279 will set the size once configured, so this just sets an initial
280 280 size until the guest activates the display. */
281   - ds->surface = qemu_resize_displaysurface(ds->surface, 320, 320, 32, 4 * 320);
  281 + ds->surface = qemu_resize_displaysurface(ds, 320, 320);
282 282 dpy_resize(ds);
283 283 }
284 284  
... ...
hw/sm501.c
... ... @@ -948,7 +948,10 @@ static inline int get_depth_index(DisplayState *s)
948 948 case 16:
949 949 return 2;
950 950 case 32:
951   - return 3;
  951 + if (is_surface_bgr(s->surface))
  952 + return 4;
  953 + else
  954 + return 3;
952 955 }
953 956 }
954 957  
... ...
hw/tcx.c
... ... @@ -66,7 +66,10 @@ static void update_palette_entries(TCXState *s, int start, int end)
66 66 s->palette[i] = rgb_to_pixel16(s->r[i], s->g[i], s->b[i]);
67 67 break;
68 68 case 32:
69   - s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
  69 + if (is_surface_bgr(s->ds->surface))
  70 + s->palette[i] = rgb_to_pixel32bgr(s->r[i], s->g[i], s->b[i]);
  71 + else
  72 + s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
70 73 break;
71 74 }
72 75 }
... ... @@ -124,11 +127,12 @@ static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
124 127 const uint32_t *cplane,
125 128 const uint32_t *s24)
126 129 {
127   - int x, r, g, b;
  130 + int x, bgr, r, g, b;
128 131 uint8_t val, *p8;
129 132 uint32_t *p = (uint32_t *)d;
130 133 uint32_t dval;
131 134  
  135 + bgr = is_surface_bgr(s1->ds->surface);
132 136 for(x = 0; x < width; x++, s++, s24++) {
133 137 if ((be32_to_cpu(*cplane++) & 0xff000000) == 0x03000000) {
134 138 // 24-bit direct, BGR order
... ... @@ -137,7 +141,10 @@ static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
137 141 b = *p8++;
138 142 g = *p8++;
139 143 r = *p8++;
140   - dval = rgb_to_pixel32(r, g, b);
  144 + if (bgr)
  145 + dval = rgb_to_pixel32bgr(r, g, b);
  146 + else
  147 + dval = rgb_to_pixel32(r, g, b);
141 148 } else {
142 149 val = *s;
143 150 dval = s1->palette[val];
... ...
hw/vga.c
... ... @@ -1161,7 +1161,10 @@ static inline int get_depth_index(DisplayState *s)
1161 1161 case 16:
1162 1162 return 2;
1163 1163 case 32:
1164   - return 3;
  1164 + if (is_surface_bgr(s->surface))
  1165 + return 4;
  1166 + else
  1167 + return 3;
1165 1168 }
1166 1169 }
1167 1170  
... ... @@ -1627,7 +1630,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
1627 1630 if (depth == 32) {
1628 1631 #endif
1629 1632 if (is_graphic_console()) {
1630   - qemu_free_displaysurface(s->ds->surface);
  1633 + qemu_free_displaysurface(s->ds);
1631 1634 s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
1632 1635 s->line_offset,
1633 1636 s->vram_ptr + (s->start_addr * 4));
... ... @@ -2619,7 +2622,7 @@ static void vga_screen_dump_common(VGAState *s, const char *filename,
2619 2622 dcl.dpy_resize = vga_save_dpy_resize;
2620 2623 dcl.dpy_refresh = vga_save_dpy_refresh;
2621 2624 register_displaychangelistener(ds, &dcl);
2622   - ds->surface = qemu_create_displaysurface(w, h, 32, 4 * w);
  2625 + ds->surface = qemu_create_displaysurface(ds, w, h);
2623 2626  
2624 2627 s->ds = ds;
2625 2628 s->graphic_mode = -1;
... ... @@ -2627,7 +2630,7 @@ static void vga_screen_dump_common(VGAState *s, const char *filename,
2627 2630  
2628 2631 ppm_save(filename, ds->surface);
2629 2632  
2630   - qemu_free_displaysurface(ds->surface);
  2633 + qemu_free_displaysurface(ds);
2631 2634 s->ds = saved_ds;
2632 2635 }
2633 2636  
... ...
qemu-common.h
... ... @@ -162,6 +162,7 @@ typedef struct BlockDriverState BlockDriverState;
162 162 typedef struct DisplayState DisplayState;
163 163 typedef struct DisplayChangeListener DisplayChangeListener;
164 164 typedef struct DisplaySurface DisplaySurface;
  165 +typedef struct DisplayAllocator DisplayAllocator;
165 166 typedef struct PixelFormat PixelFormat;
166 167 typedef struct TextConsole TextConsole;
167 168 typedef TextConsole QEMUConsole;
... ...
... ... @@ -53,17 +53,20 @@ static int absolute_enabled = 0;
53 53 static int guest_cursor = 0;
54 54 static int guest_x, guest_y;
55 55 static SDL_Cursor *guest_sprite = 0;
  56 +static uint8_t allocator;
  57 +static uint8_t hostbpp;
56 58  
57 59 static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
58 60 {
59   - SDL_Rect rec;
60   - rec.x = x;
61   - rec.y = y;
62   - rec.w = w;
63   - rec.h = h;
64 61 // printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
65   -
66   - SDL_BlitSurface(guest_screen, &rec, real_screen, &rec);
  62 + if (guest_screen) {
  63 + SDL_Rect rec;
  64 + rec.x = x;
  65 + rec.y = y;
  66 + rec.w = w;
  67 + rec.h = h;
  68 + SDL_BlitSurface(guest_screen, &rec, real_screen, &rec);
  69 + }
67 70 SDL_UpdateRect(real_screen, x, y, w, h);
68 71 }
69 72  
... ... @@ -83,7 +86,7 @@ static void sdl_setdata(DisplayState *ds)
83 86 ds->surface->pf.bmask, ds->surface->pf.amask);
84 87 }
85 88  
86   -static void sdl_resize(DisplayState *ds)
  89 +static void do_sdl_resize(int width, int height, int bpp)
87 90 {
88 91 int flags;
89 92  
... ... @@ -95,15 +98,101 @@ static void sdl_resize(DisplayState *ds)
95 98 if (gui_noframe)
96 99 flags |= SDL_NOFRAME;
97 100  
98   - width = ds_get_width(ds);
99   - height = ds_get_height(ds);
100   - real_screen = SDL_SetVideoMode(width, height, 0, flags);
  101 + real_screen = SDL_SetVideoMode(width, height, bpp, flags);
101 102 if (!real_screen) {
102 103 fprintf(stderr, "Could not open SDL display\n");
103 104 exit(1);
104 105 }
  106 +}
  107 +
  108 +static void sdl_resize(DisplayState *ds)
  109 +{
  110 + if (!allocator) {
  111 + do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0);
  112 + sdl_setdata(ds);
  113 + } else {
  114 + if (guest_screen != NULL) {
  115 + SDL_FreeSurface(guest_screen);
  116 + guest_screen = NULL;
  117 + }
  118 + }
  119 +}
  120 +
  121 +static PixelFormat sdl_to_qemu_pixelformat(SDL_PixelFormat *sdl_pf)
  122 +{
  123 + PixelFormat qemu_pf;
  124 +
  125 + memset(&qemu_pf, 0x00, sizeof(PixelFormat));
  126 +
  127 + qemu_pf.bits_per_pixel = sdl_pf->BitsPerPixel;
  128 + qemu_pf.bytes_per_pixel = sdl_pf->BytesPerPixel;
  129 + qemu_pf.depth = (qemu_pf.bits_per_pixel) == 32 ? 24 : (qemu_pf.bits_per_pixel);
  130 +
  131 + qemu_pf.rmask = sdl_pf->Rmask;
  132 + qemu_pf.gmask = sdl_pf->Gmask;
  133 + qemu_pf.bmask = sdl_pf->Bmask;
  134 + qemu_pf.amask = sdl_pf->Amask;
  135 +
  136 + qemu_pf.rshift = sdl_pf->Rshift;
  137 + qemu_pf.gshift = sdl_pf->Gshift;
  138 + qemu_pf.bshift = sdl_pf->Bshift;
  139 + qemu_pf.ashift = sdl_pf->Ashift;
  140 +
  141 + qemu_pf.rbits = 8 - sdl_pf->Rloss;
  142 + qemu_pf.gbits = 8 - sdl_pf->Gloss;
  143 + qemu_pf.bbits = 8 - sdl_pf->Bloss;
  144 + qemu_pf.abits = 8 - sdl_pf->Aloss;
  145 +
  146 + qemu_pf.rmax = ((1 << qemu_pf.rbits) - 1);
  147 + qemu_pf.gmax = ((1 << qemu_pf.gbits) - 1);
  148 + qemu_pf.bmax = ((1 << qemu_pf.bbits) - 1);
  149 + qemu_pf.amax = ((1 << qemu_pf.abits) - 1);
  150 +
  151 + return qemu_pf;
  152 +}
  153 +
  154 +static DisplaySurface* sdl_create_displaysurface(int width, int height)
  155 +{
  156 + DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
  157 + if (surface == NULL) {
  158 + fprintf(stderr, "sdl_create_displaysurface: malloc failed\n");
  159 + exit(1);
  160 + }
  161 +
  162 + surface->width = width;
  163 + surface->height = height;
105 164  
106   - sdl_setdata(ds);
  165 + if (hostbpp == 16)
  166 + do_sdl_resize(width, height, 16);
  167 + else
  168 + do_sdl_resize(width, height, 32);
  169 +
  170 + surface->pf = sdl_to_qemu_pixelformat(real_screen->format);
  171 + surface->linesize = real_screen->pitch;
  172 + surface->data = real_screen->pixels;
  173 +
  174 +#ifdef WORDS_BIGENDIAN
  175 + surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
  176 +#else
  177 + surface->flags = QEMU_ALLOCATED_FLAG;
  178 +#endif
  179 + allocator = 1;
  180 +
  181 + return surface;
  182 +}
  183 +
  184 +static void sdl_free_displaysurface(DisplaySurface *surface)
  185 +{
  186 + allocator = 0;
  187 + if (surface == NULL)
  188 + return;
  189 + qemu_free(surface);
  190 +}
  191 +
  192 +static DisplaySurface* sdl_resize_displaysurface(DisplaySurface *surface, int width, int height)
  193 +{
  194 + sdl_free_displaysurface(surface);
  195 + return sdl_create_displaysurface(width, height);
107 196 }
108 197  
109 198 /* generic keyboard conversion */
... ... @@ -391,7 +480,7 @@ static void sdl_send_mouse_event(int dx, int dy, int dz, int x, int y, int state
391 480 static void toggle_full_screen(DisplayState *ds)
392 481 {
393 482 gui_fullscreen = !gui_fullscreen;
394   - sdl_resize(ds);
  483 + do_sdl_resize(real_screen->w, real_screen->h, real_screen->format->BitsPerPixel);
395 484 if (gui_fullscreen) {
396 485 gui_saved_grab = gui_grab;
397 486 sdl_grab_start();
... ... @@ -669,6 +758,8 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
669 758 {
670 759 int flags;
671 760 uint8_t data = 0;
  761 + DisplayAllocator *da;
  762 + const SDL_VideoInfo *vi;
672 763  
673 764 #if defined(__APPLE__)
674 765 /* always use generic keymaps */
... ... @@ -689,6 +780,8 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
689 780 fprintf(stderr, "Could not initialize SDL - exiting\n");
690 781 exit(1);
691 782 }
  783 + vi = SDL_GetVideoInfo();
  784 + hostbpp = vi->vfmt->BitsPerPixel;
692 785  
693 786 dcl = qemu_mallocz(sizeof(DisplayChangeListener));
694 787 dcl->dpy_update = sdl_update;
... ... @@ -700,6 +793,18 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
700 793 ds->cursor_define = sdl_mouse_define;
701 794 register_displaychangelistener(ds, dcl);
702 795  
  796 + da = qemu_mallocz(sizeof(DisplayAllocator));
  797 + da->create_displaysurface = sdl_create_displaysurface;
  798 + da->resize_displaysurface = sdl_resize_displaysurface;
  799 + da->free_displaysurface = sdl_free_displaysurface;
  800 + if (register_displayallocator(ds, da) == da) {
  801 + DisplaySurface *surf;
  802 + surf = sdl_create_displaysurface(ds_get_width(ds), ds_get_height(ds));
  803 + defaultallocator_free_displaysurface(ds->surface);
  804 + ds->surface = surf;
  805 + dpy_resize(ds);
  806 + }
  807 +
703 808 sdl_update_caption();
704 809 SDL_EnableKeyRepeat(250, 50);
705 810 gui_grab = 0;
... ...
... ... @@ -2874,6 +2874,12 @@ void pcmcia_info(Monitor *mon)
2874 2874 /***********************************************************/
2875 2875 /* register display */
2876 2876  
  2877 +struct DisplayAllocator default_allocator = {
  2878 + defaultallocator_create_displaysurface,
  2879 + defaultallocator_resize_displaysurface,
  2880 + defaultallocator_free_displaysurface
  2881 +};
  2882 +
2877 2883 void register_displaystate(DisplayState *ds)
2878 2884 {
2879 2885 DisplayState **s;
... ... @@ -2889,12 +2895,19 @@ DisplayState *get_displaystate(void)
2889 2895 return display_state;
2890 2896 }
2891 2897  
  2898 +DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da)
  2899 +{
  2900 + if(ds->allocator == &default_allocator) ds->allocator = da;
  2901 + return ds->allocator;
  2902 +}
  2903 +
2892 2904 /* dumb display */
2893 2905  
2894 2906 static void dumb_display_init(void)
2895 2907 {
2896 2908 DisplayState *ds = qemu_mallocz(sizeof(DisplayState));
2897   - ds->surface = qemu_create_displaysurface(640, 480, 32, 640 * 4);
  2909 + ds->allocator = &default_allocator;
  2910 + ds->surface = qemu_create_displaysurface(ds, 640, 480);
2898 2911 register_displaystate(ds);
2899 2912 }
2900 2913  
... ...