static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd) { SimpleSpiceUpdate *update; QXLDrawable *drawable; QXLImage *image; QXLCommand *cmd; uint8_t *src, *dst; int by, bw, bh; struct timespec time_space; if (qemu_spice_rect_is_empty(&ssd->dirty)) { return NULL; }; trace_qemu_spice_create_update( ssd->dirty.left, ssd->dirty.right, ssd->dirty.top, ssd->dirty.bottom); update = g_malloc0(sizeof(*update)); drawable = &update->drawable; image = &update->image; cmd = &update->ext.cmd; bw = ssd->dirty.right - ssd->dirty.left; bh = ssd->dirty.bottom - ssd->dirty.top; update->bitmap = g_malloc(bw * bh * 4); drawable->bbox = ssd->dirty; drawable->clip.type = SPICE_CLIP_TYPE_NONE; drawable->effect = QXL_EFFECT_OPAQUE; drawable->release_info.id = (uintptr_t)update; 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; if (ssd->conv == NULL) { PixelFormat dst = qemu_default_pixelformat(32); ssd->conv = qemu_pf_conv_get(&dst, &ssd->ds->surface->pf); assert(ssd->conv); } src = ds_get_data(ssd->ds) + ssd->dirty.top * ds_get_linesize(ssd->ds) + ssd->dirty.left * ds_get_bytes_per_pixel(ssd->ds); dst = update->bitmap; for (by = 0; by < bh; by++) { qemu_pf_conv_run(ssd->conv, dst, src, bw); src += ds_get_linesize(ssd->ds); dst += image->bitmap.stride; } cmd->type = QXL_CMD_DRAW; cmd->data = (uintptr_t)drawable; memset(&ssd->dirty, 0, sizeof(ssd->dirty)); return update; }
/* bitmap and rects are freed, so they must be allocated with malloc */ SimpleSpiceUpdate *test_spice_create_update_from_bitmap(uint32_t surface_id, QXLRect bbox, uint8_t *bitmap, uint32_t num_clip_rects, QXLRect *clip_rects) { SimpleSpiceUpdate *update; QXLDrawable *drawable; QXLImage *image; uint32_t bw, bh; bh = bbox.bottom - bbox.top; bw = bbox.right - bbox.left; update = calloc(sizeof(*update), 1); update->bitmap = bitmap; drawable = &update->drawable; image = &update->image; drawable->surface_id = surface_id; drawable->bbox = bbox; if (num_clip_rects == 0) { drawable->clip.type = SPICE_CLIP_TYPE_NONE; } else { QXLClipRects *cmd_clip; cmd_clip = calloc(sizeof(QXLClipRects) + num_clip_rects*sizeof(QXLRect), 1); cmd_clip->num_rects = num_clip_rects; cmd_clip->chunk.data_size = num_clip_rects*sizeof(QXLRect); cmd_clip->chunk.prev_chunk = cmd_clip->chunk.next_chunk = 0; memcpy(cmd_clip + 1, clip_rects, cmd_clip->chunk.data_size); drawable->clip.type = SPICE_CLIP_TYPE_RECTS; drawable->clip.data = (intptr_t)cmd_clip; free(clip_rects); } drawable->effect = QXL_EFFECT_OPAQUE; simple_set_release_info(&drawable->release_info, (intptr_t)update); drawable->type = QXL_DRAW_COPY; drawable->surfaces_dest[0] = -1; drawable->surfaces_dest[1] = -1; drawable->surfaces_dest[2] = -1; drawable->u.copy.rop_descriptor = SPICE_ROPD_OP_PUT; drawable->u.copy.src_bitmap = (intptr_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, 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 = (intptr_t)bitmap; image->bitmap.palette = 0; image->bitmap.format = SPICE_BITMAP_FMT_32BIT; set_cmd(&update->ext, QXL_CMD_DRAW, (intptr_t)drawable); return update; }
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_one_update(SimpleSpiceDisplay *ssd, QXLRect *rect) { SimpleSpiceUpdate *update; QXLDrawable *drawable; QXLImage *image; QXLCommand *cmd; uint8_t *src, *mirror, *dst; int by, bw, bh, offset, bytes; trace_qemu_spice_create_update( rect->left, rect->right, rect->top, rect->bottom); update = qemu_mallocz(sizeof(*update)); drawable = &update->drawable; image = &update->image; cmd = &update->ext.cmd; bw = rect->right - rect->left; bh = rect->bottom - rect->top; update->bitmap = qemu_malloc(bw * bh * 4); drawable->bbox = *rect; drawable->clip.type = SPICE_CLIP_TYPE_NONE; drawable->effect = QXL_EFFECT_OPAQUE; drawable->release_info.id = (intptr_t)update; drawable->type = QXL_DRAW_COPY; drawable->surfaces_dest[0] = -1; drawable->surfaces_dest[1] = -1; drawable->surfaces_dest[2] = -1; drawable->u.copy.rop_descriptor = SPICE_ROPD_OP_PUT; drawable->u.copy.src_bitmap = (intptr_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 = (intptr_t)(update->bitmap); image->bitmap.palette = 0; image->bitmap.format = SPICE_BITMAP_FMT_32BIT; offset = rect->top * ds_get_linesize(ssd->ds) + rect->left * ds_get_bytes_per_pixel(ssd->ds); bytes = ds_get_bytes_per_pixel(ssd->ds) * bw; src = ds_get_data(ssd->ds) + offset; mirror = ssd->ds_mirror + offset; dst = update->bitmap; for (by = 0; by < bh; by++) { memcpy(mirror, src, bytes); qemu_pf_conv_run(ssd->conv, dst, mirror, bw); src += ds_get_linesize(ssd->ds); mirror += ds_get_linesize(ssd->ds); dst += image->bitmap.stride; } cmd->type = QXL_CMD_DRAW; cmd->data = (intptr_t)drawable; QTAILQ_INSERT_TAIL(&ssd->updates, update, next); }