Signed-off-by: Erlon R. Cruz <erlon.cruz@xxxxxxxxxxxxxxxxxxxxx> Signed-off-by: Fabiano Fidêncio <fabiano.fidencio@xxxxxxxxxxxxxxxxxxxxx> Signed-off-by: Rafael F. Santos <fonsecasantos.rafael@xxxxxxxxx> --- examples/Makefile.am | 6 +- examples/virtioqxl.xorg.conf.example | 24 +++ src/Makefile.am | 11 +- src/qxl.h | 196 +++++++++++++++++++++++- src/qxl_driver.c | 275 ++++++++++++++++++++++++++-------- src/qxl_logger.c | 8 + src/qxl_ring.c | 169 ++++++++++++++++++++- src/qxl_surface.c | 94 ++++-------- 8 files changed, 637 insertions(+), 146 deletions(-) create mode 100644 examples/virtioqxl.xorg.conf.example diff --git a/examples/Makefile.am b/examples/Makefile.am index 75e61ea..251f6f1 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -19,6 +19,8 @@ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. if BUILD_XSPICE -doc_DATA = spiceqxl.xorg.conf.example +doc_DATA = spiceqxl.xorg.conf.example \ + virtioqxl.xorg.conf.example endif -EXTRA_DIST = spiceqxl.xorg.conf.example +EXTRA_DIST = spiceqxl.xorg.conf.example \ + virtioqxl.xorg.conf.example diff --git a/examples/virtioqxl.xorg.conf.example b/examples/virtioqxl.xorg.conf.example new file mode 100644 index 0000000..bcb9b9d --- /dev/null +++ b/examples/virtioqxl.xorg.conf.example @@ -0,0 +1,24 @@ +Section "Device" + Identifier "QXL_device" + Driver "virtioqxl" + Option "virtiodev" "/dev/virtioqxl0" +EndSection + +Section "InputDevice" + Identifier "Mouse" + Driver "mouse" + Option "Protocol" "PS/2" + Option "Device" "/dev/input/mice" +EndSection + +Section "Monitor" + Identifier "Configured Monitor" +EndSection + +Section "Screen" + Identifier "Screen" + Monitor "Configured Monitor" + Device "QXL_device" + DefaultDepth 24 +EndSection + diff --git a/src/Makefile.am b/src/Makefile.am index 3ffa3ce..09d89ad 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -31,6 +31,7 @@ AM_CFLAGS = $(SPICE_PROTOCOL_CFLAGS) $(XORG_CFLAGS) $(PCIACCESS_CFLAGS) $(CWARNF if ENABLE_DEBUG DEBUGFLAGS = -DENABLE_DEBUG -O0 -g +DEBUG_FILES = qxl_logger.c endif if BUILD_DUMP_COMMANDS @@ -57,7 +58,7 @@ qxl_drv_la_SOURCES = \ murmurhash3.h \ qxl_cursor.c \ compat-api.h \ - qxl_logger.c + $(DEBUG_FILES) endif if BUILD_VIRTIO_QXL @@ -80,7 +81,7 @@ virtioqxl_drv_la_SOURCES = \ murmurhash3.c \ murmurhash3.h \ qxl_cursor.c \ - qxl_logger.c + $(DEBUG_FILES) endif if BUILD_XSPICE @@ -103,7 +104,7 @@ spiceqxl_drv_la_SOURCES = \ spiceqxl_driver.c \ spiceqxl_driver.h \ spiceqxl_main_loop.c \ - spiceqxl_main_loop.h \ + spiceqxl_main_loop.h \ spiceqxl_display.c \ spiceqxl_display.h \ spiceqxl_inputs.c \ @@ -118,5 +119,5 @@ spiceqxl_drv_la_SOURCES = \ murmurhash3.c \ murmurhash3.h \ qxl_cursor.c \ - qxl_logger.c -endif + $(DEBUG_FILES) +endif \ No newline at end of file diff --git a/src/qxl.h b/src/qxl.h index 7d90dfc..83eea99 100644 --- a/src/qxl.h +++ b/src/qxl.h @@ -30,6 +30,21 @@ #include <spice.h> #endif +#ifdef VIRTIO_QXL +#include <linux/virtio_bridge.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <endian.h> + +#ifdef ENABLE_DEBUG +#define DEBUG_RINGS 0 +#define DEBUG_CURSOR_RING 0 +#define DEBUG_COMMAND_RING 0 +#define DEBUG_RELEASE_RING 0 +#define DEBUG_RAM_UPDATES 0 +#endif +#endif // VIRTIO_QXL + #include "compiler.h" #include "xf86.h" #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 @@ -53,7 +68,10 @@ #include "compat-api.h" #define hidden _X_HIDDEN -#ifdef XSPICE +#ifdef VIRTIO_QXL +#define QXL_NAME "virtioqxl" +#define QXL_DRIVER_NAME "virtioqxl" +#elif defined XSPICE #define QXL_NAME "spiceqxl" #define QXL_DRIVER_NAME "spiceqxl" #else @@ -92,6 +110,47 @@ typedef struct typedef struct qxl_surface_t qxl_surface_t; +struct qxl_surface_t +{ + surface_cache_t *cache; + + uint32_t id; + + pixman_image_t * dev_image; + pixman_image_t * host_image; + + uxa_access_t access_type; + RegionRec access_region; + + void * address; + void * end; + + qxl_surface_t * next; + qxl_surface_t * prev; /* Only used in the 'live' + * chain in the surface cache + */ + + int in_use; + int bpp; /* bpp of the pixmap */ + int ref_count; + + PixmapPtr pixmap; + + struct evacuated_surface_t *evacuated; + + union + { + qxl_surface_t *copy_src; + Pixel solid_pixel; + } u; +}; + +typedef enum { + CURSOR_RING, + COMMAND_RING, + RELEASE_RING +} ring_type; + /* * Config Options */ @@ -172,7 +231,7 @@ struct _qxl_screen_t EntityInfoPtr entity; -#ifndef XSPICE +#if !defined XSPICE && !defined VIRTIO_QXL void * io_pages; void * io_pages_physical; @@ -220,6 +279,13 @@ struct _qxl_screen_t int enable_fallback_cache; int enable_surfaces; +#ifdef VIRTIO_QXL + int virtiofd; + struct virtioqxl_config virtio_config; + void *vmem_start; + char *device_name; +#endif + #ifdef XSPICE /* XSpice specific */ struct QXLRom shadow_rom; /* Parameter RAM */ @@ -248,6 +314,54 @@ struct _qxl_screen_t #endif /* XSPICE */ }; +#ifdef VIRTIO_QXL +static inline uint64_t physical_address(qxl_screen_t *qxl, + void *virtual, + uint8_t slot_id){ + + char *ram; + uint64_t offset; + int maplen; + + ram = (char *)qxl->ram; + maplen = qxl->virtio_config.ramsize + qxl->virtio_config.vramsize + + qxl->virtio_config.romsize; + offset = (char *)virtual - ram; + + if (offset >= 0 && offset < maplen) { + return offset; + } + + // Die + fprintf(stderr, "GUEST (%s): Memory %p (%ld) out of bounds [%p - %p]\n", + __func__, virtual, (char *)virtual - ram, ram, ram + maplen); + exit(1); +} + +static inline void * virtual_address (qxl_screen_t *qxl, + void *physical, + uint8_t slot_id){ + + char *ram; + uint64_t offset; + void *local; + int memlen = qxl->virtio_config.ramsize + qxl->virtio_config.vramsize + + qxl->virtio_config.romsize; + + ram = (char *)qxl->ram; + offset = (uint64_t)physical; + + if (offset >= 0 && offset < memlen) { + local = (void *)(ram + offset); + } else { + fprintf(stderr, "GUEST (%s): Memory %p (%ld) out of bounds [%p - %p]\n", + __func__, (uint64_t)physical + ram, offset, ram, ram + memlen); + exit(1); + } + + return local; +} +#else static inline uint64_t physical_address (qxl_screen_t *qxl, void *virtual, uint8_t slot_id) { @@ -267,6 +381,7 @@ virtual_address (qxl_screen_t *qxl, void *physical, uint8_t slot_id) return (void *)virt; } +#endif // VIRTIO_QXL static inline void * u64_to_pointer (uint64_t u) @@ -296,7 +411,8 @@ struct qxl_ring * qxl_ring_create (struct qxl_ring_header *header, int element_size, int n_elements, int prod_notify, - qxl_screen_t *qxl); + qxl_screen_t *qxl, + int ring_type); void qxl_ring_push (struct qxl_ring *ring, const void *element); Bool qxl_ring_pop (struct qxl_ring *ring, @@ -387,7 +503,7 @@ static inline struct QXLRam * get_ram_header (qxl_screen_t *qxl) { return (struct QXLRam *) - ((uint8_t *)qxl->ram + qxl->rom->ram_header_offset); + ((uint8_t *)qxl->ram + le32toh(qxl->rom->ram_header_offset)); } /* @@ -430,13 +546,13 @@ void qxl_mem_unverifiable(struct qxl_mem *mem); static inline void qxl_mem_unverifiable(struct qxl_mem *mem) {} #endif -#ifdef DUMP_COMMANDS +#ifdef ENABLE_DEBUG void qxl_log_command(qxl_screen_t *qxl, QXLCommand *cmd, char *direction); #endif /* * I/O port commands */ -void qxl_update_area(qxl_screen_t *qxl); +void qxl_update_area(qxl_screen_t *qxl,qxl_surface_t *surface); void qxl_io_memslot_add(qxl_screen_t *qxl, uint8_t id); void qxl_io_create_primary(qxl_screen_t *qxl); void qxl_io_destroy_primary(qxl_screen_t *qxl); @@ -447,6 +563,12 @@ void qxl_io_destroy_all_surfaces (qxl_screen_t *qxl); #ifdef XSPICE /* device to spice-server, now xspice to spice-server */ void ioport_write(qxl_screen_t *qxl, uint32_t io_port, uint32_t val); +#elif defined VIRTIO_QXL +static inline void ioport_write(qxl_screen_t *qxl, int port, int val) +{ + int cmd = _IOW(QXLMAGIC, port, unsigned int); + ioctl(qxl->virtiofd, cmd, val); +} #else static inline void ioport_write(qxl_screen_t *qxl, int port, int val) { @@ -454,6 +576,68 @@ static inline void ioport_write(qxl_screen_t *qxl, int port, int val) } #endif +#ifdef ENABLE_DEBUG +void qxl_log_command(qxl_screen_t *qxl, QXLCommand *cmd, char *direction); +#endif + +#ifdef VIRTIO_QXL +/* Write guest memory on host*/ +static inline void virtioqxl_push_ram(qxl_screen_t *qxl, void *ptr, int len) +{ + char *start, *end; + struct qxl_ram_area ram_area; + int memlen = qxl->virtio_config.ramsize + qxl->virtio_config.vramsize + + qxl->virtio_config.romsize; + + start = (char *)ptr; + end = (char *)ptr + len; + + if (start < (char *)qxl->ram || + end > ((char *)qxl->ram + memlen)) { + fprintf(stderr,"%s: Error pushing memory [%p - %p] out of bounds " + "[%p - %p]\n", __func__, start, end, qxl->ram, + (char *)qxl->ram + memlen); + return; + } + + ram_area.offset = start - (char *)qxl->ram; + ram_area.len = len; + +#ifdef ENABLE_DEBUG + fprintf(stderr,"%s: pushing area[%d->%d]. %d bytes\n", + __func__, ram_area.offset, ram_area.offset + ram_area.len, + ram_area.len); +#endif + + write(qxl->virtiofd,ptr,len); +} + +/* Read from memory on host*/ +static inline void virtioqxl_pull_ram(qxl_screen_t *qxl, void *ptr, int len) +{ + struct qxl_ram_area ram_area; + int mem_size = qxl->virtio_config.ramsize + qxl->virtio_config.vramsize + + qxl->virtio_config.romsize; + + if ((uint8_t *)ptr < (uint8_t *)qxl->ram || + (uint8_t *)ptr+len > ((uint8_t *)qxl->ram + mem_size)) { + fprintf(stderr,"%s: Error pulling memory out of bounds\n",__func__); + return; + } + + ram_area.offset = (uint8_t *)ptr - (uint8_t *)qxl->ram; + ram_area.len = len; + +#ifdef ENABLE_DEBUG + fprintf(stderr,"%s: pulling area[%d->%d]. %d bytes\n", + __func__, ram_area.offset, ram_area.offset + ram_area.len, + ram_area.len); +#endif + + read(qxl->virtiofd,ptr,len); +} +#endif // VIRTIO_QXL + #ifdef XSPICE #define MEMSLOT_GROUP 0 diff --git a/src/qxl_driver.c b/src/qxl_driver.c index e4c477a..5474850 100644 --- a/src/qxl_driver.c +++ b/src/qxl_driver.c @@ -46,6 +46,14 @@ #include "assert.h" #include "qxl_option_helpers.h" +#ifdef VIRTIO_QXL +#include <linux/virtio_bridge.h> +#include "spiceqxl_driver.h" +#define VIRTIO_DEV "/dev/virtioqxl0" +#include <sys/stat.h> +#include <fcntl.h> +#endif + #ifdef XSPICE #include "spiceqxl_driver.h" #include "spiceqxl_main_loop.h" @@ -126,7 +134,7 @@ qxl_available_options (int chipid, int busid) return DefaultOptions; } -#ifndef XSPICE +#if (!defined XSPICE && !defined VIRTIO_QXL) static void qxl_wait_for_io_command(qxl_screen_t *qxl) { struct QXLRam *ram_header = (void *)( @@ -139,9 +147,16 @@ static void qxl_wait_for_io_command(qxl_screen_t *qxl) } #endif -void qxl_update_area(qxl_screen_t *qxl) +void qxl_update_area(qxl_screen_t *qxl, qxl_surface_t *surface) { -#ifndef XSPICE + +#ifdef VIRTIO_QXL + QXLRam *ram_header = get_ram_header(qxl); + virtioqxl_push_ram(qxl, &ram_header->update_area, sizeof(QXLRect)); + virtioqxl_push_ram(qxl, &ram_header->update_surface, sizeof(int)); +#endif + +#if !defined XSPICE && !defined VIRTIO_QXL if (qxl->pci->revision >= 3) { ioport_write(qxl, QXL_IO_UPDATE_AREA_ASYNC, 0); qxl_wait_for_io_command(qxl); @@ -151,11 +166,20 @@ void qxl_update_area(qxl_screen_t *qxl) #else ioport_write(qxl, QXL_IO_UPDATE_AREA, 0); #endif + +#ifdef VIRTIO_QXL + if (!surface || !surface->id) { //Primary + virtioqxl_pull_ram(qxl, qxl->surface0_area, qxl->surface0_size); + } else { + virtioqxl_pull_ram(qxl, surface->address, + (intptr_t)surface->end - (intptr_t)surface->address); + } +#endif } void qxl_io_memslot_add(qxl_screen_t *qxl, uint8_t id) { -#ifndef XSPICE +#if !defined XSPICE && !defined VIRTIO_QXL if (qxl->pci->revision >= 3) { ioport_write(qxl, QXL_IO_MEMSLOT_ADD_ASYNC, id); qxl_wait_for_io_command(qxl); @@ -169,7 +193,7 @@ void qxl_io_memslot_add(qxl_screen_t *qxl, uint8_t id) void qxl_io_create_primary(qxl_screen_t *qxl) { -#ifndef XSPICE +#if !defined XSPICE && !defined VIRTIO_QXL if (qxl->pci->revision >= 3) { ioport_write(qxl, QXL_IO_CREATE_PRIMARY_ASYNC, 0); qxl_wait_for_io_command(qxl); @@ -184,7 +208,7 @@ void qxl_io_create_primary(qxl_screen_t *qxl) void qxl_io_destroy_primary(qxl_screen_t *qxl) { -#ifndef XSPICE +#if (!defined XSPICE && !defined VIRTIO_QXL) if (qxl->pci->revision >= 3) { ioport_write(qxl, QXL_IO_DESTROY_PRIMARY_ASYNC, 0); @@ -206,7 +230,7 @@ void qxl_io_notify_oom(qxl_screen_t *qxl) void qxl_io_flush_surfaces(qxl_screen_t *qxl) { -#ifndef XSPICE +#if (!defined XSPICE && !defined VIRTIO_QXL) ioport_write(qxl, QXL_IO_FLUSH_SURFACES_ASYNC, 0); qxl_wait_for_io_command(qxl); #else @@ -273,9 +297,14 @@ qxl_garbage_collect (qxl_screen_t *qxl) qxl_surface_recycle (qxl->surface_cache, surface_cmd->surface_id); qxl_surface_cache_sanity_check (qxl->surface_cache); } - - id = info->next; - + +#ifdef VIRTIO_QXL + virtioqxl_pull_ram(qxl,&info->next,sizeof(info->next)); + id = info->next; +#else + id = info->next; +#endif + qxl_free (qxl->mem, info); ++i; @@ -358,7 +387,99 @@ qxl_blank_screen(ScreenPtr pScreen, int mode) return TRUE; } -#ifdef XSPICE +#ifdef VIRTIO_QXL + +#undef SPICE_RING_PROD_ITEM +#define SPICE_RING_PROD_ITEM(r, ret) { \ + typeof(r) start = r; \ + typeof(r) end = r + 1; \ + uint32_t prod = (r)->prod & SPICE_RING_INDEX_MASK(r); \ + typeof(&(r)->items[prod]) m_item = &(r)->items[prod]; \ + if (!((uint8_t *)m_item >= (uint8_t *)(start) && (uint8_t *)(m_item + 1) <= (uint8_t *)(end))) { \ + abort(); \ + } \ + ret = &m_item->el; \ +} + +#undef SPICE_RING_CONS_ITEM +#define SPICE_RING_CONS_ITEM(r, ret) { \ + typeof(r) start = r; \ + typeof(r) end = r + 1; \ + uint32_t cons = (r)->cons & SPICE_RING_INDEX_MASK(r); \ + typeof(&(r)->items[cons]) m_item = &(r)->items[cons]; \ + if (!((uint8_t *)m_item >= (uint8_t *)(start) && (uint8_t *)(m_item + 1) <= (uint8_t *)(end))) { \ + abort(); \ + } \ + ret = &m_item->el; \ +} + +static void virtio_init_qxl_ram(qxl_screen_t *qxl) +{ + QXLRam *ram = get_ram_header(qxl); + uint64_t *item; + + ram->magic = htole32(QXL_RAM_MAGIC); + ram->int_pending = htole32(0); + ram->int_mask = htole32(0); + SPICE_RING_INIT(&ram->cmd_ring); + SPICE_RING_INIT(&ram->cursor_ring); + SPICE_RING_INIT(&ram->release_ring); + SPICE_RING_PROD_ITEM(&ram->release_ring, item); + *item = 0; +} + +static void unmap_memory_helper(qxl_screen_t *qxl) +{ + free(qxl->ram); + close(qxl->virtiofd); +} + +static void map_memory_helper(qxl_screen_t *qxl) +{ + void *vmem_start,*modes_start; + int memlen, num_modes; + struct QXLRom *rom; + QXLRam *ram_header; + + CHECK_POINT(); + + qxl->virtiofd = open(qxl->device_name, O_RDWR | O_SYNC); + + if (qxl->virtiofd < 0) { + ErrorF("Error opening virtio device. Check if " + " virtio-qxl-bridge is loaded\n"); + return; + } + + ioctl(qxl->virtiofd, QXL_IOCTL_QXL_IO_GETCFG, &qxl->virtio_config); + + memlen = qxl->virtio_config.ramsize + qxl->virtio_config.vramsize + + qxl->virtio_config.romsize; + + qxl->ram = vmem_start = qxl->ram_physical = malloc(memlen); + memset(qxl->ram,0x0,memlen); + ErrorF("%s: allocated %d bytes as video memory at %p\n",__func__, memlen,qxl->ram); + ioctl(qxl->virtiofd, QXL_IOCTL_QXL_IO_SET_RAMSTART, &qxl->ram); + + qxl->vram = (uint8_t *)vmem_start + qxl->virtio_config.ramsize; + qxl->vram_size = qxl->virtio_config.vramsize; + qxl->vram_physical = qxl->vram; + qxl->rom = (void *)((uint8_t *)vmem_start + qxl->virtio_config.ramsize + + qxl->virtio_config.vramsize); + + ram_header = get_ram_header(qxl); + rom = qxl->rom; + //Read the ROM contents from the device + //The 4 aditional bits brings the number of modes + read(qxl->virtiofd, qxl->rom,sizeof(*qxl->rom)+sizeof(int)); + num_modes = le32toh(*(int *)((char *)qxl->rom+sizeof(*qxl->rom))); + modes_start = (char *)qxl->rom+sizeof(*qxl->rom)+sizeof(int); + read(qxl->virtiofd, modes_start,sizeof(QXLMode)*num_modes); + + read(qxl->virtiofd, ram_header,sizeof(*ram_header)); +} + +#elif defined XSPICE static void unmap_memory_helper(qxl_screen_t *qxl) { @@ -441,7 +562,7 @@ map_memory_helper(qxl_screen_t *qxl) qxl->io_base = qxl->pci->ioBase[3]; #endif } -#endif /* XSPICE */ +#endif /* VIRTIO_QXL */ static void qxl_unmap_memory(qxl_screen_t *qxl) @@ -477,30 +598,35 @@ qxl_mspace_print_func(void *user_data, const char *format, ...) static Bool qxl_map_memory(qxl_screen_t *qxl, int scrnIndex) { + +#ifdef VIRTIO_QXL + xf86DrvMsg(scrnIndex, X_INFO, "Opening device %s.\n", qxl->device_name); +#endif + map_memory_helper(qxl); if (!qxl->ram || !qxl->vram || !qxl->rom) return FALSE; xf86DrvMsg(scrnIndex, X_INFO, "framebuffer at %p (%d KB)\n", - qxl->ram, qxl->rom->surface0_area_size / 1024); + qxl->ram, le32toh(qxl->rom->surface0_area_size) / 1024); xf86DrvMsg(scrnIndex, X_INFO, "command ram at %p (%d KB)\n", - (void *)((unsigned long)qxl->ram + qxl->rom->surface0_area_size), - (qxl->rom->num_pages * getpagesize() - qxl->rom->surface0_area_size)/1024); + (void *)((unsigned long)qxl->ram + le32toh(qxl->rom->surface0_area_size)), + (le32toh(qxl->rom->num_pages) * getpagesize() - le32toh(qxl->rom->surface0_area_size))/1024); xf86DrvMsg(scrnIndex, X_INFO, "vram at %p (%ld KB)\n", qxl->vram, qxl->vram_size / 1024); xf86DrvMsg(scrnIndex, X_INFO, "rom at %p\n", qxl->rom); - qxl->num_modes = *(uint32_t *)((uint8_t *)qxl->rom + qxl->rom->modes_offset); - qxl->modes = (struct QXLMode *)(((uint8_t *)qxl->rom) + qxl->rom->modes_offset + 4); + qxl->num_modes = le32toh(*(uint32_t *)((uint8_t *)qxl->rom + le32toh(qxl->rom->modes_offset))); + qxl->modes = (struct QXLMode *)(((uint8_t *)qxl->rom) + le32toh(qxl->rom->modes_offset) + 4); qxl->surface0_area = qxl->ram; - qxl->surface0_size = qxl->rom->surface0_area_size; + qxl->surface0_size = le32toh(qxl->rom->surface0_area_size); qxl->mem = qxl_mem_create ((void *)((unsigned long)qxl->ram + qxl->surface0_size), - qxl->rom->num_pages * getpagesize() - qxl->surface0_size); + le32toh(qxl->rom->num_pages) * getpagesize() - qxl->surface0_size); qxl->surf_mem = qxl_mem_create ((void *)((unsigned long)qxl->vram), qxl->vram_size); mspace_set_abort_func(qxl_mspace_abort_func); @@ -509,7 +635,7 @@ qxl_map_memory(qxl_screen_t *qxl, int scrnIndex) return TRUE; } -#ifdef XSPICE +#if defined XSPICE || defined VIRTIO_QXL static void qxl_save_state(ScrnInfoPtr pScrn) { @@ -589,7 +715,10 @@ qxl_reset_and_create_mem_slots (qxl_screen_t *qxl) qxl->mem_slots = xnfalloc (qxl->n_mem_slots * sizeof (qxl_memslot_t)); -#ifdef XSPICE +#ifdef VIRTIO_QXL + virtio_init_qxl_ram(qxl); + qxl->main_mem_slot = qxl->vram_mem_slot = setup_slot(qxl, 0, 0, ~0, 0, ~0); +#elif defined XSPICE qxl->main_mem_slot = qxl->vram_mem_slot = setup_slot(qxl, 0, 0, ~0, 0, ~0); #else /* QXL */ qxl->main_mem_slot = setup_slot(qxl, 0, @@ -616,7 +745,7 @@ qxl_mark_mem_unverifiable(qxl_screen_t *qxl) void qxl_io_destroy_all_surfaces (qxl_screen_t *qxl) { -#ifndef XSPICE +#if (!defined XSPICE && !defined VIRTIO_QXL) if (qxl->pci->revision >= 3) { ioport_write(qxl, QXL_IO_DESTROY_ALL_SURFACES_ASYNC, 0); @@ -648,7 +777,7 @@ qxl_close_screen(CLOSE_SCREEN_ARGS_DECL) result = pScreen->CloseScreen(CLOSE_SCREEN_ARGS); -#ifndef XSPICE +#if (!defined XSPICE && !defined VIRTIO_QXL) if (!xf86IsPrimaryPci (qxl->pci) && qxl->primary) qxl_reset_and_create_mem_slots (qxl); #endif @@ -679,7 +808,7 @@ set_screen_pixmap_header (ScreenPtr pScreen) pScreen->ModifyPixmapHeader( pPixmap, - qxl->current_mode->x_res, qxl->current_mode->y_res, + le32toh(qxl->current_mode->x_res), le32toh(qxl->current_mode->y_res), -1, -1, qxl->pScrn->displayWidth * qxl->bytes_per_pixel, NULL); @@ -1170,20 +1299,20 @@ qxl_screen_init(SCREEN_INIT_ARGS_DECL) qxl_reset_and_create_mem_slots (qxl); ErrorF ("done reset\n"); -#ifndef XSPICE +#if (!defined XSPICE && !defined VIRTIO_QXL) qxl->io_pages = (void *)((unsigned long)qxl->ram); qxl->io_pages_physical = (void *)((unsigned long)qxl->ram_physical); #endif qxl->command_ring = qxl_ring_create ((struct qxl_ring_header *)&(ram_header->cmd_ring), sizeof (struct QXLCommand), - QXL_COMMAND_RING_SIZE, QXL_IO_NOTIFY_CMD, qxl); + QXL_COMMAND_RING_SIZE, QXL_IO_NOTIFY_CMD, qxl,COMMAND_RING); qxl->cursor_ring = qxl_ring_create ((struct qxl_ring_header *)&(ram_header->cursor_ring), sizeof (struct QXLCommand), - QXL_CURSOR_RING_SIZE, QXL_IO_NOTIFY_CURSOR, qxl); + QXL_CURSOR_RING_SIZE, QXL_IO_NOTIFY_CURSOR, qxl,CURSOR_RING); qxl->release_ring = qxl_ring_create ((struct qxl_ring_header *)&(ram_header->release_ring), sizeof (uint64_t), - QXL_RELEASE_RING_SIZE, 0, qxl); + QXL_RELEASE_RING_SIZE, 0, qxl,RELEASE_RING); qxl->surface_cache = qxl_surface_cache_create (qxl); @@ -1325,12 +1454,12 @@ print_modes (qxl_screen_t *qxl, int scrnIndex) xf86DrvMsg (scrnIndex, X_INFO, "%d: %dx%d, %d bits, stride %d, %dmm x %dmm, orientation %d\n", - m->id, m->x_res, m->y_res, m->bits, m->stride, m->x_mili, - m->y_mili, m->orientation); + le32toh(m->id), le32toh(m->x_res), le32toh(m->y_res), le32toh(m->bits), le32toh(m->stride), le32toh(m->x_mili), + le32toh(m->y_mili), le32toh(m->orientation)); } } -#ifndef XSPICE +#if (!defined XSPICE && !defined VIRTIO_QXL) static Bool qxl_check_device(ScrnInfoPtr pScrn, qxl_screen_t *qxl) { @@ -1381,18 +1510,18 @@ qxl_find_native_mode(ScrnInfoPtr pScrn, DisplayModePtr p) for (i = 0; i < qxl->num_modes; i++) { struct QXLMode *m = qxl->modes + i; - - if (m->x_res == p->HDisplay && - m->y_res == p->VDisplay && - m->bits == pScrn->bitsPerPixel) + + if (le32toh(m->x_res) == p->HDisplay && + le32toh(m->y_res) == p->VDisplay && + le32toh(m->bits) == pScrn->bitsPerPixel) { - if (m->bits == 16) + if (le32toh(m->bits) == 16) { /* What QXL calls 16 bit is actually x1r5g5b515 */ if (pScrn->depth == 15) return i; } - else if (m->bits == 32) + else if (le32toh(m->bits) == 32) { /* What QXL calls 32 bit is actually x8r8g8b8 */ if (pScrn->depth == 24) @@ -1499,7 +1628,7 @@ qxl_pre_init(ScrnInfoPtr pScrn, int flags) qxl->entity = xf86GetEntityInfo(pScrn->entityList[0]); -#ifndef XSPICE +#if (!defined XSPICE && !defined VIRTIO_QXL) qxl->pci = xf86GetPciInfoForEntity(qxl->entity->index); #ifndef XSERVER_LIBPCIACCESS qxl->pci_tag = pciTag(qxl->pci->bus, qxl->pci->device, qxl->pci->func); @@ -1529,19 +1658,28 @@ qxl_pre_init(ScrnInfoPtr pScrn, int flags) qxl->enable_image_cache? "Enabled" : "Disabled"); xf86DrvMsg(scrnIndex, X_INFO, "Fallback Cache: %s\n", qxl->enable_fallback_cache? "Enabled" : "Disabled"); - + +#ifdef VIRTIO_QXL + qxl->device_name = xf86FindOptionValue(pScrn->options,"virtiodev"); + + if (!qxl->device_name) + qxl->device_name = VIRTIO_DEV; + + xf86DrvMsg(scrnIndex, X_INFO, "Using virtio device %s.\n", qxl->device_name); +#endif + if (!qxl_map_memory(qxl, scrnIndex)) goto out; - -#ifndef XSPICE + +#if (!defined XSPICE && !defined VIRTIO_QXL) if (!qxl_check_device(pScrn, qxl)) goto out; -#else +#elif defined XSPICE xspice_init_qxl_ram(qxl); /* initialize the rings */ #endif - pScrn->videoRam = (qxl->rom->num_pages * 4096) / 1024; + pScrn->videoRam = (le32toh(qxl->rom->num_pages) * 4096) / 1024; xf86DrvMsg(scrnIndex, X_INFO, "%d KB of video RAM\n", pScrn->videoRam); - xf86DrvMsg(scrnIndex, X_INFO, "%d surfaces\n", qxl->rom->n_surfaces); + xf86DrvMsg(scrnIndex, X_INFO, "%d surfaces\n", le32toh(qxl->rom->n_surfaces)); /* ddc stuff here */ @@ -1568,13 +1706,13 @@ qxl_pre_init(ScrnInfoPtr pScrn, int flags) /* Add any modes not in xorg's default mode list */ for (i = 0; i < qxl->num_modes; i++) - if (qxl->modes[i].orientation == 0) { - qxl_add_mode(pScrn, qxl->modes[i].x_res, qxl->modes[i].y_res, + if (le32toh(qxl->modes[i].orientation) == 0) { + qxl_add_mode(pScrn, le32toh(qxl->modes[i].x_res), le32toh(qxl->modes[i].y_res), M_T_DRIVER); - if (qxl->modes[i].x_res > max_x) - max_x = qxl->modes[i].x_res; - if (qxl->modes[i].y_res > max_y) - max_y = qxl->modes[i].y_res; + if (le32toh(qxl->modes[i].x_res) > max_x) + max_x = le32toh(qxl->modes[i].x_res); + if (le32toh(qxl->modes[i].y_res) > max_y) + max_y = le32toh(qxl->modes[i].y_res); } if (pScrn->display->virtualX == 0 && pScrn->display->virtualY == 0) { @@ -1582,8 +1720,8 @@ qxl_pre_init(ScrnInfoPtr pScrn, int flags) to a virtual size which will not fit into the framebuffer when this happens we prefer max width and make height as large as possible */ if (max_x * max_y * (pScrn->bitsPerPixel / 8) > - qxl->rom->surface0_area_size) - pScrn->display->virtualY = qxl->rom->surface0_area_size / + le32toh(qxl->rom->surface0_area_size)) + pScrn->display->virtualY = le32toh(qxl->rom->surface0_area_size) / (max_x * (pScrn->bitsPerPixel / 8)); else pScrn->display->virtualY = max_y; @@ -1618,7 +1756,7 @@ qxl_pre_init(ScrnInfoPtr pScrn, int flags) xf86SetDpi(pScrn, 0, 0); if (!xf86LoadSubModule(pScrn, "fb") -#ifndef XSPICE +#if (!defined XSPICE && !defined VIRTIO_QXL) || !xf86LoadSubModule(pScrn, "ramdac") || !xf86LoadSubModule(pScrn, "vgahw") #endif @@ -1629,7 +1767,7 @@ qxl_pre_init(ScrnInfoPtr pScrn, int flags) print_modes (qxl, scrnIndex); -#ifndef XSPICE +#if (!defined XSPICE && !defined VIRTIO_QXL) /* VGA hardware initialisation */ if (!vgaHWGetHWRec(pScrn)) return FALSE; @@ -1656,7 +1794,7 @@ out: return FALSE; } -#ifndef XSPICE +#if (!defined XSPICE && !defined VIRTIO_QXL) #ifdef XSERVER_LIBPCIACCESS enum qxl_class { @@ -1695,7 +1833,7 @@ static PciChipsets qxlPciChips[] = static void qxl_identify(int flags) { -#ifndef XSPICE +#if (!defined XSPICE && !defined VIRTIO_QXL) xf86PrintChipsets("qxl", "Driver for QXL virtual graphics", qxlChips); #endif } @@ -1713,7 +1851,7 @@ qxl_init_scrn(ScrnInfoPtr pScrn) pScrn->LeaveVT = qxl_leave_vt; } -#ifdef XSPICE +#if (defined VIRTIO_QXL || defined XSPICE) static Bool qxl_probe(struct _DriverRec *drv, int flags) { @@ -1738,11 +1876,6 @@ qxl_probe(struct _DriverRec *drv, int flags) return TRUE; } -static Bool qxl_driver_func(ScrnInfoPtr screen_info_ptr, xorgDriverFuncOp xorg_driver_func_op, pointer hw_flags) -{ - *(xorgHWFlags*)hw_flags = (xorgHWFlags)HW_SKIP_CONSOLE; - return TRUE; -} #else /* normal, not XSPICE */ #ifndef XSERVER_LIBPCIACCESS static Bool @@ -1812,7 +1945,15 @@ qxl_pci_probe(DriverPtr drv, int entity, struct pci_device *dev, intptr_t match) #define qxl_probe NULL #endif -#endif /* XSPICE */ +#endif /* VIRTIO_QXL || XSPICE */ + +#ifdef XSPICE +static Bool qxl_driver_func(ScrnInfoPtr screen_info_ptr, xorgDriverFuncOp xorg_driver_func_op, pointer hw_flags) +{ + *(xorgHWFlags*)hw_flags = (xorgHWFlags)HW_SKIP_CONSOLE; + return TRUE; +} +#endif static DriverRec qxl_driver = { 0, @@ -1822,7 +1963,11 @@ static DriverRec qxl_driver = { qxl_available_options, NULL, 0, -#ifdef XSPICE +#ifdef VIRTIO_QXL + NULL, + NULL, + NULL +#elif defined XSPICE qxl_driver_func, NULL, NULL @@ -1870,6 +2015,8 @@ static XF86ModuleVersionInfo qxl_module_info = { _X_EXPORT XF86ModuleData #ifdef XSPICE spiceqxlModuleData +#elif VIRTIO_QXL +virtioqxlModuleData #else qxlModuleData #endif diff --git a/src/qxl_logger.c b/src/qxl_logger.c index 40025e4..98286b8 100644 --- a/src/qxl_logger.c +++ b/src/qxl_logger.c @@ -180,6 +180,7 @@ static void qxl_log_cmd_surface(qxl_screen_t *qxl, QXLSurfaceCmd *cmd) { uint64_t offset; + void *data; fprintf(stderr," %s id %d", qxl_name(qxl_surface_cmd, cmd->type), @@ -189,7 +190,14 @@ qxl_log_cmd_surface(qxl_screen_t *qxl, QXLSurfaceCmd *cmd) return; } +#ifdef VIRTIO_QXL offset = cmd->u.surface_create.data; +#else + data = virtual_address(qxl, (void *)cmd->u.surface_create.data, + qxl->vram_mem_slot); + offset = virtual_address(qxl, data, qxl->vram_mem_slot); +#endif + fprintf(stderr," size %dx%d stride %d format %s data @ %llu", cmd->u.surface_create.width, cmd->u.surface_create.height, diff --git a/src/qxl_ring.c b/src/qxl_ring.c index 5dd1f90..e503ae0 100644 --- a/src/qxl_ring.c +++ b/src/qxl_ring.c @@ -46,6 +46,7 @@ struct qxl_ring int n_elements; int io_port_prod_notify; qxl_screen_t *qxl; + int type; }; struct qxl_ring * @@ -53,7 +54,7 @@ qxl_ring_create (struct qxl_ring_header *header, int element_size, int n_elements, int io_port_prod_notify, - qxl_screen_t *qxl) + qxl_screen_t *qxl, int ring_type) { struct qxl_ring *ring; @@ -61,6 +62,7 @@ qxl_ring_create (struct qxl_ring_header *header, if (!ring) return NULL; + ring->type = ring_type; ring->ring = (volatile struct ring *)header; ring->element_size = element_size; ring->n_elements = n_elements; @@ -69,6 +71,132 @@ qxl_ring_create (struct qxl_ring_header *header, return ring; } +#ifdef VIRTIO_QXL +static void +update_cursor_ring(qxl_screen_t *qxl) { + char *push1 = (char *)qxl->cursor_ring->ring; + char *pull = push1 + sizeof(uint32_t) * 3; + char *push2 = pull + sizeof(uint32_t); + + virtioqxl_push_ram(qxl, (void *)push2, + sizeof(QXLCursorRing) - sizeof(uint32_t) * 4); + virtioqxl_push_ram(qxl, (void *)push1, sizeof(uint32_t) * 3); + virtioqxl_pull_ram(qxl, (void *)pull, sizeof(uint32_t)); +} + +static void +update_command_ring(qxl_screen_t *qxl) { + char *push1 = (char *)qxl->command_ring->ring; + char *pull = push1 + sizeof(uint32_t) * 3; + char *push2 = pull + sizeof(uint32_t); + + virtioqxl_push_ram(qxl, (void *)push2, + sizeof(QXLCommandRing) - sizeof(uint32_t) * 4); + virtioqxl_push_ram(qxl, (void *)push1, sizeof(uint32_t) * 3); + virtioqxl_pull_ram(qxl, (void *)pull, sizeof(uint32_t)); +} + +static void +update_release_ring(qxl_screen_t *qxl) { + char *pull1 = (char *)qxl->release_ring->ring; + char *push = pull1 + sizeof(uint32_t) * 3; + char *pull2 = push + sizeof(uint32_t); + + virtioqxl_pull_ram(qxl, (void *)pull2, + sizeof(QXLReleaseRing) - sizeof(uint32_t) * 4); + virtioqxl_pull_ram(qxl, (void *)pull1, sizeof(uint32_t) * 3); + virtioqxl_push_ram(qxl, (void *)push, sizeof(uint32_t)); +} +#endif + +#ifdef VIRTIO_QXL +static void +qxl_ring_push_command(struct qxl_ring *ring, struct QXLCommand *cmd) +{ + qxl_screen_t *qxl = ring->qxl; + + switch (cmd->type) { + case QXL_CMD_SURFACE: + { + int stride; + QXLSurface surf; + uint8_t *ptr; + QXLSurfaceCmd *c = virtual_address(qxl, (void *)cmd->data, + qxl->main_mem_slot); + + virtioqxl_push_ram(qxl, (void *)c, sizeof(*c)); + + if (c->type == QXL_SURFACE_CMD_DESTROY) { + break; + } + + surf = c->u.surface_create; + stride = abs(surf.stride); + ptr = virtual_address(qxl, (void *)surf.data, qxl->vram_mem_slot); + virtioqxl_push_ram(qxl, (void *)ptr, + surf.height * stride + stride); + break; + } + case QXL_CMD_DRAW: + { + QXLPHYSICAL addr; + QXLImage *image; + QXLDataChunk *chunk; + QXLDrawable *draw = virtual_address(qxl, (void *)cmd->data, + qxl->main_mem_slot); + + virtioqxl_push_ram(qxl, (void *)draw, sizeof(*draw)); + + if (draw->type != QXL_DRAW_COPY) { + break; + } + + image = virtual_address(qxl, (void *)draw->u.copy.src_bitmap, + qxl->main_mem_slot); + virtioqxl_push_ram(qxl, (void *)image, sizeof(*image)); + + if (image->descriptor.type == SPICE_IMAGE_TYPE_SURFACE) { + break; + } + + if (image->bitmap.flags & QXL_BITMAP_DIRECT) { + uint8_t *ptr = virtual_address(qxl, (void *)image->bitmap.data, + qxl->main_mem_slot); + virtioqxl_push_ram(qxl, (void *)ptr, + image->descriptor.height * image->bitmap.stride); + break; + } + addr = image->bitmap.data; + while (addr) { + chunk = virtual_address(qxl, (void *)addr, qxl->main_mem_slot); + virtioqxl_push_ram(qxl, (void *)chunk, + sizeof(*chunk) + chunk->data_size); + addr = chunk->next_chunk; + } + break; + } + case QXL_CMD_CURSOR: + { + QXLCursor *cursor; + QXLCursorCmd *c = virtual_address(qxl, (void *)cmd->data, + qxl->main_mem_slot); + + virtioqxl_push_ram(qxl, (void *)c, sizeof(*c)); + + if (c->type != QXL_CURSOR_SET) { + break; + } + + cursor = virtual_address(qxl, (void *)c->u.set.shape, + qxl->main_mem_slot); + virtioqxl_push_ram(qxl, (void *)cursor, + sizeof(*cursor) + cursor->data_size); + break; + } + } +} +#endif // VIRTIO_QXL + void qxl_ring_push (struct qxl_ring *ring, const void *new_elt) @@ -77,18 +205,40 @@ qxl_ring_push (struct qxl_ring *ring, volatile uint8_t *elt; int idx; -#ifdef DUMP_COMMANDS - struct QXLCommand *cmd = (QXLCommand *)new_elt; +#if defined VIRTIO_QXL || defined ENABLE_DEBUG + struct QXLCommand *cmd = (QXLCommand *)new_elt; +#endif + +#ifdef VIRTIO_QXL + struct QXLRam *ram = get_ram_header(ring->qxl); + if(ring->type == CURSOR_RING){ + // When the guest stop sending cursor commands, the host side + // consumer(libspice thread) sleeps. This avoid a delay when starting + // to move the mouse again. + if(SPICE_RING_IS_EMPTY(&ram->cursor_ring)){ + ioport_write(ring->qxl, QXL_IO_NOTIFY_CURSOR, 0); + } + } + qxl_ring_push_command(ring, cmd); +#endif + +#ifdef ENABLE_DEBUG qxl_log_command(ring->qxl, cmd, ""); #endif while (header->prod - header->cons == header->num_items) { - header->notify_on_cons = header->cons + 1; +#ifdef VIRTIO_QXL + ioport_write(ring->qxl, QXL_IO_NOTIFY_CURSOR, 0); + update_command_ring(ring->qxl); + update_cursor_ring(ring->qxl); + sched_yield(); +#endif + header->notify_on_cons = header->cons + 1; #ifdef XSPICE /* in gtkperf, circles, this is a major bottleneck. Can't be that good in a vm either * Adding the yield reduces cpu usage, but doesn't improve throughput. */ - sched_yield(); + sched_yield(); #endif mem_barrier(); } @@ -102,6 +252,11 @@ qxl_ring_push (struct qxl_ring *ring, mem_barrier(); +#ifdef VIRTIO_QXL + update_command_ring(ring->qxl); + update_cursor_ring(ring->qxl); +#endif + if (header->prod == header->notify_on_prod) { ioport_write (ring->qxl, ring->io_port_prod_notify, 0); } @@ -115,6 +270,10 @@ qxl_ring_pop (struct qxl_ring *ring, volatile uint8_t *ring_elt; int idx; +#ifdef VIRTIO_QXL + update_release_ring(ring->qxl); +#endif + if (header->cons == header->prod) return FALSE; diff --git a/src/qxl_surface.c b/src/qxl_surface.c index 113f09b..22823ba 100644 --- a/src/qxl_surface.c +++ b/src/qxl_surface.c @@ -57,41 +57,6 @@ static FILE* surface_log; typedef struct evacuated_surface_t evacuated_surface_t; -struct qxl_surface_t -{ - surface_cache_t *cache; - - uint32_t id; - - pixman_image_t * dev_image; - pixman_image_t * host_image; - - uxa_access_t access_type; - RegionRec access_region; - - void * address; - void * end; - - qxl_surface_t * next; - qxl_surface_t * prev; /* Only used in the 'live' - * chain in the surface cache - */ - - int in_use; - int bpp; /* bpp of the pixmap */ - int ref_count; - - PixmapPtr pixmap; - - struct evacuated_surface_t *evacuated; - - union - { - qxl_surface_t *copy_src; - Pixel solid_pixel; - } u; -}; - struct evacuated_surface_t { pixman_image_t *image; @@ -169,7 +134,7 @@ static void debug_surface_log(surface_cache_t *cache) static Bool surface_cache_init (surface_cache_t *cache, qxl_screen_t *qxl) { - int n_surfaces = qxl->rom->n_surfaces; + int n_surfaces = le32toh(qxl->rom->n_surfaces); int i; if (!cache->all_surfaces) @@ -356,38 +321,40 @@ qxl_surface_cache_create_primary (surface_cache_t *cache, qxl_surface_t *surface; qxl_screen_t *qxl = cache->qxl; - if (mode->bits == 16) + if (le32toh(mode->bits) == 16) { format = PIXMAN_x1r5g5b5; } - else if (mode->bits == 32) + else if (le32toh(mode->bits) == 32) { format = PIXMAN_x8r8g8b8; } else { - xf86DrvMsg (cache->qxl->pScrn->scrnIndex, X_ERROR, - "Unknown bit depth %d\n", mode->bits); + xf86DrvMsg (cache->qxl->pScrn->scrnIndex, X_ERROR, + "Unknown bit depth %d\n", le32toh(mode->bits)); return NULL; } - - create->width = mode->x_res; - create->height = mode->y_res; - create->stride = - mode->stride; - create->format = mode->bits; - create->position = 0; /* What is this? The Windows driver doesn't use it */ - create->flags = 0; - create->type = QXL_SURF_TYPE_PRIMARY; - create->mem = physical_address (cache->qxl, cache->qxl->ram, cache->qxl->main_mem_slot); + + create->width = mode->x_res; //this will be sent to the host that spect LE values + create->height = mode->y_res; //Modes is in LE already. No need to convert + create->stride = htole32(-le32toh(mode->stride)); + create->format = mode->bits; + create->position = 0; /* What is this? The Windows driver doesn't use it */ + create->flags = 0; + create->type = htole32(QXL_SURF_TYPE_PRIMARY); + create->mem = htole64(physical_address(cache->qxl, cache->qxl->ram, cache->qxl->main_mem_slot)); + +#ifdef VIRTIO_QXL + virtioqxl_push_ram(qxl, create, sizeof(*create)); +#endif qxl_io_create_primary(qxl); - dev_addr = (uint8_t *)qxl->ram + mode->stride * (mode->y_res - 1); - - dev_image = pixman_image_create_bits (format, mode->x_res, mode->y_res, - (uint32_t *)dev_addr, -mode->stride); - - host_image = pixman_image_create_bits (format, + dev_addr = (uint8_t *)qxl->ram + le32toh(mode->stride) * (le32toh(mode->y_res) - 1); + dev_image = pixman_image_create_bits (format, le32toh(mode->x_res), le32toh(mode->y_res), + (uint32_t *)dev_addr, le32toh(-mode->stride)); + host_image = pixman_image_create_bits (format, qxl->virtual_x, qxl->virtual_y, qxl->fb, qxl->stride); @@ -396,7 +363,7 @@ qxl_surface_cache_create_primary (surface_cache_t *cache, surface->dev_image = dev_image; surface->host_image = host_image; surface->cache = cache; - surface->bpp = mode->bits; + surface->bpp = le32toh(mode->bits); surface->next = NULL; surface->prev = NULL; surface->evacuated = NULL; @@ -486,7 +453,7 @@ make_drawable (qxl_screen_t *qxl, int surface, uint8_t type, if (rect) drawable->bbox = *rect; - drawable->mm_time = qxl->rom->mm_clock; + drawable->mm_time = le32toh(qxl->rom->mm_clock); return drawable; } @@ -894,14 +861,13 @@ download_box (qxl_surface_t *surface, int x1, int y1, int x2, int y2) { struct QXLRam *ram_header = get_ram_header (surface->cache->qxl); - ram_header->update_area.top = y1; - ram_header->update_area.bottom = y2; - ram_header->update_area.left = x1; - ram_header->update_area.right = x2; - - ram_header->update_surface = surface->id; + ram_header->update_area.top = htole32(y1); + ram_header->update_area.bottom = htole32(y2); + ram_header->update_area.left = htole32(x1); + ram_header->update_area.right = htole32(x2); + ram_header->update_surface = htole32(surface->id); - qxl_update_area(surface->cache->qxl); + qxl_update_area(surface->cache->qxl,surface); pixman_image_composite (PIXMAN_OP_SRC, surface->dev_image, -- 1.7.4.1 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel