summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@gmail.com>2012-11-12 20:36:23 +1000
committerDave Airlie <airlied@gmail.com>2012-11-12 20:36:23 +1000
commit9672ac70f5d2f78f81d767deb445b6066c6b5c0a (patch)
treecf179712df1a283960ccd9d91d56573a2585cd5c
parentaaddb6193b92bb64c00fefd68cbae3a6743cf102 (diff)
qxl refactorqxl-refactor
-rw-r--r--src/Makefile.am5
-rw-r--r--src/qxl.h70
-rw-r--r--src/qxl_bo.c49
-rw-r--r--src/qxl_bo.h33
-rw-r--r--src/qxl_bo_int.h35
-rw-r--r--src/qxl_bo_ums.c544
-rw-r--r--src/qxl_driver.c231
-rw-r--r--src/qxl_image.c17
-rw-r--r--src/qxl_mem.h49
-rw-r--r--src/qxl_ring.c4
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
diff --git a/src/qxl.h b/src/qxl.h
index 3eb3dc5..73abf1e 100644
--- a/src/qxl.h
+++ b/src/qxl.h
@@ -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;