diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/ui/console.h | 485 | ||||
-rw-r--r-- | include/ui/pixel_ops.h | 53 | ||||
-rw-r--r-- | include/ui/qemu-pixman.h | 39 | ||||
-rw-r--r-- | include/ui/qemu-spice.h | 79 | ||||
-rw-r--r-- | include/ui/spice-display.h | 134 |
5 files changed, 790 insertions, 0 deletions
diff --git a/include/ui/console.h b/include/ui/console.h new file mode 100644 index 0000000000..777881d4a3 --- /dev/null +++ b/include/ui/console.h @@ -0,0 +1,485 @@ +#ifndef CONSOLE_H +#define CONSOLE_H + +#include "ui/qemu-pixman.h" +#include "qdict.h" +#include "notify.h" +#include "monitor.h" +#include "trace.h" +#include "qapi-types.h" +#include "error.h" + +/* keyboard/mouse support */ + +#define MOUSE_EVENT_LBUTTON 0x01 +#define MOUSE_EVENT_RBUTTON 0x02 +#define MOUSE_EVENT_MBUTTON 0x04 + +/* identical to the ps/2 keyboard bits */ +#define QEMU_SCROLL_LOCK_LED (1 << 0) +#define QEMU_NUM_LOCK_LED (1 << 1) +#define QEMU_CAPS_LOCK_LED (1 << 2) + +/* in ms */ +#define GUI_REFRESH_INTERVAL 30 + +typedef void QEMUPutKBDEvent(void *opaque, int keycode); +typedef void QEMUPutLEDEvent(void *opaque, int ledstate); +typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int buttons_state); + +typedef struct QEMUPutMouseEntry { + QEMUPutMouseEvent *qemu_put_mouse_event; + void *qemu_put_mouse_event_opaque; + int qemu_put_mouse_event_absolute; + char *qemu_put_mouse_event_name; + + int index; + + /* used internally by qemu for handling mice */ + QTAILQ_ENTRY(QEMUPutMouseEntry) node; +} QEMUPutMouseEntry; + +typedef struct QEMUPutLEDEntry { + QEMUPutLEDEvent *put_led; + void *opaque; + QTAILQ_ENTRY(QEMUPutLEDEntry) next; +} QEMUPutLEDEntry; + +void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque); +void qemu_remove_kbd_event_handler(void); +QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, + void *opaque, int absolute, + const char *name); +void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry); +void qemu_activate_mouse_event_handler(QEMUPutMouseEntry *entry); + +QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func, void *opaque); +void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry); + +void kbd_put_keycode(int keycode); +void kbd_put_ledstate(int ledstate); +void kbd_mouse_event(int dx, int dy, int dz, int buttons_state); + +/* Does the current mouse generate absolute events */ +int kbd_mouse_is_absolute(void); +void qemu_add_mouse_mode_change_notifier(Notifier *notify); +void qemu_remove_mouse_mode_change_notifier(Notifier *notify); + +/* Of all the mice, is there one that generates absolute events */ +int kbd_mouse_has_absolute(void); + +struct MouseTransformInfo { + /* Touchscreen resolution */ + int x; + int y; + /* Calibration values as used/generated by tslib */ + int a[7]; +}; + +void do_mouse_set(Monitor *mon, const QDict *qdict); + +/* keysym is a unicode code except for special keys (see QEMU_KEY_xxx + constants) */ +#define QEMU_KEY_ESC1(c) ((c) | 0xe100) +#define QEMU_KEY_BACKSPACE 0x007f +#define QEMU_KEY_UP QEMU_KEY_ESC1('A') +#define QEMU_KEY_DOWN QEMU_KEY_ESC1('B') +#define QEMU_KEY_RIGHT QEMU_KEY_ESC1('C') +#define QEMU_KEY_LEFT QEMU_KEY_ESC1('D') +#define QEMU_KEY_HOME QEMU_KEY_ESC1(1) +#define QEMU_KEY_END QEMU_KEY_ESC1(4) +#define QEMU_KEY_PAGEUP QEMU_KEY_ESC1(5) +#define QEMU_KEY_PAGEDOWN QEMU_KEY_ESC1(6) +#define QEMU_KEY_DELETE QEMU_KEY_ESC1(3) + +#define QEMU_KEY_CTRL_UP 0xe400 +#define QEMU_KEY_CTRL_DOWN 0xe401 +#define QEMU_KEY_CTRL_LEFT 0xe402 +#define QEMU_KEY_CTRL_RIGHT 0xe403 +#define QEMU_KEY_CTRL_HOME 0xe404 +#define QEMU_KEY_CTRL_END 0xe405 +#define QEMU_KEY_CTRL_PAGEUP 0xe406 +#define QEMU_KEY_CTRL_PAGEDOWN 0xe407 + +void kbd_put_keysym(int keysym); + +/* consoles */ + +#define QEMU_BIG_ENDIAN_FLAG 0x01 +#define QEMU_ALLOCATED_FLAG 0x02 + +struct PixelFormat { + uint8_t bits_per_pixel; + uint8_t bytes_per_pixel; + uint8_t depth; /* color depth in bits */ + uint32_t rmask, gmask, bmask, amask; + uint8_t rshift, gshift, bshift, ashift; + uint8_t rmax, gmax, bmax, amax; + uint8_t rbits, gbits, bbits, abits; +}; + +struct DisplaySurface { + pixman_format_code_t format; + pixman_image_t *image; + uint8_t flags; + + struct PixelFormat pf; +}; + +/* cursor data format is 32bit RGBA */ +typedef struct QEMUCursor { + int width, height; + int hot_x, hot_y; + int refcount; + uint32_t data[]; +} QEMUCursor; + +QEMUCursor *cursor_alloc(int width, int height); +void cursor_get(QEMUCursor *c); +void cursor_put(QEMUCursor *c); +QEMUCursor *cursor_builtin_hidden(void); +QEMUCursor *cursor_builtin_left_ptr(void); +void cursor_print_ascii_art(QEMUCursor *c, const char *prefix); +int cursor_get_mono_bpl(QEMUCursor *c); +void cursor_set_mono(QEMUCursor *c, + uint32_t foreground, uint32_t background, uint8_t *image, + int transparent, uint8_t *mask); +void cursor_get_mono_image(QEMUCursor *c, int foreground, uint8_t *mask); +void cursor_get_mono_mask(QEMUCursor *c, int transparent, uint8_t *mask); + +struct DisplayChangeListener { + int idle; + uint64_t gui_timer_interval; + + void (*dpy_refresh)(struct DisplayState *s); + + void (*dpy_gfx_update)(struct DisplayState *s, int x, int y, int w, int h); + void (*dpy_gfx_resize)(struct DisplayState *s); + void (*dpy_gfx_setdata)(struct DisplayState *s); + void (*dpy_gfx_copy)(struct DisplayState *s, int src_x, int src_y, + int dst_x, int dst_y, int w, int h); + + void (*dpy_text_cursor)(struct DisplayState *s, int x, int y); + void (*dpy_text_resize)(struct DisplayState *s, int w, int h); + void (*dpy_text_update)(struct DisplayState *s, int x, int y, int w, int h); + + void (*dpy_mouse_set)(struct DisplayState *s, int x, int y, int on); + void (*dpy_cursor_define)(struct DisplayState *s, QEMUCursor *cursor); + + QLIST_ENTRY(DisplayChangeListener) next; +}; + +struct DisplayState { + struct DisplaySurface *surface; + void *opaque; + struct QEMUTimer *gui_timer; + bool have_gfx; + bool have_text; + + QLIST_HEAD(, DisplayChangeListener) listeners; + + struct DisplayState *next; +}; + +void register_displaystate(DisplayState *ds); +DisplayState *get_displaystate(void); +DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp, + int linesize, uint8_t *data); +PixelFormat qemu_different_endianness_pixelformat(int bpp); +PixelFormat qemu_default_pixelformat(int bpp); + +DisplaySurface *qemu_create_displaysurface(DisplayState *ds, + int width, int height); +DisplaySurface *qemu_resize_displaysurface(DisplayState *ds, + int width, int height); +void qemu_free_displaysurface(DisplayState *ds); + +static inline int is_surface_bgr(DisplaySurface *surface) +{ + if (surface->pf.bits_per_pixel == 32 && surface->pf.rshift == 0) + return 1; + else + return 0; +} + +static inline int is_buffer_shared(DisplaySurface *surface) +{ + return !(surface->flags & QEMU_ALLOCATED_FLAG); +} + +void gui_setup_refresh(DisplayState *ds); + +static inline void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl) +{ + QLIST_INSERT_HEAD(&ds->listeners, dcl, next); + gui_setup_refresh(ds); + if (dcl->dpy_gfx_resize) { + dcl->dpy_gfx_resize(ds); + } +} + +static inline void unregister_displaychangelistener(DisplayState *ds, + DisplayChangeListener *dcl) +{ + QLIST_REMOVE(dcl, next); + gui_setup_refresh(ds); +} + +static inline void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h) +{ + 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->dpy_gfx_update) { + dcl->dpy_gfx_update(s, x, y, w, h); + } + } +} + +static inline void dpy_gfx_resize(DisplayState *s) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->dpy_gfx_resize) { + dcl->dpy_gfx_resize(s); + } + } +} + +static inline void dpy_gfx_setdata(DisplayState *s) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->dpy_gfx_setdata) { + dcl->dpy_gfx_setdata(s); + } + } +} + +static inline void dpy_refresh(DisplayState *s) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->dpy_refresh) { + dcl->dpy_refresh(s); + } + } +} + +static inline void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y, + int dst_x, int dst_y, int w, int h) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->dpy_gfx_copy) { + dcl->dpy_gfx_copy(s, src_x, src_y, dst_x, dst_y, w, h); + } else { /* TODO */ + dcl->dpy_gfx_update(s, dst_x, dst_y, w, h); + } + } +} + +static inline void dpy_text_cursor(struct DisplayState *s, int x, int y) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->dpy_text_cursor) { + dcl->dpy_text_cursor(s, x, y); + } + } +} + +static inline void dpy_text_update(DisplayState *s, int x, int y, int w, int h) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->dpy_text_update) { + dcl->dpy_text_update(s, x, y, w, h); + } + } +} + +static inline void dpy_text_resize(DisplayState *s, int w, int h) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->dpy_text_resize) { + dcl->dpy_text_resize(s, w, h); + } + } +} + +static inline void dpy_mouse_set(struct DisplayState *s, int x, int y, int on) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->dpy_mouse_set) { + dcl->dpy_mouse_set(s, x, y, on); + } + } +} + +static inline void dpy_cursor_define(struct DisplayState *s, QEMUCursor *cursor) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->dpy_cursor_define) { + dcl->dpy_cursor_define(s, cursor); + } + } +} + +static inline bool dpy_cursor_define_supported(struct DisplayState *s) +{ + struct DisplayChangeListener *dcl; + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->dpy_cursor_define) { + return true; + } + } + return false; +} + +static inline int ds_get_linesize(DisplayState *ds) +{ + return pixman_image_get_stride(ds->surface->image); +} + +static inline uint8_t* ds_get_data(DisplayState *ds) +{ + return (void *)pixman_image_get_data(ds->surface->image); +} + +static inline int ds_get_width(DisplayState *ds) +{ + return pixman_image_get_width(ds->surface->image); +} + +static inline int ds_get_height(DisplayState *ds) +{ + return pixman_image_get_height(ds->surface->image); +} + +static inline int ds_get_bits_per_pixel(DisplayState *ds) +{ + int bits = PIXMAN_FORMAT_BPP(ds->surface->format); + return bits; +} + +static inline int ds_get_bytes_per_pixel(DisplayState *ds) +{ + int bits = PIXMAN_FORMAT_BPP(ds->surface->format); + return (bits + 7) / 8; +} + +static inline pixman_format_code_t ds_get_format(DisplayState *ds) +{ + return ds->surface->format; +} + +static inline pixman_image_t *ds_get_image(DisplayState *ds) +{ + return ds->surface->image; +} + +static inline int ds_get_depth(DisplayState *ds) +{ + return ds->surface->pf.depth; +} + +static inline int ds_get_rmask(DisplayState *ds) +{ + return ds->surface->pf.rmask; +} + +static inline int ds_get_gmask(DisplayState *ds) +{ + return ds->surface->pf.gmask; +} + +static inline int ds_get_bmask(DisplayState *ds) +{ + return ds->surface->pf.bmask; +} + +#ifdef CONFIG_CURSES +#include <curses.h> +typedef chtype console_ch_t; +#else +typedef unsigned long console_ch_t; +#endif +static inline void console_write_ch(console_ch_t *dest, uint32_t ch) +{ + if (!(ch & 0xff)) + ch |= ' '; + *dest = ch; +} + +typedef void (*vga_hw_update_ptr)(void *); +typedef void (*vga_hw_invalidate_ptr)(void *); +typedef void (*vga_hw_screen_dump_ptr)(void *, const char *, bool cswitch, + Error **errp); +typedef void (*vga_hw_text_update_ptr)(void *, console_ch_t *); + +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); + +void vga_hw_update(void); +void vga_hw_invalidate(void); +void vga_hw_text_update(console_ch_t *chardata); + +int is_graphic_console(void); +int is_fixedsize_console(void); +CharDriverState *text_console_init(QemuOpts *opts); +void text_consoles_set_display(DisplayState *ds); +void console_select(unsigned int index); +void console_color_init(DisplayState *ds); +void qemu_console_resize(DisplayState *ds, int width, int height); +void qemu_console_copy(DisplayState *ds, int src_x, int src_y, + int dst_x, int dst_y, int w, int h); + +/* sdl.c */ +void sdl_display_init(DisplayState *ds, int full_screen, int no_frame); + +/* cocoa.m */ +void cocoa_display_init(DisplayState *ds, int full_screen); + +/* vnc.c */ +void vnc_display_init(DisplayState *ds); +void vnc_display_open(DisplayState *ds, const char *display, Error **errp); +void vnc_display_add_client(DisplayState *ds, int csock, int skipauth); +char *vnc_display_local_addr(DisplayState *ds); +#ifdef CONFIG_VNC +int vnc_display_password(DisplayState *ds, const char *password); +int vnc_display_pw_expire(DisplayState *ds, time_t expires); +#else +static inline int vnc_display_password(DisplayState *ds, const char *password) +{ + return -ENODEV; +} +static inline int vnc_display_pw_expire(DisplayState *ds, time_t expires) +{ + return -ENODEV; +}; +#endif + +/* curses.c */ +void curses_display_init(DisplayState *ds, int full_screen); + +/* input.c */ +int index_from_key(const char *key); +int index_from_keycode(int code); + +#endif diff --git a/include/ui/pixel_ops.h b/include/ui/pixel_ops.h new file mode 100644 index 0000000000..d390adfd1b --- /dev/null +++ b/include/ui/pixel_ops.h @@ -0,0 +1,53 @@ +static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, + unsigned int b) +{ + return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6); +} + +static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, + unsigned int b) +{ + return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3); +} + +static inline unsigned int rgb_to_pixel15bgr(unsigned int r, unsigned int g, + unsigned int b) +{ + return ((b >> 3) << 10) | ((g >> 3) << 5) | (r >> 3); +} + +static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, + unsigned int b) +{ + return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); +} + +static inline unsigned int rgb_to_pixel16bgr(unsigned int r, unsigned int g, + unsigned int b) +{ + return ((b >> 3) << 11) | ((g >> 2) << 5) | (r >> 3); +} + +static inline unsigned int rgb_to_pixel24(unsigned int r, unsigned int g, + unsigned int b) +{ + return (r << 16) | (g << 8) | b; +} + +static inline unsigned int rgb_to_pixel24bgr(unsigned int r, unsigned int g, + unsigned int b) +{ + return (b << 16) | (g << 8) | r; +} + +static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, + unsigned int b) +{ + return (r << 16) | (g << 8) | b; +} + +static inline unsigned int rgb_to_pixel32bgr(unsigned int r, unsigned int g, + unsigned int b) +{ + return (b << 16) | (g << 8) | r; +} diff --git a/include/ui/qemu-pixman.h b/include/ui/qemu-pixman.h new file mode 100644 index 0000000000..3c05c83a7c --- /dev/null +++ b/include/ui/qemu-pixman.h @@ -0,0 +1,39 @@ +/* + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef QEMU_PIXMAN_H +#define QEMU_PIXMAN_H + +#include <pixman.h> + +#include "console.h" + +/* + * pixman image formats are defined to be native endian, + * that means host byte order on qemu. So we go define + * fixed formats here for cases where it is needed, like + * feeding libjpeg / libpng and writing screenshots. + */ + +#ifdef HOST_WORDS_BIGENDIAN +# define PIXMAN_BE_r8g8b8 PIXMAN_r8g8b8 +#else +# define PIXMAN_BE_r8g8b8 PIXMAN_b8g8r8 +#endif + +/* -------------------------------------------------------------------- */ + +int qemu_pixman_get_type(int rshift, int gshift, int bshift); +pixman_format_code_t qemu_pixman_get_format(PixelFormat *pf); + +pixman_image_t *qemu_pixman_linebuf_create(pixman_format_code_t format, + int width); +void qemu_pixman_linebuf_fill(pixman_image_t *linebuf, pixman_image_t *fb, + int width, int x, int y); +pixman_image_t *qemu_pixman_mirror_create(pixman_format_code_t format, + pixman_image_t *image); +void qemu_pixman_image_unref(pixman_image_t *image); + +#endif /* QEMU_PIXMAN_H */ diff --git a/include/ui/qemu-spice.h b/include/ui/qemu-spice.h new file mode 100644 index 0000000000..5857b8a92e --- /dev/null +++ b/include/ui/qemu-spice.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2010 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef QEMU_SPICE_H +#define QEMU_SPICE_H + +#ifdef CONFIG_SPICE + +#include <spice.h> + +#include "qemu-option.h" +#include "qemu-config.h" +#include "monitor.h" + +extern int using_spice; + +void qemu_spice_init(void); +void qemu_spice_input_init(void); +void qemu_spice_audio_init(void); +void qemu_spice_display_init(DisplayState *ds); +int qemu_spice_display_add_client(int csock, int skipauth, int tls); +int qemu_spice_add_interface(SpiceBaseInstance *sin); +int qemu_spice_set_passwd(const char *passwd, + bool fail_if_connected, bool disconnect_if_connected); +int qemu_spice_set_pw_expire(time_t expires); +int qemu_spice_migrate_info(const char *hostname, int port, int tls_port, + const char *subject, + MonitorCompletion cb, void *opaque); + +void do_info_spice_print(Monitor *mon, const QObject *data); +void do_info_spice(Monitor *mon, QObject **ret_data); + +CharDriverState *qemu_chr_open_spice(QemuOpts *opts); + +#else /* CONFIG_SPICE */ +#include "monitor.h" + +#define using_spice 0 +static inline int qemu_spice_set_passwd(const char *passwd, + bool fail_if_connected, + bool disconnect_if_connected) +{ + return -1; +} +static inline int qemu_spice_set_pw_expire(time_t expires) +{ + return -1; +} +static inline int qemu_spice_migrate_info(const char *h, int p, int t, + const char *s, + MonitorCompletion cb, void *opaque) +{ + cb(opaque, NULL); + return -1; +} + +static inline int qemu_spice_display_add_client(int csock, int skipauth, + int tls) +{ + return -1; +} + +#endif /* CONFIG_SPICE */ + +#endif /* QEMU_SPICE_H */ diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h new file mode 100644 index 0000000000..928e0a1bae --- /dev/null +++ b/include/ui/spice-display.h @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2010 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <spice/ipc_ring.h> +#include <spice/enums.h> +#include <spice/qxl_dev.h> + +#include "qemu-thread.h" +#include "ui/qemu-pixman.h" +#include "sysemu.h" + +#define NUM_MEMSLOTS 8 +#define MEMSLOT_GENERATION_BITS 8 +#define MEMSLOT_SLOT_BITS 8 + +#define MEMSLOT_GROUP_HOST 0 +#define MEMSLOT_GROUP_GUEST 1 +#define NUM_MEMSLOTS_GROUPS 2 + +/* + * Internal enum to differenciate between options for + * io calls that have a sync (old) version and an _async (new) + * version: + * QXL_SYNC: use the old version + * QXL_ASYNC: use the new version and make sure there are no two + * happening at the same time. This is used for guest initiated + * calls + */ +typedef enum qxl_async_io { + QXL_SYNC, + QXL_ASYNC, +} qxl_async_io; + +enum { + QXL_COOKIE_TYPE_IO, + QXL_COOKIE_TYPE_RENDER_UPDATE_AREA, + QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG, +}; + +typedef struct QXLCookie { + int type; + uint64_t io; + union { + uint32_t surface_id; + QXLRect area; + struct { + QXLRect area; + int redraw; + } render; + } u; +} QXLCookie; + +QXLCookie *qxl_cookie_new(int type, uint64_t io); + +typedef struct SimpleSpiceDisplay SimpleSpiceDisplay; +typedef struct SimpleSpiceUpdate SimpleSpiceUpdate; + +struct SimpleSpiceDisplay { + DisplayState *ds; + void *buf; + int bufsize; + QXLWorker *worker; + QXLInstance qxl; + uint32_t unique; + pixman_image_t *surface; + pixman_image_t *mirror; + int32_t num_surfaces; + + QXLRect dirty; + int notify; + + /* + * All struct members below this comment can be accessed from + * both spice server and qemu (iothread) context and any access + * to them must be protected by the lock. + */ + QemuMutex lock; + QTAILQ_HEAD(, SimpleSpiceUpdate) updates; + QEMUCursor *cursor; + int mouse_x, mouse_y; +}; + +struct SimpleSpiceUpdate { + QXLDrawable drawable; + QXLImage image; + QXLCommandExt ext; + uint8_t *bitmap; + QTAILQ_ENTRY(SimpleSpiceUpdate) next; +}; + +int qemu_spice_rect_is_empty(const QXLRect* r); +void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r); + +void qemu_spice_destroy_update(SimpleSpiceDisplay *sdpy, SimpleSpiceUpdate *update); +void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd); +void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd); +void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd); +void qemu_spice_vm_change_state_handler(void *opaque, int running, + RunState state); +void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds); + +void qemu_spice_display_update(SimpleSpiceDisplay *ssd, + int x, int y, int w, int h); +void qemu_spice_display_resize(SimpleSpiceDisplay *ssd); +void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd); +void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd); + +void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot, + qxl_async_io async); +void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid, + uint32_t sid); +void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id, + QXLDevSurfaceCreate *surface, + qxl_async_io async); +void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, + uint32_t id, qxl_async_io async); +void qemu_spice_wakeup(SimpleSpiceDisplay *ssd); +void qemu_spice_display_start(void); +void qemu_spice_display_stop(void); +int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd); |