summaryrefslogtreecommitdiff
path: root/ui
diff options
context:
space:
mode:
Diffstat (limited to 'ui')
-rw-r--r--ui/cocoa.m57
-rw-r--r--ui/console.c470
-rw-r--r--ui/curses.c28
-rw-r--r--ui/gtk.c160
-rw-r--r--ui/sdl.c118
-rw-r--r--ui/spice-display.c81
-rw-r--r--ui/vnc-enc-tight.c7
-rw-r--r--ui/vnc-jobs.c1
-rw-r--r--ui/vnc.c143
-rw-r--r--ui/vnc.h4
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;
diff --git a/ui/gtk.c b/ui/gtk.c
index 794dab15b1..305940d0ba 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -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)
diff --git a/ui/sdl.c b/ui/sdl.c
index 1657848e9f..8da05341bb 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -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;
diff --git a/ui/vnc.c b/ui/vnc.c
index ff4e2ae586..bbe1e0f179 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -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);
}
diff --git a/ui/vnc.h b/ui/vnc.h
index 45d7686843..58e002eed3 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -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 */