/* called from spice server thread context only */ int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext) { QXLCursorCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id); QXLCursor *cursor; QEMUCursor *c; if (!cmd) { return 1; } if (!dpy_cursor_define_supported(qxl->vga.con)) { return 0; } if (qxl->debug > 1 && cmd->type != QXL_CURSOR_MOVE) { fprintf(stderr, "%s", __FUNCTION__); qxl_log_cmd_cursor(qxl, cmd, ext->group_id); fprintf(stderr, "\n"); } switch (cmd->type) { case QXL_CURSOR_SET: cursor = qxl_phys2virt(qxl, cmd->u.set.shape, ext->group_id); if (!cursor) { return 1; } if (cursor->chunk.data_size != cursor->data_size) { fprintf(stderr, "%s: multiple chunks\n", __FUNCTION__); return 1; } c = qxl_cursor(qxl, cursor); if (c == NULL) { c = cursor_builtin_left_ptr(); } qemu_mutex_lock(&qxl->ssd.lock); if (qxl->ssd.cursor) { cursor_put(qxl->ssd.cursor); } qxl->ssd.cursor = c; qxl->ssd.mouse_x = cmd->u.set.position.x; qxl->ssd.mouse_y = cmd->u.set.position.y; qemu_mutex_unlock(&qxl->ssd.lock); qemu_bh_schedule(qxl->ssd.cursor_bh); break; case QXL_CURSOR_MOVE: qemu_mutex_lock(&qxl->ssd.lock); qxl->ssd.mouse_x = cmd->u.position.x; qxl->ssd.mouse_y = cmd->u.position.y; qemu_mutex_unlock(&qxl->ssd.lock); qemu_bh_schedule(qxl->ssd.cursor_bh); break; } return 0; }
int qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id) { QXLCursor *cursor; fprintf(stderr, ": %s", qxl_name(qxl_cursor_cmd, cmd->type)); switch (cmd->type) { case QXL_CURSOR_SET: fprintf(stderr, " +%d+%d visible %s, shape @ 0x%" PRIx64, cmd->u.set.position.x, cmd->u.set.position.y, cmd->u.set.visible ? "yes" : "no", cmd->u.set.shape); cursor = qxl_phys2virt(qxl, cmd->u.set.shape, group_id); if (!cursor) { return 1; } fprintf(stderr, " type %s size %dx%d hot-spot +%d+%d" " unique 0x%" PRIx64 " data-size %d", qxl_name(spice_cursor_type, cursor->header.type), cursor->header.width, cursor->header.height, cursor->header.hot_spot_x, cursor->header.hot_spot_y, cursor->header.unique, cursor->data_size); break; case QXL_CURSOR_MOVE: fprintf(stderr, " +%d+%d", cmd->u.position.x, cmd->u.position.y); break; } return 0; }
static int qxl_log_image(PCIQXLDevice *qxl, QXLPHYSICAL addr, int group_id) { QXLImage *image; QXLImageDescriptor *desc; image = qxl_phys2virt(qxl, addr, group_id); if (!image) { return 1; } desc = &image->descriptor; fprintf(stderr, " (id %" PRIx64 " type %d flags %d width %d height %d", desc->id, desc->type, desc->flags, desc->width, desc->height); switch (desc->type) { case SPICE_IMAGE_TYPE_BITMAP: fprintf(stderr, ", fmt %d flags %d x %d y %d stride %d" " palette %" PRIx64 " data %" PRIx64, image->bitmap.format, image->bitmap.flags, image->bitmap.x, image->bitmap.y, image->bitmap.stride, image->bitmap.palette, image->bitmap.data); break; } fprintf(stderr, ")"); return 0; }
void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext) { bool compat = ext->flags & QXL_COMMAND_FLAG_COMPAT; void *data; if (!qxl->cmdlog) { return; } fprintf(stderr, "qxl-%d/%s:", qxl->id, ring); fprintf(stderr, " cmd @ 0x%" PRIx64 " %s%s", ext->cmd.data, qxl_name(qxl_type, ext->cmd.type), compat ? "(compat)" : ""); data = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id); switch (ext->cmd.type) { case QXL_CMD_DRAW: if (!compat) { qxl_log_cmd_draw(qxl, data); } else { qxl_log_cmd_draw_compat(qxl, data); } break; case QXL_CMD_SURFACE: qxl_log_cmd_surface(qxl, data); break; case QXL_CMD_CURSOR: qxl_log_cmd_cursor(qxl, data, ext->group_id); break; } fprintf(stderr, "\n"); }
static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl) { VGACommonState *vga = &qxl->vga; int i; if (qxl->guest_primary.resized) { qxl->guest_primary.resized = 0; qxl->guest_primary.data = qxl_phys2virt(qxl, qxl->guest_primary.surface.mem, MEMSLOT_GROUP_GUEST); if (!qxl->guest_primary.data) { return; } qxl_set_rect_to_surface(qxl, &qxl->dirty[0]); qxl->num_dirty_rects = 1; trace_qxl_render_guest_primary_resized( qxl->guest_primary.surface.width, qxl->guest_primary.surface.height, qxl->guest_primary.qxl_stride, qxl->guest_primary.bytes_pp, qxl->guest_primary.bits_pp); if (qxl->guest_primary.qxl_stride > 0) { qemu_free_displaysurface(vga->ds); vga->ds->surface = qemu_create_displaysurface_from (qxl->guest_primary.surface.width, qxl->guest_primary.surface.height, qxl->guest_primary.bits_pp, qxl->guest_primary.abs_stride, qxl->guest_primary.data); } else { qemu_resize_displaysurface(vga->ds, qxl->guest_primary.surface.width, qxl->guest_primary.surface.height); } dpy_resize(vga->ds); } if (!qxl->guest_primary.data) { return; } for (i = 0; i < qxl->num_dirty_rects; i++) { if (qemu_spice_rect_is_empty(qxl->dirty+i)) { break; } if (qxl->dirty[i].left < 0 || qxl->dirty[i].top < 0 || qxl->dirty[i].left > qxl->dirty[i].right || qxl->dirty[i].top > qxl->dirty[i].bottom || qxl->dirty[i].right > qxl->guest_primary.surface.width || qxl->dirty[i].bottom > qxl->guest_primary.surface.height) { continue; } qxl_blit(qxl, qxl->dirty+i); dpy_update(vga->ds, qxl->dirty[i].left, qxl->dirty[i].top, qxl->dirty[i].right - qxl->dirty[i].left, qxl->dirty[i].bottom - qxl->dirty[i].top); } qxl->num_dirty_rects = 0; }
static void qxl_unpack_chunks(void *dest, size_t size, PCIQXLDevice *qxl, QXLDataChunk *chunk, uint32_t group_id) { uint32_t max_chunks = 32; size_t offset = 0; size_t bytes; for (;;) { bytes = MIN(size - offset, chunk->data_size); memcpy(dest + offset, chunk->data, bytes); offset += bytes; if (offset == size) { return; } chunk = qxl_phys2virt(qxl, chunk->next_chunk, group_id); if (!chunk) { return; } max_chunks--; if (max_chunks == 0) { return; } } }