diff options
-rw-r--r-- | block/curl.c | 24 | ||||
-rw-r--r-- | block/iscsi.c | 83 | ||||
-rw-r--r-- | block/nfs.c | 23 | ||||
-rw-r--r-- | hw/display/virtio-gpu-3d.c | 13 | ||||
-rw-r--r-- | include/ui/console.h | 21 | ||||
-rw-r--r-- | include/ui/gtk.h | 25 | ||||
-rw-r--r-- | include/ui/sdl2.h | 13 | ||||
-rw-r--r-- | ui/console.c | 30 | ||||
-rw-r--r-- | ui/gtk-egl.c | 25 | ||||
-rw-r--r-- | ui/gtk-gl-area.c | 12 | ||||
-rw-r--r-- | ui/gtk.c | 12 | ||||
-rw-r--r-- | ui/sdl.c | 10 | ||||
-rw-r--r-- | ui/sdl2-gl.c | 28 | ||||
-rw-r--r-- | ui/sdl2.c | 3 | ||||
-rw-r--r-- | ui/spice-core.c | 6 | ||||
-rw-r--r-- | ui/spice-display.c | 74 | ||||
-rw-r--r-- | ui/vnc.c | 3 |
17 files changed, 276 insertions, 129 deletions
diff --git a/block/curl.c b/block/curl.c index 2939cc77e9..e83dcd8f50 100644 --- a/block/curl.c +++ b/block/curl.c @@ -135,6 +135,7 @@ typedef struct BDRVCURLState { char *cookie; bool accept_range; AioContext *aio_context; + QemuMutex mutex; char *username; char *password; char *proxyusername; @@ -333,6 +334,7 @@ static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len, return FIND_RET_NONE; } +/* Called with s->mutex held. */ static void curl_multi_check_completion(BDRVCURLState *s) { int msgs_in_queue; @@ -374,7 +376,9 @@ static void curl_multi_check_completion(BDRVCURLState *s) continue; } + qemu_mutex_unlock(&s->mutex); acb->common.cb(acb->common.opaque, -EPROTO); + qemu_mutex_lock(&s->mutex); qemu_aio_unref(acb); state->acb[i] = NULL; } @@ -386,6 +390,7 @@ static void curl_multi_check_completion(BDRVCURLState *s) } } +/* Called with s->mutex held. */ static void curl_multi_do_locked(CURLState *s) { CURLSocket *socket, *next_socket; @@ -409,19 +414,19 @@ static void curl_multi_do(void *arg) { CURLState *s = (CURLState *)arg; - aio_context_acquire(s->s->aio_context); + qemu_mutex_lock(&s->s->mutex); curl_multi_do_locked(s); - aio_context_release(s->s->aio_context); + qemu_mutex_unlock(&s->s->mutex); } static void curl_multi_read(void *arg) { CURLState *s = (CURLState *)arg; - aio_context_acquire(s->s->aio_context); + qemu_mutex_lock(&s->s->mutex); curl_multi_do_locked(s); curl_multi_check_completion(s->s); - aio_context_release(s->s->aio_context); + qemu_mutex_unlock(&s->s->mutex); } static void curl_multi_timeout_do(void *arg) @@ -434,11 +439,11 @@ static void curl_multi_timeout_do(void *arg) return; } - aio_context_acquire(s->aio_context); + qemu_mutex_lock(&s->mutex); curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running); curl_multi_check_completion(s); - aio_context_release(s->aio_context); + qemu_mutex_unlock(&s->mutex); #else abort(); #endif @@ -771,6 +776,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, curl_easy_cleanup(state->curl); state->curl = NULL; + qemu_mutex_init(&s->mutex); curl_attach_aio_context(bs, bdrv_get_aio_context(bs)); qemu_opts_del(opts); @@ -801,12 +807,11 @@ static void curl_readv_bh_cb(void *p) CURLAIOCB *acb = p; BlockDriverState *bs = acb->common.bs; BDRVCURLState *s = bs->opaque; - AioContext *ctx = bdrv_get_aio_context(bs); size_t start = acb->sector_num * BDRV_SECTOR_SIZE; size_t end; - aio_context_acquire(ctx); + qemu_mutex_lock(&s->mutex); // In case we have the requested data already (e.g. read-ahead), // we can just call the callback and be done. @@ -854,7 +859,7 @@ static void curl_readv_bh_cb(void *p) curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running); out: - aio_context_release(ctx); + qemu_mutex_unlock(&s->mutex); if (ret != -EINPROGRESS) { acb->common.cb(acb->common.opaque, ret); qemu_aio_unref(acb); @@ -883,6 +888,7 @@ static void curl_close(BlockDriverState *bs) DPRINTF("CURL: Close\n"); curl_detach_aio_context(bs); + qemu_mutex_destroy(&s->mutex); g_free(s->cookie); g_free(s->url); diff --git a/block/iscsi.c b/block/iscsi.c index c4f813bfd2..76319a1a6e 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -58,6 +58,7 @@ typedef struct IscsiLun { int events; QEMUTimer *nop_timer; QEMUTimer *event_timer; + QemuMutex mutex; struct scsi_inquiry_logical_block_provisioning lbp; struct scsi_inquiry_block_limits bl; unsigned char *zeroblock; @@ -252,6 +253,7 @@ static int iscsi_translate_sense(struct scsi_sense *sense) return ret; } +/* Called (via iscsi_service) with QemuMutex held. */ static void iscsi_co_generic_cb(struct iscsi_context *iscsi, int status, void *command_data, void *opaque) @@ -352,6 +354,7 @@ static const AIOCBInfo iscsi_aiocb_info = { static void iscsi_process_read(void *arg); static void iscsi_process_write(void *arg); +/* Called with QemuMutex held. */ static void iscsi_set_events(IscsiLun *iscsilun) { @@ -395,10 +398,10 @@ iscsi_process_read(void *arg) IscsiLun *iscsilun = arg; struct iscsi_context *iscsi = iscsilun->iscsi; - aio_context_acquire(iscsilun->aio_context); + qemu_mutex_lock(&iscsilun->mutex); iscsi_service(iscsi, POLLIN); iscsi_set_events(iscsilun); - aio_context_release(iscsilun->aio_context); + qemu_mutex_unlock(&iscsilun->mutex); } static void @@ -407,10 +410,10 @@ iscsi_process_write(void *arg) IscsiLun *iscsilun = arg; struct iscsi_context *iscsi = iscsilun->iscsi; - aio_context_acquire(iscsilun->aio_context); + qemu_mutex_lock(&iscsilun->mutex); iscsi_service(iscsi, POLLOUT); iscsi_set_events(iscsilun); - aio_context_release(iscsilun->aio_context); + qemu_mutex_unlock(&iscsilun->mutex); } static int64_t sector_lun2qemu(int64_t sector, IscsiLun *iscsilun) @@ -589,6 +592,7 @@ iscsi_co_writev_flags(BlockDriverState *bs, int64_t sector_num, int nb_sectors, uint64_t lba; uint32_t num_sectors; bool fua = flags & BDRV_REQ_FUA; + int r = 0; if (fua) { assert(iscsilun->dpofua); @@ -604,6 +608,7 @@ iscsi_co_writev_flags(BlockDriverState *bs, int64_t sector_num, int nb_sectors, lba = sector_qemu2lun(sector_num, iscsilun); num_sectors = sector_qemu2lun(nb_sectors, iscsilun); iscsi_co_init_iscsitask(iscsilun, &iTask); + qemu_mutex_lock(&iscsilun->mutex); retry: if (iscsilun->use_16_for_rw) { #if LIBISCSI_API_VERSION >= (20160603) @@ -640,7 +645,9 @@ retry: #endif while (!iTask.complete) { iscsi_set_events(iscsilun); + qemu_mutex_unlock(&iscsilun->mutex); qemu_coroutine_yield(); + qemu_mutex_lock(&iscsilun->mutex); } if (iTask.task != NULL) { @@ -655,12 +662,15 @@ retry: if (iTask.status != SCSI_STATUS_GOOD) { iscsi_allocmap_set_invalid(iscsilun, sector_num, nb_sectors); - return iTask.err_code; + r = iTask.err_code; + goto out_unlock; } iscsi_allocmap_set_allocated(iscsilun, sector_num, nb_sectors); - return 0; +out_unlock: + qemu_mutex_unlock(&iscsilun->mutex); + return r; } @@ -693,18 +703,21 @@ static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs, goto out; } + qemu_mutex_lock(&iscsilun->mutex); retry: if (iscsi_get_lba_status_task(iscsilun->iscsi, iscsilun->lun, sector_qemu2lun(sector_num, iscsilun), 8 + 16, iscsi_co_generic_cb, &iTask) == NULL) { ret = -ENOMEM; - goto out; + goto out_unlock; } while (!iTask.complete) { iscsi_set_events(iscsilun); + qemu_mutex_unlock(&iscsilun->mutex); qemu_coroutine_yield(); + qemu_mutex_lock(&iscsilun->mutex); } if (iTask.do_retry) { @@ -721,20 +734,20 @@ retry: * because the device is busy or the cmd is not * supported) we pretend all blocks are allocated * for backwards compatibility */ - goto out; + goto out_unlock; } lbas = scsi_datain_unmarshall(iTask.task); if (lbas == NULL) { ret = -EIO; - goto out; + goto out_unlock; } lbasd = &lbas->descriptors[0]; if (sector_qemu2lun(sector_num, iscsilun) != lbasd->lba) { ret = -EIO; - goto out; + goto out_unlock; } *pnum = sector_lun2qemu(lbasd->num_blocks, iscsilun); @@ -756,6 +769,8 @@ retry: if (*pnum > nb_sectors) { *pnum = nb_sectors; } +out_unlock: + qemu_mutex_unlock(&iscsilun->mutex); out: if (iTask.task != NULL) { scsi_free_scsi_task(iTask.task); @@ -818,6 +833,7 @@ static int coroutine_fn iscsi_co_readv(BlockDriverState *bs, num_sectors = sector_qemu2lun(nb_sectors, iscsilun); iscsi_co_init_iscsitask(iscsilun, &iTask); + qemu_mutex_lock(&iscsilun->mutex); retry: if (iscsilun->use_16_for_rw) { #if LIBISCSI_API_VERSION >= (20160603) @@ -855,7 +871,9 @@ retry: #endif while (!iTask.complete) { iscsi_set_events(iscsilun); + qemu_mutex_unlock(&iscsilun->mutex); qemu_coroutine_yield(); + qemu_mutex_lock(&iscsilun->mutex); } if (iTask.task != NULL) { @@ -867,6 +885,7 @@ retry: iTask.complete = 0; goto retry; } + qemu_mutex_unlock(&iscsilun->mutex); if (iTask.status != SCSI_STATUS_GOOD) { return iTask.err_code; @@ -881,6 +900,7 @@ static int coroutine_fn iscsi_co_flush(BlockDriverState *bs) struct IscsiTask iTask; iscsi_co_init_iscsitask(iscsilun, &iTask); + qemu_mutex_lock(&iscsilun->mutex); retry: if (iscsi_synchronizecache10_task(iscsilun->iscsi, iscsilun->lun, 0, 0, 0, 0, iscsi_co_generic_cb, &iTask) == NULL) { @@ -889,7 +909,9 @@ retry: while (!iTask.complete) { iscsi_set_events(iscsilun); + qemu_mutex_unlock(&iscsilun->mutex); qemu_coroutine_yield(); + qemu_mutex_lock(&iscsilun->mutex); } if (iTask.task != NULL) { @@ -901,6 +923,7 @@ retry: iTask.complete = 0; goto retry; } + qemu_mutex_unlock(&iscsilun->mutex); if (iTask.status != SCSI_STATUS_GOOD) { return iTask.err_code; @@ -910,6 +933,7 @@ retry: } #ifdef __linux__ +/* Called (via iscsi_service) with QemuMutex held. */ static void iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status, void *command_data, void *opaque) @@ -1034,6 +1058,7 @@ static BlockAIOCB *iscsi_aio_ioctl(BlockDriverState *bs, acb->task->expxferlen = acb->ioh->dxfer_len; data.size = 0; + qemu_mutex_lock(&iscsilun->mutex); if (acb->task->xfer_dir == SCSI_XFER_WRITE) { if (acb->ioh->iovec_count == 0) { data.data = acb->ioh->dxferp; @@ -1049,6 +1074,7 @@ static BlockAIOCB *iscsi_aio_ioctl(BlockDriverState *bs, iscsi_aio_ioctl_cb, (data.size > 0) ? &data : NULL, acb) != 0) { + qemu_mutex_unlock(&iscsilun->mutex); scsi_free_scsi_task(acb->task); qemu_aio_unref(acb); return NULL; @@ -1068,6 +1094,7 @@ static BlockAIOCB *iscsi_aio_ioctl(BlockDriverState *bs, } iscsi_set_events(iscsilun); + qemu_mutex_unlock(&iscsilun->mutex); return &acb->common; } @@ -1092,6 +1119,7 @@ coroutine_fn iscsi_co_pdiscard(BlockDriverState *bs, int64_t offset, int count) IscsiLun *iscsilun = bs->opaque; struct IscsiTask iTask; struct unmap_list list; + int r = 0; if (!is_byte_request_lun_aligned(offset, count, iscsilun)) { return -ENOTSUP; @@ -1106,15 +1134,19 @@ coroutine_fn iscsi_co_pdiscard(BlockDriverState *bs, int64_t offset, int count) list.num = count / iscsilun->block_size; iscsi_co_init_iscsitask(iscsilun, &iTask); + qemu_mutex_lock(&iscsilun->mutex); retry: if (iscsi_unmap_task(iscsilun->iscsi, iscsilun->lun, 0, 0, &list, 1, iscsi_co_generic_cb, &iTask) == NULL) { - return -ENOMEM; + r = -ENOMEM; + goto out_unlock; } while (!iTask.complete) { iscsi_set_events(iscsilun); + qemu_mutex_unlock(&iscsilun->mutex); qemu_coroutine_yield(); + qemu_mutex_lock(&iscsilun->mutex); } if (iTask.task != NULL) { @@ -1131,17 +1163,20 @@ retry: /* the target might fail with a check condition if it is not happy with the alignment of the UNMAP request we silently fail in this case */ - return 0; + goto out_unlock; } if (iTask.status != SCSI_STATUS_GOOD) { - return iTask.err_code; + r = iTask.err_code; + goto out_unlock; } iscsi_allocmap_set_invalid(iscsilun, offset >> BDRV_SECTOR_BITS, count >> BDRV_SECTOR_BITS); - return 0; +out_unlock: + qemu_mutex_unlock(&iscsilun->mutex); + return r; } static int @@ -1153,6 +1188,7 @@ coroutine_fn iscsi_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, uint64_t lba; uint32_t nb_blocks; bool use_16_for_ws = iscsilun->use_16_for_rw; + int r = 0; if (!is_byte_request_lun_aligned(offset, count, iscsilun)) { return -ENOTSUP; @@ -1186,6 +1222,7 @@ coroutine_fn iscsi_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, } } + qemu_mutex_lock(&iscsilun->mutex); iscsi_co_init_iscsitask(iscsilun, &iTask); retry: if (use_16_for_ws) { @@ -1205,7 +1242,9 @@ retry: while (!iTask.complete) { iscsi_set_events(iscsilun); + qemu_mutex_unlock(&iscsilun->mutex); qemu_coroutine_yield(); + qemu_mutex_lock(&iscsilun->mutex); } if (iTask.status == SCSI_STATUS_CHECK_CONDITION && @@ -1215,7 +1254,8 @@ retry: /* WRITE SAME is not supported by the target */ iscsilun->has_write_same = false; scsi_free_scsi_task(iTask.task); - return -ENOTSUP; + r = -ENOTSUP; + goto out_unlock; } if (iTask.task != NULL) { @@ -1231,7 +1271,8 @@ retry: if (iTask.status != SCSI_STATUS_GOOD) { iscsi_allocmap_set_invalid(iscsilun, offset >> BDRV_SECTOR_BITS, count >> BDRV_SECTOR_BITS); - return iTask.err_code; + r = iTask.err_code; + goto out_unlock; } if (flags & BDRV_REQ_MAY_UNMAP) { @@ -1242,7 +1283,9 @@ retry: count >> BDRV_SECTOR_BITS); } - return 0; +out_unlock: + qemu_mutex_unlock(&iscsilun->mutex); + return r; } static void apply_chap(struct iscsi_context *iscsi, QemuOpts *opts, @@ -1331,7 +1374,7 @@ static void iscsi_nop_timed_event(void *opaque) { IscsiLun *iscsilun = opaque; - aio_context_acquire(iscsilun->aio_context); + qemu_mutex_lock(&iscsilun->mutex); if (iscsi_get_nops_in_flight(iscsilun->iscsi) >= MAX_NOP_FAILURES) { error_report("iSCSI: NOP timeout. Reconnecting..."); iscsilun->request_timed_out = true; @@ -1344,7 +1387,7 @@ static void iscsi_nop_timed_event(void *opaque) iscsi_set_events(iscsilun); out: - aio_context_release(iscsilun->aio_context); + qemu_mutex_unlock(&iscsilun->mutex); } static void iscsi_readcapacity_sync(IscsiLun *iscsilun, Error **errp) @@ -1890,6 +1933,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, scsi_free_scsi_task(task); task = NULL; + qemu_mutex_init(&iscsilun->mutex); iscsi_attach_aio_context(bs, iscsilun->aio_context); /* Guess the internal cluster (page) size of the iscsi target by the means @@ -1935,6 +1979,7 @@ static void iscsi_close(BlockDriverState *bs) iscsi_destroy_context(iscsi); g_free(iscsilun->zeroblock); iscsi_allocmap_free(iscsilun); + qemu_mutex_destroy(&iscsilun->mutex); memset(iscsilun, 0, sizeof(IscsiLun)); } diff --git a/block/nfs.c b/block/nfs.c index ffb54be065..890d5d4aff 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -54,6 +54,7 @@ typedef struct NFSClient { int events; bool has_zero_init; AioContext *aio_context; + QemuMutex mutex; blkcnt_t st_blocks; bool cache_used; NFSServer *server; @@ -191,6 +192,7 @@ static void nfs_parse_filename(const char *filename, QDict *options, static void nfs_process_read(void *arg); static void nfs_process_write(void *arg); +/* Called with QemuMutex held. */ static void nfs_set_events(NFSClient *client) { int ev = nfs_which_events(client->context); @@ -209,20 +211,20 @@ static void nfs_process_read(void *arg) { NFSClient *client = arg; - aio_context_acquire(client->aio_context); + qemu_mutex_lock(&client->mutex); nfs_service(client->context, POLLIN); nfs_set_events(client); - aio_context_release(client->aio_context); + qemu_mutex_unlock(&client->mutex); } static void nfs_process_write(void *arg) { NFSClient *client = arg; - aio_context_acquire(client->aio_context); + qemu_mutex_lock(&client->mutex); nfs_service(client->context, POLLOUT); nfs_set_events(client); - aio_context_release(client->aio_context); + qemu_mutex_unlock(&client->mutex); } static void nfs_co_init_task(BlockDriverState *bs, NFSRPC *task) @@ -242,6 +244,7 @@ static void nfs_co_generic_bh_cb(void *opaque) aio_co_wake(task->co); } +/* Called (via nfs_service) with QemuMutex held. */ static void nfs_co_generic_cb(int ret, struct nfs_context *nfs, void *data, void *private_data) @@ -273,12 +276,15 @@ static int coroutine_fn nfs_co_preadv(BlockDriverState *bs, uint64_t offset, nfs_co_init_task(bs, &task); task.iov = iov; + qemu_mutex_lock(&client->mutex); if (nfs_pread_async(client->context, client->fh, offset, bytes, nfs_co_generic_cb, &task) != 0) { + qemu_mutex_unlock(&client->mutex); return -ENOMEM; } nfs_set_events(client); + qemu_mutex_unlock(&client->mutex); while (!task.complete) { qemu_coroutine_yield(); } @@ -317,9 +323,11 @@ static int coroutine_fn nfs_co_pwritev(BlockDriverState *bs, uint64_t offset, buf = iov->iov[0].iov_base; } + qemu_mutex_lock(&client->mutex); if (nfs_pwrite_async(client->context, client->fh, offset, bytes, buf, nfs_co_generic_cb, &task) != 0) { + qemu_mutex_unlock(&client->mutex); if (my_buffer) { g_free(buf); } @@ -327,6 +335,7 @@ static int coroutine_fn nfs_co_pwritev(BlockDriverState *bs, uint64_t offset, } nfs_set_events(client); + qemu_mutex_unlock(&client->mutex); while (!task.complete) { qemu_coroutine_yield(); } @@ -349,12 +358,15 @@ static int coroutine_fn nfs_co_flush(BlockDriverState *bs) nfs_co_init_task(bs, &task); + qemu_mutex_lock(&client->mutex); if (nfs_fsync_async(client->context, client->fh, nfs_co_generic_cb, &task) != 0) { + qemu_mutex_unlock(&client->mutex); return -ENOMEM; } nfs_set_events(client); + qemu_mutex_unlock(&client->mutex); while (!task.complete) { qemu_coroutine_yield(); } @@ -440,6 +452,7 @@ static void nfs_file_close(BlockDriverState *bs) { NFSClient *client = bs->opaque; nfs_client_close(client); + qemu_mutex_destroy(&client->mutex); } static NFSServer *nfs_config(QDict *options, Error **errp) @@ -647,6 +660,7 @@ static int nfs_file_open(BlockDriverState *bs, QDict *options, int flags, if (ret < 0) { return ret; } + qemu_mutex_init(&client->mutex); bs->total_sectors = ret; ret = 0; return ret; @@ -702,6 +716,7 @@ static int nfs_has_zero_init(BlockDriverState *bs) return client->has_zero_init; } +/* Called (via nfs_service) with QemuMutex held. */ static void nfs_get_allocated_file_size_cb(int ret, struct nfs_context *nfs, void *data, void *private_data) diff --git a/hw/display/virtio-gpu-3d.c b/hw/display/virtio-gpu-3d.c index ecb09d17a1..f49b7fe8cd 100644 --- a/hw/display/virtio-gpu-3d.c +++ b/hw/display/virtio-gpu-3d.c @@ -177,16 +177,15 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g, qemu_console_resize(g->scanout[ss.scanout_id].con, ss.r.width, ss.r.height); virgl_renderer_force_ctx_0(); - dpy_gl_scanout(g->scanout[ss.scanout_id].con, info.tex_id, - info.flags & 1 /* FIXME: Y_0_TOP */, - info.width, info.height, - ss.r.x, ss.r.y, ss.r.width, ss.r.height); + dpy_gl_scanout_texture(g->scanout[ss.scanout_id].con, info.tex_id, + info.flags & 1 /* FIXME: Y_0_TOP */, + info.width, info.height, + ss.r.x, ss.r.y, ss.r.width, ss.r.height); } else { if (ss.scanout_id != 0) { dpy_gfx_replace_surface(g->scanout[ss.scanout_id].con, NULL); } - dpy_gl_scanout(g->scanout[ss.scanout_id].con, 0, false, - 0, 0, 0, 0, 0, 0); + dpy_gl_scanout_disable(g->scanout[ss.scanout_id].con); } g->scanout[ss.scanout_id].resource_id = ss.resource_id; } @@ -597,7 +596,7 @@ void virtio_gpu_virgl_reset(VirtIOGPU *g) if (i != 0) { dpy_gfx_replace_surface(g->scanout[i].con, NULL); } - dpy_gl_scanout(g->scanout[i].con, 0, false, 0, 0, 0, 0, 0, 0); + dpy_gl_scanout_disable(g->scanout[i].con); } } diff --git a/include/ui/console.h b/include/ui/console.h index af6350e96f..ac2895ca93 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -215,10 +215,14 @@ typedef struct DisplayChangeListenerOps { QEMUGLContext ctx); QEMUGLContext (*dpy_gl_ctx_get_current)(DisplayChangeListener *dcl); - void (*dpy_gl_scanout)(DisplayChangeListener *dcl, - uint32_t backing_id, bool backing_y_0_top, - uint32_t backing_width, uint32_t backing_height, - uint32_t x, uint32_t y, uint32_t w, uint32_t h); + void (*dpy_gl_scanout_disable)(DisplayChangeListener *dcl); + void (*dpy_gl_scanout_texture)(DisplayChangeListener *dcl, + uint32_t backing_id, + bool backing_y_0_top, + uint32_t backing_width, + uint32_t backing_height, + uint32_t x, uint32_t y, + uint32_t w, uint32_t h); void (*dpy_gl_update)(DisplayChangeListener *dcl, uint32_t x, uint32_t y, uint32_t w, uint32_t h); @@ -284,10 +288,11 @@ bool dpy_cursor_define_supported(QemuConsole *con); bool dpy_gfx_check_format(QemuConsole *con, pixman_format_code_t format); -void dpy_gl_scanout(QemuConsole *con, - uint32_t backing_id, bool backing_y_0_top, - uint32_t backing_width, uint32_t backing_height, - uint32_t x, uint32_t y, uint32_t w, uint32_t h); +void dpy_gl_scanout_disable(QemuConsole *con); +void dpy_gl_scanout_texture(QemuConsole *con, + uint32_t backing_id, bool backing_y_0_top, + uint32_t backing_width, uint32_t backing_height, + uint32_t x, uint32_t y, uint32_t w, uint32_t h); void dpy_gl_update(QemuConsole *con, uint32_t x, uint32_t y, uint32_t w, uint32_t h); diff --git a/include/ui/gtk.h b/include/ui/gtk.h index 47ffddb5b4..ca9a2268de 100644 --- a/include/ui/gtk.h +++ b/include/ui/gtk.h @@ -103,11 +103,14 @@ void gd_egl_switch(DisplayChangeListener *dcl, DisplaySurface *surface); QEMUGLContext gd_egl_create_context(DisplayChangeListener *dcl, QEMUGLParams *params); -void gd_egl_scanout(DisplayChangeListener *dcl, - uint32_t backing_id, bool backing_y_0_top, - uint32_t backing_width, uint32_t backing_height, - uint32_t x, uint32_t y, - uint32_t w, uint32_t h); +void gd_egl_scanout_disable(DisplayChangeListener *dcl); +void gd_egl_scanout_texture(DisplayChangeListener *dcl, + uint32_t backing_id, + bool backing_y_0_top, + uint32_t backing_width, + uint32_t backing_height, + uint32_t x, uint32_t y, + uint32_t w, uint32_t h); void gd_egl_scanout_flush(DisplayChangeListener *dcl, uint32_t x, uint32_t y, uint32_t w, uint32_t h); void gtk_egl_init(void); @@ -126,11 +129,13 @@ QEMUGLContext gd_gl_area_create_context(DisplayChangeListener *dcl, QEMUGLParams *params); void gd_gl_area_destroy_context(DisplayChangeListener *dcl, QEMUGLContext ctx); -void gd_gl_area_scanout(DisplayChangeListener *dcl, - uint32_t backing_id, bool backing_y_0_top, - uint32_t backing_width, uint32_t backing_height, - uint32_t x, uint32_t y, - uint32_t w, uint32_t h); +void gd_gl_area_scanout_texture(DisplayChangeListener *dcl, + uint32_t backing_id, + bool backing_y_0_top, + uint32_t backing_width, + uint32_t backing_height, + uint32_t x, uint32_t y, + uint32_t w, uint32_t h); void gd_gl_area_scanout_flush(DisplayChangeListener *dcl, uint32_t x, uint32_t y, uint32_t w, uint32_t h); void gtk_gl_area_init(void); diff --git a/include/ui/sdl2.h b/include/ui/sdl2.h index 683bb6af2e..aaf226c2c0 100644 --- a/include/ui/sdl2.h +++ b/include/ui/sdl2.h @@ -62,11 +62,14 @@ int sdl2_gl_make_context_current(DisplayChangeListener *dcl, QEMUGLContext ctx); QEMUGLContext sdl2_gl_get_current_context(DisplayChangeListener *dcl); -void sdl2_gl_scanout(DisplayChangeListener *dcl, - uint32_t backing_id, bool backing_y_0_top, - uint32_t backing_width, uint32_t backing_height, - uint32_t x, uint32_t y, - uint32_t w, uint32_t h); +void sdl2_gl_scanout_disable(DisplayChangeListener *dcl); +void sdl2_gl_scanout_texture(DisplayChangeListener *dcl, + uint32_t backing_id, + bool backing_y_0_top, + uint32_t backing_width, + uint32_t backing_height, + uint32_t x, uint32_t y, + uint32_t w, uint32_t h); void sdl2_gl_scanout_flush(DisplayChangeListener *dcl, uint32_t x, uint32_t y, uint32_t w, uint32_t h); diff --git a/ui/console.c b/ui/console.c index 49d0740b40..d1ff7504ec 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1735,16 +1735,30 @@ QEMUGLContext dpy_gl_ctx_get_current(QemuConsole *con) return con->gl->ops->dpy_gl_ctx_get_current(con->gl); } -void dpy_gl_scanout(QemuConsole *con, - uint32_t backing_id, bool backing_y_0_top, - uint32_t backing_width, uint32_t backing_height, - uint32_t x, uint32_t y, uint32_t width, uint32_t height) +void dpy_gl_scanout_disable(QemuConsole *con) { assert(con->gl); - con->gl->ops->dpy_gl_scanout(con->gl, backing_id, - backing_y_0_top, - backing_width, backing_height, - x, y, width, height); + if (con->gl->ops->dpy_gl_scanout_disable) { + con->gl->ops->dpy_gl_scanout_disable(con->gl); + } else { + con->gl->ops->dpy_gl_scanout_texture(con->gl, 0, false, 0, 0, + 0, 0, 0, 0); + } +} + +void dpy_gl_scanout_texture(QemuConsole *con, + uint32_t backing_id, + bool backing_y_0_top, + uint32_t backing_width, + uint32_t backing_height, + uint32_t x, uint32_t y, + uint32_t width, uint32_t height) +{ + assert(con->gl); + con->gl->ops->dpy_gl_scanout_texture(con->gl, backing_id, + backing_y_0_top, + backing_width, backing_height, + x, y, width, height); } void dpy_gl_update(QemuConsole *con, diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 3f5d328c7b..d53288f027 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -170,11 +170,21 @@ QEMUGLContext gd_egl_create_context(DisplayChangeListener *dcl, return qemu_egl_create_context(dcl, params); } -void gd_egl_scanout(DisplayChangeListener *dcl, - uint32_t backing_id, bool backing_y_0_top, - uint32_t backing_width, uint32_t backing_height, - uint32_t x, uint32_t y, - uint32_t w, uint32_t h) +void gd_egl_scanout_disable(DisplayChangeListener *dcl) +{ + VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); + + vc->gfx.w = 0; + vc->gfx.h = 0; + vc->gfx.tex_id = 0; + gtk_egl_set_scanout_mode(vc, false); +} + +void gd_egl_scanout_texture(DisplayChangeListener *dcl, + uint32_t backing_id, bool backing_y_0_top, + uint32_t backing_width, uint32_t backing_height, + uint32_t x, uint32_t y, + uint32_t w, uint32_t h) { VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); @@ -188,11 +198,6 @@ void gd_egl_scanout(DisplayChangeListener *dcl, eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, vc->gfx.esurface, vc->gfx.ectx); - if (vc->gfx.tex_id == 0 || vc->gfx.w == 0 || vc->gfx.h == 0) { - gtk_egl_set_scanout_mode(vc, false); - return; - } - gtk_egl_set_scanout_mode(vc, true); if (!vc->gfx.fbo_id) { glGenFramebuffers(1, &vc->gfx.fbo_id); diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 0df5a36a9f..b05c665cbb 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -167,11 +167,13 @@ void gd_gl_area_destroy_context(DisplayChangeListener *dcl, QEMUGLContext ctx) /* FIXME */ } -void gd_gl_area_scanout(DisplayChangeListener *dcl, - uint32_t backing_id, bool backing_y_0_top, - uint32_t backing_width, uint32_t backing_height, - uint32_t x, uint32_t y, - uint32_t w, uint32_t h) +void gd_gl_area_scanout_texture(DisplayChangeListener *dcl, + uint32_t backing_id, + bool backing_y_0_top, + uint32_t backing_width, + uint32_t backing_height, + uint32_t x, uint32_t y, + uint32_t w, uint32_t h) { VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); @@ -669,7 +669,7 @@ static const DisplayChangeListenerOps dcl_gl_area_ops = { .dpy_gl_ctx_destroy = gd_gl_area_destroy_context, .dpy_gl_ctx_make_current = gd_gl_area_make_current, .dpy_gl_ctx_get_current = gd_gl_area_get_current_context, - .dpy_gl_scanout = gd_gl_area_scanout, + .dpy_gl_scanout_texture = gd_gl_area_scanout_texture, .dpy_gl_update = gd_gl_area_scanout_flush, }; @@ -688,7 +688,8 @@ static const DisplayChangeListenerOps dcl_egl_ops = { .dpy_gl_ctx_destroy = qemu_egl_destroy_context, .dpy_gl_ctx_make_current = gd_egl_make_current, .dpy_gl_ctx_get_current = qemu_egl_get_current_context, - .dpy_gl_scanout = gd_egl_scanout, + .dpy_gl_scanout_disable = gd_egl_scanout_disable, + .dpy_gl_scanout_texture = gd_egl_scanout_texture, .dpy_gl_update = gd_egl_scanout_flush, }; @@ -2200,11 +2201,12 @@ static void gd_set_keycode_type(GtkDisplayState *s) GdkDisplay *display = gtk_widget_get_display(s->window); if (GDK_IS_X11_DISPLAY(display)) { Display *x11_display = gdk_x11_display_get_xdisplay(display); - XkbDescPtr desc = XkbGetKeyboard(x11_display, XkbGBN_AllComponentsMask, - XkbUseCoreKbd); + XkbDescPtr desc = XkbGetMap(x11_display, XkbGBN_AllComponentsMask, + XkbUseCoreKbd); char *keycodes = NULL; - if (desc && desc->names) { + if (desc && + (XkbGetNames(x11_display, XkbKeycodesNameMask, desc) == Success)) { keycodes = XGetAtomName(x11_display, desc->names->keycodes); } if (keycodes == NULL) { @@ -233,10 +233,12 @@ static int check_for_evdev(void) if (!SDL_GetWMInfo(&info)) { return 0; } - desc = XkbGetKeyboard(info.info.x11.display, - XkbGBN_AllComponentsMask, - XkbUseCoreKbd); - if (desc && desc->names) { + desc = XkbGetMap(info.info.x11.display, + XkbGBN_AllComponentsMask, + XkbUseCoreKbd); + if (desc && + (XkbGetNames(info.info.x11.display, + XkbKeycodesNameMask, desc) == Success)) { keycodes = XGetAtomName(info.info.x11.display, desc->names->keycodes); if (keycodes == NULL) { fprintf(stderr, "could not lookup keycode name\n"); diff --git a/ui/sdl2-gl.c b/ui/sdl2-gl.c index 039645df3e..1cd77e2c16 100644 --- a/ui/sdl2-gl.c +++ b/ui/sdl2-gl.c @@ -184,11 +184,24 @@ QEMUGLContext sdl2_gl_get_current_context(DisplayChangeListener *dcl) return (QEMUGLContext)sdlctx; } -void sdl2_gl_scanout(DisplayChangeListener *dcl, - uint32_t backing_id, bool backing_y_0_top, - uint32_t backing_width, uint32_t backing_height, - uint32_t x, uint32_t y, - uint32_t w, uint32_t h) +void sdl2_gl_scanout_disable(DisplayChangeListener *dcl) +{ + struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl); + + assert(scon->opengl); + scon->w = 0; + scon->h = 0; + scon->tex_id = 0; + sdl2_set_scanout_mode(scon, false); +} + +void sdl2_gl_scanout_texture(DisplayChangeListener *dcl, + uint32_t backing_id, + bool backing_y_0_top, + uint32_t backing_width, + uint32_t backing_height, + uint32_t x, uint32_t y, + uint32_t w, uint32_t h) { struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl); @@ -202,11 +215,6 @@ void sdl2_gl_scanout(DisplayChangeListener *dcl, SDL_GL_MakeCurrent(scon->real_window, scon->winctx); - if (scon->tex_id == 0 || scon->w == 0 || scon->h == 0) { - sdl2_set_scanout_mode(scon, false); - return; - } - sdl2_set_scanout_mode(scon, true); if (!scon->fbo_id) { glGenFramebuffers(1, &scon->fbo_id); @@ -733,7 +733,8 @@ static const DisplayChangeListenerOps dcl_gl_ops = { .dpy_gl_ctx_destroy = sdl2_gl_destroy_context, .dpy_gl_ctx_make_current = sdl2_gl_make_context_current, .dpy_gl_ctx_get_current = sdl2_gl_get_current_context, - .dpy_gl_scanout = sdl2_gl_scanout, + .dpy_gl_scanout_disable = sdl2_gl_scanout_disable, + .dpy_gl_scanout_texture = sdl2_gl_scanout_texture, .dpy_gl_update = sdl2_gl_scanout_flush, }; #endif diff --git a/ui/spice-core.c b/ui/spice-core.c index 39ccab7561..804abc5c0f 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -497,6 +497,12 @@ static QemuOptsList qemu_spice_opts = { },{ .name = "seamless-migration", .type = QEMU_OPT_BOOL, + },{ + .name = "display", + .type = QEMU_OPT_STRING, + },{ + .name = "head", + .type = QEMU_OPT_NUMBER, #ifdef HAVE_SPICE_GL },{ .name = "gl", diff --git a/ui/spice-display.c b/ui/spice-display.c index 64e472eeb0..b353445f58 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -928,39 +928,44 @@ static QEMUGLContext qemu_spice_gl_create_context(DisplayChangeListener *dcl, return qemu_egl_create_context(dcl, params); } -static void qemu_spice_gl_scanout(DisplayChangeListener *dcl, - uint32_t tex_id, - bool y_0_top, - uint32_t backing_width, - uint32_t backing_height, - uint32_t x, uint32_t y, - uint32_t w, uint32_t h) +static void qemu_spice_gl_scanout_disable(DisplayChangeListener *dcl) +{ + SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); + + dprint(1, "%s: no framebuffer\n", __func__); + spice_qxl_gl_scanout(&ssd->qxl, -1, 0, 0, 0, 0, false); + qemu_spice_gl_monitor_config(ssd, 0, 0, 0, 0); + ssd->have_surface = false; + ssd->have_scanout = false; +} + +static void qemu_spice_gl_scanout_texture(DisplayChangeListener *dcl, + uint32_t tex_id, + bool y_0_top, + uint32_t backing_width, + uint32_t backing_height, + uint32_t x, uint32_t y, + uint32_t w, uint32_t h) { SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); EGLint stride = 0, fourcc = 0; int fd = -1; - if (tex_id) { - fd = egl_get_fd_for_texture(tex_id, &stride, &fourcc); - if (fd < 0) { - fprintf(stderr, "%s: failed to get fd for texture\n", __func__); - return; - } - dprint(1, "%s: %dx%d (stride %d, fourcc 0x%x)\n", __func__, - w, h, stride, fourcc); - } else { - dprint(1, "%s: no texture (no framebuffer)\n", __func__); + assert(tex_id); + fd = egl_get_fd_for_texture(tex_id, &stride, &fourcc); + if (fd < 0) { + fprintf(stderr, "%s: failed to get fd for texture\n", __func__); + return; } - - assert(!tex_id || fd >= 0); + dprint(1, "%s: %dx%d (stride %d, fourcc 0x%x)\n", __func__, + w, h, stride, fourcc); /* note: spice server will close the fd */ spice_qxl_gl_scanout(&ssd->qxl, fd, backing_width, backing_height, stride, fourcc, y_0_top); - ssd->have_surface = false; - ssd->have_scanout = (tex_id != 0); - qemu_spice_gl_monitor_config(ssd, x, y, w, h); + ssd->have_surface = false; + ssd->have_scanout = true; } static void qemu_spice_gl_update(DisplayChangeListener *dcl, @@ -993,7 +998,8 @@ static const DisplayChangeListenerOps display_listener_gl_ops = { .dpy_gl_ctx_make_current = qemu_egl_make_context_current, .dpy_gl_ctx_get_current = qemu_egl_get_current_context, - .dpy_gl_scanout = qemu_spice_gl_scanout, + .dpy_gl_scanout_disable = qemu_spice_gl_scanout_disable, + .dpy_gl_scanout_texture = qemu_spice_gl_scanout_texture, .dpy_gl_update = qemu_spice_gl_update, }; @@ -1029,9 +1035,26 @@ static void qemu_spice_display_init_one(QemuConsole *con) void qemu_spice_display_init(void) { - QemuConsole *con; + QemuOptsList *olist = qemu_find_opts("spice"); + QemuOpts *opts = QTAILQ_FIRST(&olist->head); + QemuConsole *spice_con, *con; + const char *str; int i; + str = qemu_opt_get(opts, "display"); + if (str) { + int head = qemu_opt_get_number(opts, "head", 0); + Error *err = NULL; + + spice_con = qemu_console_lookup_by_device_name(str, head, &err); + if (err) { + error_report("Failed to lookup display/head"); + exit(1); + } + } else { + spice_con = NULL; + } + for (i = 0;; i++) { con = qemu_console_lookup_by_index(i); if (!con || !qemu_console_is_graphic(con)) { @@ -1040,6 +1063,9 @@ void qemu_spice_display_init(void) if (qemu_spice_have_display_interface(con)) { continue; } + if (spice_con != NULL && spice_con != con) { + continue; + } qemu_spice_display_init_one(con); } } @@ -3181,6 +3181,7 @@ static void vnc_display_close(VncDisplay *vd) g_free(vd->lsock); g_free(vd->lsock_tag); vd->lsock = NULL; + vd->lsock_tag = NULL; vd->nlsock = 0; for (i = 0; i < vd->nlwebsock; i++) { @@ -3192,6 +3193,7 @@ static void vnc_display_close(VncDisplay *vd) g_free(vd->lwebsock); g_free(vd->lwebsock_tag); vd->lwebsock = NULL; + vd->lwebsock_tag = NULL; vd->nlwebsock = 0; vd->auth = VNC_AUTH_INVALID; @@ -3204,6 +3206,7 @@ static void vnc_display_close(VncDisplay *vd) vd->tlsaclname = NULL; if (vd->lock_key_sync) { qemu_remove_led_event_handler(vd->led); + vd->led = NULL; } } |