diff options
Diffstat (limited to 'ui')
-rw-r--r-- | ui/cocoa.m | 57 | ||||
-rw-r--r-- | ui/console.c | 470 | ||||
-rw-r--r-- | ui/curses.c | 28 | ||||
-rw-r--r-- | ui/gtk.c | 160 | ||||
-rw-r--r-- | ui/sdl.c | 118 | ||||
-rw-r--r-- | ui/spice-display.c | 81 | ||||
-rw-r--r-- | ui/vnc-enc-tight.c | 7 | ||||
-rw-r--r-- | ui/vnc-jobs.c | 1 | ||||
-rw-r--r-- | ui/vnc.c | 143 | ||||
-rw-r--r-- | ui/vnc.h | 4 |
10 files changed, 597 insertions, 472 deletions
diff --git a/ui/cocoa.m b/ui/cocoa.m index ca42413b34..8e0eaa2601 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -264,8 +264,7 @@ static int cocoa_keycode_to_qemu(int keycode) BOOL isAbsoluteEnabled; BOOL isTabletEnabled; } -- (void) resizeContentToWidth:(int)w height:(int)h displayState:(DisplayState *)ds; -- (void) updateDataOffset:(DisplayState *)ds; +- (void) switchSurface:(DisplaySurface *)surface; - (void) grabMouse; - (void) ungrabMouse; - (void) toggleFullScreen:(id)sender; @@ -400,19 +399,19 @@ QemuCocoaView *cocoaView; } } -- (void) resizeContentToWidth:(int)w height:(int)h displayState:(DisplayState *)ds +- (void) switchSurface:(DisplaySurface *)surface { - COCOA_DEBUG("QemuCocoaView: resizeContent\n"); + COCOA_DEBUG("QemuCocoaView: switchSurface\n"); // update screenBuffer if (dataProviderRef) CGDataProviderRelease(dataProviderRef); //sync host window color space with guests - screen.bitsPerPixel = ds_get_bits_per_pixel(ds); - screen.bitsPerComponent = ds_get_bytes_per_pixel(ds) * 2; + screen.bitsPerPixel = surface_bits_per_pixel(surface); + screen.bitsPerComponent = surface_bytes_per_pixel(surface) * 2; - dataProviderRef = CGDataProviderCreateWithData(NULL, ds_get_data(ds), w * 4 * h, NULL); + dataProviderRef = CGDataProviderCreateWithData(NULL, surface_data(surface), w * 4 * h, NULL); // update windows if (isFullscreen) { @@ -430,20 +429,6 @@ QemuCocoaView *cocoaView; [self setFrame:NSMakeRect(cx, cy, cw, ch)]; } -- (void) updateDataOffset:(DisplayState *)ds -{ - COCOA_DEBUG("QemuCocoaView: UpdateDataOffset\n"); - - // update screenBuffer - if (dataProviderRef) { - CGDataProviderRelease(dataProviderRef); - } - - size_t size = ds_get_width(ds) * 4 * ds_get_height(ds); - dataProviderRef = CGDataProviderCreateWithData(NULL, ds_get_data(ds), - size, NULL); -} - - (void) toggleFullScreen:(id)sender { COCOA_DEBUG("QemuCocoaView: toggleFullScreen\n"); @@ -969,7 +954,8 @@ int main (int argc, const char * argv[]) { #pragma mark qemu -static void cocoa_update(DisplayState *ds, int x, int y, int w, int h) +static void cocoa_update(DisplayChangeListener *dcl, + int x, int y, int w, int h) { COCOA_DEBUG("qemu_cocoa: cocoa_update\n"); @@ -986,14 +972,15 @@ static void cocoa_update(DisplayState *ds, int x, int y, int w, int h) [cocoaView setNeedsDisplayInRect:rect]; } -static void cocoa_resize(DisplayState *ds) +static void cocoa_switch(DisplayChangeListener *dcl, + DisplaySurface *surface) { COCOA_DEBUG("qemu_cocoa: cocoa_resize\n"); - [cocoaView resizeContentToWidth:(int)(ds_get_width(ds)) height:(int)(ds_get_height(ds)) displayState:ds]; + [cocoaView switchSurface:surface]; } -static void cocoa_refresh(DisplayState *ds) +static void cocoa_refresh(DisplayChangeListener *dcl) { COCOA_DEBUG("qemu_cocoa: cocoa_refresh\n"); @@ -1019,17 +1006,19 @@ static void cocoa_refresh(DisplayState *ds) vga_hw_update(); } -static void cocoa_setdata(DisplayState *ds) -{ - [cocoaView updateDataOffset:ds]; -} - static void cocoa_cleanup(void) { COCOA_DEBUG("qemu_cocoa: cocoa_cleanup\n"); g_free(dcl); } +static const DisplayChangeListenerOps dcl_ops = { + .dpy_name = "cocoa", + .dpy_gfx_update = cocoa_update; + .dpy_gfx_switch = cocoa_switch; + .dpy_refresh = cocoa_refresh; +}; + void cocoa_display_init(DisplayState *ds, int full_screen) { COCOA_DEBUG("qemu_cocoa: cocoa_display_init\n"); @@ -1037,12 +1026,8 @@ void cocoa_display_init(DisplayState *ds, int full_screen) dcl = g_malloc0(sizeof(DisplayChangeListener)); // register vga output callbacks - dcl->dpy_gfx_update = cocoa_update; - dcl->dpy_gfx_resize = cocoa_resize; - dcl->dpy_refresh = cocoa_refresh; - dcl->dpy_gfx_setdata = cocoa_setdata; - - register_displaychangelistener(ds, dcl); + dcl->ops = &dcl_ops; + register_displaychangelistener(ds, dcl); // register cleanup function atexit(cocoa_cleanup); diff --git a/ui/console.c b/ui/console.c index 27e87f8879..eb7a2bc1bf 100644 --- a/ui/console.c +++ b/ui/console.c @@ -208,51 +208,17 @@ void vga_hw_text_update(console_ch_t *chardata) active_console->hw_text_update(active_console->hw, chardata); } -/* convert a RGBA color to a color index usable in graphic primitives */ -static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba) -{ - unsigned int r, g, b, color; - - switch(ds_get_bits_per_pixel(ds)) { -#if 0 - case 8: - r = (rgba >> 16) & 0xff; - g = (rgba >> 8) & 0xff; - b = (rgba) & 0xff; - color = (rgb_to_index[r] * 6 * 6) + - (rgb_to_index[g] * 6) + - (rgb_to_index[b]); - break; -#endif - case 15: - r = (rgba >> 16) & 0xff; - g = (rgba >> 8) & 0xff; - b = (rgba) & 0xff; - color = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3); - break; - case 16: - r = (rgba >> 16) & 0xff; - g = (rgba >> 8) & 0xff; - b = (rgba) & 0xff; - color = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); - break; - case 32: - default: - color = rgba; - break; - } - return color; -} - -static void vga_fill_rect (DisplayState *ds, - int posx, int posy, int width, int height, uint32_t color) +static void vga_fill_rect(QemuConsole *con, + int posx, int posy, int width, int height, + uint32_t color) { + DisplaySurface *surface = qemu_console_surface(con); uint8_t *d, *d1; int x, y, bpp; - bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3; - d1 = ds_get_data(ds) + - ds_get_linesize(ds) * posy + bpp * posx; + bpp = surface_bytes_per_pixel(surface); + d1 = surface_data(surface) + + surface_stride(surface) * posy + bpp * posx; for (y = 0; y < height; y++) { d = d1; switch(bpp) { @@ -275,38 +241,40 @@ static void vga_fill_rect (DisplayState *ds, } break; } - d1 += ds_get_linesize(ds); + d1 += surface_stride(surface); } } /* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */ -static void vga_bitblt(DisplayState *ds, int xs, int ys, int xd, int yd, int w, int h) +static void vga_bitblt(QemuConsole *con, + int xs, int ys, int xd, int yd, int w, int h) { + DisplaySurface *surface = qemu_console_surface(con); const uint8_t *s; uint8_t *d; int wb, y, bpp; - bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3; + bpp = surface_bytes_per_pixel(surface); wb = w * bpp; if (yd <= ys) { - s = ds_get_data(ds) + - ds_get_linesize(ds) * ys + bpp * xs; - d = ds_get_data(ds) + - ds_get_linesize(ds) * yd + bpp * xd; + s = surface_data(surface) + + surface_stride(surface) * ys + bpp * xs; + d = surface_data(surface) + + surface_stride(surface) * yd + bpp * xd; for (y = 0; y < h; y++) { memmove(d, s, wb); - d += ds_get_linesize(ds); - s += ds_get_linesize(ds); + d += surface_stride(surface); + s += surface_stride(surface); } } else { - s = ds_get_data(ds) + - ds_get_linesize(ds) * (ys + h - 1) + bpp * xs; - d = ds_get_data(ds) + - ds_get_linesize(ds) * (yd + h - 1) + bpp * xd; + s = surface_data(surface) + + surface_stride(surface) * (ys + h - 1) + bpp * xs; + d = surface_data(surface) + + surface_stride(surface) * (yd + h - 1) + bpp * xd; for (y = 0; y < h; y++) { memmove(d, s, wb); - d -= ds_get_linesize(ds); - s -= ds_get_linesize(ds); + d -= surface_stride(surface); + s -= surface_stride(surface); } } } @@ -358,8 +326,6 @@ static const uint32_t dmask4[4] = { PAT(0xffffffff), }; -static uint32_t color_table[2][8]; - #ifndef CONFIG_CURSES enum color_names { COLOR_BLACK = 0, @@ -396,23 +362,6 @@ static const uint32_t color_table_rgb[2][8] = { } }; -static inline unsigned int col_expand(DisplayState *ds, unsigned int col) -{ - switch(ds_get_bits_per_pixel(ds)) { - case 8: - col |= col << 8; - col |= col << 16; - break; - case 15: - case 16: - col |= col << 16; - break; - default: - break; - } - - return col; -} #ifdef DEBUG_CONSOLE static void console_print_text_attributes(TextAttributes *t_attrib, char ch) { @@ -446,9 +395,10 @@ static void console_print_text_attributes(TextAttributes *t_attrib, char ch) } #endif -static void vga_putcharxy(DisplayState *ds, int x, int y, int ch, +static void vga_putcharxy(QemuConsole *s, int x, int y, int ch, TextAttributes *t_attrib) { + DisplaySurface *surface = qemu_console_surface(s); uint8_t *d; const uint8_t *font_ptr; unsigned int font_data, linesize, xorcol, bpp; @@ -461,20 +411,20 @@ static void vga_putcharxy(DisplayState *ds, int x, int y, int ch, #endif if (t_attrib->invers) { - bgcol = color_table[t_attrib->bold][t_attrib->fgcol]; - fgcol = color_table[t_attrib->bold][t_attrib->bgcol]; + bgcol = color_table_rgb[t_attrib->bold][t_attrib->fgcol]; + fgcol = color_table_rgb[t_attrib->bold][t_attrib->bgcol]; } else { - fgcol = color_table[t_attrib->bold][t_attrib->fgcol]; - bgcol = color_table[t_attrib->bold][t_attrib->bgcol]; + fgcol = color_table_rgb[t_attrib->bold][t_attrib->fgcol]; + bgcol = color_table_rgb[t_attrib->bold][t_attrib->bgcol]; } - bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3; - d = ds_get_data(ds) + - ds_get_linesize(ds) * y * FONT_HEIGHT + bpp * x * FONT_WIDTH; - linesize = ds_get_linesize(ds); + bpp = surface_bytes_per_pixel(surface); + d = surface_data(surface) + + surface_stride(surface) * y * FONT_HEIGHT + bpp * x * FONT_WIDTH; + linesize = surface_stride(surface); font_ptr = vgafont16 + FONT_HEIGHT * ch; xorcol = bgcol ^ fgcol; - switch(ds_get_bits_per_pixel(ds)) { + switch (surface_bits_per_pixel(surface)) { case 8: for(i = 0; i < FONT_HEIGHT; i++) { font_data = *font_ptr++; @@ -579,19 +529,22 @@ static void update_xy(QemuConsole *s, int x, int y) TextCell *c; int y1, y2; - if (s == active_console) { - if (!ds_get_bits_per_pixel(s->ds)) { - text_update_xy(s, x, y); - return; - } + if (s != active_console) { + return; + } + if (s->ds->have_text) { + text_update_xy(s, x, y); + } + + if (s->ds->have_gfx) { y1 = (s->y_base + y) % s->total_height; y2 = y1 - s->y_displayed; if (y2 < 0) y2 += s->total_height; if (y2 < s->height) { c = &s->cells[y1 * s->width + x]; - vga_putcharxy(s->ds, x, y2, c->ch, + vga_putcharxy(s, x, y2, c->ch, &(c->t_attrib)); invalidate_xy(s, x, y2); } @@ -602,15 +555,17 @@ static void console_show_cursor(QemuConsole *s, int show) { TextCell *c; int y, y1; + int x = s->x; - if (s == active_console) { - int x = s->x; + if (s != active_console) { + return; + } - if (!ds_get_bits_per_pixel(s->ds)) { - s->cursor_invalidate = 1; - return; - } + if (s->ds->have_text) { + s->cursor_invalidate = 1; + } + if (s->ds->have_gfx) { if (x >= s->width) { x = s->width - 1; } @@ -623,9 +578,9 @@ static void console_show_cursor(QemuConsole *s, int show) if (show && s->cursor_visible_phase) { TextAttributes t_attrib = s->t_attrib_default; t_attrib.invers = !(t_attrib.invers); /* invert fg and bg */ - vga_putcharxy(s->ds, x, y, c->ch, &t_attrib); + vga_putcharxy(s, x, y, c->ch, &t_attrib); } else { - vga_putcharxy(s->ds, x, y, c->ch, &(c->t_attrib)); + vga_putcharxy(s, x, y, c->ch, &(c->t_attrib)); } invalidate_xy(s, x, y); } @@ -634,6 +589,7 @@ static void console_show_cursor(QemuConsole *s, int show) static void console_refresh(QemuConsole *s) { + DisplaySurface *surface = qemu_console_surface(s); TextCell *c; int x, y, y1; @@ -649,13 +605,13 @@ static void console_refresh(QemuConsole *s) } if (s->ds->have_gfx) { - vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds), - color_table[0][COLOR_BLACK]); + vga_fill_rect(s, 0, 0, surface_width(surface), surface_height(surface), + color_table_rgb[0][COLOR_BLACK]); y1 = s->y_displayed; for (y = 0; y < s->height; y++) { c = s->cells + y1 * s->width; for (x = 0; x < s->width; x++) { - vga_putcharxy(s->ds, x, y, c->ch, + vga_putcharxy(s, x, y, c->ch, &(c->t_attrib)); c++; } @@ -664,7 +620,8 @@ static void console_refresh(QemuConsole *s) } } console_show_cursor(s, 1); - dpy_gfx_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds)); + dpy_gfx_update(s, 0, 0, + surface_width(surface), surface_height(surface)); } } @@ -727,24 +684,25 @@ static void console_put_lf(QemuConsole *s) c++; } if (s == active_console && s->y_displayed == s->y_base) { - if (!ds_get_bits_per_pixel(s->ds)) { + if (s->ds->have_text) { s->text_x[0] = 0; s->text_y[0] = 0; s->text_x[1] = s->width - 1; s->text_y[1] = s->height - 1; - return; } - vga_bitblt(s->ds, 0, FONT_HEIGHT, 0, 0, - s->width * FONT_WIDTH, - (s->height - 1) * FONT_HEIGHT); - vga_fill_rect(s->ds, 0, (s->height - 1) * FONT_HEIGHT, - s->width * FONT_WIDTH, FONT_HEIGHT, - color_table[0][s->t_attrib_default.bgcol]); - s->update_x0 = 0; - s->update_y0 = 0; - s->update_x1 = s->width * FONT_WIDTH; - s->update_y1 = s->height * FONT_HEIGHT; + if (s->ds->have_gfx) { + vga_bitblt(s, 0, FONT_HEIGHT, 0, 0, + s->width * FONT_WIDTH, + (s->height - 1) * FONT_HEIGHT); + vga_fill_rect(s, 0, (s->height - 1) * FONT_HEIGHT, + s->width * FONT_WIDTH, FONT_HEIGHT, + color_table_rgb[0][s->t_attrib_default.bgcol]); + s->update_x0 = 0; + s->update_y0 = 0; + s->update_x1 = s->width * FONT_WIDTH; + s->update_y1 = s->height * FONT_HEIGHT; + } } } } @@ -1082,13 +1040,15 @@ static void console_putchar(QemuConsole *s, int ch) void console_select(unsigned int index) { + DisplaySurface *surface; QemuConsole *s; if (index >= MAX_CONSOLES) return; if (active_console) { - active_console->g_width = ds_get_width(active_console->ds); - active_console->g_height = ds_get_height(active_console->ds); + surface = qemu_console_surface(active_console); + active_console->g_width = surface_width(surface); + active_console->g_height = surface_height(surface); } s = consoles[index]; if (s) { @@ -1099,11 +1059,11 @@ void console_select(unsigned int index) } active_console = s; if (ds->have_gfx) { - ds->surface = qemu_resize_displaysurface(ds, s->g_width, s->g_height); - dpy_gfx_resize(ds); + surface = qemu_create_displaysurface(s->g_width, s->g_height); + dpy_gfx_replace_surface(s, surface); } if (ds->have_text) { - dpy_text_resize(ds, s->width, s->height); + dpy_text_resize(s, s->width, s->height); } if (s->cursor_timer) { qemu_mod_timer(s->cursor_timer, @@ -1128,7 +1088,7 @@ static int console_puts(CharDriverState *chr, const uint8_t *buf, int len) } console_show_cursor(s, 1); if (s->ds->have_gfx && s->update_x0 < s->update_x1) { - dpy_gfx_update(s->ds, s->update_x0, s->update_y0, + dpy_gfx_update(s, s->update_x0, s->update_y0, s->update_x1 - s->update_x0, s->update_y1 - s->update_y0); } @@ -1216,9 +1176,11 @@ void kbd_put_keysym(int keysym) static void text_console_invalidate(void *opaque) { QemuConsole *s = (QemuConsole *) opaque; - if (!ds_get_bits_per_pixel(s->ds) && s->console_type == TEXT_CONSOLE) { - s->g_width = ds_get_width(s->ds); - s->g_height = ds_get_height(s->ds); + DisplaySurface *surface = qemu_console_surface(s); + + if (s->ds->have_text && s->console_type == TEXT_CONSOLE) { + s->g_width = surface_width(surface); + s->g_height = surface_height(surface); text_console_resize(s); } console_refresh(s); @@ -1238,7 +1200,7 @@ static void text_console_update(void *opaque, console_ch_t *chardata) (s->cells[src].t_attrib.fgcol << 12) | (s->cells[src].t_attrib.bgcol << 8) | (s->cells[src].t_attrib.bold << 21)); - dpy_text_update(s->ds, s->text_x[0], s->text_y[0], + dpy_text_update(s, s->text_x[0], s->text_y[0], s->text_x[1] - s->text_x[0], i - s->text_y[0]); s->text_x[0] = s->width; s->text_y[0] = s->height; @@ -1246,23 +1208,11 @@ static void text_console_update(void *opaque, console_ch_t *chardata) s->text_y[1] = 0; } if (s->cursor_invalidate) { - dpy_text_cursor(s->ds, s->x, s->y); + dpy_text_cursor(s, s->x, s->y); s->cursor_invalidate = 0; } } -static QemuConsole *get_graphic_console(DisplayState *ds) -{ - int i; - QemuConsole *s; - for (i = 0; i < nb_consoles; i++) { - s = consoles[i]; - if (s->console_type == GRAPHIC_CONSOLE && s->ds == ds) - return s; - } - return NULL; -} - static QemuConsole *new_console(DisplayState *ds, console_type_t console_type) { QemuConsole *s; @@ -1316,34 +1266,24 @@ static void qemu_alloc_display(DisplaySurface *surface, int width, int height, #endif } -DisplaySurface *qemu_create_displaysurface(DisplayState *ds, - int width, int height) +DisplaySurface *qemu_create_displaysurface(int width, int height) { DisplaySurface *surface = g_new0(DisplaySurface, 1); - int linesize = width * 4; + + trace_displaysurface_create(surface, width, height); qemu_alloc_display(surface, width, height, linesize, qemu_default_pixelformat(32), 0); return surface; } -DisplaySurface *qemu_resize_displaysurface(DisplayState *ds, - int width, int height) -{ - int linesize = width * 4; - - trace_displaysurface_resize(ds, ds->surface, width, height); - qemu_alloc_display(ds->surface, width, height, linesize, - qemu_default_pixelformat(32), 0); - return ds->surface; -} - DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp, int linesize, uint8_t *data, bool byteswap) { DisplaySurface *surface = g_new0(DisplaySurface, 1); + trace_displaysurface_create_from(surface, width, height, bpp, byteswap); if (byteswap) { surface->pf = qemu_different_endianness_pixelformat(bpp); } else { @@ -1364,14 +1304,162 @@ DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp, return surface; } -void qemu_free_displaysurface(DisplayState *ds) +void qemu_free_displaysurface(DisplaySurface *surface) { - trace_displaysurface_free(ds, ds->surface); - if (ds->surface == NULL) { + if (surface == NULL) { return; } - qemu_pixman_image_unref(ds->surface->image); - g_free(ds->surface); + trace_displaysurface_free(surface); + qemu_pixman_image_unref(surface->image); + g_free(surface); +} + +void register_displaychangelistener(DisplayState *ds, + DisplayChangeListener *dcl) +{ + trace_displaychangelistener_register(dcl, dcl->ops->dpy_name); + dcl->ds = ds; + QLIST_INSERT_HEAD(&ds->listeners, dcl, next); + gui_setup_refresh(ds); + if (dcl->ops->dpy_gfx_switch) { + dcl->ops->dpy_gfx_switch(dcl, ds->surface); + } +} + +void unregister_displaychangelistener(DisplayChangeListener *dcl) +{ + DisplayState *ds = dcl->ds; + trace_displaychangelistener_unregister(dcl, dcl->ops->dpy_name); + QLIST_REMOVE(dcl, next); + gui_setup_refresh(ds); +} + +void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h) +{ + DisplayState *s = con->ds; + struct DisplayChangeListener *dcl; + int width = pixman_image_get_width(s->surface->image); + int height = pixman_image_get_height(s->surface->image); + + x = MAX(x, 0); + y = MAX(y, 0); + x = MIN(x, width); + y = MIN(y, height); + w = MIN(w, width - x); + h = MIN(h, height - y); + + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_gfx_update) { + dcl->ops->dpy_gfx_update(dcl, x, y, w, h); + } + } +} + +void dpy_gfx_replace_surface(QemuConsole *con, + DisplaySurface *surface) +{ + DisplayState *s = con->ds; + DisplaySurface *old_surface = s->surface; + struct DisplayChangeListener *dcl; + + s->surface = surface; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_gfx_switch) { + dcl->ops->dpy_gfx_switch(dcl, surface); + } + } + qemu_free_displaysurface(old_surface); +} + +void dpy_refresh(DisplayState *s) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_refresh) { + dcl->ops->dpy_refresh(dcl); + } + } +} + +void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y, + int dst_x, int dst_y, int w, int h) +{ + DisplayState *s = con->ds; + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_gfx_copy) { + dcl->ops->dpy_gfx_copy(dcl, src_x, src_y, dst_x, dst_y, w, h); + } else { /* TODO */ + dcl->ops->dpy_gfx_update(dcl, dst_x, dst_y, w, h); + } + } +} + +void dpy_text_cursor(QemuConsole *con, int x, int y) +{ + DisplayState *s = con->ds; + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_text_cursor) { + dcl->ops->dpy_text_cursor(dcl, x, y); + } + } +} + +void dpy_text_update(QemuConsole *con, int x, int y, int w, int h) +{ + DisplayState *s = con->ds; + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_text_update) { + dcl->ops->dpy_text_update(dcl, x, y, w, h); + } + } +} + +void dpy_text_resize(QemuConsole *con, int w, int h) +{ + DisplayState *s = con->ds; + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_text_resize) { + dcl->ops->dpy_text_resize(dcl, w, h); + } + } +} + +void dpy_mouse_set(QemuConsole *con, int x, int y, int on) +{ + DisplayState *s = con->ds; + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_mouse_set) { + dcl->ops->dpy_mouse_set(dcl, x, y, on); + } + } +} + +void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor) +{ + DisplayState *s = con->ds; + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_cursor_define) { + dcl->ops->dpy_cursor_define(dcl, cursor); + } + } +} + +bool dpy_cursor_define_supported(QemuConsole *con) +{ + DisplayState *s = con->ds; + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_cursor_define) { + return true; + } + } + return false; } static void dumb_display_init(void) @@ -1384,7 +1472,8 @@ static void dumb_display_init(void) width = active_console->g_width; height = active_console->g_height; } - ds->surface = qemu_create_displaysurface(ds, width, height); + ds->surface = qemu_create_displaysurface(width, height); + register_displaystate(ds); } @@ -1409,32 +1498,27 @@ DisplayState *get_displaystate(void) return display_state; } -DisplayState *graphic_console_init(vga_hw_update_ptr update, - vga_hw_invalidate_ptr invalidate, - vga_hw_screen_dump_ptr screen_dump, - vga_hw_text_update_ptr text_update, - void *opaque) +QemuConsole *graphic_console_init(vga_hw_update_ptr update, + vga_hw_invalidate_ptr invalidate, + vga_hw_screen_dump_ptr screen_dump, + vga_hw_text_update_ptr text_update, + void *opaque) { QemuConsole *s; DisplayState *ds; ds = (DisplayState *) g_malloc0(sizeof(DisplayState)); - ds->surface = qemu_create_displaysurface(ds, 640, 480); - s = new_console(ds, GRAPHIC_CONSOLE); - if (s == NULL) { - qemu_free_displaysurface(ds); - g_free(ds); - return NULL; - } s->hw_update = update; s->hw_invalidate = invalidate; s->hw_screen_dump = screen_dump; s->hw_text_update = text_update; s->hw = opaque; + ds->surface = qemu_create_displaysurface(640, 480); + register_displaystate(ds); - return ds; + return s; } int is_graphic_console(void) @@ -1447,17 +1531,6 @@ int is_fixedsize_console(void) return active_console && active_console->console_type != TEXT_CONSOLE; } -void console_color_init(DisplayState *ds) -{ - int i, j; - for (j = 0; j < 2; j++) { - for (i = 0; i < 8; i++) { - color_table[j][i] = col_expand(ds, - vga_get_color(ds, color_table_rgb[j][i])); - } - } -} - static void text_console_set_echo(CharDriverState *chr, bool echo) { QemuConsole *s = chr->opaque; @@ -1478,7 +1551,6 @@ static void text_console_update_cursor(void *opaque) static void text_console_do_init(CharDriverState *chr, DisplayState *ds) { QemuConsole *s; - static int color_inited; s = chr->opaque; @@ -1489,18 +1561,14 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds) s->kbd_timer = qemu_new_timer_ms(rt_clock, kbd_send_chars, s); s->ds = ds; - if (!color_inited) { - color_inited = 1; - console_color_init(s->ds); - } s->y_displayed = 0; s->y_base = 0; s->total_height = DEFAULT_BACKSCROLL; s->x = 0; s->y = 0; if (s->console_type == TEXT_CONSOLE) { - s->g_width = ds_get_width(s->ds); - s->g_height = ds_get_height(s->ds); + s->g_width = surface_width(s->ds->surface); + s->g_height = surface_height(s->ds->surface); } s->cursor_timer = @@ -1600,27 +1668,35 @@ void text_consoles_set_display(DisplayState *ds) } } -void qemu_console_resize(DisplayState *ds, int width, int height) +void qemu_console_resize(QemuConsole *s, int width, int height) { - QemuConsole *s = get_graphic_console(ds); - if (!s) return; - s->g_width = width; s->g_height = height; if (is_graphic_console()) { - ds->surface = qemu_resize_displaysurface(ds, width, height); - dpy_gfx_resize(ds); + DisplaySurface *surface; + surface = qemu_create_displaysurface(width, height); + dpy_gfx_replace_surface(s, surface); } } -void qemu_console_copy(DisplayState *ds, int src_x, int src_y, +void qemu_console_copy(QemuConsole *con, int src_x, int src_y, int dst_x, int dst_y, int w, int h) { if (is_graphic_console()) { - dpy_gfx_copy(ds, src_x, src_y, dst_x, dst_y, w, h); + dpy_gfx_copy(con, src_x, src_y, dst_x, dst_y, w, h); } } +DisplaySurface *qemu_console_surface(QemuConsole *console) +{ + return console->ds->surface; +} + +DisplayState *qemu_console_displaystate(QemuConsole *console) +{ + return console->ds; +} + PixelFormat qemu_different_endianness_pixelformat(int bpp) { PixelFormat pf; diff --git a/ui/curses.c b/ui/curses.c index d78e378440..ff82307361 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -35,12 +35,14 @@ #define FONT_HEIGHT 16 #define FONT_WIDTH 8 +static DisplayChangeListener *dcl; static console_ch_t screen[160 * 100]; static WINDOW *screenpad = NULL; static int width, height, gwidth, gheight, invalidate; static int px, py, sminx, sminy, smaxx, smaxy; -static void curses_update(DisplayState *ds, int x, int y, int w, int h) +static void curses_update(DisplayChangeListener *dcl, + int x, int y, int w, int h) { chtype *line; @@ -91,7 +93,8 @@ static void curses_calc_pad(void) } } -static void curses_resize(DisplayState *ds, int width, int height) +static void curses_resize(DisplayChangeListener *dcl, + int width, int height) { if (width == gwidth && height == gheight) { return; @@ -128,7 +131,8 @@ static void curses_winch_handler(int signum) #endif #endif -static void curses_cursor_position(DisplayState *ds, int x, int y) +static void curses_cursor_position(DisplayChangeListener *dcl, + int x, int y) { if (x >= 0) { x = sminx + x - px; @@ -154,7 +158,7 @@ static void curses_cursor_position(DisplayState *ds, int x, int y) static kbd_layout_t *kbd_layout = NULL; -static void curses_refresh(DisplayState *ds) +static void curses_refresh(DisplayChangeListener *dcl) { int chr, nextchr, keysym, keycode, keycode_alt; @@ -187,7 +191,7 @@ static void curses_refresh(DisplayState *ds) clear(); refresh(); curses_calc_pad(); - curses_update(ds, 0, 0, width, height); + curses_update(dcl, 0, 0, width, height); continue; } #endif @@ -323,9 +327,16 @@ static void curses_keyboard_setup(void) } } +static const DisplayChangeListenerOps dcl_ops = { + .dpy_name = "curses", + .dpy_text_update = curses_update, + .dpy_text_resize = curses_resize, + .dpy_refresh = curses_refresh, + .dpy_text_cursor = curses_cursor_position, +}; + void curses_display_init(DisplayState *ds, int full_screen) { - DisplayChangeListener *dcl; #ifndef _WIN32 if (!isatty(1)) { fprintf(stderr, "We need a terminal output\n"); @@ -346,10 +357,7 @@ void curses_display_init(DisplayState *ds, int full_screen) #endif dcl = (DisplayChangeListener *) g_malloc0(sizeof(DisplayChangeListener)); - dcl->dpy_text_update = curses_update; - dcl->dpy_text_resize = curses_resize; - dcl->dpy_refresh = curses_refresh; - dcl->dpy_text_cursor = curses_cursor_position; + dcl->ops = &dcl_ops; register_displaychangelistener(ds, dcl); invalidate = 1; @@ -143,7 +143,7 @@ typedef struct GtkDisplayState GtkWidget *drawing_area; cairo_surface_t *surface; DisplayChangeListener dcl; - DisplayState *ds; + DisplaySurface *ds; int button_mask; int last_x; int last_y; @@ -225,11 +225,50 @@ static void gd_update_caption(GtkDisplayState *s) g_free(title); } +static void gd_update_windowsize(GtkDisplayState *s) +{ + if (!s->full_screen) { + GtkRequisition req; + double sx, sy; + + if (s->free_scale) { + sx = s->scale_x; + sy = s->scale_y; + + s->scale_y = 1.0; + s->scale_x = 1.0; + } else { + sx = 1.0; + sy = 1.0; + } + + gtk_widget_set_size_request(s->drawing_area, + surface_width(s->ds) * s->scale_x, + surface_height(s->ds) * s->scale_y); +#if GTK_CHECK_VERSION(3, 0, 0) + gtk_widget_get_preferred_size(s->vbox, NULL, &req); +#else + gtk_widget_size_request(s->vbox, &req); +#endif + + gtk_window_resize(GTK_WINDOW(s->window), + req.width * sx, req.height * sy); + } +} + +static void gd_update_full_redraw(GtkDisplayState *s) +{ + int ww, wh; + gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh); + gtk_widget_queue_draw_area(s->drawing_area, 0, 0, ww, wh); +} + /** DisplayState Callbacks **/ -static void gd_update(DisplayState *ds, int x, int y, int w, int h) +static void gd_update(DisplayChangeListener *dcl, + int x, int y, int w, int h) { - GtkDisplayState *s = ds->opaque; + GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl); int x1, x2, y1, y2; int mx, my; int fbw, fbh; @@ -243,8 +282,8 @@ static void gd_update(DisplayState *ds, int x, int y, int w, int h) x2 = ceil(x * s->scale_x + w * s->scale_x); y2 = ceil(y * s->scale_y + h * s->scale_y); - fbw = ds_get_width(s->ds) * s->scale_x; - fbh = ds_get_height(s->ds) * s->scale_y; + fbw = surface_width(s->ds) * s->scale_x; + fbh = surface_height(s->ds) * s->scale_y; gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh); @@ -259,25 +298,33 @@ static void gd_update(DisplayState *ds, int x, int y, int w, int h) gtk_widget_queue_draw_area(s->drawing_area, mx + x1, my + y1, (x2 - x1), (y2 - y1)); } -static void gd_refresh(DisplayState *ds) +static void gd_refresh(DisplayChangeListener *dcl) { vga_hw_update(); } -static void gd_resize(DisplayState *ds) +static void gd_switch(DisplayChangeListener *dcl, + DisplaySurface *surface) { - GtkDisplayState *s = ds->opaque; + GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl); cairo_format_t kind; + bool resized = true; int stride; DPRINTF("resize(width=%d, height=%d)\n", - ds_get_width(ds), ds_get_height(ds)); + surface_width(surface), surface_height(surface)); if (s->surface) { cairo_surface_destroy(s->surface); } - switch (ds->surface->pf.bits_per_pixel) { + if (s->ds && + surface_width(s->ds) == surface_width(surface) && + surface_height(s->ds) == surface_height(surface)) { + resized = false; + } + s->ds = surface; + switch (surface_bits_per_pixel(surface)) { case 8: kind = CAIRO_FORMAT_A8; break; @@ -292,41 +339,19 @@ static void gd_resize(DisplayState *ds) break; } - stride = cairo_format_stride_for_width(kind, ds_get_width(ds)); - g_assert(ds_get_linesize(ds) == stride); + stride = cairo_format_stride_for_width(kind, surface_width(surface)); + g_assert(surface_stride(surface) == stride); - s->surface = cairo_image_surface_create_for_data(ds_get_data(ds), + s->surface = cairo_image_surface_create_for_data(surface_data(surface), kind, - ds_get_width(ds), - ds_get_height(ds), - ds_get_linesize(ds)); - - if (!s->full_screen) { - GtkRequisition req; - double sx, sy; - - if (s->free_scale) { - sx = s->scale_x; - sy = s->scale_y; - - s->scale_y = 1.0; - s->scale_x = 1.0; - } else { - sx = 1.0; - sy = 1.0; - } - - gtk_widget_set_size_request(s->drawing_area, - ds_get_width(ds) * s->scale_x, - ds_get_height(ds) * s->scale_y); -#if GTK_CHECK_VERSION(3, 0, 0) - gtk_widget_get_preferred_size(s->vbox, NULL, &req); -#else - gtk_widget_size_request(s->vbox, &req); -#endif + surface_width(surface), + surface_height(surface), + surface_stride(surface)); - gtk_window_resize(GTK_WINDOW(s->window), - req.width * sx, req.height * sy); + if (resized) { + gd_update_windowsize(s); + } else { + gd_update_full_redraw(s); } } @@ -382,7 +407,7 @@ static gboolean gd_window_close(GtkWidget *widget, GdkEvent *event, GtkDisplayState *s = opaque; if (!no_quit) { - unregister_displaychangelistener(s->ds, &s->dcl); + unregister_displaychangelistener(&s->dcl); qmp_quit(NULL); return FALSE; } @@ -401,8 +426,8 @@ static gboolean gd_draw_event(GtkWidget *widget, cairo_t *cr, void *opaque) return FALSE; } - fbw = ds_get_width(s->ds); - fbh = ds_get_height(s->ds); + fbw = surface_width(s->ds); + fbh = surface_height(s->ds); gdk_drawable_get_size(gtk_widget_get_window(widget), &ww, &wh); @@ -480,8 +505,8 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, int fbh, fbw; int ww, wh; - fbw = ds_get_width(s->ds) * s->scale_x; - fbh = ds_get_height(s->ds) * s->scale_y; + fbw = surface_width(s->ds) * s->scale_x; + fbh = surface_height(s->ds) * s->scale_y; gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh); @@ -497,14 +522,14 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, y = (motion->y - my) / s->scale_y; if (x < 0 || y < 0 || - x >= ds_get_width(s->ds) || - y >= ds_get_height(s->ds)) { + x >= surface_width(s->ds) || + y >= surface_height(s->ds)) { return TRUE; } if (kbd_mouse_is_absolute()) { - dx = x * 0x7FFF / (ds_get_width(s->ds) - 1); - dy = y * 0x7FFF / (ds_get_height(s->ds) - 1); + dx = x * 0x7FFF / (surface_width(s->ds) - 1); + dy = y * 0x7FFF / (surface_height(s->ds) - 1); } else if (s->last_x == -1 || s->last_y == -1) { dx = 0; dy = 0; @@ -585,8 +610,8 @@ static gboolean gd_button_event(GtkWidget *widget, GdkEventButton *button, } if (kbd_mouse_is_absolute()) { - dx = s->last_x * 0x7FFF / (ds_get_width(s->ds) - 1); - dy = s->last_y * 0x7FFF / (ds_get_height(s->ds) - 1); + dx = s->last_x * 0x7FFF / (surface_width(s->ds) - 1); + dy = s->last_y * 0x7FFF / (surface_height(s->ds) - 1); } else { dx = 0; dy = 0; @@ -715,7 +740,8 @@ static void gd_menu_full_screen(GtkMenuItem *item, void *opaque) gd_menu_show_tabs(GTK_MENU_ITEM(s->show_tabs_item), s); gtk_widget_set_size_request(s->menu_bar, -1, -1); gtk_widget_set_size_request(s->drawing_area, - ds_get_width(s->ds), ds_get_height(s->ds)); + surface_width(s->ds), + surface_height(s->ds)); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item), FALSE); s->full_screen = FALSE; s->scale_x = 1.0; @@ -735,7 +761,7 @@ static void gd_menu_zoom_in(GtkMenuItem *item, void *opaque) s->scale_x += .25; s->scale_y += .25; - gd_resize(s->ds); + gd_update_windowsize(s); } static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque) @@ -751,7 +777,7 @@ static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque) s->scale_x = MAX(s->scale_x, .25); s->scale_y = MAX(s->scale_y, .25); - gd_resize(s->ds); + gd_update_windowsize(s); } static void gd_menu_zoom_fixed(GtkMenuItem *item, void *opaque) @@ -761,13 +787,12 @@ static void gd_menu_zoom_fixed(GtkMenuItem *item, void *opaque) s->scale_x = 1.0; s->scale_y = 1.0; - gd_resize(s->ds); + gd_update_windowsize(s); } static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque) { GtkDisplayState *s = opaque; - int ww, wh; if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->zoom_fit_item))) { s->free_scale = TRUE; @@ -775,10 +800,8 @@ static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque) s->free_scale = FALSE; } - gd_resize(s->ds); - - gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh); - gtk_widget_queue_draw_area(s->drawing_area, 0, 0, ww, wh); + gd_update_windowsize(s); + gd_update_full_redraw(s); } static void gd_grab_keyboard(GtkDisplayState *s) @@ -1281,17 +1304,20 @@ static void gd_create_menus(GtkDisplayState *s) gtk_menu_shell_append(GTK_MENU_SHELL(s->menu_bar), s->view_menu_item); } +static const DisplayChangeListenerOps dcl_ops = { + .dpy_name = "gtk", + .dpy_gfx_update = gd_update, + .dpy_gfx_switch = gd_switch, + .dpy_refresh = gd_refresh, +}; + void gtk_display_init(DisplayState *ds) { GtkDisplayState *s = g_malloc0(sizeof(*s)); gtk_init(NULL, NULL); - ds->opaque = s; - s->ds = ds; - s->dcl.dpy_gfx_update = gd_update; - s->dcl.dpy_gfx_resize = gd_resize; - s->dcl.dpy_refresh = gd_refresh; + s->dcl.ops = &dcl_ops; s->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); #if GTK_CHECK_VERSION(3, 2, 0) @@ -35,6 +35,7 @@ #include "sdl_zoom.h" static DisplayChangeListener *dcl; +static DisplaySurface *surface; static SDL_Surface *real_screen; static SDL_Surface *guest_screen = NULL; static int gui_grab; /* if true, all keyboard/mouse events are grabbed */ @@ -59,7 +60,8 @@ static SDL_PixelFormat host_format; static int scaling_active = 0; static Notifier mouse_mode_notifier; -static void sdl_update(DisplayState *ds, int x, int y, int w, int h) +static void sdl_update(DisplayChangeListener *dcl, + int x, int y, int w, int h) { // printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h); SDL_Rect rec; @@ -81,16 +83,6 @@ static void sdl_update(DisplayState *ds, int x, int y, int w, int h) SDL_UpdateRect(real_screen, rec.x, rec.y, rec.w, rec.h); } -static void sdl_setdata(DisplayState *ds) -{ - if (guest_screen != NULL) SDL_FreeSurface(guest_screen); - - guest_screen = SDL_CreateRGBSurfaceFrom(ds_get_data(ds), ds_get_width(ds), ds_get_height(ds), - ds_get_bits_per_pixel(ds), ds_get_linesize(ds), - ds->surface->pf.rmask, ds->surface->pf.gmask, - ds->surface->pf.bmask, ds->surface->pf.amask); -} - static void do_sdl_resize(int width, int height, int bpp) { int flags; @@ -114,15 +106,32 @@ static void do_sdl_resize(int width, int height, int bpp) } } -static void sdl_resize(DisplayState *ds) +static void sdl_switch(DisplayChangeListener *dcl, + DisplaySurface *new_surface) { + + /* temporary hack: allows to call sdl_switch to handle scaling changes */ + if (new_surface) { + surface = new_surface; + } + if (!scaling_active) { - do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0); - } else if (real_screen->format->BitsPerPixel != ds_get_bits_per_pixel(ds)) { + do_sdl_resize(surface_width(surface), surface_height(surface), 0); + } else if (real_screen->format->BitsPerPixel != + surface_bits_per_pixel(surface)) { do_sdl_resize(real_screen->w, real_screen->h, - ds_get_bits_per_pixel(ds)); + surface_bits_per_pixel(surface)); + } + + if (guest_screen != NULL) { + SDL_FreeSurface(guest_screen); } - sdl_setdata(ds); + guest_screen = SDL_CreateRGBSurfaceFrom + (surface_data(surface), + surface_width(surface), surface_height(surface), + surface_bits_per_pixel(surface), surface_stride(surface), + surface->pf.rmask, surface->pf.gmask, + surface->pf.bmask, surface->pf.amask); } /* generic keyboard conversion */ @@ -445,7 +454,7 @@ static void sdl_send_mouse_event(int dx, int dy, int dz, int x, int y, int state kbd_mouse_event(dx, dy, dz, buttons); } -static void sdl_scale(DisplayState *ds, int width, int height) +static void sdl_scale(int width, int height) { int bpp = real_screen->format->BitsPerPixel; @@ -454,32 +463,30 @@ static void sdl_scale(DisplayState *ds, int width, int height) } do_sdl_resize(width, height, bpp); scaling_active = 1; - if (!is_buffer_shared(ds->surface)) { - ds->surface = qemu_resize_displaysurface(ds, ds_get_width(ds), - ds_get_height(ds)); - dpy_gfx_resize(ds); - } } -static void toggle_full_screen(DisplayState *ds) +static void toggle_full_screen(void) { + int width = surface_width(surface); + int height = surface_height(surface); + int bpp = surface_bits_per_pixel(surface); + gui_fullscreen = !gui_fullscreen; if (gui_fullscreen) { gui_saved_width = real_screen->w; gui_saved_height = real_screen->h; gui_saved_scaling = scaling_active; - do_sdl_resize(ds_get_width(ds), ds_get_height(ds), - ds_get_bits_per_pixel(ds)); + do_sdl_resize(width, height, bpp); scaling_active = 0; gui_saved_grab = gui_grab; sdl_grab_start(); } else { if (gui_saved_scaling) { - sdl_scale(ds, gui_saved_width, gui_saved_height); + sdl_scale(gui_saved_width, gui_saved_height); } else { - do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0); + do_sdl_resize(width, height, 0); } if (!gui_saved_grab || !is_graphic_console()) { sdl_grab_end(); @@ -489,7 +496,7 @@ static void toggle_full_screen(DisplayState *ds) vga_hw_update(); } -static void handle_keydown(DisplayState *ds, SDL_Event *ev) +static void handle_keydown(SDL_Event *ev) { int mod_state; int keycode; @@ -508,13 +515,13 @@ static void handle_keydown(DisplayState *ds, SDL_Event *ev) keycode = sdl_keyevent_to_keycode(&ev->key); switch (keycode) { case 0x21: /* 'f' key on US keyboard */ - toggle_full_screen(ds); + toggle_full_screen(); gui_keysym = 1; break; case 0x16: /* 'u' key on US keyboard */ if (scaling_active) { scaling_active = 0; - sdl_resize(ds); + sdl_switch(dcl, NULL); vga_hw_invalidate(); vga_hw_update(); } @@ -545,9 +552,10 @@ static void handle_keydown(DisplayState *ds, SDL_Event *ev) if (!gui_fullscreen) { int width = MAX(real_screen->w + (keycode == 0x1b ? 50 : -50), 160); - int height = (ds_get_height(ds) * width) / ds_get_width(ds); + int height = (surface_height(surface) * width) / + surface_width(surface); - sdl_scale(ds, width, height); + sdl_scale(width, height); vga_hw_invalidate(); vga_hw_update(); gui_keysym = 1; @@ -634,7 +642,7 @@ static void handle_keydown(DisplayState *ds, SDL_Event *ev) } } -static void handle_keyup(DisplayState *ds, SDL_Event *ev) +static void handle_keyup(SDL_Event *ev) { int mod_state; @@ -666,7 +674,7 @@ static void handle_keyup(DisplayState *ds, SDL_Event *ev) } } -static void handle_mousemotion(DisplayState *ds, SDL_Event *ev) +static void handle_mousemotion(SDL_Event *ev) { int max_x, max_y; @@ -690,7 +698,7 @@ static void handle_mousemotion(DisplayState *ds, SDL_Event *ev) } } -static void handle_mousebutton(DisplayState *ds, SDL_Event *ev) +static void handle_mousebutton(SDL_Event *ev) { int buttonstate = SDL_GetMouseState(NULL, NULL); SDL_MouseButtonEvent *bev; @@ -726,7 +734,7 @@ static void handle_mousebutton(DisplayState *ds, SDL_Event *ev) } } -static void handle_activation(DisplayState *ds, SDL_Event *ev) +static void handle_activation(SDL_Event *ev) { #ifdef _WIN32 /* Disable grab if the window no longer has the focus @@ -753,7 +761,7 @@ static void handle_activation(DisplayState *ds, SDL_Event *ev) } } -static void sdl_refresh(DisplayState *ds) +static void sdl_refresh(DisplayChangeListener *dcl) { SDL_Event ev1, *ev = &ev1; @@ -768,13 +776,13 @@ static void sdl_refresh(DisplayState *ds) while (SDL_PollEvent(ev)) { switch (ev->type) { case SDL_VIDEOEXPOSE: - sdl_update(ds, 0, 0, real_screen->w, real_screen->h); + sdl_update(dcl, 0, 0, real_screen->w, real_screen->h); break; case SDL_KEYDOWN: - handle_keydown(ds, ev); + handle_keydown(ev); break; case SDL_KEYUP: - handle_keyup(ds, ev); + handle_keyup(ev); break; case SDL_QUIT: if (!no_quit) { @@ -783,17 +791,17 @@ static void sdl_refresh(DisplayState *ds) } break; case SDL_MOUSEMOTION: - handle_mousemotion(ds, ev); + handle_mousemotion(ev); break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: - handle_mousebutton(ds, ev); + handle_mousebutton(ev); break; case SDL_ACTIVEEVENT: - handle_activation(ds, ev); + handle_activation(ev); break; case SDL_VIDEORESIZE: - sdl_scale(ds, ev->resize.w, ev->resize.h); + sdl_scale(ev->resize.w, ev->resize.h); vga_hw_invalidate(); vga_hw_update(); break; @@ -803,7 +811,8 @@ static void sdl_refresh(DisplayState *ds) } } -static void sdl_mouse_warp(DisplayState *ds, int x, int y, int on) +static void sdl_mouse_warp(DisplayChangeListener *dcl, + int x, int y, int on) { if (on) { if (!guest_cursor) @@ -819,7 +828,8 @@ static void sdl_mouse_warp(DisplayState *ds, int x, int y, int on) guest_x = x, guest_y = y; } -static void sdl_mouse_define(DisplayState *ds, QEMUCursor *c) +static void sdl_mouse_define(DisplayChangeListener *dcl, + QEMUCursor *c) { uint8_t *image, *mask; int bpl; @@ -849,6 +859,15 @@ static void sdl_cleanup(void) SDL_QuitSubSystem(SDL_INIT_VIDEO); } +static const DisplayChangeListenerOps dcl_ops = { + .dpy_name = "sdl", + .dpy_gfx_update = sdl_update, + .dpy_gfx_switch = sdl_switch, + .dpy_refresh = sdl_refresh, + .dpy_mouse_set = sdl_mouse_warp, + .dpy_cursor_define = sdl_mouse_define, +}; + void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) { int flags; @@ -917,12 +936,7 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) } dcl = g_malloc0(sizeof(DisplayChangeListener)); - dcl->dpy_gfx_update = sdl_update; - dcl->dpy_gfx_resize = sdl_resize; - dcl->dpy_refresh = sdl_refresh; - dcl->dpy_gfx_setdata = sdl_setdata; - dcl->dpy_mouse_set = sdl_mouse_warp; - dcl->dpy_cursor_define = sdl_mouse_define; + dcl->ops = &dcl_ops; register_displaychangelistener(ds, dcl); mouse_mode_notifier.notify = sdl_mouse_mode_change; diff --git a/ui/spice-display.c b/ui/spice-display.c index dc7e58d0ed..eaab19d9bd 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -214,10 +214,10 @@ static void qemu_spice_create_one_update(SimpleSpiceDisplay *ssd, static void qemu_spice_create_update(SimpleSpiceDisplay *ssd) { static const int blksize = 32; - int blocks = (ds_get_width(ssd->ds) + blksize - 1) / blksize; + int blocks = (surface_width(ssd->ds) + blksize - 1) / blksize; int dirty_top[blocks]; int y, yoff, x, xoff, blk, bw; - int bpp = ds_get_bytes_per_pixel(ssd->ds); + int bpp = surface_bytes_per_pixel(ssd->ds); uint8_t *guest, *mirror; if (qemu_spice_rect_is_empty(&ssd->dirty)) { @@ -225,19 +225,19 @@ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd) }; if (ssd->surface == NULL) { - ssd->surface = pixman_image_ref(ds_get_image(ssd->ds)); - ssd->mirror = qemu_pixman_mirror_create(ds_get_format(ssd->ds), - ds_get_image(ssd->ds)); + ssd->surface = pixman_image_ref(ssd->ds->image); + ssd->mirror = qemu_pixman_mirror_create(ssd->ds->format, + ssd->ds->image); } for (blk = 0; blk < blocks; blk++) { dirty_top[blk] = -1; } - guest = ds_get_data(ssd->ds); + guest = surface_data(ssd->ds); mirror = (void *)pixman_image_get_data(ssd->mirror); for (y = ssd->dirty.top; y < ssd->dirty.bottom; y++) { - yoff = y * ds_get_linesize(ssd->ds); + yoff = y * surface_stride(ssd->ds); for (x = ssd->dirty.left; x < ssd->dirty.right; x += blksize) { xoff = x * bpp; blk = x / blksize; @@ -312,11 +312,11 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd) memset(&surface, 0, sizeof(surface)); dprint(1, "%s: %dx%d\n", __FUNCTION__, - ds_get_width(ssd->ds), ds_get_height(ssd->ds)); + surface_width(ssd->ds), surface_height(ssd->ds)); surface.format = SPICE_SURFACE_FMT_32_xRGB; - surface.width = ds_get_width(ssd->ds); - surface.height = ds_get_height(ssd->ds); + surface.width = surface_width(ssd->ds); + surface.height = surface_height(ssd->ds); surface.stride = -surface.width * 4; surface.mouse_mode = true; surface.flags = 0; @@ -334,9 +334,8 @@ void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd) qemu_spice_destroy_primary_surface(ssd, 0, QXL_SYNC); } -void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds) +void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd) { - ssd->ds = ds; qemu_mutex_init(&ssd->lock); QTAILQ_INIT(&ssd->updates); ssd->mouse_x = -1; @@ -367,7 +366,8 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd, qemu_spice_rect_union(&ssd->dirty, &update_area); } -void qemu_spice_display_resize(SimpleSpiceDisplay *ssd) +void qemu_spice_display_switch(SimpleSpiceDisplay *ssd, + DisplaySurface *surface) { SimpleSpiceUpdate *update; @@ -382,6 +382,7 @@ void qemu_spice_display_resize(SimpleSpiceDisplay *ssd) } qemu_mutex_lock(&ssd->lock); + ssd->ds = surface; while ((update = QTAILQ_FIRST(&ssd->updates)) != NULL) { QTAILQ_REMOVE(&ssd->updates, update, next); qemu_spice_destroy_update(ssd, update); @@ -397,12 +398,14 @@ void qemu_spice_display_resize(SimpleSpiceDisplay *ssd) void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd) { if (ssd->cursor) { - dpy_cursor_define(ssd->ds, ssd->cursor); + assert(ssd->con); + dpy_cursor_define(ssd->con, ssd->cursor); cursor_put(ssd->cursor); ssd->cursor = NULL; } if (ssd->mouse_x != -1 && ssd->mouse_y != -1) { - dpy_mouse_set(ssd->ds, ssd->mouse_x, ssd->mouse_y, 1); + assert(ssd->con); + dpy_mouse_set(ssd->con, ssd->mouse_x, ssd->mouse_y, 1); ssd->mouse_x = -1; ssd->mouse_y = -1; } @@ -414,7 +417,7 @@ void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd) vga_hw_update(); qemu_mutex_lock(&ssd->lock); - if (QTAILQ_EMPTY(&ssd->updates)) { + if (QTAILQ_EMPTY(&ssd->updates) && ssd->ds) { qemu_spice_create_update(ssd); ssd->notify++; } @@ -581,39 +584,47 @@ static const QXLInterface dpy_interface = { .client_monitors_config = interface_client_monitors_config, }; -static SimpleSpiceDisplay sdpy; - -static void display_update(struct DisplayState *ds, int x, int y, int w, int h) +static void display_update(DisplayChangeListener *dcl, + int x, int y, int w, int h) { - qemu_spice_display_update(&sdpy, x, y, w, h); + SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); + qemu_spice_display_update(ssd, x, y, w, h); } -static void display_resize(struct DisplayState *ds) +static void display_switch(DisplayChangeListener *dcl, + struct DisplaySurface *surface) { - qemu_spice_display_resize(&sdpy); + SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); + qemu_spice_display_switch(ssd, surface); } -static void display_refresh(struct DisplayState *ds) +static void display_refresh(DisplayChangeListener *dcl) { - qemu_spice_display_refresh(&sdpy); + SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); + qemu_spice_display_refresh(ssd); } -static DisplayChangeListener display_listener = { +static const DisplayChangeListenerOps display_listener_ops = { + .dpy_name = "spice", .dpy_gfx_update = display_update, - .dpy_gfx_resize = display_resize, - .dpy_refresh = display_refresh, + .dpy_gfx_switch = display_switch, + .dpy_refresh = display_refresh, }; void qemu_spice_display_init(DisplayState *ds) { - assert(sdpy.ds == NULL); - qemu_spice_display_init_common(&sdpy, ds); + SimpleSpiceDisplay *ssd = g_new0(SimpleSpiceDisplay, 1); + + qemu_spice_display_init_common(ssd); + + ssd->qxl.base.sif = &dpy_interface.base; + qemu_spice_add_interface(&ssd->qxl.base); + assert(ssd->worker); - sdpy.qxl.base.sif = &dpy_interface.base; - qemu_spice_add_interface(&sdpy.qxl.base); - assert(sdpy.worker); + qemu_spice_create_host_memslot(ssd); - qemu_spice_create_host_memslot(&sdpy); - qemu_spice_create_host_primary(&sdpy); - register_displaychangelistener(ds, &display_listener); + ssd->dcl.ops = &display_listener_ops; + register_displaychangelistener(ds, &ssd->dcl); + + qemu_spice_create_host_primary(ssd); } diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c index 4ddea7d4f5..e6966aebc3 100644 --- a/ui/vnc-enc-tight.c +++ b/ui/vnc-enc-tight.c @@ -123,7 +123,7 @@ static bool tight_can_send_png_rect(VncState *vs, int w, int h) return false; } - if (ds_get_bytes_per_pixel(vs->ds) == 1 || + if (surface_bytes_per_pixel(vs->vd->ds) == 1 || vs->client_pf.bytes_per_pixel == 1) { return false; } @@ -301,7 +301,7 @@ tight_detect_smooth_image(VncState *vs, int w, int h) return 0; } - if (ds_get_bytes_per_pixel(vs->ds) == 1 || + if (surface_bytes_per_pixel(vs->vd->ds) == 1 || vs->client_pf.bytes_per_pixel == 1 || w < VNC_TIGHT_DETECT_MIN_WIDTH || h < VNC_TIGHT_DETECT_MIN_HEIGHT) { return 0; @@ -1184,8 +1184,9 @@ static int send_jpeg_rect(VncState *vs, int x, int y, int w, int h, int quality) uint8_t *buf; int dy; - if (ds_get_bytes_per_pixel(vs->ds) == 1) + if (surface_bytes_per_pixel(vs->vd->ds) == 1) { return send_full_color_rect(vs, x, y, w, h); + } buffer_reserve(&vs->tight.jpeg, 2048); diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c index 0bfc0c5485..2d3fce8155 100644 --- a/ui/vnc-jobs.c +++ b/ui/vnc-jobs.c @@ -183,7 +183,6 @@ static void vnc_async_encoding_start(VncState *orig, VncState *local) { local->vnc_encoding = orig->vnc_encoding; local->features = orig->features; - local->ds = orig->ds; local->vd = orig->vd; local->lossy_rect = orig->lossy_rect; local->write_pixels = orig->write_pixels; @@ -44,7 +44,6 @@ static const struct timeval VNC_REFRESH_LOSSY = { 2, 0 }; #include "d3des.h" static VncDisplay *vnc_display; /* needed for info vnc */ -static DisplayChangeListener *dcl; static int vnc_cursor_define(VncState *vs); static void vnc_release_modifiers(VncState *vs); @@ -430,13 +429,14 @@ static void framebuffer_update_request(VncState *vs, int incremental, static void vnc_refresh(void *opaque); static int vnc_refresh_server_surface(VncDisplay *vd); -static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h) +static void vnc_dpy_update(DisplayChangeListener *dcl, + int x, int y, int w, int h) { int i; - VncDisplay *vd = ds->opaque; + VncDisplay *vd = container_of(dcl, VncDisplay, dcl); struct VncSurface *s = &vd->guest; - int width = ds_get_width(ds); - int height = ds_get_height(ds); + int width = surface_width(vd->ds); + int height = surface_height(vd->ds); h += y; @@ -518,17 +518,17 @@ void buffer_advance(Buffer *buf, size_t len) static void vnc_desktop_resize(VncState *vs) { - DisplayState *ds = vs->ds; + DisplaySurface *ds = vs->vd->ds; if (vs->csock == -1 || !vnc_has_feature(vs, VNC_FEATURE_RESIZE)) { return; } - if (vs->client_width == ds_get_width(ds) && - vs->client_height == ds_get_height(ds)) { + if (vs->client_width == surface_width(ds) && + vs->client_height == surface_height(ds)) { return; } - vs->client_width = ds_get_width(ds); - vs->client_height = ds_get_height(ds); + vs->client_width = surface_width(ds); + vs->client_height = surface_height(ds); vnc_lock_output(vs); vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); vnc_write_u8(vs, 0); @@ -573,18 +573,20 @@ void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y) return ptr; } -static void vnc_dpy_resize(DisplayState *ds) +static void vnc_dpy_switch(DisplayChangeListener *dcl, + DisplaySurface *surface) { - VncDisplay *vd = ds->opaque; + VncDisplay *vd = container_of(dcl, VncDisplay, dcl); VncState *vs; vnc_abort_display_jobs(vd); /* server surface */ qemu_pixman_image_unref(vd->server); + vd->ds = surface; vd->server = pixman_image_create_bits(VNC_SERVER_FB_FORMAT, - ds_get_width(ds), - ds_get_height(ds), + surface_width(vd->ds), + surface_height(vd->ds), NULL, 0); /* guest surface */ @@ -593,8 +595,8 @@ static void vnc_dpy_resize(DisplayState *ds) console_color_init(ds); #endif qemu_pixman_image_unref(vd->guest.fb); - vd->guest.fb = pixman_image_ref(ds->surface->image); - vd->guest.format = ds->surface->format; + vd->guest.fb = pixman_image_ref(surface->image); + vd->guest.format = surface->format; memset(vd->guest.dirty, 0xFF, sizeof(vd->guest.dirty)); QTAILQ_FOREACH(vs, &vd->clients, next) { @@ -735,9 +737,11 @@ static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, i vnc_flush(vs); } -static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h) +static void vnc_dpy_copy(DisplayChangeListener *dcl, + int src_x, int src_y, + int dst_x, int dst_y, int w, int h) { - VncDisplay *vd = ds->opaque; + VncDisplay *vd = container_of(dcl, VncDisplay, dcl); VncState *vs, *vn; uint8_t *src_row; uint8_t *dst_row; @@ -806,7 +810,8 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int } } -static void vnc_mouse_set(DisplayState *ds, int x, int y, int visible) +static void vnc_mouse_set(DisplayChangeListener *dcl, + int x, int y, int visible) { /* can we ask the client(s) to move the pointer ??? */ } @@ -832,7 +837,8 @@ static int vnc_cursor_define(VncState *vs) return -1; } -static void vnc_dpy_cursor_define(DisplayState *ds, QEMUCursor *c) +static void vnc_dpy_cursor_define(DisplayChangeListener *dcl, + QEMUCursor *c) { VncDisplay *vd = vnc_display; VncState *vs; @@ -1059,7 +1065,7 @@ void vnc_disconnect_finish(VncState *vs) } if (QTAILQ_EMPTY(&vs->vd->clients)) { - dcl->idle = 1; + vs->vd->dcl.idle = 1; } vnc_remove_timer(vs->vd); @@ -1453,7 +1459,8 @@ static void check_pointer_type_change(Notifier *notifier, void *data) vnc_write_u8(vs, 0); vnc_write_u16(vs, 1); vnc_framebuffer_update(vs, absolute, 0, - ds_get_width(vs->ds), ds_get_height(vs->ds), + surface_width(vs->vd->ds), + surface_height(vs->vd->ds), VNC_ENCODING_POINTER_TYPE_CHANGE); vnc_unlock_output(vs); vnc_flush(vs); @@ -1465,6 +1472,8 @@ static void pointer_event(VncState *vs, int button_mask, int x, int y) { int buttons = 0; int dz = 0; + int width = surface_width(vs->vd->ds); + int height = surface_height(vs->vd->ds); if (button_mask & 0x01) buttons |= MOUSE_EVENT_LBUTTON; @@ -1478,10 +1487,8 @@ static void pointer_event(VncState *vs, int button_mask, int x, int y) dz = 1; if (vs->absolute) { - kbd_mouse_event(ds_get_width(vs->ds) > 1 ? - x * 0x7FFF / (ds_get_width(vs->ds) - 1) : 0x4000, - ds_get_height(vs->ds) > 1 ? - y * 0x7FFF / (ds_get_height(vs->ds) - 1) : 0x4000, + kbd_mouse_event(width > 1 ? x * 0x7FFF / (width - 1) : 0x4000, + height > 1 ? y * 0x7FFF / (height - 1) : 0x4000, dz, buttons); } else if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE)) { x -= 0x7FFF; @@ -1771,12 +1778,15 @@ static void framebuffer_update_request(VncState *vs, int incremental, int w, int h) { int i; - const size_t width = ds_get_width(vs->ds) / 16; + const size_t width = surface_width(vs->vd->ds) / 16; + const size_t height = surface_height(vs->vd->ds); - if (y_position > ds_get_height(vs->ds)) - y_position = ds_get_height(vs->ds); - if (y_position + h >= ds_get_height(vs->ds)) - h = ds_get_height(vs->ds) - y_position; + if (y_position > height) { + y_position = height; + } + if (y_position + h >= height) { + h = height - y_position; + } vs->need_update = 1; if (!incremental) { @@ -1795,7 +1805,9 @@ static void send_ext_key_event_ack(VncState *vs) vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); vnc_write_u8(vs, 0); vnc_write_u16(vs, 1); - vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds), + vnc_framebuffer_update(vs, 0, 0, + surface_width(vs->vd->ds), + surface_height(vs->vd->ds), VNC_ENCODING_EXT_KEY_EVENT); vnc_unlock_output(vs); vnc_flush(vs); @@ -1807,7 +1819,9 @@ static void send_ext_audio_ack(VncState *vs) vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); vnc_write_u8(vs, 0); vnc_write_u16(vs, 1); - vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds), + vnc_framebuffer_update(vs, 0, 0, + surface_width(vs->vd->ds), + surface_height(vs->vd->ds), VNC_ENCODING_AUDIO); vnc_unlock_output(vs); vnc_flush(vs); @@ -1972,16 +1986,6 @@ static void pixel_format_message (VncState *vs) { vs->write_pixels = vnc_write_pixels_copy; } -static void vnc_dpy_setdata(DisplayState *ds) -{ - VncDisplay *vd = ds->opaque; - - qemu_pixman_image_unref(vd->guest.fb); - vd->guest.fb = pixman_image_ref(ds->surface->image); - vd->guest.format = ds->surface->format; - vnc_dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds)); -} - static void vnc_colordepth(VncState *vs) { if (vnc_has_feature(vs, VNC_FEATURE_WMVI)) { @@ -1990,8 +1994,10 @@ static void vnc_colordepth(VncState *vs) vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); vnc_write_u8(vs, 0); vnc_write_u16(vs, 1); /* number of rects */ - vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), - ds_get_height(vs->ds), VNC_ENCODING_WMVi); + vnc_framebuffer_update(vs, 0, 0, + surface_width(vs->vd->ds), + surface_height(vs->vd->ds), + VNC_ENCODING_WMVi); pixel_format_message(vs); vnc_unlock_output(vs); vnc_flush(vs); @@ -2207,8 +2213,8 @@ static int protocol_client_init(VncState *vs, uint8_t *data, size_t len) } vnc_set_share_mode(vs, mode); - vs->client_width = ds_get_width(vs->ds); - vs->client_height = ds_get_height(vs->ds); + vs->client_width = surface_width(vs->vd->ds); + vs->client_height = surface_height(vs->vd->ds); vnc_write_u16(vs, vs->client_width); vnc_write_u16(vs, vs->client_height); @@ -2686,7 +2692,7 @@ static void vnc_init_timer(VncDisplay *vd) vd->timer_interval = VNC_REFRESH_INTERVAL_BASE; if (vd->timer == NULL && !QTAILQ_EMPTY(&vd->clients)) { vd->timer = qemu_new_timer_ms(rt_clock, vnc_refresh, vd); - vnc_dpy_resize(vd->ds); + vga_hw_update(); vnc_refresh(vd); } } @@ -2725,7 +2731,7 @@ static void vnc_connect(VncDisplay *vd, int csock, int skipauth, bool websocket) } VNC_DEBUG("New client on socket %d\n", csock); - dcl->idle = 0; + vd->dcl.idle = 0; socket_set_nonblock(vs->csock); #ifdef CONFIG_VNC_WS if (websocket) { @@ -2756,7 +2762,6 @@ void vnc_init_state(VncState *vs) vs->initialized = true; VncDisplay *vd = vs->vd; - vs->ds = vd->ds; vs->last_x = -1; vs->last_y = -1; @@ -2822,14 +2827,20 @@ static void vnc_listen_websocket_read(void *opaque) } #endif /* CONFIG_VNC_WS */ +static const DisplayChangeListenerOps dcl_ops = { + .dpy_name = "vnc", + .dpy_gfx_copy = vnc_dpy_copy, + .dpy_gfx_update = vnc_dpy_update, + .dpy_gfx_switch = vnc_dpy_switch, + .dpy_mouse_set = vnc_mouse_set, + .dpy_cursor_define = vnc_dpy_cursor_define, +}; + void vnc_display_init(DisplayState *ds) { VncDisplay *vs = g_malloc0(sizeof(*vs)); - dcl = g_malloc0(sizeof(DisplayChangeListener)); - - ds->opaque = vs; - dcl->idle = 1; + vs->dcl.idle = 1; vnc_display = vs; vs->lsock = -1; @@ -2837,7 +2848,6 @@ void vnc_display_init(DisplayState *ds) vs->lwebsock = -1; #endif - vs->ds = ds; QTAILQ_INIT(&vs->clients); vs->expires = TIME_MAX; @@ -2852,19 +2862,14 @@ void vnc_display_init(DisplayState *ds) qemu_mutex_init(&vs->mutex); vnc_start_worker_thread(); - dcl->dpy_gfx_copy = vnc_dpy_copy; - dcl->dpy_gfx_update = vnc_dpy_update; - dcl->dpy_gfx_resize = vnc_dpy_resize; - dcl->dpy_gfx_setdata = vnc_dpy_setdata; - dcl->dpy_mouse_set = vnc_mouse_set; - dcl->dpy_cursor_define = vnc_dpy_cursor_define; - register_displaychangelistener(ds, dcl); + vs->dcl.ops = &dcl_ops; + register_displaychangelistener(ds, &vs->dcl); } static void vnc_display_close(DisplayState *ds) { - VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; + VncDisplay *vs = vnc_display; if (!vs) return; @@ -2895,7 +2900,7 @@ static void vnc_display_close(DisplayState *ds) static int vnc_display_disable_login(DisplayState *ds) { - VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; + VncDisplay *vs = vnc_display; if (!vs) { return -1; @@ -2915,7 +2920,7 @@ static int vnc_display_disable_login(DisplayState *ds) int vnc_display_password(DisplayState *ds, const char *password) { - VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; + VncDisplay *vs = vnc_display; if (!vs) { return -EINVAL; @@ -2941,7 +2946,7 @@ int vnc_display_password(DisplayState *ds, const char *password) int vnc_display_pw_expire(DisplayState *ds, time_t expires) { - VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; + VncDisplay *vs = vnc_display; if (!vs) { return -EINVAL; @@ -2953,14 +2958,14 @@ int vnc_display_pw_expire(DisplayState *ds, time_t expires) char *vnc_display_local_addr(DisplayState *ds) { - VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; + VncDisplay *vs = vnc_display; return vnc_socket_local_addr("%s:%s", vs->lsock); } void vnc_display_open(DisplayState *ds, const char *display, Error **errp) { - VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; + VncDisplay *vs = vnc_display; const char *options; int password = 0; int reverse = 0; @@ -3266,7 +3271,7 @@ fail: void vnc_display_add_client(DisplayState *ds, int csock, int skipauth) { - VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display; + VncDisplay *vs = vnc_display; vnc_connect(vs, csock, skipauth, 0); } @@ -150,7 +150,8 @@ struct VncDisplay bool websocket; char *ws_display; #endif - DisplayState *ds; + DisplaySurface *ds; + DisplayChangeListener dcl; kbd_layout_t *kbd_layout; int lock_key_sync; QemuMutex mutex; @@ -247,7 +248,6 @@ struct VncState { int csock; - DisplayState *ds; DECLARE_BITMAP(dirty[VNC_MAX_HEIGHT], VNC_DIRTY_BITS); uint8_t **lossy_rect; /* Not an Array to avoid costly memcpy in * vnc-jobs-async.c */ |