From bb756eebdac6fd24e8919e2c43f7d2c8c4091f59 Mon Sep 17 00:00:00 2001 From: RajithaY Date: Tue, 25 Apr 2017 03:31:15 -0700 Subject: Adding qemu as a submodule of KVMFORNFV This Patch includes the changes to add qemu as a submodule to kvmfornfv repo and make use of the updated latest qemu for the execution of all testcase Change-Id: I1280af507a857675c7f81d30c95255635667bdd7 Signed-off-by:RajithaY --- qemu/ui/spice-display.c | 936 ------------------------------------------------ 1 file changed, 936 deletions(-) delete mode 100644 qemu/ui/spice-display.c (limited to 'qemu/ui/spice-display.c') diff --git a/qemu/ui/spice-display.c b/qemu/ui/spice-display.c deleted file mode 100644 index 242ab5f46..000000000 --- a/qemu/ui/spice-display.c +++ /dev/null @@ -1,936 +0,0 @@ -/* - * 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 . - */ - -#include "qemu/osdep.h" -#include "qemu-common.h" -#include "ui/qemu-spice.h" -#include "qemu/timer.h" -#include "qemu/queue.h" -#include "ui/console.h" -#include "sysemu/sysemu.h" -#include "trace.h" - -#include "ui/spice-display.h" - -static int debug = 0; - -static void GCC_FMT_ATTR(2, 3) dprint(int level, const char *fmt, ...) -{ - va_list args; - - if (level <= debug) { - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); - } -} - -int qemu_spice_rect_is_empty(const QXLRect* r) -{ - return r->top == r->bottom || r->left == r->right; -} - -void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r) -{ - if (qemu_spice_rect_is_empty(r)) { - return; - } - - if (qemu_spice_rect_is_empty(dest)) { - *dest = *r; - return; - } - - dest->top = MIN(dest->top, r->top); - dest->left = MIN(dest->left, r->left); - dest->bottom = MAX(dest->bottom, r->bottom); - 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) { - spice_qxl_add_memslot_async(&ssd->qxl, memslot, - (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO, - QXL_IO_MEMSLOT_ADD_ASYNC)); - } else { - spice_qxl_add_memslot(&ssd->qxl, memslot); - } -} - -void qemu_spice_del_memslot(SimpleSpiceDisplay *ssd, uint32_t gid, uint32_t sid) -{ - trace_qemu_spice_del_memslot(ssd->qxl.id, gid, sid); - spice_qxl_del_memslot(&ssd->qxl, gid, sid); -} - -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) { - spice_qxl_create_primary_surface_async(&ssd->qxl, id, surface, - (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO, - QXL_IO_CREATE_PRIMARY_ASYNC)); - } else { - spice_qxl_create_primary_surface(&ssd->qxl, 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) { - spice_qxl_destroy_primary_surface_async(&ssd->qxl, id, - (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO, - QXL_IO_DESTROY_PRIMARY_ASYNC)); - } else { - spice_qxl_destroy_primary_surface(&ssd->qxl, id); - } -} - -void qemu_spice_wakeup(SimpleSpiceDisplay *ssd) -{ - trace_qemu_spice_wakeup(ssd->qxl.id); - spice_qxl_wakeup(&ssd->qxl); -} - -static void qemu_spice_create_one_update(SimpleSpiceDisplay *ssd, - QXLRect *rect) -{ - SimpleSpiceUpdate *update; - QXLDrawable *drawable; - QXLImage *image; - QXLCommand *cmd; - int bw, bh; - struct timespec time_space; - pixman_image_t *dest; - - trace_qemu_spice_create_update( - rect->left, rect->right, - rect->top, rect->bottom); - - update = g_malloc0(sizeof(*update)); - drawable = &update->drawable; - image = &update->image; - cmd = &update->ext.cmd; - - bw = rect->right - rect->left; - bh = rect->bottom - rect->top; - update->bitmap = g_malloc(bw * bh * 4); - - drawable->bbox = *rect; - drawable->clip.type = SPICE_CLIP_TYPE_NONE; - drawable->effect = QXL_EFFECT_OPAQUE; - drawable->release_info.id = (uintptr_t)(&update->ext); - drawable->type = QXL_DRAW_COPY; - drawable->surfaces_dest[0] = -1; - drawable->surfaces_dest[1] = -1; - drawable->surfaces_dest[2] = -1; - clock_gettime(CLOCK_MONOTONIC, &time_space); - /* time in milliseconds from epoch. */ - drawable->mm_time = time_space.tv_sec * 1000 - + time_space.tv_nsec / 1000 / 1000; - - drawable->u.copy.rop_descriptor = SPICE_ROPD_OP_PUT; - drawable->u.copy.src_bitmap = (uintptr_t)image; - drawable->u.copy.src_area.right = bw; - drawable->u.copy.src_area.bottom = bh; - - QXL_SET_IMAGE_ID(image, QXL_IMAGE_GROUP_DEVICE, ssd->unique++); - image->descriptor.type = SPICE_IMAGE_TYPE_BITMAP; - image->bitmap.flags = QXL_BITMAP_DIRECT | QXL_BITMAP_TOP_DOWN; - image->bitmap.stride = bw * 4; - image->descriptor.width = image->bitmap.x = bw; - image->descriptor.height = image->bitmap.y = bh; - image->bitmap.data = (uintptr_t)(update->bitmap); - image->bitmap.palette = 0; - image->bitmap.format = SPICE_BITMAP_FMT_32BIT; - - dest = pixman_image_create_bits(PIXMAN_LE_x8r8g8b8, bw, bh, - (void *)update->bitmap, bw * 4); - pixman_image_composite(PIXMAN_OP_SRC, ssd->surface, NULL, ssd->mirror, - rect->left, rect->top, 0, 0, - rect->left, rect->top, bw, bh); - pixman_image_composite(PIXMAN_OP_SRC, ssd->mirror, NULL, dest, - rect->left, rect->top, 0, 0, - 0, 0, bw, bh); - pixman_image_unref(dest); - - cmd->type = QXL_CMD_DRAW; - cmd->data = (uintptr_t)drawable; - - QTAILQ_INSERT_TAIL(&ssd->updates, update, next); -} - -static void qemu_spice_create_update(SimpleSpiceDisplay *ssd) -{ - static const int blksize = 32; - int blocks = (surface_width(ssd->ds) + blksize - 1) / blksize; - int dirty_top[blocks]; - int y, yoff1, yoff2, x, xoff, blk, bw; - int bpp = surface_bytes_per_pixel(ssd->ds); - uint8_t *guest, *mirror; - - if (qemu_spice_rect_is_empty(&ssd->dirty)) { - return; - }; - - for (blk = 0; blk < blocks; blk++) { - dirty_top[blk] = -1; - } - - guest = surface_data(ssd->ds); - mirror = (void *)pixman_image_get_data(ssd->mirror); - for (y = ssd->dirty.top; y < ssd->dirty.bottom; y++) { - yoff1 = y * surface_stride(ssd->ds); - yoff2 = y * pixman_image_get_stride(ssd->mirror); - for (x = ssd->dirty.left; x < ssd->dirty.right; x += blksize) { - xoff = x * bpp; - blk = x / blksize; - bw = MIN(blksize, ssd->dirty.right - x); - if (memcmp(guest + yoff1 + xoff, - mirror + yoff2 + xoff, - bw * bpp) == 0) { - if (dirty_top[blk] != -1) { - QXLRect update = { - .top = dirty_top[blk], - .bottom = y, - .left = x, - .right = x + bw, - }; - qemu_spice_create_one_update(ssd, &update); - dirty_top[blk] = -1; - } - } else { - if (dirty_top[blk] == -1) { - dirty_top[blk] = y; - } - } - } - } - - for (x = ssd->dirty.left; x < ssd->dirty.right; x += blksize) { - blk = x / blksize; - bw = MIN(blksize, ssd->dirty.right - x); - if (dirty_top[blk] != -1) { - QXLRect update = { - .top = dirty_top[blk], - .bottom = ssd->dirty.bottom, - .left = x, - .right = x + bw, - }; - qemu_spice_create_one_update(ssd, &update); - dirty_top[blk] = -1; - } - } - - memset(&ssd->dirty, 0, sizeof(ssd->dirty)); -} - -static SimpleSpiceCursor* -qemu_spice_create_cursor_update(SimpleSpiceDisplay *ssd, - QEMUCursor *c, - int on) -{ - size_t size = c ? c->width * c->height * 4 : 0; - SimpleSpiceCursor *update; - QXLCursorCmd *ccmd; - QXLCursor *cursor; - QXLCommand *cmd; - - update = g_malloc0(sizeof(*update) + size); - ccmd = &update->cmd; - cursor = &update->cursor; - cmd = &update->ext.cmd; - - if (c) { - ccmd->type = QXL_CURSOR_SET; - ccmd->u.set.position.x = ssd->ptr_x + ssd->hot_x; - ccmd->u.set.position.y = ssd->ptr_y + ssd->hot_y; - ccmd->u.set.visible = true; - ccmd->u.set.shape = (uintptr_t)cursor; - cursor->header.unique = ssd->unique++; - cursor->header.type = SPICE_CURSOR_TYPE_ALPHA; - cursor->header.width = c->width; - cursor->header.height = c->height; - cursor->header.hot_spot_x = c->hot_x; - cursor->header.hot_spot_y = c->hot_y; - cursor->data_size = size; - cursor->chunk.data_size = size; - memcpy(cursor->chunk.data, c->data, size); - } else if (!on) { - ccmd->type = QXL_CURSOR_HIDE; - } else { - ccmd->type = QXL_CURSOR_MOVE; - ccmd->u.position.x = ssd->ptr_x + ssd->hot_x; - ccmd->u.position.y = ssd->ptr_y + ssd->hot_y; - } - ccmd->release_info.id = (uintptr_t)(&update->ext); - - cmd->type = QXL_CMD_CURSOR; - cmd->data = (uintptr_t)ccmd; - - return update; -} - -/* - * Called from spice server thread context (via interface_release_resource) - * We do *not* hold the global qemu mutex here, so extra care is needed - * when calling qemu functions. QEMU interfaces used: - * - g_free (underlying glibc free is re-entrant). - */ -void qemu_spice_destroy_update(SimpleSpiceDisplay *sdpy, SimpleSpiceUpdate *update) -{ - g_free(update->bitmap); - g_free(update); -} - -void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd) -{ - QXLDevMemSlot memslot; - - dprint(1, "%s/%d:\n", __func__, ssd->qxl.id); - - memset(&memslot, 0, sizeof(memslot)); - memslot.slot_group_id = MEMSLOT_GROUP_HOST; - memslot.virt_end = ~0; - qemu_spice_add_memslot(ssd, &memslot, QXL_SYNC); -} - -void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd) -{ - QXLDevSurfaceCreate surface; - uint64_t surface_size; - - memset(&surface, 0, sizeof(surface)); - - surface_size = (uint64_t) surface_width(ssd->ds) * - surface_height(ssd->ds) * 4; - assert(surface_size > 0); - assert(surface_size < INT_MAX); - if (ssd->bufsize < surface_size) { - ssd->bufsize = surface_size; - g_free(ssd->buf); - ssd->buf = g_malloc(ssd->bufsize); - } - - dprint(1, "%s/%d: %ux%u (size %" PRIu64 "/%d)\n", __func__, ssd->qxl.id, - surface_width(ssd->ds), surface_height(ssd->ds), - surface_size, ssd->bufsize); - - surface.format = SPICE_SURFACE_FMT_32_xRGB; - surface.width = surface_width(ssd->ds); - surface.height = surface_height(ssd->ds); - surface.stride = -surface.width * 4; - surface.mouse_mode = true; - surface.flags = 0; - surface.type = 0; - surface.mem = (uintptr_t)ssd->buf; - surface.group_id = MEMSLOT_GROUP_HOST; - - qemu_spice_create_primary_surface(ssd, 0, &surface, QXL_SYNC); -} - -void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd) -{ - dprint(1, "%s/%d:\n", __func__, ssd->qxl.id); - - qemu_spice_destroy_primary_surface(ssd, 0, QXL_SYNC); -} - -void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd) -{ - qemu_mutex_init(&ssd->lock); - QTAILQ_INIT(&ssd->updates); - ssd->mouse_x = -1; - ssd->mouse_y = -1; - if (ssd->num_surfaces == 0) { - ssd->num_surfaces = 1024; - } -} - -/* display listener callbacks */ - -void qemu_spice_display_update(SimpleSpiceDisplay *ssd, - int x, int y, int w, int h) -{ - QXLRect update_area; - - dprint(2, "%s/%d: x %d y %d w %d h %d\n", __func__, - ssd->qxl.id, x, y, w, h); - update_area.left = x, - update_area.right = x + w; - update_area.top = y; - update_area.bottom = y + h; - - if (qemu_spice_rect_is_empty(&ssd->dirty)) { - ssd->notify++; - } - qemu_spice_rect_union(&ssd->dirty, &update_area); -} - -void qemu_spice_display_switch(SimpleSpiceDisplay *ssd, - DisplaySurface *surface) -{ - SimpleSpiceUpdate *update; - bool need_destroy; - - if (surface && ssd->surface && - surface_width(surface) == pixman_image_get_width(ssd->surface) && - surface_height(surface) == pixman_image_get_height(ssd->surface) && - surface_format(surface) == pixman_image_get_format(ssd->surface)) { - /* no-resize fast path: just swap backing store */ - dprint(1, "%s/%d: fast (%dx%d)\n", __func__, ssd->qxl.id, - surface_width(surface), surface_height(surface)); - qemu_mutex_lock(&ssd->lock); - ssd->ds = surface; - pixman_image_unref(ssd->surface); - ssd->surface = pixman_image_ref(ssd->ds->image); - qemu_mutex_unlock(&ssd->lock); - qemu_spice_display_update(ssd, 0, 0, - surface_width(surface), - surface_height(surface)); - return; - } - - /* full mode switch */ - dprint(1, "%s/%d: full (%dx%d -> %dx%d)\n", __func__, ssd->qxl.id, - ssd->surface ? pixman_image_get_width(ssd->surface) : 0, - ssd->surface ? pixman_image_get_height(ssd->surface) : 0, - surface ? surface_width(surface) : 0, - surface ? surface_height(surface) : 0); - - memset(&ssd->dirty, 0, sizeof(ssd->dirty)); - if (ssd->surface) { - pixman_image_unref(ssd->surface); - ssd->surface = NULL; - pixman_image_unref(ssd->mirror); - ssd->mirror = NULL; - } - - qemu_mutex_lock(&ssd->lock); - need_destroy = (ssd->ds != NULL); - ssd->ds = surface; - while ((update = QTAILQ_FIRST(&ssd->updates)) != NULL) { - QTAILQ_REMOVE(&ssd->updates, update, next); - qemu_spice_destroy_update(ssd, update); - } - qemu_mutex_unlock(&ssd->lock); - if (need_destroy) { - qemu_spice_destroy_host_primary(ssd); - } - if (ssd->ds) { - ssd->surface = pixman_image_ref(ssd->ds->image); - ssd->mirror = qemu_pixman_mirror_create(ssd->ds->format, - ssd->ds->image); - qemu_spice_create_host_primary(ssd); - } - - memset(&ssd->dirty, 0, sizeof(ssd->dirty)); - ssd->notify++; - - qemu_mutex_lock(&ssd->lock); - if (ssd->cursor) { - g_free(ssd->ptr_define); - ssd->ptr_define = qemu_spice_create_cursor_update(ssd, ssd->cursor, 0); - } - qemu_mutex_unlock(&ssd->lock); -} - -static void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd) -{ - if (ssd->cursor) { - assert(ssd->dcl.con); - dpy_cursor_define(ssd->dcl.con, ssd->cursor); - } - if (ssd->mouse_x != -1 && ssd->mouse_y != -1) { - assert(ssd->dcl.con); - dpy_mouse_set(ssd->dcl.con, ssd->mouse_x, ssd->mouse_y, 1); - ssd->mouse_x = -1; - ssd->mouse_y = -1; - } -} - -void qemu_spice_cursor_refresh_bh(void *opaque) -{ - SimpleSpiceDisplay *ssd = opaque; - - qemu_mutex_lock(&ssd->lock); - qemu_spice_cursor_refresh_unlocked(ssd); - qemu_mutex_unlock(&ssd->lock); -} - -void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd) -{ - dprint(3, "%s/%d:\n", __func__, ssd->qxl.id); - graphic_hw_update(ssd->dcl.con); - - qemu_mutex_lock(&ssd->lock); - if (QTAILQ_EMPTY(&ssd->updates) && ssd->ds) { - qemu_spice_create_update(ssd); - ssd->notify++; - } - qemu_mutex_unlock(&ssd->lock); - - if (ssd->notify) { - ssd->notify = 0; - qemu_spice_wakeup(ssd); - dprint(2, "%s/%d: notify\n", __func__, ssd->qxl.id); - } -} - -/* spice display interface callbacks */ - -static void interface_attach_worker(QXLInstance *sin, QXLWorker *qxl_worker) -{ - SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl); - - dprint(1, "%s/%d:\n", __func__, ssd->qxl.id); - ssd->worker = qxl_worker; -} - -static void interface_set_compression_level(QXLInstance *sin, int level) -{ - dprint(1, "%s/%d:\n", __func__, sin->id); - /* nothing to do */ -} - -static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time) -{ - dprint(3, "%s/%d:\n", __func__, sin->id); - /* nothing to do */ -} - -static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info) -{ - SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl); - - info->memslot_gen_bits = MEMSLOT_GENERATION_BITS; - info->memslot_id_bits = MEMSLOT_SLOT_BITS; - info->num_memslots = NUM_MEMSLOTS; - info->num_memslots_groups = NUM_MEMSLOTS_GROUPS; - info->internal_groupslot_id = 0; - info->qxl_ram_size = 16 * 1024 * 1024; - info->n_surfaces = ssd->num_surfaces; -} - -static int interface_get_command(QXLInstance *sin, QXLCommandExt *ext) -{ - SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl); - SimpleSpiceUpdate *update; - int ret = false; - - dprint(3, "%s/%d:\n", __func__, ssd->qxl.id); - - qemu_mutex_lock(&ssd->lock); - update = QTAILQ_FIRST(&ssd->updates); - if (update != NULL) { - QTAILQ_REMOVE(&ssd->updates, update, next); - *ext = update->ext; - ret = true; - } - qemu_mutex_unlock(&ssd->lock); - - return ret; -} - -static int interface_req_cmd_notification(QXLInstance *sin) -{ - dprint(2, "%s/%d:\n", __func__, sin->id); - return 1; -} - -static void interface_release_resource(QXLInstance *sin, - QXLReleaseInfoExt rext) -{ - SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl); - SimpleSpiceUpdate *update; - SimpleSpiceCursor *cursor; - QXLCommandExt *ext; - - dprint(2, "%s/%d:\n", __func__, ssd->qxl.id); - ext = (void *)(intptr_t)(rext.info->id); - switch (ext->cmd.type) { - case QXL_CMD_DRAW: - update = container_of(ext, SimpleSpiceUpdate, ext); - qemu_spice_destroy_update(ssd, update); - break; - case QXL_CMD_CURSOR: - cursor = container_of(ext, SimpleSpiceCursor, ext); - g_free(cursor); - break; - default: - g_assert_not_reached(); - } -} - -static int interface_get_cursor_command(QXLInstance *sin, QXLCommandExt *ext) -{ - SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl); - int ret; - - dprint(3, "%s/%d:\n", __func__, ssd->qxl.id); - - qemu_mutex_lock(&ssd->lock); - if (ssd->ptr_define) { - *ext = ssd->ptr_define->ext; - ssd->ptr_define = NULL; - ret = true; - } else if (ssd->ptr_move) { - *ext = ssd->ptr_move->ext; - ssd->ptr_move = NULL; - ret = true; - } else { - ret = false; - } - qemu_mutex_unlock(&ssd->lock); - return ret; -} - -static int interface_req_cursor_notification(QXLInstance *sin) -{ - dprint(2, "%s:\n", __func__); - return 1; -} - -static void interface_notify_update(QXLInstance *sin, uint32_t update_id) -{ - fprintf(stderr, "%s: abort()\n", __FUNCTION__); - abort(); -} - -static int interface_flush_resources(QXLInstance *sin) -{ - fprintf(stderr, "%s: abort()\n", __FUNCTION__); - abort(); - return 0; -} - -static void interface_update_area_complete(QXLInstance *sin, - uint32_t surface_id, - QXLRect *dirty, uint32_t num_updated_rects) -{ - /* should never be called, used in qxl native mode only */ - fprintf(stderr, "%s: abort()\n", __func__); - abort(); -} - -/* called from spice server thread context only */ -static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token) -{ - QXLCookie *cookie = (QXLCookie *)(uintptr_t)cookie_token; - - switch (cookie->type) { -#ifdef HAVE_SPICE_GL - case QXL_COOKIE_TYPE_GL_DRAW_DONE: - { - SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl); - qemu_bh_schedule(ssd->gl_unblock_bh); - break; - } -#endif - default: - /* should never be called, used in qxl native mode only */ - fprintf(stderr, "%s: abort()\n", __func__); - abort(); - } - g_free(cookie); -} - -static void interface_set_client_capabilities(QXLInstance *sin, - uint8_t client_present, - uint8_t caps[58]) -{ - dprint(3, "%s:\n", __func__); -} - -static int interface_client_monitors_config(QXLInstance *sin, - VDAgentMonitorsConfig *mc) -{ - SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl); - QemuUIInfo info; - - if (!dpy_ui_info_supported(ssd->dcl.con)) { - return 0; /* == not supported by guest */ - } - - if (!mc) { - return 1; - } - - /* - * FIXME: multihead is tricky due to the way - * spice has multihead implemented. - */ - memset(&info, 0, sizeof(info)); - if (mc->num_of_monitors > 0) { - info.width = mc->monitors[0].width; - info.height = mc->monitors[0].height; - } - dpy_set_ui_info(ssd->dcl.con, &info); - dprint(1, "%s/%d: size %dx%d\n", __func__, ssd->qxl.id, - info.width, info.height); - return 1; -} - -static const QXLInterface dpy_interface = { - .base.type = SPICE_INTERFACE_QXL, - .base.description = "qemu simple display", - .base.major_version = SPICE_INTERFACE_QXL_MAJOR, - .base.minor_version = SPICE_INTERFACE_QXL_MINOR, - - .attache_worker = interface_attach_worker, - .set_compression_level = interface_set_compression_level, - .set_mm_time = interface_set_mm_time, - .get_init_info = interface_get_init_info, - - /* the callbacks below are called from spice server thread context */ - .get_command = interface_get_command, - .req_cmd_notification = interface_req_cmd_notification, - .release_resource = interface_release_resource, - .get_cursor_command = interface_get_cursor_command, - .req_cursor_notification = interface_req_cursor_notification, - .notify_update = interface_notify_update, - .flush_resources = interface_flush_resources, - .async_complete = interface_async_complete, - .update_area_complete = interface_update_area_complete, - .set_client_capabilities = interface_set_client_capabilities, - .client_monitors_config = interface_client_monitors_config, -}; - -static void display_update(DisplayChangeListener *dcl, - int x, int y, int w, int h) -{ - SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); - qemu_spice_display_update(ssd, x, y, w, h); -} - -static void display_switch(DisplayChangeListener *dcl, - DisplaySurface *surface) -{ - SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); - qemu_spice_display_switch(ssd, surface); -} - -static void display_refresh(DisplayChangeListener *dcl) -{ - SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); - qemu_spice_display_refresh(ssd); -} - -static void display_mouse_set(DisplayChangeListener *dcl, - int x, int y, int on) -{ - SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); - - qemu_mutex_lock(&ssd->lock); - ssd->ptr_x = x; - ssd->ptr_y = y; - g_free(ssd->ptr_move); - ssd->ptr_move = qemu_spice_create_cursor_update(ssd, NULL, on); - qemu_mutex_unlock(&ssd->lock); -} - -static void display_mouse_define(DisplayChangeListener *dcl, - QEMUCursor *c) -{ - SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); - - qemu_mutex_lock(&ssd->lock); - if (c) { - cursor_get(c); - } - cursor_put(ssd->cursor); - ssd->cursor = c; - ssd->hot_x = c->hot_x; - ssd->hot_y = c->hot_y; - g_free(ssd->ptr_move); - ssd->ptr_move = NULL; - g_free(ssd->ptr_define); - ssd->ptr_define = qemu_spice_create_cursor_update(ssd, c, 0); - qemu_mutex_unlock(&ssd->lock); -} - -static const DisplayChangeListenerOps display_listener_ops = { - .dpy_name = "spice", - .dpy_gfx_update = display_update, - .dpy_gfx_switch = display_switch, - .dpy_gfx_check_format = qemu_pixman_check_format, - .dpy_refresh = display_refresh, - .dpy_mouse_set = display_mouse_set, - .dpy_cursor_define = display_mouse_define, -}; - -#ifdef HAVE_SPICE_GL - -static void qemu_spice_gl_block(SimpleSpiceDisplay *ssd, bool block) -{ - uint64_t timeout; - - if (block) { - timeout = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); - timeout += 1000; /* one sec */ - timer_mod(ssd->gl_unblock_timer, timeout); - } else { - timer_del(ssd->gl_unblock_timer); - } - graphic_hw_gl_block(ssd->dcl.con, block); -} - -static void qemu_spice_gl_unblock_bh(void *opaque) -{ - SimpleSpiceDisplay *ssd = opaque; - - qemu_spice_gl_block(ssd, false); -} - -static void qemu_spice_gl_block_timer(void *opaque) -{ - fprintf(stderr, "WARNING: spice: no gl-draw-done within one second\n"); -} - -static QEMUGLContext qemu_spice_gl_create_context(DisplayChangeListener *dcl, - QEMUGLParams *params) -{ - eglMakeCurrent(qemu_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, - qemu_egl_rn_ctx); - 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 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 >= 0); - - /* note: spice server will close the fd */ - spice_qxl_gl_scanout(&ssd->qxl, fd, - surface_width(ssd->ds), - surface_height(ssd->ds), - stride, fourcc, y_0_top); -} - -static void qemu_spice_gl_update(DisplayChangeListener *dcl, - uint32_t x, uint32_t y, uint32_t w, uint32_t h) -{ - SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); - uint64_t cookie; - - dprint(2, "%s: %dx%d+%d+%d\n", __func__, w, h, x, y); - qemu_spice_gl_block(ssd, true); - cookie = (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_GL_DRAW_DONE, 0); - spice_qxl_gl_draw_async(&ssd->qxl, x, y, w, h, cookie); -} - -static const DisplayChangeListenerOps display_listener_gl_ops = { - .dpy_name = "spice-egl", - .dpy_gfx_update = display_update, - .dpy_gfx_switch = display_switch, - .dpy_gfx_check_format = qemu_pixman_check_format, - .dpy_refresh = display_refresh, - .dpy_mouse_set = display_mouse_set, - .dpy_cursor_define = display_mouse_define, - - .dpy_gl_ctx_create = qemu_spice_gl_create_context, - .dpy_gl_ctx_destroy = qemu_egl_destroy_context, - .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_update = qemu_spice_gl_update, -}; - -#endif /* HAVE_SPICE_GL */ - -static void qemu_spice_display_init_one(QemuConsole *con) -{ - SimpleSpiceDisplay *ssd = g_new0(SimpleSpiceDisplay, 1); - - qemu_spice_display_init_common(ssd); - - ssd->dcl.ops = &display_listener_ops; -#ifdef HAVE_SPICE_GL - if (display_opengl) { - ssd->dcl.ops = &display_listener_gl_ops; - ssd->dmabuf_fd = -1; - ssd->gl_unblock_bh = qemu_bh_new(qemu_spice_gl_unblock_bh, ssd); - ssd->gl_unblock_timer = timer_new_ms(QEMU_CLOCK_REALTIME, - qemu_spice_gl_block_timer, ssd); - } -#endif - ssd->dcl.con = con; - - ssd->qxl.base.sif = &dpy_interface.base; - qemu_spice_add_display_interface(&ssd->qxl, con); - assert(ssd->worker); - qemu_spice_create_host_memslot(ssd); - - register_displaychangelistener(&ssd->dcl); -} - -void qemu_spice_display_init(void) -{ - QemuConsole *con; - int i; - - for (i = 0;; i++) { - con = qemu_console_lookup_by_index(i); - if (!con || !qemu_console_is_graphic(con)) { - break; - } - if (qemu_spice_have_display_interface(con)) { - continue; - } - qemu_spice_display_init_one(con); - } -} -- cgit 1.2.3-korg