diff options
Diffstat (limited to 'ui')
-rw-r--r-- | ui/sdl.c | 4 | ||||
-rw-r--r-- | ui/spice-core.c | 62 | ||||
-rw-r--r-- | ui/spice-display.c | 71 | ||||
-rw-r--r-- | ui/spice-display.h | 21 | ||||
-rw-r--r-- | ui/vnc-auth-sasl.c | 4 | ||||
-rw-r--r-- | ui/vnc-auth-sasl.h | 4 | ||||
-rw-r--r-- | ui/vnc-enc-hextile-template.h | 1 | ||||
-rw-r--r-- | ui/vnc-jobs-async.c | 48 | ||||
-rw-r--r-- | ui/vnc-jobs.h | 1 | ||||
-rw-r--r-- | ui/vnc.c | 20 | ||||
-rw-r--r-- | ui/vnc.h | 2 |
11 files changed, 148 insertions, 90 deletions
@@ -167,10 +167,6 @@ static PixelFormat sdl_to_qemu_pixelformat(SDL_PixelFormat *sdl_pf) static DisplaySurface* sdl_create_displaysurface(int width, int height) { DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface)); - if (surface == NULL) { - fprintf(stderr, "sdl_create_displaysurface: malloc failed\n"); - exit(1); - } surface->width = width; surface->height = height; diff --git a/ui/spice-core.c b/ui/spice-core.c index 1308a3d886..a468524799 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -19,6 +19,7 @@ #include <spice-experimental.h> #include <netdb.h> +#include "sysemu.h" #include "qemu-common.h" #include "qemu-spice.h" @@ -139,8 +140,6 @@ static void watch_remove(SpiceWatch *watch) g_free(watch); } -#if SPICE_INTERFACE_CORE_MINOR >= 3 - typedef struct ChannelList ChannelList; struct ChannelList { SpiceChannelEventInfo *info; @@ -229,8 +228,8 @@ static void channel_event(int event, SpiceChannelEventInfo *info) add_addr_info(server, (struct sockaddr *)&info->laddr_ext, info->llen_ext); } else { - fprintf(stderr, "spice: %s, extended address is expected\n", - __func__); + error_report("spice: %s, extended address is expected", + __func__); #endif add_addr_info(client, &info->paddr, info->plen); add_addr_info(server, &info->laddr, info->llen); @@ -257,15 +256,6 @@ static void channel_event(int event, SpiceChannelEventInfo *info) } } -#else /* SPICE_INTERFACE_CORE_MINOR >= 3 */ - -static QList *channel_list_get(void) -{ - return NULL; -} - -#endif /* SPICE_INTERFACE_CORE_MINOR >= 3 */ - static SpiceCoreInterface core_interface = { .base.type = SPICE_INTERFACE_CORE, .base.description = "qemu core services", @@ -281,9 +271,7 @@ static SpiceCoreInterface core_interface = { .watch_update_mask = watch_update_mask, .watch_remove = watch_remove, -#if SPICE_INTERFACE_CORE_MINOR >= 3 .channel_event = channel_event, -#endif }; #ifdef SPICE_INTERFACE_MIGRATION @@ -346,7 +334,7 @@ static int parse_name(const char *string, const char *optname, if (value != -1) { return value; } - fprintf(stderr, "spice: invalid %s: %s\n", optname, string); + error_report("spice: invalid %s: %s", optname, string); exit(1); } @@ -490,7 +478,6 @@ static void migration_state_notifier(Notifier *notifier, void *data) spice_server_migrate_start(spice_server); #endif } else if (migration_has_finished(s)) { -#if SPICE_SERVER_VERSION >= 0x000701 /* 0.7.1 */ #ifndef SPICE_INTERFACE_MIGRATION spice_server_migrate_switch(spice_server); #else @@ -498,7 +485,6 @@ static void migration_state_notifier(Notifier *notifier, void *data) } else if (migration_has_failed(s)) { spice_server_migrate_end(spice_server, false); #endif -#endif } } @@ -526,6 +512,12 @@ static int add_channel(const char *name, const char *value, void *opaque) int rc; if (strcmp(name, "tls-channel") == 0) { + int *tls_port = opaque; + if (!*tls_port) { + error_report("spice: tried to setup tls-channel" + " without specifying a TLS port"); + exit(1); + } security = SPICE_CHANNEL_SECURITY_SSL; } if (strcmp(name, "plaintext-channel") == 0) { @@ -540,7 +532,7 @@ static int add_channel(const char *name, const char *value, void *opaque) rc = spice_server_set_channel_security(spice_server, value, security); } if (rc != 0) { - fprintf(stderr, "spice: failed to set channel security for %s\n", value); + error_report("spice: failed to set channel security for %s", value); exit(1); } return 0; @@ -562,21 +554,21 @@ void qemu_spice_init(void) qemu_thread_get_self(&me); - if (!opts) { + if (!opts) { return; } port = qemu_opt_get_number(opts, "port", 0); tls_port = qemu_opt_get_number(opts, "tls-port", 0); if (!port && !tls_port) { - fprintf(stderr, "neither port nor tls-port specified for spice."); + error_report("neither port nor tls-port specified for spice"); exit(1); } if (port < 0 || port > 65535) { - fprintf(stderr, "spice port is out of range"); + error_report("spice port is out of range"); exit(1); } if (tls_port < 0 || tls_port > 65535) { - fprintf(stderr, "spice tls-port is out of range"); + error_report("spice tls-port is out of range"); exit(1); } password = qemu_opt_get(opts, "password"); @@ -646,11 +638,11 @@ void qemu_spice_init(void) #if SPICE_SERVER_VERSION >= 0x000900 /* 0.9.0 */ if (spice_server_set_sasl_appname(spice_server, "qemu") == -1 || spice_server_set_sasl(spice_server, 1) == -1) { - fprintf(stderr, "spice: failed to enable sasl\n"); + error_report("spice: failed to enable sasl"); exit(1); } #else - fprintf(stderr, "spice: sasl is not available (spice >= 0.9 required)\n"); + error_report("spice: sasl is not available (spice >= 0.9 required)"); exit(1); #endif } @@ -659,11 +651,9 @@ void qemu_spice_init(void) spice_server_set_noauth(spice_server); } -#if SPICE_SERVER_VERSION >= 0x000801 if (qemu_opt_get_bool(opts, "disable-copy-paste", 0)) { spice_server_set_agent_copypaste(spice_server, false); } -#endif compression = SPICE_IMAGE_COMPRESS_AUTO_GLZ; str = qemu_opt_get(opts, "image-compression"); @@ -697,10 +687,15 @@ void qemu_spice_init(void) spice_server_set_playback_compression (spice_server, qemu_opt_get_bool(opts, "playback-compression", 1)); - qemu_opt_foreach(opts, add_channel, NULL, 0); + qemu_opt_foreach(opts, add_channel, &tls_port, 0); + +#if SPICE_SERVER_VERSION >= 0x000a02 /* 0.10.2 */ + spice_server_set_name(spice_server, qemu_name); + spice_server_set_uuid(spice_server, qemu_uuid); +#endif if (0 != spice_server_init(spice_server, &core_interface)) { - fprintf(stderr, "failed to initialize spice server"); + error_report("failed to initialize spice server"); exit(1); }; using_spice = 1; @@ -725,7 +720,7 @@ int qemu_spice_add_interface(SpiceBaseInstance *sin) { if (!spice_server) { if (QTAILQ_FIRST(&qemu_spice_opts.head) != NULL) { - fprintf(stderr, "Oops: spice configured but not active\n"); + error_report("Oops: spice configured but not active"); exit(1); } /* @@ -792,10 +787,3 @@ static void spice_register_config(void) qemu_add_opts(&qemu_spice_opts); } machine_init(spice_register_config); - -static void spice_register_types(void) -{ - qemu_spice_init(); -} - -type_init(spice_register_types) diff --git a/ui/spice-display.c b/ui/spice-display.c index 6c302a3909..28d6d4a6b3 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -22,6 +22,7 @@ #include "monitor.h" #include "console.h" #include "sysemu.h" +#include "trace.h" #include "spice-display.h" @@ -60,15 +61,27 @@ void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r) dest->right = MAX(dest->right, r->right); } +QXLCookie *qxl_cookie_new(int type, uint64_t io) +{ + QXLCookie *cookie; + + cookie = g_malloc0(sizeof(*cookie)); + cookie->type = type; + cookie->io = io; + return cookie; +} + void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot, qxl_async_io async) { + trace_qemu_spice_add_memslot(ssd->qxl.id, memslot->slot_id, + memslot->virt_start, memslot->virt_end, + async); + if (async != QXL_SYNC) { -#if SPICE_INTERFACE_QXL_MINOR >= 1 - spice_qxl_add_memslot_async(&ssd->qxl, memslot, 0); -#else - abort(); -#endif + spice_qxl_add_memslot_async(&ssd->qxl, memslot, + (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO, + QXL_IO_MEMSLOT_ADD_ASYNC)); } else { ssd->worker->add_memslot(ssd->worker, memslot); } @@ -76,6 +89,7 @@ void qemu_spice_add_memslot(SimpleSpiceDisplay *ssd, QXLDevMemSlot *memslot, void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid, uint32_t sid) { + trace_qemu_spice_del_memslot(ssd->qxl.id, gid, sid); ssd->worker->del_memslot(ssd->worker, gid, sid); } @@ -83,27 +97,24 @@ void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id, QXLDevSurfaceCreate *surface, qxl_async_io async) { + trace_qemu_spice_create_primary_surface(ssd->qxl.id, id, surface, async); if (async != QXL_SYNC) { -#if SPICE_INTERFACE_QXL_MINOR >= 1 - spice_qxl_create_primary_surface_async(&ssd->qxl, id, surface, 0); -#else - abort(); -#endif + spice_qxl_create_primary_surface_async(&ssd->qxl, id, surface, + (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO, + QXL_IO_CREATE_PRIMARY_ASYNC)); } else { ssd->worker->create_primary_surface(ssd->worker, id, surface); } } - void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id, qxl_async_io async) { + trace_qemu_spice_destroy_primary_surface(ssd->qxl.id, id, async); if (async != QXL_SYNC) { -#if SPICE_INTERFACE_QXL_MINOR >= 1 - spice_qxl_destroy_primary_surface_async(&ssd->qxl, id, 0); -#else - abort(); -#endif + spice_qxl_destroy_primary_surface_async(&ssd->qxl, id, + (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO, + QXL_IO_DESTROY_PRIMARY_ASYNC)); } else { ssd->worker->destroy_primary_surface(ssd->worker, id); } @@ -111,16 +122,19 @@ void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd, void qemu_spice_wakeup(SimpleSpiceDisplay *ssd) { + trace_qemu_spice_wakeup(ssd->qxl.id); ssd->worker->wakeup(ssd->worker); } void qemu_spice_start(SimpleSpiceDisplay *ssd) { + trace_qemu_spice_start(ssd->qxl.id); ssd->worker->start(ssd->worker); } void qemu_spice_stop(SimpleSpiceDisplay *ssd) { + trace_qemu_spice_stop(ssd->qxl.id); ssd->worker->stop(ssd->worker); } @@ -138,7 +152,7 @@ static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd) return NULL; }; - dprint(2, "%s: lr %d -> %d, tb -> %d -> %d\n", __FUNCTION__, + trace_qemu_spice_create_update( ssd->dirty.left, ssd->dirty.right, ssd->dirty.top, ssd->dirty.bottom); @@ -317,16 +331,8 @@ void qemu_spice_display_resize(SimpleSpiceDisplay *ssd) ssd->notify++; } -void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd) +void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd) { - dprint(3, "%s:\n", __FUNCTION__); - vga_hw_update(); - - qemu_mutex_lock(&ssd->lock); - if (ssd->update == NULL) { - ssd->update = qemu_spice_create_update(ssd); - ssd->notify++; - } if (ssd->cursor) { ssd->ds->cursor_define(ssd->cursor); cursor_put(ssd->cursor); @@ -337,6 +343,19 @@ void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd) ssd->mouse_x = -1; ssd->mouse_y = -1; } +} + +void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd) +{ + dprint(3, "%s:\n", __func__); + vga_hw_update(); + + qemu_mutex_lock(&ssd->lock); + if (ssd->update == NULL) { + ssd->update = qemu_spice_create_update(ssd); + ssd->notify++; + } + qemu_spice_cursor_refresh_unlocked(ssd); qemu_mutex_unlock(&ssd->lock); if (ssd->notify) { diff --git a/ui/spice-display.h b/ui/spice-display.h index 5e52df99be..12e50b6efc 100644 --- a/ui/spice-display.h +++ b/ui/spice-display.h @@ -48,6 +48,26 @@ typedef enum qxl_async_io { QXL_ASYNC, } qxl_async_io; +enum { + QXL_COOKIE_TYPE_IO, + QXL_COOKIE_TYPE_RENDER_UPDATE_AREA, +}; + +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; @@ -97,6 +117,7 @@ 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); diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c index e2045fc0b8..8fba7702c2 100644 --- a/ui/vnc-auth-sasl.c +++ b/ui/vnc-auth-sasl.c @@ -31,7 +31,9 @@ void vnc_sasl_client_cleanup(VncState *vs) { if (vs->sasl.conn) { - vs->sasl.runSSF = vs->sasl.waitWriteSSF = vs->sasl.wantSSF = 0; + vs->sasl.runSSF = false; + vs->sasl.wantSSF = false; + vs->sasl.waitWriteSSF = 0; vs->sasl.encodedLength = vs->sasl.encodedOffset = 0; vs->sasl.encoded = NULL; g_free(vs->sasl.username); diff --git a/ui/vnc-auth-sasl.h b/ui/vnc-auth-sasl.h index fd9b18a8fe..ee243a9d64 100644 --- a/ui/vnc-auth-sasl.h +++ b/ui/vnc-auth-sasl.h @@ -37,9 +37,9 @@ typedef struct VncDisplaySASL VncDisplaySASL; struct VncStateSASL { sasl_conn_t *conn; /* If we want to negotiate an SSF layer with client */ - int wantSSF :1; + bool wantSSF; /* If we are now running the SSF layer */ - int runSSF :1; + bool runSSF; /* * If this is non-zero, then wait for that many bytes * to be written plain, before switching to SSF encoding diff --git a/ui/vnc-enc-hextile-template.h b/ui/vnc-enc-hextile-template.h index b9f9f5ef89..a7310e1947 100644 --- a/ui/vnc-enc-hextile-template.h +++ b/ui/vnc-enc-hextile-template.h @@ -175,6 +175,7 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs, /* we really don't have to invalidate either the bg or fg but we've lost the old values. oh well. */ } + break; default: break; } diff --git a/ui/vnc-jobs-async.c b/ui/vnc-jobs-async.c index 9b3016c129..087b84d319 100644 --- a/ui/vnc-jobs-async.c +++ b/ui/vnc-jobs-async.c @@ -28,6 +28,7 @@ #include "vnc.h" #include "vnc-jobs.h" +#include "qemu_socket.h" /* * Locking: @@ -155,6 +156,24 @@ void vnc_jobs_join(VncState *vs) qemu_cond_wait(&queue->cond, &queue->mutex); } vnc_unlock_queue(queue); + vnc_jobs_consume_buffer(vs); +} + +void vnc_jobs_consume_buffer(VncState *vs) +{ + bool flush; + + vnc_lock_output(vs); + if (vs->jobs_buffer.offset) { + vnc_write(vs, vs->jobs_buffer.buffer, vs->jobs_buffer.offset); + buffer_reset(&vs->jobs_buffer); + } + flush = vs->csock != -1 && vs->abort != true; + vnc_unlock_output(vs); + + if (flush) { + vnc_flush(vs); + } } /* @@ -197,7 +216,6 @@ static int vnc_worker_thread_loop(VncJobQueue *queue) VncState vs; int n_rectangles; int saved_offset; - bool flush; vnc_lock_queue(queue); while (QTAILQ_EMPTY(&queue->jobs) && !queue->exit) { @@ -213,6 +231,7 @@ static int vnc_worker_thread_loop(VncJobQueue *queue) vnc_lock_output(job->vs); if (job->vs->csock == -1 || job->vs->abort == true) { + vnc_unlock_output(job->vs); goto disconnected; } vnc_unlock_output(job->vs); @@ -233,10 +252,6 @@ static int vnc_worker_thread_loop(VncJobQueue *queue) if (job->vs->csock == -1) { vnc_unlock_display(job->vs->vd); - /* output mutex must be locked before going to - * disconnected: - */ - vnc_lock_output(job->vs); goto disconnected; } @@ -254,24 +269,19 @@ static int vnc_worker_thread_loop(VncJobQueue *queue) vs.output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF; vs.output.buffer[saved_offset + 1] = n_rectangles & 0xFF; - /* Switch back buffers */ vnc_lock_output(job->vs); - if (job->vs->csock == -1) { - goto disconnected; + if (job->vs->csock != -1) { + buffer_reserve(&job->vs->jobs_buffer, vs.output.offset); + buffer_append(&job->vs->jobs_buffer, vs.output.buffer, + vs.output.offset); + /* Copy persistent encoding data */ + vnc_async_encoding_end(job->vs, &vs); + + qemu_bh_schedule(job->vs->bh); } - - vnc_write(job->vs, vs.output.buffer, vs.output.offset); - -disconnected: - /* Copy persistent encoding data */ - vnc_async_encoding_end(job->vs, &vs); - flush = (job->vs->csock != -1 && job->vs->abort != true); vnc_unlock_output(job->vs); - if (flush) { - vnc_flush(job->vs); - } - +disconnected: vnc_lock_queue(queue); QTAILQ_REMOVE(&queue->jobs, job, next); vnc_unlock_queue(queue); diff --git a/ui/vnc-jobs.h b/ui/vnc-jobs.h index b8dab8169f..4c661f95e5 100644 --- a/ui/vnc-jobs.h +++ b/ui/vnc-jobs.h @@ -40,6 +40,7 @@ void vnc_jobs_join(VncState *vs); #ifdef CONFIG_VNC_THREAD +void vnc_jobs_consume_buffer(VncState *vs); void vnc_start_worker_thread(void); bool vnc_worker_thread_running(void); void vnc_stop_worker_thread(void); @@ -1068,7 +1068,10 @@ static void vnc_disconnect_finish(VncState *vs) #ifdef CONFIG_VNC_THREAD qemu_mutex_destroy(&vs->output_mutex); + qemu_bh_delete(vs->bh); + buffer_free(&vs->jobs_buffer); #endif + for (i = 0; i < VNC_STAT_ROWS; ++i) { g_free(vs->lossy_rect[i]); } @@ -1283,6 +1286,14 @@ static long vnc_client_read_plain(VncState *vs) return ret; } +#ifdef CONFIG_VNC_THREAD +static void vnc_jobs_bh(void *opaque) +{ + VncState *vs = opaque; + + vnc_jobs_consume_buffer(vs); +} +#endif /* * First function called whenever there is more data to be read from @@ -1936,7 +1947,10 @@ static void pixel_format_message (VncState *vs) { static void vnc_dpy_setdata(DisplayState *ds) { - /* We don't have to do anything */ + VncDisplay *vd = ds->opaque; + + *(vd->guest.ds) = *(ds->surface); + vnc_dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds)); } static void vnc_colordepth(VncState *vs) @@ -2548,6 +2562,9 @@ static int vnc_refresh_server_surface(VncDisplay *vd) * Update server dirty map. */ cmp_bytes = 16 * ds_get_bytes_per_pixel(vd->ds); + if (cmp_bytes > vd->ds->surface->linesize) { + cmp_bytes = vd->ds->surface->linesize; + } guest_row = vd->guest.ds->data; server_row = vd->server->data; for (y = 0; y < vd->guest.ds->height; y++) { @@ -2684,6 +2701,7 @@ static void vnc_connect(VncDisplay *vd, int csock, int skipauth) #ifdef CONFIG_VNC_THREAD qemu_mutex_init(&vs->output_mutex); + vs->bh = qemu_bh_new(vnc_jobs_bh, vs); #endif QTAILQ_INSERT_HEAD(&vd->clients, vs, next); @@ -304,6 +304,8 @@ struct VncState VncJob job; #else QemuMutex output_mutex; + QEMUBH *bh; + Buffer jobs_buffer; #endif /* Encoding specific, if you add something here, don't forget to |