diff options
author | Dave Airlie <airlied@gmail.com> | 2012-11-12 20:36:23 +1000 |
---|---|---|
committer | Dave Airlie <airlied@gmail.com> | 2012-11-12 20:36:23 +1000 |
commit | 9672ac70f5d2f78f81d767deb445b6066c6b5c0a (patch) | |
tree | cf179712df1a283960ccd9d91d56573a2585cd5c | |
parent | aaddb6193b92bb64c00fefd68cbae3a6743cf102 (diff) |
qxl refactorqxl-refactor
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/qxl.h | 70 | ||||
-rw-r--r-- | src/qxl_bo.c | 49 | ||||
-rw-r--r-- | src/qxl_bo.h | 33 | ||||
-rw-r--r-- | src/qxl_bo_int.h | 35 | ||||
-rw-r--r-- | src/qxl_bo_ums.c | 544 | ||||
-rw-r--r-- | src/qxl_driver.c | 231 | ||||
-rw-r--r-- | src/qxl_image.c | 17 | ||||
-rw-r--r-- | src/qxl_mem.h | 49 | ||||
-rw-r--r-- | src/qxl_ring.c | 4 |
10 files changed, 777 insertions, 260 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index c117f7a..2fb1a9a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -51,7 +51,8 @@ qxl_drv_la_SOURCES = \ qxl_option_helpers.c \ qxl_option_helpers.h \ qxl_edid.c \ - compat-api.h + compat-api.h \ + qxl_bo.c qxl_bo_ums.c endif if BUILD_XSPICE @@ -90,5 +91,5 @@ spiceqxl_drv_la_SOURCES = \ murmurhash3.h \ qxl_cursor.c \ qxl_edid.c \ - compat-api.h + compat-api.h endif @@ -55,6 +55,7 @@ #include "vgaHW.h" #endif /* XSPICE */ +#include "qxl_bo.h" #include "compat-api.h" #define hidden _X_HIDDEN @@ -160,15 +161,17 @@ enum { struct _qxl_screen_t { /* These are the names QXL uses */ +#if 0 void * ram; /* Command RAM */ void * ram_physical; void * vram; /* Surface RAM */ void * vram_physical; struct QXLRom * rom; /* Parameter RAM */ - struct qxl_ring * command_ring; + // struct qxl_ring * command_ring; struct qxl_ring * cursor_ring; struct qxl_ring * release_ring; +#endif int device_primary; uint32_t primary_handle; @@ -280,8 +283,10 @@ struct _qxl_screen_t const char *name); void *(*alloc_surface)(qxl_screen_t *qxl, uint32_t *handle, int width, int height, int stride); + void (*free_data)(qxl_screen_t *qxl, uint32_t *handle, void *data, + const char *name); - + struct qxl_bo_manager *bom; #ifdef XSPICE /* XSpice specific */ struct QXLRom shadow_rom; /* Parameter RAM */ @@ -325,38 +330,6 @@ typedef struct qxl_crtc_private { xf86OutputPtr output; } qxl_crtc_private; -static inline uint64_t -physical_address (qxl_screen_t *qxl, void *virtual, uint8_t slot_id) -{ - qxl_memslot_t *p_slot = &(qxl->mem_slots[slot_id]); - - return p_slot->high_bits | ((unsigned long)virtual - p_slot->start_virt_addr); -} - -static inline void * -virtual_address (qxl_screen_t *qxl, void *physical, uint8_t slot_id) -{ - qxl_memslot_t *p_slot = &(qxl->mem_slots[slot_id]); - unsigned long virt; - - virt = ((unsigned long)physical) & qxl->va_slot_mask; - virt += p_slot->start_virt_addr; - - return (void *)virt; -} - -static inline void * -u64_to_pointer (uint64_t u) -{ - return (void *)(unsigned long)u; -} - -static inline uint64_t -pointer_to_u64 (void *p) -{ - return (uint64_t)(unsigned long)p; -} - struct qxl_ring; static inline int is_kms(qxl_screen_t *qxl) @@ -372,25 +345,6 @@ void qxl_cursor_init (ScreenPtr pScreen); /* - * Rings - */ -struct qxl_ring * qxl_ring_create (struct qxl_ring_header *header, - int element_size, - int n_elements, - int prod_notify, - qxl_screen_t *qxl); -void qxl_ring_push (struct qxl_ring *ring, - const void *element); -Bool qxl_ring_pop (struct qxl_ring *ring, - void *element); -void qxl_ring_wait_idle (struct qxl_ring *ring); - -void qxl_ring_request_notify (struct qxl_ring *ring); - -int qxl_ring_prod (struct qxl_ring *ring); -int qxl_ring_cons (struct qxl_ring *ring); - -/* * Surface */ surface_cache_t * qxl_surface_cache_create (qxl_screen_t *qxl); @@ -514,17 +468,11 @@ void qxl_drop_image_cache (qxl_screen_t *qxl); /* * Malloc */ +#include "qxl_mem.h" + int qxl_handle_oom (qxl_screen_t *qxl); -struct qxl_mem * qxl_mem_create (void *base, - unsigned long n_bytes); void qxl_mem_dump_stats (struct qxl_mem *mem, const char *header); -void * qxl_alloc (struct qxl_mem *mem, - unsigned long n_bytes, - const char * name); -void qxl_free (struct qxl_mem *mem, - void *d, - const char * name); void qxl_mem_free_all (struct qxl_mem *mem); void * qxl_allocnf (qxl_screen_t *qxl, unsigned long size, diff --git a/src/qxl_bo.c b/src/qxl_bo.c new file mode 100644 index 0000000..e755adf --- /dev/null +++ b/src/qxl_bo.c @@ -0,0 +1,49 @@ + +#include "qxl_bo.h" +#include "qxl_bo_int.h" +#include <stdlib.h> + +struct qxl_bo * +qxl_bo_alloc(struct qxl_bo_manager *bom, uint32_t size, + uint32_t type, const char *name) +{ + struct qxl_bo *bo; + bo = bom->funcs->bo_alloc(bom, size, type, name); + return bo; +} + +void qxl_bo_ref(struct qxl_bo *bo) +{ + struct qxl_bo_int *boi = (struct qxl_bo_int *)bo; + boi->cref++; + boi->bom->funcs->bo_ref(boi); +} + +struct qxl_bo *qxl_bo_unref(struct qxl_bo *bo) +{ + struct qxl_bo_int *boi = (struct qxl_bo_int *)bo; + if (bo == NULL) + return NULL; + + boi->cref--; + + return (struct qxl_bo *)boi->bom->funcs->bo_unref(boi); +} + +int qxl_bo_map(struct qxl_bo *bo, int write) +{ + struct qxl_bo_int *boi = (struct qxl_bo_int *)bo; + return boi->bom->funcs->bo_map(boi, write); +} + +void qxl_bo_unmap(struct qxl_bo *bo) +{ + struct qxl_bo_int *boi = (struct qxl_bo_int *)bo; + boi->bom->funcs->bo_unmap(boi); +} + +void qxl_bo_update_area(struct qxl_bo_manager *bom, uint32_t surface_id, + int x1, int y1, int x2, int y2) +{ + return bom->funcs->bo_update_area(bom, surface_id, x1, y1, x2, y2); +} diff --git a/src/qxl_bo.h b/src/qxl_bo.h new file mode 100644 index 0000000..808e20d --- /dev/null +++ b/src/qxl_bo.h @@ -0,0 +1,33 @@ +#ifndef QXL_BO_H +#define QXL_BO_H + +#include <stdint.h> +struct qxl_bo { + void *ptr; + uint32_t handle; + uint32_t size; + uint32_t type; + const char *name; +}; + +struct qxl_bo_manager; + +struct qxl_bo *qxl_bo_alloc(struct qxl_bo_manager *mgr, + uint32_t size, uint32_t type, + const char *name); + +int qxl_bo_map(struct qxl_bo *bo, int write); +void qxl_bo_unmap(struct qxl_bo *bo); + +void qxl_bo_ref(struct qxl_bo *bo); +struct qxl_bo *qxl_bo_unref(struct qxl_bo *bo); + +void qxl_update_area(struct qxl_bo_manager *managerx, uint32_t id, int x1, int y1, int x2, + int y2); + +#define QXL_BO_SURFACE 1 +#define QXL_BO_DATA 2 + +struct qxl_bo_manager *qxl_bo_ums_manager_create(void); +void qxl_bo_ums_create_mem(struct qxl_bo_manager *manager, uint32_t type, void *start, uint32_t size); +#endif diff --git a/src/qxl_bo_int.h b/src/qxl_bo_int.h new file mode 100644 index 0000000..fa9cbcd --- /dev/null +++ b/src/qxl_bo_int.h @@ -0,0 +1,35 @@ +#ifndef QXL_BO_INT_H +#define QXL_BO_INT_H + +struct qxl_bo_funcs; +struct qxl_bo_manager { + struct qxl_bo_funcs *funcs; + int fd; +}; + +struct qxl_bo_int +{ + void *ptr; + uint32_t handle; + uint32_t size; + uint32_t type; + const char *name; + struct qxl_bo_manager *bom; + uint32_t cref; +}; + +struct qxl_bo_funcs { + struct qxl_bo *(*bo_alloc)(struct qxl_bo_manager *bom, + uint32_t size, + uint32_t type, + const char *name); + void (*bo_ref)(struct qxl_bo_int *bo); + struct qxl_bo_int *(*bo_unref)(struct qxl_bo_int *bo); + int (*bo_map)(struct qxl_bo_int *bo, int write); + void (*bo_unmap)(struct qxl_bo_int *bo); + + void (*bo_update_area)(struct qxl_bo_manager *manager, uint32_t surface_id, + int x1, int y1, int x2, int y2); +}; + +#endif diff --git a/src/qxl_bo_ums.c b/src/qxl_bo_ums.c new file mode 100644 index 0000000..7c26f50 --- /dev/null +++ b/src/qxl_bo_ums.c @@ -0,0 +1,544 @@ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <spice/qxl_dev.h> + +#ifndef XSPICE +#ifdef XSERVER_PCIACCESS +#include "pciaccess.h" +#endif +#include "fb.h" +#include "vgaHW.h" +#endif /* XSPICE */ + +#include <string.h> +#include <stdlib.h> +#include "qxl_bo.h" +#include "qxl_bo_int.h" + +#include "qxl_mem.h" + +typedef struct +{ + uint8_t generation; + uint64_t start_phys_addr; + uint64_t end_phys_addr; + uint64_t start_virt_addr; + uint64_t end_virt_addr; + uint64_t high_bits; +} qxl_memslot_t; + +enum { + QXL_DEVICE_PRIMARY_UNDEFINED, + QXL_DEVICE_PRIMARY_NONE, + QXL_DEVICE_PRIMARY_CREATED, +}; + +struct qxl_ums_bo_manager { + struct qxl_bo_manager base; + struct qxl_mem *mem; + struct qxl_mem *surf_mem; + + void * ram; /* Command RAM */ + void * ram_physical; + void * vram; /* Surface RAM */ + void * vram_physical; + struct QXLRom * rom; /* Parameter RAM */ + + struct qxl_ring *command_ring; + struct qxl_ring *cursor_ring; + struct qxl_ring *release_ring; + +#ifndef XSPICE + void * io_pages; + void * io_pages_physical; + +#ifdef XSERVER_LIBPCIACCESS + struct pci_device * pci; +#else + pciVideoPtr pci; +#endif +#endif /* XSPICE */ + + qxl_memslot_t * mem_slots; + uint8_t n_mem_slots; + + uint8_t main_mem_slot; + uint8_t slot_id_bits; + uint8_t slot_gen_bits; + uint64_t va_slot_mask; + + uint8_t vram_mem_slot; + +}; + +static inline uint64_t +physical_address (struct qxl_ums_bo_manager *qxl, + void *virtual, uint8_t slot_id) +{ + qxl_memslot_t *p_slot = &(qxl->mem_slots[slot_id]); + + return p_slot->high_bits | ((unsigned long)virtual - p_slot->start_virt_addr); +} + +static inline void * +virtual_address (struct qxl_ums_bo_manager *qxl, void *physical, uint8_t slot_id) +{ + qxl_memslot_t *p_slot = &(qxl->mem_slots[slot_id]); + unsigned long virt; + + virt = ((unsigned long)physical) & qxl->va_slot_mask; + virt += p_slot->start_virt_addr; + + return (void *)virt; +} + +static inline void * +u64_to_pointer (uint64_t u) +{ + return (void *)(unsigned long)u; +} + +static inline uint64_t +pointer_to_u64 (void *p) +{ + return (uint64_t)(unsigned long)p; +} + +static uint64_t qxl_garbage_collect_ums(struct qxl_bo_manager *bom, + uint64_t id) +{ + struct qxl_ums_bo_manager *qxl = (struct qxl_ums_bo_manager *)bom; +#define POINTER_MASK ((1 << 2) - 1) + union QXLReleaseInfo *info = u64_to_pointer (id & ~POINTER_MASK); + struct QXLCursorCmd *cmd = (struct QXLCursorCmd *)info; + struct QXLDrawable *drawable = (struct QXLDrawable *)info; + struct QXLSurfaceCmd *surface_cmd = (struct QXLSurfaceCmd *)info; + int is_cursor = FALSE; + int is_surface = FALSE; + int is_drawable = FALSE; + + if ((id & POINTER_MASK) == 1) + is_cursor = TRUE; + else if ((id & POINTER_MASK) == 2) + is_surface = TRUE; + else + is_drawable = TRUE; + + if (is_cursor && cmd->type == QXL_CURSOR_SET) + { + struct QXLCursor *cursor = (void *)virtual_address ( + qxl, u64_to_pointer (cmd->u.set.shape), qxl->main_mem_slot); + + qxl_free (qxl->mem, cursor, "cursor image"); + } + else if (is_drawable && drawable->type == QXL_DRAW_COPY) + { + struct QXLImage *image = virtual_address ( + qxl, u64_to_pointer (drawable->u.copy.src_bitmap), qxl->main_mem_slot); + + if (image->descriptor.type == SPICE_IMAGE_TYPE_SURFACE) + { + qxl_surface_unref (qxl->surface_cache, image->surface_image.surface_id); + qxl_surface_cache_sanity_check (qxl->surface_cache); + qxl_free (qxl->mem, image, "surface image"); + } + else + { + qxl_image_destroy (qxl, image); + } + } + else if (is_drawable && drawable->type == QXL_DRAW_COMPOSITE) + { + struct QXLTransform *src_trans, *mask_trans; + struct QXLImage *src_img, *mask_img; + struct QXLComposite *composite = &drawable->u.composite; + + /* Source */ + src_img = virtual_address ( + qxl, u64_to_pointer (drawable->u.composite.src), qxl->main_mem_slot); + qxl_free (qxl->mem, src_img, "image struct"); + + if (composite->src_transform) + { + src_trans = virtual_address ( + qxl, u64_to_pointer (composite->src_transform), qxl->main_mem_slot); + qxl_free (qxl->mem, src_trans, "transform"); + } + + /* Mask */ + if (drawable->u.composite.mask) + { + if (drawable->u.composite.mask_transform) + { + mask_trans = virtual_address ( + qxl, u64_to_pointer (drawable->u.composite.mask_transform), qxl->main_mem_slot); + + qxl_free (qxl->mem, mask_trans, "transform"); + } + + mask_img = virtual_address ( + qxl, u64_to_pointer (drawable->u.composite.mask), qxl->main_mem_slot); + qxl_free (qxl->mem, mask_img, "image struct"); + } + } + else if (is_surface && surface_cmd->type == QXL_SURFACE_CMD_DESTROY) + { + qxl_surface_recycle (qxl->surface_cache, surface_cmd->surface_id); + qxl_surface_cache_sanity_check (qxl->surface_cache); + } + + id = info->next; + + qxl_free (qxl->mem, info, "command"); + + return id; +} +static struct qxl_bo *ums_bo_alloc(struct qxl_bo_manager *_bom, + uint32_t size, + uint32_t type, + const char *name) +{ + struct qxl_ums_bo_manager *bom = (struct qxl_ums_bo_manager *)_bom; + struct qxl_bo_int *bo = calloc(1, sizeof(struct qxl_bo_int)); + + bo->size = size; + + if (type == QXL_BO_SURFACE) { + bo->ptr = qxl_alloc(bom->surf_mem, size, name); + } else { + bo->ptr = qxl_alloc(bom->mem, size, name); + } + + bo->type = type; + bo->name = name; + return (struct qxl_bo *)bo; +} + +static void ums_bo_ref(struct qxl_bo_int *bo) +{ +} + +static struct qxl_bo_int *ums_bo_unref(struct qxl_bo_int *bo) +{ + struct qxl_ums_bo_manager *bom = (struct qxl_ums_bo_manager *)bo->bom; + + if (bo->cref) + return bo; + + if (bo->type == QXL_BO_SURFACE) + qxl_free(bom->surf_mem, bo->ptr, bo->name); + else + qxl_free(bom->mem, bo->ptr, bo->name); + free(bo); + return NULL; +} + +static int ums_bo_map(struct qxl_bo_int *bo, int write) +{ + return 0; +} + +static void ums_bo_unmap(struct qxl_bo_int *bo) +{ +} +#ifndef XSPICE +static void +qxl_wait_for_io_command (struct qxl_bo_manager *bom) +{ + struct qxl_ums_bo_manager *qxl = (struct qxl_ums_bo_manager *)bom; + struct QXLRam *ram_header; + + ram_header = (void *)((unsigned long)qxl->ram + qxl->rom->ram_header_offset); + + while (!(ram_header->int_pending & QXL_INTERRUPT_IO_CMD)) + usleep (1); + + ram_header->int_pending &= ~QXL_INTERRUPT_IO_CMD; +} +#endif + +void +qxl_io_update_area (struct qxl_bo_manager *bom) +{ + struct qxl_ums_bo_manager *qxl = (struct qxl_ums_bo_manager *)bom; +#ifndef XSPICE + if (qxl->pci->revision >= 3) + { + ioport_write (qxl, QXL_IO_UPDATE_AREA_ASYNC, 0); + qxl_wait_for_io_command (qxl); + } + else + { + ioport_write (qxl, QXL_IO_UPDATE_AREA, 0); + } +#else + ioport_write (qxl, QXL_IO_UPDATE_AREA, 0); +#endif +} + +static void +qxl_io_memslot_add (struct qxl_bo_manager *bom, uint8_t id) +{ + struct qxl_ums_bo_manager *qxl = (struct qxl_ums_bo_manager *)bom; +#ifndef XSPICE + if (qxl->pci->revision >= 3) + { + ioport_write (qxl, QXL_IO_MEMSLOT_ADD_ASYNC, id); + qxl_wait_for_io_command (qxl); + } + else + { + ioport_write (qxl, QXL_IO_MEMSLOT_ADD, id); + } +#else + ioport_write (qxl, QXL_IO_MEMSLOT_ADD, id); +#endif +} + +static void +qxl_io_create_primary (struct qxl_bo_manager *bom) +{ + struct qxl_ums_bo_manager *qxl = (struct qxl_ums_bo_manager *)bom; +#ifndef XSPICE + if (qxl->pci->revision >= 3) + { + ioport_write (qxl, QXL_IO_CREATE_PRIMARY_ASYNC, 0); + qxl_wait_for_io_command (qxl); + } + else + { + ioport_write (qxl, QXL_IO_CREATE_PRIMARY, 0); + } +#else + ioport_write (qxl, QXL_IO_CREATE_PRIMARY, 0); +#endif +} + +static void ums_update_area(struct qxl_bo_manager *bom, uint32_t surface_id, + int x1, int y1, int x2, int y2) +{ + struct qxl_ums_bo_manager *qxl = (struct qxl_ums_bo_manager *)bom; + struct QXLRam *ram_header = get_ram_header (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; + + qxl_io_update_area(qxl); +} + +struct qxl_bo_funcs qxl_bo_ums_funcs = { + ums_bo_alloc, + ums_bo_ref, + ums_bo_unref, + ums_bo_map, + ums_bo_unmap, + + ums_update_area, +}; + + +#ifdef XSPICE +static void +unmap_memory_helper (struct qxl_bo_manager *bom) +{ + struct qxl_ums_bo_manager *qxl = (struct qxl_ums_bo_manager *)bom; + free (qxl->ram); + free (qxl->vram); + free (qxl->rom); + qxl->ram = qxl->ram_physical = qxl->vram = qxl->rom = NULL; +} + +static void +map_memory_helper (struct qxl_bo_manager *bom) +{ + struct qxl_ums_bo_manager *qxl = (struct qxl_ums_bo_manager *)bom; + qxl->ram = malloc (RAM_SIZE); + qxl->ram_size = RAM_SIZE; + qxl->ram_physical = qxl->ram; + qxl->vram = malloc (VRAM_SIZE); + qxl->vram_size = VRAM_SIZE; + qxl->vram_physical = qxl->vram; + qxl->rom = malloc (ROM_SIZE); + + init_qxl_rom (qxl, ROM_SIZE); +} + +#else /* Default */ + +static void +unmap_memory_helper (struct qxl_bo_manager *bom) +{ + struct qxl_ums_bo_manager *qxl = (struct qxl_ums_bo_manager *)bom; +#ifdef XSERVER_LIBPCIACCESS + if (qxl->ram) + pci_device_unmap_range (qxl->pci, qxl->ram, qxl->pci->regions[0].size); + if (qxl->vram) + pci_device_unmap_range (qxl->pci, qxl->vram, qxl->pci->regions[1].size); + if (qxl->rom) + pci_device_unmap_range (qxl->pci, qxl->rom, qxl->pci->regions[2].size); +#else + if (qxl->ram) + xf86UnMapVidMem (scrnIndex, qxl->ram, (1 << qxl->pci->size[0])); + if (qxl->vram) + xf86UnMapVidMem (scrnIndex, qxl->vram, (1 << qxl->pci->size[1])); + if (qxl->rom) + xf86UnMapVidMem (scrnIndex, qxl->rom, (1 << qxl->pci->size[2])); +#endif + qxl->ram = qxl->ram_physical = qxl->vram = qxl->rom = NULL; +} + +static void +map_memory_helper (struct qxl_bo_manager *bom) +{ + struct qxl_ums_bo_manager *qxl = (struct qxl_ums_bo_manager *)bom; +#ifdef XSERVER_LIBPCIACCESS + pci_device_map_range (qxl->pci, qxl->pci->regions[0].base_addr, + qxl->pci->regions[0].size, + PCI_DEV_MAP_FLAG_WRITABLE | PCI_DEV_MAP_FLAG_WRITE_COMBINE, + &qxl->ram); + qxl->ram_physical = u64_to_pointer (qxl->pci->regions[0].base_addr); + qxl->ram_size = qxl->pci->regions[0].size; + + pci_device_map_range (qxl->pci, qxl->pci->regions[1].base_addr, + qxl->pci->regions[1].size, + PCI_DEV_MAP_FLAG_WRITABLE, + &qxl->vram); + qxl->vram_physical = u64_to_pointer (qxl->pci->regions[1].base_addr); + qxl->vram_size = qxl->pci->regions[1].size; + + pci_device_map_range (qxl->pci, qxl->pci->regions[2].base_addr, + qxl->pci->regions[2].size, 0, + (void **)&qxl->rom); + + qxl->io_base = qxl->pci->regions[3].base_addr; +#else + qxl->ram = xf86MapPciMem (scrnIndex, VIDMEM_FRAMEBUFFER, + qxl->pci_tag, qxl->pci->memBase[0], + (1 << qxl->pci->size[0])); + qxl->ram_physical = (void *)qxl->pci->memBase[0]; + + qxl->vram = xf86MapPciMem (scrnIndex, VIDMEM_MMIO | VIDMEM_MMIO_32BIT, + qxl->pci_tag, qxl->pci->memBase[1], + (1 << qxl->pci->size[1])); + qxl->vram_physical = (void *)qxl->pci->memBase[1]; + qxl->vram_size = (1 << qxl->pci->size[1]); + + qxl->rom = xf86MapPciMem (scrnIndex, VIDMEM_MMIO | VIDMEM_MMIO_32BIT, + qxl->pci_tag, qxl->pci->memBase[2], + (1 << qxl->pci->size[2])); + + qxl->io_base = qxl->pci->ioBase[3]; +#endif +} + +#endif /* XSPICE */ + +struct qxl_bo_manager *qxl_bo_ums_manager_create(void *pci) +{ + struct qxl_ums_bo_manager *bom = calloc(1, sizeof(struct qxl_ums_bo_manager)); + struct QXLRam *ram_header; + + if (!bom) + return NULL; + + bom->base.funcs = &qxl_bo_ums_funcs; + bom->pci = pci; + + ram_header = (void *)((unsigned long)qxl->ram + + (unsigned long)qxl->rom->ram_header_offset); + bom->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); + bom->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); + bom->release_ring = qxl_ring_create ((struct qxl_ring_header *)&(ram_header->release_ring), + sizeof (uint64_t), + QXL_RELEASE_RING_SIZE, 0, qxl); + } + return &bom->base; +} + +void qxl_bo_ums_create_mem(struct qxl_bo_manager *manager, uint32_t type, void *start, uint32_t size) +{ + struct qxl_ums_bo_manager *bom = (struct qxl_ums_bo_manager *)manager; + + if (type == QXL_BO_SURFACE) { + bom->surf_mem = qxl_mem_create(start, size); + } else { + bom->mem = qxl_mem_create(start, size); + } +} + + +static void +qxl_ums_reset_and_create_mem_slots (struct qxl_bo_manager *bom) +{ + struct qxl_ums_bo_manager *qxl = (struct qxl_ums_bo_manager *)bom; + ioport_write (qxl, QXL_IO_RESET, 0); + qxl->device_primary = QXL_DEVICE_PRIMARY_NONE; + /* Mem slots */ + ErrorF ("slots start: %d, slots end: %d\n", + qxl->rom->slots_start, + qxl->rom->slots_end); + + /* Main slot */ + qxl->n_mem_slots = qxl->rom->slots_end; + qxl->slot_gen_bits = qxl->rom->slot_gen_bits; + qxl->slot_id_bits = qxl->rom->slot_id_bits; + qxl->va_slot_mask = (~(uint64_t)0) >> (qxl->slot_id_bits + qxl->slot_gen_bits); + + qxl->mem_slots = xnfalloc (qxl->n_mem_slots * sizeof (qxl_memslot_t)); + +#ifdef 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, + (unsigned long)qxl->ram_physical, + (unsigned long)qxl->ram_physical + qxl->surface0_size + + (unsigned long)qxl->rom->num_pages * getpagesize (), + (uint64_t)(uintptr_t)qxl->ram, + (uint64_t)(uintptr_t)qxl->ram + qxl->surface0_size + + (unsigned long)qxl->rom->num_pages * getpagesize () + ); + qxl->vram_mem_slot = setup_slot (qxl, 1, + (unsigned long)qxl->vram_physical, + (unsigned long)qxl->vram_physical + (unsigned long)qxl->vram_size, + (uint64_t)(uintptr_t)qxl->vram, + (uint64_t)(uintptr_t)qxl->vram + (uint64_t)qxl->vram_size); +#endif +} + +static void +qxl_mark_mem_unverifiable (struct qxl_bo_manager *bom) +{ + struct qxl_ums_bo_manager *qxl = (struct qxl_ums_bo_manager *)bom; + qxl_mem_unverifiable (qxl->mem); + qxl_mem_unverifiable (qxl->surf_mem); +} + +void +qxl_io_destroy_all_surfaces (struct qxl_bo_manager *bom) +{ + struct qxl_ums_bo_manager *qxl = (struct qxl_ums_bo_manager *)bom; +#ifndef XSPICE + if (qxl->pci->revision >= 3) + { + ioport_write (qxl, QXL_IO_DESTROY_ALL_SURFACES_ASYNC, 0); + qxl_wait_for_io_command (qxl); + } + else + { + ioport_write (qxl, QXL_IO_DESTROY_ALL_SURFACES, 0); + } +#else + ErrorF ("Xspice: error: UNIMPLEMENTED qxl_io_destroy_all_surfaces\n"); +#endif + qxl->device_primary = QXL_DEVICE_PRIMARY_NONE; +} diff --git a/src/qxl_driver.c b/src/qxl_driver.c index 1769356..c704347 100644 --- a/src/qxl_driver.c +++ b/src/qxl_driver.c @@ -138,90 +138,6 @@ qxl_available_options (int chipid, int busid) return DefaultOptions; } -#ifndef XSPICE -static void -qxl_wait_for_io_command (qxl_screen_t *qxl) -{ - struct QXLRam *ram_header; - - ram_header = (void *)((unsigned long)qxl->ram + qxl->rom->ram_header_offset); - - while (!(ram_header->int_pending & QXL_INTERRUPT_IO_CMD)) - usleep (1); - - ram_header->int_pending &= ~QXL_INTERRUPT_IO_CMD; -} - -#if 0 -static void -qxl_wait_for_display_interrupt (qxl_screen_t *qxl) -{ - struct QXLRam *ram_header; - - ram_header = (void *)((unsigned long)qxl->ram + qxl->rom->ram_header_offset); - - while (!(ram_header->int_pending & QXL_INTERRUPT_DISPLAY)) - usleep (1); - - ram_header->int_pending &= ~QXL_INTERRUPT_DISPLAY; -} - -#endif -#endif - -void -qxl_io_update_area (qxl_screen_t *qxl) -{ -#ifndef XSPICE - if (qxl->pci->revision >= 3) - { - ioport_write (qxl, QXL_IO_UPDATE_AREA_ASYNC, 0); - qxl_wait_for_io_command (qxl); - } - else - { - ioport_write (qxl, QXL_IO_UPDATE_AREA, 0); - } -#else - ioport_write (qxl, QXL_IO_UPDATE_AREA, 0); -#endif -} - -static void -qxl_io_memslot_add (qxl_screen_t *qxl, uint8_t id) -{ -#ifndef XSPICE - if (qxl->pci->revision >= 3) - { - ioport_write (qxl, QXL_IO_MEMSLOT_ADD_ASYNC, id); - qxl_wait_for_io_command (qxl); - } - else - { - ioport_write (qxl, QXL_IO_MEMSLOT_ADD, id); - } -#else - ioport_write (qxl, QXL_IO_MEMSLOT_ADD, id); -#endif -} - -static void -qxl_io_create_primary (qxl_screen_t *qxl) -{ -#ifndef XSPICE - if (qxl->pci->revision >= 3) - { - ioport_write (qxl, QXL_IO_CREATE_PRIMARY_ASYNC, 0); - qxl_wait_for_io_command (qxl); - } - else - { - ioport_write (qxl, QXL_IO_CREATE_PRIMARY, 0); - } -#else - ioport_write (qxl, QXL_IO_CREATE_PRIMARY, 0); -#endif -} #ifndef XSPICE static void qxl_kms_decref_resource(qxl_screen_t *qxl, @@ -590,20 +506,21 @@ qxl_handle_oom (qxl_screen_t *qxl) return qxl_garbage_collect (qxl); } -static void * -qxl_ums_alloc_data(qxl_screen_t *qxl, uint32_t *handle, unsigned long size, +static struct qxl_bo * +qxl_ums_alloc_data(qxl_screen_t *qxl, unsigned long size, const char *name) { void *result; int n_attempts = 0; - + struct qxl_bo *bo; #if 0 static int nth_oom = 1; #endif qxl_garbage_collect (qxl); - while (!(result = qxl_alloc (qxl->mem, size, name))) + retry: + while (!(bo = qxl_bo_alloc (qxl->bom, size, QXL_BO_DATA, name))) { #if 0 ErrorF ("eliminated memory (%d)\n", nth_oom++); @@ -623,12 +540,18 @@ qxl_ums_alloc_data(qxl_screen_t *qxl, uint32_t *handle, unsigned long size, } } } - - return result; + + return bo; +} + +static void +qxl_ums_free_data(qxl_screen_t *qxl, struct qxl_bo *bo) +{ + // qxl_free(qxl->mem, data, name); } #ifndef XSPICE -static void * +static struct qxl_bo * qxl_kms_alloc_data(qxl_screen_t *qxl, uint32_t *handle, unsigned long size) { *handle = qxl_kms_alloc_resource(qxl, size, @@ -640,104 +563,21 @@ qxl_kms_alloc_data(qxl_screen_t *qxl, uint32_t *handle, unsigned long size) // NB: we may be repeatedly mapping here. should be cached. return qxl_kms_mmap(qxl, *handle, size); } -#endif - -static Bool -qxl_blank_screen (ScreenPtr pScreen, int mode) -{ - return TRUE; -} -#ifdef XSPICE static void -unmap_memory_helper (qxl_screen_t *qxl) +qxl_kms_free_data(qxl_screen_t *qxl, + struct qxl_bo *bo) { - free (qxl->ram); - free (qxl->vram); - free (qxl->rom); -} -static void -map_memory_helper (qxl_screen_t *qxl) -{ - qxl->ram = malloc (RAM_SIZE); - qxl->ram_size = RAM_SIZE; - qxl->ram_physical = qxl->ram; - qxl->vram = malloc (VRAM_SIZE); - qxl->vram_size = VRAM_SIZE; - qxl->vram_physical = qxl->vram; - qxl->rom = malloc (ROM_SIZE); - - init_qxl_rom (qxl, ROM_SIZE); } - -#else /* Default */ - -static void -unmap_memory_helper (qxl_screen_t *qxl) -{ -#ifdef XSERVER_LIBPCIACCESS - if (qxl->ram) - pci_device_unmap_range (qxl->pci, qxl->ram, qxl->pci->regions[0].size); - if (qxl->vram) - pci_device_unmap_range (qxl->pci, qxl->vram, qxl->pci->regions[1].size); - if (qxl->rom) - pci_device_unmap_range (qxl->pci, qxl->rom, qxl->pci->regions[2].size); -#else - if (qxl->ram) - xf86UnMapVidMem (scrnIndex, qxl->ram, (1 << qxl->pci->size[0])); - if (qxl->vram) - xf86UnMapVidMem (scrnIndex, qxl->vram, (1 << qxl->pci->size[1])); - if (qxl->rom) - xf86UnMapVidMem (scrnIndex, qxl->rom, (1 << qxl->pci->size[2])); #endif -} -static void -map_memory_helper (qxl_screen_t *qxl) +static Bool +qxl_blank_screen (ScreenPtr pScreen, int mode) { -#ifdef XSERVER_LIBPCIACCESS - pci_device_map_range (qxl->pci, qxl->pci->regions[0].base_addr, - qxl->pci->regions[0].size, - PCI_DEV_MAP_FLAG_WRITABLE | PCI_DEV_MAP_FLAG_WRITE_COMBINE, - &qxl->ram); - qxl->ram_physical = u64_to_pointer (qxl->pci->regions[0].base_addr); - qxl->ram_size = qxl->pci->regions[0].size; - - pci_device_map_range (qxl->pci, qxl->pci->regions[1].base_addr, - qxl->pci->regions[1].size, - PCI_DEV_MAP_FLAG_WRITABLE, - &qxl->vram); - qxl->vram_physical = u64_to_pointer (qxl->pci->regions[1].base_addr); - qxl->vram_size = qxl->pci->regions[1].size; - - pci_device_map_range (qxl->pci, qxl->pci->regions[2].base_addr, - qxl->pci->regions[2].size, 0, - (void **)&qxl->rom); - - qxl->io_base = qxl->pci->regions[3].base_addr; -#else - qxl->ram = xf86MapPciMem (scrnIndex, VIDMEM_FRAMEBUFFER, - qxl->pci_tag, qxl->pci->memBase[0], - (1 << qxl->pci->size[0])); - qxl->ram_physical = (void *)qxl->pci->memBase[0]; - - qxl->vram = xf86MapPciMem (scrnIndex, VIDMEM_MMIO | VIDMEM_MMIO_32BIT, - qxl->pci_tag, qxl->pci->memBase[1], - (1 << qxl->pci->size[1])); - qxl->vram_physical = (void *)qxl->pci->memBase[1]; - qxl->vram_size = (1 << qxl->pci->size[1]); - - qxl->rom = xf86MapPciMem (scrnIndex, VIDMEM_MMIO | VIDMEM_MMIO_32BIT, - qxl->pci_tag, qxl->pci->memBase[2], - (1 << qxl->pci->size[2])); - - qxl->io_base = qxl->pci->ioBase[3]; -#endif + return TRUE; } -#endif /* XSPICE */ - static void qxl_unmap_memory (qxl_screen_t *qxl) { @@ -759,7 +599,7 @@ qxl_unmap_memory (qxl_screen_t *qxl) qxl_mem_free_all (qxl->surf_mem); unmap_memory_helper (qxl); - qxl->ram = qxl->ram_physical = qxl->vram = qxl->rom = NULL; + qxl->num_modes = 0; qxl->modes = NULL; @@ -847,8 +687,7 @@ qxl_ums_resize_surface0 (qxl_screen_t *qxl, long surface0_size) qxl->surface0_size = surface0_size; qxl->mem_size = new_mem_size; - qxl->mem = qxl_mem_create ((void *)((unsigned long)qxl->surface0_area + qxl->surface0_size), - qxl->mem_size); + qxl_bo_ums_create_mem(qxl->bom, QXL_BO_DATA, (void *)((unsigned long)qxl->surface0_area + qxl->surface0_size), qxl->mem_size); return 1; } @@ -884,12 +723,10 @@ qxl_map_memory (qxl_screen_t *qxl, int scrnIndex) qxl->surface0_area = qxl->ram; qxl->surface0_size = 0; qxl->mem = NULL; - if (!is_kms (qxl)) { - if (!qxl_ums_resize_surface0 (qxl, qxl->rom->surface0_area_size)) - return FALSE; - qxl->surf_mem = qxl_mem_create ((void *)((unsigned long)qxl->vram), - qxl->vram_size); - } + if (!qxl_ums_resize_surface0 (qxl, qxl->rom->surface0_area_size)) + return FALSE; + + qxl_bo_ums_create_mem(qxl->bom, QXL_BO_SURFACE, (void *)((unsigned long)qxl->vram), qxl->vram_size); qxl_allocate_monitors_config (qxl); return TRUE; @@ -2774,16 +2611,16 @@ qxl_ums_alloc_surface(qxl_screen_t *qxl, uint32_t *handle /* unused */, { int n_attempts = 0; void *address; + struct qxl_bo *bo; /* the final + stride is to work around a bug where the device apparently * scribbles after the end of the image */ qxl_garbage_collect (qxl); retry2: - address = qxl_alloc (qxl->surf_mem, stride * height + stride, - "surface memory"); - - if (!address) + bo = qxl_bo_alloc(qxl->bom, stride * height + stride, + QXL_BO_SURFACE, "surface_memory"); + if (!bo) { ErrorF ("- %dth attempt\n", n_attempts++); @@ -2804,6 +2641,10 @@ retry2: return NULL; } + + qxl_bo_map(bo, 1); + address = bo->ptr; + return address; } @@ -2831,6 +2672,7 @@ set_callbacks_to_ums(qxl_screen_t *qxl) qxl->push_surface_cmd = qxl_ums_push_surface_cmd; qxl->push_cursor_cmd = qxl_ums_push_cursor_cmd; qxl->alloc_data = qxl_ums_alloc_data; + qxl->free_data = qxl_ums_free_data; qxl->alloc_surface = qxl_ums_alloc_surface; } @@ -2847,6 +2689,7 @@ set_callbacks_to_kms(qxl_screen_t *qxl) qxl->push_surface_cmd = qxl_kms_push_surface_cmd; qxl->push_cursor_cmd = qxl_kms_push_cursor_cmd; qxl->alloc_data = qxl_kms_alloc_data; + qxl->free_data = qxl_kms_free_data; qxl->alloc_surface = qxl_kms_alloc_surface; } #endif @@ -2929,6 +2772,9 @@ qxl_pre_init (ScrnInfoPtr pScrn, int flags) #ifndef XSPICE open_drm(qxl, pScrn); if (!is_kms(qxl)) { + /* create BO manager */ + qxl->bom = qxl_bo_ums_manager_create(qxl->pci); + if (!qxl_map_memory(qxl, scrnIndex)) goto out; if (!qxl_check_device(pScrn, qxl)) @@ -2938,6 +2784,7 @@ qxl_pre_init (ScrnInfoPtr pScrn, int flags) set_callbacks_to_kms(qxl); } #else + qxl->bom = qxl_bo_ums_manager_create(); if (!qxl_map_memory(qxl, scrnIndex)) goto out; set_callbacks_to_ums(qxl); diff --git a/src/qxl_image.c b/src/qxl_image.c index 0efa641..ab94018 100644 --- a/src/qxl_image.c +++ b/src/qxl_image.c @@ -40,7 +40,9 @@ struct image_info_t { struct QXLImage *image; int ref_count; + struct qxl_bo *bo; image_info_t *next; + uint32_t *chunk_handles; }; #define HASH_SIZE 4096 @@ -144,6 +146,7 @@ qxl_image_create (qxl_screen_t *qxl, uint32_t *image_handle, uint32_t head_handle = 0; int dest_stride = (width * Bpp + 3) & (~3); int h; + struct qxl_bo *bo; data += y * stride + x * Bpp; @@ -199,8 +202,12 @@ qxl_image_create (qxl_screen_t *qxl, uint32_t *image_handle, } /* Image */ - image = qxl->alloc_data(qxl, image_handle, sizeof *image, - "image struct"); + bo = qxl_bo_alloc(qxl->bom, sizeof *image, QXL_BO_DATA, + "image struct"); + + qxl_bo_map(bo, 1); + + image = bo->ptr; image->descriptor.id = 0; image->descriptor.type = SPICE_IMAGE_TYPE_BITMAP; @@ -231,7 +238,7 @@ qxl_image_create (qxl_screen_t *qxl, uint32_t *image_handle, image->bitmap.y = height; image->bitmap.stride = dest_stride; image->bitmap.palette = 0; - qxl->add_reloc(qxl, cmd, image, *image_handle, + qxl->add_reloc(qxl, cmd, image, bo->handle, offsetof(QXLImage, bitmap.data), head, head_handle, 0); @@ -242,6 +249,7 @@ qxl_image_create (qxl_screen_t *qxl, uint32_t *image_handle, if ((info = insert_image_info (hash))) { info->image = image; + info->bo = bo; info->ref_count = 1; image->descriptor.id = hash; @@ -253,6 +261,8 @@ qxl_image_create (qxl_screen_t *qxl, uint32_t *image_handle, } } + qxl_bo_unmap(bo); + return image; } @@ -262,6 +272,7 @@ qxl_image_destroy (qxl_screen_t *qxl, { image_info_t *info; uint64_t chunk; + uint32_t img_handle = 0; info = lookup_image_info (image->descriptor.id, image->descriptor.width, diff --git a/src/qxl_mem.h b/src/qxl_mem.h new file mode 100644 index 0000000..8be31f7 --- /dev/null +++ b/src/qxl_mem.h @@ -0,0 +1,49 @@ + +#ifndef QXL_MEM_H +#define QXL_MEM_H + +struct qxl_mem; + +struct qxl_mem * qxl_mem_create (void *base, + unsigned long n_bytes); + +void * qxl_alloc (struct qxl_mem *mem, + unsigned long n_bytes, + const char * name); + +void qxl_free (struct qxl_mem *mem, + void *d, + const char * name); + + +#pragma pack(push,1) + +struct qxl_ring_header { + uint32_t num_items; + uint32_t prod; + uint32_t notify_on_prod; + uint32_t cons; + uint32_t notify_on_cons; +}; + +#pragma pack(pop) +/* + * Rings + */ +struct qxl_ring * qxl_ring_create (struct qxl_ring_header *header, + int element_size, + int n_elements, + int prod_notify, + void *qxl); +void qxl_ring_push (struct qxl_ring *ring, + const void *element); +Bool qxl_ring_pop (struct qxl_ring *ring, + void *element); +void qxl_ring_wait_idle (struct qxl_ring *ring); + +void qxl_ring_request_notify (struct qxl_ring *ring); + +int qxl_ring_prod (struct qxl_ring *ring); +int qxl_ring_cons (struct qxl_ring *ring); + +#endif diff --git a/src/qxl_ring.c b/src/qxl_ring.c index 2156113..2c0f171 100644 --- a/src/qxl_ring.c +++ b/src/qxl_ring.c @@ -45,7 +45,7 @@ struct qxl_ring int element_size; int n_elements; int io_port_prod_notify; - qxl_screen_t *qxl; + void *qxl; }; struct qxl_ring * @@ -53,7 +53,7 @@ qxl_ring_create (struct qxl_ring_header *header, int element_size, int n_elements, int io_port_prod_notify, - qxl_screen_t *qxl) + void *qxl) { struct qxl_ring *ring; |